|
@@ -0,0 +1,92 @@
|
|
|
+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
|
|
|
+}
|