~/home of geeks

MailBuilder

· 940 Wörter · 5 Minute(n) Lesedauer

patterns in nature

Neulich habe ich die Java Mail API benutzt, um Mails zu versenden. Dabei fiel mir auf, dass ein schöner MailBuilder mit fluent API fehlt, auch wenn die MimeMessage und MimeBodyPart Klassen recht komfortabel zu benutzen sind.

Dabei habe ich mich an einige einfache Usecases gehalten. Erstellen von Mails mit

import org.apache.commons.lang.StringUtils;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.internet.AddressException;
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.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static javax.mail.Message.RecipientType;

/**
 * Builder für Mails.
 *
 * @author Serhat Cinar
 */
public class MailBuilder {

    private final Session session;
    private InternetAddress from;
    private String subject;
    private final List<MimeBodyPart> bodyParts = new ArrayList<>();
    private final Map<String, List<String>> headers = new LinkedHashMap<>();
    private final Map<RecipientType, List<InternetAddress>> recipientsByType = new LinkedHashMap<>();
    private String multipartSubtype = "mixed";

    public MailBuilder(Session session) {
        this.session = session;
    }

    public MailBuilder addBodyPart(MimeBodyPart bodyPart) {
        if (bodyPart != null) {
            bodyParts.add(bodyPart);
        }
        return this;
    }

    public MailBuilder addBodyPart(Object content, String contentType) throws MessagingException {
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setContent(content, contentType);
        return addBodyPart(bodyPart);
    }

    public MailBuilder addText(String text, String subType) throws MessagingException {
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setText(text, "UTF-8", subType);
        return addBodyPart(bodyPart);
    }

    public MailBuilder addPlainText(String text) throws MessagingException {
        return addText(text, "plain");
    }

    public MailBuilder addHtml(String html) throws MessagingException {
        return addText(html, "html");
    }

    public MailBuilder addHtmlWithInlineImages(String html, String[] imageContentIds, byte[][] imageData, String contentType) throws MessagingException {
        ByteArrayDataSource[] byteArrayDataSources = new ByteArrayDataSource[imageData.length];
        for (int i = 0; i < byteArrayDataSources.length; i++) {
            byteArrayDataSources[i] = new ByteArrayDataSource(imageData[i], contentType);
        }
        return addHtmlWithInlineImages(html, imageContentIds, byteArrayDataSources);
    }

    public MailBuilder addHtmlWithInlineImages(String html, String[] imageContentIds, File[] imageFiles) throws MessagingException {
        FileDataSource[] fileDataSources = new FileDataSource[imageFiles.length];
        for (int i = 0; i < fileDataSources.length; i++) {
            fileDataSources[i] = new FileDataSource(imageFiles[i]);
        }
        return addHtmlWithInlineImages(html, imageContentIds, fileDataSources);
    }

    public MailBuilder addHtmlWithInlineImages(String html, String[] imageContentIds, DataSource[] imageDataSources) throws MessagingException {
        addHtml(html);
        String contentId = null;
        DataSource dataSource = null;
        MimeBodyPart bodyPart = null;
        for (int i = 0; i < imageContentIds.length; i++) {
            contentId = imageContentIds[i];
            dataSource = imageDataSources[i];
            bodyPart = new MimeBodyPart();
            bodyPart.setDataHandler(new DataHandler(dataSource));
            if (dataSource instanceof FileDataSource) {
                bodyPart.setFileName(((FileDataSource) dataSource).getName());
            }
            bodyPart.setContentID(contentId);
            bodyPart.setDisposition(MimeBodyPart.INLINE);
            addBodyPart(bodyPart);
        }
        multipartSubtype = "related";
        return this;
    }

    public MailBuilder addAttachment(File file) throws MessagingException {
        return addAttachment(new FileDataSource(file), null);
    }

    public MailBuilder addAttachment(byte[] data, String contentType, String filename) throws MessagingException {
        return addAttachment(new ByteArrayDataSource(data, contentType), filename);
    }

    public MailBuilder addAttachment(DataSource dataSource, String filename) throws MessagingException {
        MimeBodyPart bodyPart = new MimeBodyPart();
        bodyPart.setDataHandler(new DataHandler(dataSource));
        bodyPart.addHeader("ContentType", dataSource.getContentType());
        if (filename != null) {
            bodyPart.setFileName(filename);
        } else if (dataSource instanceof FileDataSource) {
            bodyPart.setFileName(((FileDataSource) dataSource).getName());
        }
        bodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
        return addBodyPart(bodyPart);
    }

    public MailBuilder addRecipient(RecipientType recipientType, InternetAddress recipient) {
        if (recipient != null) {
            if (recipientType == null) {
                recipientType = RecipientType.TO;
            }
            List<InternetAddress> recipients = recipientsByType.get(recipientType);
            if (recipients == null) {
                recipients = new ArrayList<>();
                recipientsByType.put(recipientType, recipients);
            }
            recipients.add(recipient);
        }
        return this;
    }

