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