package io.mangoo.email;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.HtmlEmail;
import org.apache.commons.mail.MultiPartEmail;
import org.apache.commons.mail.SimpleEmail;
import io.mangoo.configuration.Config;
import io.mangoo.core.Application;
import io.mangoo.enums.Default;
import io.mangoo.enums.Required;
import io.mangoo.exceptions.MangooMailerException;
import io.mangoo.exceptions.MangooTemplateEngineException;
import io.mangoo.templating.TemplateEngine;
/**
*
* @author svenkubiak
*
*/
public class Mail {
private static volatile DefaultAuthenticator defaultAuthenticator;
private final Map<String, Object> content = new HashMap<>();
private final List<File> files = new ArrayList<>();
private final List<String> recipients = new ArrayList<>();
private final List<String> ccRecipients = new ArrayList<>();
private final List<String> bccRecipients = new ArrayList<>();
private String template;
private String subject;
private String from;
private String body;
private static volatile String host;
private static int port;
private boolean html;
private boolean attachment;
private static boolean ssl;
public static Mail newMail(){
init();
return new Mail();
}
public static Mail newHtmlMail() {
init();
return new Mail().isHtml();
}
private static void init() {
Config config = Application.getInstance(Config.class);
host = config.getSmtpHost();
port = config.getSmtpPort();
ssl = config.isSmtpSSL();
final String username = config.getSmtpUsername();
final String password = config.getSmtpPassword();
if (StringUtils.isNotBlank(username) && StringUtils.isNotBlank(password)) {
defaultAuthenticator = new DefaultAuthenticator(username, password);
}
}
/**
* Adds a recipient to the mail
*
* @param recipient The mail address of the recipient
* @return A mail object instance
*/
public Mail withRecipient(String recipient) {
Objects.requireNonNull(recipient, Required.RECIPIENT.toString());
this.recipients.add(recipient);
return this;
}
/**
* Adds a cc recipient to the mail
*
* @param recipient The mail address of the cc recipient
* @return A mail object instance
*/
public Mail withCC(String recipient) {
Objects.requireNonNull(recipient, Required.CC_RECIPIENT.toString());
this.ccRecipients.add(recipient);
return this;
}
/**
* Adds a subject to the mail
*
* @param subject The subject of the email
* @return A mail object instance
*/
public Mail withSubject(String subject) {
Objects.requireNonNull(subject, Required.SUBJECT.toString());
this.subject = subject;
return this;
}
/**
* Add a template to the mail which will be rendered before the mail is send
*
* @param template The path to the template fail (e.g. emails/mail.ftl)
* @return A mail object instance
*/
public Mail withTemplate(String template) {
Objects.requireNonNull(template, Required.TEMPLATE.toString());
if (template.charAt(0) == '/' || template.startsWith("\\")) {
this.template = template.substring(1, template.length());
} else {
this.template = template;
}
return this;
}
/**
* @return The current template path
*/
public String getTemplate() {
return this.template;
}
/**
* Adds a bcc recipient to the mail
*
* @param recipient The subject of the email
* @return A mail object instance
*/
public Mail withBCC(String recipient) {
Objects.requireNonNull(recipient, Required.BCC_RECIPIENT.toString());
this.bccRecipients.add(recipient);
return this;
}
/**
* Adds a custom to the mail
*
* This will overwrite rendering of the template!
*
* @param body The body of the email
* @return A mail object instance
*/
public Mail withBody(String body) {
Objects.requireNonNull(body, Required.BODY.toString());
this.body = body;
return this;
}
/**
* Adds the from address to the mail
* @param from The from address, e.g. jon.snow@winterfell.com
* @return A mail object instance
*/
public Mail withFrom(String from) {
Objects.requireNonNull(from, Required.FROM.toString());
this.from = from;
return this;
}
/**
* Adds a file attachment to the mail
*
* @param file The file to add
* @return A mail object instance
*/
public Mail withAttachment(File file) {
Objects.requireNonNull(file, Required.FILE.toString());
this.attachment = true;
this.files.add(file);
return this;
}
/**
* Mark the mail as an HTML mail
*
* @deprecated As of version 4.4.0, will be private in 5.0.0., use {@link #newHtmlMail()} instead.
* @return A mail object instance
*/
@Deprecated
public Mail isHtml() {
this.html = true;
return this;
}
/**
* Adds content to the template which will be rendered
*
* @param key The key
* @param value The value
* @return A mail object instance
*/
public Mail withContent(String key, Object value) {
Objects.requireNonNull(key, Required.KEY.toString());
Objects.requireNonNull(value, Required.VALUE.toString());
content.put(key, value);
return this;
}
/**
* Sends the mail
*
* @throws MangooMailerException when sending the mail failed
*/
public void send() throws MangooMailerException {
Config config = Application.getInstance(Config.class);
if (StringUtils.isBlank(this.from)) {
this.from = config.getSmtpFrom();
}
if (this.html) {
sendHtmlEmail();
} else if (this.attachment) {
sendMultipartEmail();
} else {
sendSimpleEmail();
}
}
private void sendSimpleEmail() throws MangooMailerException {
try {
Email email = new SimpleEmail();
email.setCharset(Default.ENCODING.toString());
email.setHostName(host);
email.setSmtpPort(port);
email.setAuthenticator(defaultAuthenticator);
email.setSSLOnConnect(ssl);
email.setFrom(this.from);
email.setSubject(this.subject);
email.setMsg(render());
for (String recipient : this.recipients) {
email.addTo(recipient);
}
for (String cc : this.ccRecipients) {
email.addCc(cc);
}
for (String bcc : this.bccRecipients) {
email.addBcc(bcc);
}
email.send();
} catch (EmailException | MangooTemplateEngineException e) {
throw new MangooMailerException(e);
}
}
private void sendMultipartEmail() throws MangooMailerException {
try {
MultiPartEmail multiPartEmail = new MultiPartEmail();
multiPartEmail.setCharset(Default.ENCODING.toString());
multiPartEmail.setHostName(host);
multiPartEmail.setSmtpPort(port);
multiPartEmail.setAuthenticator(defaultAuthenticator);
multiPartEmail.setSSLOnConnect(ssl);
multiPartEmail.setFrom(this.from);
multiPartEmail.setSubject(this.subject);
multiPartEmail.setMsg(render());
for (String recipient : this.recipients) {
multiPartEmail.addTo(recipient);
}
for (String cc : this.ccRecipients) {
multiPartEmail.addCc(cc);
}
for (String bcc : this.bccRecipients) {
multiPartEmail.addBcc(bcc);
}
for (File file : this.files) {
multiPartEmail.attach(file);
}
multiPartEmail.send();
} catch (EmailException | MangooTemplateEngineException e) {
throw new MangooMailerException(e);
}
}
private void sendHtmlEmail() throws MangooMailerException {
try {
HtmlEmail htmlEmail = new HtmlEmail();
htmlEmail.setCharset(Default.ENCODING.toString());
htmlEmail.setHostName(host);
htmlEmail.setSmtpPort(port);
htmlEmail.setAuthenticator(defaultAuthenticator);
htmlEmail.setSSLOnConnect(ssl);
htmlEmail.setFrom(this.from);
htmlEmail.setSubject(this.subject);
htmlEmail.setHtmlMsg(render());
for (String recipient : this.recipients) {
htmlEmail.addTo(recipient);
}
for (String cc : this.ccRecipients) {
htmlEmail.addCc(cc);
}
for (String bcc : this.bccRecipients) {
htmlEmail.addBcc(bcc);
}
for (File file : this.files) {
htmlEmail.attach(file);
}
htmlEmail.send();
} catch (EmailException | MangooTemplateEngineException e) {
throw new MangooMailerException(e);
}
}
private String render() throws MangooTemplateEngineException {
return StringUtils.isNotBlank(this.body) ? this.body : Application.getInstance(TemplateEngine.class).render("", this.template, this.content);
}
}