Azure FunctionsはAzureで提供されているFaaS(Function As a Service)です。複数の言語に対応していますが、Microsoft製のサービスとあって他にはない.NETが使えるのがポイントです。
今回はこのAzure Functionsを使ってCustomers Mail Cloudでメール送信を行う方法を紹介します。
Customers Mail Cloudの設定
まずはCustomers Mail Cloudにて送信サーバの設定を行います。
ユーザ登録
ユーザ登録はまず、メールアドレスとパスワードを入力するところからはじまります。
入力したメールアドレス宛にメールアドレスの確認メール(仮登録受付メール)が届きますので、URLをクリックします。その後、名前や住所といった必要な情報を入力します。ユーザ登録が完了すると、無料トライアル開始のための審査が入ります。時間は長くとも30分程度です。「Customers Mail Cloud 無料トライアル利用開始のご案内」というメールが届いたら利用できます。
ログイン後に行うこと
ログインしたら、2つの作業を行う必要があります。
DKIMキーを設定する
DKIMキーはメールのなりすましを防止するための技術になります。メール配信を行うドメインのTXTレコードに対して設定します。管理コンソールでドメインを追加しようとすると、専用のキーが表示されます。
ドメインは s999999999999._domainkey.example.com
のような形式になります。設定する値は v=DKIM1; p=MIG...QAB
のように指定されるはずです。この設定はシステム管理者などに依頼して行ってもらってください。
DNS設定はすぐに反映されませんので、数分後にDNSを確認ボタンを押します。正しく設定されていれば、ドメインが追加登録できます。
ユーザを追加する
次にメール配信を行うユーザを追加します。これはAPI設定にて行います。ユーザ名(メールアドレス形式)、パスワードを設定します。また、利用できる機能を制限できます。例えばSMTPのみ、APIのみといった指定も可能です。
サーバに設定を反映する
設定を行ったら、それをサーバに反映します。サーバ構成機能にて行います。この反映を行わないと、DKIMやユーザ追加設定が反映されませんので注意してください。ここまでで以下の情報が入手できているはずです。
- APIユーザ
- APIキー
さらにAPIサーバのエンドポイントURLが必要です。これは契約しているプランによって異なりますのでご注意ください。
プラン名 | エンドポイントURL |
---|---|
無料トライアル | https://sandbox.smtps.jp/api/v2/emails/send.json |
Standardプラン | https://te.smtps.jp/api/v2/emails/send.json |
Proプラン | https://SUBDOMAIN.smtps.jp/api/v2/emails/send.json |
これらの情報はメール送信時に設定しますので覚えておいてください。
AzureでFunctionsのベースを作成する
AzureにログインしてFunction Appを選択し、ベースを作成します。今回はWindowsで、.NET Coreを選択しています。
CLIツールのインストール
Azure用のCLIツールをインストールします。インストールはAzure CLI のインストールに各OS向けの説明があります。macOSの場合、Homebrewを使って下記コマンドでインストールできます。
brew update && brew install azure-cli
プロジェクトの作成
以下のコマンドでAzureにログインします。
az login
ログイン後、プロジェクトのベースを作成します。対話型になっているので、言語としてdotnetを選ぶのを忘れないでください。
$ func init azure-function Select a worker runtime: 1. dotnet 2. node 3. python (preview) 4. powershell (preview) Choose option: 1 dotnet Writing /path/to/azure-function/.vscode/extensions.json
プロジェクトは以下のような構成になっています。まだ空の状態と言えます。
$ tree . . ├── azure-function.csproj ├── host.json └── local.settings.json 0 directories, 3 files
そしてテンプレートを使ってC#のファイルを作成します。今回はHTTPアクセスによる関数実行にするため、HttpTriggerをテンプレートにしています。
$ func new --name MyHttpTrigger --template "HttpTrigger" Select a template: Function name: MyHttpTrigger The function "MyHttpTrigger" was created successfully from the "HttpTrigger" template.
環境設定を行う
API経由でメール送信を行う際に使うAPIユーザ、APIキー、さらに契約状態によって異なるAPIエンドポイントURLは環境変数として定義します。開発時には local.settings.json
に書き込みます。
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "", "FUNCTIONS_WORKER_RUNTIME": "dotnet", "API_USER": "APIユーザ名", "API_KEY": "APIキー", "ENDPOINT": "エンドポイントのURL" } }
これはローカルでの設定になります。本番環境側では、Azure Functionsの構成にある、アプリケーション設定で値を追加します。値の名前は、 local.settings.json
と同じものです。
- API_USER
- API_KEY
- ENDPOINT
コードについて
MyHttpTrigger.cs
について解説します。まず必要なライブラリを読み込みます。
using System; using System.IO; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Extensions.Http; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Configuration; using Newtonsoft.Json;
次にメール送信APIに必要なパラメータをクラスで定義します。
[DataContract] public class Email { [DataMember(Name="name")] public string Name { get; set; } [DataMember(Name="address")] public string Address { get; set; } } [DataContract] public class Params { [DataMember(Name="api_user")] public string ApiUser {get; set; } [DataMember(Name="api_key")] public string ApiKey {get; set; } [DataMember(Name="subject")] public string Subject {get; set; } [DataMember(Name="text")] public string Text {get; set; } [DataMember(Name="to")] public Email[] To {get; set;} [DataMember(Name="from")] public Email From {get; set;} }
環境変数を読み込むため、Run関数に ExecutionContext context
を追加します。
public static async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log, ExecutionContext context )
ここからの処理は、このRun関数の中に記述していきます。まずリクエストデータ(POST)を処理できるようにします。
string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); dynamic data = JsonConvert.DeserializeObject(requestBody);
環境変数を読み込みます。これで config として扱えるようになります。設定ファイルの後、環境変数も読み込みますので、ローカルの開発時と本番環境で同じ config からアクセスできるようになります。
var config = new ConfigurationBuilder() .SetBasePath(context.FunctionAppDirectory) .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true) .AddEnvironmentVariables() .Build();
メール送信APIに送信するパラメータを作ります。APIに関する情報は config から、メールの送信先はリクエストボディから指定できるようにしました。
Params p = new Params(); p.ApiUser = config["API_USER"]; p.ApiKey = config["API_KEY"]; p.Subject = "テストメール from Customers Mail Cloud"; p.Text = "こんにちは。\r\n\r\n改行を入れました。"; Email to = new Email(); to.Name = data?.name; to.Address = data?.address; p.To = new Email[] {to}; Email from = new Email(); from.Name = "Admin"; from.Address = "info@smtpd.jp"; p.From = from;
そして、このパラメータをJSON文字列にします。
var ms = new MemoryStream(); var sr = new StreamReader(ms); var serializer = new DataContractJsonSerializer(typeof(Params)); serializer.WriteObject(ms, p); ms.Position = 0; var json = sr.ReadToEnd();
そしてメール送信APIを呼び出します。この処理は C#でメールを送信する で書いている通りです。
System.Net.WebClient wc = new System.Net.WebClient(); wc.Headers[System.Net.HttpRequestHeader.ContentType] = "application/json;charset=UTF-8"; wc.Headers[System.Net.HttpRequestHeader.Accept] = "application/json"; wc.Encoding = System.Text.Encoding.UTF8; string response = wc.UploadString(new Uri(config["ENDPOINT"]), json); wc.Dispose(); return (ActionResult)new OkObjectResult(response);
ローカルでテストする
Azure CLIではローカルでテストできる仕組みがあります。
func host start --build
そうすると最後に次のように出力されます。
Http Functions: MyHttpTrigger: [GET,POST] http://localhost:7071/api/MyHttpTrigger
このURLに対してリクエストを行うことでテスト実行が可能です。
$ curl -X POST \ -H "Content-Type: application/json" \ -d '{"name":"テストカスタマー", "email":"user@stmpd.jp"}' \ http://localhost:7071/api/MyHttpTrigger
デプロイする
Azure Functionsへのデプロイは以下のコマンドで行えます。最後の引数はあらかじめ作成してあるAzure Function Appの名前です。
$ func azure functionapp publish CustomersMailCloud .NET Core 向け Microsoft (R) Build Engine バージョン 15.9.20+g88f5fadfbe Copyright (C) Microsoft Corporation.All rights reserved. : Getting site publishing info... Creating archive for current directory... Uploading 3.37 MB [###############################################################################] Upload completed successfully. Deployment completed successfully. Syncing triggers... Functions in CustomersMailCloud: MyHttpTrigger - [httpTrigger] Invoke url: https://customersmailcloud.azurewebsites.net/api/example?code=3hy...4pw==
初回実行時に専用のURLが生成されます。上記の場合は https://customersmailcloud.azurewebsites.net/api/example?code=3hy...4pw==
となります。このURLは管理画面でも確認できます。
メール送信を試す
では実際にメールを送信してみます。
$ curl -X POST \ -H "Content-Type: application/json" \ -d '{"name":"テストカスタマー", "address":"user@smtpd.jp"}' \ https://customersmailcloud.azurewebsites.net/api/example?code=3hy...4pw==
問題なければ以下のように結果が返ってきます。
{"id":"C1673412149.1272.1565250534682@mta01.sandbox.smtps.jp"}
まとめ
Azure Functionsを使うことでサーバレスでC#(またはNode.jsやPythonなど)を実行できます。さらにCustomers Mail Cloudと組み合わせることで、サーバレスでのメール送信が簡単に実現できます。ぜひお試しください!