package org.smartly.packages.mail.impl;
import org.smartly.commons.logging.util.LoggingUtils;
import org.smartly.commons.util.ExceptionUtils;
import org.smartly.commons.util.FormatUtils;
import org.smartly.commons.util.MimeTypeUtils;
import org.smartly.commons.util.StringUtils;
import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import java.io.File;
import java.io.InputStream;
import java.util.*;
import java.util.Map.Entry;
public class RunnablePostman
implements Runnable {
private String _smtpHost;
private int _smtpPort = 25;
private String _from;
private String _to;
private String _subject;
private String _message;
private String _user = null;
private String _password = null;
private boolean _TLS = false;
private String _mailFormat = MimeTypeUtils.getMimeType(".txt");
private boolean _debug = false;
private final List<String> _addresses;
private final List<File> _fileAttachments;
private final Map<String, InputStream> _streamAttachments;
private Exception _exception;
public RunnablePostman() {
_addresses = new ArrayList<String>();
_fileAttachments = new ArrayList<File>();
_streamAttachments = new HashMap<String, InputStream>();
}
@Override
protected void finalize() throws Throwable {
try {
_addresses.clear();
_fileAttachments.clear();
_streamAttachments.clear();
} catch (Exception e) {
}
super.finalize();
}
@Override
public void run() {
try {
this.sendMail();
} catch (Exception e) {
_exception = new Exception(ExceptionUtils.getRealMessage(e), e);
}
}
public Exception getException() {
return _exception;
}
public boolean isTLS() {
return _TLS;
}
public void setTLS(boolean TLS) {
this._TLS = TLS;
}
public boolean isDebug() {
return _debug;
}
public void setDebug(boolean debug) {
this._debug = debug;
}
public String getSmtpHost() {
return _smtpHost;
}
public void setSmtpHost(String value) {
_smtpHost = value;
}
public int getSmtpPort() {
return _smtpPort;
}
public void setSmtpPort(int value) {
_smtpPort = value;
}
public String getFrom() {
return _from;
}
public void setFrom(String value) {
_from = this.checkAddress(value);
}
public String getTo() {
return _to;
}
public void setTo(String value) {
_to = this.checkAddress(value);
}
public String getSubject() {
return _subject;
}
public void setSubject(String value) {
_subject = value;
}
public String getMessage() {
return _message;
}
public void setMessage(String value) {
_message = value;
}
public String getUser() {
return _user;
}
public void setUser(String value) {
_user = value;
}
public String getPassword() {
return _password;
}
public void setPassword(String value) {
_password = value;
}
public String getMailFormat() {
return _mailFormat;
}
public void setMailFormat(final String value) {
_mailFormat = value;
}
public void addAddress(final String address) {
if(StringUtils.hasText(address)){
if (address.indexOf(";") > 0) {
final String[] addresses = address.split(";");
addAddresses(addresses);
} else {
_addresses.add(checkAddress(address));
}
}
}
public void addAddresses(String[] addresses) {
for (final String address : addresses) {
if (null != address && address.length() > 0) {
_addresses.add(checkAddress(address));
}
}
}
public String[] getAddresses() {
return _addresses.toArray(new String[_addresses.size()]);
}
public void clearAddresses() {
_addresses.clear();
}
public void addFileAttachment(final String path) {
_fileAttachments.add(new File(path));
}
public void addFileAttachment(final File file) {
_fileAttachments.add(file);
}
/**
* Add an attachment as output stream.<br>
* In most cases you can take "other content types" to mean file attachments,
* such as Word documents, but for something a bit more interesting,
* for example sending a Java serialized object.<br>
*
* @param name Name
* @param stream InputStream
*/
public void addStreamAttachment(final String name, final InputStream stream) {
try {
_streamAttachments.put(name, stream);
} catch (Throwable ignored) {
}
}
public boolean sendMail() {
try {
// create addresses
if (null != _to && _to.length() > 0) {
final String[] addresses = _to.split(";");
this.addAddresses(addresses);
}
// Create a mail session
final Authenticator auth;
final Properties props = new Properties();
props.put("mail.smtp.host", _smtpHost);
props.put("mail.smtp.port", "" + _smtpPort);
if (null != _user && _user.length() > 0) {
props.put("mail.smtp.auth", "true");
if (this.isTLS()) {
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.ssl.protocols", "SSLv3 TLSv1");
}
auth = new SMTPAuthenticator(_user, _password);
} else {
props.put("mail.smtp.auth", "false");
auth = null;
}
final Session session = Session.getInstance(props, auth);
session.setDebug(isDebug());
final Transport transport = session.getTransport("smtp");
try {
transport.connect();
int count = _addresses.size();
for (int i = 0; i < count; i++) {
final String mailAddress = _addresses.get(i);
final InternetAddress[] addressTo = new InternetAddress[1];
addressTo[0] = new InternetAddress(mailAddress);
final InternetAddress addressFrom = new InternetAddress(_from);
// Construct the message
final Message msg = new MimeMessage(session);
msg.setSentDate(new Date());
msg.setDescription("this is a smartly message");
msg.setFrom(addressFrom);
msg.setReplyTo(new InternetAddress[]{addressFrom});
msg.setRecipients(Message.RecipientType.TO, addressTo);
msg.setSubject(_subject);
//msg.setContent(_message, _mailFormat.toString());
final Multipart mp = this.getMailMultiPart();
msg.setContent(mp);
// Send the message
Transport.send(msg);
}
return true;
} finally {
try {
transport.close();
} catch (MessagingException ex) {
}
}
} catch (Throwable t) {
final String msg = FormatUtils.format("SEND EMAIL ERROR: " +
"'%s' error sending mail: [%s].",
t.getClass().getSimpleName(),
ExceptionUtils.getRealMessage(t));
_exception = new Exception(msg, t);
LoggingUtils.getLogger(this).severe(msg);
}
return false;
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private Multipart getMailMultiPart() throws MessagingException {
// simple body
final MimeBodyPart body = new MimeBodyPart();
body.setContent(_message, _mailFormat);
//msg.setContent(_message, _mailFormat.toString());
// attachments
final MimeBodyPart[] attachments = this.getAttachments();
final Multipart result = new MimeMultipart();
// add body
result.addBodyPart(body);
// add attachments
for (MimeBodyPart part : attachments) {
result.addBodyPart(part);
}
return result;
}
private MimeBodyPart[] getAttachments() throws MessagingException {
final List<MimeBodyPart> result = new ArrayList<MimeBodyPart>();
// file attachments
for (final File file : _fileAttachments) {
final DataHandler dh = new DataHandler(new FileDataSource(file));
final MimeBodyPart part = new MimeBodyPart();
part.setDataHandler(dh);
part.setFileName(file.getName());
result.add(part);
}
// stream attachments
final Set<Entry<String, InputStream>> entries = _streamAttachments.entrySet();
for (final Entry<String, InputStream> entry : entries) {
try {
final String name = entry.getKey();
final InputStream stream = entry.getValue();
final DataHandler dh = new DataHandler(new ByteArrayDataSource(stream, name));
final MimeBodyPart body = new MimeBodyPart();
body.setDataHandler(dh);
result.add(body);
} catch (Throwable t) {
}
}
return result.toArray(new MimeBodyPart[result.size()]);
}
private String checkAddress(final String address) {
final String result = address.replace("[", "<").replace("]", ">");
return result;
}
// ------------------------------------------------------------------------
// e m b e d d e d
// ------------------------------------------------------------------------
/**
* SimpleAuthenticator is used to do simple authentication
* when the SMTP server requires it.
*/
private class SMTPAuthenticator extends Authenticator {
private String _usr = null;
private String _psw = null;
public SMTPAuthenticator(final String user,
final String password) {
_usr = user;
_psw = password;
}
@Override
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(_usr, _psw);
}
}
}