1 package com.randomnoun.common.email;
2
3
4
5
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.util.ArrayList;
9 import java.util.Date;
10 import java.util.Iterator;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Properties;
14
15 import org.apache.log4j.Logger;
16
17 import com.randomnoun.common.StreamUtil;
18
19 import jakarta.activation.DataHandler;
20 import jakarta.activation.DataSource;
21 import jakarta.activation.FileDataSource;
22 import jakarta.mail.Message;
23 import jakarta.mail.MessagingException;
24 import jakarta.mail.Part;
25 import jakarta.mail.Session;
26 import jakarta.mail.Transport;
27 import jakarta.mail.internet.InternetAddress;
28 import jakarta.mail.internet.MimeBodyPart;
29 import jakarta.mail.internet.MimeMessage;
30 import jakarta.mail.internet.MimeMultipart;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class EmailWrapper {
50
51 public static Logger logger = Logger.getLogger(EmailWrapper.class);
52
53 private static boolean isBlank(String string) {
54 return (string==null || "".equals(string));
55 }
56
57
58
59
60
61
62
63
64
65
66
67 public static void emailToNoEx(String to, String from, String host, String subject,
68 String bodyText, String username, String password) {
69 try {
70 emailTo(to, from, host, subject, bodyText, username, password);
71 } catch (MessagingException me) {
72 logger.error("A messaging exception occurred whilst sending an email", me);
73 }
74 }
75
76
77
78
79
80
81
82
83
84
85
86
87
88 public static void emailTo(String to, String from, String host, String subject, String bodyText,
89 String username, String password)
90 throws MessagingException {
91 Properties props;
92
93 props = new Properties();
94 props.put("to", to);
95 props.put("from", from);
96 props.put("host", host);
97 props.put("subject", subject);
98 props.put("bodyText", bodyText);
99 if (username!=null) { props.put("username", username); }
100 if (password!=null) { props.put("password", password); }
101 emailAttachmentTo(props);
102 }
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117 public static void emailTo(String to, String from, String host, String subject, String bodyText,
118 String bodyHtml, String username, String password)
119 throws MessagingException {
120 Properties props;
121
122 props = new Properties();
123 props.put("to", to);
124 props.put("from", from);
125 props.put("host", host);
126 props.put("subject", subject);
127 props.put("bodyText", bodyText);
128 props.put("bodyHtml", bodyHtml);
129
130 if (username!=null) { props.put("username", username); }
131 if (password!=null) { props.put("password", password); }
132 emailAttachmentTo(props);
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 private static InternetAddress[] getAddressList(String stringList, String headerName, List<Map<String, Object>> headerList)
154 throws MessagingException {
155 String[] addresses;
156 List<InternetAddress> addressList = new ArrayList<>();
157 int i;
158
159
160 if (!isBlank(stringList)) {
161 addresses = stringList.split(",");
162
163 for (i = 0; i < addresses.length; i++) {
164 addressList.add(new InternetAddress(addresses[i]));
165 }
166 }
167
168
169 if (!isBlank(headerName) && (headerList != null)) {
170 for (Iterator<Map<String, Object>> j = headerList.iterator(); j.hasNext();) {
171 Map<String, Object> map = (Map<String, Object>) j.next();
172
173 if (headerName.equals(map.get("name"))) {
174 addresses = ((String) map.get("value")).split(",");
175
176 for (i = 0; i < addresses.length; i++) {
177 addressList.add(new InternetAddress(addresses[i]));
178 }
179 }
180 }
181 }
182
183 return (InternetAddress[]) addressList.toArray(new InternetAddress[] { });
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256 @SuppressWarnings("unchecked")
257 public static void emailAttachmentTo(Map<Object, Object> params)
258 throws MessagingException {
259 logger.debug("Inside emailAttachmentTo method with params");
260
261
262 String to = (String) params.get("to");
263 String from = (String) params.get("from");
264 String cc = (String) params.get("cc");
265 String bcc = (String) params.get("bcc");
266 String replyTo = (String) params.get("replyTo");
267 String bodyText = (String) params.get("bodyText");
268 String bodyHtml = (String) params.get("bodyHtml");
269 String subject = (String) params.get("subject");
270 String host = (String) params.get("host");
271 String username = (String) params.get("username");
272 String password = (String) params.get("password");
273 String client = (String) params.get("client");
274 String suffix = (String) params.get("suffix");
275
276 List<Map<String, Object>> attachFiles = (List<Map<String, Object>>) params.get("attachFiles");
277 List<Map<String, Object>> attachResources = (List<Map<String, Object>>) params.get("attachResources");
278 List<Map<String, Object>> attachData = (List<Map<String, Object>>) params.get("attachData");
279 List<Map<String, Object>> headers = (List<Map<String, Object>>) params.get("headers");
280 Map<String, Object> sessionProperties = (Map<String, Object>) params.get("sessionProperties");
281
282 boolean isMultipart = false;
283 boolean isAltContent = false;
284
285
286 if (isBlank(to)) { throw new IllegalArgumentException("Empty 'to' address"); }
287 if (isBlank(host)) { host = "127.0.0.1"; }
288
289
290 Properties props = new Properties();
291 props.put("mail.smtp.host", host);
292 if (username != null) { props.put("mail.smtp.user", username); }
293 if (sessionProperties != null) {
294 props.putAll(sessionProperties);
295 }
296
297 Session session = Session.getInstance(props, null);
298 Message msg;
299 if (isBlank(client) || isBlank(suffix)) {
300 msg = new MimeMessage(session);
301 } else {
302 msg = new CustomMimeMessage(session, client, suffix);
303 }
304
305 if (!isBlank(from)) {
306 msg.setFrom(new InternetAddress(from));
307 }
308 if (!isBlank(subject)) {
309 msg.setSubject(subject);
310 }
311
312 msg.setSentDate(new Date());
313
314 if (bodyHtml!=null && bodyText!=null) {
315 isMultipart = true;
316 isAltContent = true;
317 }
318
319
320 InternetAddress[] toArray = getAddressList(to, "to", headers);
321 if (toArray.length > 0) { msg.setRecipients(Message.RecipientType.TO, toArray); }
322
323 InternetAddress[] ccArray = getAddressList(cc, "cc", headers);
324 if (ccArray.length > 0) { msg.setRecipients(Message.RecipientType.CC, ccArray); }
325
326 InternetAddress[] bccArray = getAddressList(bcc, "bcc", headers);
327 if (bccArray.length > 0) { msg.setRecipients(Message.RecipientType.BCC, bccArray); }
328
329 InternetAddress[] replyToArray = getAddressList(replyTo, "replyTo", headers);
330 if (replyToArray.length > 0) { msg.setReplyTo(replyToArray); }
331
332
333 if (headers != null) {
334 for (Iterator<Map<String, Object>> i = headers.iterator(); i.hasNext();) {
335 Map<String, Object> map = i.next();
336 String headerName = (String) map.get("name");
337
338 if (headerName != null && !headerName.equals("to") && !headerName.equals("cc") && !headerName.equals("bcc")) {
339 msg.addHeader(headerName, (String) map.get("value"));
340 }
341 }
342 }
343
344
345 MimeMultipart multiPart;
346 if (isAltContent) {
347 multiPart = new MimeMultipart("alternative");
348 MimeBodyPart bodyPart = new MimeBodyPart();
349 bodyPart.setText(bodyText );
350 multiPart.addBodyPart(bodyPart);
351 bodyPart = new MimeBodyPart();
352 bodyPart.setText(bodyHtml, "us-ascii", "html" );
353 multiPart.addBodyPart(bodyPart);
354 } else {
355 multiPart = new MimeMultipart("mixed");
356 MimeBodyPart bodyPart = new MimeBodyPart();
357 if (bodyText!=null) {
358 bodyPart.setText(bodyText );
359 } else if (bodyHtml!=null) {
360 bodyPart.setText(bodyHtml, "us-ascii", "html");
361 }
362 multiPart.addBodyPart(bodyPart);
363 }
364
365
366 if (attachFiles != null) {
367 for (Iterator<Map<String, Object>> i = attachFiles.iterator(); i.hasNext();) {
368 Map<String, Object> map = i.next();
369 String filename = (String) map.get("filename");
370 String attachFilename = (String) map.get("attachFilename");
371 DataSource dataSource = new FileDataSource(filename);
372 MimeBodyPart attachment = new MimeBodyPart();
373
374 attachment.setDataHandler(new DataHandler(dataSource));
375 attachment.setFileName(attachFilename);
376 multiPart.addBodyPart(attachment);
377 isMultipart = true;
378 }
379 }
380
381
382 try {
383 if (attachResources != null) {
384 for (Iterator<Map<String, Object>> i = attachResources.iterator(); i.hasNext();) {
385 Map<String, Object> map = i.next();
386 String resource = (String) map.get("resource");
387 String attachFilename = (String) map.get("attachFilename");
388 Object classLoaderObject = (Object) map.get("classloader");
389 String contentType = (String) map.get("contentType");
390
391 if (isBlank(contentType)) {
392 contentType = "application/octet-stream";
393 }
394
395 ClassLoader classLoader;
396
397 if (classLoaderObject == null) {
398 classLoaderObject = EmailWrapper.class;
399 }
400
401 if (classLoaderObject instanceof Class) {
402 classLoader = ((Class<?>) classLoaderObject).getClassLoader();
403 } else if (classLoaderObject instanceof ClassLoader) {
404 classLoader = (ClassLoader) classLoaderObject;
405 } else {
406 classLoader = classLoaderObject.getClass().getClassLoader();
407 }
408
409 InputStream inputStream = classLoader.getResourceAsStream(resource);
410 byte[] attachmentData = StreamUtil.getByteArray(inputStream);
411 DataSource dataSource = new ByteArrayDataSource(attachmentData, attachFilename, contentType);
412 MimeBodyPart attachment = new MimeBodyPart();
413
414 attachment.setDataHandler(new DataHandler(dataSource));
415 attachment.setFileName(attachFilename);
416 multiPart.addBodyPart(attachment);
417 isMultipart = true;
418 }
419 }
420 } catch (IOException ioe) {
421 throw new MessagingException("Error reading resource", ioe);
422 }
423
424
425 if (attachData != null) {
426 for (Iterator<Map<String, Object>> i = attachData.iterator(); i.hasNext();) {
427 Map<String, Object> map = i.next();
428 String attachFilename = (String) map.get("attachFilename");
429 Object data = map.get("data");
430 String contentType = (String) map.get("contentType");
431 String contentId = (String) map.get("contentId");
432 String disposition = (String) map.get("disposition");
433 if (isBlank(contentType)) {
434 contentType = "application/octet-stream";
435 }
436
437
438 byte[] attachmentData;
439
440 if (data instanceof byte[]) {
441 attachmentData = (byte[]) data;
442 } else if (data instanceof String) {
443 attachmentData = ((String) data).getBytes();
444 } else {
445 attachmentData = data.toString().getBytes();
446 }
447
448 DataSource dataSource = new ByteArrayDataSource(attachmentData, attachFilename, contentType);
449 MimeBodyPart attachment = new MimeBodyPart();
450
451 attachment.setDataHandler(new DataHandler(dataSource));
452 attachment.setFileName(attachFilename);
453 multiPart.addBodyPart(attachment);
454 if (contentId!=null) {
455 attachment.addHeader("Content-ID", contentId);
456 }
457 if ("inline".equals(disposition)) {
458 attachment.setDisposition(Part.INLINE);
459 } else {
460 attachment.setDisposition(Part.ATTACHMENT);
461 }
462
463
464 isMultipart = true;
465 }
466 }
467
468
469 if (isMultipart) {
470
471 msg.setContent(multiPart);
472 } else {
473 if (bodyText!=null) {
474 msg.setText(bodyText);
475 } else if (bodyHtml!=null) {
476 throw new UnsupportedOperationException("HTML text supplied without plain text. Test this before using.");
477 }
478 }
479
480 Transport tr = session.getTransport("smtp");
481 if (username!=null && password!=null) {
482 tr.connect(host, username, password);
483 } else {
484 tr.connect();
485 }
486 msg.saveChanges();
487 tr.sendMessage(msg, msg.getAllRecipients());
488 tr.close();
489 }
490 }