LoginSignup
8
9

More than 5 years have passed since last update.

SendGrid+JavaMail+UTF-8でメールを送信する

Last updated at Posted at 2014-11-04

クラウドメールサービスSendGridを使ってJavaからメールを送ってみます。
SendGridを使ってメールを送る方法はいくつかあります。詳しくは公式ブログを参照してください。

  • SMTP
  • Web API
  • マーケティングメール機能

今回はSMTPとX-SMTPAPIを組み合わせて宛先毎に内容の異なるメールを送ってみます。

SMTP

SMTPはWeb APIに比べて細かいメール送信パラメータを指定できるのがメリットですが、それが面倒な場合、デメリットにもなります。今回はUTF-8でメールを送ります。メール送信用ライブラリは定番のJavaMailを使っています。

X-SMTPAPI

名前がSMTPっぽくて紛らわしいですが、X-SMTPAPIはSendGrid独自の拡張ヘッダです。これを利用するとメール送信時にSendGridの様々な機能を使うことができます。今回は、To、Substitutionを利用してメールの件名や本文内の特定のキー文字列を宛先毎に異なる値に置換してメールを送ってみます。

とりあえず送ってみる

以下の手順でサンプルコードをクローン、.envファイル編集、実行してください。
Java 1.8で動作確認していますが1.6くらいでもたぶん動くような気がします。

git clone https://github.com/SendGridJP/sendgrid-smtp-java-example.git
cd sendgrid-smtp-java-example
cp .env.example .env
# .envファイルを編集してください
# src/main/java/com/github/sendgridjp/JavaMailMultipartExample.javaの定数CHARSETとENCODEを下のコードサンプルのように"UTF-8"と"base64"に編集してください
gradle build
./run-multipart.sh

.envファイルの編集

SENDGRID_USERNAME=SendGridユーザ名
SENDGRID_PASSWORD=SendGridパスワード
TOS=hoge@hogehoge.com,fuga@fugafuga.com,piyo@piyopiyo.com,hogera@hogera.com
NAMES=名前1,名前2,名前3,名前4
FROM=you@youremail.com

SENDGRID_USERNAME:SendGridのユーザ名を指定してください。
SENDGRID_PASSWORD:SendGridのパスワードを指定してください。
TOS:宛先をカンマ区切りで指定してください。
NAMES:宛先毎の宛名をカンマ区切りで指定してください。
FROM:送信元アドレスを指定してください。

指定したアドレスにメールは届きましたか?

コード

JavaMailMultipartExample.java
package com.github.sendgridjp;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Path;
import java.nio.file.FileSystems;
import java.nio.file.Files;

import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.Multipart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.mail.internet.MimeUtility;
import javax.mail.internet.InternetAddress;
import javax.mail.util.ByteArrayDataSource;

import com.sendgrid.smtpapi.SMTPAPI;

public class JavaMailMultipartExample {
  // 設定情報
  static final String USERNAME = System.getenv("SENDGRID_USERNAME");
  static final String PASSWORD = System.getenv("SENDGRID_PASSWORD");
  static final String[] TOS    = System.getenv("TOS").split(",");
  static final String[] NAMES  = System.getenv("NAMES").split(",");
  static final String FROM     = System.getenv("FROM");
  static final String CHARSET  = "UTF-8"; // "ISO-2022-JP";
  static final String ENCODE   = "base64"; // "7bit"; // "quoted-printable";

  public static void main(String[] args)
  throws IOException, MessagingException, UnsupportedEncodingException {
    // SMTP接続情報
    Properties props = new Properties();
    props.put("mail.transport.protocol", "smtp");
    props.put("mail.smtp.host", "smtp.sendgrid.net");
    props.put("mail.smtp.port", 587);
    props.put("mail.smtp.auth", "true");
    Authenticator auth = new SMTPAuthenticator();
    Session mailSession = Session.getDefaultInstance(props, auth);
    mailSession.setDebug(true); // console log for debug

    // メッセージの構築
    MimeMessage message = new MimeMessage(mailSession);

    // ダミーの宛先(X-SMTPAPIの宛先が優先される)
    message.addRecipient(Message.RecipientType.TO, new InternetAddress(FROM));

    // From
    message.setFrom(FROM);

    // Subject
    message.setSubject("こんにちはSendGrid", CHARSET);

    // Body
    // Alternative part
    MimeMultipart altPart = new MimeMultipart();
    altPart.setSubType("alternative");
    // Text part
    String body = "こんにちは、nameさん\r\nようこそ〜テキストメールの世界へ!";
    MimeBodyPart textBodyPart = new MimeBodyPart();
    textBodyPart.setText(body, CHARSET, "plain");
    textBodyPart.setHeader("Content-Transfer-Encoding", ENCODE);
    altPart.addBodyPart(textBodyPart);
    // Html part
    String htmlBody =
      "<html>" +
      "<body bgcolor=\"#d9edf7\" style=\"background-color: #d9edf7;\">" +
      "こんにちは、nameさん<br>ようこそ〜HTMLメールの世界へ!<br>" +
      "<img src=\"cid:123@456\">" +
      "</body></html>";
    MimeBodyPart htmlBodyPart = new MimeBodyPart();
    htmlBodyPart.setText(htmlBody, CHARSET, "html");
    htmlBodyPart.setHeader("Content-Transfer-Encoding", ENCODE);
    altPart.addBodyPart(htmlBodyPart);
    // Alternative part
    MimeBodyPart altBodyPart = new MimeBodyPart();
    altBodyPart.setContent(altPart);
    // Attachment part
    MimeBodyPart attachmentPart = getMimeBodyPart(
      "./logo.gif", "logo.gif", "image/gif", "123@456"
    );
    altPart.addBodyPart(attachmentPart);

    message.setContent(altPart);

    // X-SMTPAPIヘッダ
    String smtpapi = createSmtpapi(TOS, NAMES);
    smtpapi = MimeUtility.encodeText(smtpapi);
    message.setHeader("X-SMTPAPI", MimeUtility.fold(76, smtpapi));

    // 送信
    mailSession.getTransport().send(message);
  }

  // FileからMimeBodyPartを生成
  private static MimeBodyPart getMimeBodyPart(
    String path, String name, String type, String cid
  )
  throws IOException, MessagingException, UnsupportedEncodingException {
    MimeBodyPart attachment = new MimeBodyPart();
    byte[] bytes = Files.readAllBytes(FileSystems.getDefault().getPath(path));
    DataSource dataSource = new ByteArrayDataSource(bytes, type);
    DataHandler dataHandler = new DataHandler(dataSource);
    attachment.setDataHandler(dataHandler);
    attachment.setFileName(MimeUtility.encodeWord(name));
    attachment.setContentID("<" + cid + ">");
    attachment.setDisposition(MimeBodyPart.ATTACHMENT);
    return attachment;
  }

  // X-SMTPAPIヘッダに設定する値の生成
  private static String createSmtpapi(String[] tos, String[] names) {
    SMTPAPI smtpapi = new SMTPAPI();
    smtpapi.setTos(tos);
    smtpapi.addSubstitutions("name", names);
    smtpapi.addCategory("category1");
    return smtpapi.rawJsonString();
  }

  // SMTP
  private static class SMTPAuthenticator extends javax.mail.Authenticator {
    public PasswordAuthentication getPasswordAuthentication() {
      return new PasswordAuthentication(USERNAME, PASSWORD);
    }
  }
}
8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9