package smtp import ( "context" "strings" "testing" "code.yun.ink/pkg/mailx/interfaces" ) // 测试内容类型检测 func TestContentTypeDetection(t *testing.T) { smtpClient := NewSmtp() tests := []struct { name string body string expected interfaces.ContentType }{ { name: "HTML with html tag", body: "Test", expected: interfaces.ContentTypeHTML, }, { name: "HTML with div tag", body: "
Test content
", expected: interfaces.ContentTypeHTML, }, { name: "HTML with img tag", body: "Check this image: ", expected: interfaces.ContentTypeHTML, }, { name: "Plain text", body: "This is plain text without any HTML tags.", expected: interfaces.ContentTypeText, }, { name: "Text with angle brackets", body: "Price: 100 < 200, Quality: A > B", expected: interfaces.ContentTypeText, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { result := smtpClient.detectContentType(tt.body) if result != tt.expected { t.Errorf("Expected %s, got %s for body: %s", tt.expected, result, tt.body) } }) } } // 测试邮件头构建 func TestBuildHeaders(t *testing.T) { smtpClient := NewSmtp() smtpClient.SetOption(context.Background(), interfaces.SetSmtp(&interfaces.EmailConfigDataSmtp{})) boundary := "test-boundary" tests := []struct { name string message interfaces.Message expected string }{ { name: "HTML with inline images", message: interfaces.Message{ Subject: "Test Subject", InlineImage: []interfaces.Attachment{{Name: "test.jpg"}}, }, expected: "multipart/related", }, { name: "HTML with attachments", message: interfaces.Message{ Subject: "Test Subject", Attachment: []interfaces.Attachment{{Name: "test.pdf"}}, }, expected: "multipart/mixed", }, { name: "Simple message", message: interfaces.Message{ Subject: "Test Subject", }, expected: "multipart/alternative", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { headers := smtpClient.buildHeaders(tt.message, boundary) contentType := headers["Content-Type"] if !strings.Contains(contentType, tt.expected) { t.Errorf("Expected Content-Type to contain %s, got %s", tt.expected, contentType) } }) } } // 测试附件类型处理 func TestAttachmentTypes(t *testing.T) { tests := []struct { name string attachment interfaces.Attachment expectCID bool }{ { name: "File attachment", attachment: interfaces.Attachment{ Name: "document.pdf", Type: interfaces.AttachmentTypeFile, }, expectCID: false, }, { name: "Inline image", attachment: interfaces.Attachment{ Name: "image.jpg", Type: interfaces.AttachmentTypeInline, CID: "test-image", }, expectCID: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if tt.expectCID && tt.attachment.CID == "" { t.Error("Expected CID for inline attachment") } if !tt.expectCID && tt.attachment.Type == interfaces.AttachmentTypeFile { // File attachments should not have CID if tt.attachment.CID != "" { t.Error("File attachment should not have CID") } } }) } } // 测试消息验证 func TestMessageValidation2(t *testing.T) { smtpClient := NewSmtp() ctx := context.Background() // 配置SMTP客户端 err := smtpClient.SetOption(ctx, func(opt *interfaces.Options) { opt.Smtp = &interfaces.EmailConfigDataSmtp{ Host: "smtp.example.com", Port: "587", Username: "test@example.com", Password: "password", } }) if err != nil { t.Fatalf("Failed to configure SMTP: %v", err) } tests := []struct { name string message interfaces.Message wantErr bool }{ { name: "Valid HTML message", message: interfaces.Message{ To: []string{"test@example.com"}, Subject: "Test", Body: "

Test

