使用Microsoft Graph API无人值守发送邮件。

huangapple go评论64阅读模式
英文:

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 = &quot;application/octet-stream&quot;
            }
        };

        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&lt;FileAttachment&gt;(uploadSession, fileStream, maxSliceSize);

        var totalLength = fileStream.Length;
        // Create a callback that is invoked after each slice is uploaded
        IProgress&lt;long&gt; progress = new Progress&lt;long&gt;(prog =&gt;
        {
            Console.WriteLine($&quot;Uploaded {prog} bytes of {totalLength} bytes&quot;);
        });
        try
        {
            // Upload the file
            var uploadResult = fileUploadTask.UploadAsync(progress).GetAwaiter().GetResult();
            Console.WriteLine(uploadResult.UploadSucceeded ? &quot;Upload complete&quot; : &quot;Upload failed&quot;);
        }
        catch (ServiceException ex)
        {
            Console.WriteLine($&quot;Error uploading: {ex.ToString()}&quot;);
        }

huangapple
  • 本文由 发表于 2023年5月11日 04:43:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/76222423.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定