Microsoft Graph を使用して Go アプリにメール機能を追加する

この記事では、Microsoft Graph メール API を使用して 、ビルド Go アプリで 作成したアプリケーションを Microsoft Graph で拡張します。 Microsoft Graph を使用して、ユーザーの受信トレイを一覧表示し、メールを送信します。

ユーザーの受信トレイを一覧表示する

まず、ユーザーのメール 受信トレイにメッセージを一覧表示します。

  1. 次の関数を ./graphhelper/graphhelper.go に追加します。

    func (g *GraphHelper) GetInbox() (models.MessageCollectionResponseable, error) {
        var topValue int32 = 25
        query := users.ItemMailFoldersItemMessagesRequestBuilderGetQueryParameters{
            // Only request specific properties
            Select: []string{"from", "isRead", "receivedDateTime", "subject"},
            // Get at most 25 results
            Top: &topValue,
            // Sort by received time, newest first
            Orderby: []string{"receivedDateTime DESC"},
        }
    
        return g.userClient.Me().MailFolders().
            ByMailFolderId("inbox").
            Messages().
            Get(context.Background(),
                &users.ItemMailFoldersItemMessagesRequestBuilderGetRequestConfiguration{
                    QueryParameters: &query,
                })
    }
    
  2. graphtutorial.go の空のlistInbox関数を次のように置き換えます。

    func listInbox(graphHelper *graphhelper.GraphHelper) {
        messages, err := graphHelper.GetInbox()
        if err != nil {
            log.Panicf("Error getting user's inbox: %v", err)
        }
    
        // Load local time zone
        // Dates returned by Graph are in UTC, use this
        // to convert to local
        location, err := time.LoadLocation("Local")
        if err != nil {
            log.Panicf("Error getting local timezone: %v", err)
        }
    
        // Output each message's details
        for _, message := range messages.GetValue() {
            fmt.Printf("Message: %s\n", *message.GetSubject())
            fmt.Printf("  From: %s\n", *message.GetFrom().GetEmailAddress().GetName())
    
            status := "Unknown"
            if *message.GetIsRead() {
                status = "Read"
            } else {
                status = "Unread"
            }
            fmt.Printf("  Status: %s\n", status)
            fmt.Printf("  Received: %s\n", (*message.GetReceivedDateTime()).In(location))
        }
    
        // If GetOdataNextLink does not return nil,
        // there are more messages available on the server
        nextLink := messages.GetOdataNextLink()
    
        fmt.Println()
        fmt.Printf("More messages available? %t\n", nextLink != nil)
        fmt.Println()
    }
    
  3. アプリを実行し、サインインし、オプション 2 を選択して受信トレイを一覧表示します。

    Please choose one of the following options:
    0. Exit
    1. Display access token
    2. List my inbox
    3. Send mail
    4. Make a Graph call
    2
    Message: Updates from Ask HR and other communities
      From: Contoso Demo on Yammer
      Status: Read
      Received: 2021-12-30 04:54:54 -0500 EST
    Message: Employee Initiative Thoughts
      From: Patti Fernandez
      Status: Read
      Received: 2021-12-28 17:01:10 -0500 EST
    Message: Voice Mail (11 seconds)
      From: Alex Wilber
      Status: Unread
      Received: 2021-12-28 17:00:46 -0500 EST
    Message: Our Spring Blog Update
      From: Alex Wilber
      Status: Unread
      Received: 2021-12-28 16:49:46 -0500 EST
    Message: Atlanta Flight Reservation
      From: Alex Wilber
      Status: Unread
      Received: 2021-12-28 16:35:42 -0500 EST
    Message: Atlanta Trip Itinerary - down time
      From: Alex Wilber
      Status: Unread
      Received: 2021-12-28 16:22:04 -0500 EST
    
    ...
    
    More messages available? True
    

GetInbox の説明

GetInbox関数のコードについて考えてみましょう。

既知のメール フォルダーへのアクセス

関数は、list messages API への要求をビルドするuserClient.Me().MailFolders.ByMailFolderId("inbox").Messages()要求ビルダーを使用します。 ByMailFolderId("inbox")要求ビルダーが含まれているため、API は要求されたメール フォルダー内のメッセージのみを返します。 この場合、受信トレイはユーザーのメールボックス内の既定の既知のフォルダーであるため、既知の名前を使用してアクセスできます。 既定以外のフォルダーには、既知の名前をメール フォルダーの ID プロパティに置き換えることで、同じ方法でアクセスされます。 使用可能な既知のフォルダー名の詳細については、「 mailFolder リソースの種類」を参照してください。

コレクションへのアクセス

