【问题标题】:is there a way to get the smtpaddress for an mapifolder or outlook interop folder given the entryid (or storeid)有没有办法在给定 entryid(或 storeid)的情况下获取 mapifolder 或 Outlook 互操作文件夹的 smtpaddress
【发布时间】:2022-04-03 01:09:23
【问题描述】:

如果我有一个 mapifolder 的 storeid,通过文件夹选择器从 Outlook 互操作库中选择,有没有办法让我获取该文件夹的 smtpaddress?

我知道它在扩展属性中,但我希望在没有任何繁重的解析或 ldap 查询的情况下做到这一点。

我需要 smtpaddress 的原因是为了通过 EWS 连接到文件夹 - 我目前正在尝试用 Exchange Web 服务替换我们对 Outlook 互操作的引用,这已成为一个症结所在,因为我们的许多用户拥有对不属于他们的邮箱的委托访问权限

【问题讨论】:

  • 一般来说,文件夹没有 SMTP 地址。你的意思是文件夹ID吗?
  • 我没有 - 我的意思是文件夹所在邮箱所有者的 smtpaddress。为了获取 mapifolder 的 entryid 属性并将其转换为交换 Web 服务商店 ID,我需要提供邮箱所有者的smtpaddress。 here 是 idformat 的枚举。这样我就可以转换为here
  • 达到上一条评论的编辑限制this 是我想做的,但是当我使用文件夹选择器选择另一个用户邮箱中的文件夹(我有权访问)时,我得到了该帐户没有任何回报

标签: outlook


【解决方案1】:

我知道那是几年后的事了(抱歉),但我需要为一堆邮箱获取 SMTP 地址,而接受的答案不起作用(因为我有离线商店)所以我做了解析。

public static bool TryGetSmtpAddress(MAPIFolder folder, out string smtpAddress)
{
    smtpAddress = default;

    var storeId = HexToBytes(folder.StoreID);

    // check it's a store entry id
    if (BitConverter.ToUInt64(storeId, 4) != 0x1A10E50510BBA138UL
        || BitConverter.ToUInt64(storeId, 12) != 0xC2562A2B0008BBA1UL) { return false; }

    var indexDn = Array.IndexOf(storeId, (byte)0x00, 60) + 1;
    var indexV3Block = Array.IndexOf(storeId, (byte)0x00, indexDn) + 1;

    // check it's a V3 entry id (with SMTP address)
    if (BitConverter.ToUInt32(storeId, indexV3Block) != 0xF43246E9UL) { return false; }

    var offsetSmtpAddress = BitConverter.ToUInt32(storeId, indexV3Block + 12);

    smtpAddress = BytesToUnicode(storeId, indexV3Block + (int)offsetSmtpAddress);
    return true;
}

private static byte[] HexToBytes(string input)
{
    var bytesLength = input.Length / 2;
    var bytes = new byte[bytesLength];
    for (var i = 0; i < bytesLength; i++) { bytes[i] = Convert.ToByte(input.Substring(i * 2, 2), 16); }
    return bytes;
}

private static string BytesToUnicode(byte[] value, int startIndex)
{
    var charsLength = (value.Length - startIndex) / 2;
    var chars = new char[charsLength];
    for (var i = 0; i < charsLength; i++)
    {
        var c = chars[i] = BitConverter.ToChar(value, startIndex + i * 2);
        if (c == '\0') { return new String(chars, 0, i); }
    }
    return new String(chars);
}

