Convert from BoltDB to Maildir storage for emails
This commit is contained in:
@@ -5,11 +5,18 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/asdine/storm"
|
||||
"github.com/coreos/bbolt"
|
||||
)
|
||||
|
||||
const (
|
||||
DatabaseFilename = "crockery.db"
|
||||
MailboxesDirname = "mailboxes"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Domain() string
|
||||
TLS() tls.Certificate
|
||||
@@ -19,26 +26,42 @@ type Interface interface {
|
||||
SetTLS([]byte, []byte) error
|
||||
|
||||
AccountInterface
|
||||
MailboxInterface
|
||||
MaildirInterface
|
||||
MessageInterface
|
||||
SpoolInterface
|
||||
|
||||
io.Closer
|
||||
}
|
||||
|
||||
func buildPath(parts ...string) string {
|
||||
if len(parts) == 0 || parts[0] == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
return filepath.Join(parts...)
|
||||
}
|
||||
func BuildDatabasePath(home string) string {
|
||||
return buildPath(home, DatabaseFilename)
|
||||
}
|
||||
|
||||
func BuildMailboxesPath(home string) string {
|
||||
return buildPath(home, MailboxesDirname)
|
||||
}
|
||||
|
||||
func IsNotFound(err error) bool {
|
||||
return err.Error() == "not found" // Magic hardcoded value in storm
|
||||
}
|
||||
|
||||
func New(ctx context.Context, filename string) (Interface, error) {
|
||||
func New(ctx context.Context, home string) (Interface, error) {
|
||||
filename := BuildDatabasePath(home)
|
||||
db, err := storm.Open(filename, storm.BoltOptions(0600, &bolt.Options{}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := &concrete{
|
||||
filename: filename,
|
||||
storm: db,
|
||||
home: home,
|
||||
storm: db,
|
||||
}
|
||||
|
||||
if err := out.setup(); err != nil {
|
||||
@@ -48,19 +71,30 @@ func New(ctx context.Context, filename string) (Interface, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func Init(filename, domain string, certPEM, keyPEM []byte) error {
|
||||
func Init(home, domain string, certPEM, keyPEM []byte) error {
|
||||
filename := BuildDatabasePath(home)
|
||||
mailboxes := BuildMailboxesPath(home)
|
||||
|
||||
if _, err := os.Stat(mailboxes); !os.IsNotExist(err) {
|
||||
return fmt.Errorf("mailboxes directory %q already exists", mailboxes)
|
||||
}
|
||||
|
||||
db, err := storm.Open(filename, storm.BoltOptions(0600, &bolt.Options{}))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
builder := &concrete{
|
||||
filename: filename,
|
||||
storm: db,
|
||||
home: home,
|
||||
storm: db,
|
||||
}
|
||||
|
||||
defer builder.Close()
|
||||
|
||||
if err := os.Mkdir(mailboxes, 0700); err != nil {
|
||||
return fmt.Errorf("Couldn't create mailboxes directory %q: %v", mailboxes, err)
|
||||
}
|
||||
|
||||
if err := builder.SetDomain(domain); err != nil {
|
||||
return fmt.Errorf("Couldn't set domain: %v", err)
|
||||
}
|
||||
@@ -73,8 +107,9 @@ func Init(filename, domain string, certPEM, keyPEM []byte) error {
|
||||
}
|
||||
|
||||
type concrete struct {
|
||||
filename string
|
||||
storm *storm.DB
|
||||
home string
|
||||
storm *storm.DB
|
||||
|
||||
domainBucket storm.Node
|
||||
|
||||
// These are persisted in BoltDB, but we might as well keep them in memory
|
||||
|
Reference in New Issue
Block a user