1 つのオブジェクトを返す前のセクションの GetUser 関数とは異なり、このメソッドはメッセージのコレクションを返します。 コレクションを返す Microsoft Graph のほとんどの API では、使用可能なすべての結果が 1 つの応答で返されるわけではありません。 代わりに、 ページングを 使用して結果の一部を返しながら、クライアントが次のページを要求するメソッドを提供します。

既定のページ サイズ

ページングを使用する API では、既定のページ サイズが実装されます。 メッセージの場合、既定値は 10 です。 クライアントは、 $top クエリ パラメーターを使用して、より多く (またはそれ以下) を要求できます。 GetInboxでは、クエリ パラメーターの Top プロパティを使用して$topを追加します。

注:

Topで渡される値は、明示的な数値ではなく、上限です。 API は、指定した値までのメッセージ数 返します。

後続のページを取得する

サーバーで使用可能な結果が増える場合、コレクション応答には、次のページにアクセスするための API URL を含む @odata.nextLink プロパティが含まれます。 Go SDK は、コレクション ページ オブジェクトに GetOdataNextLink メソッドを提供します。 このメソッドが nil 以外を返す場合は、使用可能な結果が増えます。

コレクションを並べ替える

関数は、クエリ パラメーターの OrderBy プロパティを使用して、メッセージの受信時刻 (receivedDateTime プロパティ) で並べ替えられた結果を要求します。 最近受信したメッセージが最初に一覧表示されるように、DESC キーワード (keyword)が含まれます。 OrderBy プロパティは、$orderby クエリ パラメーターを API 呼び出しに追加します。

メールを送信する

次に、認証されたユーザーとして電子メール メッセージを送信する機能を追加します。

  1. 次の関数を ./graphhelper/graphhelper.go に追加します。

    func (g *GraphHelper) SendMail(subject *string, body *string, recipient *string) error {
        // Create a new message
        message := models.NewMessage()
        message.SetSubject(subject)
    
        messageBody := models.NewItemBody()
        messageBody.SetContent(body)
        contentType := models.TEXT_BODYTYPE
        messageBody.SetContentType(&contentType)
        message.SetBody(messageBody)
    
        toRecipient := models.NewRecipient()
        emailAddress := models.NewEmailAddress()
        emailAddress.SetAddress(recipient)
        toRecipient.SetEmailAddress(emailAddress)
        message.SetToRecipients([]models.Recipientable{
            toRecipient,
        })
    
        sendMailBody := users.NewItemSendMailPostRequestBody()
        sendMailBody.SetMessage(message)
    
        // Send the message
        return g.userClient.Me().SendMail().Post(context.Background(), sendMailBody, nil)
    }
    
  2. graphtutorial.go の空のsendMail関数を次のように置き換えます。

    func sendMail(graphHelper *graphhelper.GraphHelper) {
        // Send mail to the signed-in user
        // Get the user for their email address
        user, err := graphHelper.GetUser()
        if err != nil {
            log.Panicf("Error getting user: %v", err)
        }
    
        // For Work/school accounts, email is in Mail property
        // Personal accounts, email is in UserPrincipalName
        email := user.GetMail()
        if email == nil {
            email = user.GetUserPrincipalName()
        }
    
        subject := "Testing Microsoft Graph"
        body := "Hello world!"
        err = graphHelper.SendMail(&subject, &body, email)
        if err != nil {
            log.Panicf("Error sending mail: %v", err)
        }
    
        fmt.Println("Mail sent.")
        fmt.Println()
    }
    
  3. アプリを実行し、サインインし、オプション 3 を選択して自分にメールを送信します。

    Please choose one of the following options:
    0. Exit
    1. Display access token
    2. List my inbox
    3. Send mail
    4. Make a Graph call
    3
    Mail sent.
    

    注:

    Microsoft 365 開発者プログラムの開発者テナントでテストしている場合は、送信したメールが配信されず、配信不能レポートが届く場合があります。 テナントからのメール送信のブロックを解除する場合は、Microsoft 365 管理センターからサポートにお問い合わせください。

  4. メッセージが受信されたことを確認するには、オプション 2 を選択して受信トレイを一覧表示します。

SendMail の説明

SendMail関数のコードについて考えてみましょう。

メールの送信

関数は、メール送信 API への要求をビルドするuserClient.Me().SendMail()要求ビルダーを使用します。 要求ビルダーは、送信するメッセージを表す Message オブジェクトを受け取ります。

オブジェクトの作成

データのみを読み取る Microsoft Graph の以前の呼び出しとは異なり、この呼び出しではデータが作成されます。 クライアント ライブラリで項目を作成するには、データを表すクラスのインスタンス (この場合は models.Message) を作成し、目的のプロパティを設定してから、API 呼び出しで送信します。 呼び出しはデータを送信しているため、Getの代わりに Post メソッドが使用されます。

次の手順