【讨论】:

    【解决方案2】:

    对于邮箱所有者,您可以尝试读取MAPIFolder.Store 属性以获取父存储,然后使用Store.PropertyAccessor.GetProperty 读取PR_MAILBOX_OWNER_ENTRYID 属性(DASL 名称"http://schemas.microsoft.com/mapi/proptag/0x661B0102")。然后,您可以使用店主条目 ID 调用 Namespace.GetAddressEntryFromID。拥有AddressEntry 对象后,您可以使用AddressEntry.GetExchangeUser.PrimarySmtpAddress

    请注意,PR_MAILBOX_OWNER_ENTRYID 属性仅在在线商店中可用。您可能想使用Redemption(我是它的作者)和它的RDOExchangeMailboxStore.Owner.SmtpAddress 属性。可以使用RDOSession.GetRDOObjectfromOutlookObject(Store)RDOSession.GetStoreFromID 检索RDOExchangeMailboxStore

    【讨论】:

    • 这就像一个魅力 - 唯一 id 添加的是 GetProperty 返回一个 byte(),并使用 system.text.encoding 将其转换为字符串无法按预期工作。相反,您需要使用 PropertyAccessor.BinaryToString
    • 不要让它工作:(我取回字节数组,但我无法将其转换为有意义的东西
    • 如果不能选择使用 Redemption,您只能使用 Extended MAPI(仅限 C++ 或 Delphi)进行 - 数据存储在配置文件部分。
    • @Eñaut - 如上所述,PR_MAILBOX_OWNER_ENTRYID 仅在商店缓存时可用。您也可以尝试解析商店条目 id。提取 EX 地址,然后使用它来创建 GAL 条目 ID。
    • 是的,商店入口 id - 在 OutlookSpy 中查看:点击 IMsgStore 按钮,选择 PR_ENTRYID 或 PR_STORE_ENTRYID 属性,查看“Symb”编辑框。
    【解决方案3】:

    NZTony 在 VB.net 中的回答:

    Public Sub test()
            Dim smtpAddress As String
            Dim selectedItem As Outlook.Folder
            smtpAddress = ""
            TryGetSmtpAddress(Application.ActiveExplorer.Selection.Item(1).Parent, smtpAddress)
    End Sub
    
    Public Shared Function TryGetSmtpAddress(ByVal folder As MAPIFolder, ByRef smtpAddress As String) As Boolean
            smtpAddress = "default"
            Dim storeId = HexToBytes(folder.StoreID)
    
            If BitConverter.ToUInt64(storeId, 4) <> &H1A10E50510BBA138UL OrElse BitConverter.ToUInt64(storeId, 12) <> &HC2562A2B0008BBA1UL Then
                Return False
            End If
    
            Dim indexDn = Array.IndexOf(storeId, CByte(&H0), 60) + 1
            Dim indexV3Block = Array.IndexOf(storeId, CByte(&H0), indexDn) + 1
    
            If BitConverter.ToUInt32(storeId, indexV3Block) <> &HF43246E9UL Then
                Return False
            End If
    
            Dim offsetSmtpAddress = BitConverter.ToUInt32(storeId, indexV3Block + 12)
            smtpAddress = BytesToUnicode(storeId, indexV3Block + CInt(offsetSmtpAddress))
            Return True
    End Function
    
        Private Shared Function HexToBytes(ByVal input As String) As Byte()
            Dim bytesLength = input.Length / 2
            Dim bytes = New Byte(bytesLength - 1) {}
    
            For i = 0 To bytesLength - 1
                bytes(i) = Convert.ToByte(input.Substring(i * 2, 2), 16)
            Next
    
            Return bytes
    End Function
    
        Private Shared Function BytesToUnicode(ByVal value As Byte(), ByVal startIndex As Integer) As String
            Dim charsLength = (value.Length - startIndex) / 2
            Dim chars = New Char(charsLength - 1) {}
    
            For i = 0 To charsLength - 1
                Dim c = CSharpImpl.__Assign(chars(i), BitConverter.ToChar(value, startIndex + i * 2))
                If c = vbNullChar Then
                    Return New String(chars, 0, i)
                End If
            Next
    
            Return New String(chars)
    End Function
    
    Private Class CSharpImpl
            <Obsolete("Please refactor calling code to use normal Visual Basic assignment")>
            Shared Function __Assign(Of T)(ByRef target As T, value As T) As T
                target = value
                Return value
            End Function
    End Class
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-18
      • 2015-11-28
      • 1970-01-01
      • 2022-07-13
      • 2015-10-29
      • 2011-06-04
      • 2013-07-09
      • 1970-01-01
      相关资源
      最近更新 更多