package org.swellrt.server.box.servlet;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.ResourceBundle;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.tools.ToolManager;
import org.apache.velocity.tools.generic.EscapeTool;
import org.apache.velocity.tools.generic.ResourceTool;
import org.swellrt.server.velocity.CustomResourceTool;
import org.waveprotocol.box.server.authentication.SessionManager;
import org.waveprotocol.box.server.persistence.AccountStore;
import org.waveprotocol.wave.util.logging.Log;
import com.google.inject.Inject;
import com.typesafe.config.Config;
public class EmailSenderImp implements EmailSender, DecoupledTemplates {
private static final Log LOG = Log.get(EmailSenderImp.class);
private AccountStore accountStore;
private String host;
private String from;
private Session mailSession;
private ToolManager manager;
private VelocityEngine ve;
private String velocityPath;
private ClassLoader propertyClassloader;
private boolean isExternalPropertyClassLoader = false;
@Inject
public EmailSenderImp(SessionManager sessionManager, AccountStore accountStore, VelocityEngine ve, Config config) {
this.accountStore = accountStore;
this.ve = ve;
this.velocityPath = config.getString("email.template_path");
this.host = config.getString("email.host");
this.from = config.getString("email.from_email_address");
Properties p = new Properties();
p.put("resource.loader", "file, class");
p.put("file.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.FileResourceLoader");
p.put("file.resource.loader.path", velocityPath);
p.put("class.resource.loader.class",
"org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
ve.init(p);
Properties properties = new Properties();
// Get the default Session object.
mailSession = Session.getDefaultInstance(properties, null);
// Setup mail server
properties.setProperty("mail.smtp.host", host);
properties.setProperty("mail.smtp.from", from);
manager = new ToolManager(false);
manager.setVelocityEngine(ve);
manager.configure("velocity-tools-config.xml");
try {
// based on http://stackoverflow.com/a/15654598/4928558
File file = new File(velocityPath);
if (!file.exists())
throw new IOException("Folder for email template files not found!");
URL[] urls = {file.toURI().toURL()};
propertyClassloader = new URLClassLoader(urls);
isExternalPropertyClassLoader = true;
} catch (IOException e) {
LOG.warning("Loading default email template files"+e.getMessage());
propertyClassloader = getClass().getClassLoader();
isExternalPropertyClassLoader = false;
}
}
@Override
public void send(InternetAddress address, String subject, String htmlBody)
throws AddressException, MessagingException {
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, address);
message.setSubject(subject);
message.setText(htmlBody, "UTF-8", "html");
LOG.info("Sending email:" + "\n Subject: " + subject + "\n Message body: " + htmlBody);
// Send message
Transport.send(message);
}
@Override
public Template getTemplateFromName(String templateName) {
String path =
ve.resourceExists(templateName) ? templateName : CLASSPATH_VELOCITY_PATH + templateName;
return ve.getTemplate(path);
}
@Override
public ResourceBundle getBundleFromName(String messageBundleName, Locale locale) {
if (locale == null) {
locale = Locale.getDefault();
}
return ResourceBundle.getBundle(getDecoupledBundleName(messageBundleName), locale, propertyClassloader);
}
@Override
public String getDecoupledBundleName(String messageBundleName) {
if (!isExternalPropertyClassLoader)
return CLASSPATH_VELOCITY_PATH.replace("/", ".") + messageBundleName;
else
return messageBundleName;
}
@Override
public String getTemplateMessage(Template template, String messageBundleName,
Map<String, Object> params, Locale locale) {
Map<String, Object> ctx = new HashMap<String, Object>();
if (locale == null) {
locale = Locale.getDefault();
}
ctx.put("locale", locale);
ctx.put(ResourceTool.BUNDLES_KEY, getDecoupledBundleName(messageBundleName));
ctx.put(CustomResourceTool.CLASS_LOADER_KEY, propertyClassloader);
Context context = manager.createContext(ctx);
Iterator<Map.Entry<String, Object>> it = params.entrySet().iterator();
while (it.hasNext()) {
Entry<String, Object> p = it.next();
context.put(p.getKey(), p.getValue());
}
context.put("esc", new EscapeTool());
StringWriter sw = new StringWriter();
template.merge(context, sw);
sw.flush();
return sw.toString();
};
}