001
014
015 package com.liferay.util.mail;
016
017 import com.liferay.mail.model.FileAttachment;
018 import com.liferay.mail.service.MailServiceUtil;
019 import com.liferay.portal.kernel.exception.SystemException;
020 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.log.LogUtil;
024 import com.liferay.portal.kernel.mail.Account;
025 import com.liferay.portal.kernel.mail.MailMessage;
026 import com.liferay.portal.kernel.mail.SMTPAccount;
027 import com.liferay.portal.kernel.util.GetterUtil;
028 import com.liferay.portal.kernel.util.InfrastructureUtil;
029 import com.liferay.portal.kernel.util.Validator;
030
031 import java.io.File;
032
033 import java.net.SocketException;
034
035 import java.util.Arrays;
036 import java.util.Date;
037 import java.util.List;
038 import java.util.Properties;
039
040 import javax.activation.DataHandler;
041 import javax.activation.DataSource;
042 import javax.activation.FileDataSource;
043
044 import javax.mail.Message;
045 import javax.mail.MessagingException;
046 import javax.mail.Part;
047 import javax.mail.SendFailedException;
048 import javax.mail.Session;
049 import javax.mail.Transport;
050 import javax.mail.internet.AddressException;
051 import javax.mail.internet.InternetAddress;
052 import javax.mail.internet.MimeBodyPart;
053 import javax.mail.internet.MimeMessage;
054 import javax.mail.internet.MimeMultipart;
055
056 import org.apache.commons.lang.time.StopWatch;
057
058
066 public class MailEngine {
067
068 public static Session getSession() {
069 return getSession(false);
070 }
071
072 public static Session getSession(Account account) {
073 Properties properties = _getProperties(account);
074
075 Session session = Session.getInstance(properties);
076
077 if (_log.isDebugEnabled()) {
078 session.setDebug(true);
079
080 session.getProperties().list(System.out);
081 }
082
083 return session;
084 }
085
086 public static Session getSession(boolean cache) {
087 Session session = null;
088
089 try {
090 session = MailServiceUtil.getSession();
091 }
092 catch (SystemException se) {
093 if (_log.isWarnEnabled()) {
094 _log.warn(se, se);
095 }
096
097 session = InfrastructureUtil.getMailSession();
098 }
099
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(byte[] bytes) throws MailEngineException {
110 try {
111 Session session = getSession();
112
113 Message message = new MimeMessage(
114 session, new UnsyncByteArrayInputStream(bytes));
115
116 _send(session, message, null);
117 }
118 catch (Exception e) {
119 throw new MailEngineException(e);
120 }
121 }
122
123 public static void send(
124 InternetAddress from, InternetAddress to, String subject,
125 String body)
126 throws MailEngineException {
127
128 send(
129 from, new InternetAddress[] {to}, null, null, subject, body, false,
130 null, null, null);
131 }
132
133 public static void send(
134 InternetAddress from, InternetAddress to, String subject,
135 String body, boolean htmlFormat)
136 throws MailEngineException {
137
138 send(
139 from, new InternetAddress[] {to}, null, null, subject, body,
140 htmlFormat, null, null, null);
141 }
142
143 public static void send(
144 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
145 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
146 String subject, String body, boolean htmlFormat,
147 InternetAddress[] replyTo, String messageId, String inReplyTo)
148 throws MailEngineException {
149
150 send(
151 from, to, cc, bcc, bulkAddresses, subject, body, htmlFormat,
152 replyTo, messageId, inReplyTo, null);
153 }
154
155 public static void send(
156 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
157 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
158 String subject, String body, boolean htmlFormat,
159 InternetAddress[] replyTo, String messageId, String inReplyTo,
160 List<FileAttachment> fileAttachments)
161 throws MailEngineException {
162
163 send(
164 from, to, cc, bcc, bulkAddresses, subject, body, htmlFormat,
165 replyTo, messageId, inReplyTo, fileAttachments, null);
166 }
167
168 public static void send(
169 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
170 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
171 String subject, String body, boolean htmlFormat,
172 InternetAddress[] replyTo, String messageId, String inReplyTo,
173 List<FileAttachment> fileAttachments, SMTPAccount smtpAccount)
174 throws MailEngineException {
175
176 StopWatch stopWatch = null;
177
178 if (_log.isDebugEnabled()) {
179 stopWatch = new StopWatch();
180
181 stopWatch.start();
182
183 _log.debug("From: " + from);
184 _log.debug("To: " + Arrays.toString(to));
185 _log.debug("CC: " + Arrays.toString(cc));
186 _log.debug("BCC: " + Arrays.toString(bcc));
187 _log.debug("List Addresses: " + Arrays.toString(bulkAddresses));
188 _log.debug("Subject: " + subject);
189 _log.debug("Body: " + body);
190 _log.debug("HTML Format: " + htmlFormat);
191 _log.debug("Reply to: " + Arrays.toString(replyTo));
192 _log.debug("Message ID: " + messageId);
193 _log.debug("In Reply To: " + inReplyTo);
194
195 if ((fileAttachments != null) && _log.isDebugEnabled()) {
196 for (int i = 0; i < fileAttachments.size(); i++) {
197 FileAttachment fileAttachment = fileAttachments.get(i);
198
199 File file = fileAttachment.getFile();
200
201 if (file == null) {
202 continue;
203 }
204
205 _log.debug(
206 "Attachment " + i + " file " + file.getAbsolutePath() +
207 " and file name " + fileAttachment.getFileName());
208 }
209 }
210 }
211
212 try {
213 Session session = null;
214
215 if (smtpAccount == null) {
216 session = getSession();
217 }
218 else {
219 session = getSession(smtpAccount);
220 }
221
222 Message message = new LiferayMimeMessage(session);
223
224 message.setFrom(from);
225 message.setRecipients(Message.RecipientType.TO, to);
226
227 if (cc != null) {
228 message.setRecipients(Message.RecipientType.CC, cc);
229 }
230
231 if (bcc != null) {
232 message.setRecipients(Message.RecipientType.BCC, bcc);
233 }
234
235 subject = GetterUtil.getString(subject);
236
237 message.setSubject(subject);
238
239 if ((fileAttachments != null) && (fileAttachments.size() > 0)) {
240 MimeMultipart rootMultipart = new MimeMultipart(
241 _MULTIPART_TYPE_MIXED);
242
243 MimeMultipart messageMultipart = new MimeMultipart(
244 _MULTIPART_TYPE_ALTERNATIVE);
245
246 MimeBodyPart messageBodyPart = new MimeBodyPart();
247
248 messageBodyPart.setContent(messageMultipart);
249
250 rootMultipart.addBodyPart(messageBodyPart);
251
252 if (htmlFormat) {
253 MimeBodyPart bodyPart = new MimeBodyPart();
254
255 bodyPart.setContent(body, _TEXT_HTML);
256
257 messageMultipart.addBodyPart(bodyPart);
258 }
259 else {
260 MimeBodyPart bodyPart = new MimeBodyPart();
261
262 bodyPart.setText(body);
263
264 messageMultipart.addBodyPart(bodyPart);
265 }
266
267 for (int i = 0; i < fileAttachments.size(); i++) {
268 FileAttachment fileAttachment = fileAttachments.get(i);
269
270 File file = fileAttachment.getFile();
271
272 if (file == null) {
273 continue;
274 }
275
276 MimeBodyPart mimeBodyPart = new MimeBodyPart();
277
278 DataSource dataSource = new FileDataSource(file);
279
280 mimeBodyPart.setDataHandler(new DataHandler(dataSource));
281 mimeBodyPart.setDisposition(Part.ATTACHMENT);
282
283 if (fileAttachment.getFileName() != null) {
284 mimeBodyPart.setFileName(fileAttachment.getFileName());
285 }
286 else {
287 mimeBodyPart.setFileName(file.getName());
288 }
289
290 rootMultipart.addBodyPart(mimeBodyPart);
291 }
292
293 message.setContent(rootMultipart);
294
295 message.saveChanges();
296 }
297 else {
298 if (htmlFormat) {
299 message.setContent(body, _TEXT_HTML);
300 }
301 else {
302 message.setContent(body, _TEXT_PLAIN);
303 }
304 }
305
306 message.setSentDate(new Date());
307
308 if (replyTo != null) {
309 message.setReplyTo(replyTo);
310 }
311
312 if (messageId != null) {
313 message.setHeader("Message-ID", messageId);
314 }
315
316 if (inReplyTo != null) {
317 message.setHeader("In-Reply-To", inReplyTo);
318 message.setHeader("References", inReplyTo);
319 }
320
321 _send(session, message, bulkAddresses);
322 }
323 catch (SendFailedException sfe) {
324 _log.error(sfe);
325 }
326 catch (Exception e) {
327 throw new MailEngineException(e);
328 }
329
330 if (_log.isDebugEnabled()) {
331 _log.debug("Sending mail takes " + stopWatch.getTime() + " ms");
332 }
333 }
334
335 public static void send(
336 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
337 InternetAddress[] bcc, String subject, String body)
338 throws MailEngineException {
339
340 send(from, to, cc, bcc, subject, body, false, null, null, null);
341 }
342
343 public static void send(
344 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
345 InternetAddress[] bcc, String subject, String body,
346 boolean htmlFormat, InternetAddress[] replyTo, String messageId,
347 String inReplyTo)
348 throws MailEngineException {
349
350 send(
351 from, to, cc, bcc, null, subject, body, htmlFormat, replyTo,
352 messageId, inReplyTo, null);
353 }
354
355 public static void send(
356 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
357 String subject, String body)
358 throws MailEngineException {
359
360 send(from, to, cc, null, subject, body, false, null, null, null);
361 }
362
363 public static void send(
364 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
365 String subject, String body, boolean htmlFormat)
366 throws MailEngineException {
367
368 send(from, to, cc, null, subject, body, htmlFormat, null, null, null);
369 }
370
371 public static void send(
372 InternetAddress from, InternetAddress[] to, String subject,
373 String body)
374 throws MailEngineException {
375
376 send(from, to, null, null, subject, body, false, null, null, null);
377 }
378
379 public static void send(
380 InternetAddress from, InternetAddress[] to, String subject,
381 String body, boolean htmlFormat)
382 throws MailEngineException {
383
384 send(from, to, null, null, subject, body, htmlFormat, null, null, null);
385 }
386
387 public static void send(MailMessage mailMessage)
388 throws MailEngineException {
389
390 send(
391 mailMessage.getFrom(), mailMessage.getTo(), mailMessage.getCC(),
392 mailMessage.getBCC(), mailMessage.getBulkAddresses(),
393 mailMessage.getSubject(), mailMessage.getBody(),
394 mailMessage.isHTMLFormat(), mailMessage.getReplyTo(),
395 mailMessage.getMessageId(), mailMessage.getInReplyTo(),
396 mailMessage.getFileAttachments(), mailMessage.getSMTPAccount());
397 }
398
399 public static void send(String from, String to, String subject, String body)
400 throws MailEngineException {
401
402 try {
403 send(
404 new InternetAddress(from), new InternetAddress(to), subject,
405 body);
406 }
407 catch (AddressException ae) {
408 throw new MailEngineException(ae);
409 }
410 }
411
412 private static Properties _getProperties(Account account) {
413 Properties properties = new Properties();
414
415 String protocol = account.getProtocol();
416
417 properties.setProperty("mail.transport.protocol", protocol);
418 properties.setProperty("mail." + protocol + ".host", account.getHost());
419 properties.setProperty(
420 "mail." + protocol + ".port", String.valueOf(account.getPort()));
421
422 if (account.isRequiresAuthentication()) {
423 properties.setProperty("mail." + protocol + ".auth", "true");
424 properties.setProperty(
425 "mail." + protocol + ".user", account.getUser());
426 properties.setProperty(
427 "mail." + protocol + ".password", account.getPassword());
428 }
429
430 if (account.isSecure()) {
431 properties.setProperty(
432 "mail." + protocol + ".socketFactory.class",
433 "javax.net.ssl.SSLSocketFactory");
434 properties.setProperty(
435 "mail." + protocol + ".socketFactory.fallback", "false");
436 properties.setProperty(
437 "mail." + protocol + ".socketFactory.port",
438 String.valueOf(account.getPort()));
439 }
440
441 return properties;
442 }
443
444 private static String _getSMTPProperty(Session session, String suffix) {
445 String protocol = GetterUtil.getString(
446 session.getProperty("mail.transport.protocol"));
447
448 if (protocol.equals(Account.PROTOCOL_SMTPS)) {
449 return session.getProperty("mail.smtps." + suffix);
450 }
451 else {
452 return session.getProperty("mail.smtp." + suffix);
453 }
454 }
455
456 private static void _send(
457 Session session, Message message, InternetAddress[] bulkAddresses) {
458
459 try {
460 boolean smtpAuth = GetterUtil.getBoolean(
461 _getSMTPProperty(session, "auth"), false);
462 String smtpHost = _getSMTPProperty(session, "host");
463 int smtpPort = GetterUtil.getInteger(
464 _getSMTPProperty(session, "port"), Account.PORT_SMTP);
465 String user = _getSMTPProperty(session, "user");
466 String password = _getSMTPProperty(session, "password");
467
468 if (smtpAuth && Validator.isNotNull(user) &&
469 Validator.isNotNull(password)) {
470
471 String protocol = GetterUtil.getString(
472 session.getProperty("mail.transport.protocol"),
473 Account.PROTOCOL_SMTP);
474
475 Transport transport = session.getTransport(protocol);
476
477 transport.connect(smtpHost, smtpPort, user, password);
478
479 if ((bulkAddresses != null) && (bulkAddresses.length > 0)) {
480 transport.sendMessage(message, bulkAddresses);
481 }
482 else {
483 transport.sendMessage(message, message.getAllRecipients());
484 }
485
486 transport.close();
487 }
488 else {
489 if ((bulkAddresses != null) && (bulkAddresses.length > 0)) {
490 Transport.send(message, bulkAddresses);
491 }
492 else {
493 Transport.send(message);
494 }
495 }
496 }
497 catch (MessagingException me) {
498 if (me.getNextException() instanceof SocketException) {
499 if (_log.isWarnEnabled()) {
500 _log.warn(
501 "Failed to connect to a valid mail server. Please " +
502 "make sure one is properly configured. " +
503 me.getMessage());
504 }
505 }
506 else {
507 _log.error(me.getMessage());
508
509 LogUtil.log(_log, me);
510 }
511 }
512 }
513
514 private static final String _MULTIPART_TYPE_ALTERNATIVE = "alternative";
515
516 private static final String _MULTIPART_TYPE_MIXED = "mixed";
517
518 private static final String _TEXT_HTML = "text/html;charset=\"UTF-8\"";
519
520 private static final String _TEXT_PLAIN = "text/plain;charset=\"UTF-8\"";
521
522 private static Log _log = LogFactoryUtil.getLog(MailEngine.class);
523
524 }