diff --git a/Source/Mail/Mail.Indy.pas b/Source/Mail/Mail.Indy.pas
new file mode 100644
index 0000000..11d905d
--- /dev/null
+++ b/Source/Mail/Mail.Indy.pas
@@ -0,0 +1,205 @@
+unit Mail.Indy;
+
+interface
+
+uses
+ System.SysUtils,
+ IdSMTP,
+ IdMessage,
+ IdSSLOpenSSL,
+ IdExplicitTLSClientServerBase,
+ IdText,
+ IdAttachmentFile,
+ MailInterface,
+ MailBase;
+
+type
+ EMailIndyException = class(EMailException);
+
+ TMailIndy = class(TMailBase, IMail)
+ private const
+ CONNECT_TIMEOUT = 10000;
+ READ_TIMEOUT = 10000;
+ private
+ procedure ConfigureSmtp(const ASmtp: TIdSMTP);
+ procedure AddToRecipients(const AMsg: TIdMessage);
+ procedure AddCcRecipients(const AMsg: TIdMessage);
+ procedure AddBccRecipients(const AMsg: TIdMessage);
+ procedure AddFrom(const AMsg: TIdMessage);
+ procedure AddReplyTo(const AMsg: TIdMessage);
+ procedure AddAttachments(const AMsg: TIdMessage);
+ procedure AddBody(const AMsg: TIdMessage);
+ protected
+ procedure DoSend; override;
+ public
+ class function New: IMail; static;
+ end;
+
+implementation
+
+{ TMailIndy }
+
+procedure TMailIndy.AddAttachments(const AMsg: TIdMessage);
+var
+ i: Integer;
+ attachment: TIdAttachmentFile;
+begin
+ for i := 0 to Pred(GetAttachments.Count) do
+ begin
+ attachment := TIdAttachmentFile.Create(AMsg.MessageParts, GetAttachments[i]);
+ attachment.Headers.Add(Format('Content-ID: <%s>', [ExtractFileName(GetAttachments[i])]));
+ end;
+end;
+
+procedure TMailIndy.AddBccRecipients(const AMsg: TIdMessage);
+var
+ i: Integer;
+begin
+ for i := 0 to Pred(GetBccRecipients.Count) do
+ begin
+ with AMsg.BccList.Add do
+ begin
+ Address := GetBccRecipients[i];
+ end;
+ end;
+end;
+
+procedure TMailIndy.AddBody(const AMsg: TIdMessage);
+var
+ body: TIdText;
+begin
+ body := TIdText.Create(AMsg.MessageParts);
+ body.Body.Text := GetMessages.Text;
+ body.ContentType := 'text/plain';
+ if IsWithHTML then
+ begin
+ body.ContentType := 'text/html';
+ end;
+end;
+
+procedure TMailIndy.AddCcRecipients(const AMsg: TIdMessage);
+var
+ i: Integer;
+begin
+ for i := 0 to Pred(GetCcRecipients.Count) do
+ begin
+ with AMsg.CCList.Add do
+ begin
+ Address := GetCcRecipients[i];
+ end;
+ end;
+end;
+
+procedure TMailIndy.AddFrom(const AMsg: TIdMessage);
+begin
+ AMsg.From.Address := GetFromAddress;
+ AMsg.From.Name := GetFromName;
+ if IsWithConfirmation then
+ begin
+ AMsg.ReceiptRecipient.Address := GetFromAddress;
+ AMsg.ReceiptRecipient.Name := GetFromName;
+ end;
+end;
+
+procedure TMailIndy.AddReplyTo(const AMsg: TIdMessage);
+begin
+ with AMsg.ReplyTo.Add do
+ begin
+ Address := GetReplyToAddress;
+ Name := GetReplyToName;
+ end;
+end;
+
+procedure TMailIndy.AddToRecipients(const AMsg: TIdMessage);
+var
+ i: Integer;
+begin
+ for i := 0 to Pred(GetToRecipients.Count) do
+ begin
+ with AMsg.Recipients.Add do
+ begin
+ Address := GetToRecipients[i];
+ end;
+ end;
+end;
+
+procedure TMailIndy.ConfigureSmtp(const ASmtp: TIdSMTP);
+begin
+ ASmtp.ConnectTimeout := CONNECT_TIMEOUT;
+ ASmtp.ReadTimeout := READ_TIMEOUT;
+ ASmtp.Host := GetHost;
+ ASmtp.Username := GetUsername;
+ ASmtp.Password := GetPassword;
+ ASmtp.Port := GetPort;
+ ASmtp.AuthType := satNone;
+ if IsWithAuthentication then
+ begin
+ ASmtp.AuthType := satDefault;
+ end;
+ if IsWithSSL then
+ begin
+ ASmtp.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(ASmtp);
+ TIdSSLIOHandlerSocketOpenSSL(ASmtp.IOHandler).SSLOptions.Method := sslvSSLv23;
+ TIdSSLIOHandlerSocketOpenSSL(ASmtp.IOHandler).SSLOptions.Mode := sslmClient;
+ ASmtp.UseTLS := utUseExplicitTLS;
+ end;
+ if IsWithTLS then
+ begin
+ ASmtp.UseTLS := utUseRequireTLS;
+ end;
+end;
+
+procedure TMailIndy.DoSend;
+var
+ smtp: TIdSMTP;
+ msg: TIdMessage;
+begin
+ inherited;
+ smtp := TIdSMTP.Create(nil);
+ try
+ try
+ ConfigureSmtp(smtp);
+ msg := TIdMessage.Create(nil);
+ try
+ msg.Date := Now;
+ msg.Subject := GetSubject;
+ msg.ContentType := 'multipart/mixed';
+
+ AddToRecipients(msg);
+ AddCcRecipients(msg);
+ AddBccRecipients(msg);
+ AddFrom(msg);
+ AddReplyTo(msg);
+ AddAttachments(msg);
+ AddBody(msg);
+
+ smtp.Connect;
+ try
+ if IsWithAuthentication then
+ begin
+ smtp.Authenticate;
+ end;
+ smtp.Send(msg);
+ finally
+ smtp.Disconnect;
+ end;
+ finally
+ FreeAndNil(msg);
+ end;
+ except
+ on E: Exception do
+ begin
+ raise EMailIndyException.Create('E-mail could not be sent!' + ^M + E.Message);
+ end;
+ end;
+ finally
+ FreeAndNil(smtp);
+ end;
+end;
+
+class function TMailIndy.New: IMail;
+begin
+ Result := TMailIndy.Create;
+end;
+
+end.
diff --git a/Source/Mail/MailBase.pas b/Source/Mail/MailBase.pas
new file mode 100644
index 0000000..33169dc
--- /dev/null
+++ b/Source/Mail/MailBase.pas
@@ -0,0 +1,338 @@
+unit MailBase;
+
+interface
+
+uses
+ System.SysUtils,
+ System.Classes,
+ MailInterface;
+
+type
+ TMailBase = class abstract(TInterfacedObject, IMail)
+ private
+ FHost: string;
+ FPort: Integer;
+ FUsername: string;
+ FPassword: string;
+ FSSL: Boolean;
+ FTLS: Boolean;
+ FAuthentication: Boolean;
+ FFromName: string;
+ FFromAddress: string;
+ FReplyToName: string;
+ FReplyToAddress: string;
+ FToRecipients: TStringList;
+ FCcRecipients: TStringList;
+ FBccRecipients: TStringList;
+ FConfirmation: Boolean;
+ FAttachments: TStringList;
+ FSubject: string;
+ FMessages: TStringList;
+ FHTML: Boolean;
+ protected
+ function GetHost: string;
+ function GetPort: Integer;
+ function GetUsername: string;
+ function GetPassword: string;
+ function IsWithSSL: Boolean;
+ function IsWithTLS: Boolean;
+ function IsWithAuthentication: Boolean;
+ function GetFromName: string;
+ function GetFromAddress: string;
+ function GetReplyToName: string;
+ function GetReplyToAddress: string;
+ function GetToRecipients: TStringList;
+ function GetCcRecipients: TStringList;
+ function GetBccRecipients: TStringList;
+ function IsWithConfirmation: Boolean;
+ function GetAttachments: TStringList;
+ function GetSubject: string;
+ function GetMessages: TStringList;
+ function IsWithHTML: Boolean;
+
+ procedure DoSend; virtual; abstract;
+
+ public
+ constructor Create;
+ destructor Destroy; override;
+
+ function Host(const AValue: string): IMail;
+ function Port(const AValue: Integer): IMail;
+ function Username(const AValue: string): IMail;
+ function Password(const AValue: string): IMail;
+ function UsingSSL(const AValue: Boolean = True): IMail;
+ function UsingTLS(const AValue: Boolean = True): IMail;
+ function AuthenticationRequired(const AValue: Boolean = True): IMail;
+
+ function From(const AName: string; const AAddress: string): IMail;
+ function ReplyTo(const AName: string; const AAddress: string): IMail;
+ function ToRecipient(const AAddress: string): IMail;
+ function CcRecipient(const AAddress: string): IMail;
+ function BccRecipient(const AAddress: string): IMail;
+ function AskForConfirmation(const AValue: Boolean = True): IMail;
+
+ function Attachment(const AFileName: string): IMail;
+
+ function Subject(const AValue: string): IMail;
+ function &Message(const AValue: string): IMail; overload;
+ function &Message(const AValues: TStringList): IMail; overload;
+ function UsingHTML(const AValue: Boolean = True): IMail;
+
+ procedure Send;
+ end;
+
+implementation
+
+{ TMailBase }
+
+function TMailBase.AskForConfirmation(const AValue: Boolean): IMail;
+begin
+ FConfirmation := AValue;
+ Result := Self;
+end;
+
+function TMailBase.Attachment(const AFileName: string): IMail;
+begin
+ FAttachments.Add(AFileName);
+ Result := Self;
+end;
+
+function TMailBase.AuthenticationRequired(const AValue: Boolean): IMail;
+begin
+ FAuthentication := AValue;
+ Result := Self;
+end;
+
+function TMailBase.BccRecipient(const AAddress: string): IMail;
+begin
+ FBccRecipients.Add(AAddress);
+ Result := Self;
+end;
+
+function TMailBase.CcRecipient(const AAddress: string): IMail;
+begin
+ FCcRecipients.Add(AAddress);
+ Result := Self;
+end;
+
+constructor TMailBase.Create;
+begin
+ inherited Create;
+ FHost := EmptyStr;
+ FPort := 0;
+ FUsername := EmptyStr;
+ FPassword := EmptyStr;
+ FSSL := False;
+ FTLS := False;
+ FAuthentication := False;
+ FFromName := EmptyStr;
+ FFromAddress := EmptyStr;
+ FToRecipients := TStringList.Create;
+ FCcRecipients := TStringList.Create;
+ FBccRecipients := TStringList.Create;
+ FConfirmation := False;
+ FAttachments := TStringList.Create;
+ FSubject := EmptyStr;
+ FMessages := TStringList.Create;
+ FHTML := False;
+end;
+
+destructor TMailBase.Destroy;
+begin
+ FreeAndNil(FToRecipients);
+ FreeAndNil(FCcRecipients);
+ FreeAndNil(FBccRecipients);
+ FreeAndNil(FAttachments);
+ FreeAndNil(FMessages);
+ inherited Destroy;
+end;
+
+function TMailBase.From(const AName, AAddress: string): IMail;
+begin
+ FFromName := AName;
+ FFromAddress := AAddress;
+ Result := Self;
+end;
+
+function TMailBase.GetAttachments: TStringList;
+begin
+ Result := FAttachments;
+end;
+
+function TMailBase.GetBccRecipients: TStringList;
+begin
+ Result := FBccRecipients;
+end;
+
+function TMailBase.GetCcRecipients: TStringList;
+begin
+ Result := FCcRecipients;
+end;
+
+function TMailBase.GetFromAddress: string;
+begin
+ Result := FFromAddress;
+end;
+
+function TMailBase.GetFromName: string;
+begin
+ Result := FFromName;
+end;
+
+function TMailBase.GetHost: string;
+begin
+ Result := FHost;
+end;
+
+function TMailBase.GetMessages: TStringList;
+begin
+ Result := FMessages;
+end;
+
+function TMailBase.GetPassword: string;
+begin
+ Result := FPassword;
+end;
+
+function TMailBase.GetPort: Integer;
+begin
+ Result := FPort;
+end;
+
+function TMailBase.GetReplyToAddress: string;
+begin
+ Result := FReplyToAddress;
+ if Result.Trim.IsEmpty then
+ begin
+ Result := FFromAddress;
+ end;
+end;
+
+function TMailBase.GetReplyToName: string;
+begin
+ Result := FReplyToName;
+ if Result.Trim.IsEmpty then
+ begin
+ Result := FFromName;
+ end;
+end;
+
+function TMailBase.GetSubject: string;
+begin
+ Result := FSubject;
+end;
+
+function TMailBase.GetToRecipients: TStringList;
+begin
+ Result := FToRecipients;
+end;
+
+function TMailBase.GetUsername: string;
+begin
+ Result := FUsername;
+end;
+
+function TMailBase.Host(const AValue: string): IMail;
+begin
+ FHost := AValue;
+ Result := Self;
+end;
+
+function TMailBase.IsWithAuthentication: Boolean;
+begin
+ Result := FAuthentication;
+end;
+
+function TMailBase.IsWithConfirmation: Boolean;
+begin
+ Result := FConfirmation;
+end;
+
+function TMailBase.IsWithHTML: Boolean;
+begin
+ Result := FHTML;
+end;
+
+function TMailBase.IsWithSSL: Boolean;
+begin
+ Result := FSSL;
+end;
+
+function TMailBase.IsWithTLS: Boolean;
+begin
+ Result := FTLS;
+end;
+
+function TMailBase.Message(const AValue: string): IMail;
+begin
+ FMessages.Add(AValue);
+ Result := Self;
+end;
+
+function TMailBase.Message(const AValues: TStringList): IMail;
+begin
+ FMessages.Text := AValues.Text;
+ Result := Self;
+end;
+
+function TMailBase.Password(const AValue: string): IMail;
+begin
+ FPassword := AValue;
+ Result := Self;
+end;
+
+function TMailBase.Port(const AValue: Integer): IMail;
+begin
+ FPort := AValue;
+ Result := Self;
+end;
+
+function TMailBase.ReplyTo(const AName, AAddress: string): IMail;
+begin
+ FReplyToName := AName;
+ FReplyToAddress := AAddress;
+ Result := Self;
+end;
+
+procedure TMailBase.Send;
+begin
+ DoSend;
+end;
+
+function TMailBase.Subject(const AValue: string): IMail;
+begin
+ FSubject := AValue;
+ Result := Self;
+end;
+
+function TMailBase.ToRecipient(const AAddress: string): IMail;
+begin
+ FToRecipients.Add(AAddress);
+ Result := Self;
+end;
+
+function TMailBase.Username(const AValue: string): IMail;
+begin
+ FUsername := AValue;
+ Result := Self;
+end;
+
+function TMailBase.UsingHTML(const AValue: Boolean): IMail;
+begin
+ FHTML := AValue;
+ Result := Self;
+end;
+
+function TMailBase.UsingSSL(const AValue: Boolean): IMail;
+begin
+ FSSL := AValue;
+ Result := Self;
+end;
+
+function TMailBase.UsingTLS(const AValue: Boolean): IMail;
+begin
+ FTLS := AValue;
+ Result := Self;
+end;
+
+end.
diff --git a/Source/Mail/MailInterface.pas b/Source/Mail/MailInterface.pas
new file mode 100644
index 0000000..351bd62
--- /dev/null
+++ b/Source/Mail/MailInterface.pas
@@ -0,0 +1,42 @@
+unit MailInterface;
+
+interface
+
+uses
+ System.Classes,
+ System.SysUtils;
+
+type
+ EMailException = class(Exception);
+
+ IMail = interface
+ ['{07C2551B-B2A6-47C6-9454-A2AE5BE884DB}']
+
+ function Host(const AValue: string): IMail;
+ function Port(const AValue: Integer): IMail;
+ function Username(const AValue: string): IMail;
+ function Password(const AValue: string): IMail;
+ function UsingSSL(const AValue: Boolean = True): IMail;
+ function UsingTLS(const AValue: Boolean = True): IMail;
+ function AuthenticationRequired(const AValue: Boolean = True): IMail;
+
+ function From(const AName: string; const AAddress: string): IMail;
+ function ReplyTo(const AName: string; const AAddress: string): IMail;
+ function ToRecipient(const AAddress: string): IMail;
+ function CcRecipient(const AAddress: string): IMail;
+ function BccRecipient(const AAddress: string): IMail;
+ function AskForConfirmation(const AValue: Boolean = True): IMail;
+
+ function Attachment(const AFileName: string): IMail;
+
+ function Subject(const AValue: string): IMail;
+ function &Message(const AValue: string): IMail; overload;
+ function &Message(const AValue: TStringList): IMail; overload;
+ function UsingHTML(const AValue: Boolean = True): IMail;
+
+ procedure Send;
+ end;
+
+implementation
+
+end.
diff --git a/Source/Mail/README.md b/Source/Mail/README.md
new file mode 100644
index 0000000..aa97822
--- /dev/null
+++ b/Source/Mail/README.md
@@ -0,0 +1,41 @@
+# E-mail para Delphi
+
+Framework de mailing voltada para simplificar o envio de e-mails com Delphi.
+Inclui envio de e-mails com texto simples e/ou HTML, imagens incorporadas e anexos separados.
+Utiliza: SMTP ou SMTPS/SSL ou SMTP + SSL.
+O **Mail** fornece uma estrutura independente de driver, sendo possível extendê-lo para outros, como **Outlook**, **MAPI**, **Synapse** entre outros.
+
+A estrutura da mensagem de e-mail foi construída para funcionar com todos os clientes de e-mail e foi testada com muitos clientes da web, bem como alguns aplicativos de cliente convencionais, como MS Outlook ou Mozilla Thunderbird.
+
+# Drivers implementados
+- Indy
+
+# Modo de usar
+Adicione no library path do Delphi:
+
+> Source\Mail
+
+# Exemplo de uso
+
+```
+uses
+ MailBase,
+ Mail.Indy;
+
+procedure EnviaEmail;
+begin
+ TMailIndy.New
+ .Host('smtp.exemplo.com.br')
+ .Port(123)
+ .Username('usuario')
+ .Password('senha_forte_do_usuario')
+ .From('Princess Leia', 'princess.leia@jabba.the.hutt.com')
+ .ToRecipient('darth.vader@darkforce.com')
+ .CcRecipient('mestre.yoda@jedi.com')
+ .BccRecipient('obi.wan.kenoby@jedi.com')
+ .Attachment('C:\jabba.the.hutt.kill.luke.skywalker.jpg')
+ .Subject('Veja só, Jabba The Hutt mata Luke Skywalker')
+ .Message('Caro Darth Vader, veja como ele ficou nessa imagem... hahahaha')
+ .Send;
+end
+```
\ No newline at end of file
diff --git a/TestAtlas.dpr b/TestAtlas.dpr
index 5412a07..2eb91e8 100644
--- a/TestAtlas.dpr
+++ b/TestAtlas.dpr
@@ -16,7 +16,11 @@ uses
TesteSQLBuilder.Insert in 'Testes\SQLBuilder\TesteSQLBuilder.Insert.pas',
TesteObjetoConexao in 'Testes\TesteObjetoConexao.pas',
Types.Conexao in 'Source\Objetos\Types.Conexao.pas',
- SQLBuilder in 'Source\SQLBuilder\SQLBuilder.pas';
+ SQLBuilder in 'Source\SQLBuilder\SQLBuilder.pas',
+ TesteMail.Indy in 'Testes\Mail\TesteMail.Indy.pas',
+ MailInterface in 'Source\Mail\MailInterface.pas',
+ MailBase in 'Source\Mail\MailBase.pas',
+ Mail.Indy in 'Source\Mail\Mail.Indy.pas';
var
runner : ITestRunner;
diff --git a/TestAtlas.dproj b/TestAtlas.dproj
index bbc59c3..fb2e90d 100644
--- a/TestAtlas.dproj
+++ b/TestAtlas.dproj
@@ -106,6 +106,10 @@
+
+
+
+
Cfg_2
Base
diff --git a/Testes/Mail/TesteMail.Indy.pas b/Testes/Mail/TesteMail.Indy.pas
new file mode 100644
index 0000000..a3e027f
--- /dev/null
+++ b/Testes/Mail/TesteMail.Indy.pas
@@ -0,0 +1,45 @@
+unit TesteMail.Indy;
+
+interface
+
+uses
+ DUnitX.TestFramework,
+ DUnitX.Assert.Ex;
+
+type
+
+ [ TestFixture ]
+ TTestSQLBuilderSelect = class( TObject )
+ public
+
+ [ Test ]
+ procedure sendEmail;
+
+ end;
+
+implementation
+
+uses
+ MailBase,
+ Mail.Indy;
+
+{ TTestSQLBuilderSelect }
+
+procedure TTestSQLBuilderSelect.sendEmail;
+begin
+ TMailIndy.New
+ .Host('')
+ .Port(0)
+ .Username('')
+ .Password('')
+ .From('name', 'email')
+ .ToRecipient('')
+ .CcRecipient('')
+ .BccRecipient('')
+ .Attachment('')
+ .Subject('')
+ .Message('')
+ .Send;
+end;
+
+end.
diff --git a/pkgAtlas.dpk b/pkgAtlas.dpk
index d9876db..ae6730b 100644
--- a/pkgAtlas.dpk
+++ b/pkgAtlas.dpk
@@ -25,7 +25,7 @@ package pkgAtlas;
{$IMAGEBASE $400000}
{$DEFINE DEBUG}
{$ENDIF IMPLICITBUILDING}
-{$DESCRIPTION 'Atlas Framework'}
+{$DESCRIPTION 'SDK Runtine Libraries'}
{$RUNONLY}
{$IMPLICITBUILD ON}
@@ -33,12 +33,18 @@ requires
rtl,
vcl,
FireDAC,
- dbrtl;
+ dbrtl,
+ IndySystem,
+ IndyProtocols,
+ IndyCore;
contains
ValorPor in 'Source\ValorPor.pas',
SQLBuilder in 'Source\SQLBuilder\SQLBuilder.pas',
Conexao in 'Source\Objetos\Conexao.pas',
- Types.Conexao in 'Source\Objetos\Types.Conexao.pas';
+ Types.Conexao in 'Source\Objetos\Types.Conexao.pas',
+ MailInterface in 'Source\Mail\MailInterface.pas',
+ MailBase in 'Source\Mail\MailBase.pas',
+ Mail.Indy in 'Source\Mail\Mail.Indy.pas';
end.
diff --git a/pkgAtlas.dproj b/pkgAtlas.dproj
index ca605de..020f718 100644
--- a/pkgAtlas.dproj
+++ b/pkgAtlas.dproj
@@ -54,7 +54,7 @@
All
pkgAtlas
true
- $(DCC_UnitSearchPath);modules\.dcp;modules\.dcu;modules;modules\.bpl;modules\doscommand\Source
+ modules\.dcp;modules\.dcu;modules;modules\.bpl;modules\doscommand\Source;$(DCC_UnitSearchPath)
Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;$(DCC_Namespace)
@@ -102,10 +102,16 @@
+
+
+
+
+
+
Cfg_2
Base
@@ -148,14 +154,14 @@
true
-
+
- pkgAtlas.bpl
true
-
+
+ pkgAtlas.bpl
true