list

server

This is the main dovel repository, it has the Go code to run dovel SMTP server.

curl https://dovel.email/server.tar tar

f887f0c

Author: blmayer (bleemayer@gmail.com)

Date: Thu Sep 14 03:01:51 2023 -0300

Parent: f24608b

Improved email sending

Diff

cmd/dovel/backend.go

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"

cmd/dovel/main.go

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)
 	}