DirectMailでメール送信

Posted on 2020/08/12

ToC

DirectMailの利用設定の記事で設定したDirectMailの続きです。

メール送信者の設定

メールを送信するためにメール送信者(Sender Addresses)を設定します。
2020/8現在、ROSでサポートされていないため、Aliyun CLIで実行を試みましたが、こちらもサポートされていない ようでした。そのため、今回はPythonのスクリプトで実行しました。

元ネタは、OpenAPI Exploreで作成したソースコードを一部改良して作成しました。
RAMで設定したユーザーの AccessKeySecretを利用して実行します。また、SendTypeとしては、 都度送信する機能を利用するためtriggerを指定しています。

# -*- coding: utf-8 -*-
import json
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest

client = AcsClient('<accessKeyId>', '<accessSecret>', region_id='ap-southeast-1')
request = CommonRequest()
request.set_accept_format('json')
request.set_domain('dm.ap-southeast-1.aliyuncs.com')
request.set_method('POST')
request.set_protocol_type('https') # https | http
request.set_version('2015-11-23')
request.set_action_name('CreateMailAddress')

request.add_query_param('RegionId', "ap-southeast-1")
request.add_query_param('AccountName', "sendonly@m.example.tokyo")
request.add_query_param('Sendtype', "trigger")
request.add_query_param('ReplyAddress', "reply@example.net")

response = client.do_action_with_exception(request)
print(json.dumps(json.loads(str(response, encoding = 'utf-8')), indent=2))

これでSender Addressが登録されます。
しかしながら、登録直後だと コンソール画面で見るとReply-To AddressのステータスがVerification failedと なっています。 とくに失敗しているわけではないのですが、まだ未確認なのでこのような表示になっているようです。 そのため、Verify the reply-to address を実行してみましょう。

/posts/2020/08/img/2ae833b2_hue6b13147d657624e60227feaa7cd68e3_10083_450x0_resize_lanczos_3.png

ダイアログが表示されて、Confirmを押すとReply-Toに指定したアドレスに確認のメールが送信されます。 メールの本文中にある確認のリンクをクリックするとReply-Toにアドレスが確認された状態になります。

/posts/2020/08/img/08e455cd_hub2387253e945e7c904cd1bd58eff0f95_28221_500x0_resize_lanczos_3.png

このReply-Toは、APIでメールを送信した際に有効のようです。
SMTPプロトコルでメール送信する際には、メール送信時に設定が必要なようです。

メール送信ポリシー

AccessKeySecretが流出した際のことを考えるとメール送信ユーザーの権限はある程度 制限した状態として運用することが望ましいと考えられます。
RAMのPolicy設定では、メール送信ができる最低限のアクションに絞っておくことでより安全に運用が 可能になると思います。リソースも特定のメールアドレスのみにするような指定をしたかったのですが、 今回はわからず断念しました。

{
  "Version": "1",
  "Statement": [
    {
      "Action": [
        "dm:SingleSendMail"
      ],
      "Resource": [
        "*"
      ],
      "Effect": "Allow"
    }
  ]
}

APIによるメール送信

メール送信者の設定が完了したら、DirectMailを利用してメール送信が可能になります。
メール送信は、それほど難しくありません。Subjectの設定と本文の設定をして送信するだけでメールが 送信されます。

# -*- coding: utf-8 -*-
import json
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest

client = AcsClient('<accessKeyId>', '<accessSecret>', region_id='ap-southeast-1')
request = CommonRequest()
request.set_accept_format('json')
request.set_domain('dm.ap-southeast-1.aliyuncs.com')
request.set_method('POST')
request.set_protocol_type('https') # https | http
request.set_version('2015-11-23')
request.set_action_name('SingleSendMail')

request.add_query_param('RegionId', "ap-southeast-1")
request.add_query_param('AccountName', "sendonly@m.example.tokyo")
request.add_query_param('AddressType', "1")
request.add_query_param('ReplyToAddress', "true")
request.add_query_param('ToAddress', "send-to@example.com")
request.add_query_param('Subject', "はじめてのアリババダイレクトメール from Alibaba DirectMail")
request.add_query_param('TextBody', "はじめてAlibaba Direct Mailでメール送信のテストです。\n届くと良いですね。")

