11package org .rostilos .codecrow .email ;
22
3- import com .icegreen .greenmail .util .GreenMail ;
4- import com .icegreen .greenmail .util .ServerSetupTest ;
3+ import com .icegreen .greenmail .configuration .GreenMailConfiguration ;
4+ import com .icegreen .greenmail .junit5 .GreenMailExtension ;
5+ import com .icegreen .greenmail .util .ServerSetup ;
6+ import jakarta .mail .Multipart ;
57import jakarta .mail .internet .MimeMessage ;
68import org .junit .jupiter .api .*;
9+ import org .junit .jupiter .api .extension .RegisterExtension ;
710import org .springframework .mail .SimpleMailMessage ;
811import org .springframework .mail .javamail .JavaMailSenderImpl ;
912import org .springframework .mail .javamail .MimeMessageHelper ;
1518/**
1619 * Integration test for email delivery using GreenMail embedded SMTP server.
1720 * Verifies actual SMTP delivery, HTML rendering, multi-part messages.
21+ *
22+ * Uses {@link GreenMailExtension} with a dynamic port to avoid port conflicts
23+ * in CI environments and ensure proper server lifecycle management.
1824 */
1925@ TestMethodOrder (MethodOrderer .OrderAnnotation .class )
2026class EmailDeliveryIT {
2127
22- private GreenMail greenMail ;
28+ @ RegisterExtension
29+ static GreenMailExtension greenMail = new GreenMailExtension (
30+ new ServerSetup (0 , null , ServerSetup .PROTOCOL_SMTP ))
31+ .withConfiguration (GreenMailConfiguration .aConfig ().withDisabledAuthentication ());
32+
2333 private JavaMailSenderImpl mailSender ;
2434
2535 @ BeforeEach
2636 void setup () {
27- greenMail = new GreenMail (ServerSetupTest .SMTP );
28- greenMail .start ();
37+ greenMail .reset ();
2938
3039 mailSender = new JavaMailSenderImpl ();
3140 mailSender .setHost ("localhost" );
@@ -37,9 +46,32 @@ void setup() {
3746 props .put ("mail.smtp.starttls.enable" , "false" );
3847 }
3948
40- @ AfterEach
41- void teardown () {
42- greenMail .stop ();
49+ /**
50+ * Extracts text content from a MimeMessage, handling both plain text
51+ * and nested multipart (HTML) messages.
52+ */
53+ private String extractTextContent (MimeMessage msg ) throws Exception {
54+ Object content = msg .getContent ();
55+ if (content instanceof String s ) {
56+ return s ;
57+ }
58+ if (content instanceof Multipart multipart ) {
59+ return extractFromMultipart (multipart );
60+ }
61+ return content .toString ();
62+ }
63+
64+ private String extractFromMultipart (Multipart multipart ) throws Exception {
65+ StringBuilder sb = new StringBuilder ();
66+ for (int i = 0 ; i < multipart .getCount (); i ++) {
67+ Object partContent = multipart .getBodyPart (i ).getContent ();
68+ if (partContent instanceof String s ) {
69+ sb .append (s );
70+ } else if (partContent instanceof Multipart nested ) {
71+ sb .append (extractFromMultipart (nested ));
72+ }
73+ }
74+ return sb .toString ();
4375 }
4476
4577 @ Test
@@ -75,7 +107,7 @@ void shouldSendHtmlEmail() throws Exception {
75107
76108 MimeMessage [] received = greenMail .getReceivedMessages ();
77109 assertThat (received ).hasSize (1 );
78- String content = received [0 ]. getContent (). toString ( );
110+ String content = extractTextContent ( received [0 ]);
79111 assertThat (content ).contains ("CodeCrow Report" );
80112 assertThat (content ).contains ("5 issues found" );
81113 }
@@ -150,7 +182,7 @@ void shouldSendBackupCodesEmail() throws Exception {
150182
151183 MimeMessage [] received = greenMail .getReceivedMessages ();
152184 assertThat (received ).hasSize (1 );
153- String content = received [0 ]. getContent (). toString ( );
185+ String content = extractTextContent ( received [0 ]);
154186 assertThat (content ).contains ("CODE-0001" , "CODE-0005" );
155187 }
156188}
0 commit comments