- the wrapper class now takes a Locale, Address (recipient), subject line and template name
- rewrote mailer to use Apache Velocity template engine
- added a lot cool headers for better UTF-8 support in mails
*/
package org.mxchange.jmailee.model.delivery;
+import java.io.StringWriter;
import java.text.MessageFormat;
import java.util.Date;
+import java.util.Properties;
+import javax.mail.Address;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
import org.mxchange.jcoreeelogger.beans.local.logger.Log;
import org.mxchange.jcoreeelogger.beans.local.logger.LoggerBeanLocal;
+import org.mxchange.jmailee.model.delivery.wrapper.WrapableEmailDelivery;
/**
* An email class for sending out mails from templates
@Log
private LoggerBeanLocal loggerBeanLocal;
+ /**
+ * Properties for this mailer
+ * <p>
+ * Valid are: - mailer.errorsto = Email address for "Errors-To" header -
+ * mailer.bouncesto = Email address for "Bounces-To" header (optional, if
+ * not set, errorsto must be set) - mailer.xloop = Email address for
+ * "X-Loop" header (optional, if not set, errorsto must be set)
+ */
+ private Properties properties;
+
+ /**
+ * Template engine
+ */
+ private final VelocityEngine templateEngine;
+
/**
* Default constructor
*/
// Continue to throw
throw new RuntimeException(MessageFormat.format("context.lookup() failed: {0}", ex.getMessage()), ex); //NOI18N
}
+
+ // Init template engine
+ this.templateEngine = new VelocityEngine();
+ this.templateEngine.init();
}
- /**
- * Getter for logger bean
- * <p>
- * @return Local logger bean
- */
- protected LoggerBeanLocal getLoggerBeanLocal () {
- return this.loggerBeanLocal;
+ @Override
+ public VelocityEngine getTemplateEngine () {
+ return this.templateEngine;
}
/**
* @param body Body part
* @param mailSession Corresponding mail session to use
* <p>
- * @throws NamingException If the resource cannot be found
* @throws MessagingException If something happened on message delivery
*/
- protected void sendMail (final String emailAddress, final String subjectLine, final String body, final Session mailSession) throws NamingException, MessagingException {
+ private void sendMail (final Address emailAddress, final String subjectLine, final String body, final Session mailSession) throws MessagingException {
// Get MIME message instance
MimeMessage message = new MimeMessage(mailSession);
// Set subject, recipients and body
message.setSubject(subjectLine);
- message.setRecipients(javax.mail.Message.RecipientType.TO, InternetAddress.parse(emailAddress, true));
+ message.setRecipients(javax.mail.Message.RecipientType.TO, InternetAddress.parse(emailAddress.toString(), true));
message.setSentDate(new Date());
message.setText(body);
+ message.setHeader("MIME-Version", "1.0"); //NOI18N
+ message.setHeader("Content-Type", "text/plain; charset=UTF-8"); //NOI18N
+ message.setHeader("Content-Transfer-Encoding", "8bit"); //NOI18N
+ message.setHeader("Errors-To", this.properties.getProperty("mailer.errorsto")); //NOI18N
+
+ // Is the property "bouncesto" set?
+ if (this.properties.containsKey("mailer.bouncesto")) { //NOI18N
+ // Use this
+ message.setHeader("Bounces-To", this.properties.getProperty("mailer.bouncesto")); //NOI18N
+ } else {
+ // Use "errorsto"
+ message.setHeader("Bounces-To", this.properties.getProperty("mailer.errorsto")); //NOI18N
+ }
+
+ // Is the property "xloop" set?
+ if (this.properties.containsKey("mailer.xloop")) { //NOI18N
+ // Use this
+ message.setHeader("X-Loop", this.properties.getProperty("mailer.xloop")); //NOI18N
+ } else {
+ // Use "errorsto"
+ message.setHeader("X-Loop", this.properties.getProperty("mailer.errorsto")); //NOI18N
+ }
// Directly send email
Transport.send(message);
}
+ /**
+ * Getter for logger bean
+ * <p>
+ * @return Local logger bean
+ */
+ protected LoggerBeanLocal getLoggerBeanLocal () {
+ return this.loggerBeanLocal;
+ }
+
+ /**
+ * Sends given mail template to all addresses found in email wrapper
+ * <p>
+ * @param template Template to send
+ * @param context Velocity context
+ * @param emailWrapper Email wrapper containing recipient and such
+ * @param mailSession Mail session
+ * <p>
+ * @throws MessagingException If something happened on message delivery
+ */
+ protected void sendMailTemplate (final Template template, final VelocityContext context, final WrapableEmailDelivery emailWrapper, final Session mailSession) throws MessagingException {
+ // Log trace message
+ this.getLoggerBeanLocal().logTrace(MessageFormat.format("sendMailTemplate: template={0},emailWrapper={1},mailSession={2} - CALLED!", template, emailWrapper, mailSession)); //NOI18N
+
+ // The parameters must be valid
+ if (null == template) {
+ // Throw NPE
+ throw new NullPointerException("template is null"); //NOI18N
+ } else if (null == emailWrapper) {
+ // Throw NPE
+ throw new NullPointerException("emailWrapper is null"); //NOI18N
+ } else if (emailWrapper.getRecipient() == null) {
+ // Throw NPE again
+ throw new NullPointerException("emailWrapper.recipient is null"); //NOI18N
+ } else if (emailWrapper.getSubjectLine() == null) {
+ // ... and again
+ throw new NullPointerException("emailWrapper.subjectLine is null"); //NOI18N
+ } else if (emailWrapper.getSubjectLine().isEmpty()) {
+ // Is empty
+ throw new IllegalArgumentException("emailWrapper.subjectLine is empty"); //NOI18N
+ } else if (emailWrapper.getTemplateName() == null) {
+ // ... and again
+ throw new NullPointerException("emailWrapper.templateName is null"); //NOI18N
+ } else if (emailWrapper.getTemplateName().isEmpty()) {
+ // Is empty
+ throw new IllegalArgumentException("emailWrapper.templateName is empty"); //NOI18N
+ } else if (emailWrapper.getLocale()== null) {
+ // Throw NPE again
+ throw new NullPointerException("emailWrapper.locale is null"); //NOI18N
+ }
+
+ // Get writer instance
+ StringWriter writer = new StringWriter();
+
+ // Merge template
+ template.merge(context, writer);
+
+ // Get all out and send it
+ this.sendMail(emailWrapper.getRecipient(), emailWrapper.getSubjectLine(), writer.toString(), mailSession);
+ }
+
}
package org.mxchange.jmailee.model.delivery;
import java.io.Serializable;
+import org.apache.velocity.app.VelocityEngine;
/**
* An interface for email delivery classes
*/
public interface DeliverableEmail extends Serializable {
+ /**
+ * Getter for template engine
+ * <p>
+ * @return Template engine
+ */
+ VelocityEngine getTemplateEngine ();
+
}
*/
package org.mxchange.jmailee.model.delivery.wrapper;
+import java.util.Locale;
import java.util.Properties;
+import javax.mail.Address;
/**
* A wrapper class for email delivery.
private static final long serialVersionUID = 518_209_689_877_185_914L;
/**
- * Body of email
+ * Locale instance for language
*/
- private String body;
+ private Locale locale;
/**
* Recipient email address
*/
- private String emailAddress;
+ private Address recipient;
/**
- * (Optional) properties
+ * Subject line
*/
- private Properties[] properties;
+ private String subjectLine;
/**
- * Subject line
+ * Template name
*/
- private String subjectLine;
+ private String templateName;
/**
- * Constructor with email address (recipient), subject line, body and
- * optional properties
- *
- * @param emailAddress Recipient's email address
- * @param subjectLine Subject line
- * @param body Body content
- * @param properties Optional properties to e.g. override from address
+ * Template variables
*/
- public EmailDeliveryWrapper (final String emailAddress, final String subjectLine, final String body, final Properties[] properties) {
- // Check all except properties as they are optional
- if (null == emailAddress) {
- // Throw NPE
- throw new NullPointerException("emailAddress is null"); //NOI18N
- } else if (emailAddress.trim().isEmpty()) {
- // Is empty
- throw new IllegalArgumentException("emailAddress is empty"); //NOI18N
- } else if (null == subjectLine) {
- // Throw NPE
- throw new NullPointerException("subjectLine is null"); //NOI18N
- } else if (subjectLine.trim().isEmpty()) {
- // Is empty
- throw new IllegalArgumentException("subjectLine is empty"); //NOI18N
- } else if (null == body) {
- // Throw NPE
- throw new NullPointerException("body is null"); //NOI18N
- } else if (body.trim().isEmpty()) {
- // Is empty
- throw new IllegalArgumentException("body is empty"); //NOI18N
- }
-
- // Then set all
- this.emailAddress = emailAddress;
- this.subjectLine = subjectLine;
- this.body = body;
- this.properties = properties;
+ private Properties templateVariables;
+
+ @Override
+ public Locale getLocale () {
+ return this.locale;
}
@Override
- public String getBody () {
- return this.body;
+ public void setLocale (final Locale locale) {
+ this.locale = locale;
}
@Override
- public void setBody (final String body) {
- this.body = body;
+ public Address getRecipient () {
+ return this.recipient;
}
@Override
- public String getEmailAddress () {
- return this.emailAddress;
+ public void setRecipient (final Address recipient) {
+ this.recipient = recipient;
}
@Override
- public void setEmailAddress (final String emailAddress) {
- this.emailAddress = emailAddress;
+ public String getSubjectLine () {
+ return this.subjectLine;
}
@Override
- @SuppressWarnings ("ReturnOfCollectionOrArrayField")
- public Properties[] getProperties () {
- return this.properties;
+ public void setSubjectLine (final String subjectLine) {
+ this.subjectLine = subjectLine;
}
@Override
- @SuppressWarnings ("AssignmentToCollectionOrArrayFieldFromParameter")
- public void setProperties (final Properties[] properties) {
- this.properties = properties;
+ public String getTemplateName () {
+ return this.templateName;
}
@Override
- public String getSubjectLine () {
- return this.subjectLine;
+ public void setTemplateName (final String templateName) {
+ this.templateName = templateName;
}
@Override
- public void setSubjectLine (final String subjectLine) {
- this.subjectLine = subjectLine;
+ @SuppressWarnings ("ReturnOfCollectionOrArrayField")
+ public Properties getTemplateVariables () {
+ return this.templateVariables;
+ }
+
+ @Override
+ @SuppressWarnings ("AssignmentToCollectionOrArrayFieldFromParameter")
+ public void setTemplateVariables (final Properties templateVariables) {
+ this.templateVariables = templateVariables;
}
}
package org.mxchange.jmailee.model.delivery.wrapper;
import java.io.Serializable;
+import java.util.Locale;
import java.util.Properties;
+import javax.mail.Address;
/**
* A generic wrapper interface for mail delivery.
public interface WrapableEmailDelivery extends Serializable {
/**
- * Getter for body
+ * Getter fo template name
* <p>
- * @return Body
+ * @return Template name
*/
- String getBody ();
+ String getTemplateName ();
/**
- * Setter for body
+ * Setter fo template name
* <p>
- * @param body Body
+ * @param templateName Template name
*/
- void setBody (final String body);
+ void setTemplateName (final String templateName);
/**
- * Getter for recipient's email address
+ * Getter for recipient email address
* <p>
- * @return Recipient's email address
+ * @return Email address recipient
*/
- String getEmailAddress ();
+ Address getRecipient ();
/**
- * Setter for recipient's email address
+ * Setter for recipient email address
* <p>
- * @param emailAddress Recipient's email address
+ * @param recipient Email address recipient
*/
- void setEmailAddress (final String emailAddress);
+ void setRecipient (final Address recipient);
/**
* Getter for optional properties
* <p>
* @return Optional properties
*/
- Properties[] getProperties ();
+ Properties getTemplateVariables ();
/**
* Setter for optional properties
* <p>
* @param properties Optional properties
*/
- void setProperties (final Properties[] properties);
+ void setTemplateVariables (final Properties properties);
/**
* Getter for subject line
*/
void setSubjectLine (final String subjectLine);
+ /**
+ * Getter for locale
+ * <p>
+ * @return Locale instance
+ */
+ Locale getLocale ();
+
+ /**
+ * Setter for locale
+ * <p>
+ * @param locale Locale instance
+ */
+ void setLocale (final Locale locale);
+
}