unit MapiControl;
interfaceuses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs;
type{ Вводим новый тип события для получения Errorcode }
TMapiErrEvent = procedure(Sender: TObject; ErrCode: Integer) ofobject;
TMapiControl = class(TComponent)
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
private{ Private-объявления }
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;
{ +> Изменения, внесённые Eugene Mayevski [mailto:Mayevski@eldos.org]}procedure SetToAddr(newValue : TStrings);
procedure SetCCAddr(newValue : TStrings);
procedure SetBCCAddr(newValue : TStrings);
procedure SetAttachedFileName(newValue : TStrings);
{ +< конец изменений }protected{ Protected-объявления }public{ Public-объявления }
ApplicationHandle: THandle;
procedure Sendmail();
procedure Reset();
published{ Published-объявления }property Subject: stringread FSubject write FSubject;
property Body: stringread FMailText write FMailText;
property FromName: stringread FFromName write FFromName;
property FromAdress: stringread 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;
{ события: }property OnUserAbort: TNotifyEvent read FOnUserAbort write FOnUserAbort;
property OnMapiError: TMapiErrEvent read FOnMapiError write FOnMapiError;
property OnSuccess: TNotifyEvent read FOnSuccess write FOnSuccess;
end;
procedureregister;
implementationuses Mapi;
{ регистрируем компонент: }procedureregister;
begin
RegisterComponents('expectIT', [TMapiControl]);
end;
{ TMapiControl }constructor TMapiControl.Create(AOwner: TComponent);
begininherited 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;
{ +> Изменения, внесённые 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;
{ +< конец изменений }destructor TMapiControl.Destroy;
begin
FTOAdr.Free;
FCCAdr.Free;
FBCCAdr.Free;
FAttachedFileName.Free;
FDisplayFileName.Free;
inherited destroy;
end;
{ Сбрасываем все используемые поля}procedure TMapiControl.Reset;
begin
FSubject := '';
FMailtext := '';
FFromName := '';
FFromAdress := '';
FTOAdr.Clear;
FCCAdr.Clear;
FBCCAdr.Clear;
FAttachedFileName.Clear;
FDisplayFileName.Clear;
end;
{ Эта процедура составляет и отправляет Email }procedure TMapiControl.Sendmail;
var
MapiMessage: TMapiMessage;
MError: Cardinal;
Sender: TMapiRecipDesc;
PRecip, Recipients: PMapiRecipDesc;
PFiles, Attachments: PMapiFileDesc;
i: Integer;
AppHandle: THandle;
begin{ Перво-наперво сохраняем Handle приложения, if not
the Component might fail to send the Email or
your calling Program gets locked up. }
AppHandle := Application.Handle;
{ Нам нужно зарезервировать память для всех получателей }
MapiMessage.nRecipCount := FTOAdr.Count + FCCAdr.Count + FBCCAdr.Count;
GetMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc));
trywith MapiMessage dobegin
ulReserved := 0;
{ Устанавливаем поле Subject: }
lpszSubject := PChar(Self.FSubject);
{ ... Body: }
lpszNoteText := PChar(FMailText);
lpszMessageType := nil;
lpszDateReceived := nil;
lpszConversationID := nil;
flFlags := 0;
{ и отправителя: (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;
{ У нас много получателей письма: (MAPI_TO)
установим для каждого: }if nRecipCount > 0 thenbeginfor i := 1 to FTOAdr.Count dobegin
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]);
{ Если Вы используете этот компонент совместно с Outlook97 или 2000
(не Express версии) , то Вам прийдётся добавить
'SMTP:' в начало каждого (email-) адреса.
}
PRecip^.lpszAddress := PChar('SMTP:' + FTOAdr.Strings[i - 1]);
PRecip^.ulEIDSize := 0;
PRecip^.lpEntryID := nil;
Inc(PRecip);
end;
{ То же самое проделываем с получателями копии письма: (CC, MAPI_CC) }for i := 1 to FCCAdr.Count dobegin
PRecip^.ulReserved := 0;
PRecip^.ulRecipClass := MAPI_CC;
PRecip^.lpszName := PChar(FCCAdr.Strings[i - 1]);
PRecip^.lpszAddress := PChar('SMTP:' + FCCAdr.Strings[i - 1]);
PRecip^.ulEIDSize := 0;
PRecip^.lpEntryID := nil;
Inc(PRecip);
end;
{ ... тоже самое для Bcc: (BCC, MAPI_BCC) }for i := 1 to FBCCAdr.Count dobegin
PRecip^.ulReserved := 0;
PRecip^.ulRecipClass := MAPI_BCC;
PRecip^.lpszName := PChar(FBCCAdr.Strings[i - 1]);
PRecip^.lpszAddress := PChar('SMTP:' + FBCCAdr.Strings[i - 1]);
PRecip^.ulEIDSize := 0;
PRecip^.lpEntryID := nil;
Inc(PRecip);
end;
end;
lpRecips := Recipients;
{ Теперь обработаем прикреплённые к письму файлы: }if FAttachedFileName.Count > 0 thenbegin
nFileCount := FAttachedFileName.Count;
GetMem(Attachments, MapiMessage.nFileCount * sizeof(TMapiFileDesc));
PFiles := Attachments;
{ Во первых установим отображаемые на экране имена файлов (без пути): }
FDisplayFileName.Clear;
for i := 0 to FAttachedFileName.Count - 1 do
FDisplayFileName.Add(ExtractFileName(FAttachedFileName[i]));
if nFileCount > 0 thenbegin{ Теперь составим структурку для прикреплённого файла: }for i := 1 to FAttachedFileName.Count dobegin{ Устанавливаем полный путь }
Attachments^.lpszPathName := PChar(FAttachedFileName.Strings[i - 1]);
{ ... и имя, отображаемое на дисплее: }
Attachments^.lpszFileName := PChar(FDisplayFileName.Strings[i - 1]);
Attachments^.ulReserved := 0;
Attachments^.flFlags := 0;
{ Положение должно быть -1, за разьяснениями обращайтесь в WinApi Help. }
Attachments^.nPosition := Cardinal(-1);
Attachments^.lpFileType := nil;
Inc(Attachments);
end;
end;
lpFiles := PFiles;
endelsebegin
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.
}if FShowDialog then
MError := MapiSendMail(0, AppHandle, MapiMessage, MAPI_DIALOG
or MAPI_LOGON_UI or MAPI_NEW_SESSION, 0)
else
MError := MapiSendMail(0, AppHandle, MapiMessage, 0, 0);
{
Теперь обработаем сообщения об ошибках. В MAPI их присутствует достаточное.
количество. В этом примере я обрабатываю только два из них: USER_ABORT и SUCCESS,
относящиеся к специальным.
Сообщения, не относящиеся к специальным:
MAPI_E_AMBIGUOUS_RECIPIENT,
MAPI_E_ATTACHMENT_NOT_FOUND,
MAPI_E_ATTACHMENT_OPEN_FAILURE,
MAPI_E_BAD_RECIPTYPE,
MAPI_E_FAILURE,
MAPI_E_INSUFFICIENT_MEMORY,
MAPI_E_LOGIN_FAILURE,
MAPI_E_TEXT_TOO_LARGE,
MAPI_E_TOO_MANY_FILES,
MAPI_E_TOO_MANY_RECIPIENTS,
MAPI_E_UNKNOWN_RECIPIENT:
}case MError of
MAPI_E_USER_ABORT:
beginif Assigned(FOnUserAbort) then
FOnUserAbort(Self);
end;
SUCCESS_SUCCESS:
beginif Assigned(FOnSuccess) then
FOnSuccess(Self);
endelsebeginif Assigned(FOnMapiError) then
FOnMapiError(Self, MError);
end;
end;
finally{ В заключение освобождаем память }
FreeMem(Recipients, MapiMessage.nRecipCount * sizeof(TMapiRecipDesc));
end;
end;
{ Вопросы и замечания присылайте Автору. }end.
Перевод контента на русский язык:
Это компонент Delphi для отправки электронных писем с использованием MAPI (Messaging Application Programming Interface). Он позволяет отправлять электронные письма с вложениями, CC/BCC-адресатами и пользовательским текстом электронного письма.
Вот некоторые вещи, которые можно улучшить или изменить:
Обработка ошибок: Код не обрабатывает ошибки хорошо. Например, если MapiSendMail fails, код не проверяет или не обрабатывает код ошибки правильно.
Управление памятью: Код использует GetMem и FreeMem, чтобы выделить и освободить память, что может привести к утечкам памяти, если не используется аккуратно.
Организация кода: Процедура Sendmail quite long и выполняет несколько задач. Она может быть лучше разбита на более маленькие процедуры или функции, каждая из которых обрабатывает конкретную задачу.
Проверка типов: Код предполагает, что список файловых имен FAttachedFileName содержит только имена файлов, но не проверяет это предположение. Если кто-то передаст список с недопустимыми именами файлов, код может упасть или производить неожиданные результаты.
Комментарии к коду: В коде есть некоторые комментарии, но они могут быть более подробными и объяснять, что каждый раздел кода делает.
Вот пример, как можно улучшить процедуру Sendmail:
procedureTMapiControl.SendMail;varMapiMessage:TMapiMessage;MError:Cardinal;begin// Создать новый MAPI-сообщениеMapiMessage:=TMapiMessage.Create;try// Установить свойства сообщенияMapiMessage.ulReserved:=0;MapiMessage.lpszSubject:=PChar(FSubject);MapiMessage.lpszNoteText:=PChar(FMailText);// Добавить адресатовifFTOAdr.Count>0thenAddRecipients(MapiMessage,FTOAdr,MAPI_TO);// Добавить CC/BCC-адресатовifFCCAdr.Count>0thenAddRecipients(MapiMessage,FCCAdr,MAPI_CC);ifFBCCAdr.Count>0thenAddRecipients(MapiMessage,FBCCAdr,MAPI_BCC);// Добавить вложенияifFAttachedFileName.Count>0thenAddAttachments(MapiMessage,FAttachedFileName);// Отправить электронное письмоMError:=MapiSendMail(0,Application.Handle,MapiMessage,MAPI_DIALOGorMAPI_LOGON_UIorMAPI_NEW_SESSION,0);// Проверить ошибки и обрабатывать их соответствующим образомcaseMErrorofMAPI_E_USER_ABORT:beginifAssigned(FOnUserAbort)thenFOnUserAbort(Self);end;SUCCESS_SUCCESS:beginifAssigned(FOnSuccess)thenFOnSuccess(Self);endelsebeginifAssigned(FOnMapiError)thenFOnMapiError(Self,MError);end;finally// Освободить выделенную память для сообщенияMapiMessage.Free;end;end;procedureTMapiControl.AddRecipients(varMapiMessage:TMapiMessage;RecipientList:TStringList;RecipientType:Integer);vari:Integer;beginMapiMessage.nRecipCount:=RecipientList.Count;GetMem(MapiMessage.lpRecips,MapiMessage.nRecipCount*sizeof(TMapiRecipDesc));fori:=0toRecipientList.Count-1dobegin// Установить свойства адресатаMapiMessage.lpRecips^[i].ulReserved:=0;MapiMessage.lpRecips^[i].ulRecipClass:=RecipientType;MapiMessage.lpRecips^[i].lpszName:=PChar(RecipientList[i]);MapiMessage.lpRecips^[i].lpszAddress:=PChar('SMTP:'+RecipientList[i]);// Добавить адресата в списокInc(MapiMessage.lpRecips);end;end;procedureTMapiControl.AddAttachments(varMapiMessage:TMapiMessage;AttachmentList:TStringList);vari:Integer;beginMapiMessage.nFileCount:=AttachmentList.Count;GetMem(MapiMessage.lpFiles,MapiMessage.nFileCount*sizeof(TMapiFileDesc));fori:=0toAttachmentList.Count-1dobegin// Установить свойства вложенияMapiMessage.lpFiles^[i].lpszPathName:=PChar(AttachmentList[i]);MapiMessage.lpFiles^[i].lpszFileName:=PChar(ExtractFileName(AttachmentList[i]));MapiMessage.lpFiles^[i].ulReserved:=0;MapiMessage.lpFiles^[i].flFlags:=0;// Добавить вложение в списокInc(MapiMessage.lpFiles);end;end;
Обратите внимание, что это только пример, и вам может потребоваться модифицировать его для соответствия вашим конкретным требованиям.
Отправка электронной почты через MAPI: компонент для отправки электронных писем с использованием МAPI-интерфейса Microsoft.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.