システム開発する上でメールの送受信テストは何かと面倒です。できればユニットテストに組み込んで人手のテストは避けたい所だと思います。
JavaでJUnitを使ってテストする場合、SubEtha SMTPのようなライブラリを使うと割と簡単にテストできます。この辺はWEB+DB PRESS Vol.102のJavaの新定石で特集されているので、詳しく知りたい方は手に取ってみてください。
gihyo.jp
プログラミング言語に縛られない良い方法はないのかなと思っていたところ、先日SparkPostのブログでMailSlurpというサービスが紹介されていました。
End-to-endのメールテストを簡単にするサービスで、Web APIを使ってテスト用のinbox作成と受信確認ができます。
実際に試してみたら非常に簡単だったので紹介します。
アカウント作成後、API Keyを取得します。
Web APIでinboxを作成します。
curl -X POST https://api.mailslurp.com/inboxes?apiKey=test
成功するとidと宛先のメールアドレスが返ってきます。
{ "payload":{ "id":"xxxxxx-xxxx-xxxx-xxxx-xxxx", "address":""xxxxxx-xxxx-xxxx-xxxx-xxxx@example.com" }, "message":"" }
上記メアドにメールを送信後した後、idをURLのパスに含めてGETするとinboxで受信したメールを取得できます。
curl https://api.mailslurp.com/inboxes/xxxxxx-xxxx-xxxx-xxxx-xxxx?apiKey=test
レスポンスで返ってくるpayloadはinbox作成時と違って配列形式なので注意してください(気付かずJavaでJSON->Object変換にしばらくハマってました)
{ "payload": [ { "body": "xxxxx", "from": "xxx", "id": "xxxxxx-xxxx-xxxx-xxxx-xxxx", "received": "2018-02-18T14:11:02.688Z", "returnPath": "xxx@examle.com", "subject": "Hello", "to": [ "string" ] } ], "message": "" }
このようにWeb API経由でinboxを作成&受信確認できるので、言語に関わらず簡単に使えます。また、テスト用の宛先が発行されるので誤送信も防げます。
次のコードはJavaでテストした例です。メール送信はSendGrid&JavaMailを使っています。
/** | |
* MailSlurpを利用したメールのEnd-To-Endテスト | |
* | |
* @author kikuta | |
*/ | |
public class MailSlurpTest { | |
private final static String MAILSLURP_API_KEY = "xxx"; | |
private final static String SENDGRID_API_KEY = "xxx"; | |
@Test | |
public void MailEndToEndTest() throws UnirestException, MessagingException, InterruptedException { | |
//MailSlurpにinboxを作成 | |
HttpResponse<PostResponse> postRet = Unirest.post(" https://api.mailslurp.com/inboxes") | |
.queryString("apiKey", MAILSLURP_API_KEY) | |
.asObject(PostResponse.class); | |
//inboxの宛先 | |
String testTo = postRet.getBody().getPayload().getAddress(); | |
//JavaMailからSendGridのSMTPを利用してメール送信 | |
Properties props = new Properties(); | |
props.put("mail.smtp.host", "smtp.sendgrid.net"); | |
props.put("mail.smtp.port", 587); | |
props.put("mail.smtp.auth", true); | |
Session session = Session.getInstance(props, new Authenticator(){ | |
@Override | |
protected PasswordAuthentication getPasswordAuthentication(){ | |
return new PasswordAuthentication("apikey", SENDGRID_API_KEY); | |
} | |
}); | |
session.setDebug(true); | |
Message msg = new MimeMessage(session); | |
msg.setSubject("subject"); | |
msg.setContent("hello", "text/plain"); | |
Address from = new InternetAddress("from@kikutaro.xyz"); | |
msg.setFrom(from); | |
Address to = new InternetAddress(testTo); | |
msg.setRecipient(RecipientType.TO, to); | |
msg.setHeader("X-Mailer", "JavaMail"); | |
//メール送信 | |
Transport.send(msg); | |
//MailSlurpのinbox受信待ちのためにウェイト | |
Thread.sleep(20000); | |
//inboxで受信確認 | |
HttpResponse<GetResponse> getRes = Unirest.get("https://api.mailslurp.com/inboxes/{id}") | |
.routeParam("id", postRet.getBody().getPayload().getId()) | |
.queryString("apiKey", MAILSLURP_API_KEY) | |
.asObject(GetResponse.class); | |
getRes.getBody().getPayload().stream().forEach(p -> { | |
assertThat(p.getSubject(), is("subject")); | |
System.out.println(p.getBody()); | |
}); | |
} | |
} |
inbox作成にwaitが必要で、この時間をどのくらいに定めるか微妙なところですが、非常にお手軽です。実際に動くソースは以下に置きました。