当没有文件夹命名空间时在 MailKit 中打开一个邮件文件夹

Open a mail folder in MailKit when there are no folder namespaces

我们在尝试打开邮件文件夹时在客户端遇到了一些问题,但无法找到它,所以我创建了以下方法来尽力找到邮件文件夹所在的文件夹名称空间在.

private FolderNamespace FindFolderNamespace(ImapClient imapClient, string folderName)
{
    string[] folderNameParts = folderName.Split('/');

    FolderNamespaceCollection folderNamespaces = new FolderNamespaceCollection();
    foreach (FolderNamespace folderNamespace in imapClient.PersonalNamespaces) folderNamespaces.Add(folderNamespace);
    foreach (FolderNamespace folderNamespace in imapClient.SharedNamespaces) folderNamespaces.Add(folderNamespace);
    foreach (FolderNamespace folderNamespace in imapClient.OtherNamespaces) folderNamespaces.Add(folderNamespace);

    Dictionary<FolderNamespace, string> potentialFolderNamespaces = new Dictionary<FolderNamespace, string>();
    foreach (FolderNamespace folderNamespace in folderNamespaces)
    {
        IMailFolder mailFolder = imapClient.GetFolder(folderNamespace);
        foreach (string folderNamePart in folderNameParts)
        {
            if (mailFolder.GetSubfolders().Any(mf => mf.Name.Equals(folderNamePart, StringComparison.OrdinalIgnoreCase)))
            {
                mailFolder = mailFolder.GetSubfolder(folderNamePart);
            }
            else
            {
                break;
            }
        }

        if (mailFolder.FullName.IndexOf(folderName, StringComparison.OrdinalIgnoreCase) >= 0)
        {
            return folderNamespace;
        }

        if (!mailFolder.IsNamespace)
        {
            potentialFolderNamespaces.Add(folderNamespace, mailFolder.FullName);
        }
    }

    FolderNamespace closestFolderNameSpace = potentialFolderNamespaces.OrderByDescending(n => n.Value.Length).FirstOrDefault().Key;
    if (closestFolderNameSpace != null)
    {
        return closestFolderNameSpace;
    }

    FolderNamespace defaultFolderNamespace = folderNamespaces.FirstOrDefault();

    return defaultFolderNamespace;
}

但是,这没有用。仔细检查后,PersonalNamespaces、SharedNamespaces 和 OtherNamespaces 似乎都是空的,因此该帐户没有文件夹命名空间。

作为快速检查,我刚刚尝试了以下操作:

imapClient.GetFolder(folderName)

然而,这引发了一个 ImapProtocolException 说:

The IMAP server has unexpectedly disconnected.

尝试仅使用根文件夹名称也做了同样的事情。

我有点不知道如何打开此帐户上的文件夹,因为我似乎找不到它。我该怎么做?


更多细节:


协议日志:

Connected to --cut--
S: * OK The Microsoft Exchange IMAP4 service is ready. --cut--
C: A00000000 CAPABILITY
S: * CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
S: A00000000 OK CAPABILITY completed.
C: A00000001 AUTHENTICATE XOAUTH2 --cut--
S: A00000001 NO AUTHENTICATE failed.
C: A00000002 AUTHENTICATE PLAIN --cut--
S: A00000002 OK AUTHENTICATE completed.
C: A00000003 CAPABILITY
S: * CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CLIENTACCESSRULES CLIENTNETWORKPRESENCELOCATION BACKENDAUTHENTICATE CHILDREN IDLE NAMESPACE LITERAL+
S: A00000003 OK CAPABILITY completed.
C: A00000004 NAMESPACE
S: A00000004 BAD User is authenticated but not connected.
C: A00000005 LIST "" "INBOX"
S: A00000005 BAD User is authenticated but not connected.
S: * BYE Connection closed. 14

这是问题所在:

C: A00000004 NAMESPACE
S: A00000004 BAD User is authenticated but not connected.
C: A00000005 LIST "" "INBOX"
S: A00000005 BAD User is authenticated but not connected.
S: * BYE Connection closed. 14

身份验证后,MailKit 发送 NAMESPACE 命令从服务器获取命名空间列表,但它以一个无意义的错误响应,声称客户端已通过身份验证但未连接(呃,那是不可能的,或者我们不会发送命令或接收响应,呃)。

当 MailKit 收到 NAMESPACE 命令的 BAD 响应时,它会回退到尝试获取 INBOX 文件夹的信息...为此它会返回相同的 BAD 错误,这毫无意义。

结论:IMAP 服务器坏了。

可能的解决方案(除了获得一个不烂的新 IMAP 服务器):

此日志看起来像是使用旧 MailKit 版本(1.1?)获取的,因此请在调用 Authenticate("username", "password"):

之前尝试这样做
client.AuthenticationMechanisms.Remove ("XOAUTH2");

如果 仍然 导致 BAD NAMESPACE 命令,那么我不确定可以做什么...

更新:

基于 https://unix.stackexchange.com/questions/164823/user-is-authenticated-but-not-connected-after-changing-my-exchange-password - 听起来 Exchange IMAP 有一个错误,如果用户名正确但密码错误,Exchange IMAP 服务器将 "authenticate" 用户但进入这个"authenticated but not connected" 的奇怪状态导致出现上述错误。

解决方法是提供正确的密码。