All Articles

Azure Communication Service Email を使ってメール通知を送ってみた

はじめに

Microsoft Azure Tech Advent Calendar 2022 16 日目の記事です。

日本マイクロソフトの Cloud Solution Architect というロールで主に AI/ML 周りの支援をしている伊藤と言います。

機械学習モデルを使用した異常検知システムから、何かしら API なり SDK (できれば Python) を使ってメール通知を送りたいと思って色々調べていたところ、Azure Communication Service Email が使えそうな雰囲気だったので使ってみました。

なお、Azure Communication Service Email は 2022 年 12 月現在パブリックプレビューの位置づけです。もし使用する場合はその前提でご利用ください。

リソース準備

必要なリソースは

  • Azure Communication Service
  • Azure Communication Service Email

の 2 つです。前者がエンドポイントの役割を果たし、後者が実際にメールを送るためのドメイン周りの設定を担っているように見えます。

Azure Communication Service Email

リソース作成

日本語では「メール通信サービス」となっていました。

image.png

Data location は現在 United States しか選べないようなのでそうします。

ドメイン設定

image.png

Azure が用意したサブドメインか、自前のドメインを設定できるようです。

「1 クリックで追加」を押すとサブドメインの展開が始まります。数分で完了し、「 [email protected] 」という自動生成感が非常に強いアドレスが割り当てられました。

カスタムドメインを追加する場合はボタンクリック後に追加したいドメインを入力すると、ドメインの所有確認のための DNS レコードの情報が表示されます。

image.png

image.png

TXT レコードによる所有確認後、SPF、DKIM、DKIM2 の 3 つについてもレコード追加を行うと使用可能になります。DNS のレコードを Azure 側で取得できるようになるまでそれなりに時間がかかります。僕の環境ではおおよそ 1 時間程度で「検証済み」に変化しました。

Azure Communication Service

リソース作成

日本語では「通信サービス」という名前になっていました。

image.png

データの場所くらいしか固有の設定が無かったのですが、Email の方が United States しか選べなかったのでそれに合わせてこちらも United States にしました。

Email リソースの紐づけ

左メニューの「ドメイン」から Email リソースを紐づけるメニューに飛ぶことができます。

image.png

Email リソースおよび検証済みのドメインを選択して接続します。

image.png

接続文字列取得

Azure Communication Service リソース左メニューの「キー」からエンドポイントと接続文字列を取得することができます。

image.png

Python SDK によるメール送信

使用するパッケージ

Python 3.10.8 環境に以下パッケージをインストールしました。

  • azure-communication-email==1.0.0b1
  • Pillow==9.3.0

コード

from azure.communication.email import (
    EmailClient,
    EmailRecipients,
    EmailContent,
    EmailAddress,
    EmailMessage,
    EmailAttachment,
)
import base64

COMMUNICATION_SERVICE_CONNECTION_STRING = "<connection_string>"

def send_email(to_email_address: str, name: str, subject: str, body: str, attachment_name=None, attachment=None) -> None:
    # https://azure.github.io/azure-sdk-for-python/communication.html#azure-communication-email
    client = EmailClient.from_connection_string(COMMUNICATION_SERVICE_CONNECTION_STRING)

    content = EmailContent(
        subject=subject,
        plain_text=body,
        html=f"<html>{body}</html>",
    )
    address = EmailAddress(email=to_email_address, display_name=name)

    if attachment is None:
        message = EmailMessage(
            sender="[email protected]",
            content=content,
            recipients=EmailRecipients(to=[address]),
        )
    else:
        file_bytes_b64 = base64.b64encode(attachment)
        attachment = EmailAttachment(
            name=attachment_name,
            attachment_type="png",
            content_bytes_base64=file_bytes_b64.decode(),
        )
        message = EmailMessage(
            sender="[email protected]",
            content=content,
            recipients=EmailRecipients(to=[address]),
            attachments=[attachment],
        )

    response = client.send(message)

SDK を使用してこんな感じで実装しました。テストのため接続文字列をそのままハードコードしていますが、本番環境では絶対に真似しないでください。

senderは Email リソースからドメインをクリックするとドメインを表現するサブリソースに飛べるのですが、そちらに記載があります。

EmailAdressEmailContentEmailAttachmentEmailMessageなどのメールを構成する各種要素を表現するクラスを使ってメールを組み上げ、メールを表現するインスタンスをEmailClientsend関数に渡すことで送信するという流れになっています。

テストメールを送るとちゃんとメールが来ました。

image.png

続いて画像を添付してみます。

バイナリとして画像を読み込むコードは以下の通りです。

import io
from PIL import Image

img = Image.open('tired_engineer.png')
img_bin = io.BytesIO()
img.save(img_bin, format="PNG")

img_bin.getvalue()でバイナリを取り出せるので、この値をsend_email関数のattachmentに渡し送信してみます。

image.png

週末疲れ果てたタイミングで Stable Diffusion に「tired engineer」とプロンプトを渡したら出力された趣ある表情の被生成エンジニアの画像がちゃんと来ていますね。

無事成功です。

制限

プレビューであることに加え、Azure Communication Service Email には以下の制限があります。

image.png

1 通/秒とかで送ると引っかかりますね。

おわりに

Azure Communication Service Email の Python SDK を使用してメールを送信することができました。

先輩から「Azure からメールを送るときは色々注意が必要」と聞いていたのですが、パブリックプレビューの新サービスにより先輩から聞いていた「色々」を回避して、ヌルっとメール通知を送ることができて大満足です。

Originally published on Qiita .

Published 2022/12/16

ShuntaIto による技術ブログ