/** * Abiquo community edition * cloud management application for hybrid clouds * Copyright (C) 2008-2010 - Abiquo Holdings S.L. * * This application is free software; you can redistribute it and/or * modify it under the terms of the GNU LESSER GENERAL PUBLIC * LICENSE as published by the Free Software Foundation under * version 3 of the License * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * LESSER GENERAL PUBLIC LICENSE v.3 for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package com.abiquo.mailman; import java.util.Properties; import java.util.Set; import javax.mail.Address; import javax.mail.Message; import javax.mail.Multipart; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.naming.NamingException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.abiquo.abiserver.config.AbiConfig; import com.abiquo.abiserver.config.AbiConfigManager; import com.abiquo.abiserver.exception.MailException; /** * @author Diego Parrilla * @date 04-dic-2009 * @version $Revision: 1.2 $ */ public class MailManager { /** debug. */ private static final Logger logger = LoggerFactory.getLogger(MailManager.class); private static final String DEFAULT_TRANSPORT = "smtp"; private static final String BAD_JNDI_ERROR = "Bad JNDI Error."; private static final String BAD_INTERNET_ADDRESS_ERROR = "Bad Internet Address error."; // private static final String BAD_MAIL_ADDRESS_ERROR = "Bad Mail Address error."; private static final String DEFAULT_ENCODING = "UTF-8"; private static final String MAIL_SMTP_AUTH = "mail.smtp.auth"; private Session session_ = null; private String host_, username_, password_, encoding_; private Boolean isSmtpAuthentication = true; private Boolean isTls = true; private Boolean isSsl = true; private Integer sslPort = 443; private final static boolean STRICT_EMAIL_CHECK = true; /** * Creates an object that handles the connection to a MTA. * * @param host mail host server (IP or hostname) * @param username login user name in the mail host server * @param password password of the user in the mail host server * @param encoding encoding type of the mails * @param isAuth use authentication to connect * @param isTls start a TLS conversation to connect * @param isSsl use SSL to connect * @param sslPort port used for SSL connection */ protected MailManager(String host, String username, String password, String encoding, Boolean isAuth, Boolean isTls, Boolean isSsl, Integer sslPort) { this.host_ = host; this.username_ = username; this.password_ = password; this.encoding_ = encoding; this.isSmtpAuthentication = isAuth; this.isTls = isTls; this.isSsl = isSsl; this.sslPort = sslPort; } /** * Creates an object that handles the connection to a MTA. * * @param host mail host server (IP or hostname) * @param username login user name in the mail host server * @param password password of the user in the mail host server * @param encoding encoding type of the mails * @param isAuth use authentication to connect * @param isTls start a TLS conversation to connect */ protected MailManager(String host, String username, String password, String encoding, Boolean isAuth, Boolean isTls) { this.host_ = host; this.username_ = username; this.password_ = password; this.encoding_ = encoding; this.isSmtpAuthentication = isAuth; this.isTls = isTls; this.isSsl = false; this.sslPort = 443; } /** * Creates an object that handles the connection to a MTA. * * @param host mail host server (IP or hostname) * @param username login user name in the mail host server * @param password password of the user in the mail host server * @param encoding encoding type of the mails * @param isAuth use authentication to connect */ protected MailManager(String host, String username, String password, String encoding, Boolean isAuth) { this.host_ = host; this.username_ = username; this.password_ = password; this.encoding_ = encoding; this.isSmtpAuthentication = isAuth; this.isTls = false; this.isSsl = false; this.sslPort = 443; } /** * Creates an object that handles the connection to a MTA. * * @param host mail host server (IP or hostname) * @param username login user name in the mail host server * @param password password of the user in the mail host server * @param encoding encoding type of the mails */ protected MailManager(String host, String username, String password, String encoding) { this.host_ = host; this.username_ = username; this.password_ = password; this.encoding_ = encoding; this.isSmtpAuthentication = false; this.isTls = false; this.isSsl = false; this.sslPort = 443; } /** * Creates an object that handles the connection to a MTA. The emails sent are encoded by * default with UTF-8 encoding * * @param host mail host server (IP or hostname) * @param username login user name in the mail host server * @param password password of the user in the mail host server */ private MailManager(String host, String username, String password) { host_ = host; username_ = username; password_ = password; encoding_ = MailManager.DEFAULT_ENCODING; this.isSmtpAuthentication = false; this.isTls = false; this.isSsl = false; this.sslPort = 443; } /** Singleton isntance. */ private static MailManager instance; /** * Instantiate the class using the configuration elements (SMTP account). */ public static synchronized MailManager instance() { if (instance == null) { AbiConfig conf = AbiConfigManager.getInstance().getAbiConfig(); logger.info("Created MailManager to work with [{}] using [{}]", conf.getMailServer(), conf.getMailUser()); instance = new MailManager(conf.getMailServer(), conf.getMailUser(), conf.getMailPassword()); } return instance; } /** * Sends a email TO & CC the lists given as parameters. * * @param from Contains the e-mail of the sender * @param to List that contains the TO receivers of the mail * @param to List that contains the CC receivers of the mail * @param subject Contains the subject of the mail * @param body Contains the body of the mail * @return if null any error, otherwise an String containing some warning (some bad email * address) */ public String send(String from, Set<String> addressListTO, Set<String> addressListCC, String subject, String body) throws MailException { StringBuilder errorBuilder = new StringBuilder(); try { // Creating the message MimeMessage myMessage = new MimeMessage(this.getMailSession()); // Setting the parts of the message //////////////////////////////// // Setting the subject of the message. Uses the in parameter subject myMessage.setSubject(subject, encoding_); // Set from in the emails depending on the brand. if ((from != null) && !from.equals("")) { myMessage.setFrom(new InternetAddress(from, STRICT_EMAIL_CHECK)); } MimeBodyPart mbp1 = new MimeBodyPart(); mbp1.setText(body, encoding_); Multipart mp = new MimeMultipart(); mp.addBodyPart(mbp1); myMessage.setContent(mp); // Setting the TO addresses of the receivers for (String addr : addressListTO) { try { Address addressAux = new InternetAddress(addr, STRICT_EMAIL_CHECK); myMessage.addRecipient(Message.RecipientType.TO, addressAux); } // capture any malformed address catch (AddressException addEx) { final String cause = String.format("Invalid email address TO [%s] caused by [%s]", addr, addEx.getLocalizedMessage()); errorBuilder.append(cause); } } // Setting the CC addresses of the receivers if (addressListCC != null) { for (String addr : addressListCC) { try { Address addressAux = new InternetAddress(addr, STRICT_EMAIL_CHECK); myMessage.addRecipient(Message.RecipientType.CC, addressAux); } // capture any malformed address catch (AddressException addEx) { final String cause = String.format("Invalid email address CC [%s] caused by [%s]", addr, addEx.getLocalizedMessage()); errorBuilder.append(cause); } } } // Send the message to receivers Transport tr = session_.getTransport(MailManager.DEFAULT_TRANSPORT); tr.connect(host_, username_, password_); myMessage.saveChanges(); // don't forget this tr.sendMessage(myMessage, myMessage.getAllRecipients()); tr.close(); } // catch (javax.mail.internet.AddressException exc) // { // throw new MailException(MailManager.BAD_MAIL_ADDRESS_ERROR, exc); // } catch (AddressException ae) { throw new MailException(MailManager.BAD_INTERNET_ADDRESS_ERROR, ae); } catch (javax.mail.MessagingException exc) { throw new MailException(MailManager.BAD_INTERNET_ADDRESS_ERROR, exc); } catch (javax.naming.NamingException exc) { throw new MailException(MailManager.BAD_JNDI_ERROR, exc); } return errorBuilder.toString(); } /** * Sends a email with the parameter keys. * * @exception AmpliaMarcoException * @param mailFrom - mail account from the mail is send * @param mailTo - recipients for send to. A String separated by commas * @param mailCc - recipients for send in copy. A String separated by commas * @param subject - subject of the mail * @param body - body of the mail * @return if null any error, otherwise an String containing some warning (some bad email * address) */ public String send(String mailFrom, String mailTo, String mailCc, String subject, String body) throws MailException { StringBuilder errorBuilder = new StringBuilder(); try { // Creating the message MimeMessage myMessage = new MimeMessage(this.getMailSession()); // Setting the subject of the message. Uses the in parameter subject myMessage.setSubject(subject, encoding_); if ((mailFrom != null) && (!mailFrom.equals(""))) { Address myAddress = new InternetAddress(mailFrom, STRICT_EMAIL_CHECK); myMessage.setFrom(myAddress); } else { myMessage.setFrom(); } // Setting the content of the message. Uses the in parameter body MimeBodyPart mbp1 = new MimeBodyPart(); mbp1.setText(body, encoding_); Multipart mp = new MimeMultipart(); mp.addBodyPart(mbp1); myMessage.setContent(mp); try { // Setting the TO addresses of the receivers myMessage.addRecipients(Message.RecipientType.TO, InternetAddress.parse(mailTo, STRICT_EMAIL_CHECK)); } // capture any malformed address catch (AddressException addEx) { final String cause = String.format("Invalid email address TO [%s] caused by [%s]", mailTo, addEx.getLocalizedMessage()); errorBuilder.append(cause); } // Setting the CC addresses of the receivers if (mailCc != null) { try { myMessage.addRecipients(Message.RecipientType.CC, InternetAddress.parse(mailCc, STRICT_EMAIL_CHECK)); } // capture any malformed address catch (AddressException addEx) { final String cause = String.format("Invalid email address CC [%s] caused by [%s]", mailCc, addEx.getLocalizedMessage()); errorBuilder.append(cause).append(addEx.getLocalizedMessage()); } } // Send the message to receivers Transport tr = session_.getTransport(MailManager.DEFAULT_TRANSPORT); tr.connect(host_, username_, password_); myMessage.saveChanges(); // don't forget this tr.sendMessage(myMessage, myMessage.getAllRecipients()); tr.close(); } // catch (javax.mail.internet.AddressException exc) // { // throw new MailException(MailManager.BAD_MAIL_ADDRESS_ERROR, exc); // } catch (javax.mail.MessagingException exc) { throw new MailException(MailManager.BAD_INTERNET_ADDRESS_ERROR, exc); } catch (javax.naming.NamingException exc) { throw new MailException(MailManager.BAD_JNDI_ERROR, exc); } return errorBuilder.toString(); } /** * Sends a email with the parameter keys. * * @exception AmpliaMarcoException * @param mailFrom - mail account from the mail is send * @param mailTo - recipients for send to. A String separated by commas * @param subject - subject of the mail * @param body - body of the mail * @return if null any error, otherwise an String containing some warning (some bad email * address) */ public String send(String mailFrom, String mailTo, String subject, String body) throws MailException { return this.send(mailFrom, mailTo, null, subject, body); } /** * The value of mailFrom is obtained from the property "mail.user". Sends a email with the * parameter keys. * * @exception AmpliaMarcoException * @param mailTo - recipients for send to. A String separated by commas * @param mailCc - recipients for send in copy. A String separated by commas * @param subject - subject of the mail * @param body - body of the mail * @return if null any error, otherwise an String containing some warning (some bad email * address) */ public String sendFromMailUser(String mailTo, String mailCc, String subject, String body) throws MailException { return this.send(null, mailTo, mailCc, subject, body); } /** * The value of mailFrom is obtained from the property "mail.user". Sends a email with the * parameter keys. * * @exception AmpliaMarcoException * @param mailTo - recipients for send to. A String separated by commas * @param subject - subject of the mail * @param body - body of the mail * @return if null any error, otherwise an String containing some warning (some bad email * address) */ public String sendFromMailUser(String mailTo, String subject, String body) throws Exception { return this.sendFromMailUser(mailTo, null, subject, body); } private Session getMailSession() throws NamingException, MailException { if (session_ == null) { Properties props = new Properties(); // Use the following if you need authentication props.put(MailManager.MAIL_SMTP_AUTH, isSmtpAuthentication.toString()); // Use the following if you need to start TLS props.put("mail.smtp.starttls.enable", isTls.toString()); // Use the following if you need SSL if (isSsl) { props.put("mail.smtp.socketFactory.port", sslPort.toString()); props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.smtp.socketFactory.fallback", "false"); } session_ = Session.getDefaultInstance(props, null); } return session_; } }