b3c22c261e
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.
69 lines
1.9 KiB
Go
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)
|
|
}
|
|
}
|