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