diff --git a/email.go b/email.go new file mode 100644 index 0000000..a772456 --- /dev/null +++ b/email.go @@ -0,0 +1,108 @@ +package main + +import ( + "crypto/tls" + "flag" + "io" + "log" + "time" + + smtp "github.com/emersion/go-smtp" +) + +func startSMTPServer() { + keyPath := flag.Arg(1) + if keyPath == "" { + log.Println("No argument given for key files. smtp signing off...") + quitChan <- "smtp arg" + return + } + tlsCert, err := tls.LoadX509KeyPair(keyPath+"/fullchain.pem", keyPath+"/key.pem") + if err != nil { + log.Println("Error while loading tls certificate:", err) + quitChan <- "smtp err" + return + } + cfg := &tls.Config{Certificates: []tls.Certificate{tlsCert}} + serv := smtp.NewServer(&SMTPBackend{ + tlsConfig: cfg, + }) + serv.Network = "tcp" + serv.Addr = ":587" + serv.TLSConfig = cfg + serv.Domain = "darkstorm.tech" + serv.WriteTimeout = 10 * time.Second + serv.ReadTimeout = 10 * time.Second + serv.MaxMessageBytes = 1024 * 1024 + serv.AllowInsecureAuth = true + serv.MaxRecipients = 2 + err = serv.ListenAndServeTLS() + log.Println("Error while serving smtp:", err) + quitChan <- "smtp err" +} + +type SMTPBackend struct { + tlsConfig *tls.Config +} + +func (b *SMTPBackend) NewSession(c *smtp.Conn) (smtp.Session, error) { + return NewSession(b.tlsConfig, c.Server().Addr) +} + +type SMTPSession struct { + tlsConfig *tls.Config + client *smtp.Client + addr string +} + +func NewSession(tlsConfig *tls.Config, addr string) (*SMTPSession, error) { + client, err := smtp.DialTLS(addr, tlsConfig) + if err != nil { + return nil, err + } + return &SMTPSession{ + tlsConfig: tlsConfig, + client: client, + addr: addr, + }, nil +} + +func (s *SMTPSession) Reset() { + var err error + s.client, err = smtp.DialTLS(s.addr, s.tlsConfig) + if err != nil { + log.Println("Error while resetting smtp session:", err) + } +} + +func (s *SMTPSession) Logout() error { + return s.client.Quit() +} + +func (s *SMTPSession) AuthPlain(username, password string) error { + //TODO + return nil +} + +func (s *SMTPSession) Mail(from string, opts *smtp.MailOptions) error { + return s.client.Mail(from, opts) +} + +func (s *SMTPSession) Rcpt(to string, opts *smtp.RcptOptions) error { + return s.client.Rcpt(to, opts) +} + +func (s *SMTPSession) Data(r io.Reader) error { + wrt, err := s.client.Data() + if err != nil { + log.Println("Error while writing smtp data:", err) + return err + } + _, err = io.Copy(wrt, r) + if err != nil { + log.Println("Error while writing smtp data:", err) + return err + } + wrt.Close() + return nil +} diff --git a/go.mod b/go.mod index f0e2227..b6af9a3 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,10 @@ require ( go.mongodb.org/mongo-driver v1.13.1 ) +require github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect + require ( + github.com/emersion/go-smtp v0.20.2 github.com/golang/snappy v0.0.4 // indirect github.com/google/uuid v1.6.0 // indirect github.com/klauspost/compress v1.17.6 // indirect diff --git a/go.sum b/go.sum index 3e905a6..206b640 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,10 @@ github.com/CalebQ42/swassistant-backend v0.2.1 h1:DqBx1pvPgMOE7LbzxvSoasH83FDgGL github.com/CalebQ42/swassistant-backend v0.2.1/go.mod h1:WY+3UvzBcTUoZMtYCVhNWfFW/Cx3lBActCJfk+EUD0s= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ= +github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= +github.com/emersion/go-smtp v0.20.2 h1:peX42Qnh5Q0q3vrAnRy43R/JwTnnv75AebxbkTL7Ia4= +github.com/emersion/go-smtp v0.20.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= diff --git a/main.go b/main.go index a5b46af..9972ee2 100644 --- a/main.go +++ b/main.go @@ -13,6 +13,7 @@ func main() { flag.Parse() go linker() go webserver(*mongoStr) + go startSMTPServer() for failure := <-quitChan; ; failure = <-quitChan { switch failure { case "tcp conf": @@ -23,6 +24,11 @@ func main() { continue case "web err": go websiteRestart(*mongoStr) + case "smtp arg": + continue + case "smtp err": + //TODO: restart smtp server + continue } } } @@ -39,4 +45,4 @@ func websiteRestart(mongoStr string) { time.Sleep(5 * time.Second) log.Println("Restarting website") webserver(mongoStr) -} \ No newline at end of file +}