smtpd/envelope.go

92 lines
2.1 KiB
Go

package smtpd
import (
"io"
"net/mail"
"strings"
baseSmtpd "github.com/bradfitz/go-smtpd/smtpd"
"github.com/go-xweb/log"
)
type DemoEnvelope struct {
SmtpNetwork string `json:"-"`
SmtpRemote string `json:"-"`
MailFrom baseSmtpd.MailAddress `json:"mail_from"`
RcptTo baseSmtpd.MailAddress `json:"rcpt_to"`
Lines strings.Builder `json:"lines"`
}
func (d *DemoEnvelope) AddRecipient(rcpt baseSmtpd.MailAddress) error {
log.Printf("Inbound email from %s for %s", d.MailFrom.Email(), rcpt)
d.RcptTo = rcpt
return nil
}
func (d *DemoEnvelope) BeginData() error {
d.Lines = strings.Builder{}
return nil
}
func (d *DemoEnvelope) Write(line []byte) error {
d.Lines.Write(line)
return nil
}
func (d *DemoEnvelope) Close() error {
msg, err := d.Parse()
if err == nil {
d.Handle(*msg)
}
return nil
}
func (d DemoEnvelope) Handle(message mail.Message) {
//for i, h := range message.Header {
// first := h[0]
// if len(h[1:]) > 0 {
// log.Printf("%-10s %s(+more)\n", i, first)
// } else {
// log.Printf("%-10s %s\n", i, first)
// }
//}
parser := mail.AddressParser{}
from, err := parser.Parse(message.Header.Get("From"))
if err != nil {
log.Errorf("Error parsing From: header: %v\n", err)
from = &mail.Address{}
}
if from.Name == "" {
from.Name = "(no From name)"
}
to, err := parser.Parse(message.Header.Get("To"))
if err != nil {
log.Errorf("Error parsing To: header: %v\n", err)
to = &mail.Address{}
}
if to.Name == "" {
to.Name = "(no To name)"
}
subject := message.Header.Get("Subject")
body, err := io.ReadAll(message.Body)
if err != nil {
log.Errorf("Error reading body: %v", err)
}
log.Printf("From: %-20s (%s)\n", from.Name, from.Address)
log.Printf("To: %-20s (%s)\n", to.Name, to.Address)
log.Printf("Subject: %s\n", subject)
log.Printf("Message:\n%s\n", string(body))
}
func (d DemoEnvelope) Parse() (*mail.Message, error) {
reader := strings.NewReader(d.Lines.String())
message, err := mail.ReadMessage(reader)
if err != nil {
log.Errorf("Error reading submitted message: %v", err)
return &mail.Message{}, err
}
return message, nil
}