response = client.do_action_with_exception(request)
print(json.dumps(json.loads(str(response, encoding = 'utf-8')), indent=2))

APIのレスポンスは、下記のようなものです。
メール送信のAPIリクエストは、メールの送信先へメール到達、メール不達によらずAPIの実行結果のレスポンスが 戻ってきます。(非同期処理のため、メールの送信結果は別の方法で確認することになります。)

{
  "RequestId": "12345678-ABCD-1234-EFGH-123456789012",
  "EnvId": "17870283366620771794"
}

DirectMailから送信されたメールを確認

DirectMailのAPIで送信したメールをメール受信して内容を確認してみます。 DirectMailで送信したメールのヘッダ情報を見てみると、確かにAlibabaのメールサーバーからメールが送信されて いることがReceivedの部分やX-Mailer: Alimail-Mailagentのあたりからも想像できます。
時刻を見てみるとUTC +0800との表示もあるので、たしかにシンガポールリージョンから送信されているように見えます。
また、X-EnvIdというヘッダが追加されていて、これがAPIのレスポンスで戻ってきたEnvIdとおなじのようですね。

Received: from mail-sgdm-xxx-xxx.aliyun.com (mail-sgdm-xxx-xxx.aliyun.com. [47.88.xxx.xxx])
Reply-To: <reply@example.net>
Received: from chitu-hsf(mailfrom:sendonly@m.example.tokyo fp:ma_xxxxxxxxx)
          by smtp.aliyun-inc.com(127.0.0.1);
          Wed, 12 Aug 2020 14:25:53 +0800

Date: Wed, 12 Aug 2020 14:25:53 +0800

From: <sendonly@m.example.tokyo>
Return-Path: <sendonly@m.example.tokyo>
To: <send-to@example.com>
Reply-To: <reply@example.net>
Message-ID: <12345678-aaaa-bbbb-cccc-012301230123@alibaba.com>

Subject: はじめてのアリババダイレクトメール from Alibaba DirectMail
X-Priority: 3
X-Mailer: Alimail-Mailagent
MIME-Version: 1.0
X-EnvId: 17870283366620771794

送信状況の確認

メールの送信結果は、 コンソール画面のReportingの機能で確認が可能です。
Reporting > Sending Details を参照するとメール送信の結果が一覧で表示されます。 実行時間、宛先、送信結果の一覧が参照できます。

また、API(SenderStatisticsDetailByParam)でも同様に結果を一覧取得できます。 ステータス等の条件での絞り込みもできるようです。ステータスのIDを少し調べてみましたが、下記のようですね。

  • 0: Successful
  • 2: Invalid Mail Address
  • 3: Junk Mail
  • 4: Failed

送信失敗の結果だけを取得してみると下記のようなデータが取得できました。
送信結果のEnvId等は表示されないようなので、厳密に突き合わせして送信の成功や失敗を確認することは 少し難しいかもしれませんが、送信頻度がそれほど高くなければ特に問題にはならないかもしれません。

{
  "RequestId": "12345678-ABCD-EFGH-IJKL-123456789012",
  "data": {
    "mailDetail": [
      {
        "Status": 4,
        "UtcLastUpdateTime": 1597194016,
        "Message": "550  relaying denied by recipient not exist of check_mx_available plugin",
        "LastUpdateTime": "2020-08-12T09:00Z",
        "ToAddress": "error@example.net",
        "AccountName": "sendonly@m.example.tokyo"
      }
    ]
  },
  "NextStart": ""
}

その他にも コンソール画面のDelivery Overview機能では、メール送信結果をグラフで参照できます。 パッと見た目にも、わかりやすくて良い機能ですね。

/posts/2020/08/img/656f7d72_hu539f1734909468ca103ffbfd6309f6d6_58950_700x0_resize_lanczos_3.png

参照