package com.idega.util;
import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimePart;
import com.idega.builder.bean.AdvancedProperty;
import com.idega.core.file.util.MimeTypeUtil;
import com.idega.core.messaging.MessagingSettings;
import com.idega.core.messaging.SMTPAuthenticator;
import com.idega.idegaweb.DefaultIWBundle;
import com.idega.idegaweb.IWMainApplication;
import com.idega.idegaweb.IWMainApplicationSettings;
import com.sun.mail.smtp.SMTPTransport;
/**
* <p>
* Utility class to send Emails with the Java Mail API.
* </p>
* Last modified: $Date: 2009/06/18 15:57:43 $ by $Author: eiki $
*
* @author <a href="mailto:tryggvil@idega.com">tryggvil</a>
* @version $Revision: 1.20 $
*/
public class SendMail {
public static final String HEADER_AUTO_SUBMITTED = "Auto-Submitted",
HEADER_PRECEDENCE = "Precedence";
private static final Logger LOGGER = Logger.getLogger(SendMail.class.getName());
private SendMail() {}
/**
* <p>
* Method that uses the Java Mail API to send an email message.<br/> It is
* recommended to use the <type>com.idega.core.messaging.EmailMessage</type>
* class rather than calling this method directly.
* </p>
*
* @param from
* @param to
* @param cc
* @param bcc
* @param replyTo
* @param host
* @param subject
* @param text
* @param mailType: plain text, HTML etc.
* @param attachedFiles
* @throws MessagingException
*/
public static void send(String from, String to, String cc, String bcc, String replyTo, String host, String subject, String text, String mailType,
File... attachedFiles) throws MessagingException {
send(from, to, cc, bcc, replyTo, host, subject, text, mailType, false, attachedFiles);
}
/**
* Sends email
* @param from
* @param to
* @param cc
* @param bcc
* @param replyTo
* @param host
* @param subject
* @param text
* @param mailType
* @param deleteFiles
* @param attachedFiles
* @throws MessagingException
*/
public static void send(String from, String to, String cc, String bcc, String replyTo, String host, String subject, String text, String mailType, boolean deleteFiles,
File... attachedFiles) throws MessagingException {
send(from, to, cc, bcc, replyTo, host, subject, text, mailType, null, false, deleteFiles, attachedFiles);
}
/**
* <p>
* Method that uses the Java Mail API to send an email message.<br/> It is
* recommended to use the <type>com.idega.core.messaging.EmailMessage</type>
* class rather than calling this method directly.
* </p>
*
* @param from
* @param to
* @param cc
* @param bcc
* @param replyTo
* @param host
* @param subject
* @param text
* @param mailType
* @param headers
* @param attachedFiles
* @throws MessagingException
*/
public static Message send(String from, String to, String cc, String bcc, String replyTo, String host, String subject, String text, String mailType,
List<AdvancedProperty> headers, final boolean useThread, final boolean deleteFiles, final File... attachedFiles) throws MessagingException {
if (!DefaultIWBundle.isProductionEnvironment()) {
LOGGER.log(Level.INFO, "to: " + to + " mail: " + text);
return null;
}
// Charset usually either "UTF-8" or "ISO-8859-1". If not set the system default set is taken
IWMainApplicationSettings settings = IWMainApplication.getDefaultIWApplicationContext().getApplicationSettings();
String charset = settings.getCharSetForSendMail();
boolean useSmtpAuthentication = settings.getBoolean(MessagingSettings.PROP_SYSTEM_SMTP_USE_AUTHENTICATION, Boolean.TRUE);
boolean useSSL = settings.getBoolean(MessagingSettings.PROP_SYSTEM_SMTP_USE_SSL, Boolean.TRUE);
String username = settings.getProperty(MessagingSettings.PROP_SYSTEM_SMTP_USER_NAME, "idegatest@idega.com");
String password = settings.getProperty(MessagingSettings.PROP_SYSTEM_SMTP_PASSWORD, "pl4tf0rm");
String port = settings.getProperty(MessagingSettings.PROP_SYSTEM_SMTP_PORT, CoreConstants.EMPTY);
if (StringUtil.isEmpty(host)) {
host = useSSL ? "secure.emailsrvr.com" :
settings.getProperty(MessagingSettings.PROP_SYSTEM_SMTP_MAILSERVER, "smtp.emailsrvr.com");
if (StringUtil.isEmpty(host))
throw new MessagingException("Mail server is not configured.");
}
if (StringUtil.isEmpty(username))
useSmtpAuthentication = false;
// Set the host smtp address
Properties props = new Properties();
props.put("mail.smtp.host", host);
// Set the smtp server port
if (!StringUtil.isEmpty(port))
props.put("mail.smtp.port", port);
// Start a session
Session session;
if (useSmtpAuthentication) {
props.put("mail.smtp.auth", Boolean.TRUE.toString());
Authenticator auth = new SMTPAuthenticator(username, password);
if (useSSL)
props.put("mail.smtp.ssl.enable", Boolean.TRUE.toString());
session = Session.getInstance(props, auth);
} else {
session = Session.getInstance(props, null);
}
// Set debug if needed
session.setDebug(settings.isDebugActive());
// Construct a message
// Sender
if (StringUtil.isEmpty(from))
throw new MessagingException("From address is null.");
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
// Process to, cc and bcc
if (!addRecipients(message, Message.RecipientType.TO, to)) {
LOGGER.warning("Unable to send email to " + to);
return null;
}
addRecipients(message, Message.RecipientType.CC, cc);
addRecipients(message, Message.RecipientType.BCC, bcc);
// Reply-to
if (!StringUtil.isEmpty(replyTo))
message.setReplyTo(InternetAddress.parse(replyTo));
// Subject
message.setSubject(subject, charset);
// Attachments
if (ArrayUtil.isEmpty(attachedFiles)) {
setMessageContent(message, text, mailType, charset);
} else {
MimeBodyPart body = new MimeBodyPart();
setMessageContent(body, text, mailType, charset);
MimeMultipart multipart = new MimeMultipart();
multipart.addBodyPart(body);
for (File attachedFile: attachedFiles) {
if (attachedFile == null)
continue;
if (!attachedFile.exists()) {
LOGGER.warning("File '" + attachedFile + "' does not exist!");
continue;
}
BodyPart attachment = new MimeBodyPart();
DataSource attachmentSource = new FileDataSource(attachedFile);
DataHandler attachmentHandler = new DataHandler(attachmentSource);
attachment.setDataHandler(attachmentHandler);
attachment.setFileName(attachedFile.getName());
attachment.setDescription("Attached file: " + attachment.getFileName());
multipart.addBodyPart(attachment);
}
message.setContent(multipart);
}
// Headers
if (!ListUtil.isEmpty(headers)) {
for (AdvancedProperty header: headers) {
message.addHeader(header.getId(), header.getValue());
}
}
// Send the message and close the connection
final Message mail = message;
Thread transporter = new Thread(new Runnable() {
@Override
public void run() {
try {
SMTPTransport.send(mail);
} catch (Exception e) {
StringBuilder filesNames = new StringBuilder();
if (!ArrayUtil.isEmpty(attachedFiles)) {
for (File attachment: attachedFiles) {
if (attachment == null)
continue;
filesNames.append(attachment.getName()).append(CoreConstants.COMMA).append(CoreConstants.SPACE);
}
}
LOGGER.log(Level.WARNING, "Error sending mail " + mail + " - Attachments: '" + filesNames.toString() + "': " + e.getMessage());
} finally {
if (deleteFiles && !ArrayUtil.isEmpty(attachedFiles)) {
for (File attachment: attachedFiles) {
if (attachment != null && attachment.exists())
attachment.delete();
}
}
}
}
});
if (useThread)
transporter.start();
else
transporter.run();
return message;
}
private static void setMessageContent(MimePart message, String content, String mailType, String charset) throws MessagingException {
boolean htmlMail = MimeTypeUtil.MIME_TYPE_HTML.equals(mailType);
if (htmlMail) {
message.setText(content, charset, "html");
} else {
message.setText(content, charset);
}
}
private static boolean doValidateAddresses(String addresses) {
if (StringUtil.isEmpty(addresses))
return false;
String[] emails = addresses.split(CoreConstants.COMMA);
if (ArrayUtil.isEmpty(emails))
return false;
for (String email: emails) {
if (!EmailValidator.getInstance().validateEmail(email))
return false;
}
return true;
}
private static boolean addRecipients(MimeMessage message, RecipientType recipientType, String addresses) throws MessagingException {
if (StringUtil.isEmpty(addresses))
return false;
addresses = StringHandler.replace(addresses, CoreConstants.SEMICOLON, CoreConstants.COMMA);
if (!doValidateAddresses(addresses)) {
LOGGER.warning("Adrresses " + addresses + " are invalid!");
return false;
}
message.addRecipients(recipientType, InternetAddress.parse(addresses));
return true;
}
public static void send(String from, String to, String cc, String bcc, String host, String subject, String text, File attachedFile) throws MessagingException {
send(from, to, cc, bcc, host, subject, text, false, false, attachedFile);
}
public static void send(String from, String to, String cc, String bcc, String host, String subject, String text, boolean useThread, boolean deleteFile, File attachedFile)
throws MessagingException {
send(from, to, cc, bcc, null, host, subject, text, useThread, deleteFile, attachedFile);
}
public static void send(SendMailMessageValue mv) throws MessagingException {
File attachment = mv.getAttachedFile();
send(mv.getFrom(), mv.getTo(), mv.getCc(), mv.getBcc(), mv.getReplyTo(), mv.getHost(), mv.getSubject(), mv.getText(), mv.getHeaders(), false, true, attachment);
}
public static void send(String from, String to, String cc, String bcc, String host, String subject, String text) throws MessagingException {
send(from, to, cc, bcc, null, host, subject, text);
}
public static void send(String from, String to, String cc, String bcc, String replyTo, String host, String subject, String text) throws MessagingException {
send(from, to, cc, bcc, replyTo, host, subject, text, true, false, new File[] {});
}
/**
* Sends email
* @param from
* @param to
* @param cc
* @param bcc
* @param replyTo
* @param host
* @param subject
* @param text
* @param useThread
* @param deleteFiles
* @param attachedFiles
* @return
* @throws MessagingException
*/
public static Message send(String from, String to, String cc, String bcc, String replyTo, String host, String subject, String text, boolean useThread, boolean deleteFiles,
File... attachedFiles) throws MessagingException {
List<AdvancedProperty> headers = Collections.emptyList();
return send(from, to, cc, bcc, replyTo, host, subject, text, headers, useThread, deleteFiles, attachedFiles);
}
/**
* Sends email
* @param from
* @param to
* @param cc
* @param bcc
* @param replyTo
* @param host
* @param subject
* @param text
* @param headers
* @param useThread
* @param deleteFiles
* @param attachedFiles
* @return
* @throws MessagingException
*/
public static Message send(String from, String to, String cc, String bcc, String replyTo, String host, String subject, String text, List<AdvancedProperty> headers,
boolean useThread, boolean deleteFiles, File... attachedFiles) throws MessagingException {
return send(from, to, cc, bcc, replyTo, host, subject, text, MimeTypeUtil.MIME_TYPE_TEXT_PLAIN, headers, useThread, deleteFiles, attachedFiles);
}
}