git-svn-id: https://192.168.0.254/svn/Proyectos.Tecsitel_FactuGES2/trunk@1051 0c75b7a4-871f-7646-8a2f-f78d34cc349f
457 lines
15 KiB
ObjectPascal
457 lines
15 KiB
ObjectPascal
unit uEMailUtils;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
|
|
|
|
type
|
|
{ Introducing a new Type of Event to get the Errorcode }
|
|
TMapiErrEvent = procedure(Sender: TObject; ErrCode: Integer) of object;
|
|
|
|
TMapiControl = class(TComponent)
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
private
|
|
{ Private-Deklarationen }
|
|
FSubject: string;
|
|
FMailtext: string;
|
|
FFromName: string;
|
|
FFromAdress: string;
|
|
FTOAdr: TStrings;
|
|
FCCAdr: TStrings;
|
|
FBCCAdr: TStrings;
|
|
FAttachedFileName: TStrings;
|
|
FDisplayFileName: TStrings;
|
|
FShowDialog: Boolean;
|
|
FUseAppHandle: Boolean;
|
|
{ Error Events: }
|
|
{ FOnUserAbort: TNotifyEvent;
|
|
FOnMapiError: TMapiErrEvent;
|
|
FOnSuccess: TNotifyEvent;}
|
|
{ +> Changes by Eugene Mayevski [mailto:Mayevski@eldos.org]}
|
|
procedure SetToAddr(newValue: TStrings);
|
|
procedure SetCCAddr(newValue: TStrings);
|
|
procedure SetBCCAddr(newValue: TStrings);
|
|
procedure SetAttachedFileName(newValue: TStrings);
|
|
{ +< Changes }
|
|
protected
|
|
{ Protected-Deklarationen }
|
|
public
|
|
{ Public-Deklarationen }
|
|
ApplicationHandle: THandle;
|
|
function Sendmail: Boolean;
|
|
procedure Reset;
|
|
published
|
|
{ Published-Deklarationen }
|
|
property Subject: string read FSubject write FSubject;
|
|
property Body: string read FMailText write FMailText;
|
|
property FromName: string read FFromName write FFromName;
|
|
property FromAdress: string read FFromAdress write FFromAdress;
|
|
property Recipients: TStrings read FTOAdr write SetTOAddr;
|
|
property CopyTo: TStrings read FCCAdr write SetCCAddr;
|
|
property BlindCopyTo: TStrings read FBCCAdr write SetBCCAddr;
|
|
property AttachedFiles: TStrings read FAttachedFileName write SetAttachedFileName;
|
|
property DisplayFileName: TStrings read FDisplayFileName;
|
|
property ShowDialog: Boolean read FShowDialog write FShowDialog;
|
|
property UseAppHandle: Boolean read FUseAppHandle write FUseAppHandle;
|
|
|
|
{ Events: }
|
|
{property OnUserAbort: TNotifyEvent read FOnUserAbort write FOnUserAbort;
|
|
property OnMapiError: TMapiErrEvent read FOnMapiError write FOnMapiError;
|
|
property OnSuccess: TNotifyEvent read FOnSuccess write FOnSuccess;}
|
|
end;
|
|
|
|
function EsDireccionEMailValida(const Value: string): boolean;
|
|
function EnviarEMailMAPI(const AAsunto, ACuerpo, AFicheroAdjunto, ANombreRemitente, AEMailRemitente,
|
|
ANombreDestinatario, AEMailDestinatario: String; AEnviarDirectamente: Boolean = false) : boolean;
|
|
|
|
implementation
|
|
|
|
uses
|
|
MAPI;
|
|
|
|
function EsDireccionEMailValida(const Value: string): boolean;
|
|
function CheckAllowed(const s: string): boolean;
|
|
var
|
|
i: integer;
|
|
begin
|
|
Result:= false;
|
|
for i:= 1 to Length(s) do
|
|
begin
|
|
// illegal char in s -> no valid address
|
|
if not (s[i] in ['a'..'z','A'..'Z','0'..'9','_','-','.']) then
|
|
Exit;
|
|
end;
|
|
Result:= true;
|
|
end;
|
|
var
|
|
i: integer;
|
|
namePart, serverPart: string;
|
|
begin // of IsValidEmail
|
|
Result:= false;
|
|
i:= Pos('@', Value);
|
|
if (i = 0) or (pos('..', Value) > 0) then
|
|
Exit;
|
|
namePart:= Copy(Value, 1, i - 1);
|
|
serverPart:= Copy(Value, i + 1, Length(Value));
|
|
if (Length(namePart) = 0) // @ or name missing
|
|
or ((Length(serverPart) < 4)) // name or server missing or
|
|
then Exit; // too short
|
|
i:= Pos('.', serverPart);
|
|
// must have dot and at least 3 places from end
|
|
if (i < 2) or (i > (Length(serverPart) - 2)) then
|
|
Exit;
|
|
Result:= CheckAllowed(namePart) and CheckAllowed(serverPart);
|
|
end;
|
|
|
|
function EnviarEMailMAPI(const AAsunto, ACuerpo, AFicheroAdjunto, ANombreRemitente, AEMailRemitente,
|
|
ANombreDestinatario, AEMailDestinatario: String; AEnviarDirectamente: Boolean = false) : boolean;
|
|
var
|
|
AMAPIControl : TMapiControl;
|
|
begin
|
|
AMAPIControl := TMapiControl.Create(NIL);
|
|
try
|
|
with AMAPIControl do
|
|
begin
|
|
Subject := AAsunto;
|
|
Body := ACuerpo;
|
|
FromName := ANombreRemitente;
|
|
FromAdress := AEMailRemitente;
|
|
|
|
Recipients.Add(AEMailDestinatario);
|
|
AttachedFiles.Add(AFicheroAdjunto);
|
|
|
|
ShowDialog := not AEnviarDirectamente;
|
|
end;
|
|
Result := AMAPIControl.Sendmail;
|
|
finally
|
|
FreeANDNIL(AMAPIControl);
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TMapiControl }
|
|
|
|
constructor TMapiControl.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
{FOnUserAbort := nil;
|
|
FOnMapiError := nil;
|
|
FOnSuccess := nil;}
|
|
FSubject := '';
|
|
FMailtext := '';
|
|
FFromName := '';
|
|
FFromAdress := '';
|
|
FTOAdr := TStringList.Create;
|
|
FCCAdr := TStringList.Create;
|
|
FBCCAdr := TStringList.Create;
|
|
FAttachedFileName := TStringList.Create;
|
|
FDisplayFileName := TStringList.Create;
|
|
FShowDialog := False;
|
|
ApplicationHandle := Application.Handle;
|
|
end;
|
|
|
|
{ +> Changes by Eugene Mayevski [mailto:Mayevski@eldos.org]}
|
|
|
|
procedure TMapiControl.SetToAddr(newValue: TStrings);
|
|
begin
|
|
FToAdr.Assign(newValue);
|
|
end;
|
|
|
|
procedure TMapiControl.SetCCAddr(newValue: TStrings);
|
|
begin
|
|
FCCAdr.Assign(newValue);
|
|
end;
|
|
|
|
procedure TMapiControl.SetBCCAddr(newValue: TStrings);
|
|
begin
|
|
FBCCAdr.Assign(newValue);
|
|
end;
|
|
|
|
procedure TMapiControl.SetAttachedFileName(newValue: TStrings);
|
|
begin
|
|
FAttachedFileName.Assign(newValue);
|
|
end;
|
|
{ +< Changes }
|
|
|
|
destructor TMapiControl.Destroy;
|
|
begin
|
|
FTOAdr.Free;
|
|
FCCAdr.Free;
|
|
FBCCAdr.Free;
|
|
FAttachedFileName.Free;
|
|
FDisplayFileName.Free;
|
|
inherited destroy;
|
|
end;
|
|
|
|
{ Reset the fields for re-use}
|
|
|
|
procedure TMapiControl.Reset;
|
|
begin
|
|
FSubject := '';
|
|
FMailtext := '';
|
|
FFromName := '';
|
|
FFromAdress := '';
|
|
FTOAdr.Clear;
|
|
FCCAdr.Clear;
|
|
FBCCAdr.Clear;
|
|
FAttachedFileName.Clear;
|
|
FDisplayFileName.Clear;
|
|
end;
|
|
|
|
{ Send the Mail via the API, this procedure composes and sends
|
|
the Email }
|
|
|
|
function TMapiControl.Sendmail: Boolean;
|
|
var
|
|
MapiMessage: TMapiMessage;
|
|
MError: Cardinal;
|
|
Sender: TMapiRecipDesc;
|
|
PRecip, Recipients: PMapiRecipDesc;
|
|
PFiles, Attachments: PMapiFileDesc;
|
|
i: Integer;
|
|
AppHandle: THandle;
|
|
begin
|
|
{ First we store the Application Handle, if not
|
|
the Component might fail to send the Email or
|
|
your calling Program gets locked up. }
|
|
AppHandle := Application.Handle;
|
|
|
|
{ Initialize the Attachment Pointer, to keep Delphi quiet }
|
|
PFiles := nil;
|
|
|
|
{ We need all recipients to alloc the memory }
|
|
MapiMessage.nRecipCount := FTOAdr.Count + FCCAdr.Count + FBCCAdr.Count;
|
|
GetMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc));
|
|
|
|
try
|
|
with MapiMessage do
|
|
begin
|
|
ulReserved := 0;
|
|
{ Setting the Subject: }
|
|
lpszSubject := PChar(Self.FSubject);
|
|
|
|
{ ... the Body: }
|
|
lpszNoteText := PChar(FMailText);
|
|
lpszMessageType := nil;
|
|
lpszDateReceived := nil;
|
|
lpszConversationID := nil;
|
|
flFlags := 0;
|
|
|
|
{ and the sender: (MAPI_ORIG) }
|
|
Sender.ulReserved := 0;
|
|
Sender.ulRecipClass := MAPI_ORIG;
|
|
Sender.lpszName := PChar(FromName);
|
|
Sender.lpszAddress := PChar(FromAdress);
|
|
Sender.ulEIDSize := 0;
|
|
Sender.lpEntryID := nil;
|
|
lpOriginator := @Sender;
|
|
PRecip := Recipients;
|
|
|
|
{ We have multiple recipients: (MAPI_TO)
|
|
and setting up each: }
|
|
if nRecipCount > 0 then
|
|
begin
|
|
for i := 1 to FTOAdr.Count do
|
|
begin
|
|
PRecip^.ulReserved := 0;
|
|
PRecip^.ulRecipClass := MAPI_TO;
|
|
{ lpszName should carry the Name like in the
|
|
contacts or the adress book, I will take the
|
|
email adress to keep it short: }
|
|
PRecip^.lpszName := PChar(FTOAdr.Strings[i - 1]);
|
|
{ If you use this component with Outlook97 or 2000
|
|
and not some of Express versions you will have to set
|
|
'SMTP:' in front of each (email-) adress. Otherwise
|
|
Outlook/Mapi will try to handle the Email on itself.
|
|
Sounds strange, just erease the 'SMTP:', compile, compose
|
|
a mail and take a look at the resulting email adresses
|
|
(right click).
|
|
}
|
|
{ +> Changes by Andreas Hoerig [mailto:andreas.hoerig@sillner.com] }
|
|
PRecip^.lpszAddress := StrNew(PChar('SMTP:' + FTOAdr.Strings[i - 1]));
|
|
{ +< Changes }
|
|
PRecip^.ulEIDSize := 0;
|
|
PRecip^.lpEntryID := nil;
|
|
Inc(PRecip);
|
|
end;
|
|
|
|
{ Same with the carbon copy recipients: (CC, MAPI_CC) }
|
|
for i := 1 to FCCAdr.Count do
|
|
begin
|
|
PRecip^.ulReserved := 0;
|
|
PRecip^.ulRecipClass := MAPI_CC;
|
|
PRecip^.lpszName := PChar(FCCAdr.Strings[i - 1]);
|
|
{ +> Changes by Andreas Hoerig [mailto:andreas.hoerig@sillner.com] }
|
|
PRecip^.lpszAddress := StrNew(PChar('SMTP:' + FCCAdr.Strings[i - 1]));
|
|
{ +< Changes }
|
|
PRecip^.ulEIDSize := 0;
|
|
PRecip^.lpEntryID := nil;
|
|
Inc(PRecip);
|
|
end;
|
|
|
|
{ ... and the blind copy recipients: (BCC, MAPI_BCC) }
|
|
for i := 1 to FBCCAdr.Count do
|
|
begin
|
|
PRecip^.ulReserved := 0;
|
|
PRecip^.ulRecipClass := MAPI_BCC;
|
|
PRecip^.lpszName := PChar(FBCCAdr.Strings[i - 1]);
|
|
{ +> Changes by Andreas Hoerig [mailto:andreas.hoerig@sillner.com] }
|
|
PRecip^.lpszAddress := StrNew(PChar('SMTP:' + FBCCAdr.Strings[i - 1]));
|
|
{ +< Changes }
|
|
PRecip^.ulEIDSize := 0;
|
|
PRecip^.lpEntryID := nil;
|
|
Inc(PRecip);
|
|
end;
|
|
end;
|
|
lpRecips := Recipients;
|
|
|
|
{ Now we process the attachments: }
|
|
nFileCount := FAttachedFileName.Count;
|
|
if nFileCount > 0 then
|
|
begin
|
|
GetMem(Attachments, nFileCount * sizeof(TMapiFileDesc));
|
|
PFiles := Attachments;
|
|
|
|
{ Fist setting up the display names (without path): }
|
|
FDisplayFileName.Clear;
|
|
for i := 1 to FAttachedFileName.Count do
|
|
FDisplayFileName.Add(ExtractFileName(FAttachedFileName[i - 1]));
|
|
|
|
if nFileCount > 0 then
|
|
begin
|
|
{ Now we pass the attached file (their paths) to the
|
|
structure: }
|
|
for i := 1 to FAttachedFileName.Count do
|
|
begin
|
|
{ Setting the complete Path }
|
|
Attachments^.lpszPathName := PChar(FAttachedFileName.Strings[i - 1]);
|
|
{ ... and the displayname: }
|
|
Attachments^.lpszFileName := PChar(FDisplayFileName.Strings[i - 1]);
|
|
Attachments^.ulReserved := 0;
|
|
Attachments^.flFlags := 0;
|
|
{ Position has to be -1, please see the WinApi Help
|
|
for details. }
|
|
Attachments^.nPosition := Cardinal(-1);
|
|
Attachments^.lpFileType := nil;
|
|
Inc(Attachments);
|
|
end;
|
|
end;
|
|
lpFiles := PFiles;
|
|
end
|
|
else
|
|
begin
|
|
nFileCount := 0;
|
|
lpFiles := nil;
|
|
end;
|
|
end;
|
|
|
|
{ Send the Mail, silent or verbose:
|
|
Verbose means in Express a Mail is composed and shown as setup.
|
|
In non-Express versions we show the Login-Dialog for a new
|
|
session and after we have choosen the profile to use, the
|
|
composed email is shown before sending
|
|
|
|
Silent does currently not work for non-Express version. We have
|
|
no Session, no Login Dialog so the system refuses to compose a
|
|
new email. In Express Versions the email is sent in the
|
|
background.
|
|
|
|
Please Note: It seems that your success on the delivery depends
|
|
on a combination of MAPI-Flags (MAPI_DIALOG, MAPI_LOGON_UI, ...)
|
|
and your used OS and Office Version. I am currently using
|
|
Win2K SP1 and Office 2K SP2 with no problems at all.
|
|
If you experience problems on another versions, please try
|
|
a different combination of flags for each purpose (Dialog or not).
|
|
I would be glad to setup a table with working flags on
|
|
each OS/Office combination, just drop me a line.
|
|
|
|
Possible combinations are also (with Dialog):
|
|
1. MAPI_DIALOG or MAPI_LOGON_UI MAPI_NEW_SESSION or MAPI_USE_DEFAULT
|
|
2. MAPI_SIMPLE_DEFAULT
|
|
|
|
See MAPI.PAS or MAPI.H (SDK) for more...
|
|
}
|
|
if FShowDialog then
|
|
MError := MapiSendMail(0, AppHandle, MapiMessage, MAPI_DIALOG or MAPI_LOGON_UI or MAPI_NEW_SESSION, 0)
|
|
// MError := MapiSendMail(0, AppHandle, MapiMessage, MAPI_SIMPLE_EXPLICIT, 0)
|
|
else
|
|
MError := MapiSendMail(0, AppHandle, MapiMessage, 0, 0);
|
|
|
|
{ Now we have to process the error messages. There are some
|
|
defined in the MAPI unit please take a look at the unit to get
|
|
familiar with it.
|
|
I decided to handle USER_ABORT and SUCCESS as special and leave
|
|
the rest to fire the "new" error event defined at the top (as
|
|
generic error)
|
|
|
|
Not treated as special (constants from mapi.pas):
|
|
|
|
MAPI_E_FAILURE = 2;
|
|
MAPI_E_LOGON_FAILURE = 3;
|
|
MAPI_E_LOGIN_FAILURE = MAPI_E_LOGON_FAILURE;
|
|
MAPI_E_DISK_FULL = 4;
|
|
MAPI_E_INSUFFICIENT_MEMORY = 5;
|
|
MAPI_E_ACCESS_DENIED = 6;
|
|
MAPI_E_TOO_MANY_SESSIONS = 8;
|
|
MAPI_E_TOO_MANY_FILES = 9;
|
|
MAPI_E_TOO_MANY_RECIPIENTS = 10;
|
|
MAPI_E_ATTACHMENT_NOT_FOUND = 11;
|
|
MAPI_E_ATTACHMENT_OPEN_FAILURE = 12;
|
|
MAPI_E_ATTACHMENT_WRITE_FAILURE = 13;
|
|
MAPI_E_UNKNOWN_RECIPIENT = 14;
|
|
MAPI_E_BAD_RECIPTYPE = 15;
|
|
MAPI_E_NO_MESSAGES = 16;
|
|
MAPI_E_INVALID_MESSAGE = 17;
|
|
MAPI_E_TEXT_TOO_LARGE = 18;
|
|
MAPI_E_INVALID_SESSION = 19;
|
|
MAPI_E_TYPE_NOT_SUPPORTED = 20;
|
|
MAPI_E_AMBIGUOUS_RECIPIENT = 21;
|
|
MAPI_E_AMBIG_RECIP = MAPI_E_AMBIGUOUS_RECIPIENT;
|
|
MAPI_E_MESSAGE_IN_USE = 22;
|
|
MAPI_E_NETWORK_FAILURE = 23;
|
|
MAPI_E_INVALID_EDITFIELDS = 24;
|
|
MAPI_E_INVALID_RECIPS = 25;
|
|
MAPI_E_NOT_SUPPORTED = 26;
|
|
}
|
|
|
|
{ case MError of
|
|
MAPI_E_USER_ABORT:
|
|
begin
|
|
if Assigned(FOnUserAbort) then
|
|
FOnUserAbort(Self);
|
|
end;
|
|
SUCCESS_SUCCESS:
|
|
begin
|
|
if Assigned(FOnSuccess) then
|
|
FOnSuccess(Self);
|
|
end
|
|
else
|
|
begin
|
|
if Assigned(FOnMapiError) then
|
|
FOnMapiError(Self, MError);
|
|
end;
|
|
end;}
|
|
Result := (MError = 0);
|
|
|
|
finally
|
|
{ Finally we do the cleanups, the message should be on its way }
|
|
{ +> Changes by Andreas Hoerig [mailto:andreas.hoerig@sillner.com] }
|
|
PRecip := Recipients;
|
|
for i := 1 to MapiMessage.nRecipCount do
|
|
begin
|
|
StrDispose(PRecip^.lpszAddress);
|
|
Inc(PRecip)
|
|
end;
|
|
{ +< Changes }
|
|
FreeMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc));
|
|
{ +> Changes due to Ken Halliwell [mailto:kjhalliwell@aol.com] }
|
|
if Assigned(PFiles) then
|
|
FreeMem(PFiles, MapiMessage.nFileCount * sizeof(TMapiFileDesc));
|
|
{ +< Changes }
|
|
end;
|
|
end;
|
|
|
|
end.
|