/*
* Copyright 2011 Blazebit
*/
package com.blazebit.mail.impl;
import com.blazebit.mail.Mail;
import com.blazebit.mail.MailException;
import com.blazebit.mail.MailResource;
import com.blazebit.mail.MailSender;
import com.blazebit.mail.MailTransport;
import com.blazebit.mail.util.MailUtils;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.Message.RecipientType;
import javax.mail.MessagingException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
/**
*
* @author Christian Beikov
* @since 0.1.2
*/
public class SimpleMailSender implements MailSender {
private static final Logger log = Logger.getLogger(SimpleMailSender.class
.getName());
private Session session;
private MailTransport transport;
public SimpleMailSender(Session session) {
this.session = session;
}
public SimpleMailSender(String host, Integer port, String username,
String password) {
this(host, port, username, password, MailTransport.SMTP);
}
public SimpleMailSender(String host, Integer port, String username,
String password, MailTransport transport) {
if (host == null || host.trim().equals("")) {
throw new MailException(MailException.MISSING_HOST);
} else if ((password != null && !password.trim().equals(""))
&& (username == null || username.trim().equals(""))) {
throw new MailException(MailException.MISSING_USERNAME);
}
this.transport = transport;
this.session = createMailSession(host, port, username, password);
}
public Session createMailSession(String host, Integer port,
String username, String password) {
if (transport == null) {
log.warning("MailTransport not set, using plain SMTP strategy instead!");
transport = MailTransport.SMTP;
}
Properties props = transport.getDefaultProperties();
props.put(transport.getHostProperty(), host);
if (port != null) {
props.put(transport.getPortProperty(), String.valueOf(port));
} else if (transport.getDefaultPort() != null) {
props.put(transport.getPortProperty(),
String.valueOf(transport.getDefaultPort()));
}
if (username != null) {
props.put(transport.getUserProperty(), username);
}
if (password != null) {
props.put(transport.getPasswordProperty(), password);
props.put(transport.getAuthentificationProperty(), "true");
return Session.getInstance(props, new SimplePasswordAuthenticator(
username, password));
} else {
return Session.getInstance(props);
}
}
public void setDebug(boolean debug) {
session.setDebug(debug);
}
@Override
public void sendMail(Mail email) throws MailException {
sendMail(email, transport);
}
@Override
public void sendMail(Mail email, MailTransport transport)
throws MailException {
if (MailUtils.validate(email)) {
try {
Message message = prepareMessage(email);
message.saveChanges();
Transport t = session.getTransport(transport.getProtocol());
t.connect();
t.sendMessage(message, message.getAllRecipients());
t.close();
} catch (UnsupportedEncodingException e) {
log.log(Level.SEVERE, e.getMessage(), e);
throw new MailException(String.format(
MailException.INVALID_ENCODING, e.getMessage()));
} catch (MessagingException e) {
log.log(Level.SEVERE, e.getMessage(), e);
throw new MailException(String.format(
MailException.GENERIC_ERROR, e.getMessage()), e);
} finally {
transport.clearTemporaryTrustedHosts();
}
}
}
private Message prepareMessage(Mail email) throws MessagingException,
UnsupportedEncodingException {
MimeMultipart multipartRoot = new MimeMultipart("mixed");
MimeBodyPart contentRelated = new MimeBodyPart();
MimeMultipart multipartRelated = new MimeMultipart("related");
MimeBodyPart contentAlternativeMessages = new MimeBodyPart();
MimeMultipart multipartAlternativeMessages = new MimeMultipart(
"alternative");
multipartRoot.addBodyPart(contentRelated);
contentRelated.setContent(multipartRelated);
multipartRelated.addBodyPart(contentAlternativeMessages);
contentAlternativeMessages.setContent(multipartAlternativeMessages);
Message message = new MimeMessage(session);
message.setSubject(email.getSubject());
message.setFrom(email.getFrom());
setReplyTo(email, message);
setRecipients(email, message);
setTexts(email, multipartAlternativeMessages);
setEmbeddedImages(email, multipartRelated);
setAttachments(email, multipartRoot);
message.setContent(multipartRoot);
setHeaders(email, message);
message.setSentDate(new Date());
return message;
}
private void setRecipients(Mail email, Message message)
throws UnsupportedEncodingException, MessagingException {
for (InternetAddress recipient : email.getTo()) {
message.addRecipient(RecipientType.TO, recipient);
}
for (InternetAddress recipient : email.getBcc()) {
message.addRecipient(RecipientType.BCC, recipient);
}
for (InternetAddress recipient : email.getCc()) {
message.addRecipient(RecipientType.CC, recipient);
}
}
private void setReplyTo(Mail email, Message message)
throws UnsupportedEncodingException, MessagingException {
InternetAddress replyToRecipient = email.getReplyTo();
if (replyToRecipient != null) {
message.setReplyTo(new Address[] { replyToRecipient });
}
}
private void setTexts(Mail email, MimeMultipart multipartAlternativeMessages)
throws MessagingException {
if (email.getText() != null) {
MimeBodyPart messagePart = new MimeBodyPart();
messagePart.setText(email.getText(), "UTF-8");
multipartAlternativeMessages.addBodyPart(messagePart);
}
if (email.getHtml() != null) {
MimeBodyPart messagePartHTML = new MimeBodyPart();
messagePartHTML.setContent(email.getHtml(),
"text/html; charset=\"UTF-8\"");
multipartAlternativeMessages.addBodyPart(messagePartHTML);
}
}
private void setEmbeddedImages(Mail email, MimeMultipart multipartRelated)
throws MessagingException {
for (MailResource embeddedImage : email.getEmbeddedImages()) {
multipartRelated.addBodyPart(getBodyPartFromDatasource(
embeddedImage, Part.INLINE));
}
}
private void setAttachments(Mail email, MimeMultipart multipartRoot)
throws MessagingException {
for (MailResource resource : email.getAttachments()) {
multipartRoot.addBodyPart(getBodyPartFromDatasource(resource,
Part.ATTACHMENT));
}
}
private void setHeaders(Mail email, Message message)
throws UnsupportedEncodingException, MessagingException {
for (Map.Entry<String, String> header : email.getHeaders().entrySet()) {
String headerName = header.getKey();
String headerValue = MimeUtility.encodeText(header.getValue(),
"UTF-8", null);
String foldedHeaderValue = MimeUtility.fold(
headerName.length() + 2, headerValue);
message.addHeader(header.getKey(), foldedHeaderValue);
}
}
private BodyPart getBodyPartFromDatasource(MailResource resource,
String dispositionType) throws MessagingException {
BodyPart attachmentPart = new MimeBodyPart();
DataSource ds = resource.getDataSource();
attachmentPart
.setDataHandler(new DataHandler(resource.getDataSource()));
attachmentPart.setFileName(resource.getName());
attachmentPart.setHeader("Content-Type", ds.getContentType()
+ "; filename=" + ds.getName() + "; name=" + ds.getName());
attachmentPart.setHeader("Content-ID",
String.format("<%s>", ds.getName()));
attachmentPart.setDisposition(dispositionType + "; size=0");
return attachmentPart;
}
}