Files
mailgoserver/internal/webui/webmail_bounce_test.go
T

75 lines
2.5 KiB
Go

package webui
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
"mailgoserver/internal/db"
"mailgoserver/internal/mailstore"
)
// TestWebmailComposeSendBouncesFailedRecipientToSenderInbox confirms that when one
// recipient in a multi-recipient send fails (here: an over-quota local mailbox, caught
// only at delivery time — RCPT-equivalent resolution succeeds), the sender still gets
// their flash "sent, but..." feedback AND a persistent bounce notification lands in
// their own INBOX, mirroring a real mail provider's delivery-failure notice.
func TestWebmailComposeSendBouncesFailedRecipientToSenderInbox(t *testing.T) {
app := newTestApp(t)
mux := app.Mux()
domains, _ := app.DB.ListDomains()
domainID := domains[0].ID
senderID := createTestMailboxWithPassword(t, app, "sender@example.com", domainID, "sender-password-1!")
// A second local mailbox with an effectively-zero quota, so StoreMessage always
// fails with ErrQuotaExceeded — a hermetic, deterministic delivery failure with no
// network dependency (unlike a relay-to-external-domain failure would be).
hash, err := db.HashPassword("full-password-1!")
if err != nil {
t.Fatal(err)
}
wrapped, nonce, err := app.Mailstore.WrapDEK(mailstore.GenerateDEK())
if err != nil {
t.Fatal(err)
}
fullID, err := app.DB.CreateMailbox("full@example.com", hash, domainID, 1, wrapped, nonce)
if err != nil {
t.Fatal(err)
}
cookie := webmailLoginSession(t, app, senderID)
form := url.Values{
"to": {"full@example.com"}, "subject": {"Big attachment incoming"}, "body_html": {"body text"},
}
req := httptest.NewRequest(http.MethodPost, MailboxPrefix+"/mail/compose", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.AddCookie(cookie)
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
if rec.Code != http.StatusFound {
t.Fatalf("compose send: status=%d body=%s", rec.Code, rec.Body.String())
}
fullMsgs, err := app.DB.ListMessagesInFolder(fullID, "INBOX")
if err != nil {
t.Fatal(err)
}
if len(fullMsgs) != 0 {
t.Fatalf("expected no message delivered to the over-quota mailbox, got %d", len(fullMsgs))
}
bounces, err := app.DB.ListMessagesInFolder(senderID, "INBOX")
if err != nil {
t.Fatal(err)
}
if len(bounces) != 1 {
t.Fatalf("expected 1 bounce message in the sender's own INBOX, got %d", len(bounces))
}
if bounces[0].CachedSubject != "Undelivered Mail Returned to Sender" {
t.Errorf("bounce subject = %q", bounces[0].CachedSubject)
}
}