platform/email: add attachment support; order delegates SMTP to it
go-cart-actor's hand-rolled SMTP stack (SASL loginAuth/plainAuth, dial/ STARTTLS/auth/MAIL/RCPT/DATA wire code, MIME builders) is replaced by an adapter over platform/email, which gains the multipart/mixed attachment envelope ported from it. One SMTP implementation now serves both the order/ledger senders and go-auth's AUTH_EMAIL_* flows; public surfaces (SMTPEmailSenderConfig, NewSMTPEmailSender, EmailSender, EmailMessage) are unchanged so all callers compile untouched. Bumps the go-cart-actor pin to 7cad997. Generated with Codebuff 🤖 Co-Authored-By: Codebuff <noreply@codebuff.com>
This commit is contained in:
1 parent
59c737b4fb
commit
b585245d47
2 files changed
+115
-4
No files matched your search
@@ -2,6 +2,7 @@ package email
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"net/mail"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -157,6 +158,50 @@ func TestBuildMessageRejectsHeaderInjection(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildMessageAttachment(t *testing.T) {
|
||||
body, err := buildMessage(Message{
|
||||
From: mail.Address{Name: "B2B Demo AB", Address: "faktura@demo.se"},
|
||||
To: []mail.Address{{Address: "faktura@falk.se"}},
|
||||
Subject: "Faktura INV-000001",
|
||||
TextBody: "Hej,\nFaktura bifogas.",
|
||||
Attachments: []Attachment{{
|
||||
Filename: "INV-000001.pdf",
|
||||
Content: []byte("%PDF-1.4 fake"),
|
||||
}},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("buildMessage: %v", err)
|
||||
}
|
||||
s := string(body)
|
||||
for _, want := range []string{
|
||||
"multipart/mixed;",
|
||||
`Content-Type: application/pdf; name="INV-000001.pdf"`,
|
||||
`Content-Disposition: attachment; filename="INV-000001.pdf"`,
|
||||
"Content-Transfer-Encoding: base64",
|
||||
} {
|
||||
if !strings.Contains(s, want) {
|
||||
t.Errorf("message missing %q", want)
|
||||
}
|
||||
}
|
||||
|
||||
// The attachment payload round-trips: extract the base64 blob between the
|
||||
// attachment part header and the closing CRLF, decode, compare.
|
||||
idx := strings.Index(s, `Content-Disposition: attachment; filename="INV-000001.pdf"`)
|
||||
rest := s[idx:]
|
||||
lineEnd := strings.Index(rest, "\r\n\r\n")
|
||||
if lineEnd < 0 {
|
||||
t.Fatal("attachment part has no body separator")
|
||||
}
|
||||
b64line := strings.SplitN(rest[lineEnd+4:], "\r\n", 2)[0]
|
||||
decoded, err := base64.StdEncoding.DecodeString(strings.TrimSpace(b64line))
|
||||
if err != nil {
|
||||
t.Fatalf("decode attachment base64: %v", err)
|
||||
}
|
||||
if string(decoded) != "%PDF-1.4 fake" {
|
||||
t.Fatalf("attachment content = %q", decoded)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildMessageMissingBody(t *testing.T) {
|
||||
if _, err := buildMessage(Message{
|
||||
From: testFrom(), To: []mail.Address{{Address: "a@b"}}, Subject: "x",
|
||||
|
||||
Reference in new issue
Block a user