从.msg获取特定命名的MAPI属性的问题

本文关键字:MAPI 属性 问题 msg 获取 | 更新日期: 2023-09-27 18:01:36

我在c#控制台应用程序中从MailItem获得一对"自定义" MAPI属性时遇到了类似的问题,但额外的扭转是它在本地工作,而不是在服务器上。

这两个属性是PR_SERVERID和PR_MSGID,当通过MFCMAPI检查时,它们都可以在邮件项上使用,我按照以下方式访问它们:

MessageDetails.PR_SERVERID = Message.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/PR_SERVERID").ToString();
MessageDetails.PR_MSG_ID = Message.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/PR_MSGID").ToString();

其中Message类型为Outlook.MailItem。当我在本地运行时(从构建的exe或调试中),它可以工作,但在单独的服务器上,完全相同的消息失败:

15:17:26 Error getting getting MAPI properties from the stub: 
System.ApplicationException: System.Runtime.InteropServices.COMException (0x8004010F): 
The property "http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/PR_SERVERID" is unknown or cannot be found.

在此之前,我成功地从同一项检索两个"标准"MAPI属性(PR_CREATOR_NAME和PR_INTERNET_MESSAGE_ID),因此MailItem是可访问的。

MFCMAPI中显示的属性的DASL在两台服务器和我的本地机器之间是相同的,并且都运行Outlook 2010并通过调用Outlook会话访问mailItem。

我唯一能想到的是Outlook本身无法识别自定义属性,如果没有远程服务器上缺失的一些配置,Outlook是否必须在命名空间级别配置属性以使其被识别,即使被DASL识别?

编辑:邮件项目的附加信息:邮件是从存档系统下载的"存根",这两个属性为"完整"消息内容提供了标识符。我从远程服务器下载存根,将其保存在本地,然后使用:

访问集合中的每个存根。
Outlook.NameSpace NS = _outlookApplication.GetNamespace("MAPI");
Object item = _outlookApplication.Session.OpenSharedItem(MessageDetails.FilePath)
Outlook.MailItem Message = (Outlook.MailItem)item;

并试图通过从Message获得属性来将两个属性添加到MessageDetails对象。

编辑2:<罢工>我注意到,当检索"新鲜"主机上的属性时,当我访问自定义属性时,我得到一个安全提示"程序正在试图访问存储在Outlook中的电子邮件地址信息",但是当我从标准属性访问主题行/发件人等时,不是。这似乎表明,当使用outlook通过COM互操作访问这些自定义属性时,有些东西是"不同的"。没关系,这只是在调用PropertyAccessor.GetProperty时的默认保护。

答:Dmitry说得很对,我把他的回答标记为答案,这些属性无法访问,因为它们从未在商店中创建过。对于用户机器,创建这些属性是因为我们在某个时候将邮件"存档"到远程存储中,并在邮箱中留下的存根上设置自定义属性。在服务器上,这从来没有做过,所以我为"第一次运行"添加了一个选项,创建一个虚拟对象,设置两个空的自定义属性,保存它,然后删除它。随后的运行可以使用PropertyAccessor.GetProperty访问属性。

从.msg获取特定命名的MAPI属性的问题

Outlook Object Model总是假设字符串中的属性为PT_UNICODE/PT_STRING8类型。名称空间。在你的例子中,类型是PT_LONG (0x0003)。

作为测试,你可以安装Redemption(我是它的作者),并尝试以下脚本从OutlookSpy(我也是它的作者-点击脚本,粘贴脚本,点击运行)

  set Session = CreateObject("Redemption.RDOSession")
  Session.MAPIOBJECT = Application.Session.MAPIOBJECT
  set Msg = Session.GetMessageFromMsgFile("c:'temp'yourmsg.msg")
  MsgBox Msg.Fields("http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/PR_SERVERID/0x00000003")

在代码失败的机器上,在OutlookSpy中尝试以下脚本。当IMessage窗口弹出时,您看到命名属性了吗?

set msg = Application.Session.OpenSharedItem("c:'temp'yourmsg.msg")
BrowseObject(msg.MAPIOBJECT)

我猜服务器上没有安装{00020329-0000-0000-C000-000000000046}定义的接口。在它工作的机器上搜索它(例如使用Regedit),并注意它与什么dll相关联(这将在InprocServer32子键中作为默认属性)。然后在服务器上执行同样的操作:它可能根本找不到CLSID。

如果是这种情况,那么您需要安装丢失的dll -以及它的所有依赖项,这意味着它被包裹在包中。