/*
* Copyright 2001-2008 Uwyn bvba/sprl <info[remove] at uwyn dot com>
* Distributed under the terms of the GNU General Public License, v2 or later
* $Id: DatabaseMailQueueExecutor.java 3918 2008-04-14 17:35:35Z gbevin $
*/
package com.uwyn.rife.mail.executors;
import com.uwyn.rife.database.Datasource;
import com.uwyn.rife.database.Datasources;
import com.uwyn.rife.database.DbBeanFetcher;
import com.uwyn.rife.database.DbQueryManager;
import com.uwyn.rife.database.queries.Update;
import com.uwyn.rife.database.querymanagers.generic.GenericQueryManager;
import com.uwyn.rife.database.querymanagers.generic.GenericQueryManagerFactory;
import com.uwyn.rife.mail.Email;
import com.uwyn.rife.mail.MailQueueExecutor;
import com.uwyn.rife.scheduler.Executor;
import com.uwyn.rife.scheduler.Task;
import com.uwyn.rife.scheduler.exceptions.SchedulerException;
import com.uwyn.rife.tools.Base64;
import com.uwyn.rife.tools.ExceptionUtils;
import com.uwyn.rife.tools.StringUtils;
import java.io.ByteArrayInputStream;
import java.util.Collection;
import java.util.Date;
import java.util.Properties;
import java.util.logging.Logger;
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;
public class DatabaseMailQueueExecutor extends Executor implements MailQueueExecutor
{
private final static Object RUNNING_MONITOR = new Object();
private static boolean sRunning = false;
private String mMailqueueName = "";
public boolean isDeliveryAllowed(Email email)
{
return true;
}
public boolean executeTask(Task task)
{
// obtain the mail queue name
try
{
mMailqueueName = task.getTaskoptionValue("name");
}
catch (SchedulerException e)
{
mMailqueueName = null;
}
if (null == mMailqueueName)
{
mMailqueueName = "";
}
else
{
mMailqueueName += " : ";
}
Logger.getLogger("com.uwyn.rife.mail").finest(mMailqueueName+"Running MailQueueExecutor.");
// obtain the datasource name
String datasource_name = null;
try
{
datasource_name = task.getTaskoptionValue("datasource");
}
catch (SchedulerException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'datasource' task option value.\n"+ExceptionUtils.getExceptionStackTrace(e));
}
if (null == datasource_name)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Missing 'datasource' task option for the MailQueueExecutor.");
return false;
}
// obtain the smtp server name
String smtp_server = null;
try
{
smtp_server = task.getTaskoptionValue("smtp_server");
}
catch (SchedulerException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'smtp_server' task option value.\n"+ExceptionUtils.getExceptionStackTrace(e));
return false;
}
// obtain the smtp ssl
boolean smtp_ssl = false;
try
{
smtp_ssl = StringUtils.convertToBoolean(task.getTaskoptionValue("smtp_ssl"));
}
catch (SchedulerException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'smtp_ssl' task option value.\n"+ExceptionUtils.getExceptionStackTrace(e));
}
// obtain the smtp server port
String smtp_port = null;
try
{
smtp_port = task.getTaskoptionValue("smtp_port");
}
catch (SchedulerException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'smtp_port' task option value, using the default value.\n"+ExceptionUtils.getExceptionStackTrace(e));
}
if (null == smtp_port)
{
if (smtp_ssl)
{
smtp_port = "465";
}
else
{
smtp_port = "25";
}
}
// obtain the smtp username
// obtain the smtp password
// obtained together, because they must both be provided to be valid
String smtp_username = null;
String smtp_password = null;
try
{
smtp_username = task.getTaskoptionValue("smtp_username");
}
catch (SchedulerException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'smtp_username' task option value.\n"+ExceptionUtils.getExceptionStackTrace(e));
return false;
}
try
{
smtp_password = task.getTaskoptionValue("smtp_password");
}
catch (SchedulerException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'smtp_password' task option value.\n"+ExceptionUtils.getExceptionStackTrace(e));
return false;
}
if ((smtp_username != null || smtp_password != null) &&
(null == smtp_username || null == smtp_password))
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'smtp_username' and 'smtp_password' task option values, they must be provided together.\n");
return false;
}
Datasource datasource = Datasources.getRepInstance().getDatasource(datasource_name);
if (null == datasource)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error: the MailQueueExecutor's datasource '"+datasource+"' could not be found.");
return false;
}
String smtp_from = null;
try
{
smtp_from = task.getTaskoptionValue("smtp_from");
}
catch (SchedulerException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while obtaining the MailQueueExecutor's 'smtp_from' task option value.\n"+ExceptionUtils.getExceptionStackTrace(e));
return false;
}
GenericQueryManager<Email> emails = GenericQueryManagerFactory.getInstance(datasource, Email.class);
synchronized (RUNNING_MONITOR)
{
if (!sRunning)
{
Logger.getLogger("com.uwyn.rife.mail").finest(mMailqueueName+"MailQueueExecutor not currently running, starting a new one.");
// not currrently running, start a new run
sRunning = true;
try
{
// flag messages for sending
Update flag_messages = new Update(datasource)
.table(emails.getTable())
.field("queueFlag", true);
new DbQueryManager(datasource).executeUpdate(flag_messages);
Logger.getLogger("com.uwyn.rife.mail").finest(mMailqueueName+"MailQueueExecutor's flags set, starting processing.");
Session session = null;
// connect to the SMTP server
if (smtp_server != null && smtp_server.length() > 0)
{
Properties props = new Properties();
props.put("mail.transport", "smtp");
props.put("mail.host", smtp_server);
props.put("mail.port", smtp_port);
props.put("mail.smtp.host", smtp_server);
props.put("mail.smtp.port", smtp_port);
if (smtp_username != null && smtp_password != null)
{
if (smtp_ssl)
{
props.put("mail.smtps.auth", "true");
}
else
{
props.put("mail.smtp.auth", "true");
}
}
if (smtp_from != null)
{
props.put("mail.smtp.from", smtp_from);
}
session = Session.getDefaultInstance(props, null);
}
// send the flagged messages
SendEmails send_emails = new SendEmails(datasource, session, emails, smtp_server, Integer.parseInt(smtp_port), smtp_username, smtp_password, smtp_ssl);
emails.restore(emails.getRestoreQuery()
.where("queueFlag", "=", true), send_emails);
Logger.getLogger("com.uwyn.rife.mail").info(String.valueOf(mMailqueueName)+send_emails.getCount()+" mails were sent");
}
finally
{
sRunning = false;
}
}
else
{
Logger.getLogger("com.uwyn.rife.mail").finest(mMailqueueName+"MailQueueExecutor is currently RUNNING, not running another");
}
}
Logger.getLogger("com.uwyn.rife.mail").finest(mMailqueueName+"MailQueueExecutor run finished.");
return true;
}
public String getHandledTasktype()
{
return "MailQueue";
}
class SendEmails extends DbBeanFetcher<Email>
{
private Session mSession = null;
private GenericQueryManager<Email> mEmailManager = null;
private int mCount = 0;
private String mHost = null;
private int mPort = 0;
private String mUsername = null;
private String mPassword = null;
private boolean mSsl = false;
SendEmails(Datasource datasource, Session session, GenericQueryManager<Email> emails, String host, int port, String username, String password, boolean ssl)
{
super(datasource, Email.class);
mSession = session;
mEmailManager = emails;
mHost = host;
mPort = port;
mUsername = username;
mPassword = password;
mSsl = ssl;
}
int getCount()
{
return mCount;
}
public boolean gotBeanInstance(Email email)
{
if (null == mSession)
{
Logger.getLogger("com.uwyn.rife.mail").warning(mMailqueueName+"Email not sent since no 'smtp_server' task option has not been provided to the MailQueueExecutor.\n"+email.toString());
return false;
}
if (!isDeliveryAllowed(email))
{
return false;
}
MimeMessage message;
try
{
// try to detect if a raw javamail message has been queued
if (email.getFromAddress().equals(MimeMessage.class.getName()) &&
email.getToAddresses().equals(MimeMessage.class.getName()) &&
email.getSubject().equals(MimeMessage.class.getName()))
{
ByteArrayInputStream in = new ByteArrayInputStream(Base64.decode(email.getBody()));
message = new MimeMessage(mSession, in);
}
else
{
message = new MimeMessage(mSession);
// build the mail message
message.setFrom(new InternetAddress(email.getFromAddress(), false));
message.setSubject(email.getSubject());
message.setText(email.getBody(), "UTF-8");
message.setSentDate(new Date());
int to_count = 0;
Collection<String> to_list = StringUtils.split(email.getToAddresses(), ",");
InternetAddress[] to_array = new InternetAddress[to_list.size()];
for (String to : to_list)
{
to_array[to_count++] = new InternetAddress(to, false);
}
message.setRecipients(Message.RecipientType.TO, to_array);
int cc_count = 0;
Collection<String> cc_list = StringUtils.split(email.getCcAddresses(), ",");
InternetAddress[] cc_array = new InternetAddress[cc_list.size()];
for (String cc : cc_list)
{
cc_array[cc_count++] = new InternetAddress(cc, false);
}
message.setRecipients(Message.RecipientType.CC, cc_array);
int bcc_count = 0;
Collection<String> bcc_list = StringUtils.split(email.getBccAddresses(), ",");
InternetAddress[] bcc_array = new InternetAddress[bcc_list.size()];
for (String bcc : bcc_list)
{
bcc_array[bcc_count++] = new InternetAddress(bcc, false);
}
message.setRecipients(Message.RecipientType.BCC, bcc_array);
}
}
catch (MessagingException e)
{
message = null;
Logger.getLogger("com.uwyn.rife.mail").warning(mMailqueueName+"Email not sent due to an error while building the message.\n"+email.toString()+"\n"+ExceptionUtils.getExceptionStackTrace(e));
}
// send the mail
if (message != null)
{
try
{
if (mUsername != null && mPassword != null)
{
Transport transport = mSession.getTransport(mSsl ? "smtps" : "smtp");
transport.connect(mHost, mPort, mUsername, mPassword);
message.saveChanges();
transport.sendMessage(message, message.getAllRecipients());
}
else
{
Transport.send(message);
}
// removed the message
mEmailManager.delete(email.getId());
mCount++;
try
{
Thread.sleep(300);
if (0 == (mCount % 100))
{
Thread.sleep(10000);
}
}
catch (InterruptedException e3)
{
// do nothing
}
}
catch (MessagingException e)
{
Logger.getLogger("com.uwyn.rife.mail").severe(mMailqueueName+"Unexpected error while sending the MailQueueExecutor's email message \n"+email.toString()+"\n"+ExceptionUtils.getExceptionStackTrace(e));
}
}
return true;
}
}
}