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 ", "Auto-Submitted: auto-replied", "nobody@remote.example", "MX lookup failed", "Subject: Hello", "Message-ID: ", } { 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) } }