1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.mail2.jakarta;
18
19 import static org.junit.jupiter.api.Assertions.assertEquals;
20 import static org.junit.jupiter.api.Assertions.assertFalse;
21 import static org.junit.jupiter.api.Assertions.assertTrue;
22 import static org.junit.jupiter.api.Assertions.fail;
23
24 import java.io.BufferedOutputStream;
25 import java.io.ByteArrayOutputStream;
26 import java.io.File;
27 import java.io.IOException;
28 import java.net.URL;
29 import java.util.Date;
30 import java.util.Enumeration;
31 import java.util.List;
32
33 import org.apache.commons.mail2.jakarta.settings.EmailConfiguration;
34 import org.apache.commons.mail2.jakarta.util.MimeMessageUtils;
35 import org.junit.jupiter.api.AfterEach;
36 import org.junit.jupiter.api.BeforeEach;
37 import org.mockito.Mockito;
38 import org.subethamail.wiser.Wiser;
39 import org.subethamail.wiser.WiserMessage;
40
41 import jakarta.activation.DataHandler;
42 import jakarta.mail.Header;
43 import jakarta.mail.MessagingException;
44 import jakarta.mail.Multipart;
45 import jakarta.mail.internet.InternetAddress;
46 import jakarta.mail.internet.MimeMessage;
47
48
49
50
51 public abstract class AbstractEmailTest {
52
53 public static final int BODY_END_PAD = 3;
54
55
56 public static final int BODY_START_PAD = 2;
57
58
59 private static final String LINE_SEPARATOR = "\r\n";
60
61
62 private static int mailServerPort = 2500;
63
64
65 private static int fileNameCounter;
66
67
68 protected Wiser fakeMailServer;
69
70
71 protected String strTestMailServer = "localhost";
72
73
74 protected String strTestMailFrom = "test_from@apache.org";
75
76
77 protected String strTestMailTo = "test_to@apache.org";
78
79
80 protected String strTestUser = "user";
81
82
83 protected String strTestPasswd = "password";
84
85
86 protected String strTestURL = EmailConfiguration.TEST_URL;
87
88
89 protected String[] testCharsValid = { " ", "a", "A", "\uc5ec", "0123456789", "012345678901234567890" };
90
91
92 protected String[] endOfLineCombinations = { "\n", "\r", "\r\n", "\n\r", };
93
94
95 protected String[] testCharsNotValid = { "", null };
96
97
98 private File emailOutputDir;
99
100
101
102
103
104
105
106
107
108 @SuppressWarnings("resource")
109 protected URL createInvalidURL() throws Exception {
110 URL url = new URL("http://example.invalid");
111 url = Mockito.spy(url);
112 Mockito.doThrow(new IOException("Mocked IOException")).when(url).openStream();
113 return url;
114 }
115
116
117
118
119
120 public void getMailServer() {
121 if (fakeMailServer == null || isMailServerStopped(fakeMailServer)) {
122 mailServerPort++;
123
124 fakeMailServer = Wiser.port(getMailServerPort());
125 fakeMailServer.start();
126
127 assertFalse(isMailServerStopped(fakeMailServer), "fake mail server didn't start");
128
129 final Date dtStartWait = new Date();
130 while (isMailServerStopped(fakeMailServer)) {
131
132 if (fakeMailServer != null && !isMailServerStopped(fakeMailServer)) {
133 break;
134 }
135
136
137 if (dtStartWait.getTime() + EmailConfiguration.TIME_OUT <= new Date().getTime()) {
138 fail("Mail server failed to start");
139 }
140 }
141 }
142 }
143
144
145
146
147
148
149 protected int getMailServerPort() {
150 return mailServerPort;
151 }
152
153
154
155
156
157 public String getMessageAsString(final int intMsgNo) {
158 final List<?> receivedMessages = fakeMailServer.getMessages();
159 assertTrue(receivedMessages.size() >= intMsgNo, "mail server didn't get enough messages");
160
161 final WiserMessage emailMessage = (WiserMessage) receivedMessages.get(intMsgNo);
162
163 if (emailMessage != null) {
164 try {
165 return serializeEmailMessage(emailMessage);
166 } catch (final Exception e) {
167
168 }
169 }
170 fail("Message not found");
171 return "";
172 }
173
174
175
176
177
178
179
180
181 private String getMessageBody(final WiserMessage wiserMessage) throws IOException {
182 if (wiserMessage == null) {
183 return "";
184 }
185
186 byte[] messageBody = null;
187
188 try {
189 final MimeMessage message = wiserMessage.getMimeMessage();
190 messageBody = getMessageBodyBytes(message);
191 } catch (final MessagingException e) {
192
193
194 final IllegalStateException rethrow = new IllegalStateException("couldn't process MimeMessage from WiserMessage in getMessageBody()");
195 rethrow.initCause(e);
196 throw rethrow;
197 }
198
199 return messageBody != null ? new String(messageBody).intern() : "";
200 }
201
202
203
204
205
206
207
208
209
210 private byte[] getMessageBodyBytes(final MimeMessage mimeMessage) throws IOException, MessagingException {
211 final DataHandler dataHandler = mimeMessage.getDataHandler();
212 final ByteArrayOutputStream byteArrayOutStream = new ByteArrayOutputStream();
213 final BufferedOutputStream buffOs = new BufferedOutputStream(byteArrayOutStream);
214 dataHandler.writeTo(buffOs);
215 buffOs.flush();
216
217 return byteArrayOutStream.toByteArray();
218 }
219
220
221
222
223
224
225
226 protected boolean isMailServerStopped(final Wiser fakeMailServer) {
227 return !fakeMailServer.getServer().isRunning();
228 }
229
230
231
232
233
234
235
236
237 protected void saveEmailToFile(final WiserMessage email) throws IOException, MessagingException {
238 final int currCounter = fileNameCounter++ % 10;
239 final String emailFileName = "email" + new Date().getTime() + "-" + currCounter + ".eml";
240 final File emailFile = new File(emailOutputDir, emailFileName);
241 MimeMessageUtils.writeMimeMessage(email.getMimeMessage(), emailFile);
242 }
243
244
245
246
247
248
249
250
251
252
253 private String serializeEmailMessage(final WiserMessage wiserMessage) throws MessagingException, IOException {
254 if (wiserMessage == null) {
255 return "";
256 }
257
258 final StringBuilder serializedEmail = new StringBuilder();
259 final MimeMessage message = wiserMessage.getMimeMessage();
260
261
262 for (final Enumeration<?> headers = message.getAllHeaders(); headers.hasMoreElements();) {
263 final Header header = (Header) headers.nextElement();
264 serializedEmail.append(header.getName());
265 serializedEmail.append(": ");
266 serializedEmail.append(header.getValue());
267 serializedEmail.append(LINE_SEPARATOR);
268 }
269
270
271 final byte[] messageBody = getMessageBodyBytes(message);
272
273 serializedEmail.append(LINE_SEPARATOR);
274 serializedEmail.append(messageBody);
275 serializedEmail.append(LINE_SEPARATOR);
276
277 return serializedEmail.toString();
278 }
279
280 @BeforeEach
281 public void setUpAbstractEmailTest() {
282 emailOutputDir = new File("target/test-emails");
283 if (!emailOutputDir.exists()) {
284 emailOutputDir.mkdirs();
285 }
286 }
287
288 protected void stopServer() {
289 if (fakeMailServer != null) {
290 fakeMailServer.stop();
291 }
292 }
293
294 @AfterEach
295 public void tearDownEmailTest() {
296
297 if (fakeMailServer != null && !isMailServerStopped(fakeMailServer)) {
298 fakeMailServer.stop();
299 assertTrue(isMailServerStopped(fakeMailServer), "Mail server didn't stop");
300 }
301
302 fakeMailServer = null;
303 }
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318 protected WiserMessage validateSend(final Wiser mailServer, final String strSubject, final InternetAddress fromAdd, final List<InternetAddress> toAdd,
319 final List<InternetAddress> ccAdd, final List<InternetAddress> bccAdd, final boolean boolSaveToFile) throws IOException {
320 assertTrue(mailServer.getMessages().size() == 1, "mail server doesn't contain expected message");
321 final WiserMessage emailMessage = mailServer.getMessages().get(0);
322
323 if (boolSaveToFile) {
324 try {
325 saveEmailToFile(emailMessage);
326 } catch (final MessagingException e) {
327 final IllegalStateException rethrow = new IllegalStateException("caught MessagingException during saving the email");
328 rethrow.initCause(e);
329 throw rethrow;
330 }
331 }
332
333 try {
334
335 final MimeMessage mimeMessage = emailMessage.getMimeMessage();
336
337
338 assertEquals(strSubject, mimeMessage.getHeader("Subject", null), "got wrong subject from mail");
339
340
341 assertEquals(fromAdd.toString(), mimeMessage.getHeader("From", null), "got wrong From: address from mail");
342
343
344 assertTrue(toAdd.toString().contains(mimeMessage.getHeader("To", null)), "got wrong To: address from mail");
345
346
347 if (!ccAdd.isEmpty()) {
348 assertTrue(ccAdd.toString().contains(mimeMessage.getHeader("Cc", null)), "got wrong Cc: address from mail");
349 }
350
351
352 if (!bccAdd.isEmpty()) {
353 assertTrue(bccAdd.toString().contains(mimeMessage.getHeader("Bcc", null)), "got wrong Bcc: address from mail");
354 }
355 } catch (final MessagingException e) {
356 final IllegalStateException rethrow = new IllegalStateException("caught MessagingException in validateSend()");
357 rethrow.initCause(e);
358 throw rethrow;
359 }
360
361 return emailMessage;
362 }
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377 protected void validateSend(final Wiser mailServer, final String strSubject, final Multipart content, final InternetAddress fromAdd,
378 final List<InternetAddress> toAdd, final List<InternetAddress> ccAdd, final List<InternetAddress> bccAdd, final boolean boolSaveToFile)
379 throws IOException {
380
381 final WiserMessage emailMessage = validateSend(mailServer, strSubject, fromAdd, toAdd, ccAdd, bccAdd, boolSaveToFile);
382
383
384
385
386 final String strSentContent = content.getContentType();
387
388
389 final String emailMessageBody = getMessageBody(emailMessage);
390 final String strMessageBody = emailMessageBody.substring(AbstractEmailTest.BODY_START_PAD, emailMessageBody.length() - AbstractEmailTest.BODY_END_PAD);
391 assertTrue(strMessageBody.contains(strSentContent), "didn't find expected content type in message body");
392 }
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407 protected void validateSend(final Wiser mailServer, final String strSubject, final String strMessage, final InternetAddress fromAdd,
408 final List<InternetAddress> toAdd, final List<InternetAddress> ccAdd, final List<InternetAddress> bccAdd, final boolean boolSaveToFile)
409 throws IOException {
410
411 final WiserMessage emailMessage = validateSend(mailServer, strSubject, fromAdd, toAdd, ccAdd, bccAdd, true);
412
413
414 assertTrue(getMessageBody(emailMessage).contains(strMessage), "didn't find expected message content in message body");
415 }
416 }