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

daa51d7

Author: b (git@mail.blmayer.dev)

Date: Fri Jun 30 20:50:07 2023 -0300

Parent: d301a8d

Improved handlers

Diff

cmd/dovel/backend.go

commit daa51d72677f74977289e7718976094d61417209
Author: b <git@mail.blmayer.dev>
Date:   Fri Jun 30 20:50:07 2023 -0300

    Improved handlers

diff --git a/cmd/dovel/backend.go b/cmd/dovel/backend.go
index cd42039..fdb0ea0 100644
--- a/cmd/dovel/backend.go
+++ b/cmd/dovel/backend.go
@@ -4,6 +4,7 @@ import (
 	"crypto"
 	"fmt"
 	"io"
+	"net/mail"
 	"strings"
 
 	"blmayer.dev/x/dovel/interfaces"
@@ -13,59 +14,73 @@ import (
 
 // A Session is returned after EHLO.
 type Session struct {
-	User     string
+	user     string
 	handlers map[string]interfaces.Mailer
+	from string
+	to   string
 }
 
 func (s Session) AuthPlain(username, password string) error {
 	println("connection sent", username, password)
+	// call vault
 	return nil
 }
 
 func (s Session) Mail(from string, opts *smtp.MailOptions) error {
 	println("Mail from:", from)
+	s.from = from
 	return nil
 }
 
 func (s Session) Rcpt(to string) error {
 	println("Rcpt to:", to)
+	s.to = to
 	return nil
 }
 
 func (s Session) Data(r io.Reader) error {
-	content, err := io.ReadAll(r)
+	email, err := mail.ReadMessage(r)
 	if err != nil {
-		println("read content", err.Error())
+		println("parse email", err.Error())
 		return err
 	}
 
-	email, err := parsemail.Parse(strings.NewReader(string(content)))
+	from, err := mail.ParseAddress(s.from)
 	if err != nil {
-		println("parse email", err.Error())
+		println("parse address", err.Error())
+		return err
+	}
+	fromDomain := strings.Split(from, "@")[1]
+	tos, err := mail.ParseAddressList(s.to)
+	if err != nil {
+		println("parse addresslist", err.Error())
 		return err
 	}
 
-	// get user from to field
-	mail := interfaces.ToEmail(email)
-	mail.Raw = content
-	for _, to := range mail.To {
-		userDomain := strings.Split(to, "@")
-		handler, ok := s.handlers[userDomain[1]]
-		if !ok {
-			println("no handler for domain", userDomain[1])
-			return fmt.Errorf("no handler for domain %s", userDomain)
+	for _, to := range tos {
+		localdom := strings.Split(to.Address, "@")
+		if h, ok := s.handlers[localdom[1]]; ok {
+			err = h.Save(r)
+		} else {
+			if user == "" {
+				return fmt.Errorf("needs auth")
+			}
+			h, ok = s.handlers[fromDomain]
+			if !ok {
+				return fmt.Errorf("from is wrong")
+			}
+			err = h.Send(r)
 		}
-		mail.To = []string{to}
-		if err := handler.Save(mail); err != nil {
+		if err != nil {
 			println("handler error", err.Error())
-			return fmt.Errorf("handler error %s", err.Error())
+			return
 		}
 	}
 
 	return nil
 }
 
-func (s Session) Reset() {}
+func (s Session) Reset() { }
 
 func (s Session) Logout() error {
 	println("logged out")