Files
mailgoserver/internal/webui/view_message_content_test.go
T

88 lines
3.0 KiB
Go

package webui
import (
"net/http"
"net/http/httptest"
"strconv"
"strings"
"testing"
"time"
"mailgoserver/internal/db"
)
// 1x1 transparent PNG, base64-encoded — a minimal real image for the attachment part.
const testPNGBase64 = "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII="
func buildTestMIMEMessageWithImage() string {
boundary := "testboundary123"
return strings.Join([]string{
"From: attacker@evil.example",
"To: victim@example.com",
"Subject: Free money",
"MIME-Version: 1.0",
"Content-Type: multipart/mixed; boundary=\"" + boundary + "\"",
"",
"--" + boundary,
`Content-Type: text/html; charset="UTF-8"`,
"",
"<p>Click <b>here</b> to claim your prize.</p>",
"",
"--" + boundary,
"Content-Type: image/png",
"Content-Transfer-Encoding: base64",
`Content-Disposition: attachment; filename="lure.png"`,
"",
testPNGBase64,
"",
"--" + boundary + "--",
}, "\r\n")
}
// TestViewMessageContentRendersHTMLAndAttachmentInlineForStoredContent confirms that
// when a log's message_body holds a full raw message (the new default for a
// quarantined/opted-in message — see session.go's storeContent), the "View Full
// Message" page actually renders the real HTML body and offers the attachment inline
// (as a data: URI, no separate file/route needed) — not just a plain-text dump, and
// not silently dropping the image the way the old text-only capture always did.
func TestViewMessageContentRendersHTMLAndAttachmentInlineForStoredContent(t *testing.T) {
app := newTestApp(t)
mux := app.Mux()
cookie := loginSession(t, app)
logID, err := app.DB.InsertEmailLog(db.EmailLog{
MessageID: "test-msg-id", Timestamp: time.Now(), PeerIP: "203.0.113.5",
MailFrom: "attacker@evil.example", ToAddress: "victim@example.com", Subject: "Free money",
EmailHeaders: "From: attacker@evil.example\nSubject: Free money",
MessageBody: buildTestMIMEMessageWithImage(),
Status: "failed",
})
if err != nil {
t.Fatal(err)
}
req := httptest.NewRequest(http.MethodGet, Prefix+"/msg/content/"+strconv.FormatInt(logID, 10), nil)
req.AddCookie(cookie)
rec := httptest.NewRecorder()
mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected 200, got %d: %s", rec.Code, rec.Body.String())
}
body := rec.Body.String()
if !strings.Contains(body, "Click") || !strings.Contains(body, "<b>here</b>") {
t.Errorf("expected the sanitized HTML body rendered, got:\n%s", body)
}
if !strings.Contains(body, "data:image/png;base64,") {
t.Error("expected the attachment rendered inline as a data: URI")
}
if !strings.Contains(body, "lure.png") {
t.Error("expected the attachment's filename shown")
}
// This is fetched into a modal on the logs page, not navigated to directly — it
// must be a bare fragment, not a full page with the dashboard's own nav/sidebar.
if strings.Contains(body, "<!DOCTYPE") || strings.Contains(body, "Email Server Management") || strings.Contains(body, "sidebar_email") {
t.Errorf("expected a bare fragment with no dashboard chrome, got:\n%s", body)
}
}