Files
emailsender/pkg/email/email_test.go
T
urko b3c22c261e feat: harden SMTP transport
Add explicit TLS modes, context-aware delivery, and typed transport errors.
Preserve raw MIME messages and cover the new delivery paths with local SMTP tests.
2026-08-18 18:16:22 -06:00

69 lines
1.9 KiB
Go

package email
import (
"bytes"
"context"
"errors"
"strings"
"testing"
)
func TestMockSendEmailCompatibility(t *testing.T) {
t.Parallel()
called := false
service := NewMockMailService(func(params ...interface{}) {
called = true
if len(params) != 1 || params[0] != "marker" {
t.Fatalf("unexpected callback params: %#v", params)
}
}, "marker")
err := service.SendEmail(MessageWithAttachments{
To: "test@example.com",
Subject: "Test Email",
Body: "This is a test email.",
})
if err != nil {
t.Fatalf("SendEmail: %v", err)
}
if !called {
t.Fatal("mock callback was not invoked")
}
}
func TestStructuredMessageRejectsHeaderInjection(t *testing.T) {
t.Parallel()
service := NewMockMailService(nil)
tests := []MessageWithAttachments{
{To: "victim@example.com", Subject: "subject\r\nBcc: attacker@example.com", Body: "body"},
{To: "victim@example.com\r\nBcc: attacker@example.com", Subject: "subject", Body: "body"},
{
To: "victim@example.com",
Subject: "subject",
Body: "body",
Attachments: []EmailAttachment{{
Title: "file.txt\r\nX-Injected: yes",
File: bytes.NewBufferString("content"),
}},
},
}
for index, message := range tests {
if err := service.SendEmailContext(context.Background(), message); err == nil {
t.Fatalf("case %d accepted injected header", index)
}
}
}
func TestLegacyConstructorReturnsSafeConfigurationError(t *testing.T) {
t.Parallel()
service := NewSecure(SecureConfig{Host: "", Port: "587", From: "sender@example.com"})
err := service.SendRaw(RawMessage{To: "recipient@example.com", Body: "Subject: x\r\n\r\nbody"})
var transportError *Error
if !errors.As(err, &transportError) || transportError.Kind != ErrorKindPermanent {
t.Fatalf("error=%v, want permanent configuration error", err)
}
if strings.Contains(err.Error(), "recipient@example.com") {
t.Fatalf("configuration error leaked message data: %v", err)
}
}