Sending Mail through Delphi via Default Email Application

I am looking at ways to send e-mail via the default mail application through Delphi. I am currently using MAPI to open the e-mail program (SendMail). The problem I am running into is that the window is opening up Modal. I would like to open the form as a normal form and be able to still open and use other windows. I could use ShellAPI to open the e-mail program, but I have read this has problems sending attachments.

Any thoughts on what is the best way to go or how you can use MAPI to open the e-mail Window not modally? Thanks for the insight.
aceswildab1Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
Ephraim WangoyaConnect With a Mentor Commented:
Try running it in a thread. This will let your apllication continue to function while the dialog is displayed
Here is a simple example
unit Unit3;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TMessageSentEvent = procedure(const AResult: Integer; const AError: string) of Object;

  TMAPIThread = class(TThread)
  private
    FErrorMessage: string;
    FMessageSent: TMessageSentEvent;
    FReceiverName, FReceiverAddress, FSenderName, FSenderAddress, FSubject, FBody: AnsiString;
    FSendResult: Integer;
    procedure DoneSend;
  public
    constructor Create(const AReceiverName, AReceiverAddress, ASenderName,
      ASenderAddress, ASubject, ABody: AnsiString; AMessageSent: TMessageSentEvent);
    procedure Execute; override;
  end;

  TForm3 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    FDialogVisible: Boolean;
    FMAPIThread: TMAPIThread;
    procedure MessageSent(const AResult: Integer; const AError: string);
  public
    { Public declarations }
  end;

var
  Form3: TForm3;

implementation

{$R *.dfm}

uses
  MAPI;

  { TMAPIThread }

constructor TMAPIThread.Create(const AReceiverName, AReceiverAddress,
  ASenderName, ASenderAddress, ASubject, ABody: AnsiString;
  AMessageSent: TMessageSentEvent);
begin
  FMessageSent := AMessageSent;
  FReceiverName := AReceiverName;
  FReceiverAddress :=AReceiverAddress;
  FSenderName := ASenderName;
  FSenderAddress := ASenderAddress;
  FSubject := ASubject;
  FBody := ABody;
  FreeOnTerminate := True;

  inherited Create(False);
end;

procedure TMAPIThread.DoneSend;
begin
  if Assigned(FMessageSent) then
    FMessageSent(FSendResult, FErrorMessage);
end;

procedure TMAPIThread.Execute;
var
  MapiMessage: TMapiMessage;
  MsgSender, MsgTarget: TMapiRecipDesc;
  PReceiverName, PReceiverAddress, PSenderName, PSenderAddress, PSubject, PBody: PAnsiChar;
begin
  FillChar(MapiMessage, SizeOf(MapiMessage), 0);
  FillChar(MsgTarget, SizeOf(MsgTarget), 0);
  FillChar(MsgSender, SizeOf(MsgSender), 0);

  //Receiver
  PReceiverAddress := PAnsiChar('SMTP: ' + FReceiverAddress);
  PReceiverName := PAnsiChar(FReceiverName);
  MsgTarget.lpszAddress := PAnsiChar(FReceiverAddress);
  MsgTarget.lpszName := PAnsiChar(FReceiverName);
  MsgTarget.ulRecipClass := MAPI_TO;
  MapiMessage.nRecipCount := 1;
  MapiMessage.lpRecips := @MsgTarget;

  //Sender
  PSenderAddress := PAnsiChar(FSenderAddress);
  PSenderName := PAnsiChar(FSenderName);
  MsgSender.lpszAddress := PAnsiChar(FSenderAddress);
  MsgSender.lpszName := PAnsiChar(FSenderName);
  MsgSender.ulRecipClass := MAPI_ORIG;
  MapiMessage.lpOriginator := @MsgSender;

  //Subject
  PSubject := PAnsiChar(FSubject);
  MapiMessage.lpszSubject := PSubject;

  //Body
  PBody := PAnsiChar(FBody);
  MapiMessage.lpszNoteText := PBody;

  try
    try
      FSendResult := Mapi.MapiSendMail(0, 0, MapiMessage, MAPI_DIALOG or MAPI_LOGON_UI or MAPI_NEW_SESSION or MAPI_ALLOW_OTHERS, 0);
    except
      on E: Exception do
        FErrorMessage := E.Message;
    end;
  finally
    Synchronize(DoneSend);
  end;
end;

{ TForm3 }

procedure TForm3.Button1Click(Sender: TObject);
begin
  Button1.Enabled := False;
  FDialogVisible := True;
  FMAPIThread := TMAPIThread.Create('Joh Doe', 'johndoe@email.com', 'Jane DOe',
      'janedoe@email.com', 'Hello', 'Hello', MessageSent);
end;

procedure TForm3.MessageSent(const AResult: Integer; const AError: string);
begin
  FMapiThread.Terminate;
  FDialogVisible := False;
  Button1.Enabled := True;
end;

end.

Open in new window

0
 
David KrollCommented:
If you just want to open the default mail application, just use ShellExecute.

http://www.latiumsoftware.com/en/delphi/00041.php
0
 
ThommyCommented:
If your mail application is OUTLOOK, you can easily control it by OLE automation...
procedure SendMailViaOutlook;
const
  OutlookItemType = 0;  //olMailItem
var
  Outlook: OleVariant;
  TheMailItem: variant;
begin
  try
    try
      //connect running outlook instance
      Outlook := GetActiveOleObject('Outlook.Application');
    except
      //start new outlook instance
      Outlook := CreateOleObject('Outlook.Application');
    end;

    TheMailItem := Outlook.CreateItem(OutlookItemType);
    TheMailItem.Recipients.Add('MailAdress@gmx.com');
    TheMailItem.Subject := 'This is an e-mail sent by Delphi app using OutLook...';
    TheMailItem.Body := 'Body text...';
    TheMailItem.Attachments.Add('c:\test\attachment.txt');

    TheMailItem.Send;
  finally
    VarClear(Outlook);
  end;
end;

Open in new window

0
 
jimyXCommented:
I doubt that works, I mean to perform MAPISendMail and get back to use the caller application before it is closed. Unless you are using thread, as shown by ewangoya.

I can provide you code that allows to disable modal effects and enable you get back to the main form even if there is another Form showing by modal and it works fine, but when you use that in any application that's calling SendMail the email application will block the I/O of your application until it's done and the email application is closed.
By applying the code that disables the modal restriction you will be able to activate your application and get the focus on it but you will not be able to click a button or even if you have timer there it will be disabled until the e-mail application is closed and the control is returned back to the caller application.

I have tried this on the OutLook and the Lotus Notes and same behavior in both applications.

So in short words that is not possible if it involves e-mail application unless using thread.
0
 
aceswildab1Author Commented:
The thread has been the best answer I've seen so far. It still opens Outlook/E-mail program modally, but it does open up the calling program to allow it to run. Thanks for the help!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.