Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
play.mvc.Mailer Maven / Gradle / Ivy
package play.mvc;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.mail.*;
import play.Logger;
import play.Play;
import play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesNamesTracer;
import play.classloading.enhancers.LocalvariablesNamesEnhancer.LocalVariablesSupport;
import play.exceptions.MailException;
import play.exceptions.TemplateNotFoundException;
import play.exceptions.UnexpectedException;
import play.libs.Mail;
import play.libs.MimeTypes;
import play.templates.Template;
import play.templates.TemplateLoader;
import play.vfs.VirtualFile;
import javax.activation.DataSource;
import javax.activation.URLDataSource;
import javax.mail.internet.InternetAddress;
import play.libs.F;
import play.libs.F.T4;
/**
* Application mailer support
*/
public class Mailer implements LocalVariablesSupport {
protected static final ThreadLocal> infos = new ThreadLocal<>();
/**
* Set subject of mail, optionally providing formatting arguments
* @param subject plain String or formatted string - interpreted as formatted string only if arguments are provided
* @param args optional arguments for formatting subject
*/
public static void setSubject(String subject, Object... args) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
if (args.length != 0) {
subject = String.format(subject, args);
}
map.put("subject", subject);
infos.set(map);
}
@SuppressWarnings("unchecked")
public static void addRecipient(String... recipients) {
List recipientsParam = Arrays.asList(recipients);
addRecipients(recipientsParam);
}
/**
* @Deprecated use method {{@link #addRecipient(String...)}}
*/
public static void addRecipient(Object... recipients) {
List recipientList = new ArrayList<>(recipients.length);
for (Object recipient : recipients) {
recipientList.add(recipient.toString());
}
addRecipients(recipientList);
}
private static void addRecipients(List recipientsParam) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
List recipientsList = (List) map.get("recipients");
if (recipientsList == null) {
recipientsList = new ArrayList<>();
map.put("recipients", recipientsList);
}
recipientsList.addAll(recipientsParam);
infos.set(map);
}
@SuppressWarnings("unchecked")
public static void addBcc(String... bccs) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
List bccsList = (List) map.get("bccs");
if (bccsList == null) {
bccsList = new ArrayList<>();
map.put("bccs", bccsList);
}
bccsList.addAll(Arrays.asList(bccs));
infos.set(map);
}
@SuppressWarnings("unchecked")
public static void addCc(String... ccs) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
List ccsList = (List) map.get("ccs");
if (ccsList == null) {
ccsList = new ArrayList<>();
map.put("ccs", ccsList);
}
ccsList.addAll(Arrays.asList(ccs));
infos.set(map);
}
@SuppressWarnings("unchecked")
public static void addAttachment(EmailAttachment... attachments) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
List attachmentsList = (List) map.get("attachments");
if (attachmentsList == null) {
attachmentsList = new ArrayList<>();
map.put("attachments", attachmentsList);
}
attachmentsList.addAll(Arrays.asList(attachments));
infos.set(map);
}
@SuppressWarnings("unchecked")
public static void attachDataSource(DataSource dataSource, String name, String description, String disposition) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
List> datasourceList = (List>) map.get("datasources");
if (datasourceList == null) {
datasourceList = new ArrayList<>();
map.put("datasources", datasourceList);
}
datasourceList.add(F.T4(dataSource, name, description, disposition));
infos.set(map);
}
public static void attachDataSource(DataSource dataSource, String name, String description){
attachDataSource(dataSource, name, description, EmailAttachment.ATTACHMENT);
}
public static String attachInlineEmbed(DataSource dataSource, String name) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
InlineImage inlineImage = new InlineImage(dataSource);
Map inlineEmbeds = (Map) map.get("inlineEmbeds");
if (inlineEmbeds == null) {
inlineEmbeds = new HashMap<>();
map.put("inlineEmbeds", inlineEmbeds);
}
inlineEmbeds.put(name, inlineImage);
infos.set(map);
return "cid:" + inlineImage.cid;
}
public static void setContentType(String contentType) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
map.put("contentType", contentType);
infos.set(map);
}
/**
* Can be of the form xxx <[email protected] >
*
* @param from
*/
public static void setFrom(String from) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
map.put("from", from);
infos.set(map);
}
public static void setFrom(InternetAddress from) {
setFrom(from.toString());
}
private static class InlineImage {
/** content id */
private final String cid;
/** DataSource
for the content */
private final DataSource dataSource;
public InlineImage(DataSource dataSource) {
this(null, dataSource);
}
public InlineImage(String cid, DataSource dataSource) {
super();
this.cid = cid != null ? cid : RandomStringUtils.randomAlphabetic(HtmlEmail.CID_LENGTH).toLowerCase();
this.dataSource = dataSource;
}
public String getCid() {
return this.cid;
}
public DataSource getDataSource() {
return this.dataSource;
}
}
private static class VirtualFileDataSource implements DataSource {
private final VirtualFile virtualFile;
public VirtualFileDataSource(VirtualFile virtualFile) {
this.virtualFile = virtualFile;
}
public VirtualFileDataSource(String relativePath) {
this.virtualFile = VirtualFile.fromRelativePath(relativePath);
}
@Override
public String getContentType() {
return MimeTypes.getContentType(this.virtualFile.getName());
}
@Override
public InputStream getInputStream() throws IOException {
return this.virtualFile.inputstream();
}
@Override
public String getName() {
return this.virtualFile.getName();
}
@Override
public OutputStream getOutputStream() throws IOException {
return this.virtualFile.outputstream();
}
public VirtualFile getVirtualFile() {
return this.virtualFile;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof VirtualFileDataSource)) {
return false;
}
VirtualFileDataSource rhs = (VirtualFileDataSource) obj;
return this.virtualFile.equals(rhs.virtualFile);
}
}
@Deprecated
public static String getEmbedddedSrc(String urlString, String name) {
return getEmbeddedSrc(urlString, name);
}
public static String getEmbeddedSrc(String urlString, String name) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
DataSource dataSource;
URL url = null;
VirtualFile img = Play.getVirtualFile(urlString);
if (img == null) {
// Not a local image, check for a distant image
try {
url = new URL(urlString);
} catch (MalformedURLException e1) {
throw new UnexpectedException("Invalid URL '" + urlString + "'", e1);
}
if (name == null || name.isEmpty()) {
String[] parts = url.getPath().split("/");
name = parts[parts.length - 1];
}
if (StringUtils.isEmpty(name)) {
throw new UnexpectedException("name cannot be null or empty");
}
dataSource = url.getProtocol().equals("file") ? new VirtualFileDataSource(
url.getFile()) : new URLDataSource(url);
} else {
dataSource = new VirtualFileDataSource(img);
}
Map inlineEmbeds = (Map) map.get("inlineEmbeds");
// Check if a URLDataSource for this name has already been attached;
// if so, return the cached CID value.
if (inlineEmbeds != null && inlineEmbeds.containsKey(name)) {
InlineImage ii = inlineEmbeds.get(name);
if (ii.getDataSource() instanceof URLDataSource) {
URLDataSource urlDataSource = (URLDataSource) ii
.getDataSource();
// Make sure the supplied URL points to the same thing
// as the one already associated with this name.
// NOTE: Comparing URLs with URL.equals() is a blocking
// operation
// in the case of a network failure therefore we use
// url.toExternalForm().equals() here.
if (url == null || urlDataSource == null || !url.toExternalForm().equals(
urlDataSource.getURL().toExternalForm())) {
throw new UnexpectedException("embedded name '" + name
+ "' is already bound to URL "
+ urlDataSource.getURL()
+ "; existing names cannot be rebound");
}
} else if (!ii.getDataSource().equals(dataSource)) {
throw new UnexpectedException("embedded name '" + name
+ "' is already bound to URL " + dataSource.getName()
+ "; existing names cannot be rebound");
}
return "cid:" + ii.getCid();
}
// Verify that the data source is valid.
try (InputStream is = dataSource.getInputStream()) {
} catch (IOException e) {
throw new UnexpectedException("Invalid URL " + urlString + " for image " + name, e);
}
return attachInlineEmbed(dataSource, name);
}
/**
* Can be of the form xxx <[email protected] >
*
* @param replyTo
*/
public static void setReplyTo(String replyTo) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
map.put("replyTo", replyTo);
infos.set(map);
}
public static void setReplyTo(InternetAddress replyTo) {
setReplyTo(replyTo.toString());
}
public static void setCharset(String bodyCharset) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
map.put("charset", bodyCharset);
infos.set(map);
}
@SuppressWarnings("unchecked")
public static void addHeader(String key, String value) {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
Map headers = (Map) map.get("headers");
if (headers == null) {
headers = new HashMap<>();
}
headers.put(key, value);
map.put("headers", headers);
infos.set(map);
}
public static Future send(Object... args) {
try {
Map map = infos.get();
if (map == null) {
throw new UnexpectedException("Mailer not instrumented ?");
}
// Body character set
String charset = (String) infos.get().get("charset");
// Headers
Map headers = (Map) infos.get().get("headers");
// Subject
String subject = (String) infos.get().get("subject");
String templateName = (String) infos.get().get("method");
if (templateName.startsWith("notifiers.")) {
templateName = templateName.substring("notifiers.".length());
}
if (templateName.startsWith("controllers.")) {
templateName = templateName.substring("controllers.".length());
}
templateName = templateName.substring(0, templateName.indexOf("("));
templateName = templateName.replace(".", "/");
// overrides Template name
if (args.length > 0 && args[0] instanceof String && LocalVariablesNamesTracer.getAllLocalVariableNames(args[0]).isEmpty()) {
templateName = args[0].toString();
}
Map templateHtmlBinding = new HashMap<>();
Map templateTextBinding = new HashMap<>();
for (Object o : args) {
List names = LocalVariablesNamesTracer.getAllLocalVariableNames(o);
for (String name : names) {
templateHtmlBinding.put(name, o);
templateTextBinding.put(name, o);
}
}
// The rule is as follow: If we ask for text/plain, we don't care about the HTML
// If we ask for HTML and there is a text/plain we add it as an alternative.
// If contentType is not specified look at the template available:
// - .txt only -> text/plain
// else
// - -> text/html
String contentType = (String) infos.get().get("contentType");
String bodyHtml = null;
String bodyText = "";
try {
Template templateHtml = TemplateLoader.load(templateName + ".html");
bodyHtml = templateHtml.render(templateHtmlBinding);
} catch (TemplateNotFoundException e) {
if (contentType != null && !contentType.startsWith("text/plain")) {
throw e;
}
}
try {
Template templateText = TemplateLoader.load(templateName + ".txt");
bodyText = templateText.render(templateTextBinding);
} catch (TemplateNotFoundException e) {
if (bodyHtml == null && (contentType == null || contentType.startsWith("text/plain"))) {
throw e;
}
}
// Content type
if (contentType == null) {
if (bodyHtml != null) {
contentType = "text/html";
} else {
contentType = "text/plain";
}
}
// Recipients
List recipientList = (List) infos.get().get("recipients");
// From
String from = (String) infos.get().get("from");
String replyTo = (String) infos.get().get("replyTo");
Email email;
if (infos.get().get("attachments") == null && infos.get().get("datasources") == null && infos.get().get("inlineEmbeds") == null ) {
if (StringUtils.isEmpty(bodyHtml)) {
email = new SimpleEmail();
email.setMsg(bodyText);
} else {
HtmlEmail htmlEmail = new HtmlEmail();
htmlEmail.setHtmlMsg(bodyHtml);
if (!StringUtils.isEmpty(bodyText)) {
htmlEmail.setTextMsg(bodyText);
}
email = htmlEmail;
}
} else {
if (StringUtils.isEmpty(bodyHtml)) {
email = new MultiPartEmail();
email.setMsg(bodyText);
} else {
HtmlEmail htmlEmail = new HtmlEmail();
htmlEmail.setHtmlMsg(bodyHtml);
if (!StringUtils.isEmpty(bodyText)) {
htmlEmail.setTextMsg(bodyText);
}
email = htmlEmail;
Map inlineEmbeds = (Map) infos.get().get("inlineEmbeds");
if (inlineEmbeds != null) {
for (Map.Entry entry : inlineEmbeds.entrySet()) {
htmlEmail.embed(entry.getValue().getDataSource(), entry.getKey(), entry.getValue().getCid());
}
}
}
MultiPartEmail multiPartEmail = (MultiPartEmail) email;
List objectList = (List) infos.get().get("attachments");
if (objectList != null) {
for (EmailAttachment object : objectList) {
multiPartEmail.attach(object);
}
}
// Handle DataSource
List> datasourceList =
(List>) infos.get().get("datasources");
if (datasourceList != null) {
for (T4 ds : datasourceList) {
multiPartEmail.attach(ds._1, ds._2, ds._3, ds._4);
}
}
}
email.setCharset("utf-8");
if (from != null) {
try {
InternetAddress iAddress = new InternetAddress(from);
email.setFrom(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.setFrom(from);
}
}
if (replyTo != null) {
try {
InternetAddress iAddress = new InternetAddress(replyTo);
email.addReplyTo(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addReplyTo(replyTo);
}
}
if (recipientList != null) {
for (String recipient : recipientList) {
try {
InternetAddress iAddress = new InternetAddress(recipient);
email.addTo(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addTo(recipient);
}
}
} else {
throw new MailException("You must specify at least one recipient.");
}
List ccsList = (List) infos.get().get("ccs");
if (ccsList != null) {
for (String cc : ccsList) {
email.addCc(cc);
}
}
List bccsList = (List) infos.get().get("bccs");
if (bccsList != null) {
for (String bcc : bccsList) {
try {
InternetAddress iAddress = new InternetAddress(bcc);
email.addBcc(iAddress.getAddress(), iAddress.getPersonal());
} catch (Exception e) {
email.addBcc(bcc);
}
}
}
if (!StringUtils.isEmpty(charset)) {
email.setCharset(charset);
}
email.setSubject(subject);
email.updateContentType(contentType);
if (headers != null) {
for (String key : headers.keySet()) {
email.addHeader(key, headers.get(key));
}
}
return Mail.send(email);
} catch (EmailException ex) {
throw new MailException("Cannot send email", ex);
}
}
public static boolean sendAndWait(Object... args) {
try {
Future result = send(args);
return result.get();
} catch (InterruptedException | ExecutionException e) {
Logger.error(e, "Error while waiting Mail.send result");
}
return false;
}
}