Mail := MailBuilder
.SetSender('no-reply@test.com')
.AddRecipient('test@test.com')
.AddRecipient('test@test.com')
.AddCC('manager@test.com')
.AddBCC('archive@test.com')
.SetSubject('This is a subject')
.SetContent('This is the content')
.AddAttachment('Test.pdf', 'application/pdf')
.Build();
Mail.Send();
unit Helpers.Email;
interface
uses
SysUtils,
Email.MailAttachment,
Email.MailBuilder,
Email.Mail,
Email.MailServerBuilder,
Email.MailPriority,
Helpers.logging;
type
TMailAttachment = Email.MailAttachment.TMailAttachment;
TMailBuilder = Email.MailBuilder.TMailBuilder;
TMailBuildResult = Email.MailBuilder.TMailBuildResult;
TMailServerSettings = Email.MailServerBuilder.TMailServerSettings;
TSendMailResult = Email.MailServerBuilder.TSendMailResult;
TMailServerBuilder = Email.MailServerBuilder.TMailServerBuilder;
TMailPriority = Email.MailPriority.TMailPriority;
function MailBuilder(AUseDefaults: Boolean = true): TMailBuilder;
var MailServer: TMailServerBuilder;
var MailLogger: TLogger;
implementation
function MailBuilder(AUseDefaults: Boolean = true): TMailBuilder;
begin
Result := TMailBuilder.Create;
if (AUseDefaults) then
MailServer.AddDefaults(Result);
end;
var
DefaultMailLoggingConfig: TLoggerConfig;
initialization
MailServer:= TMailServerBuilder.Create;
MailServer.LoadFromIniFile('.\SMTP.ini');
DefaultMailLoggingConfig.FileName := '.\log\SMTP.log';
DefaultMailLoggingConfig.LogLevel := ltTrace;
MailLogger := TLogger.Create(TLogger.ReadConfig('.\smtp-logging.ini', DefaultMailLoggingConfig));
MailLogger.Info('SMTP log started.');
finalization
FreeAndNil(MailServer);
FreeAndNil(MailLogger)
end.
///////
unit Email.MailBuilder;
interface
uses
variants, SysUtils, System.Classes, System.Generics.Collections, Email.Mail, Email.MailPriority;
type
TMailBuildResult = record
Valid: Boolean;
ExecptionMessage: string;
Mail: TMail;
end;
TMailBuilder = class
private
FMail: TMail;
function _AddTo(AEmail: string): TMailBuilder;
function _AddCC(AEmail: string): TMailBuilder;
function _AddBCC(AEmail: string): TMailBuilder;
public
constructor Create;
destructor Destroy; override;
function SetFrom(AEmail: string): TMailBuilder;
function AddTo(AEmail: string): TMailBuilder; overload;
function AddTo(AEmails: TArray<string>): TMailBuilder; overload;
function AddCC(AEmail: string): TMailBuilder; overload;
function AddCC(AEmails: TArray<string>): TMailBuilder; overload;
function AddBCC(AEmail: string): TMailBuilder; overload;
function AddBCC(AEmails: TArray<string>): TMailBuilder; overload;
function SetPriority(APriority: TMailPriority): TMailBuilder;
function ClearTo(): TMailBuilder;
function ClearCC(): TMailBuilder;
function ClearBCC(): TMailBuilder;
function SetSubject(AText: string): TMailBuilder;
function ClearContent: TMailBuilder;
function AddContent(AText: string): TMailBuilder;
function ClearHtmlContent: TMailBuilder;
function AddHtmlContent(AText: string): TMailBuilder;
function AddAttachment(AAttachmentName: string; AContentType: string; AContent: TStream; AFreeAfterSend: Boolean = false; AContentId: string = ''): TMailBuilder;
function AddFileAttachment(AFileNames: TArray<string>): TMailBuilder; overload;
function AddFileAttachment(AFileName: string): TMailBuilder; overload;
function GetDebugContent: string;
function Build: TMailBuildResult;
class function IsEmailaddressValid(AEmail: String): Boolean;
end;
implementation
uses Email.MailAttachment, Email.MailServerBuilder;
constructor TMailBuilder.Create;
begin
FMail := TMail.Create;
end;
destructor TMailBuilder.Destroy;
begin
FreeAndNil(FMail);
inherited;
end;
function TMailBuilder.GetDebugContent: string;
var
stringList: TStringList;
begin
stringList := TStringList.Create;
try
stringList.Add('From: ');
stringList.Add(Self.FMail.From);
stringList.Add('-------------------------------------------------------------');
stringList.Add('To: ');
stringList.Add(string.Join('; ' ,Self.FMail.ToList.ToArray));
stringList.Add('-------------------------------------------------------------');
stringList.Add('Cc: ');
stringList.Add(string.Join('; ' ,Self.FMail.CCList.ToArray));
stringList.Add('-------------------------------------------------------------');
stringList.Add('Bcc: ');
stringList.Add(string.Join('; ' ,Self.FMail.BCCList.ToArray));
stringList.Add('-------------------------------------------------------------');
stringList.Add('Subject: ');
stringList.Add(Self.FMail.Subject);
stringList.Add('-------------------------------------------------------------');
stringList.Add('Content: ');
stringList.Add(Self.FMail.Content);
stringList.Add('-------------------------------------------------------------');
Result := stringList.Text;
finally
stringList.Free;
end;
end;
class function TMailBuilder.IsEmailaddressValid(AEmail: string): Boolean;
begin
Result := AEmail.Trim() <> '';
end;
function TMailBuilder.Build: TMailBuildResult;
begin
Result.Valid := false;
if not IsEmailaddressValid(FMail.From) then
begin
Result.ExecptionMessage := 'Invalid mail "From" address';
end
else if FMail.ToList.Count = 0 then
begin
Result.ExecptionMessage := 'No valid mail "To" address';
end
else
begin
Result.Valid := true;
Result.Mail := FMail;
end;
end;
function TMailBuilder.SetFrom(AEmail: string): TMailBuilder;
begin
if IsEmailaddressValid(AEmail) then
FMail.From := Trim(AEmail);
Result := self;
end;
function TMailBuilder.SetPriority(APriority: TMailPriority): TMailBuilder;
begin
FMail.Priority := APriority;
result := self;
end;
function TMailBuilder.AddTo(AEmails: TArray<string>): TMailBuilder;
var
str: string;
begin
for str in AEmails do
_AddTo(str);
Result := self;
end;
function TMailBuilder.AddTo(AEmail: string): TMailBuilder;
begin
result := AddTo(AEmail.Split([';']));
end;
function TMailBuilder._AddTo(AEmail: string): TMailBuilder;
begin
if IsEmailaddressValid(AEmail) then
FMail.ToList.Add(Trim(AEmail));
Result := self;
end;
function TMailBuilder.AddCC(AEmails: TArray<string>): TMailBuilder;
var
str: string;
begin
for str in AEmails do
_AddCC(str);
Result := self;
end;
function TMailBuilder.AddCC(AEmail: string): TMailBuilder;
begin
result := AddCC(AEmail.Split([';']));
end;
function TMailBuilder._AddCC(AEmail: string): TMailBuilder;
begin
if IsEmailaddressValid(AEmail) then
FMail.CCList.Add(Trim(AEmail));
Result := self;
end;
function TMailBuilder.ClearContent(): TMailBuilder;
begin
FMail.Content := '';
Result := self;
end;
function TMailBuilder.ClearHtmlContent(): TMailBuilder;
begin
FMail.HtmlContent := '';
Result := self;
end;
function TMailBuilder.AddContent(AText: string): TMailBuilder;
begin
FMail.Content := FMail.Content + AText;
Result := self;
end;
function TMailBuilder.AddBCC(AEmails: TArray<string>): TMailBuilder;
var
str: string;
begin
for str in AEmails do
_AddBCC(str);
Result := self;
end;
function TMailBuilder.AddBCC(AEmail: string): TMailBuilder;
begin
Result := AddBCC(AEmail.Split([';']));
end;
function TMailBuilder._AddBCC(AEmail: string): TMailBuilder;
begin
if IsEmailaddressValid(AEmail) then
FMail.BCCList.Add(Trim(AEmail));
Result := self;
end;
function TMailBuilder.SetSubject(AText: string): TMailBuilder;
begin
FMail.Subject := AText;
Result := self;
end;
function TMailBuilder.AddAttachment(AAttachmentName, AContentType: string; AContent: TStream; AFreeAfterSend: Boolean = false; AContentId: string = '')
: TMailBuilder;
var
attachment: TMailAttachment;
begin
if not Assigned(AContent) then
Exit(self);
attachment.Name := AAttachmentName;
attachment.ContentType := AContentType;
attachment.Data := AContent;
attachment.ContentId := AContentId;
attachment.FreeAfterSend := AFreeAfterSend;
FMail.Attachments.Add(attachment);
Result := self;
end;
function TMailBuilder.AddFileAttachment(AFileNames: TArray<string>): TMailBuilder;
var
str: string;
begin
for str in AFileNames do
AddFileAttachment(str);
Result := self;
end;
function TMailBuilder.AddFileAttachment(AFileName: string): TMailBuilder;
var
fileStream : TFileStream;
mimetable : TIdThreadSafeMimeTable;
ContentType: string;
begin
if not TFile.Exists(AFileName) then
Exit(self);
fileStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyNone); // TFile.OpenRead(AFileName);
mimetable := TIdThreadSafeMimeTable.Create(true);
try
ContentType := mimetable.GetFileMIMEType(AFileName);
finally
mimetable.Free;
end;
Result := AddAttachment(TPath.GetFileName(fileStream.FileName), ContentType, fileStream, true);
end;
function TMailBuilder.AddHtmlContent(AText: string): TMailBuilder;
begin
FMail.HtmlContent := FMail.HtmlContent + AText;
Result := self;
end;
function TMailBuilder.ClearTo: TMailBuilder;
begin
FMail.ToList.Clear;
Result := self;
end;
function TMailBuilder.ClearCC: TMailBuilder;
begin
FMail.CCList.Clear;
Result := self;
end;
function TMailBuilder.ClearBCC: TMailBuilder;
begin
FMail.BCCList.Clear;
Result := self;
end;
end.
/////////
unit Email.MailServerBuilder;
interface
uses
variants, SysUtils, System.Classes, System.Generics.Collections, Email.Mail, Email.MailBuilder, Email.MailAttachment;
type
TMailServerSettings = class
public
Host: string;
Port: Integer;
UserName: string;
Password: string;
UseTLS: Boolean;
DefaultFrom: string;
DefaultTo: string;
DefaultCC: string;
DefaultBCC: string;
DebugOverride: string;
OverrideEmail: string;
ReferencePrefix: string;
end;
TMailServerBuilder = class;
TSendMailResult = record
public
Success: Boolean;
ExceptionMessage: string;
end;
TMailServerBuilder = class
FServerSettings: TMailServerSettings;
function LoadFromIniFile(ACompleteFilename: string): TMailServerBuilder;
function SetHost(AHost: string; APort: integer; AUseTLS: boolean = false): TMailServerBuilder;
function SetCredentials(AUserName: string; APassword: string): TMailServerBuilder;
function SendMail(AMailBuilder: TMailBuilder) : TSendMailResult;
function GetReferenceText(AText: string): string;
procedure AddDefaults(AMailBuilder: TMailBuilder);
constructor Create;
destructor Destroy; override;
end;
const EmailConfigSalt: word = 5326;
implementation
uses Helpers.Email;
constructor TMailServerBuilder.Create;
begin
FServerSettings := TMailServerSettings.Create;
end;
destructor TMailServerBuilder.Destroy;
begin
FreeAndNil(FServerSettings);
inherited;
end;
function TMailServerBuilder.GetReferenceText(AText: string): string;
begin
Result := #13#10+FServerSettings.ReferencePrefix+' '+AText;
end;
{
[SMTP]
host=
port=
useTLS=0
Username=
Password=
Override=Email@email.com (keep mail the same, but clean To,Cc, Bcc)
DebugOverride=test@test.com (Set everything in body of mail)
ReferencePrefix= referentienummer:
[DEFAULTS]
From=test@test.com
To=
CC=
BCC=test@test.com
}
function TMailServerBuilder.LoadFromIniFile(ACompleteFilename: string): TMailServerBuilder;
var
iniFile: TMemIniFile;
path: string;
Section: string;
password: string;
EncriptedPassword: string;
begin
path := ACompleteFilename;
iniFile := TMemIniFile.Create(path, TEncoding.ANSI, false);
try
Section:= 'SMTP';
FServerSettings.Host := iniFile.ReadString(Section, 'host', '');
FServerSettings.Port := iniFile.ReadInteger(Section, 'port', 0);
FServerSettings.UserName := iniFile.ReadString(Section, 'Username', '');
password := iniFile.ReadString(Section, 'Password', '');
EncriptedPassword := iniFile.ReadString(Section, 'PasswordEncrypted', '');
if (password.Trim() <> '') then
begin
EncriptedPassword := TEncryptionHelper.Encrypt(password, EmailConfigSalt);
iniFile.WriteString(Section, 'PasswordEncrypted', EncriptedPassword);
iniFile.WriteString(Section, 'Password', '');
iniFile.UpdateFile;
end;
FServerSettings.Password := TEncryptionHelper.Decrypt(EncriptedPassword, EmailConfigSalt);
FServerSettings.UseTLS := iniFile.ReadBool(Section, 'UseTLS', false);
FServerSettings.DebugOverride := iniFile.ReadString(Section, 'DebugOverride', '');
FServerSettings.OverrideEmail := iniFile.ReadString(Section, 'Override', '');
FServerSettings.ReferencePrefix := iniFile.ReadString(Section, 'ReferencePrefix', '');
Section:= 'DEFAULTS';
FServerSettings.DefaultFrom := iniFile.ReadString(Section, 'From', '');
FServerSettings.DefaultTo := iniFile.ReadString(Section, 'To', '');
FServerSettings.DefaultCC := iniFile.ReadString(Section, 'CC', '');
FServerSettings.DefaultBCC := iniFile.ReadString(Section, 'BCC', '');
finally
iniFile.Free;
end;
Result := Self;
end;
function TMailServerBuilder.SendMail(AMailBuilder: TMailBuilder): TSendMailResult;
var
smtpClient : TidSmtp;
mailMessage : TIdMessage;
email: string;
attachment: TMailAttachment;
idAttachment : TIdAttachmentMemory;
SendMailResult : TSendMailResult;
textPart : TIdText;
SSL: TIdSSLIOHandlerSocketOpenSSL;
mail : TMail;
mailBuildResult : TMailBuildResult;
debugContent: string;
begin
try
debugContent := AMailBuilder.GetDebugContent;
if TMailBuilder.IsEmailaddressValid(FServerSettings.DebugOverride) then
begin
AMailBuilder
.ClearTo()
.ClearCC()
.ClearBCC()
.AddTo(FServerSettings.DebugOverride)
.ClearContent()
.AddContent(debugContent);
end else if TMailBuilder.IsEmailaddressValid(FServerSettings.OverrideEmail) then
begin
AMailBuilder
.ClearTo()
.ClearCC()
.ClearBCC()
.AddTo(FServerSettings.OverrideEmail);
end;
mailBuildResult := AMailBuilder.Build;
if (mailBuildResult.Valid) then
begin
mail := mailBuildResult.Mail;
end else
begin
MailLogger.Warning('Failed to build valid Email, Err:' + mailBuildResult.ExecptionMessage);
Result.Success := false;
Result.ExceptionMessage := mailBuildResult.ExecptionMessage;
Exit;
end;
smtpClient := TIdSMTP.Create;
if FServerSettings.UseTLS then
begin
SSL := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
SSL.SSLOptions.Method := sslvTLSv1;
// SSL.SSLOptions.SSLVersions := [sslvSSLv2, sslvSSLv23, sslvSSLv3, sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
SSL.SSLOptions.Mode := sslmClient; // or sslmUnassigned ?
SSL.SSLOptions.VerifyMode := [];
SSL.SSLOptions.VerifyDepth := 0;
smtpClient.IOHandler := SSL;
smtpClient.UseTLS := utUseExplicitTLS;
end;
mailMessage:= TIdMessage.Create(nil);
try
smtpClient.Host := FServerSettings.Host;
smtpClient.Port := FServerSettings.Port;
smtpClient.UserName := FServerSettings.UserName;
smtpClient.Password := FServerSettings.Password;
mailMessage.Body.Clear;
mailMessage.ContentType := 'multipart/related';
mailMessage.Priority := TIdMessagePriority(mail.Priority);
mailMessage.From.Text := mail.From;
mailMessage.Subject := mail.Subject;
for email in mail.ToList do
mailMessage.Recipients.Add().Text := email;
for email in mail.CCList do
mailMessage.CCList.Add().Text := email;
for email in mail.BCCList do
mailMessage.BCCList.Add().Text := email;
mailMessage.ContentType := 'multipart/related';
if (mail.HtmlContent.Length > 0) then
begin
textPart := TIdText.Create(mailMessage.MessageParts);
textPart.Body.Text := mail.HtmlContent;
textPart.ContentType := 'text/html';
textPart.ContentDisposition := 'inline';
end;
textPart := TIdText.Create(mailMessage.MessageParts);
textPart.Body.Text := mail.Content;
textPart.ContentType := 'text/plain';
textPart.ContentDisposition := 'inline';
for attachment in mail.Attachments do
begin
attachment.Data.Position := 0;
idAttachment := TIdAttachmentMemory.Create(mailMessage.MessageParts, attachment.Data);
idAttachment.ContentType := attachment.ContentType;
idAttachment.ContentID := attachment.ContentId;
idAttachment.FileName := attachment.Name;
end;
MailLogger.Trace(FServerSettings.Host +':'+ IntToStr(FServerSettings.Port) + '; Username:' + FServerSettings.UserName);
smtpClient.Connect;
smtpClient.Send(mailMessage);
smtpClient.Disconnect(true);
finally
for attachment in mail.Attachments do
begin
if (attachment.FreeAfterSend) then
begin
attachment.Data.Free;
end;
end;
FreeAndNil(mailMessage);
FreeAndNil(smtpClient);
FreeAndNil(AMailBuilder);
end;
SendMailResult.Success := true;
MailLogger.Info('Mail successfully sent.');
Except
on E: Exception do
begin
SendMailResult.Success := false;
SendMailResult.ExceptionMessage := E.Message;
MailLogger.Error('Failed to send mail.', E);
MailLogger.Trace('FAILED EMAIL CONTENT: ' + #13#10 + debugContent);
end;
end;
Result := SendMailResult;
end;
function TMailServerBuilder.SetCredentials(AUserName: string; APassword: string): TMailServerBuilder;
begin
FServerSettings.UserName := AUserName;
FServerSettings.Password := APassword;
result := Self;
end;
procedure TMailServerBuilder.AddDefaults(AMailBuilder: TMailBuilder);
begin
AMailBuilder.SetFrom(FServerSettings.DefaultFrom);
AMailBuilder.AddTo(FServerSettings.DefaultTo.Split([';', ',']) );
AMailBuilder.AddCC(FServerSettings.DefaultCC.Split([';', ',']));
AMailBuilder.AddBCC(FServerSettings.DefaultBCC.Split([';', ',']));
end;
function TMailServerBuilder.SetHost(AHost: string; APort: integer; AUseTLS: boolean): TMailServerBuilder;
begin
FServerSettings.Host := AHost;
FServerSettings.Port := APort;
FServerSettings.UseTLS := AUseTLS;
result := Self;
end;
end.
415500cookie-checkDelphi Builder example