I have the following code in my test Delphi 2006 BDS application:
procedure TForm1.Button1Click(Sender: TObject);
const
olMailItem = 0;
var
Outlook: OleVariant;
vMailItem: variant;
begin
Outlook := CreateOleObject('Outlook.Application');
vMailItem := Outlook.CreateItem(olMailItem);
try
vMailItem.Recipients.add('[email protected]');
vMailItem.Display(True); -- outlook mail message is displayed modally
except
end;
VarClear(Outlook);
end;
I need to be able to detect whether the user sent the email from within the outlook screen. I tried the following code:
if vMailItem.Sent then
...
But received the error message 'The item has been moved or deleted'. I presume this is because the mail item has moved to the sent items folder. What is the best way to detect if the user sent the email? Also, if the user did send the email then I would also need to be able to view the email body.
Thanks in advance.
It would seem you have to use the Send Event
of the mail item. This would be a lot easier if you were using early binding, put one of the 'outlook[*].pas' files in the '..\OCX\Servers' folder of RAD studio in the 'uses' clause, then:
uses
..., outlook2000;
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
OutlookApplication: TOutlookApplication;
procedure OnMailSend(Sender: TObject; var Cancel: WordBool);
public
end;
[...]
procedure TForm1.FormCreate(Sender: TObject);
begin
OutlookApplication := TOutlookApplication.Create(Self);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MailItem: _MailItem;
Mail: TMailItem;
begin
MailItem := OutlookApplication.CreateItem(olMailItem) as _MailItem;
Mail := TMailItem.Create(nil);
try
Mail.ConnectTo(MailItem);
Mail.OnSend := OnMailSend;
MailItem.Recipients.Add('[email protected]');
MailItem.Display(True);
finally
Mail.Free;
end;
end;
procedure TForm1.OnMailSend(Sender: TObject; var Cancel: WordBool);
begin
ShowMessage((Sender as TMailItem).Body);
end;
With late binding, you'd have to do some of the work which the imported wrapper does. The simplest example could be something like this:
type
TForm1 = class(TForm, IDispatch)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
FCookie: Integer;
FMailItem: OleVariant;
procedure MailSent;
protected
function QueryInterface(const IID: TGUID; out Obj): HResult; override;
function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
stdcall;
public
end;
[...]
uses
comobj;
const
DIID_ItemEvents: TGUID = '{0006303A-0000-0000-C000-000000000046}';
SendItemDispID = 61445;
function TForm1.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if IsEqualIID(IID, DIID_ItemEvents) and GetInterface(IDispatch, Obj) then
Result := S_OK
else
Result := inherited QueryInterface(IID, Obj);
end;
function TForm1.Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult;
begin
Result := S_OK;
if DispID = SendItemDispID then
MailSent;
end;
procedure TForm1.Button1Click(Sender: TObject);
const
olMailItem = 0;
var
Outlook: OleVariant;
CPContainer: IConnectionPointContainer;
ConnectionPoint: IConnectionPoint;
begin
Outlook := CreateOleObject('Outlook.Application');
FMailItem := Outlook.CreateItem(olMailItem);
FMailItem.Recipients.add('[email protected]');
if Supports(FMailItem, IConnectionPointContainer, CPContainer) then begin
CPContainer.FindConnectionPoint(DIID_ItemEvents, ConnectionPoint);
if Assigned(ConnectionPoint) then
ConnectionPoint.Advise(Self, FCookie);
CPContainer := nil;
end;
FMailItem.Display(True);
if Assigned(ConnectionPoint) then begin
ConnectionPoint.Unadvise(FCookie);
ConnectionPoint := nil;
end;
VarClear(FMailItem);
VarClear(Outlook);
end;
procedure TForm1.MailSent;
begin
ShowMessage(FMailItem.Body);
end;