クラウドメールサービス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:送信元アドレスを指定してください。
指定したアドレスにメールは届きましたか?
コード
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);
}
}
}