package smtp import ( "context" "io" "log" "sync/atomic" "github.com/emersion/go-smtp" "ur.gs/crockery/internal/store" ) type Server interface { Run() io.Closer } func NewServer(cancel context.CancelFunc, datastore store.Interface, submission bool) Server { out := &concrete{ cancel: cancel, store: datastore, } out.server = smtp.NewServer(out) out.server.Domain = datastore.Domain() out.server.TLSConfig = datastore.TLSConfig() if submission { out.name = "submission" out.server.Addr = ":587" } else { out.name = "SMTP" out.server.Addr = ":25" } return out } type concrete struct { name string cancel context.CancelFunc store store.Interface server *smtp.Server // Session IDs sid uint64 } func (c *concrete) Run() { if err := c.server.ListenAndServe(); err != nil { log.Printf("Error serving SMTP %s: %v", c.server.Addr, err) } else { log.Printf("Stopped listening on SMTP %s", c.server.Addr) } c.cancel() } // backend implementation for go-smtp func (c *concrete) Login(user, pass string) (smtp.User, error) { // FIXME: TODO: Check for account existence and correct password(!) session := &Session{ ID: atomic.AddUint64(&c.sid, uint64(1)), AccountName: user, ServiceName: c.name, } log.Printf("Beginning %s session %d for %s", c.name, session.ID, user) return session, nil } func (c *concrete) Close() error { c.cancel() // FIXME: this doesn't touch the server return nil }