Modern Work 食堂

Microsoft 365 やら Azure やらを広く浅く触って、Modern Work の研鑽を積むためのメモブログ

Microsoft Graph を Azure Functions で呼び出す

Azure Logic Apps を使えばいいじゃんという話もあるものの、やはり Azure Functinos で独自に API を作りたい要件もきっとあるはず。
ということで、Azure Functions から Microsoft Graph の「Send Mail API」を使ってた所感を書いていこうかと。
※今回はさくっとポータル上で実装します。

(SharePoint Framework の投稿は貯めているだけで、さぼっているわけでは…。)

【目次】

【前提条件】

  • Office 365 アカウント
    要 Exchange Online ライセンス

Azure Functions の作成

Azure ポータルで Function App を作成します。
f:id:SPRestaurant:20170919011450p:plain

Function App のデプロイが完了したら、新しく「関数」を作成します。
※Function App の URL は後述で利用するので、コピーしておきます。
f:id:SPRestaurant:20170919011453p:plain

今回は「C#」「Webhook」のテンプレートを使用します。
f:id:SPRestaurant:20170919011456p:plain

以下のファイルを追加します。
ファイル名 : project.json
コード :

{
  "frameworks": {
    "net46":{
      "dependencies": {
          "Microsoft.IdentityModel.Clients.ActiveDirectory": "3.16.1"
      }
    }
   }
}

f:id:SPRestaurant:20170919011458p:plain

run.csx ファイルのコードを以下の内容に書き換えます。

#r "Newtonsoft.json"

using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    string resourceId = "https://graph.microsoft.com";
    string tenantId = "<Tenant ID>";
    string authString = "https://login.microsoftonline.com/" + tenantId;

    // AAD
    string clientId = "<App ID>";
    string clientSecret = "<Secret key>";

    var authenticationContext = new AuthenticationContext(authString, false);

    ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
    AuthenticationResult authenticationResult = await authenticationContext.AcquireTokenAsync(resourceId, clientCred);
    string token = authenticationResult.AccessToken;
    log.Verbose("token=" + token);

    var responseString = String.Empty;

    // Send Outlook message
    responseString = SendMail(token);

    return req.CreateResponse(HttpStatusCode.OK, responseString);
}

private static string SendMail(string accessToken)
{
    using (var client = new HttpClient())
    {
        string graphService = "https://graph.microsoft.com/v1.0/users/<送信元 UPN>/sendMail";

        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, graphService);
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        var msgObj = new MessageRequest()
        {
            Message = new SendMessageContent()
            {
                toRecipients = new List<Recipient>()
                {
                    new Recipient()
                    {
                        EmailAddress = new EmailAddress()
                        {
                            Address = "<送信先>"
                        }
                    }
                },
                Subject = "Sending sample message from MS Graph",
                Body = new ItemBody()
                {
                    ContentType = "Text",
                    Content = "Send sample message content."
                }
            },
            SaveToSentItems = true
        };

        request.Content = new StringContent(JsonConvert.SerializeObject(msgObj), Encoding.UTF8, "application/json");

        using (var response = client.SendAsync(request).Result)
        {
            if (response.IsSuccessStatusCode)
            {
                return "Completed send message";
            }

            return response.ReasonPhrase;
        }
    }
}

public class EmailAddress
{
    public string Name { get; set; }
    public string Address { get; set; }
}

public class ItemBody
{
    public string ContentType { get; set; }
    public string Content { get; set; }
}

public class Recipient
{
    public EmailAddress EmailAddress { get; set; }
}

public class SendMessageContent
{
    public string Subject { get; set; }
    public ItemBody Body { get; set; }
    public List<Recipient> toRecipients { get; set; }
}

class MessageRequest
{
    public SendMessageContent Message { get; set; }
    public bool SaveToSentItems { get; set; }
}

 

Azure AD Application の登録

Azure ポータルで「アプリの登録」を行います。
「サインオン URL」には、先ほどの Function App URL を入力します。 f:id:SPRestaurant:20170919011501p:plain f:id:SPRestaurant:20170919011503p:plain

「キー」を生成し、コピーしておきます。
f:id:SPRestaurant:20170919011507p:plain

「アクセス許可」を追加します。
ここで「Microsoft Graph」に「アプリケーションのアクセス許可」を設定することが大事です。
f:id:SPRestaurant:20170919011511p:plain

「アプリケーション ID」をコピーします。
f:id:SPRestaurant:20170919011505p:plain

「Azure Active Directory」の「プロパティ」を開き、「ディレクトリ ID」をコピーします。
f:id:SPRestaurant:20170919011509p:plain

関数の修正 

Function App にコピーしておいたデータを入力します。

行数 入力するデータ
15 ディレクトリ ID
19 アプリケーション ID
20 シークレットキー
41 メール送信元の UPN
57 宛先となるメールアドレス

最後に「実行」ボタンをクリックすると、テストが実行されてメールが送信されます。 f:id:SPRestaurant:20170919011513p:plain f:id:SPRestaurant:20170919011515p:plain