使用 EWS 和 IMAP 连接 Exchange Server

为了使用 Exchange Web Service 连接 Exchange 2007、2010 和 2013 服务器,Aspose.Email 提供了 IEWSClient 实现了的接口 EWSClient 类。该 EWSClient.GetEWSClient 方法实例化并返回一个 IEWSClient 对象随后用于执行与 Exchange 邮箱及其他文件夹相关的操作。本文展示了如何实例化以下对象的 IEWSClient.

使用 EWS 连接到 Exchange Server

以下代码片段展示了如何使用 Exchange Web Service (EWS) 建立连接:

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
private static IEWSClient GetExchangeEWSClient()
{
    const string mailboxUri = "https://outlook.office365.com/ews/exchange.asmx";
    const string domain = @"";
    const string username = @"username@ASE305.onmicrosoft.com";
    const string password = @"password";
    NetworkCredential credentials = new NetworkCredential(username, password, domain);
    IEWSClient client = EWSClient.GetEWSClient(mailboxUri, credentials);
    return client;
}

向 EWSClient 初始化添加自定义标头

在客户端初始化期间需要特定标头的场景(例如 EWS 中的 X-AnchorMailbox 标头),请使用以下重载方法在创建实例时添加自定义标头 IEWSClient:

  • IEWSClient GetEWSClient(string mailboxUri, ICredentials credentials, WebProxy proxy, Dictionary headers)

  • async Task GetEwsClientAsync(string mailboxUri, ICredentials credentials, WebProxy proxy, CancellationToken cancellationToken , Dictionary headers)

下面的代码示例演示了如何在使用自定义 HTTP 标头的情况下配置和初始化 IEWSClient:

var headers = new Dictionary<string, string>();
headers.Add("X-AnchorMailbox", smtpExampleAddress);
IEWSClient client = EWSClient.GetEWSClient(HttpsExampleCom, new OAuthNetworkCredential("UserName", "Token"), null, headers);

使用 IMAP 连接到 Exchange Server

Microsoft Exchange Server 支持 IMAP 协议以访问邮箱中的项目。请使用 Aspose.Email ImapClient 用于使用 IMAP 协议连接 Exchange Server 的类。有关更多信息,请参考 ImapClient 类。首先,确保已为您的 Exchange Server 启用 IMAP 服务:

  1. 打开控制面板。
  2. 转到管理工具,然后选择服务。
  3. 检查 Microsoft Exchange IMAP4 服务的状态。
  4. 如果尚未运行,请启用/启动它。

以下代码片段展示了如何使用 IMAP 协议连接并列出 Microsoft Exchange 服务器收件箱文件夹中的邮件。

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Connect to Exchange Server using ImapClient class
ImapClient imapClient = new ImapClient("ex07sp1", "Administrator", "Evaluation1");
imapClient.SecurityOptions = SecurityOptions.Auto;

// Select the Inbox folder
imapClient.SelectFolder(ImapFolderInfo.InBox);

// Get the list of messages
ImapMessageInfoCollection msgCollection = imapClient.ListMessages();
foreach (ImapMessageInfo msgInfo in msgCollection)
{
    Console.WriteLine(msgInfo.Subject);
}
// Disconnect from the server
imapClient.Dispose();

以下代码片段展示了如何使用 SSL。

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
public static void Run()
{            
    // Connect to Exchange Server using ImapClient class
    ImapClient imapClient = new ImapClient("ex07sp1", 993, "Administrator", "Evaluation1", new RemoteCertificateValidationCallback(RemoteCertificateValidationHandler));
    imapClient.SecurityOptions = SecurityOptions.SSLExplicit;

    // Select the Inbox folder
    imapClient.SelectFolder(ImapFolderInfo.InBox);

    // Get the list of messages
    ImapMessageInfoCollection msgCollection = imapClient.ListMessages();
    foreach (ImapMessageInfo msgInfo in msgCollection)
    {
        Console.WriteLine(msgInfo.Subject);
    }
    // Disconnect from the server
    imapClient.Dispose();   
}

// Certificate verification handler
private static bool RemoteCertificateValidationHandler(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    return true; // ignore the checks and go ahead
}

在使用 IMAP 连接到 Exchange 服务器并获取 IMapMessageInfoCollection,您可以获取 MessageInfo 对象。下面的代码片段展示了如何使用该对象的序列号 MessageInfo 对象用于保存特定消息。

// For complete examples and data files, please go to https://github.com/aspose-email/Aspose.Email-for-.NET
// Select the Inbox folder
imapClient.SelectFolder(ImapFolderInfo.InBox);
// Get the list of messages
ImapMessageInfoCollection msgCollection = imapClient.ListMessages();
foreach (ImapMessageInfo msgInfo in msgCollection)
{
    // Fetch the message from inbox using its SequenceNumber from msgInfo
    MailMessage message = imapClient.FetchMessage(msgInfo.SequenceNumber);

    // Save the message to disc now
    message.Save(dataDir + msgInfo.SequenceNumber + "_out.msg", SaveOptions.DefaultMsgUnicode);
}

