这是我的第507篇原创文章,写于2024年1月30日。
我先注册一个App,如下:
然后我添加权限如下用来发送邮件:
记得需要Grant admin consent for $组织$。
还要添加新的client secret。
通过如下的请求可以获取到token,这里的scope的值为 https://graph.microsoft.com/.default 。
然后参考 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"
}
}
]
}
}
可以看到返回的Status code是202,代表已经接收这个请求,但是这个邮件能否成功发送出去还不一定,实际上我这个邮件被退回来了。那么如何获取到这个邮件的发送状态呢?
我想先找到这个邮件,我通过 List messages 来看看,这个需要给client app加权限如下:
发起一个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
可以看到找出了这两封邮件,一封是发出去的,一封是退信产生的。
如果要找到我发出的那封,加上更多的筛选就可以,比如加上发件人条件: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。
还需要为这个Client app授予一个角色,我这个给最低的Security Reader角色。打开Microsoft Entra ID,点击左侧的 Roles and administrators这个导航项目。
找到Security Reader这个角色,打开然后点击 Add assignments按钮。
将我们的app加入进去。
然后我们获取token的scope参数要改一下,改成 https://outlook.office.com/.default ,才能调用后面的 MessageTrace report 和 MessageTraceDetail report 。
我们发起一个类似 https://reports.office365.com/ecp/reportingwebservice/reporting.svc/MessageTrace?$filter=MessageId eq 'SEZPR01MB4229B90C4D54C2E93140B392FF7D2@SEZPR01MB4229.apcprd01.prod.exchangelabs.com' 的Get请求来获取发送状态,如果 Status的值是非Delivered的就是发送没成功。
返回的 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这个筛选条件就会报错。
可以看到发送失败报错的更详细原因是:FailureSmtpResponse is 550 5.7.501 Service unavailable. Spam abuse detected from IP range 。