SES で Raw Message からメール送信する

Amazon SES でメール送信をする場合、ヘッダーなどの細かい情報に調整を入れて送信を行いたい場合 Raw Message を利用します。以下は日本語の文字化けを起こさないようにした MimeMessage のラッパークラスです。

public class JISMimeMessage {

  protected MimeMessage delegate = null;

  public JISMimeMessage() {
    this(Session.getInstance(new Properties(), null));
  }

  /**
   * 
   * @param session
   */
  public JISMimeMessage(Session session) {
    delegate = new MimeMessage(session);
  }

  /**
   * 
   * @param from
   * @throws MessagingException
   */
  public void setFrom(String from) throws MessagingException {
    delegate.setFrom(new InternetAddress(from));
  }

  /**
   * 
   * @param name
   * @param from
   * @throws MessagingException
   */
  public void setFrom(String name, String from) throws MessagingException {
    String source = from;
    try {
      source = SES.encodeSource(name, from);
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException(e);
    }
    delegate.setFrom(new InternetAddress(source));
  }

  /**
   * 
   * @param recipientType
   * @param recipients
   * @throws MessagingException
   */
  public void setRecipients(RecipientType recipientType, String... recipients)
      throws MessagingException {
    if (recipients == null) {
      return;
    }
    int size = recipients.length;
    InternetAddress[] address = new InternetAddress[recipients.length];
    for (int i = 0; i < size; i++) {
      try {
        address[i] = getInternetAddress(recipients[i]);
      } catch (UnsupportedEncodingException e) {
        throw new RuntimeException(e);
      }
    }
    delegate.setRecipients(recipientType, address);
  }

  /**
   * 
   * @param subject
   * @throws MessagingException
   */
  public void setSubject(String subject) throws MessagingException {
    delegate.setSubject(subject, "ISO-2022-JP");
  }

  /**
   * 
   * @param text
   * @throws MessagingException
   */
  public void setTextContent(String text) throws MessagingException {
    delegate.setText(text, "ISO-2022-JP");
    delegate.setHeader("Content-Transfer-Encoding", "7bit");
  }

  /**
   * 
   * @return
   */
  public RawMessage getRawMessage() {
    RawMessage data = new RawMessage();
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    try {
      delegate.writeTo(out);
      data.setData(ByteBuffer.wrap(out.toString().getBytes()));
    } catch (Throwable t) {
      throw new RuntimeException(t);
    } finally {
      if (out != null) {
        try {
          out.close();
        } catch (Throwable ignore) {
          // ignore
        }
      }
    }
    return data;
  }

  /**
   * 
   * @param addr
   * @return
   * @throws AddressException
   * @throws UnsupportedEncodingException
   */
  protected InternetAddress getInternetAddress(String addr)
      throws AddressException, UnsupportedEncodingException {
    InternetAddress address = null;
    StringTokenizer st = new StringTokenizer(addr, "<>");
    int count = st.countTokens();
    if (count <= 0) {
      return null;
    } else if (count == 1) {
      address = new InternetAddress(st.nextToken().trim());
    } else if (count == 2) {
      String name = st.nextToken().trim();
      String addressStr = st.nextToken().trim();
      address = new InternetAddress(addressStr, SES.encodeWordJIS(name));
    }
    return address;
  }

  protected String encodeSource(String name, String email)
      throws UnsupportedEncodingException {
    return encodeWordJIS(name) + " <" + email + ">";
  }

  protected String encodeWordJIS(String s) {
    try {
      return "=?ISO-2022-JP?B?"
        + new String(Base64.encodeBase64(s.getBytes("ISO-2022-JP")))
        + "?=";
    } catch (UnsupportedEncodingException e) {
      throw new RuntimeException("CANT HAPPEN");
    }
  }
}

利用方法は以下のようになります。

    AmazonSimpleEmailService ses =
      new AmazonSimpleEmailServiceClient(new BasicAWSCredentials(
        "*******************",
        "******************************"));

    JISMimeMessage message = new JISMimeMessage();
    message.setFrom("name", "sample@xxx.com");
    message.setRecipients(RecipientType.TO, "sample2@xxx.com");
    message.setSubject("Title");
    message.setTextContent("Body");
    ses.sendRawEmail(new SendRawEmailRequest(message.getRawMessage()));