1
14
15 package com.liferay.util.mail;
16
17 import com.liferay.mail.service.MailServiceUtil;
18 import com.liferay.portal.SystemException;
19 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
20 import com.liferay.portal.kernel.log.Log;
21 import com.liferay.portal.kernel.log.LogFactoryUtil;
22 import com.liferay.portal.kernel.log.LogUtil;
23 import com.liferay.portal.kernel.mail.Account;
24 import com.liferay.portal.kernel.mail.MailMessage;
25 import com.liferay.portal.kernel.mail.SMTPAccount;
26 import com.liferay.portal.kernel.util.GetterUtil;
27 import com.liferay.portal.kernel.util.InfrastructureUtil;
28 import com.liferay.portal.kernel.util.Validator;
29
30 import java.io.File;
31
32 import java.net.SocketException;
33
34 import java.util.Arrays;
35 import java.util.Date;
36 import java.util.Properties;
37
38 import javax.activation.DataHandler;
39 import javax.activation.DataSource;
40 import javax.activation.FileDataSource;
41
42 import javax.mail.Message;
43 import javax.mail.MessagingException;
44 import javax.mail.Part;
45 import javax.mail.SendFailedException;
46 import javax.mail.Session;
47 import javax.mail.Transport;
48 import javax.mail.internet.AddressException;
49 import javax.mail.internet.InternetAddress;
50 import javax.mail.internet.MimeBodyPart;
51 import javax.mail.internet.MimeMessage;
52 import javax.mail.internet.MimeMultipart;
53
54 import org.apache.commons.lang.time.StopWatch;
55
56
66 public class MailEngine {
67
68 public static Session getSession() {
69 return getSession(false);
70 }
71
72 public static Session getSession(boolean cache) {
73 Session session = null;
74
75 try {
76 session = MailServiceUtil.getSession();
77 }
78 catch (SystemException se) {
79 if (_log.isWarnEnabled()) {
80 _log.warn(se, se);
81 }
82
83 session = InfrastructureUtil.getMailSession();
84 }
85
86 if (_log.isDebugEnabled()) {
87 session.setDebug(true);
88
89 session.getProperties().list(System.out);
90 }
91
92 return session;
93 }
94
95 public static Session getSession(Account account) {
96 Properties properties = _getProperties(account);
97
98 Session session = Session.getInstance(properties);
99
100 if (_log.isDebugEnabled()) {
101 session.setDebug(true);
102
103 session.getProperties().list(System.out);
104 }
105
106 return session;
107 }
108
109 public static void send(MailMessage mailMessage)
110 throws MailEngineException {
111
112 send(
113 mailMessage.getFrom(), mailMessage.getTo(), mailMessage.getCC(),
114 mailMessage.getBCC(), mailMessage.getBulkAddresses(),
115 mailMessage.getSubject(), mailMessage.getBody(),
116 mailMessage.isHTMLFormat(), mailMessage.getReplyTo(),
117 mailMessage.getMessageId(), mailMessage.getInReplyTo(),
118 mailMessage.getAttachments(), mailMessage.getSMTPAccount());
119 }
120
121 public static void send(String from, String to, String subject, String body)
122 throws MailEngineException {
123
124 try {
125 send(
126 new InternetAddress(from), new InternetAddress(to), subject,
127 body);
128 }
129 catch (AddressException ae) {
130 throw new MailEngineException(ae);
131 }
132 }
133
134 public static void send(
135 InternetAddress from, InternetAddress to,
136 String subject, String body)
137 throws MailEngineException {
138
139 send(
140 from, new InternetAddress[] {to}, null, null, subject, body, false,
141 null, null, null);
142 }
143
144 public static void send(
145 InternetAddress from, InternetAddress to, String subject,
146 String body, boolean htmlFormat)
147 throws MailEngineException {
148
149 send(
150 from, new InternetAddress[] {to}, null, null, subject, body,
151 htmlFormat, null, null, null);
152 }
153
154 public static void send(
155 InternetAddress from, InternetAddress[] to, String subject,
156 String body)
157 throws MailEngineException {
158
159 send(from, to, null, null, subject, body, false, null, null, null);
160 }
161
162 public static void send(
163 InternetAddress from, InternetAddress[] to, String subject,
164 String body, boolean htmlFormat)
165 throws MailEngineException {
166
167 send(from, to, null, null, subject, body, htmlFormat, null, null, null);
168 }
169
170 public static void send(
171 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
172 String subject, String body)
173 throws MailEngineException {
174
175 send(from, to, cc, null, subject, body, false, null, null, null);
176 }
177
178 public static void send(
179 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
180 String subject, String body, boolean htmlFormat)
181 throws MailEngineException {
182
183 send(from, to, cc, null, subject, body, htmlFormat, null, null, null);
184 }
185
186 public static void send(
187 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
188 InternetAddress[] bcc, String subject, String body)
189 throws MailEngineException {
190
191 send(from, to, cc, bcc, subject, body, false, null, null, null);
192 }
193
194 public static void send(
195 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
196 InternetAddress[] bcc, String subject, String body,
197 boolean htmlFormat, InternetAddress[] replyTo, String messageId,
198 String inReplyTo)
199 throws MailEngineException {
200
201 send(
202 from, to, cc, bcc, null, subject, body, htmlFormat, replyTo,
203 messageId, inReplyTo, null);
204 }
205
206 public static void send(
207 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
208 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
209 String subject, String body, boolean htmlFormat,
210 InternetAddress[] replyTo, String messageId, String inReplyTo)
211 throws MailEngineException {
212
213 send(
214 from, to, cc, bcc, bulkAddresses, subject, body, htmlFormat,
215 replyTo, messageId, inReplyTo, null);
216 }
217
218 public static void send(
219 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
220 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
221 String subject, String body, boolean htmlFormat,
222 InternetAddress[] replyTo, String messageId, String inReplyTo,
223 File[] attachments)
224 throws MailEngineException {
225
226 send(
227 from, to, cc, bcc, bulkAddresses, subject, body, htmlFormat,
228 replyTo, messageId, inReplyTo, attachments, null);
229 }
230
231 public static void send(
232 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
233 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
234 String subject, String body, boolean htmlFormat,
235 InternetAddress[] replyTo, String messageId, String inReplyTo,
236 File[] attachments, SMTPAccount smtpAccount)
237 throws MailEngineException {
238
239 StopWatch stopWatch = null;
240
241 if (_log.isDebugEnabled()) {
242 stopWatch = new StopWatch();
243
244 stopWatch.start();
245
246 _log.debug("From: " + from);
247 _log.debug("To: " + Arrays.toString(to));
248 _log.debug("CC: " + Arrays.toString(cc));
249 _log.debug("BCC: " + Arrays.toString(bcc));
250 _log.debug("List Addresses: " + Arrays.toString(bulkAddresses));
251 _log.debug("Subject: " + subject);
252 _log.debug("Body: " + body);
253 _log.debug("HTML Format: " + htmlFormat);
254 _log.debug("Reply to: " + Arrays.toString(replyTo));
255 _log.debug("Message ID: " + messageId);
256 _log.debug("In Reply To: " + inReplyTo);
257
258 if (attachments != null) {
259 for (int i = 0; i < attachments.length; i++) {
260 File attachment = attachments[i];
261
262 if (attachment != null) {
263 String path = attachment.getAbsolutePath();
264
265 _log.debug("Attachment #" + (i + 1) + ": " + path);
266 }
267 }
268 }
269 }
270
271 try {
272 Session session = null;
273
274 if (smtpAccount == null) {
275 session = getSession();
276 }
277 else {
278 session = getSession(smtpAccount);
279 }
280
281 Message msg = new LiferayMimeMessage(session);
282
283 msg.setFrom(from);
284 msg.setRecipients(Message.RecipientType.TO, to);
285
286 if (cc != null) {
287 msg.setRecipients(Message.RecipientType.CC, cc);
288 }
289
290 if (bcc != null) {
291 msg.setRecipients(Message.RecipientType.BCC, bcc);
292 }
293
294 msg.setSubject(subject);
295
296 if ((attachments != null) && (attachments.length > 0)) {
297 MimeMultipart rootMultipart = new MimeMultipart(
298 _MULTIPART_TYPE_MIXED);
299
300 MimeMultipart messageMultipart = new MimeMultipart(
301 _MULTIPART_TYPE_ALTERNATIVE);
302
303 MimeBodyPart messageBodyPart = new MimeBodyPart();
304
305 messageBodyPart.setContent(messageMultipart);
306
307 rootMultipart.addBodyPart(messageBodyPart);
308
309 if (htmlFormat) {
310 MimeBodyPart bodyPart = new MimeBodyPart();
311
312 bodyPart.setContent(body, _TEXT_HTML);
313
314 messageMultipart.addBodyPart(bodyPart);
315 }
316 else {
317 MimeBodyPart bodyPart = new MimeBodyPart();
318
319 bodyPart.setText(body);
320
321 messageMultipart.addBodyPart(bodyPart);
322 }
323
324 for (int i = 0; i < attachments.length; i++) {
325 File attachment = attachments[i];
326
327 if (attachment != null) {
328 MimeBodyPart bodyPart = new MimeBodyPart();
329
330 DataSource source = new FileDataSource(attachment);
331
332 bodyPart.setDisposition(Part.ATTACHMENT);
333 bodyPart.setDataHandler(new DataHandler(source));
334 bodyPart.setFileName(attachment.getName());
335
336 rootMultipart.addBodyPart(bodyPart);
337 }
338 }
339
340 msg.setContent(rootMultipart);
341
342 msg.saveChanges();
343 }
344 else {
345 if (htmlFormat) {
346 msg.setContent(body, _TEXT_HTML);
347 }
348 else {
349 msg.setContent(body, _TEXT_PLAIN);
350 }
351 }
352
353 msg.setSentDate(new Date());
354
355 if (replyTo != null) {
356 msg.setReplyTo(replyTo);
357 }
358
359 if (messageId != null) {
360 msg.setHeader("Message-ID", messageId);
361 }
362
363 if (inReplyTo != null) {
364 msg.setHeader("In-Reply-To", inReplyTo);
365 msg.setHeader("References", inReplyTo);
366 }
367
368 _send(session, msg, bulkAddresses);
369 }
370 catch (SendFailedException sfe) {
371 _log.error(sfe);
372 }
373 catch (Exception e) {
374 throw new MailEngineException(e);
375 }
376
377 if (_log.isDebugEnabled()) {
378 _log.debug("Sending mail takes " + stopWatch.getTime() + " ms");
379 }
380 }
381
382 public static void send(byte[] msgByteArray) throws MailEngineException {
383 try {
384 Session session = getSession();
385
386 Message msg = new MimeMessage(
387 session, new UnsyncByteArrayInputStream(msgByteArray));
388
389 _send(session, msg, null);
390 }
391 catch (Exception e) {
392 throw new MailEngineException(e);
393 }
394 }
395
396 private static Properties _getProperties(Account account) {
397 Properties properties = new Properties();
398
399 String protocol = account.getProtocol();
400
401 properties.setProperty("mail.transport.protocol", protocol);
402 properties.setProperty("mail." + protocol + ".host", account.getHost());
403 properties.setProperty(
404 "mail." + protocol + ".port", String.valueOf(account.getPort()));
405
406 if (account.isRequiresAuthentication()) {
407 properties.setProperty("mail." + protocol + ".auth", "true");
408 properties.setProperty(
409 "mail." + protocol + ".user", account.getUser());
410 properties.setProperty(
411 "mail." + protocol + ".password", account.getPassword());
412 }
413
414 if (account.isSecure()) {
415 properties.setProperty(
416 "mail." + protocol + ".socketFactory.class",
417 "javax.net.ssl.SSLSocketFactory");
418 properties.setProperty(
419 "mail." + protocol + ".socketFactory.fallback", "false");
420 properties.setProperty(
421 "mail." + protocol + ".socketFactory.port",
422 String.valueOf(account.getPort()));
423 }
424
425 return properties;
426 }
427
428 private static String _getSMTPProperty(Session session, String suffix) {
429 String protocol = GetterUtil.getString(
430 session.getProperty("mail.transport.protocol"));
431
432 if (protocol.equals(Account.PROTOCOL_SMTPS)) {
433 return session.getProperty("mail.smtps." + suffix);
434 }
435 else {
436 return session.getProperty("mail.smtp." + suffix);
437 }
438 }
439
440 private static void _send(
441 Session session, Message msg, InternetAddress[] bulkAddresses) {
442
443 try {
444 boolean smtpAuth = GetterUtil.getBoolean(
445 _getSMTPProperty(session, "auth"), false);
446 String smtpHost = _getSMTPProperty(session, "host");
447 int smtpPort = GetterUtil.getInteger(
448 _getSMTPProperty(session, "port"), Account.PORT_SMTP);
449 String user = _getSMTPProperty(session, "user");
450 String password = _getSMTPProperty(session, "password");
451
452 if (smtpAuth && Validator.isNotNull(user) &&
453 Validator.isNotNull(password)) {
454
455 String protocol = GetterUtil.getString(
456 session.getProperty("mail.transport.protocol"),
457 Account.PROTOCOL_SMTP);
458
459 Transport transport = session.getTransport(protocol);
460
461 transport.connect(smtpHost, smtpPort, user, password);
462
463 if ((bulkAddresses != null) && (bulkAddresses.length > 0)) {
464 transport.sendMessage(msg, bulkAddresses);
465 }
466 else {
467 transport.sendMessage(msg, msg.getAllRecipients());
468 }
469
470 transport.close();
471 }
472 else {
473 if ((bulkAddresses != null) && (bulkAddresses.length > 0)) {
474 Transport.send(msg, bulkAddresses);
475 }
476 else {
477 Transport.send(msg);
478 }
479 }
480 }
481 catch (MessagingException me) {
482 if (me.getNextException() instanceof SocketException) {
483 if (_log.isWarnEnabled()) {
484 _log.warn(
485 "Failed to connect to a valid mail server. Please " +
486 "make sure one is properly configured. " +
487 me.getMessage());
488 }
489 }
490 else {
491 _log.error(me.getMessage());
492
493 LogUtil.log(_log, me);
494 }
495 }
496 }
497
498 private static final String _MULTIPART_TYPE_ALTERNATIVE = "alternative";
499
500 private static final String _MULTIPART_TYPE_MIXED = "mixed";
501
502 private static final String _TEXT_HTML = "text/html;charset=\"UTF-8\"";
503
504 private static final String _TEXT_PLAIN = "text/plain;charset=\"UTF-8\"";
505
506 private static Log _log = LogFactoryUtil.getLog(MailEngine.class);
507
508 }