/*
* (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Contributors:
* bstefanescu
*/
package org.nuxeo.ecm.automation.core.mail;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
*/
public class Mailer {
private static final Log log = LogFactory.getLog(Mailer.class);
protected Properties config;
protected volatile Session session;
protected Authenticator auth;
/**
* The JNDI session name. If not null JNDI will be used to lookup the default session, otherwise local configuration
* (through {@link #config}) will be used to create a session.
*/
protected final String sessionName;
/**
* Create a mailer that can be configured using the API.
*
* @see #setAuthenticator(Authenticator)
* @see #setCredentials(String, String)
* @see #setServer(String)
*/
public Mailer() {
this(null, new Properties());
}
/**
* Create a mailer that use the given properties to configure the session.
*
* @param config
*/
public Mailer(Properties config) {
this(null, config);
}
/**
* Create a mailer using a session that lookup for the session in JNDI under the given session name.
*
* @param sessionName
*/
public Mailer(String sessionName) {
this(sessionName, new Properties());
}
/**
* Create a mailer using a session that lookup for the session in JNDI under the given session name. If the JNDI
* binding doesn't exists use the given properties to cinfiugure the session.
*
* @param sessionName
* @param config
*/
public Mailer(String sessionName, Properties config) {
this.config = config;
this.sessionName = sessionName;
final String user = config.getProperty("mail.smtp.user");
final String pass = config.getProperty("mail.smtp.password");
if (user != null && pass != null) {
setAuthenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, pass);
}
});
}
}
public void setServer(String host) {
setServer(host, "25", false);
}
public void setServer(String host, boolean ssl) {
setServer(host, ssl ? "465" : "25", ssl);
}
/**
* Set the SMTP server address to use
*
* @param host
* @param port
*/
public void setServer(String host, String port) {
setServer(host, port, false);
}
public void setServer(String host, String port, boolean ssl) {
if (ssl) {
if (port == null) {
port = "465";
}
config.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
config.put("mail.smtp.socketFactory.fallback", "false");
config.put("mail.smtp.socketFactory.port", port);
} else if (port == null) {
port = "25";
}
config.setProperty("mail.smtp.host", host);
config.setProperty("mail.smtp.port", port);
session = null;
}
/**
* Set SMTP credential
*
* @param user
* @param pass
*/
public void setCredentials(final String user, final String pass) {
config.setProperty("mail.smtp.auth", "true");
auth = new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user, pass);
}
};
session = null;
}
public void setAuthenticator(Authenticator auth) {
config.setProperty("mail.smtp.auth", "true");
this.auth = auth;
session = null;
}
public void setDebug(boolean debug) {
config.setProperty("mail.debug", Boolean.toString(debug));
}
public Session getSession() {
if (session == null) {
synchronized (this) {
if (session == null) {
if (sessionName != null) {
try {
InitialContext ic = new InitialContext();
session = (Session) ic.lookup(sessionName);
} catch (NamingException e) {
log.warn("Failed to lookup mail session using JNDI name " + sessionName
+ ". Falling back on local configuration.");
session = Session.getInstance(config, auth);
}
} else {
session = Session.getInstance(config, auth);
}
}
}
}
return session;
}
public Properties getConfiguration() {
return config;
}
public void setConfiguration(Properties config) {
this.config = config;
}
public void loadConfiguration(InputStream in) throws IOException {
config.load(in);
}
public void send(MimeMessage message) throws MessagingException {
Transport.send(message);
}
public Message newMessage() {
return new Message(getSession());
}
/**
* Send a single email.
*/
public void sendEmail(String from, String to, String subject, String body) throws MessagingException {
// Here, no Authenticator argument is used (it is null).
// Authenticators are used to prompt the user for user
// name and password.
MimeMessage message = new MimeMessage(getSession());
// the "from" address may be set in code, or set in the
// config file under "mail.from" ; here, the latter style is used
message.setFrom(new InternetAddress(from));
message.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
message.setText(body);
Transport.send(message);
}
public static class Message extends MimeMessage {
public static enum AS {
FROM, TO, CC, BCC, REPLYTO
}
public Message(Session session) {
super(session);
}
public Message(Session session, InputStream in) throws MessagingException {
super(session, in);
}
public Message addTo(String to) throws MessagingException {
addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(to));
return this;
}
public Message addCc(String cc) throws MessagingException {
addRecipient(javax.mail.Message.RecipientType.CC, new InternetAddress(cc));
return this;
}
public Message addBcc(String bcc) throws MessagingException {
addRecipient(javax.mail.Message.RecipientType.BCC, new InternetAddress(bcc));
return this;
}
public Message addFrom(String from) throws MessagingException {
addFrom(new InternetAddress[] { new InternetAddress(from) });
return this;
}
public void addInfoInMessageHeader(String address, AS as) throws MessagingException {
switch (as) {
case FROM:
addFrom(address);
break;
case TO:
addTo(address);
break;
case CC:
addCc(address);
break;
case BCC:
addBcc(address);
break;
case REPLYTO:
Address[] oldValue = getReplyTo();
Address[] replyToValue;
if (getReplyTo() == null) {
replyToValue = new Address[1];
} else {
replyToValue = new Address[oldValue.length + 1];
}
for (int i = 0; i < oldValue.length; i++) {
replyToValue[i] = oldValue[i];
}
replyToValue[oldValue.length] = new InternetAddress(address);
setReplyTo(replyToValue);
break;
default:
throw new MessagingException("Unknown header info " + as.toString());
}
}
public Message setFrom(String from) throws MessagingException {
setFrom(new InternetAddress(from));
return this;
}
public void send() throws MessagingException {
Transport.send(this);
}
}
}