分享

使用现代身份验证(OAuth)来连接POP、IMAP或SMTP

 F2967527 2022-07-12 发布于北京

我们之前已经向大家发布了Exchange Online 服务即将停用基本身份验证的说明和提醒。

Exchange Online服务即将停用基本身份验证

Office365,公众号:Office365云服务技术支持Exchange Online服务即将停用基本身份验证

而在诸多实际的生产场景中,绝大多数网络打印机厂商、OA 及其他集成系统、邮件客户端还不支持通过 OAuth 认证方式连接 POP、IMAP 或 SMTP。随着停用基本身份验证的时间临近,我们敦促和建议广大接口厂商和系统集成合作伙伴,尽快改用 OAuth 认证方式来连接 POP、IMAP 和 SMTP。

针对这种情况,今天就向大家说明一下,如何使用现代身份验证(OAuth) 来连接 POP、IMAP 和 SMTP。请注意,以下说明只是针对各大厂商对代码进行修改,一般用户无法直接使用 OAuth 方式来连接 POP、SMTP 等协议。


   准备工作   


如果您还不了解什么是 OAuth,请参考我们之前发布的文档 使用现代身份验证(OAuth)调用 EWS 服务 中的关于 OAuth 是什么 的部分说明:

使用现代身份验证(OAuth)调用 EWS 服务

Robin Dai,公众号:Office365云服务技术支持使用现代身份验证(OAuth)调用 EWS 服务

如果您对 OAuth 申请令牌凭证已经有了一定的了解,那么请继续以下的步骤。

首先注册一个 Azure AD 应用:

  • 通过浏览器访问并登录以下网址:
    https://portal./#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/RegisteredApps

  • 点击“新注册”,并输入名称,来注册出一个应用。

  • 证书和密码中创建一个客户端密码并记住这个密码

    图片

  • 在API权限中添加权限:

    • 点击添加权限

    • 点击 Microsoft Graph

      图片

    • 选择委托的权限中的 SMTP.Send 、POP.AccessAsUser.All 和 IMAP.AccessAsUser.All 勾选并保存。

  • 在 API 权限中点击代表***授予管理员权限

图片


   请求OAuth令牌   


请求OAuth令牌,是一个关键步骤。由于 Azure AD 的终结点本身存在1.0和2.0两个版本,在这里,我们推荐大家使用1.0版本,以避免在使用2.0版本时,错误的scope参数而导致请求到无效的令牌。

由于该令牌必须有用户参与,因此无法使用客户端密码的方式(grant_type=client_credential)调用,而仅能使用代码授予grant_type=authorization_code)或用户密码凭据授予grant_type=password)的方式获取。后面两者的区别在于代码授予一定会弹出要求用户登录的页面,而 用户密码凭据授予可以保持静默登录,但安全性将打折扣

请求内容如下(以用户密码凭据授予为例,请将自己的租户 ID、注册应用 ID、客户端密码、用户名和密码替换示例中的{tenant ID}、{App ID}、{Client Secret}、user@abc.com和{user password}。):

 HTTP

POST https://login.partner./{tenant ID}/oauth2/token HTTP 1.1  

Host: login.partner.

Content-Type: application/x-www-form-urlencoded

client_id={App ID}

&client_secret={Client Secret}

&grant_type=password

&resource=https%3A%2F%2Fpartner.outlook.cn

&username=user%40abc.com

&password={user password}

 cURL

curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -d 'client_id={App ID}&resource=https%3A%2F%2Fpartner.outlook.cn%2F.default&client_secret={Client Secret}&grant_type=password&username=user%40abc.com&password={user password}'  'https://login.partner./{tenant}/oauth2/token'    


   使用OAuth令牌进行连接   


在您得到 OAuth令牌后,您需要以 SASL XOAUTH2 的格式来转换和发送凭据。SASL XOAUTH2 以以下格式将用户名、访问令牌编码在一起:

 Text

base64('user=' + userName + '^Aauth=Bearer ' + accessToken + '^A^A')    

^A 表示 Control + A () %x01 。

例如,使用访问令牌eyJ0eXAiOiJKV1QiLCJub25jZSI6IjlBOGtWal9hcXpVOWAA(此处缩略了很长一部分),访问的 user@abc.com, SASL XOAUTH2 格式为:

 Text

base64('user=user@abc.com^Aauth=Bearer eyJ0eXAiOiJKV1QiLCJub25jZSI6IjlBOGtWal9hcXpVOWAA^A^A')   

在 base64 编码后,这会转换为以下字符串:

 Text

dXNlcj11c2VyQGFiYy5jb21eQWF1dGg9QmVhcmVyIGV5SjBlWEFpT2lKS1YxUWlMQ0p1YjI1alpTSTZJamxCT0d0V2FsOWhjWHBWT1dBQV5BXkE=   

在连接不同协议时,连接的形式略有不同,具体请参考:

POP

 Text

AUTH XOAUTH2 

<base64 string in XOAUTH2 format>

IMAP

 Text

AUTHENTICATE XOAUTH2 <base64 string in XOAUTH2 format>

SMTP

 Text

AUTH XOAUTH2 <base64 string in XOAUTH2 format>

目前就我们的测试,Java.mail 和 Mailkit 库可以支持SASL XOAUTH2方式的连接。以C# 调用 Mailkit 库,通过OAuth方式连接SMTP发送邮件为例,参考代码如下(已略过请求令牌的代码):

 C#

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Net;

using MailKit.Net.Smtp;

using MailKit.Security;

using MimeKit;

using MailKit;

namespace OAuth2forMail

{

    class Program

    {

        static void Main(string[] args)

        {

            var p = new Program();

            p.Sendmm();

        }

         void Sendmm()

        {

            MimeMessage mm = new MimeMessage();

            mm.To.Add(new MailboxAddress('My Customer', 'customer@abc.com'));

            mm.From.Add(new MailboxAddress('Boss Wang', 'user@abc.com'));

            var builder = new BodyBuilder();

            builder.TextBody = @'This is a test mail.';

            mm.Subject = 'Test to send mail with OAuth2';

            mm.Body = builder.ToMessageBody();

            SaslMechanismOAuth2 oauth2 = new SaslMechanismOAuth2('user@abc.com',

                'eyJ0eXAiOiJKV1QiLCJub25jZSI6IjlBOGtWal9hcXpVOWAA'

                );

            using (var client = new SmtpClient(new ProtocolLogger('smtp.log')))

            {

                client.Connect('smtp.partner.outlook.cn', 587, SecureSocketOptions.StartTls);

                client.Authenticate(oauth2);

                try

                {

                     client.Send(mm);

                    Console.WriteLine('send success');

                    client.Disconnect(true);

                }

                catch (Exception ex)

                {

                    Console.WriteLine(ex.Message.ToString());

                }

            }

        }

    }

}

综上,建议各大厂商、开发人员尽快修改您的代码,以便支持OAuth的方式来连接POP、IMAP和SMTP协议。



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多