Customers Mail CloudのWebhookは2種類あります。
- メール受信時
- メール送信時
メール送信時は、送信したメールに対してステータスが変わったタイミングで通知が送られるものです。この記事では添付ファイル付きメールのステータス変更メールを受け取る方法を解説します。
<!—more—>
受け取るWebhookの設定
管理画面にて、受け取るWebhookを設定できます。設定は以下が用意されています。
- Bounces
- bounced(エラーメールを受け取る)
- Deliveries
- queued(キューに入ったタイミング)
- succeeded(送信完了)
- failed(送信失敗)
- deferred(送信延期)
添付ファイル付きメールを受け取る場合には application/json
の指定を外してください。
Javaによる実装
今回はJava + SpringでWebhookを受け取った場合について解説します。 application/json
の場合、Javaでは自動的に定義したJavaクラスで送信されてきたデータを取得できます。
それに対して、今回の application/json
を外した場合には multipart/form-data
で送られてきます。
この場合、 以下のようにデータを受けます。
添付ファイルは attachment1
や attachment2
というパラメータ名で受け取ります。この数は添付ファイルの数によって動的に変わります。十分な数を用意しながら、 required = false
にしておくのが良さそうです。
@RestController public class HelloController { Logger logger = LoggerFactory.getLogger(HelloController.class); @PostMapping(value = "/mails", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE}) @ResponseStatus(code = HttpStatus.OK, value = HttpStatus.OK) public void index( @RequestParam(value = "filter", defaultValue = "", required = true) String filter, @RequestParam(value = "subject", required = true) String subject, @RequestParam(value = "envelope-to", required = true) String envelope_to, @RequestParam(value = "server_composition", required = true) String server_composition, @RequestParam(value = "html", required = true) String html, @RequestParam(value = "text", required = true) String text, @RequestParam(value = "envelope-from", required = true) String envelope_from, @RequestParam(value = "headers", required = true) String headers, @RequestParam(value = "attachment1", required = false) MultipartFile multipartFile1, @RequestParam(value = "attachment2", required = false) MultipartFile multipartFile2 ) { logger.info(filter); logger.info(subject); logger.info(envelope_to); logger.info(server_composition); logger.info(html); logger.info(text); logger.info(envelope_from); logger.info(headers); if (multipartFile1 != null) { logger.info(multipartFile1.getOriginalFilename()); } if (multipartFile2 != null) { logger.info(multipartFile2.getOriginalFilename()); } } }
もちろん、各値はStringなので以下のように値を取れます。
logger.info(subject); // -> メールの件名です
ファイル名も出力されます。
logger.info(multipartFile1.getOriginalFilename()); // 画像1.jpg
メール送信した直後
メール送信を行うと、そのデータがキューに入ります。そして、以下のようなWebhookが送られてきます(データは一部マスキングしています)。
{ "event_type": "deliveries", "server_composition": "pro", "event": '{"deliveries":[{"reason":"","sourceIp":"100.100.100.1","returnPath":"info@return.pro.smtps.jp","created":"2023-01-25 14:03:06","subject":"メールマガジンのテスト","apiData":"","messageId":"<031a32d4-06cd-b1ae-9526-011c0b9f1296@example.com>","from":"info@example.com","to":"user@example.jp","senderIp":"","status":"queued"}]}' }
メール送信完了時
Customers Mail Cloudからメール送信処理が行われると、ステータスが succeeded
になったWebhookが送られてきます。
{ "event_type": "deliveries", "server_composition": "pro", "event": '{"deliveries":[{"reason":"","sourceIp":"","returnPath":"info@return.pro.smtps.jp","created":"2023-01-25 14:03:09","subject":"メールマガジンのテスト","apiData":"","messageId":"<031a32d4-06cd-b1ae-9526-011c0b9f1296@example.com>","from":"info@example.com","to":"user@example.jp","senderIp":"100.100.100.3","status":"succeeded"}]}' }
メール送信失敗時(メールアドレス形式に問題がある場合)
メールアドレスの形式に問題があるなど、送信処理が失敗した場合には以下のようなWebhookが送られてきます。
{ "event_type": "bounces", "server_composition": "pro", "event": '{"bounces":[{"reason":"host unknown","returnPath":"info@return.pro.smtps.jp","created":"2023-01-25 14:05:15","subject":"メールマガジンのテスト","apiData":"","messageId":"<8f902ee7-ae65-8711-48a8-2f708cb14205@example.com>","from":"info@example.com","to":"user@example","status":"1"}]}' }
メール送信失敗時(送信先サーバーからエラーが返ってくる場合)
ユーザーが存在しない、メールボックスがいっぱいなど送信先サーバーからエラーが返ってきた場合には、以下のようなJSONが返ってきます。
{ "event_type": "deliveries", "server_composition": "pro", "event": '{"deliveries":[{"reason":"550 5.1.1 The email account that you tried to reach does not exist. Please try 5.1.1 double-checking the recipient's email address for typos or 5.1.1 unnecessary spaces. Learn more at 5.1.1 <https://support.google.com/mail/?p=NoSuchUser> b197-20020a621bce000000b0058b80756b07si311029pfb.3 - gsmtp (in reply to RCPT TO)","sourceIp":"","returnPath":"info@return.pro.smtps.jp","created":"2023-01-25 14:06:06","subject":"メールマガジンのテスト","apiData":"","messageId":"<9e7e564c-ac83-8cd8-2cb4-b9ff2a9f168d@example.com>","from":"info@example.com","to":"no-user@example.jp","senderIp":"100.100.100.3","status":"failed"}]}' }
エラーとしてのWebhookも送られてきます。上記のものと event_type
が異なるので注意してください。
{ "event_type": "bounces", "server_composition": "pro", "event": '{"bounces":[{"reason":"550 5.1.1 The email account that you tried to reach does not exist. Please try 5.1.1 double-checking the recipient's email address for typos or 5.1.1 unnecessary spaces. Learn more at 5.1.1 <https://support.google.com/mail/?p=NoSuchUser> b197-20020a621bce000000b0058b80756b07si311029pfb.3 - gsmtp (in reply to RCPT TO)","returnPath":"info@return.pro.smtps.jp","created":"2023-01-25 14:06:07","subject":"メールマガジンのテスト","apiData":"","messageId":"<9e7e564c-ac83-8cd8-2cb4-b9ff2a9f168d@example.com>","from":"info@example.com","to":"no-user@example.jp","status":"2"}]}' }
まとめ
Webhookを使うことで、メール送信ステータスの変化に応じて通知を受け取れるようになります。メールと連携したシステムを開発する際に役立つでしょう。
Java + Springの場合、添付ファイルが動的に増減すると処理がちょっと書きづらいかも知れません。とはいえ、あまり大量の添付ファイルを付けることは多くないと思いますので、あらかじめ最大数程度の変数を用意しておけば良さそうです。なお、このWebhookはAPI/SMTP経由どちらでも利用できます。