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(Account account) {
071 Properties properties = _getProperties(account);
072
073 Session session = Session.getInstance(properties);
074
075 if (_log.isDebugEnabled()) {
076 session.setDebug(true);
077
078 session.getProperties().list(System.out);
079 }
080
081 return session;
082 }
083
084 public static Session getSession(boolean cache) {
085 Session session = null;
086
087 try {
088 session = MailServiceUtil.getSession();
089 }
090 catch (SystemException se) {
091 if (_log.isWarnEnabled()) {
092 _log.warn(se, se);
093 }
094
095 session = InfrastructureUtil.getMailSession();
096 }
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(byte[] bytes) throws MailEngineException {
108 try {
109 Session session = getSession();
110
111 Message message = new MimeMessage(
112 session, new UnsyncByteArrayInputStream(bytes));
113
114 _send(session, message, null);
115 }
116 catch (Exception e) {
117 throw new MailEngineException(e);
118 }
119 }
120
121 public static void send(
122 InternetAddress from, InternetAddress to, String subject,
123 String body)
124 throws MailEngineException {
125
126 send(
127 from, new InternetAddress[] {to}, null, null, subject, body, false,
128 null, null, null);
129 }
130
131 public static void send(
132 InternetAddress from, InternetAddress to, String subject,
133 String body, boolean htmlFormat)
134 throws MailEngineException {
135
136 send(
137 from, new InternetAddress[] {to}, null, null, subject, body,
138 htmlFormat, null, null, null);
139 }
140
141 public static void send(
142 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
143 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
144 String subject, String body, boolean htmlFormat,
145 InternetAddress[] replyTo, String messageId, String inReplyTo)
146 throws MailEngineException {
147
148 send(
149 from, to, cc, bcc, bulkAddresses, subject, body, htmlFormat,
150 replyTo, messageId, inReplyTo, null);
151 }
152
153 public static void send(
154 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
155 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
156 String subject, String body, boolean htmlFormat,
157 InternetAddress[] replyTo, String messageId, String inReplyTo,
158 File[] attachments)
159 throws MailEngineException {
160
161 send(
162 from, to, cc, bcc, bulkAddresses, subject, body, htmlFormat,
163 replyTo, messageId, inReplyTo, attachments, null);
164 }
165
166 public static void send(
167 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
168 InternetAddress[] bcc, InternetAddress[] bulkAddresses,
169 String subject, String body, boolean htmlFormat,
170 InternetAddress[] replyTo, String messageId, String inReplyTo,
171 File[] attachments, SMTPAccount smtpAccount)
172 throws MailEngineException {
173
174 StopWatch stopWatch = null;
175
176 if (_log.isDebugEnabled()) {
177 stopWatch = new StopWatch();
178
179 stopWatch.start();
180
181 _log.debug("From: " + from);
182 _log.debug("To: " + Arrays.toString(to));
183 _log.debug("CC: " + Arrays.toString(cc));
184 _log.debug("BCC: " + Arrays.toString(bcc));
185 _log.debug("List Addresses: " + Arrays.toString(bulkAddresses));
186 _log.debug("Subject: " + subject);
187 _log.debug("Body: " + body);
188 _log.debug("HTML Format: " + htmlFormat);
189 _log.debug("Reply to: " + Arrays.toString(replyTo));
190 _log.debug("Message ID: " + messageId);
191 _log.debug("In Reply To: " + inReplyTo);
192
193 if (attachments != null) {
194 for (int i = 0; i < attachments.length; i++) {
195 File attachment = attachments[i];
196
197 if (attachment != null) {
198 String path = attachment.getAbsolutePath();
199
200 _log.debug("Attachment #" + (i + 1) + ": " + path);
201 }
202 }
203 }
204 }
205
206 try {
207 Session session = null;
208
209 if (smtpAccount == null) {
210 session = getSession();
211 }
212 else {
213 session = getSession(smtpAccount);
214 }
215
216 Message message = new LiferayMimeMessage(session);
217
218 message.setFrom(from);
219 message.setRecipients(Message.RecipientType.TO, to);
220
221 if (cc != null) {
222 message.setRecipients(Message.RecipientType.CC, cc);
223 }
224
225 if (bcc != null) {
226 message.setRecipients(Message.RecipientType.BCC, bcc);
227 }
228
229 subject = GetterUtil.getString(subject);
230
231 message.setSubject(subject);
232
233 if ((attachments != null) && (attachments.length > 0)) {
234 MimeMultipart rootMultipart = new MimeMultipart(
235 _MULTIPART_TYPE_MIXED);
236
237 MimeMultipart messageMultipart = new MimeMultipart(
238 _MULTIPART_TYPE_ALTERNATIVE);
239
240 MimeBodyPart messageBodyPart = new MimeBodyPart();
241
242 messageBodyPart.setContent(messageMultipart);
243
244 rootMultipart.addBodyPart(messageBodyPart);
245
246 if (htmlFormat) {
247 MimeBodyPart bodyPart = new MimeBodyPart();
248
249 bodyPart.setContent(body, _TEXT_HTML);
250
251 messageMultipart.addBodyPart(bodyPart);
252 }
253 else {
254 MimeBodyPart bodyPart = new MimeBodyPart();
255
256 bodyPart.setText(body);
257
258 messageMultipart.addBodyPart(bodyPart);
259 }
260
261 for (int i = 0; i < attachments.length; i++) {
262 File attachment = attachments[i];
263
264 if (attachment != null) {
265 MimeBodyPart bodyPart = new MimeBodyPart();
266
267 DataSource source = new FileDataSource(attachment);
268
269 bodyPart.setDisposition(Part.ATTACHMENT);
270 bodyPart.setDataHandler(new DataHandler(source));
271 bodyPart.setFileName(attachment.getName());
272
273 rootMultipart.addBodyPart(bodyPart);
274 }
275 }
276
277 message.setContent(rootMultipart);
278
279 message.saveChanges();
280 }
281 else {
282 if (htmlFormat) {
283 message.setContent(body, _TEXT_HTML);
284 }
285 else {
286 message.setContent(body, _TEXT_PLAIN);
287 }
288 }
289
290 message.setSentDate(new Date());
291
292 if (replyTo != null) {
293 message.setReplyTo(replyTo);
294 }
295
296 if (messageId != null) {
297 message.setHeader("Message-ID", messageId);
298 }
299
300 if (inReplyTo != null) {
301 message.setHeader("In-Reply-To", inReplyTo);
302 message.setHeader("References", inReplyTo);
303 }
304
305 _send(session, message, bulkAddresses);
306 }
307 catch (SendFailedException sfe) {
308 _log.error(sfe);
309 }
310 catch (Exception e) {
311 throw new MailEngineException(e);
312 }
313
314 if (_log.isDebugEnabled()) {
315 _log.debug("Sending mail takes " + stopWatch.getTime() + " ms");
316 }
317 }
318
319 public static void send(
320 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
321 InternetAddress[] bcc, String subject, String body)
322 throws MailEngineException {
323
324 send(from, to, cc, bcc, subject, body, false, null, null, null);
325 }
326
327 public static void send(
328 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
329 InternetAddress[] bcc, String subject, String body,
330 boolean htmlFormat, InternetAddress[] replyTo, String messageId,
331 String inReplyTo)
332 throws MailEngineException {
333
334 send(
335 from, to, cc, bcc, null, subject, body, htmlFormat, replyTo,
336 messageId, inReplyTo, null);
337 }
338
339 public static void send(
340 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
341 String subject, String body)
342 throws MailEngineException {
343
344 send(from, to, cc, null, subject, body, false, null, null, null);
345 }
346
347 public static void send(
348 InternetAddress from, InternetAddress[] to, InternetAddress[] cc,
349 String subject, String body, boolean htmlFormat)
350 throws MailEngineException {
351
352 send(from, to, cc, null, subject, body, htmlFormat, null, null, null);
353 }
354
355 public static void send(
356 InternetAddress from, InternetAddress[] to, String subject,
357 String body)
358 throws MailEngineException {
359
360 send(from, to, null, null, subject, body, false, null, null, null);
361 }
362
363 public static void send(
364 InternetAddress from, InternetAddress[] to, String subject,
365 String body, boolean htmlFormat)
366 throws MailEngineException {
367
368 send(from, to, null, null, subject, body, htmlFormat, null, null, null);
369 }
370
371 public static void send(MailMessage mailMessage)
372 throws MailEngineException {
373
374 send(
375 mailMessage.getFrom(), mailMessage.getTo(), mailMessage.getCC(),
376 mailMessage.getBCC(), mailMessage.getBulkAddresses(),
377 mailMessage.getSubject(), mailMessage.getBody(),
378 mailMessage.isHTMLFormat(), mailMessage.getReplyTo(),
379 mailMessage.getMessageId(), mailMessage.getInReplyTo(),
380 mailMessage.getAttachments(), mailMessage.getSMTPAccount());
381 }
382
383 public static void send(String from, String to, String subject, String body)
384 throws MailEngineException {
385
386 try {
387 send(
388 new InternetAddress(from), new InternetAddress(to), subject,
389 body);
390 }
391 catch (AddressException ae) {
392 throw new MailEngineException(ae);
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 message, 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(message, bulkAddresses);
465 }
466 else {
467 transport.sendMessage(message, message.getAllRecipients());
468 }
469
470 transport.close();
471 }
472 else {
473 if ((bulkAddresses != null) && (bulkAddresses.length > 0)) {
474 Transport.send(message, bulkAddresses);
475 }
476 else {
477 Transport.send(message);
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 }