/* * Copyright (c) JForum Team * All rights reserved. * * Redistribution and use in source and binary forms, * with or without modification, are permitted provided * that the following conditions are met: * * 1) Redistributions of source code must retain the above * copyright notice, this list of conditions and the * following disclaimer. * 2) Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of "Rafael Steil" nor * the names of its contributors may be used to endorse * or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER * IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE * * This file creation date: 03/03/2004 - 20:29:45 * The JForum Project * http://www.jforum.net */ package net.jforum.util.mail; import java.io.StringWriter; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Properties; import javax.mail.Address; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import net.jforum.JForumExecutionContext; import net.jforum.entities.User; import net.jforum.exceptions.MailException; import net.jforum.util.preferences.ConfigKeys; import net.jforum.util.preferences.SystemGlobals; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import freemarker.template.SimpleHash; import freemarker.template.Template; /** * Dispatch emails to the world. * * @author Rafael Steil * @version $Id: Spammer.java,v 1.36 2007/09/20 16:07:08 rafaelsteil Exp $ */ public class Spammer { private static final Logger logger = Logger.getLogger(Spammer.class); private static final int MESSAGE_HTML = 0; private static final int MESSAGE_TEXT = 1; private static int messageFormat; private Session session; private String username; private String password; private Properties mailProps = new Properties(); private MimeMessage message; private List users = new ArrayList(); private String messageId; private String inReplyTo; private boolean needCustomization; private SimpleHash templateParams; private Template template; protected Spammer() throws MailException { boolean ssl = SystemGlobals.getBoolValue(ConfigKeys.MAIL_SMTP_SSL); String hostProperty = this.hostProperty(ssl); String portProperty = this.portProperty(ssl); String authProperty = this.authProperty(ssl); String localhostProperty = this.localhostProperty(ssl); mailProps.put(hostProperty, SystemGlobals.getValue(ConfigKeys.MAIL_SMTP_HOST)); mailProps.put(portProperty, SystemGlobals.getValue(ConfigKeys.MAIL_SMTP_PORT)); String localhost = SystemGlobals.getValue(ConfigKeys.MAIL_SMTP_LOCALHOST); if (!StringUtils.isEmpty(localhost)) { mailProps.put(localhostProperty, localhost); } mailProps.put("mail.mime.address.strict", "false"); mailProps.put("mail.mime.charset", SystemGlobals.getValue(ConfigKeys.MAIL_CHARSET)); mailProps.put(authProperty, SystemGlobals.getValue(ConfigKeys.MAIL_SMTP_AUTH)); username = SystemGlobals.getValue(ConfigKeys.MAIL_SMTP_USERNAME); password = SystemGlobals.getValue(ConfigKeys.MAIL_SMTP_PASSWORD); messageFormat = SystemGlobals.getValue(ConfigKeys.MAIL_MESSSAGE_FORMAT).equals("html") ? MESSAGE_HTML : MESSAGE_TEXT; this.session = Session.getInstance(mailProps); } public boolean dispatchMessages() { try { int sendDelay = SystemGlobals.getIntValue(ConfigKeys.MAIL_SMTP_DELAY); if (SystemGlobals.getBoolValue(ConfigKeys.MAIL_SMTP_AUTH)) { if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) { boolean ssl = SystemGlobals.getBoolValue(ConfigKeys.MAIL_SMTP_SSL); Transport transport = this.session.getTransport(ssl ? "smtps" : "smtp"); try { String host = SystemGlobals.getValue(ConfigKeys.MAIL_SMTP_HOST); transport.connect(host, username, password); if (transport.isConnected()) { for (Iterator userIter = this.users.iterator(); userIter.hasNext(); ) { User user = (User)userIter.next(); if (this.needCustomization) { this.defineUserMessage(user); } Address address = new InternetAddress(user.getEmail()); logger.debug("Sending mail to: " + user.getEmail()); this.message.setRecipient(Message.RecipientType.TO, address); transport.sendMessage(this.message, new Address[] { address }); if (sendDelay > 0) { try { Thread.sleep(sendDelay); } catch (InterruptedException ie) { logger.error("Error while Thread.sleep." + ie, ie); } } } } } catch (Exception e) { throw new MailException(e); } finally { try { transport.close(); } catch (Exception e) {} } } } else { for (Iterator iter = this.users.iterator(); iter.hasNext();) { User user = (User)iter.next(); if (this.needCustomization) { this.defineUserMessage(user); } Address address = new InternetAddress(user.getEmail()); logger.debug("Sending mail to: " + user.getEmail()); this.message.setRecipient(Message.RecipientType.TO,address); Transport.send(this.message, new Address[] { address }); if (sendDelay > 0) { try { Thread.sleep(sendDelay); } catch (InterruptedException ie) { logger.error("Error while Thread.sleep." + ie, ie); } } } } } catch (MessagingException e) { logger.error("Error while dispatching the message." + e, e); } return true; } private void defineUserMessage(User user) { try { this.templateParams.put("user", user); String text = this.processTemplate(); this.defineMessageText(text); } catch (Exception e) { throw new MailException(e); } } /** * Prepares the mail message for sending. * * @param subject the subject of the email * @param messageFile the path to the mail message template * @throws MailException */ protected void prepareMessage(String subject, String messageFile) throws MailException { if (this.messageId != null) { this.message = new IdentifiableMimeMessage(session); ((IdentifiableMimeMessage)this.message).setMessageId(this.messageId); } else { this.message = new MimeMessage(session); } this.templateParams.put("forumName", SystemGlobals.getValue(ConfigKeys.FORUM_NAME)); try { this.message.setSentDate(new Date()); this.message.setFrom(new InternetAddress(SystemGlobals.getValue(ConfigKeys.MAIL_SENDER))); this.message.setSubject(subject, SystemGlobals.getValue(ConfigKeys.MAIL_CHARSET)); if (this.inReplyTo != null) { this.message.addHeader("In-Reply-To", this.inReplyTo); } this.createTemplate(messageFile); this.needCustomization = this.isCustomizationNeeded(); // If we don't need to customize any part of the message, // then build the generic text right now if (!this.needCustomization) { String text = this.processTemplate(); this.defineMessageText(text); } } catch (Exception e) { throw new MailException(e); } } /** * Set the text contents of the email we're sending * @param text the text to set * @throws MessagingException */ private void defineMessageText(String text) throws MessagingException { String charset = SystemGlobals.getValue(ConfigKeys.MAIL_CHARSET); if (messageFormat == MESSAGE_HTML) { this.message.setContent(text.replaceAll("\n", "<br />"), "text/html; charset=" + charset); } else { this.message.setText(text); } } /** * Gets the message text to send in the email. * * @param messageFile The optional message file to load the text. * @return The email message text * @throws Exception */ protected void createTemplate(String messageFile) throws Exception { String templateEncoding = SystemGlobals.getValue(ConfigKeys.MAIL_TEMPLATE_ENCODING); if (StringUtils.isEmpty(templateEncoding)) { this.template = JForumExecutionContext.templateConfig().getTemplate(messageFile); } else { this.template = JForumExecutionContext.templateConfig().getTemplate(messageFile, templateEncoding); } } /** * Merge the template data, creating the final content. * This method should only be called after {@link #createTemplate(String)} * and {@link #setTemplateParams(SimpleHash)} * * @return the generated content * @throws Exception */ protected String processTemplate() throws Exception { StringWriter writer = new StringWriter(); this.template.process(this.templateParams, writer); return writer.toString(); } /** * Set the parameters for the template being processed * @param params the parameters to the template */ protected void setTemplateParams(SimpleHash params) { this.templateParams = params; } /** * Check if we have to send customized emails * @return true if there is a need for customized emails */ private boolean isCustomizationNeeded() { boolean need = false; for (Iterator iter = this.users.iterator(); iter.hasNext(); ) { User user = (User)iter.next(); if (user.notifyText()) { need = true; break; } } return need; } protected void setMessageId(String messageId) { this.messageId = messageId; } protected void setInReplyTo(String inReplyTo) { this.inReplyTo = inReplyTo; } protected void setUsers(List users) { this.users = users; } private String localhostProperty(boolean ssl) { return ssl ? ConfigKeys.MAIL_SMTP_SSL_LOCALHOST : ConfigKeys.MAIL_SMTP_LOCALHOST; } private String authProperty(boolean ssl) { return ssl ? ConfigKeys.MAIL_SMTP_SSL_AUTH : ConfigKeys.MAIL_SMTP_AUTH; } private String portProperty(boolean ssl) { return ssl ? ConfigKeys.MAIL_SMTP_SSL_PORT : ConfigKeys.MAIL_SMTP_PORT; } private String hostProperty(boolean ssl) { return ssl ? ConfigKeys.MAIL_SMTP_SSL_HOST : ConfigKeys.MAIL_SMTP_HOST; } }