设置首选加密协议

EWS 对支持的操作使用 HTTPS 传输协议。加密由 SSL/TLS 协议提供。这些协议由 .NET 框架实现,可能会因当前 .NET 框架版本而有所不同。

要设置 SSL/TLS 版本,请使用以下代码:

var client = new ImapClient("some.host");
client.SupportedEncryption = EncryptionProtocols.Tls13;

var client = new ImapClient("some.host");
client.SetSupportedEncryptionUnsafe(EncryptionProtocols.Tls13);

注意,如果当前 .NET 框架版本不支持指定的 EncryptionProtocol,则 SupportedEncryption 属性将加密协议降级到受支持的级别,并且 SetSupportedEncryptionUnsafe 方法抛出异常。

使用现代身份验证连接 Exchange Server

现代身份验证现已默认在所有新 Microsoft 365/Azure 租户中启用,因为该协议比已弃用的基础身份验证更安全。

现代身份验证基于 Active Directory Authentication Library 和 OAuth 2.0。它使用时间限制的令牌,应用程序不存储用户凭据。

先决条件设置

要使用现代身份验证,请确保已启用它。然而,对于 2017 年 8 月 1 日之前创建的租户,默认情况下现代身份验证是关闭的。在 Microsoft 365 管理中心,前往 设置 > 组织设置 > 现代身份验证。在出现的 现代身份验证弹出窗口 中,您可以识别不再需要基础身份验证的协议。对于 Azure 中的新 Microsoft365 租户,默认情况下所有应用的基础身份验证均已禁用。因此,本文本将显示在此部分。

您的组织已启用安全默认值,这意味着需要使用现代身份验证访问 Exchange Online,且基础身份验证连接被阻止。> 必须在 Azure 门户中关闭安全默认值后才能更改此处的任何设置。

您可以从以下位置为租户启用基础身份验证支持 Azure 门户,前往 Azure Active Directory > 属性 > 管理安全默认值 > 启用安全默认值 > 否。更多信息,请参阅 Microsoft 文档文章.

在 Azure Active Directory 中进行应用注册

需要在 Azure Active Directory 中进行应用注册。可用于通过应用访问邮箱的权限有两种类型。根据您创建的应用选择特定的权限类型:

  • 使用 委托权限 的应用需要有已登录用户。换句话说,当您连接到服务时,会出现用于输入用户名和密码的对话框。应用永远不会拥有比已登录用户更多的权限。
  • 使用 应用程序权限 的应用在没有已登录用户的情况下运行。例如,这些是作为后台服务或守护进程运行的应用。只有管理员可以同意应用程序权限。

另外,请参阅 Microsoft 文档文章 了解更多信息。

注册过程取决于所选的权限类型。要注册您的应用,请参阅 Microsoft 文档文章.

使用现代身份验证与 EWSClient

注册应用后,我们可以专注于编写代码,代码将包括以下部分:

  • 获取授权令牌。
  • 使用令牌进行身份验证。

获取授权令牌

要获取令牌,我们将使用 Microsoft Authentication Library (MSAL) for .NET.

以下是获取授权令牌的步骤。

  • 添加 Microsoft.Identity.Client NuGet 包 其中包含 MSAL.NET 的二进制文件。
  • 创建 AccessParameters 类来存储凭据。
  • 创建一个接受访问参数并使用 MSAL.NET 获取访问令牌的方法。

以下代码示例将取决于所选择的身份验证类型。

使用委托身份验证获取令牌

public class AccessParameters
{
    public string TenantId { get; set; }
    public string ClientId { get; set; }
    public string RedirectUri { get; set; } = "http://localhost";
    public string[] Scopes { get; set; } = { "https://outlook.office365.com/EWS.AccessAsUser.All" };
}

public static async Task<string> GetAccessToken(AccessParameters accessParameters)
{
    var pca = PublicClientApplicationBuilder
                            .Create(accessParameters.ClientId)
                            .WithTenantId(accessParameters.TenantId)
                            .WithRedirectUri(ccessParameters.RedirectUri)
                            .Build();

    var result = await pca.AcquireTokenInteractive(accessParameters.Scopes)
        .WithUseEmbeddedWebView(false)
        .ExecuteAsync();

    return result.AccessToken;
}

使用应用程序身份验证获取令牌

public class AccessParameters
{
    public string TenantId { get; set; }
    public string ClientId { get; set; }
    public string ClientSecret { get; set; }
    public string[] Scopes { get; set; } = { "https://outlook.office365.com/.default" };
}

public static async Task<string> GetAccessToken(AccessParameters accessParameters)
{
    var cca = ConfidentialClientApplicationBuilder
        .Create(accessParameters.ClientId)
        .WithClientSecret(accessParameters.ClientSecret)
        .WithTenantId(accessParameters.TenantId)
        .Build();

    var result = await cca.AcquireTokenForClient(accessParameters.Scopes).ExecuteAsync();

    return result.AccessToken;
}

