/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2009-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.javamail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.Address; import javax.mail.Authenticator; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.NoSuchProviderException; import javax.mail.Part; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.event.TransportEvent; import javax.mail.event.TransportListener; 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 org.opennms.core.utils.PropertiesUtils; import org.opennms.core.utils.ThreadCategory; import org.springframework.util.StringUtils; /** * Sends an email message using the Java Mail API * * @author <A HREF="mailto:david@opennms.org">David Hustace </A> * @version $Id: $ */ public class JavaMailer { private static final String DEFAULT_FROM_ADDRESS = "root@[127.0.0.1]"; // private static final String DEFAULT_TO_ADDRESS = "root@[127.0.0.1]"; private static final String DEFAULT_MAIL_HOST = "127.0.0.1"; private static final boolean DEFAULT_AUTHENTICATE = false; private static final String DEFAULT_AUTHENTICATE_USER = "opennms"; private static final String DEFAULT_AUTHENTICATE_PASSWORD = "opennms"; private static final String DEFAULT_MAILER = "smtpsend"; private static final String DEFAULT_TRANSPORT = "smtp"; private static final boolean DEFAULT_MAILER_DEBUG = false; private static final boolean DEFAULT_USE_JMTA = true; private static final String DEFAULT_CONTENT_TYPE = "text/plain"; private static final String DEFAULT_CHARSET = "us-ascii"; private static final String DEFAULT_ENCODING = "Q"; // I think this means quoted-printable encoding, see bug 2825 private static final boolean DEFAULT_STARTTLS_ENABLE = false; private static final boolean DEFAULT_QUIT_WAIT = true; private static final int DEFAULT_SMTP_PORT = 25; private static final boolean DEFAULT_SMTP_SSL_ENABLE = false; private Session m_session = null; /* * properties from configuration */ private Properties m_mailProps; /* * fields from properties used for deterministic behavior of the mailer */ private boolean m_debug; private String m_mailHost; private boolean m_useJMTA; private String m_mailer; private String m_transport; private String m_from; private boolean m_authenticate; private String m_user; private String m_password; private String m_contentType; private String m_charSet; private String m_encoding; private boolean m_startTlsEnabled; private boolean m_quitWait; private int m_smtpPort; private boolean m_smtpSsl; /* * Basic messaging fields */ private String m_to; private String m_subject; private String m_messageText; private String m_fileName; private InputStream m_inputStream; private String m_inputStreamName; private String m_inputStreamContentType; private Map<String,String> m_extraHeaders = new HashMap<String,String>(); /** * <p>Constructor for JavaMailer.</p> * * @param javamailProps a {@link java.util.Properties} object. * @throws org.opennms.javamail.JavaMailerException if any. */ public JavaMailer(Properties javamailProps) throws JavaMailerException { try { configureProperties(javamailProps); } catch (IOException e) { throw new JavaMailerException("Failed to construct mailer", e); } //Now set the properties into the session m_session = Session.getInstance(getMailProps(), createAuthenticator()); } /** * Default constructor. Default properties from javamailer-properties are set into session. To change these * properties, retrieve the current properties from the session and override as needed. * * @throws IOException if any. * @throws org.opennms.javamail.JavaMailerException if any. */ public JavaMailer() throws JavaMailerException { this(new Properties()); } /** * This method uses a properties file reader to pull in opennms styled javamail properties and sets * the actual javamail properties. This is here to preserve the backwards compatibility but configuration * will probably change soon. * * @throws IOException */ private void configureProperties(Properties javamailProps) throws IOException { //this loads the opennms defined properties m_mailProps = JavaMailerConfig.getProperties(); //this sets any javamail defined properties sent in to the constructor m_mailProps.putAll(javamailProps); /* * fields from properties used for deterministic behavior of the mailer */ m_debug = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.debug", DEFAULT_MAILER_DEBUG); m_mailHost = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.mailHost", DEFAULT_MAIL_HOST); m_useJMTA = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.useJMTA", DEFAULT_USE_JMTA); m_mailer = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.mailer", DEFAULT_MAILER); m_transport = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.transport", DEFAULT_TRANSPORT); m_from = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.fromAddress", DEFAULT_FROM_ADDRESS); m_authenticate = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.authenticate", DEFAULT_AUTHENTICATE); m_user = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.authenticateUser", DEFAULT_AUTHENTICATE_USER); m_password = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.authenticatePassword", DEFAULT_AUTHENTICATE_PASSWORD); m_contentType = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.messageContentType", DEFAULT_CONTENT_TYPE); m_charSet = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.charset", DEFAULT_CHARSET); m_encoding = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.encoding", DEFAULT_ENCODING); m_startTlsEnabled = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.starttls.enable", DEFAULT_STARTTLS_ENABLE); m_quitWait = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.quitwait", DEFAULT_QUIT_WAIT); m_smtpPort = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.smtpport", DEFAULT_SMTP_PORT); m_smtpSsl = PropertiesUtils.getProperty(m_mailProps, "org.opennms.core.utils.smtpssl.enable", DEFAULT_SMTP_SSL_ENABLE); //Set the actual JavaMailProperties... any that are defined in the file will not be overridden //Eventually, all configuration will be defined in properties and this strange parsing will not happen //TODO: fix this craziness! if (!m_mailProps.containsKey("mail.smtp.auth")) { m_mailProps.setProperty("mail.smtp.auth", String.valueOf(isAuthenticate())); } if (!m_mailProps.containsKey("mail.smtp.starttls.enable")) { m_mailProps.setProperty("mail.smtp.starttls.enable", String.valueOf(isStartTlsEnabled())); } if (!m_mailProps.containsKey("mail.smtp.quitwait")) { m_mailProps.setProperty("mail.smtp.quitwait", String.valueOf(isQuitWait())); } if (!m_mailProps.containsKey("mail.smtp.port")) { m_mailProps.setProperty("mail.smtp.port", String.valueOf(getSmtpPort())); } if (isSmtpSsl()) { if (!m_mailProps.containsKey("mail.smtps.auth")) { m_mailProps.setProperty("mail.smtps.auth", String.valueOf(isAuthenticate())); } if (!m_mailProps.containsKey("mail.smtps.socketFactory.class")) { m_mailProps.setProperty("mail.smtps.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); } if (!m_mailProps.containsKey("mail.smtps.socketFactory.port")) { m_mailProps.setProperty("mail.smtps.socketFactory.port", String.valueOf(getSmtpPort())); } // if (!getMailProps().containsKey("mail.smtp.socketFactory.fallback")) { // getMailProps().setProperty("mail.smtp.socketFactory.fallback", "false"); // } } if (!m_mailProps.containsKey("mail.smtp.quitwait")) { m_mailProps.setProperty("mail.smtp.quitwait", "true"); } //getMailProps().setProperty("mail.store.protocol", "pop3"); } /** * Sends a message based on properties set on this bean. * * @throws org.opennms.javamail.JavaMailerException if any. */ public void mailSend() throws JavaMailerException { log().debug(createSendLogMsg()); sendMessage(buildMessage()); } /** * Helper method to create an Authenticator based on Password Authentication * * @return a {@link javax.mail.Authenticator} object. */ public Authenticator createAuthenticator() { Authenticator auth; if (isAuthenticate()) { auth = new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(getUser(), getPassword()); } }; } else { auth = null; } return auth; } /** * Build a complete message ready for sending. * * @return completed message, ready to be passed to Transport.sendMessage * @throws org.opennms.javamail.JavaMailerException if any of the underlying operations fail */ public Message buildMessage() throws JavaMailerException { try { checkEnvelopeAndContents(); MimeMessage message = initializeMessage(); // The next line has been commented, because it prevents the usage of internationalized characters and makes the email unreadable. // String encodedText = MimeUtility.encodeText(getMessageText(), m_charSet, m_encoding); String encodedText = getMessageText(); if ((getFileName() == null) && (getInputStream() == null)) { message.setContent(encodedText, m_contentType+"; charset="+m_charSet); } else if (getFileName() == null) { BodyPart streamBodyPart = new MimeBodyPart(); streamBodyPart.setDataHandler(new DataHandler(new InputStreamDataSource(m_inputStreamName, m_inputStreamContentType, m_inputStream))); streamBodyPart.setFileName(m_inputStreamName); streamBodyPart.setHeader("Content-Transfer-Encoding", "base64"); streamBodyPart.setDisposition(Part.ATTACHMENT); MimeMultipart mp = new MimeMultipart(); mp.addBodyPart(streamBodyPart); message.setContent(mp); } else { BodyPart bp = new MimeBodyPart(); bp.setContent(encodedText, m_contentType+"; charset="+m_charSet); MimeMultipart mp = new MimeMultipart(); mp.addBodyPart(bp); mp.addBodyPart(createFileAttachment(new File(getFileName()))); message.setContent(mp); } message.setHeader("X-Mailer", getMailer()); message.setSentDate(new Date()); message.saveChanges(); return message; } catch (AddressException e) { log().error("Java Mailer Addressing exception: ", e); throw new JavaMailerException("Java Mailer Addressing exception: ", e); } catch (MessagingException e) { log().error("Java Mailer messaging exception: ", e); throw new JavaMailerException("Java Mailer messaging exception: ", e); // } catch (UnsupportedEncodingException e) { // log().error("Java Mailer messaging exception: ", e); // throw new JavaMailerException("Java Mailer encoding exception: ", e); } } /** * Helper method to that creates a MIME message. * @param session * @return * @throws MessagingException * @throws AddressException */ private MimeMessage initializeMessage() throws MessagingException, AddressException { MimeMessage message; message = new MimeMessage(getSession()); message.setFrom(new InternetAddress(getFrom())); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(getTo(), false)); message.setSubject(getSubject(), m_charSet); for (final String key : getExtraHeaders().keySet()) { message.setHeader(key, m_extraHeaders.get(key)); } return message; } /** * @return */ private String createSendLogMsg() { StringBuffer sb = new StringBuffer(); sb.append("\n\tTo: "); sb.append(getTo()); sb.append("\n\tFrom: "); sb.append(getFrom()); sb.append("\n\tSubject is: "); sb.append(getSubject()); sb.append("\n\tFile: "); sb.append(getFileName()!=null ? getFileName() : "no file attached"); sb.append("\n\n"); sb.append(getMessageText()); sb.append("\n"); return sb.toString(); } /** * Create a file attachment as a MimeBodyPart, checking to see if the file * exists before we create the attachment. * * @param file file to attach * @return attachment body part * @throws javax.mail.MessagingException if we can't set the data handler or * the file name on the MimeBodyPart * @throws org.opennms.javamail.JavaMailerException if the file does not exist or is not * readable */ public MimeBodyPart createFileAttachment(final File file) throws MessagingException, JavaMailerException { if (!file.exists()) { log().error("File attachment '" + file.getAbsolutePath() + "' does not exist."); throw new JavaMailerException("File attachment '" + file.getAbsolutePath() + "' does not exist."); } if (!file.canRead()) { log().error("File attachment '" + file.getAbsolutePath() + "' is not readable."); throw new JavaMailerException("File attachment '" + file.getAbsolutePath() + "' is not readable."); } MimeBodyPart bodyPart = new MimeBodyPart(); FileDataSource fds = new FileDataSource(file); bodyPart.setDataHandler(new DataHandler(fds)); bodyPart.setFileName(fds.getName()); return bodyPart; } /** * Check that required envelope and message contents properties have been * set. * * @throws JavaMailerException if any of the required properties have not * been set */ private void checkEnvelopeAndContents() throws JavaMailerException { if (getFrom() == null) { throw new JavaMailerException("Cannot have a null from address."); } if ("".equals(getFrom())) { throw new JavaMailerException("Cannot have an empty from address."); } if (getTo() == null) { throw new JavaMailerException("Cannot have a null to address."); } if ("".equals(getTo())) { throw new JavaMailerException("Cannot have an empty to address."); } if (getSubject() == null) { throw new JavaMailerException("Cannot have a null subject."); } if ("".equals(getSubject())) { throw new JavaMailerException("Cannot have an empty subject."); } if (getMessageText() == null) { throw new JavaMailerException("Cannot have a null messageText."); } if ("".equals(getMessageText())) { throw new JavaMailerException("Cannot have an empty messageText."); } } /** * Send message. * * @param message a {@link javax.mail.Message} object. * @throws org.opennms.javamail.JavaMailerException if any. */ public void sendMessage(Message message) throws JavaMailerException { Transport t = null; try { t = getSession().getTransport(getTransport()); log().debug("for transport name '" + getTransport() + "' got: " + t.getClass().getName() + "@" + Integer.toHexString(t.hashCode())); LoggingTransportListener listener = new LoggingTransportListener(log()); t.addTransportListener(listener); if (t.getURLName().getProtocol().equals("mta")) { // JMTA throws an AuthenticationFailedException if we call connect() log().debug("transport is 'mta', not trying to connect()"); } else if (isAuthenticate()) { log().debug("authenticating to " + getMailHost()); t.connect(getMailHost(), getSmtpPort(), getUser(), getPassword()); } else { log().debug("not authenticating to " + getMailHost()); t.connect(getMailHost(), getSmtpPort(), null, null); } t.sendMessage(message, message.getAllRecipients()); listener.assertAllMessagesDelivered(); } catch (NoSuchProviderException e) { log().error("Couldn't get a transport: " + e, e); throw new JavaMailerException("Couldn't get a transport: " + e, e); } catch (MessagingException e) { log().error("Java Mailer messaging exception: " + e, e); throw new JavaMailerException("Java Mailer messaging exception: " + e, e); } finally { try { if (t != null && t.isConnected()) { t.close(); } } catch (MessagingException e) { throw new JavaMailerException("Java Mailer messaging exception on transport close: " + e, e); } } } private class InputStreamDataSource implements DataSource { private String name; private String contentType; private ByteArrayOutputStream baos; InputStreamDataSource(String name, String contentType, InputStream inputStream) throws JavaMailerException { this.name = name; this.contentType = contentType; log().debug("setting contentType " + this.contentType); baos = new ByteArrayOutputStream(); int read; byte[] buff = new byte[256]; try { while((read = inputStream.read(buff)) != -1) { baos.write(buff, 0, read); } } catch (IOException e) { log().error("Could not read attachment from input stream: " + e, e); throw new JavaMailerException("Could not read attachment from input stream: " + e, e); } } public String getContentType() { log().debug("getContentType: " + contentType); return contentType; } public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(baos.toByteArray()); } public String getName() { return name; } public OutputStream getOutputStream() throws IOException { throw new IOException("Cannot write to this read-only resource"); } } /** * <p>getPassword</p> * * @return Returns the password. */ public String getPassword() { return m_password; } /** * <p>setPassword</p> * * @param password * The password to set. */ public void setPassword(String password) { m_password = password; } /** * <p>getUser</p> * * @return Returns the user. */ public String getUser() { return m_user; } /** * <p>setUser</p> * * @param user * The user to set. */ public void setUser(String user) { m_user = user; } /** * <p>isUseJMTA</p> * * @return Returns the _useMailHost. */ public boolean isUseJMTA() { return m_useJMTA; } /** * <p>setUseJMTA</p> * * @param useMTA a boolean. */ public void setUseJMTA(boolean useMTA) { m_useJMTA = useMTA; } /** * <p>getFrom</p> * * @return Returns the from address. */ public String getFrom() { return m_from; } /** * <p>setFrom</p> * * @param from * The from address to set. */ public void setFrom(String from) { m_from = from; } /** * <p>isAuthenticate</p> * * @return Returns the authenticate boolean. */ public boolean isAuthenticate() { return m_authenticate; } /** * <p>setAuthenticate</p> * * @param authenticate * The authenticate boolean to set. */ public void setAuthenticate(boolean authenticate) { m_authenticate = authenticate; } /** * <p>getFileName</p> * * @return Returns the file name attachment. */ public String getFileName() { return m_fileName; } /** * <p>setFileName</p> * * @param fileName a {@link java.lang.String} object. */ public void setFileName(String fileName) { m_fileName = fileName; } /** * <p>getInputStream</p> * * @return Returns the input stream attachment. */ public InputStream getInputStream() { return m_inputStream; } /** * <p>setInputStream</p> * * @param inputStream * Sets the input stream to be attached to the message. */ public void setInputStream(InputStream inputStream) { m_inputStream = inputStream; } /** * <p>getInputStreamName</p> * * @return Returns the name to use for stream attachments.. */ public String getInputStreamName() { return m_inputStreamName; } /** * <p>setInputStreamName</p> * * @param inputStreamName * Sets the name to use for stream attachments. */ public void setInputStreamName(String inputStreamName) { m_inputStreamName = inputStreamName; } /** * <p>getInputStreamContentType</p> * * @return Returns the name to use for stream attachments.. */ public String getInputStreamContentType() { return m_inputStreamContentType; } /** * <p>setInputStreamContentType</p> * * @param inputStreamContentType a {@link java.lang.String} object. */ public void setInputStreamContentType(String inputStreamContentType) { m_inputStreamContentType = inputStreamContentType; } /** * <p>getMailHost</p> * * @return Returns the mail host. */ public String getMailHost() { return m_mailHost; } /** * <p>setMailHost</p> * * @param mail_host * Sets the mail host. */ public void setMailHost(String mail_host) { m_mailHost = mail_host; } /** * <p>getMailer</p> * * @return Returns the mailer. */ public String getMailer() { return m_mailer; } /** * <p>setMailer</p> * * @param mailer * Sets the mailer. */ public void setMailer(String mailer) { m_mailer = mailer; } /** * <p>getMessageText</p> * * @return Returns the message text. */ public String getMessageText() { return m_messageText; } /** * <p>setMessageText</p> * * @param messageText * Sets the message text. */ public void setMessageText(String messageText) { m_messageText = messageText; } /** * <p>getSubject</p> * * @return Returns the message Subject. */ public String getSubject() { return m_subject; } /** * <p>setSubject</p> * * @param subject * Sets the message Subject. */ public void setSubject(String subject) { m_subject = subject; } /** * <p>getTo</p> * * @return Returns the To address. */ public String getTo() { return m_to; } /** * <p>setTo</p> * * @param to * Sets the To address. */ public void setTo(String to) { m_to = to; } /** * <p>getTransport</p> * * @return a {@link java.lang.String} object. */ public String getTransport() { if (isUseJMTA()) { return "mta"; } else { return m_transport; } } /** * <p>setTransport</p> * * @param transport a {@link java.lang.String} object. */ public void setTransport(String transport) { m_transport = transport; } /** * <p>isDebug</p> * * @return a boolean. */ public boolean isDebug() { return m_debug; } /** * <p>setDebug</p> * * @param debug a boolean. */ public void setDebug(boolean debug) { m_debug = debug; if (isDebug()) { m_session.setDebugOut(new PrintStream(new LoggingByteArrayOutputStream(log()), true)); } m_session.setDebug(isDebug()); } /** * @return log4j Category */ private ThreadCategory log() { return ThreadCategory.getInstance(getClass()); } public static class LoggingByteArrayOutputStream extends ByteArrayOutputStream { private ThreadCategory m_category; public LoggingByteArrayOutputStream(ThreadCategory threadCategory) { m_category = threadCategory; } @Override public void flush() throws IOException { super.flush(); String buffer = toString().replaceAll("\n", ""); if (buffer.length() > 0) { m_category.debug(buffer); } reset(); } } public static class LoggingTransportListener implements TransportListener { private ThreadCategory m_category; private List<Address> m_invalidAddresses = new ArrayList<Address>(); private List<Address> m_validSentAddresses = new ArrayList<Address>(); private List<Address> m_validUnsentAddresses = new ArrayList<Address>(); public LoggingTransportListener(ThreadCategory threadCategory) { m_category = threadCategory; } public void messageDelivered(TransportEvent event) { logEvent("message delivered", event); } public void messageNotDelivered(TransportEvent event) { logEvent("message not delivered", event); } public void messagePartiallyDelivered(TransportEvent event) { logEvent("message partially delivered", event); } private void logEvent(String message, TransportEvent event) { if (event.getInvalidAddresses() != null && event.getInvalidAddresses().length > 0) { m_invalidAddresses.addAll(Arrays.asList(event.getInvalidAddresses())); m_category.error(message + ": invalid addresses: " + StringUtils.arrayToDelimitedString(event.getInvalidAddresses(), ", ")); } if (event.getValidSentAddresses() != null && event.getValidSentAddresses().length > 0) { m_validSentAddresses.addAll(Arrays.asList(event.getValidSentAddresses())); m_category.debug(message + ": valid sent addresses: " + StringUtils.arrayToDelimitedString(event.getValidSentAddresses(), ", ")); } if (event.getValidUnsentAddresses() != null && event.getValidUnsentAddresses().length > 0) { m_validUnsentAddresses.addAll(Arrays.asList(event.getValidUnsentAddresses())); m_category.error(message + ": valid unsent addresses: " + StringUtils.arrayToDelimitedString(event.getValidUnsentAddresses(), ", ")); } } public boolean hasAnythingBeenReceived() { return m_invalidAddresses.size() != 0 || m_validSentAddresses.size() != 0 || m_validUnsentAddresses.size() != 0; } /** * We sleep up to ten times for 10ms, checking to see if anything has * been received because the notifications are done by a separate * thread. We also wait another 50ms after we see the first * notification come in, just to see if anything else trickles in. * This isn't perfect, but it's somewhat of a shot in the dark to * hope that we catch most things, to try to catch as many errors * as possible so we can fairly reliably report if anything had * problems. * * @throws JavaMailerException */ public void assertAllMessagesDelivered() throws JavaMailerException { for (int i = 0; i < 10; i++) { if (hasAnythingBeenReceived()) { break; } try { Thread.sleep(10); } catch (InterruptedException e) { // Do nothing } } try { Thread.sleep(50); } catch (InterruptedException e) { // Do nothing } if (m_invalidAddresses.size() == 0 && m_validUnsentAddresses.size() == 0) { // Nothing failed, so just return return; } throw new JavaMailerException("Not all messages delivered:\n" + "\t" + m_validSentAddresses.size() + " messages were sent to valid addresses: " + StringUtils.collectionToDelimitedString(m_validSentAddresses, ", ") + "\n" + "\t" + m_validUnsentAddresses.size() + " messages were not sent to valid addresses: " + StringUtils.collectionToDelimitedString(m_validUnsentAddresses, ", ") + "\n" + "\t" + m_invalidAddresses.size() + " messages had invalid addresses: " + StringUtils.collectionToDelimitedString(m_invalidAddresses, ", ")); } } /** * <p>getSession</p> * * @return the session */ public Session getSession() { return m_session; } /** * <p>setSession</p> * * @param session the session to set */ public void setSession(Session session) { m_session = session; } /** * <p>getContentType</p> * * @return the contentType */ public String getContentType() { return m_contentType; } /** * <p>setContentType</p> * * @param contentType the contentType to set */ public void setContentType(String contentType) { m_contentType = contentType; } /** * <p>getCharSet</p> * * @return the charSet */ public String getCharSet() { return m_charSet; } /** * <p>setCharSet</p> * * @param charSet the charSet to set */ public void setCharSet(String charSet) { m_charSet = charSet; } /** * <p>getEncoding</p> * * @return the encoding */ public String getEncoding() { return m_encoding; } /** * <p>setEncoding</p> * * @param encoding the encoding to set */ public void setEncoding(String encoding) { m_encoding = encoding; } /** * <p>isStartTlsEnabled</p> * * @return the startTlsEnabled */ public boolean isStartTlsEnabled() { return m_startTlsEnabled; } /** * <p>setStartTlsEnabled</p> * * @param startTlsEnabled the startTlsEnabled to set */ public void setStartTlsEnabled(boolean startTlsEnabled) { m_startTlsEnabled = startTlsEnabled; } /** * <p>isQuitWait</p> * * @return the quitWait */ public boolean isQuitWait() { return m_quitWait; } /** * <p>setQuitWait</p> * * @param quitWait the quitWait to set */ public void setQuitWait(boolean quitWait) { m_quitWait = quitWait; } /** * <p>getSmtpPort</p> * * @return the smtpPort */ public int getSmtpPort() { return m_smtpPort; } /** * <p>setSmtpPort</p> * * @param smtpPort the smtpPort to set */ public void setSmtpPort(int smtpPort) { m_smtpPort = smtpPort; } /** * <p>isSmtpSsl</p> * * @return the smtpSsl */ public boolean isSmtpSsl() { return m_smtpSsl; } /** * <p>setSmtpSsl</p> * * @param smtpSsl the smtpSsl to set */ public void setSmtpSsl(boolean smtpSsl) { m_smtpSsl = smtpSsl; } /** * This returns the properties configured in the javamail-configuration.properties file. * * @return a {@link java.util.Properties} object. */ public Properties getMailProps() { return m_mailProps; } public Map<String,String> getExtraHeaders() { return m_extraHeaders; } public void setExtraHeaders(final Map<String,String> headers) { m_extraHeaders = headers; } public void addExtraHeader(final String key, final String value) { m_extraHeaders.put(key, value); } }