/*
* 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;
}
}