1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   *
12   *
13   */
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  /**
57   * <a href="MailEngine.java.html"><b><i>View Source</i></b></a>
58   *
59   * @author Brian Wing Shun Chan
60   * @author Brian Myunghun Kim
61   * @author Jorge Ferrer
62   * @author Neil Griffin
63   * @author Thiago Moreira
64   * @author Brett Swaim
65   */
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 }