使用 Redemption.SafeMailItem 时出错 - OLE 错误 8004010E(MAPI_E 资源不足)

Error when using Redemption.SafeMailItem - OLE error 8004010E(MAPI_E NOT ENOUGH RESOURCES)

在我工作的公司中,我们使用兑换来发送来自旧 Delphi 客户的电子邮件。我们用了很多年了,升级到Office365-outlook 1906后就开始出现这个错误。

我们所有的软件版本都会出现这个问题,从 5 年前的版本到我们几天前编译的版本。

该错误是随机发生的,但是一旦发生,它将一直持续到整个机器重新启动。所以通常重启后几个小时可以再次发送邮件,但最终还是会再次出现错误。

创建uSafeMailItem时出现错误 Office365以前版本(Outlook 1906之前)不会出现该错误

我们记录的错误是 OLE 错误 8004010E,ProgID:"UnikOR.uSafeMailItem" 又名 MAPI_E 资源不足(UnikOR.uSafeMailItem 等于 Redemption.SafeMailItem)

经过这么多天的调查,我们似乎已经得出结论,要么是救赎,要么更可能是我们使用救赎的方式什么的?

我们测试了 outlook 和 windows

的组合

Windows 和 outlook 版本

  1. Windows 10 企业 1803

    • Outlook 1904(工作)
    • Outlook 1906(失败)
  2. Windows 10 企业 1809

    • Outlook 1904(工作)
    • Outlook 1906(失败)
  3. Windows 10 企业 1903

    • Outlook 1904(工作)
    • Outlook 1906(失败)

我们已经通过名为 VMMap 的工具检查了 outlook 中的可用内存

我还可以看到 outlook 有一些死进程挂起。但我不确定这是否与救赎有关

我还启用了 Outlook 日志记录并收到了一个日志文件 (OUTLOOK-20190806T1236220570-v2.etl)。但是,我似乎没有发现任何可能与 Redemption 及其调用 outlook 的方式相关的内容。

我们还查看了 Procmon 和 Fuslogvw,但没有任何运气。

下面的这段代码创建了对象

function TSendEmail.SendOutlookEmailUsingRedemption(Outlook: Olevariant; OutlookEmailFileName: string; var Email: TStream; var Subject: string; var HasAttachments: Boolean; UseOutlookSignatur: Boolean): TMailSendResult;
var
  Utils: IMAPIUtils;
  RDOSession: IRDOSession;
  SentMailFolder: IRDOFolder;
  RDOMailItem: IRDOMail;
  MailInSentFolder: IRDOMail;
  Body: string;
  I: Integer;
  Insp: Variant;
  TempInsp: Variant;
  MailItem: Variant;
  OutlookEntryID: string;
  S: string;
  SafeItem: ISafeMailItem;
  SL: TStringList;
  TempBody: string;
  OutlookSignatur: string;
begin
  Result := msrOK;
  FMailData.MailAttachments.PrepareNotes;
  try
    MailItem := Outlook.CreateItem(olMailItem);
    SafeItem := CreateOLEObject('UnikOR.uSafeMailItem') as ISafeMailItem; // do not localize
    Variant(SafeItem).Item := MailItem;
function TSendEmail.SendOutlookEmail(var Email: TStream; var Subject: string; var HasAttachments: Boolean; UseOutlookSignatur: Boolean): TMailSendResult;
var
  Outlook: Olevariant;
  OutlookEmailFileName: string;
  OutlookEntryID: string;
begin
  try
    OutlookEmailFileName := FTempPath + 'OutlookEmail.msg'; // do not localize
    try
      Outlook := GetActiveOleObject('Outlook.Application'); // do not localize
    except
      Outlook := CreateOleObject('Outlook.Application'); // do not localize
    end;
    if FMailData.UseOutlookRedemption then
      SendOutlookEmailUsingRedemption(Outlook, OutlookEmailFileName, Email, Subject, HasAttachments, UseOutlookSignatur)
    else
      SendOutlookEmailUsingMapi(Outlook, OutlookEmailFileName, Email, Subject, HasAttachments, UseOutlookSignatur);

我们希望它将电子邮件发送到目标电子邮件地址,但是我们的系统使用回退方法来打印文档并向我们发送以下错误“错误:OLE 错误 8004010E,ProgID:"UnikOR.uSafeMailItem""

每次创建可创建的 Redemption 对象时,它都会通过调用 MAPIInitialize 来初始化 MAPI 系统。当它被销毁时,它调用MAPIUnitialize。 Outlook 不喜欢让 MAPI 系统不断循环 - 经验法则是初始化 MAPI 系统一次并保持初始化状态。您可以创建一个 Redemption 对象(例如另一个 SafeMailItem 对象或 RDOSession)一次,并在您的应用程序的整个生命周期内保持其活动状态。