@@ -3,6 +3,7 @@ package integration
33import (
44 "encoding/json"
55 "net/http"
6+ "strings"
67 "testing"
78 "time"
89
@@ -397,16 +398,15 @@ func testTransactionalSend(t *testing.T, client *testutil.APIClient, factory *te
397398 require .NoError (t , err )
398399 defer resp .Body .Close ()
399400
400- // In test environment, expect 500 due to missing email provider configuration
401- // In production, this would be 200 with proper email provider setup
402- assert .Equal (t , http .StatusInternalServerError , resp .StatusCode )
401+ // With proper SMTP email provider setup, should succeed
402+ assert .Equal (t , http .StatusOK , resp .StatusCode )
403403
404404 var result map [string ]interface {}
405405 err = json .NewDecoder (resp .Body ).Decode (& result )
406406 require .NoError (t , err )
407407
408- assert .Contains (t , result , "error " )
409- assert .Equal (t , "Failed to send notification" , result [ "error" ] )
408+ assert .Contains (t , result , "message_id " )
409+ assert .NotEmpty (t , result [ "message_id" ], "Message ID should not be empty" )
410410 })
411411
412412 t .Run ("should validate required fields" , func (t * testing.T ) {
@@ -682,10 +682,10 @@ func testTransactionalSendWithCCAndBCC(t *testing.T, client *testutil.APIClient,
682682 )
683683 require .NoError (t , err )
684684
685- // Define all recipients
685+ // Define all recipients - 7 total emails expected
686686 mainRecipient := "receiver@mail.com"
687- ccRecipients := []string {"test1 @mail.com" , "test2 @mail.com" }
688- bccRecipients := []string {"test3 @mail.com" , "test4 @mail.com" }
687+ ccRecipients := []string {"cc1 @mail.com" , "cc2@mail.com" , "cc3 @mail.com" }
688+ bccRecipients := []string {"bcc1 @mail.com" , "bcc2@mail.com" , "bcc3 @mail.com" }
689689
690690 // Build list of all expected recipients
691691 allRecipients := []string {mainRecipient }
@@ -733,18 +733,75 @@ func testTransactionalSendWithCCAndBCC(t *testing.T, client *testutil.APIClient,
733733
734734 t .Logf ("Email sent successfully with message ID: %s" , messageID )
735735
736- // Wait and check Mailhog for all recipients
737- // Note: This checks if the email was sent to SMTP server, not delivery confirmation
738- t .Log ("Checking Mailhog for email delivery to all recipients..." )
736+ // Wait for SMTP server to process all emails
737+ t .Log ("Waiting for emails to be delivered to MailHog..." )
738+ time .Sleep (3 * time .Second )
739+
740+ // Check MailHog to verify all 7 emails were received
741+ t .Log ("Checking MailHog API for email count..." )
742+ mailhogResp , err := http .Get ("http://localhost:8025/api/v2/messages" )
743+ require .NoError (t , err , "Failed to connect to MailHog API" )
744+ defer mailhogResp .Body .Close ()
745+
746+ var mailhogData struct {
747+ Total int `json:"total"`
748+ Items []struct {
749+ To []struct {
750+ Mailbox string `json:"Mailbox"`
751+ Domain string `json:"Domain"`
752+ } `json:"To"`
753+ Content struct {
754+ Headers map [string ][]string `json:"Headers"`
755+ } `json:"Content"`
756+ } `json:"items"`
757+ }
758+
759+ err = json .NewDecoder (mailhogResp .Body ).Decode (& mailhogData )
760+ require .NoError (t , err , "Failed to decode MailHog response" )
761+
762+ t .Logf ("MailHog reports %d total emails" , mailhogData .Total )
763+
764+ // Count emails that match our message (by checking for the Test Email Subject)
765+ emailsForOurMessage := 0
766+ recipientsFound := make (map [string ]bool )
767+
768+ for _ , msg := range mailhogData .Items {
769+ // Check if this is our email by looking at the subject
770+ subjects := msg .Content .Headers ["Subject" ]
771+ if len (subjects ) > 0 && strings .Contains (subjects [0 ], "Test Email Subject" ) {
772+ emailsForOurMessage ++
773+
774+ // Track which recipient received this
775+ for _ , to := range msg .To {
776+ recipientEmail := to .Mailbox + "@" + to .Domain
777+ recipientsFound [recipientEmail ] = true
778+ t .Logf (" Found email to: %s" , recipientEmail )
779+ }
780+ }
781+ }
782+
783+ t .Logf ("Found %d email(s) with our subject in MailHog" , emailsForOurMessage )
739784
740- // Since Mailhog stores each recipient's copy as a separate message for BCC,
741- // we need to check the SMTP server logs or individual messages
742- // For now, we'll verify via message history and logs
785+ // Verify we have exactly 1 email (SMTP sends 1 message to multiple recipients, not separate messages)
786+ assert .Equal (t , 1 , emailsForOurMessage , "Expected 1 email in MailHog with 7 recipients" )
787+
788+ // Verify all 7 expected recipients are present in that 1 email
789+ t .Log ("\n === Recipient Verification ===" )
790+ allRecipientsFound := true
791+ for _ , expectedRecipient := range allRecipients {
792+ if recipientsFound [expectedRecipient ] {
793+ t .Logf (" ✅ %s - received email" , expectedRecipient )
794+ } else {
795+ t .Errorf (" ❌ %s - DID NOT receive email" , expectedRecipient )
796+ allRecipientsFound = false
797+ }
798+ }
743799
744- // Give the SMTP server a moment to process
745- time .Sleep (2 * time .Second )
800+ // Verify we found exactly 7 recipients
801+ assert .Equal (t , 7 , len (recipientsFound ), "Expected exactly 7 recipients in the email" )
802+ assert .True (t , allRecipientsFound , "All 7 recipients should be present in the email" )
746803
747- // Verify message history was created
804+ // Verify message history was created for the main recipient
748805 messageResp , err := client .Get ("/api/messages.list?workspace_id=" + workspaceID + "&id=" + messageID )
749806 require .NoError (t , err )
750807 defer messageResp .Body .Close ()
@@ -763,27 +820,14 @@ func testTransactionalSendWithCCAndBCC(t *testing.T, client *testutil.APIClient,
763820 message := messages [0 ].(map [string ]interface {})
764821 assert .Equal (t , mainRecipient , message ["contact_email" ], "Message should be recorded for main recipient" )
765822
766- t .Log ("✅ Message history created successfully" )
767- t .Log ("⚠️ Note: CC and BCC recipients are handled by the SMTP server" )
768- t .Log (" Message history only tracks the primary recipient as per design" )
769- t .Log (" To verify CC/BCC delivery, check Mailhog UI at http://localhost:8025" )
770-
771- // Log summary
772- t .Logf ("\n === Test Summary ===" )
773- t .Logf ("Expected behavior:" )
774- t .Logf (" - 1 message to: %s (main recipient)" , mainRecipient )
775- t .Logf (" - 2 messages to: %v (CC)" , ccRecipients )
776- t .Logf (" - 2 messages to: %v (BCC)" , bccRecipients )
777- t .Logf (" - Total: 5 recipients should receive the email" )
778- t .Logf ("\n Actual behavior:" )
779- t .Logf (" - API accepted the request: ✅" )
780- t .Logf (" - Message ID returned: %s ✅" , messageID )
781- t .Logf (" - Message history created: ✅" )
782- t .Logf ("\n To manually verify all recipients received the email:" )
783- t .Logf (" 1. Open Mailhog UI: http://localhost:8025" )
784- t .Logf (" 2. Look for emails with subject containing the template content" )
785- t .Logf (" 3. Verify 5 separate message deliveries (1 main + 2 CC + 2 BCC)" )
786- t .Logf (" 4. Note: CC recipients appear in headers, BCC do not" )
823+ // Final summary
824+ t .Log ("\n === Final Test Summary ===" )
825+ t .Logf ("✅ API accepted the request and returned message ID: %s" , messageID )
826+ t .Logf ("✅ MailHog received 1 email with 7 recipients (1 main + 3 CC + 3 BCC)" )
827+ t .Logf ("✅ All 7 recipients are included in the email envelope" )
828+ t .Logf ("✅ Message history created for primary recipient" )
829+ t .Log ("\n Note: SMTP sends 1 email to multiple recipients, not separate emails." )
830+ t .Log ("The CC recipients are visible in the Cc header, BCC recipients are hidden." )
787831 })
788832
789833 t .Run ("should validate email addresses in CC and BCC" , func (t * testing.T ) {
@@ -832,7 +876,7 @@ func testTransactionalSendWithCCAndBCC(t *testing.T, client *testutil.APIClient,
832876 assert .Equal (t , http .StatusBadRequest , resp .StatusCode , "Should reject invalid BCC email" )
833877 })
834878
835- t .Run ("should handle empty strings in CC and BCC arrays" , func (t * testing.T ) {
879+ t .Run ("should reject empty strings in CC and BCC arrays" , func (t * testing.T ) {
836880 // Create a template and notification
837881 template , err := factory .CreateTemplate (workspaceID )
838882 require .NoError (t , err )
@@ -848,31 +892,31 @@ func testTransactionalSendWithCCAndBCC(t *testing.T, client *testutil.APIClient,
848892 )
849893 require .NoError (t , err )
850894
851- // Send with empty strings in CC/BCC ( should be filtered out)
895+ // Send with empty strings in CC - should be rejected
852896 sendRequest := map [string ]interface {}{
853897 "id" : notification .ID ,
854898 "contact" : map [string ]interface {}{
855899 "email" : "receiver@mail.com" ,
856900 },
857901 "channels" : []string {"email" },
858902 "email_options" : map [string ]interface {}{
859- "cc" : []string {"" , "valid@mail.com" , "" },
860- "bcc" : []string {"" , "" , "another@mail.com" },
903+ "cc" : []string {"" , "valid@mail.com" },
861904 },
862905 }
863906
864907 resp , err := client .SendTransactionalNotification (sendRequest )
865908 require .NoError (t , err )
866909 defer resp .Body .Close ()
867910
868- // Should succeed - empty strings are filtered out by the code
869- assert .Equal (t , http .StatusOK , resp .StatusCode , "Should accept arrays with empty strings" )
911+ // Should fail validation - empty strings are not allowed
912+ assert .Equal (t , http .StatusBadRequest , resp .StatusCode , "Should reject empty strings in CC " )
870913
871914 var result map [string ]interface {}
872915 err = json .NewDecoder (resp .Body ).Decode (& result )
873916 require .NoError (t , err )
874917
875- assert .Contains (t , result , "message_id" )
876- t .Log ("✅ Empty strings in CC/BCC arrays are properly filtered out" )
918+ assert .Contains (t , result , "error" )
919+ assert .Contains (t , result ["error" ].(string ), "cc" )
920+ t .Log ("✅ Empty strings in CC/BCC arrays are properly rejected" )
877921 })
878922}
0 commit comments