はじめに
Azure Functions から Eメールを送る方法としては、SendGrid アウトプットバインディングがありますが、この記事では、2023年4月に GAされた Azure Communication Service の Email サービスを使用して Azure Functions から Email を送信する方法について記載します。
Azure Functions で Email Service を使う
Functions 内でSDKを利用する
基本的には各言語で用意されている SDK を用いることで Email 送信自体は簡単にできる。
Azure Functions 上で用いる注意点としては Singleton にするなど SNAT ポート枯渇が発生しないようにする工夫が必要である。
.NET だと以下のような感じで送信可能
using System.Threading;
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 Azure;
using Azure.Communication.Email;
namespace FunctionApp1
{
public static class Function1
{
private static EmailClient emailClient = new EmailClient(System.Environment.GetEnvironmentVariable("AzureWebJobsACSEmailConnecionString"));
[FunctionName("Function4")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var emailContent = new EmailContent("This is the subject")
{
PlainText = "This is the body",
Html = "<html><body>This is the html body</body></html>"
};
var emailMessage = new EmailMessage(
senderAddress: System.Environment.GetEnvironmentVariable("fromAddress"),
recipientAddress: System.Environment.GetEnvironmentVariable("toAddress"),
content: emailContent);
try
{
EmailSendOperation emailSendOperation = await emailClient.SendAsync(WaitUntil.Completed, emailMessage, default(CancellationToken));
log.LogInformation($"Email operation id = {emailSendOperation.Id}, Status = {emailSendOperation.Value.Status}");
}
catch (RequestFailedException ex)
{
/// OperationID is contained in the exception message and can be used for troubleshooting purposes
log.LogError($"Email send operation failed with error code: {ex.ErrorCode}, message: {ex.Message}");
}
return new OkObjectResult("done");
}
}
}
カスタムバインディングにする
SendGrid や Twillioのようにアウトプットバインディングを利用できると便利そうなので作ってみた。(Nuget packageとしてのリリースは未実施)
ACSEmail
バインディングを利用することで、SDK クライアントの管理をアプリケーションコード側で行う必要がなくなって便利。もちろん .NET 以外の言語で利用することも可能。
[FunctionName("Function1")]
public static IActionResult Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
[ACSEmail] out ACSEmailContext mail,
ILogger log)
{
string address1 = Environment.GetEnvironmentVariable("testAddress1");
string address2 = Environment.GetEnvironmentVariable("testAddress2");
string address3 = Environment.GetEnvironmentVariable("testAddress3");
string address4 = Environment.GetEnvironmentVariable("testAddress4");
mail = new ACSEmailContext();
mail.RecipientToAddresses = new List<string>() { address1, address2 };
mail.RecipientCCAddresses = new List<string>() { address3 };
mail.RecipientBCCAddresses = new List<string>() { address4 };
mail.Subject = "Test acs email from function";
mail.PlainTextContent = "Hello world";
mail.HtmlContent = "<html><body>This is the html body</body></html>";
mail.AttachmentFilePath = $"{Directory.GetCurrentDirectory()}\\host.json";
mail.AttachmentName = "host.json";
mail.AttachmentContentType = "application/json";
return (ActionResult) new OkObjectResult("OK");
}
参考記事
まずはじめに読んだ
公式ドキュメント(正直これだけだとかなり辛い)
.NETビギナーなので、SendGrid 拡張をパクっ写経してACSEmailクライアントに置き換えました。