Files
mailgoserver/internal/relay/bounce_test.go
T

99 lines
3.0 KiB
Go

package relay
import (
"path/filepath"
"strings"
"testing"
"mailgoserver/internal/db"
"mailgoserver/internal/mailstore"
)
func TestBuildBounceMessageContainsFailureDetails(t *testing.T) {
content, messageID := buildBounceMessage("mail.example.com", "sender@example.com", "Hello", "orig-id@example.com", []Result{
{Recipient: "nobody@remote.example", ErrorMessage: "MX lookup failed", ErrorCode: "MX"},
})
if messageID == "" {
t.Fatal("expected a non-empty bounce Message-ID")
}
for _, want := range []string{
"To: sender@example.com",
"Subject: Undelivered Mail Returned to Sender",
"From: Mail Delivery System <mailer-daemon@mail.example.com>",
"Auto-Submitted: auto-replied",
"nobody@remote.example",
"MX lookup failed",
"Subject: Hello",
"Message-ID: <orig-id@example.com>",
} {
if !strings.Contains(content, want) {
t.Errorf("expected bounce content to contain %q, got:\n%s", want, content)
}
}
}
func TestSendBounceNoOpWithoutSenderOrFailures(t *testing.T) {
r := &Relay{Hostname: "mail.example.com"}
if err := r.SendBounce("", "subj", "id", []Result{{Recipient: "x@example.com", ErrorMessage: "boom"}}); err != nil {
t.Fatalf("expected nil error for empty sender, got %v", err)
}
if err := r.SendBounce("sender@example.com", "subj", "id", nil); err != nil {
t.Fatalf("expected nil error for no failures, got %v", err)
}
}
// newTestMailbox mirrors mailstore's own test helper of the same name — kept local
// since it's unexported there and this package needs its own small Store+mailbox
// fixture to test SendBounce's local-delivery shortcut.
func newTestMailbox(t *testing.T, email string) (*mailstore.Store, int64) {
t.Helper()
database, err := db.Open(filepath.Join(t.TempDir(), "test.db"))
if err != nil {
t.Fatal(err)
}
t.Cleanup(func() { database.Close() })
domainID, err := database.CreateDomain("example.com")
if err != nil {
t.Fatal(err)
}
s := mailstore.New(database, mailstore.GenerateDEK(), t.TempDir())
dek := mailstore.GenerateDEK()
wrapped, nonce, err := s.WrapDEK(dek)
if err != nil {
t.Fatal(err)
}
hash, err := db.HashPassword("irrelevant-portal-password")
if err != nil {
t.Fatal(err)
}
mailboxID, err := database.CreateMailbox(email, hash, domainID, 1<<30, wrapped, nonce)
if err != nil {
t.Fatal(err)
}
return s, mailboxID
}
func TestSendBounceDeliversLocallyWhenRecipientIsLocalMailbox(t *testing.T) {
store, mailboxID := newTestMailbox(t, "sender@example.com")
r := &Relay{Hostname: "mail.example.com", Mailstore: store, Logger: nil}
err := r.SendBounce("sender@example.com", "Hello", "orig-id@example.com", []Result{
{Recipient: "nobody@remote.example", ErrorMessage: "MX lookup failed", ErrorCode: "MX"},
})
if err != nil {
t.Fatalf("SendBounce: %v", err)
}
inbox, err := store.DB.ListMessagesInFolder(mailboxID, "INBOX")
if err != nil {
t.Fatal(err)
}
if len(inbox) != 1 {
t.Fatalf("expected 1 bounce message in INBOX, got %d", len(inbox))
}
if inbox[0].CachedSubject != "Undelivered Mail Returned to Sender" {
t.Errorf("bounce subject = %q", inbox[0].CachedSubject)
}
}