    public MailBuilder addRecipient(RecipientType recipientType, String recipient) throws AddressException {
        if (StringUtils.isNotBlank(recipient)) {
            InternetAddress[] tmpRecipients = InternetAddress.parse(recipient);
            if (tmpRecipients == null || tmpRecipients.length > 0) {
                for (final InternetAddress tmpRecipient : tmpRecipients) {
                    addRecipient(recipientType, tmpRecipient);
                }
            }
        }
        return this;
    }

    public MailBuilder addRecipients(RecipientType recipientType, String... recipients) throws AddressException {
        if (recipients != null) {
            for (String recipient : recipients) {
                addRecipient(recipientType, recipient);
            }
        }
        return this;
    }

    public MailBuilder addRecipients(RecipientType recipientType, InternetAddress... recipients) {
        if (recipients != null) {
            for (InternetAddress recipient : recipients) {
                addRecipient(recipientType, recipient);
            }
        }
        return this;
    }

    public MailBuilder addRecipients(RecipientType recipientType, Collection<String> recipients) throws AddressException {
        if (recipients != null) {
            for (String recipient : recipients) {
                addRecipient(recipientType, recipient);
            }
        }
        return this;
    }

    public MailBuilder addTo(InternetAddress toRecipient) {
        return addRecipient(RecipientType.TO, toRecipient);
    }

    public MailBuilder addTo(String toRecipient) throws AddressException {
        return addRecipient(RecipientType.TO, toRecipient);
    }

    public MailBuilder addTo(String... toRecipients) throws AddressException {
        return addRecipients(RecipientType.TO, toRecipients);
    }

    public MailBuilder addTo(InternetAddress... toRecipients) {
        return addRecipients(RecipientType.TO, toRecipients);
    }

    public MailBuilder addTo(Collection<String> toRecipients) throws AddressException {
        return addRecipients(RecipientType.TO, toRecipients);
    }

    public MailBuilder addCc(InternetAddress toRecipient) {
        return addRecipient(RecipientType.CC, toRecipient);
    }

    public MailBuilder addCc(String toRecipient) throws AddressException {
        return addRecipient(RecipientType.CC, toRecipient);
    }

    public MailBuilder addCc(String... toRecipients) throws AddressException {
        return addRecipients(RecipientType.CC, toRecipients);
    }

    public MailBuilder addCc(InternetAddress... toRecipients) {
        return addRecipients(RecipientType.CC, toRecipients);
    }

    public MailBuilder addCc(Collection<String> toRecipients) throws AddressException {
        return addRecipients(RecipientType.CC, toRecipients);
    }

    public MailBuilder addBcc(InternetAddress toRecipient) {
        return addRecipient(RecipientType.BCC, toRecipient);
    }

    public MailBuilder addBcc(String toRecipient) throws AddressException {
        return addRecipient(RecipientType.BCC, toRecipient);
    }

    public MailBuilder addBcc(String... toRecipients) throws AddressException {
        return addRecipients(RecipientType.BCC, toRecipients);
    }

    public MailBuilder addBcc(InternetAddress... toRecipients) {
        return addRecipients(RecipientType.BCC, toRecipients);
    }

    public MailBuilder addBcc(Collection<String> toRecipients) throws AddressException {
        return addRecipients(RecipientType.BCC, toRecipients);
    }

    public MailBuilder addHeader(String name, String value) {
        if (name != null) {
            List<String> values = headers.get(name);
            if (values == null) {
                values = new ArrayList<>();
                headers.put(name, values);
            }
            values.add(value);
        }
        return this;
    }

    public MailBuilder from(final InternetAddress from) throws AddressException {
        this.from = from;
        return this;
    }

    public MailBuilder from(final String from) throws AddressException {
        return from(new InternetAddress(from));
    }

    public MailBuilder subject(final String subject) {
        this.subject = subject;
        return this;
    }

    public MimeMessage build() throws MessagingException {
        final MimeMessage message = new MimeMessage(session);
        MimeMultipart messageMultipartContent = new MimeMultipart(multipartSubtype);
        message.setContent(messageMultipartContent);
        message.setSubject(subject, "UTF-8");
        if (from == null) {
            throw new IllegalStateException("From was not set.");
        }
        message.setFrom(from);
        if (recipientsByType.isEmpty()) {
            throw new IllegalStateException("No recipients were defined.");
        }
        for (RecipientType recipientType : recipientsByType.keySet()) {
            List<InternetAddress> recipients = recipientsByType.get(recipientType);
            if (recipients != null) {
                message.addRecipients(recipientType, recipients.toArray(new InternetAddress[recipients.size()]));
            }
        }
        for (String headerName : headers.keySet()) {
            List<String> headerValues = headers.get(headerName);
            for (final String headerValue : headerValues) {
                message.addHeader(headerName, headerValue);
            }
        }
        if (bodyParts.isEmpty()) {
            throw new IllegalStateException("No bodyparts were defined.");
        }
        for (MimeBodyPart bodyPart : bodyParts) {
            messageMultipartContent.addBodyPart(bodyPart);
        }
        return message;
    }
}