英文:
Send Mails unattended with Microsoft Graph API
问题
我想在.NET控制台应用程序中使用Microsoft Graph API无人值守地发送邮件。
该API支持直接发送邮件或创建草稿,然后修改并发送它。前者对附件大小有限制,每个附件的大小必须小于3 MB。查看文档
后者需要Mail.ReadWrite
API权限。将其添加为应用程序权限将使应用程序能够访问组织中的每个邮箱,如果可能的话,我不想授予此权限。
另一个选项是使用用户名和密码身份验证流程。但是,我们公司的AD要求多因素身份验证,这是该流程的限制。
我尝试使用客户端凭据流程对应用程序进行身份验证。发送超过3 MB的附件需要Mail.ReadWrite
权限。
使用我的用户帐户对应用程序进行用户名/密码身份验证也失败,因为需要MFA。
我正在使用NuGet包Azure.Identity
进行身份验证流程和Microsoft.Graph
来发送请求。
从.NET控制台应用程序无人值守地发送超过3 MB的附件邮件的正确方法是什么?我在哪里出错了?
提前感谢您,并请告诉我如果需要更多详细信息。
英文:
I want to send mails unattended in a .NET console application with the Microsoft Graph API.
The API supports sending a mail directly or create a draft, modify it and send it. The first has a limitation on attachment size. Each attachment has to be under 3 MB in size. See Documentation
The latter one requires the Mail.ReadWrite
API permission. Adding it as an application permission would enable the application to access every mailbox in the organisation, which I do not want to grant if possible.
Another option would be to use the username and password authentication flow. But our corporation AD requires multi-factor authentication, a constraint of that flow.
I tried to authentiate the application with the client credential flow. Sending an attachment over 3 MB requires the Mail.ReadWrite
privilege.
Authenticating the application with my user account using the username/password did also fail, because of the MFA requirement.
I am using the NuGet packages Azure.Identity
for the authentication flow and Microsoft.Graph
to send the requests.
What is the proper way to send mails unattended with attachments over 3 MB from a .NET console application? Where did I take the wrong turn?
Thanks in advance and let me know if you need more details.
答案1
得分: 1
客户端凭证流通常是最佳选项,因为它避免了使用用户名和密码,这有许多相关问题(多因素身份验证仅是其中之一)。关于完全访问租户的问题,您可以缩小访问范围,以便您的应用程序仅能够发送/访问特定的邮箱。有关发送超过3MB的电子邮件,请参阅链接https://learn.microsoft.com/en-us/graph/outlook-large-attachments?tabs=csharp。如果您使用Graph SDK,它会使这个过程相对容易,例如:
var fileStream = System.IO.File.OpenRead(bigAttachment.FullName);
var uploadRequestBody = new Microsoft.Graph.Users.Item.Messages.Item.Attachments.CreateUploadSession.CreateUploadSessionPostRequestBody
{
AttachmentItem = new AttachmentItem
{
AttachmentType = AttachmentType.File,
Name = bigAttachment.Name,
Size = fileStream.Length,
ContentType = "application/octet-stream"
}
};
var uploadSession = graphClient.Users[objectID]
.Messages[savedDraft.Id]
.Attachments
.CreateUploadSession
.PostAsync(uploadRequestBody).GetAwaiter().GetResult();
// 最大切片大小必须是320 KiB的倍数
int maxSliceSize = 320 * 1024;
var fileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession, fileStream, maxSliceSize);
var totalLength = fileStream.Length;
// 创建在每个切片上传后调用的回调
IProgress<long> progress = new Progress<long>(prog =>
{
Console.WriteLine($"已上传 {prog} 字节,共 {totalLength} 字节");
});
try
{
// 上传文件
var uploadResult = fileUploadTask.UploadAsync(progress).GetAwaiter().GetResult();
Console.WriteLine(uploadResult.UploadSucceeded ? "上传完成" : "上传失败");
}
catch (ServiceException ex)
{
Console.WriteLine($"上传时出错: {ex.ToString()}");
}
英文:
The client credentials flow is generally the best option as this avoids having a username and password which has a lot of associated problems (MFA is just one). With the issue of having full access to the tenant you can scope down the access https://learn.microsoft.com/en-us/graph/auth-limit-mailbox-access so your app can then only Send/Access particular mailboxes.
For sending emails over 3mb see https://learn.microsoft.com/en-us/graph/outlook-large-attachments?tabs=csharp if you use the Graph SDK it makes this relatively easy eg
var fileStream = System.IO.File.OpenRead(bigAttachment.FullName);
var uploadRequestBody = new Microsoft.Graph.Users.Item.Messages.Item.Attachments.CreateUploadSession.CreateUploadSessionPostRequestBody
{
AttachmentItem = new AttachmentItem
{
AttachmentType = AttachmentType.File,
Name = bigAttachment.Name,
Size = fileStream.Length,
ContentType = "application/octet-stream"
}
};
var uploadSession = graphClient.Users[objectID]
.Messages[savedDraft.Id]
.Attachments
.CreateUploadSession
.PostAsync(uploadRequestBody).GetAwaiter().GetResult();
// Max slice size must be a multiple of 320 KiB
int maxSliceSize = 320 * 1024;
var fileUploadTask = new LargeFileUploadTask<FileAttachment>(uploadSession, fileStream, maxSliceSize);
var totalLength = fileStream.Length;
// Create a callback that is invoked after each slice is uploaded
IProgress<long> progress = new Progress<long>(prog =>
{
Console.WriteLine($"Uploaded {prog} bytes of {totalLength} bytes");
});
try
{
// Upload the file
var uploadResult = fileUploadTask.UploadAsync(progress).GetAwaiter().GetResult();
Console.WriteLine(uploadResult.UploadSucceeded ? "Upload complete" : "Upload failed");
}
catch (ServiceException ex)
{
Console.WriteLine($"Error uploading: {ex.ToString()}");
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论