使用令牌进行身份验证

之后,当我们成功获取令牌后,让我们初始化 EwsClient.

使用委托身份验证的令牌

NetworkCredential credentials = new OAuthNetworkCredential(accessToken);

using var client = EWSClient.GetEWSClient("https://outlook.office365.com/EWS/Exchange.asmx", credentials);

使用应用身份验证的令牌

// Use Microsoft365 username and access token
NetworkCredential credentials = new OAuthNetworkCredential(username, accessToken);

using var client = EWSClient.GetEWSClient("https://outlook.office365.com/EWS/Exchange.asmx", credentials);

使用现代身份验证的 IMAP、POP 或 SMTP 客户端

不支持通过应用程序权限访问 IMAP、POP、SMTP。换句话说,仅支持委托身份验证。

Azure Active Directory 应用注册过程已定义 上述.

在 Microsoft 365 管理中心启用或禁用 IMAP、POP、SMTP 身份验证

  • 打开 Microsoft 365 管理中心 并转到 用户 > 活跃用户
  • 选择用户,在出现的侧边栏中点击 邮件
  • 电子邮件应用 部分,点击 管理电子邮件应用
  • 验证 IMAP、POP、已验证的 SMTP 设置:未选中 = 禁用,选中 = 启用。
  • 点击 保存更改

从令牌服务器检索身份验证令牌

确保指定完整的作用域,包括 Outlook 资源 URLs。

IMAP: https://outlook.office.com/IMAP.AccessAsUser.All POP: https://outlook.office.com/POP.AccessAsUser.All SMTP: https://outlook.office.com/SMTP.Send

要获取令牌,我们将使用 Microsoft Authentication Library (MSAL) for .NET.

以下是获取授权令牌的步骤。

  • 添加 Microsoft.Identity.Client NuGet 包 其中包含 MSAL.NET 的二进制文件。
  • 创建 AccessParameters 类来存储凭据。
  • 创建一个接受访问参数并使用 MSAL.NET 获取访问令牌的方法。
public class AccessParameters
{
    public string TenantId { get; set; }
    public string ClientId { get; set; }
    public string RedirectUri { get; set; } = "http://localhost";
    public string[] Scopes { get; set; } = { 
        "https://outlook.office.com/IMAP.AccessAsUser.All", 
        "https://outlook.office.com/SMTP.Send" };
}

public static async Task<string> GetAccessToken(AccessParameters accessParameters)
{
    var pca = PublicClientApplicationBuilder
                            .Create(accessParameters.ClientId)
                            .WithTenantId(accessParameters.TenantId)
                            .WithRedirectUri(ccessParameters.RedirectUri)
                            .Build();

    var result = await pca.AcquireTokenInteractive(accessParameters.Scopes)
        .WithUseEmbeddedWebView(false)
        .ExecuteAsync();

    return result.AccessToken;
}

使用令牌进行身份验证

之后,当我们成功获取令牌后,让我们初始化 ImapClient.

var imapClient = new ImapClient(
    "outlook.office365.com", 
    993, 
    username, 
    accessToken, 
    true);

同样, SmtpClient 初始化将如下所示。

var smtpClient = new SmtpClient(
    "smtp.office365.com",
    587, 
    username,
    accessToken, 
    true);

返回客户端请求 ID

ReturnClientRequestId 已在 EWSClient 中添加属性,方便您指定是否应在 Exchange Web Services(EWS)调用的响应中返回客户端请求 ID。客户端请求 ID 是您可以为应用程序发送的每个 EWS 请求设置的唯一标识符。通过设置该 ReturnClientRequestId 将属性设为 true,表示您希望在 EWS 服务器的响应中包含客户端请求 ID。这在多个请求异步发起并处理的场景中,有助于跟踪和关联请求与响应。

以下代码片段展示了如何使用该属性:

using (IEWSClient client = TestUtil.CreateEWSClient(user))
{
   // Client will create random id and pass it to the server.
   // The server should include this id in request-id header of all responses.
   client.ReturnClientRequestId = true;
   
   client.LogFileName = "ews.log";
   client.GetMailboxInfo();
}

向 EWS 请求添加 X-AnchorMailbox 及其他标头

Aspose.Email API 允许向 Exchange 请求添加标头。这可用于向 EWS 请求添加不同用途的标头。例如,可添加用于管理 Exchange 服务器限流问题的 X-AnchorMailbox 标头。 AddHeader 方法的 IEWSClient 用于向 EWS 请求添加标头,如下代码片段所示。

忽略或绕过无效或已过期的 SSL 证书

Aspose.Email 可以使用以下两种方式处理 Exchange Server 上的 SSL 证书 ExchangeClientEWSClient 类。如果 SSL 证书已过期或失效,Aspose.Email 会因无效的 SSL 证书抛出异常。通过使用下面代码中的方法忽略它们,以避免此类 SSL 证书错误。在您的 main() 或 init() 方法中注册回调处理程序,并将下面的方法添加为类的成员。