这是我的第507篇原创文章,写于2024年1月30日。

我先注册一个App,如下:

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail


然后我添加权限如下用来发送邮件:

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_02


使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Office 365_03

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Office 365_04


记得需要Grant admin consent for $组织$。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_05

还要添加新的client secret。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_06


通过如下的请求可以获取到token,这里的scope的值为 https://graph.microsoft.com/.default

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_07


然后参考 user: sendMail 我们准备了如下请求来发送一封邮件:

POST https://graph.microsoft.com/v1.0/users/admin@CRM348591.onmicrosoft.com/sendMail 

{
  "message": {
    "subject": "罗勇演示邮件,编号9527",
    "body": {
      "contentType": "HTML",
      "content": "<p>这是内容!</p>"
    },
    "toRecipients": [
      {
        "emailAddress": {
          "address": "yong.luo@microsoft.com"
        }
      }
    ]
  }
}

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_08


可以看到返回的Status code是202,代表已经接收这个请求,但是这个邮件能否成功发送出去还不一定,实际上我这个邮件被退回来了。那么如何获取到这个邮件的发送状态呢?

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Office 365_09


我想先找到这个邮件,我通过 List messages 来看看,这个需要给client app加权限如下:

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_10


发起一个Get请求类似如下:

https://graph.microsoft.com/v1.0/users/admin@CRM348591.onmicrosoft.com/messages?$filter=contains(subject,'罗勇演示邮件,编号9527') and createdDateTime gt 2024-01-30T14:16:34Z and createdDateTime lt 2024-01-30T14:17:30Z

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_11


可以看到找出了这两封邮件,一封是发出去的,一封是退信产生的。

如果要找到我发出的那封,加上更多的筛选就可以,比如加上发件人条件:sender/emailAddress/address eq 'admin@CRM348591.onmicrosoft.com' 。

https://graph.microsoft.com/v1.0/users/admin@CRM348591.onmicrosoft.com/messages?$filter=contains(subject,'罗勇演示邮件,编号9527') and createdDateTime gt 2024-01-30T14:16:34Z and createdDateTime lt 2024-01-30T14:17:30Z and sender/emailAddress/address eq 'admin@CRM348591.onmicrosoft.com'&$select=internetMessageId,subject,createdDatetime,hasAttachments

还可以通过排序找第一封来解决:

https://graph.microsoft.com/v1.0/users/admin@CRM348591.onmicrosoft.com/messages?$filter=createdDateTime gt 2024-01-30T14:16:34Z and createdDateTime lt 2024-01-30T14:17:30Z and contains(subject,'罗勇演示邮件,编号9527')&$select=internetMessageId,subject,createdDatetime,hasAttachments&$orderby=createdDateTime&$top=1

至于更多可用的筛选,排序等请参考官方文档:Use query parameters to customize responses

需要记录下返回的 internetMessageId 参数值,后面用来检测邮件的发送情况。

下面介绍一个API来查询邮件发送情况。首先需要给client app添加 Office 365 Exchange Online的Application permissions 类型的 ReportingWebService.Read.All 权限,当然也要 Grant admin consent for。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Office 365_12

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_13


还需要为这个Client app授予一个角色,我这个给最低的Security Reader角色。打开Microsoft Entra ID,点击左侧的 Roles and administrators这个导航项目。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_14


找到Security Reader这个角色,打开然后点击 Add assignments按钮。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Office 365_15


将我们的app加入进去。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_16


然后我们获取token的scope参数要改一下,改成 https://outlook.office.com/.default ,才能调用后面的 MessageTrace report 和 MessageTraceDetail report

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Office 365_17


我们发起一个类似 https://reports.office365.com/ecp/reportingwebservice/reporting.svc/MessageTrace?$filter=MessageId eq 'SEZPR01MB4229B90C4D54C2E93140B392FF7D2@SEZPR01MB4229.apcprd01.prod.exchangelabs.com' 的Get请求来获取发送状态,如果 Status的值是非Delivered的就是发送没成功。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_18


返回的 MessageTraceId 有用,记录下来用来调用下一个API,发起类似 https://reports.office365.com/ecp/reportingwebservice/reporting.svc/MessageTraceDetail?$filter=MessageTraceId%20eq%20guid'29228626-fe56-4986-0b70-08dc219e105e'%20and%20RecipientAddress%20eq%20'yong.luo@microsoft.com' 的Get请求,奇怪的是这个查询如果不加上RecipientAddress这个筛选条件就会报错。

使用Graph API的Mail服务发送邮件和监控邮件的发送状态_Mail_19


可以看到发送失败报错的更详细原因是:FailureSmtpResponse is 550 5.7.501 Service unavailable. Spam abuse detected from IP range 。