This is the main dovel repository, it has the Go code to run dovel SMTP server.
Author: blmayer (bleemayer@gmail.com)
Date: Thu Sep 14 03:01:51 2023 -0300
Parent: f24608b
Improved email sending
commit f887f0c0b373f2c52354c9fa037a107ad2a388c3 Author: blmayer <bleemayer@gmail.com> Date: Thu Sep 14 03:01:51 2023 -0300 Improved email sending diff --git a/cmd/dovel/backend.go b/cmd/dovel/backend.go index 3da1372..6ada099 100644 --- a/cmd/dovel/backend.go +++ b/cmd/dovel/backend.go @@ -69,33 +69,31 @@ func (s *Session) Data(raw io.Reader) error { } // sending email - from, err := mail.ParseAddress(s.from) - if err != nil { - println("parse from", err.Error()) - return err - } - domain := strings.Split(from.Address, "@")[1] - - h := path.Join(configPath, "hooks", "send-"+domain) - if f, err := os.Lstat(h); err == nil { - if !f.Mode().IsRegular() { - h, err = os.Readlink(h) - if err != nil { - println(domain, "read link", err.Error()) - } - } - + dom := strings.Split(s.from, "@")[1] + if dom == domain { err = s.Send(s.from, s.tos, strings.NewReader(string(cont))) if err != nil { println("send", err.Error()) return err } - c := exec.Command(h) - c.Stdin = strings.NewReader(string(mess)) - c.Stdout = os.Stdout - if err := c.Run(); err != nil { - println("run script", err.Error()) - return err + + // running handlers is optional + h := path.Join(configPath, "hooks", "send-"+domain) + if f, err := os.Lstat(h); err == nil { + if !f.Mode().IsRegular() { + h, err = os.Readlink(h) + if err != nil { + println(domain, "read link", err.Error()) + } + } + + c := exec.Command(h) + c.Stdin = strings.NewReader(string(mess)) + c.Stdout = os.Stdout + if err := c.Run(); err != nil { + println("run script", err.Error()) + return err + } } } @@ -124,7 +122,7 @@ func (s *Session) Data(raw io.Reader) error { c.Stdout = os.Stdout if err := c.Run(); err != nil { println("run script", err.Error()) - return err + continue } } @@ -143,7 +141,13 @@ func (s *Session) Send(from string, tos []string, raw io.Reader) error { if err != nil { return err } + if email.Header.Get("message-id") == "" { + email.Header["Message-ID"] = []string{ + fmt.Sprintf("%s%d", from, time.Now().Unix()), + } + } + fromdom := strings.Split(from, "@") body, err := io.ReadAll(email.Body) if err != nil { return err @@ -161,10 +165,7 @@ func (s *Session) Send(from string, tos []string, raw io.Reader) error { return err } - key, err := wkd.FetchPGPKey(addr[0], addr[1]) - if err != nil { - return err - } + key, _ := wkd.FetchPGPKey(addr[0], addr[1]) if key != "" { email.Header["Content-Type"] = []string{"application/pgp-encrypted"} msg, err = helper.EncryptMessageArmored(key, msg) @@ -183,14 +184,18 @@ func (s *Session) Send(from string, tos []string, raw io.Reader) error { // dkim res := bytes.Buffer{} - options := &dkim.SignOptions{ - Domain: domain, - Selector: "dkim", - Signer: v.GetUser(s.user).PrivateKey, - } - err = dkim.Sign(&res, &payload, options) - if err != nil { - println("failed to sign body:", err.Error()) + if sig := v.GetUser(s.user).PrivateKey; sig != nil { + options := &dkim.SignOptions{ + Domain: fromdom[1], + Selector: "dkim", + Signer: v.GetUser(s.user).PrivateKey, + } + err = dkim.Sign(&res, &payload, options) + if err != nil { + println("failed to sign body:", err.Error()) + } + } else { + io.Copy(&res, &payload) } server := mxs[0].Host + ":smtp"
commit f887f0c0b373f2c52354c9fa037a107ad2a388c3 Author: blmayer <bleemayer@gmail.com> Date: Thu Sep 14 03:01:51 2023 -0300 Improved email sending diff --git a/cmd/dovel/main.go b/cmd/dovel/main.go index 76c9df4..28e5b20 100644 --- a/cmd/dovel/main.go +++ b/cmd/dovel/main.go @@ -12,9 +12,9 @@ import ( ) var ( - domain string + domain string configPath string - v vault.Vault[email.User] + v vault.Vault[email.User] ) func main() { @@ -32,6 +32,7 @@ func main() { cfg := email.Config{} json.NewDecoder(configFile).Decode(&cfg) + domain = cfg.Domain v, err = vault.NewJSONPlainTextVault[email.User](cfg.VaultFile) if err != nil { @@ -39,13 +40,13 @@ func main() { } s := smtp.NewServer(backend{}) - s.Addr = ":"+cfg.Port + s.Addr = ":" + cfg.Port s.Domain = cfg.Domain s.ReadTimeout = 10 * time.Second s.WriteTimeout = 10 * time.Second s.MaxMessageBytes = 1024 * 1024 s.MaxRecipients = 5 - + if err := s.ListenAndServe(); err != nil { panic(err) }