なんかいろいろと書いてくブログ

関東のどこかで働く、一般人

Azure Communication Serviceのメール配信について

2023年4月にAzure Communication Service(ACS)がGAとなりました

techcommunity.microsoft.com ACSはEmailをはじめとして、複数のコミュニケーションに必要なツールを統合したAPIを提供しています(SMS等)

ACSはGAしてまだ時間がたっておらず(2023年6月時点)、
機能としてはまだ出そろっていない印象なのですがAzureの機能としてメールが送れるというのはありがたく

以前まではメール送信はSendGridをはじめとしたAzureの外に存在するAPIを使用するしかなかったですが
ACSの提供によりメール送信をAzureの外で完結することができ、
請求をサブスクリプションでまとめたり
ログをApplication Insightsに統合することができそうです

実装周り

Azure

公式ドキュメントにチュートリアルが展開されており 実際にACSからメールを送信するには、Email Communication Servicesのリソースを作成する必要があるが、 以下の3つを順にやっていけばAzure側の設定は完了する(はず) ※ カスタムドメイン設定はEmail Communication Servicesの設定する過程でAzureから無料のドメインの提供があるので技術検証目的としては不要

また、有識者による記事もあるのでこれらは非常に参考になる

Azure 設定でEmail Communication Servicesにjapanがあるが、ACSにjapanが選べないのは罠だった
(両者は同じローケーションにいる必要があるので、Asia Pacific等の両者で選べるものである必要がある)

地理的な場所が同じドメインの接続のみが許可されます。 リソースの作成時に選択された通信リソースとメール通信リソースのデータの場所が同じであることを確認してください。 検証済みメール ドメインを Azure Communication Service リソースに接続する方法 - An Azure Communication Services quick start guide | Microsoft Learn

アプリケーション

.NETで実装する場合、SDK(Azure.Communication.Email)を仕様すれば比較的に簡単に実装することができ、 EmailClientを実装してSendAsyncで投げるだけ
以下は公式からの引用

string connectionString = Environment.GetEnvironmentVariable("COMMUNICATION_SERVICES_CONNECTION_STRING"); EmailClient emailClient = new EmailClient(connectionString);

EmailSendOperation emailSendOperation = await emailClient.SendAsync(
    Azure.WaitUntil.Completed,
    sender,
    recipient,
    subject,
    htmlContent);
EmailSendResult statusMonitor = emailSendOperation.Value;
string operationId = emailSendOperation.Id;

クイック スタート - Azure Communication Service を使用して電子メールを送信する方法 - An Azure Communication Services Quickstart | Microsoft Learn

各種プロパティについて

  • COMMUNICATION_SERVICES_CONNECTION_STRING
    • Azure PortalのACS画面、キーの管理から取得できる接続文字列
      (ここはAAD認証もできるよう)
  • SendAsyncのプロパティ
    • Azure.WaitUntil
    • sender
      • 送信元のメールアドレス
      • ここで使用できるのはEmail Communication Servicesのドメインをプロビジョニングする-> MailFrom addressesで追加したメールアドレス(標準だとDoNotReplay@<ドメイン>)
    • recipient
      • 送信先のメールアドレス
        • 複数のメールアドレスに送信するためのメソッドがオーバーロードとしてSendAsuncに用意されているが送信者にほかのだれに送ったのがもろばれになる(Bccに設定もできるが...)
    • subject
      • 件名
    • htmlContent
      • メール本文、htmlコンテンツ
      • plain_textを使用しえてhtmlではなく、テキストの送信もできる

learn.microsoft.com

料金体系

Azure Communication Services の価格 | Microsoft Azure

ACSにおける料金は料金 * 転送サイズで計算しており、単純にここだけを比較するのであれば
SendGridと比較して、かなり安くすむ印象
(SendGredのfreeプランを使用していれば当然SendGridのほうが安く済むが)

例えば、0.05MBのメール(直近で受信したMicroSoftのメールがそのくらいだった)を100000件送信すると (ACSでは100000件/月の送信は通常だとクオーターの上限に引っかかる) おおよそ3600円となる
これをSendGridで行うと最低でもEssentials 100kを使用する必要があるので 1000円程度安くなる
料金はACSのほうがやすくなる(多分)

SendGridはEssentials -> Pro へプランをアップグレードすると価格が大きく上がるので月のメール送信数が多いほど、 ACSのほうがコストが低くなりやすい

また、ACSは従量課金なので年を通して送信数にむらっけがある場合もここでの試算以上にコストを抑えられる可能性がある

ただし、後述するがACSはGAからまだ時間がたっていないこともあり、
手前で機能を用意する必要があったりするので、
(例えば、送信結果をログとして記録するにはEventGridからトピックを受けとって処理する機能を実装する必要がある)