", BodyType: interfaces.ContentTypeHTML, }, wantErr: false, }, { name: "Valid text message", message: interfaces.Message{ To: []string{"test@example.com"}, Subject: "Test", Body: "Plain text", BodyType: interfaces.ContentTypeText, }, wantErr: false, }, { name: "Message with inline images", message: interfaces.Message{ To: []string{"test@example.com"}, Subject: "Test", Body: "", InlineImage: []interfaces.Attachment{ { Name: "test.jpg", CID: "test", Type: interfaces.AttachmentTypeInline, }, }, }, wantErr: false, }, { name: "Empty recipients", message: interfaces.Message{ Subject: "Test", Body: "Test body", }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { err := smtpClient.validateMessage(tt.message) if (err != nil) != tt.wantErr { t.Errorf("validateMessage() error = %v, wantErr %v", err, tt.wantErr) } }) } } // 测试多部分邮件构建 func TestMultipartEmailConstruction2(t *testing.T) { smtpClient := NewSmtp() ctx := context.Background() err := smtpClient.SetOption(ctx, func(opt *interfaces.Options) { opt.Smtp = &interfaces.EmailConfigDataSmtp{ Host: "smtp.example.com", Port: "587", Username: "test@example.com", Password: "password", } }) if err != nil { t.Fatalf("Failed to configure SMTP: %v", err) } message := interfaces.Message{ To: []string{"recipient@example.com"}, Subject: "Multipart Test", BodyType: interfaces.ContentTypeHTML, Body: "

HTML Content

", TextBody: "Plain text version", InlineImage: []interfaces.Attachment{ { Data: []byte("fake-image-data"), ContentType: "image/jpeg", Name: "test.jpg", CID: "test-img", Type: interfaces.AttachmentTypeInline, }, }, Attachment: []interfaces.Attachment{ { Data: []byte("fake-pdf-data"), ContentType: "application/pdf", Name: "document.pdf", Type: interfaces.AttachmentTypeFile, }, }, } // 测试邮件构建(不实际发送) boundary := "test-boundary" headers := smtpClient.buildHeaders(message, boundary) // 验证Content-Type contentType := headers["Content-Type"] if !strings.Contains(contentType, "multipart/related") { t.Errorf("Expected multipart/related for message with inline images, got %s", contentType) } // 验证必要的头部字段 requiredHeaders := []string{"From", "To", "Subject", "Date", "MIME-Version", "Content-Type"} for _, header := range requiredHeaders { if _, exists := headers[header]; !exists { t.Errorf("Missing required header: %s", header) } } } // 测试字节数据附件 func TestByteDataAttachment(t *testing.T) { attachment := interfaces.Attachment{ Data: []byte("test file content"), ContentType: "text/plain", Name: "test.txt", Type: interfaces.AttachmentTypeFile, } if len(attachment.Data) == 0 { t.Error("Attachment data should not be empty") } if attachment.ContentType != "text/plain" { t.Errorf("Expected content type text/plain, got %s", attachment.ContentType) } } // 基准测试:HTML邮件构建性能 func BenchmarkHTMLEmailConstruction(b *testing.B) { smtpClient := NewSmtp() ctx := context.Background() smtpClient.SetOption(ctx, func(opt *interfaces.Options) { opt.Smtp = &interfaces.EmailConfigDataSmtp{ Host: "smtp.example.com", Port: "587", Username: "test@example.com", Password: "password", } }) message := interfaces.Message{ To: []string{"test@example.com"}, Subject: "Benchmark Test", BodyType: interfaces.ContentTypeHTML, Body: "

Benchmark

Performance test content

", TextBody: "Benchmark - Performance test content", InlineImage: []interfaces.Attachment{ { Data: make([]byte, 1024), // 1KB fake image ContentType: "image/jpeg", Name: "test.jpg", CID: "test-img", Type: interfaces.AttachmentTypeInline, }, }, } b.ResetTimer() for i := 0; i < b.N; i++ { boundary := "benchmark-boundary" headers := smtpClient.buildHeaders(message, boundary) _ = headers } } // 测试大附件处理 func TestLargeAttachmentHandling(t *testing.T) { // 创建大附件数据(模拟) largeData := make([]byte, 1024*1024) // 1MB for i := range largeData { largeData[i] = byte(i % 256) } attachment := interfaces.Attachment{ Data: largeData, ContentType: "application/octet-stream", Name: "large_file.bin", Type: interfaces.AttachmentTypeFile, } if len(attachment.Data) != 1024*1024 { t.Errorf("Expected 1MB data, got %d bytes", len(attachment.Data)) } // 测试是否超过限制(25MB) maxSize := 25 * 1024 * 1024 if len(attachment.Data) > maxSize { t.Errorf("Attachment size %d exceeds limit %d", len(attachment.Data), maxSize) } }