通过Outlook和Redemption发送电子邮件时的AV

时间:2011-04-25 14:24:31

标签: delphi delphi-7 outlook-redemption

这是我的代码:

const
 olMailItem = 0;

var
 olApp, OlNameSpace, OlItem, rdSafeItem, rdUtils: variant;

begin
 olApp:= CreateOleObject ('Outlook.Application');
 olNameSpace:= olApp.GetNamespace ('MAPI');
 olNameSpace.Logon;
 olItem:= olApp.CreateItem (olMailItem);
 rdSafeItem:= CreateOleObject ('Redemption.SafeMailItem');
 rdSafeItem.Item:= olItem;

 rdSafeItem.Subject:= 'Testing';
 rdSafeItem.attachments.Add ('c:\windows\win.ini');
 rdSafeItem.Recipients.Add ('test@testing.com');
 rdSafeItem.Send;
 rdUtils:= CreateOleObject ('Redemption.MAPIUtils');
 rdUtils.DeliverNow;
 olNameSpace.Logoff;
 varclear (rdUtils);
 varclear (rdSafeItem);
 varclear (olItem);
 varclear (olNameSpace);
 varclear (olApp);
end;

发送电子邮件后,我收到地址为A70D6D13的访问违规消息(此地址似乎是不变的)。如果我使用F8逐步执行整个过程,在'end'语句之后,CPU窗口将显示在地址A70D6D13,显示所有内存为????。

我正在使用Delphi 7,Outlook 2003,Redemption 4.8.0.1184 这段代码缺少什么?

编辑: 我找到了一些其他代码片段来通过Outlook / Redemption发送邮件。以下是使用OutlookApplication服务器的一个此类代码段。

begin
 outlookapplication1.Connect;
 NmSpace:= outlookapplication1.GetNamespace('MAPI');
 NmSpace.Logon('', '', False, False);
 oItem:= outlookapplication1.CreateItem(olMailItem);
 sItem:= CreateOleObject('Redemption.SafeMailItem');
 oItem.Subject:= 'my subject';
 oItem.save;
 sItem.Item:= oItem;
 sItem.Recipients.Add('test@test.com');
 sItem.Attachments.Add('C:\windows\win.ini');
 sItem.save;
 SItem.send;
 outlookapplication1.Disconnect;
end;

这也给出了同样的错误。 AV的地址有什么神奇之处?它必须是解决方案的线索。

TIA,

No'am

5 个答案:

答案 0 :(得分:0)

尝试删除varclear语句。

您所描述的症状表明您正在设法从例程中的内存中驱逐COM对象,然后当方法变量超出范围时,Delphi会尝试再次释放它们。

答案 1 :(得分:0)

<强>更新

正如No'am正确评论的那样,Outlook的应用程序COM接口不支持Connect和Disconnect。我很惊讶,但我通常使用Delphi包装器,而实际上TOutlookApplication的Connect实现只返回CreateOleObject或GetActiveObject的结果。 TOutlookApplication的Disconnect方法的实现实际上不仅仅是发布接口。如果AutoQuit为true,则在应用程序的COM接口上调用Quit。

然而,由于它似乎是可选的,我认为不要叫olApp.Quit不应该导致No'am有问题。留下我的答案作为“教育”材料,所以其他人不必检查这个。


不确定这实际上是您的问题的原因,但我在您的代码中遗漏的是与Outlook应用程序的连接和断开连接。虽然他们显然不需要使用Outlook COM服务器(正如发送邮件所建议的那样),但它们是我所知道的“正常”COM使用模式的一部分。我可以想象,当vars超出范围(在结束语句之后)触发时,不连接/断开连接可能会导致终结代码失效。

我通常使用的模式是:

Create / CreateOleObject
try
  Connect
  try
    ...
  finally
    Disconnect
  end
finally
  Free / Release 
end

如果您使用“直接”COM,则在使用Delphi提供的TxxxApplication包装器,CreateOleObject和释放界面(将其设置为nil / unassigned)时,您将使用Create和Free。

