1

Here is my code:

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;

After the email is sent, I get an access violation message at address A70D6D13 (this address seems to be constant). If I step through the entire procedure with F8, after the 'end' statement, the CPU window gets displayed at address A70D6D13, showing all the memory as ????.

I'm using Delphi 7, Outlook 2003, Redemption 4.8.0.1184 What is missing from this code?

EDIT: I've found a few other code snippets to send mail via Outlook/Redemption. Here is one such snippet which uses the OutlookApplication server.

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;

This too gives the same error. What is magical about the address of the AV? It must be a clue to the solution.

TIA,

No'am

No'am Newman
  • 6,395
  • 5
  • 38
  • 50
  • Really clutching at straws here - have you tried using the `OleVariant` type, rather than `Variant` in your parameter declarations? – Steve Mayne Apr 25 '11 at 15:41
  • Please show declaration of variables in your second code snippet. – crefird Apr 29 '11 at 01:23
  • I just tried both of your code snippets with a fresh install of Redemption 4.4, both ran without errors. So I suspect your problem may be related to the installation of Redemption and its type lib. I suggest you uninstall Redemption, remove all copies of the dll and tlb from your disk, then reinstall it. – crefird Apr 29 '11 at 17:38

5 Answers5

0

Try dropping the varclear statements.

The symptoms you're describing suggest that you're managing to evict the COM objects from memory in the routine, and then Delphi's trying to release them again when the method variables go out of scope.

Steve Mayne
  • 22,285
  • 4
  • 49
  • 49
  • Alas, removing the 'varclear' statements, or changing them to 'olApp:= unassigned' makes no difference. Even after rebooting, I'm getting the same error message with the same address. – No'am Newman Apr 25 '11 at 14:48
0

Update

As No'am rightly commented, Outlook's application COM interface does not support Connect and Disconnect. I was suprised at that, but I normally use the Delphi wrappers and indeed TOutlookApplication's implementation of Connect just returns the result of the CreateOleObject or GetActiveObject. The implementation of TOutlookApplication's Disconnect method, actually does something more than just releasing interfaces. If AutoQuit is true it calls Quit on the Application's COM interface.

However, as it seems to be optional, I think not calling olApp.Quit should not cause the problems No'am is having. Leaving my answer as "educational" material and so others don't have to check this.


Not sure this is actually the cause of your problem, but what I miss in your code is the connect to and disconnect from the Outlook Application. Although they apparently are not needed to use the Outlook COM server (as suggested by the mail being sent), they are part of the "normal" COM use patterns I know. I can well imagine that not connecting/disconnecting may well cause finalization code to fall over when that is triggered by the vars going out of scope (after the end statement).

The pattern I normally use is:

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

You would use Create and Free when using one of the Delphi provided TxxxApplication wrappers, CreateOleObject and Releasing the interface (setting it to nil/unassigned) if you are using "straight" COM.

In your example that would mean adding

olApp.Connect;

between the CreateOleObject and olNameSpace assignment lines, and adding

olApp.Disconnect;

after the olNameSpace.LogOff;

Adding a couple of try/finally blocks also wouldn't be wasted.

Marjan Venema
  • 19,136
  • 6
  • 65
  • 79
0

I am using Redemption 5.0.0.2174, Delphi 7, Outlook 2003

I modified your code as follows and was able to send an email without any errors

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;
crefird
  • 1,590
  • 11
  • 17
0

Firstly, there is no reason to use DeliverNow - MS broke it in Outlook 2002: http://www.dimastr.com/redemption/faq.htm#1

Secondly, try to get rid of the Logoff statement. You need to be careful if Outlook is already running - you don't want to kill it if a user is running it.

Dmitry Streblechenko
  • 62,942
  • 4
  • 53
  • 78
0

You get the error at the end statement, that means the error is probably thrown when it is cleaning up some temporary variables. Maybe its the cleaning up the temp var for rdSafeItem.Recipients or some intermediate variable that is used with CreateOleObject. What you can do is chop up your code into smaller pieces, doing ALL the com related stuff in those smaller procedures (at least the ones that use intermediate variables) and not in your main method. This can make it easier to track down the problem or maybe it even fixes the problem.

Something like this:

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;

Edit: added OutputDebugStrings because the error only seems to happen when the application is run without the debugger. When you find the offending function, you can add more OutputDebugStrings there.

The_Fox
  • 6,992
  • 2
  • 43
  • 69
  • After correcting the syntax of the above (the procedures should be functions, CreateSafeMailItem is later referred to as GetSafeMailItem - but never mind), the program gives exactly the same error message when run as a standalone program. When run via F8, the program works fine with no error! I don't understand this behaviour. I'm going to download a new version of Redemption and see whether that makes any difference. – No'am Newman Apr 26 '11 at 14:56
  • A newer version of Redemption didn't make any difference. – No'am Newman Apr 26 '11 at 15:03
  • @No'am Newman: I corrected the typos. What you can do to further diagnose the problem: Add OutputDebugStrings before and after calling the functions. Then start DbgView.exe and run your application outside the debugger. When you get the error, check dbgview.exe to see which function failed. – The_Fox Apr 27 '11 at 11:46
  • Is that a console app? Does it work if you display a message box (to let the Windows message loop run) before before you release all variables? – Dmitry Streblechenko Apr 27 '11 at 14:24