2016年7月19日火曜日

JavaMail と AmazonSESでメールを送る

Amazon の提供するクラウドサービスに Amazon Simple Email Service(Amazon SES)というバルクメール送信サービスがある。SMTPのインターフェースが使えるとのことなので今回 JavaMail を使いJavaプログラムからメールを送信してみた。
Amazon SES を使うためには Amazon Web Service(AWS) のアカウントを持っている必要がある。 (アカウントの取り方は省略する)
EC2をすでに利用していれたので同じアカウントで利用することができた。Amazon SES のためには最低限、以下の設定が必要である。

  1. メールアドレスの登録
    送信元(From)およびテスト用の送信先(To)のメールアドレスの設定および承認をする。
  2. SMTP設定
    SMTPサーバーにアクセスするための認証情報などを設定する。
設定はどちらも Management Console から行う。 現時点でのそれぞれの設定方法は次のようになる。

1. メールアドレスの登録

送信元(From)とするメールアドレスの設定および承認をする。 また、サービス利用直後はsandboxモードというあらかじめ登録されたメールアドレスにしか送れないモードとなっているが、この送信先(To)のメールアドレスも同じように登録する。

メールアドレスは以下の手順で登録する。送信元(From)、送信先(To)のアドレスをそれぞれ登録する。

  1. Management Consoleのメニュー"Email Addresses"を選択
  2. [Verify a New Email Address]を押す。ダイアログボックスに送信元とするメールアドレスを入れる。
  3. 入力したメールアドレスに "Amazon SES Address Verification Request"というメールが来る。その中のリンクをクリック。
  4. 「Amazon Simple Email Service(Amazon SES)でのメールアドレスの検証が完了しました。このアドレスからのメール送信を開始できます。」というページが開く。
  5. 登録完了

2. SMTP設定

SMTPサーバーにアクセスするための認証情報などを設定する。

  1. Management Consoleのメニュー"SMTP Settings"を選択
  2. [Create My SMTP Credentials]を押す
  3. "IAM User Name" を要求される。既定の値をそのまま使い [Create] を押す。
  4. 認証情報が生成される。[Show User SMTP Security Credentials]を押すと以下のような内容が表示される。
ses-smtp-user.xxxx-xxxx
SMTP Username: xxxxxxxxxxxxxxx
SMTP Password: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

SMTP Username と SMTP Password は後で使うのでメモしておく。

ここまでできたらAmazon SESでメール送信することができるすることができる。 早速、JavaMailを使いJavaプログラムからメールを送信してみよう。 SMTPサーバーはポート25か465か587が使えるので、自分の環境にあったものを選べばよいかと思う。 自分のローカルPCから送る場合は、プロバイダの方でポート25を制限していることが多いと思うのでそれ以外を選ぶのがいいだろう。 また、Transport Layer Security (TLS)が必要なのでJavaMailのほうでその設定をする。

以下のサンプルプログラムはAmazon SESのリファレンスガイドに載っていたものとほぼ同じである。 ビルドしてローカルPCで動かすと1で登録したメールアドレスにメールが配信される。

package test;

import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

public class AmazonSESTest {

  // 1で登録したメールアドレス
  static final String FROM = "xxx@xxx.jp";
  static final String TO = "yyy@yyy.jp";

  // 2で作成したSMTP Username/Passwordを設定
  static final String SMTP_USERNAME = "xxxxxxxx";
  static final String SMTP_PASSWORD = "xxxxxxxxxxxxxxxxxx";

  // Amazon SES SMTP ホスト名
  static final String HOST = "email-smtp.us-east-1.amazonaws.com";

  // ポートは25,465または587を指定する
  static final int PORT = 587;

  private static Logger logger = Logger.getLogger(AmazonSESTest.class.getName());

  public static void main(String[] args) {
    try {
      AmazonSESTest app = new AmazonSESTest();
      app.start(args);
    } catch (Throwable ex) {
      logger.log(Level.SEVERE, "エラーが発生: " + ex.toString(), ex);
    }
  }

  private void start(String[] args) throws MessagingException {
    // JavaMailの設定
    Properties props = System.getProperties();
    props.put("mail.transport.protocol", "smtp");
    props.put("mail.smtp.port", PORT);
    
    // JavaMailでTransport Layer Security (TLS)を使う設定
    props.put("mail.smtp.auth", "true");
    props.put("mail.smtp.starttls.enable", "true");
    props.put("mail.smtp.starttls.required", "true");

    // JavaMail Session 作成
    Session session = Session.getDefaultInstance(props);

    // 送信メッセージを作成
    MimeMessage msg = new MimeMessage(session);
    msg.setFrom(new InternetAddress(FROM));
    msg.setRecipient(Message.RecipientType.TO, new InternetAddress(TO));
    msg.setSubject("テストメール", "utf-8");
    msg.setContent("AmazonSESから出したメール", "text/plain;charset=utf-8");

    // メール送信
    Transport transport = session.getTransport();
    try {
      logger.info("Amazon SES SMTP で送信中...");
      transport.connect(HOST, SMTP_USERNAME, SMTP_PASSWORD);
      transport.sendMessage(msg, msg.getAllRecipients());
      logger.info("送信完了");
    } finally {
      // 後始末
      transport.close();
    }
  }

}

最後に、Amazon SESでは個別の申請をしない場合には以下のような利用制限があるようである。 後者はproduction版を申請すれば解除されるようだが、それはまた後日試してみることにする。

  • 送信できるメール数、200メール/日、1メール/秒
  • 登録済みのメールアドレスにしか送信できない(sandboxモード)

0 件のコメント:

コメントを投稿