【Java】JavaでEmail ~ JavaMail / TLS ~

■ はじめに

https://dk521123.hatenablog.com/entry/2017/04/28/234103

Amazon SES(Simple Email Service)を使用する場合、
Transport Layer Security(TLS)で送信する必要があるとのことなので、
JavaMailで実装する方法を記録する

【1】JavaMailの設定

* JavaMailのダウンロードなどについては以下の関連記事を参照のこと

JavaでEmail ~ JavaMail / Text ~
https://dk521123.hatenablog.com/entry/2016/07/16/222422

【2】JavaMailで実装する方法

以下のようにすればOK

サンプル

Properties props = new Properties();

props.put("mail.smtp.auth", "true");  
props.put("mail.smtp.starttls.enable", "true");  
props.put("mail.smtp.starttls.required", "true"); 

【3】サンプル

import java.io.UnsupportedEncodingException;
import java.security.InvalidParameterException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
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.internet.MimeUtility;

public class EmailHandler {
  private final static String DEFAULT_TIMEOUT = "10000";
  private final static String DEFAULT_HOST = "localhost";
  private final static String DEFAULT_POST = "25";
  private String fromAddress;
  private List<String> toAddresses;
  private List<String> ccAddresses;
  private List<String> bccAddresses;
  private String mailSubject;
  private String mailBody;
  private String atachmentFilePath;
  private String host;
  private String port;
  private String timeout;
  private boolean isEnabledTransportLayerSecurity;
  private boolean isEnabledSmtpAuthentication;
  private String smtpUsername;
  private String smtpPassword;
  private boolean isOnDebugMode;

  /**
   * Default Contractor.
   */
  public EmailHandler() {
    this.fromAddress = null;
    this.toAddresses = new ArrayList<>();
    this.ccAddresses = new ArrayList<>();
    this.bccAddresses = new ArrayList<>();
    this.mailSubject = null;
    this.mailBody = null;
    this.atachmentFilePath = null;
    this.host = DEFAULT_HOST;
    this.port = DEFAULT_POST;
    this.timeout = DEFAULT_TIMEOUT;
    this.isEnabledTransportLayerSecurity = false;
    this.isEnabledSmtpAuthentication = false;
    this.smtpUsername = null;
    this.smtpPassword = null;
    this.isOnDebugMode = false;
  }

  public void setFromAddress(String fromAddress) {
    this.fromAddress = fromAddress;
  }

  public void setToAddresses(List<String> toAddresses) {
    this.toAddresses = toAddresses;
  }

  public void addToAddress(String toAddress) {
    this.toAddresses.add(toAddress);
  }

  public void setCcAddresses(List<String> ccAddresses) {
    this.ccAddresses = ccAddresses;
  }

  public void addCcAddress(String ccAddress) {
    this.ccAddresses.add(ccAddress);
  }

  public void setBccAddresses(List<String> bccAddresses) {
    this.bccAddresses = bccAddresses;
  }

  public void addBccAddress(String bccAddress) {
    this.bccAddresses.add(bccAddress);
  }

  public void setMailSubject(String mailSubject) {
    this.mailSubject = mailSubject;
  }

  public void setMailBody(String mailBody) {
    this.mailBody = mailBody;
  }

  public void setAtachmentFilePath(String atachmentFilePath) {
    this.atachmentFilePath = atachmentFilePath;
  }

  public void setHost(String host) {
    this.host = host;
  }

  public void setPort(String port) {
    this.port = port;
  }

  public void setOnDebugMode(boolean isOnDebugMode) {
    this.isOnDebugMode = isOnDebugMode;
  }

  public void setEnabledTransportLayerSecurity(boolean isEnabledTransportLayerSecurity) {
    this.isEnabledTransportLayerSecurity = isEnabledTransportLayerSecurity;
  }

  public void setEnabledSmtpAuthentication(boolean isEnabledSmtpAuthentication) {
    this.isEnabledSmtpAuthentication = isEnabledSmtpAuthentication;
  }

  public void setSmtpUsername(String smtpUsername) {
    this.smtpUsername = smtpUsername;
  }

  public void setSmtpPassword(String smtpPassword) {
    this.smtpPassword = smtpPassword;
  }

