Solved

Sending non blocking mail with MAPI

Posted on 2002-06-04
9
896 Views
Last Modified: 2010-08-05
How can i send a non blocking mail with MAPI ?

I know the MapiSendMail but this function blocks until the user has sent the mail or aborted the send process.

I would like to do the same like MapiSendMail (Subject, Body, Address, Attachments) but the function should return immediatly)

thanxs
Andreas
0
Comment
Question by:Dev6
9 Comments
 
LVL 12

Expert Comment

by:Lee_Nover
Comment Utility
you could run it in a separate thread

a small nontested example:

unit Unit1;

interface

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

type
  TSendMailThread = class(TThread)
  private
    FSubject,
    FBody,
    FAddress,
    FAttachments: string;

    procedure Execute; override;
  public
    constructor Create(const Subject, Body, Address, Attachments: string);
  end;

  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{ TSendMailThread }

procedure SendMail(const Subject, Body, Address, Attachments: string);
begin
     TSendMailThread.Create(Subject, Body, Address, Attachments: string);
end;

constructor TSendMailThread.Create(const Subject, Body, Address, Attachments: string);
begin
     FSubject:=Subject;
     FBody:=Body;
     FAddress:=Address;
     FAttachments:=Attachments;
     FreeOnTerminate:=true;
     inherited Create(false);
end;

procedure TSendMailThread.Execute;
begin
     // replace this with your code to send the mail
     //MyMapiSenMail(FSubject, FBody, FAddress, FAttachments);
end;

end.
0
 
LVL 12

Expert Comment

by:Lee_Nover
Comment Utility
eh couldn't help it to test it :)

this is correct:

type
  TSendMailThread = class(TThread)
  private
    FSubject,
    FBody,
    FAddress,
    FAttachments: string;
  protected
    procedure Execute; override;
  public
    constructor Create(const Subject, Body, Address, Attachments: string);
  end;




and :



procedure SendMail(const Subject, Body, Address, Attachments: string);
begin
     TSendMailThread.Create(Subject, Body, Address, Attachments);
end;


:)
0
 

Author Comment

by:Dev6
Comment Utility
Doesn't work !
The calling applicaiton stills wait for the MAPI finishing !

This is very strange ....

I tried (for testing if the part with the thread works) to put a showmessage after the call to my SendMail
When i click the button, i get the showmessage and the Outlook form, now i can click on my form and do all what i want. If i remove the ShowMessage, the apllication waits for the MAPI !

0
 
LVL 12

Expert Comment

by:Lee_Nover
Comment Utility
weird ..
can you give me the mail sending code to check it out ?
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:Dev6
Comment Utility
This is the code, with your modified Execute ...

procedure TSendMailThread.Execute;
begin
    SendMail(FAddress, FSubject, FBody, FAttachments, TRUE);
end;


function SendEMailToMAPI(Handle : THandle; Mail : TStrings) : Cardinal;
type
    TAttachAccessArray = array[0..0] OF TMapiFileDesc;
    PAttachAccessArray = ^TAttachAccessArray;
var MapiMessage : TMapiMessage;
    Receip      : TMapiRecipDesc;
    Attachments : PAttachAccessArray;
    AttachCount : integer;
    iCount      : integer;
    FileName    : string;