実装方法によるが実際は試算よりもコストがかかる可能性がある

機能周り

料金体系でも触れたが、ACSは確かにメールを送信するためのAPIを提供しているのだが
メールを送信に付随する機能はまだ実装されていない

例えば、いわゆるサプレッションリストみたいなものは現在存在しないようだ とはいえ、不達時のサプレッションリストへの追加はともかく
ユーザー操作による購読解除はアカウント情報との紐づけが必要なので
ある程度は自分で実装をかんがえなければならない
(このあたり、Azure AD B2Cと連携してくれないかなと思ったり)

一方で、SMTPを基としたメール配信結果の取得とユーザーエンゲージメントの取得は可能であった   ACSはEventGridの機能を利用したサービスで、配信結果やユーザーエンゲージメントはEvent Gridのイベントとして作られる
(ので、topicを購読するための何かしらがいる)
Azure Communication Services - Email イベント - Azure Event Grid | Microsoft Learn

EmailDeliveryReportReceived

メール配信レポート 重要なのはstatusでメール配信結果はおそらくこれを参照することになる
有効なステータス定義は以下の6種類
- Delivered - Expanded - Bounced - Suppressed - FilteredSpam - Failed

以下、MicrosoftのDocumentから配信されるJson 

[{
  "id": "00000000-0000-0000-0000-000000000000",
  "topic": "/subscriptions/{subscription-id}/resourceGroups/{group-name}/providers/microsoft.communication/communicationservices/{communication-services-resource-name}",
  "subject": "sender/senderid@azure.com/message/00000000-0000-0000-0000-000000000000",
  "data": {
    "sender": "senderid@azure.com", 
    "recipient": "receiver@azure.com",
    "messageId": "00000000-0000-0000-0000-000000000000",
    "status": "Delivered",
    "deliveryStatusDetails": {
      "statusMessage": "Status Message"
    },
    "deliveryAttemptTimeStamp": "2020-09-18T00:22:20.2855749Z",
  },
  "eventType": "Microsoft.Communication.EmailDeliveryReportReceived",
  "dataVersion": "1.0",
  "metadataVersion": "1",
  "eventTime": "2020-09-18T00:22:20Z"
}]

EmailEngagementTrackingReportReceived

ユーザーエンゲージメントの結果
このイベントについては詳しく調査していないが、
engagementTypeがClickViewをとりうるらしい

このイベントについてはとりあえず中身をうけてLog Analyticsかなんかに投げておけば、 あとから参照するのにはこまらなさそう

以下、MicrosoftのDocumentから配信されるJson

[{
  "id": "00000000-0000-0000-0000-000000000000",
  "topic": "/subscriptions/{subscription-id}/resourceGroups/{group-name}/providers/microsoft.communication/communicationservices/{communication-services-resource-name}",
  "subject": "sender/senderid@azure.com/message/00000000-0000-0000-0000-000000000000",
  "data": {
    "sender": "senderid@azure.com", 
    "messageId": "00000000-0000-0000-0000-000000000000",
    "userActionTimeStamp": "2022-09-06T22:34:52.1303595+00:00",
    "engagementContext": "",
    "userAgent": "",
    "engagementType": "view"
  },
  "eventType": "Microsoft.Communication.EmailEngagementTrackingReportReceived",
  "dataVersion": "1.0",
  "metadataVersion": "1",
  "eventTime": "2022-09-06T22:34:52.1303612Z"
}]

制限について

ACSのEmailサービスにはいくつか制限がつけられているようで
Azure Communication Services のサービスの制限 - An Azure Communication Services how-to document | Microsoft Learn

特にメール送信するうえで厳しいのは
送信上限の制限で、これは30件/min かつ 100件/hとなっている
このままではマーケティング目的のメール配信には到たえられないので
クオーター上限引き上げのサポートリクエストを作る必要がある

制限が厳しいのはACS側でオプトアウトのような
メール配信にかかわる機能を持たないがゆえに
Azure側でメール配信のコンプライアンス的な何かが担保できないからなのではという考察

所感

ACSのEmailサービスは既存のメール配信のSASSと比較してAzure側内で完結できるがゆえの恩恵は得られる幹事はするが
GAとなって日が浅いこともあって メール配信に付随するいくつかの機能を手前で準備しなければならない
特に、マーケティング目的での大量のメール配信時の負荷に対するもろもろに懸念が残る

大量のメール配信をしない小規模なサービスにおいて 実験的に導入するのは良いが
ある程度の規模を持つプロダクトへの導入は慎重になったほうがよいかも