  public void send() throws MessagingException, UnsupportedEncodingException {
    if (this.toAddresses == null || this.host == null) {
      throw new InvalidParameterException();
    }

    Properties props = new Properties();
    props.put("mail.smtp.host", this.host);
    props.put("mail.smtp.port", this.port);
    props.put("mail.debug", this.isOnDebugMode);
    props.put("mail.smtp.connectiontimeout", this.timeout);
    props.put("mail.smtp.timeout", this.timeout);

    // TLS(Transport Layer Security)
    if (this.isEnabledTransportLayerSecurity) {
      props.put("mail.smtp.starttls.enable", "true");
      props.put("mail.smtp.starttls.required", "true");
    }

    Session session = this.createSession(props);
    Message mimeMessage = new MimeMessage(session);
    mimeMessage.setFrom(this.toInternetAddress(this.fromAddress));

    InternetAddress[] toAddresses = this.toInternetAddresses(this.toAddresses);
    mimeMessage.setRecipients(Message.RecipientType.TO, toAddresses);

    InternetAddress[] ccAddresses = this.toInternetAddresses(this.ccAddresses);
    mimeMessage.setRecipients(Message.RecipientType.CC, ccAddresses);

    InternetAddress[] bccAddresses = this.toInternetAddresses(this.bccAddresses);
    mimeMessage.setRecipients(Message.RecipientType.BCC, bccAddresses);

    mimeMessage.setSubject(this.mailSubject);
    mimeMessage.setSentDate(new Date());

    BodyPart messageBodyPart = new MimeBodyPart();
    messageBodyPart.setText(this.mailBody);
    messageBodyPart.setContent(this.mailBody, "text/html");
    Multipart multipart = new MimeMultipart();
    multipart.addBodyPart(messageBodyPart);

    // 2つ目は画像を添付する
    if (this.atachmentFilePath != null) {
      MimeBodyPart mimeBodyPart = new MimeBodyPart();
      FileDataSource fileDataSource = new FileDataSource(this.atachmentFilePath);
      DataHandler dataHandler = new DataHandler(fileDataSource);
      mimeBodyPart.setDataHandler(dataHandler);
      mimeBodyPart.setFileName(MimeUtility.encodeWord(dataHandler.getName()));
      multipart.addBodyPart(mimeBodyPart);
    }
    mimeMessage.setContent(multipart);

    Transport.send(mimeMessage);
  }

  private Session createSession(Properties props) {
    if (this.isEnabledSmtpAuthentication) {
      props.put("mail.smtp.auth", "true");

      Authenticator authenticator = new javax.mail.Authenticator() {
        protected PasswordAuthentication getPasswordAuthentication() {
          return new PasswordAuthentication(smtpUsername, smtpPassword);
        }
      };
      return Session.getInstance(props, authenticator);
    } else {
      return Session.getInstance(props, null);
    }
  }

  private InternetAddress[] toInternetAddresses(List<String> addresses) throws AddressException {
    InternetAddress[] returnValues = new InternetAddress[addresses.size()];

    int index = 0;
    for (String address : addresses) {
      returnValues[index] = this.toInternetAddress(address);
      index++;
    }

    return returnValues;
  }

  private InternetAddress toInternetAddress(String address) throws AddressException {
    return new InternetAddress(address);
  }

  /**
   * 【使用例】
   * 
   * @param args
   */
  public static void main(String[] args) {
    try {
      EmailHandler email = new EmailHandler();
      email.setPort("587");
      email.setFromAddress("sample@yahoo.com");
      email.addToAddress("to.sample@gmail.com");
      email.addCcAddress("cc.sample@gmail.com");
      email.addBccAddress("bcc.sample@gmail.com");
      email.setMailSubject("test");
      email.setMailBody("body");
      email.setOnDebugMode(true);
      email.setEnabledTransportLayerSecurity(true);
      email.setEnabledSmtpAuthentication(true);
      email.setSmtpUsername("smtp_username");
      email.setSmtpPassword("smtp_password");
      email.send();
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

関連記事

JavaでEmail ~ JavaMail / Text ~
https://dk521123.hatenablog.com/entry/2016/07/16/222422
JavaでEmail ~ JavaMail / 添付ファイル ~
https://dk521123.hatenablog.com/entry/2016/07/17/023459
JavaでEmail ~ SMTP認証 ~
https://dk521123.hatenablog.com/entry/2016/11/07/215251
JavaでEmail ~ SMTP認証 / DIGEST-MD5
https://dk521123.hatenablog.com/entry/2016/12/07/222229
Amazon SES ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2017/04/28/234103

メモ

【Linux】 ダミーSMTPサーバ構築
Email送信に関する単体試験について