begin
    FillChar(MapiMessage, SizeOf(MapiMessage), #0);
    Attachments   := nil;
    FillChar(Receip, SizeOf(Receip), #0);
    if Mail.Values['to'] <> '' then begin
        Receip.ulReserved   := 0;
        Receip.ulRecipClass := MAPI_TO;
        Receip.lpszName     := StrNew(PChar(Mail.Values['to']));
        Receip.lpszAddress  := StrNew(PChar('SMTP:' + Mail.Values['to']));
        Receip.ulEIDSize    := 0;
        MapiMessage.nRecipCount := 1;
        MapiMessage.lpRecips    := @Receip;
    end;

    AttachCount := 0;
    for iCount := 0 to MaxInt do begin
        if Mail.Values['Attachment' + IntToStr(iCount)] = '' then break;
        AttachCount := AttachCount + 1;
    end;

    if AttachCount > 0 then begin
        GetMem(Attachments,SizeOf(TMapiFileDesc) * AttachCount);
        for iCount := 0 to (AttachCount - 1) do begin
            FileName                            := Mail.Values['Attachment' + IntToStr(iCount)];
            Attachments[iCount].ulReserved      := 0;
            Attachments[iCount].flFlags         := 0;
            Attachments[iCount].nPosition       := ULONG($FFFFFFFF);
            Attachments[iCount].lpszPathName    := StrNew(PChar(FileName));
            Attachments[iCount].lpszFileName    := StrNew(PChar(ExtractFileName(FileName)));
            Attachments[iCount].lpFileType      := nil;
        end;
        MapiMessage.nFileCount  := AttachCount;
        MapiMessage.lpFiles     := @Attachments^;
    end;

    if Mail.Values['subject'] <> '' then
        MapiMessage.lpszSubject := StrNew(PChar(Mail.Values['subject']));
    if Mail.Values['body'] <> '' then
        MapiMessage.lpszNoteText := StrNew(PChar(Mail.Values['body']));

    Result := MapiSendMail(0, Handle, MapiMessage, MAPI_DIALOG*Ord(Handle <> 0) OR MAPI_LOGON_UI OR MAPI_NEW_SESSION, 0);

    for iCount := 0 to (AttachCount - 1) do begin
        strDispose(Attachments[iCount].lpszPathName);
        strDispose(Attachments[iCount].lpszFileName);
    end;

    if assigned(MapiMessage.lpszSubject)    then strDispose(MapiMessage.lpszSubject);
    if assigned(MapiMessage.lpszNoteText)   then strDispose(MapiMessage.lpszNoteText);
    if assigned(Receip.lpszAddress)         then strDispose(Receip.lpszAddress);
    if assigned(Receip.lpszName)            then strDispose(Receip.lpszName);
end;



function SendMAPIMail(Addr, Subject, Body : string; Attachments : string) : Boolean;
var Mail        : TStringList;
    i           : integer;
    Res         : integer;
begin
    Mail        := TStringList.Create;
    Mail.Values['To']           := Addr;
    Mail.Values['Subject']      := Subject;
    if length(Body) > 0 then
        Mail.Values['Body']         := Body;
    i                           := 0;
    with THostParser.Create(Attachments, #0) do begin
        while IsValid do begin
            Mail.Values['Attachment'+IntToStr(i)]   := GetValue;
            inc(i);
        end;
        Free;
    end;
    Res := SendEMailToMAPI(Application.Handle, Mail);
    case Res of
        MAPI_E_AMBIGUOUS_RECIPIENT      : LastError := 'A recipient matched more than one of the recipient descriptor structures and MAPI_DIALOG was not set. No message was sent.';
        MAPI_E_ATTACHMENT_NOT_FOUND     : LastError := 'The specified attachment was not found. No message was sent.';
        MAPI_E_ATTACHMENT_OPEN_FAILURE  : LastError := 'The specified attachment could not be open; no message was sent.';
        MAPI_E_BAD_RECIPTYPE            : LastError := 'The type of a recipient was not MAPI_TO, MAPI_CC, or MAPI_BCC. No message was sent.';
        MAPI_E_FAILURE                  : LastError := 'One or more unspecified errors occurred; no message was sent.';
        MAPI_E_INSUFFICIENT_MEMORY      : LastError := 'There was insufficient memory to proceed. No message was sent.';
        MAPI_E_LOGIN_FAILURE            : LastError := 'There was no default logon, and the user failed to log on successfully when the logon dialog box was displayed. No message was sent.';
        MAPI_E_TEXT_TOO_LARGE           : LastError := 'The text in the message was too large to sent; the message was not sent.';
        MAPI_E_TOO_MANY_FILES           : LastError := 'There were too many file attachments; no message was sent.';
        MAPI_E_TOO_MANY_RECIPIENTS      : LastError := 'There were too many recipients; no message was sent.';
        MAPI_E_UNKNOWN_RECIPIENT        : LastError := 'A recipient did not appear in the address list; no message was sent.';
        MAPI_E_USER_ABORT               : LastError := 'The user canceled one of the dialog boxes; no message was sent.';
        SUCCESS_SUCCESS                 : LastError := 'Alles OK';
    end;
    Result  := Res = SUCCESS_SUCCESS;
    Mail.Free;
end;

function SendMail(Addr, Subject, Body : string; Attachments : string; DoWait : Boolean = FALSE) : Boolean;
begin
    if DoWait then  Result  := SendMAPIMail(Addr, Subject, Body, Attachments)
    else begin
        try
            TSendMailThread.Create(Addr, Subject, Body, Attachments);
            Result  := TRUE;
        except
            Result  := FALSE;
        end;
    end;
end;
0
 
LVL 12

Expert Comment

by:Lee_Nover
Comment Utility
will check it out a bit later
hold on :)
0
 
LVL 1

Expert Comment

by:pnh73
Comment Utility
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

PAQ with No Refund

Please leave any comments here within the next seven days.
 
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!
 
Paul (pnh73)
EE Cleanup Volunteer
0
 
LVL 6

Accepted Solution

by:
Mindphaser earned 0 total points
Comment Utility
Force accepted

** Mindphaser - Community Support Moderator **
0
 

Expert Comment

by:genii_th
Comment Utility
how to use?
what ?????  THostParser >>>> with THostParser.Create(Attachments, #0) do begin  
0

Featured Post

Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now