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