在您的示例中,这意味着要添加

olApp.Connect;

在CreateOleObject和olNameSpace赋值行之间,并添加

olApp.Disconnect;
    之后的olNameSpace.LogOff;

    添加几个try / finally块也不会浪费。

答案 2 :(得分:0)

我正在使用Redemption 5.0.0.2174,Delphi 7,Outlook 2003

我按如下方式修改了您的代码,并且能够发送没有任何错误的电子邮件

const
 olMailItem = 0;
var
 olApp, OlNameSpace, OlItem, rdSafeItem, rdUtils: variant;
begin
 olApp:= CreateOleObject ('Outlook.Application');
 olNameSpace:= olApp.GetNamespace ('MAPI');
 olNameSpace.Logon;
 olItem:= olApp.CreateItem (olMailItem);
 rdSafeItem:= CreateOleObject ('Redemption.SafeMailItem');
 rdSafeItem.Item:= olItem;
 rdSafeItem.Subject:= 'Testing';
 rdSafeItem.attachments.Add ('c:\windows\win.ini');
 rdSafeItem.Recipients.Add ('test@testing.com');
 rdSafeItem.Recipients.ResolveAll;                       // added
 rdSafeItem.Send;
// rdUtils:= CreateOleObject ('Redemption.MAPIUtils');
// rdUtils.DeliverNow;
 olNameSpace.Logoff;
// varclear (rdUtils);
// varclear (rdSafeItem);
// varclear (olItem);
// varclear (olNameSpace);
// varclear (olApp);
end;

答案 3 :(得分:0)

首先,没有理由使用DeliverNow - MS在OUtlook 2002中打破了它: http://www.dimastr.com/redemption/faq.htm#1

其次,如果你忘掉了Logoff语句,它会起作用吗? 如果Outlook已经在运行,您需要小心 - 如果用户正在运行它,则不希望将其终止。

答案 4 :(得分:0)

你在结束语句中得到错误,这意味着在清理一些临时变量时可能会抛出错误。也许它会清除rdSafeItem.Recipients的临时变量或与CreateOleObject一起使用的某个中间变量。你可以做的是将你的代码分成更小的部分,在那些较小的程序中完成所有与com相关的东西(至少是使用中间变量的程序),而不是在你的main方法中。这可以更容易地追踪问题,甚至可以解决问题。

这样的事情:

function CreateOutlookApp: OleVariant;
begin
  Result := CreateOleObject ('Outlook.Application');
end;

function GetAndLogonNamespace(const olApp: OleVariant): OleVariant;
begin
  Result := olApp.GetNamespace ('MAPI');
  Result.Logon;
end;

function GetSafeMailItem(const olApp: OleVariant): OleVariant;
const
 olMailItem = 0;
var
  olItem: OleVariant;
begin
  olItem:= olApp.CreateItem (olMailItem);
  Result := CreateOleObject ('Redemption.SafeMailItem');
  Result.Item:= olItem;

  Result.Subject:= 'Testing';
  Result.attachments.Add ('c:\windows\win.ini');
  Result.Recipients.Add ('test@testing.com');
end;

procedure SendTestMail;
var
 olApp, olNameSpace, rdSafeItem: OleVariant
begin
 OutputDebugString('CreateOutlookApp');
 olApp := CreateOutlookApp;
 OutputDebugString('GetAndLogonNamespace');
 olNameSpace := GetAndLogonNamespace(olApp);
 OutputDebugString('GetSafeMailItem');
 rdSafeItem := GetSafeMailItem(olApp);
 OutputDebugString('rdSafeItem.Send');
 rdSafeItem.Send;
 OutputDebugString('DeliverNow');
 DeliverNow; //implement this yourself
 OutputDebugString('LogoffNamespace');
 LogoffNamespace(olNamespace); //implement this yourself
 OutputDebugString('Cleaning up');
end;

编辑:添加了OutputDebugStrings,因为只有在没有调试器的情况下运行应用程序时才会出现错误。当您找到有问题的功能时,可以在那里添加更多的OutputDebugStrings。