SMTP
Smtp interface provides the service to send emails using the Simple Mail Transfer Protocol.
To create an ISmtp instance, at first an instance of ISmtpProvider, ISocketProvider (TCP) and ISocketProvider (TLS) must be created.
This need to be done by calling CreateSmtpProvider(), CreateTCPSocketProvider() and CreateTLSSocketProvider(tcpSocketProvider).
An ISmtpProvider can be used to create multiple ISmtp instances. To read more about the ISocket, please check:
ISocket.
When a new TaskSmtpSend is started, the connection with the SMTP server is established using TCP.
If the server allows STARTTLS, the connection will be upgraded to TLS. Otherwise TCP will continue to be used.
File information
Functions
Functions to initialize
class ISmtpProvider * CreateSmtpProvider();
CreateSmtpProvider
Creates an instance of the ISmtpProvider.
Return value
The actual ISmtpProvider instance. That instance can be freed as soon as it no longer is used by calling the C++ delete operator.
Classes
ISmtpProvider
class ISmtpProvider {
public:
virtual ~ISmtpProvider() {}
virtual class ISmtp * CreateSmtp(class IIoMux * iomux, class ISocketProvider * tcpSocketProvider, class ISocketProvider * tlsSocketProvider, class IInstanceLog * const log) = 0;
};
Overview
This class provides ISmtp instance to manage the task to send emails.
Public functions
CreateSmtpProvider
Returns a new ISmtp instance.
Parameters
class IIoMux * const iomux | The IIoMux instance the smtp will be registered to. |
class ISocketProvider * tcpSocketProvider | The socket provider for the TCP connection. |
class ISocketProvider * tlsSocketProvider | The socket provider for the TLS connection. |
class IInstanceLog * const log | The IInstanceLog instance used for loging purposes. |
Return value
An ISmtp instance that can be used to manage the task to send emails.
Remarks
The application should store a pointer to it.
ISmtp
class ISmtp {
public:
virtual ~ISmtp() {}
virtual class ISmtpSend * CreateSend(const char *from, const char *fromName, const char *subject, const char *host, const char *server, const char *userSmtp, const char *password) = 0;
virtual void SendChunk(const char *attachmentChunk, int sChunk, bool lastChunk, dword fileIndex) = 0;
};
Overview
This class provides ISmtpSend task to send an email.
Public functions
CreateSend
Returns a new SMTP Provider.
Parameters
const char * from | The sender's email address. |
const char * fromName | The sender's name on UTF-8. |
const char * subject | The subject for the email on UTF-8. |
const char * host | The host name from the SMPT server. |
const char * server | The SMTP server. |
const char * userSmtp | The sender's user, if authentication is required. |
const char * password | The sender's password, if authentication is required. |
Return value
An ISmtpSend task that can be used to send an email.
SendChunk
Returns a new SMTP Provider.
Parameters
const char * attachmentChunk | The chunk of the file that will be attached. |
int sChunk | The size of the chunk. |
bool lastChunk | This indicates if this is the last chunk of the attachment (true) or there are still more (false). |
dword fileIndex | The number that identifies the attached file (starting on 0 and ending with the number of files been attached minus 1). |
Remarks
This must be called inside TaskProgress if at least one file has been attached to the email.
ISmtpSend
class ISmtpSend : public ITask {
public:
virtual void AddAttachment(const char *attachmentUrl) = 0;
virtual void AddTo(const char *rcpt) = 0;
virtual void AddCc(const char *rcpt) = 0;
virtual void AddBcc(const char *rcpt) = 0;
virtual void AddBody(const char *data, const char *format, const char *charset) = 0;
virtual void Start(class UTask * user) = 0;
};
Overview
This class implements the task to send an email.
Public functions
AddAttachment
Adds a new attachment to the email.
Parameters
const char * attachmentUrl | The filename of the attachment that will be sent. |
Remarks
It should be called once per attachment.
AddTo
Adds a new receiver to the recipients list.
Parameters
const char * rcpt | The receiver's email address. |
Remarks
It should be called at least once before Start(). The email will be sent to every rcpt if they are reachable (for example, it could be unreachable if your SMTP server is on "Relay Access denied" mode).
If none of the receivers is reachable, the email will not be sent.
AddCc
Adds a new receiver to the recipients list. The email will be sent as a Carbon Copy to this receiver.
Parameters
const char * rcpt | The receiver's email address. |
Remarks
It should be called at least once before Start(). The email will be sent to every rcpt if they are reachable (for example, it could be unreachable if your SMTP server is on "Relay Access denied" mode).
If none of the receivers is reachable, the email will not be sent.
AddBcc
Adds a new receiver to the recipients list. The email will be sent as a Blind Carbon Copy to this receiver.
Parameters
const char * rcpt | The receiver's email address. |
Remarks
It should be called at least once before Start(). The email will be sent to every rcpt if they are reachable (for example, it could be unreachable if your SMTP server is on "Relay Access denied" mode).
If none of the receivers is reachable, the email will not be sent.
AddBody
Adds the body to the email.
Parameters
const char * data | The text that will be sent on the body. |
const char * format | The text format i.e., text/html or text/plains. |
const char * charset | The text charset i.e., ISO-8859-1 or UTF-8. |
Remarks
This function must be called at least one. If the email should not have a body, this function must still be called with and empty string as body and valid format and charset values.
Start
Starts the task that sends the email.
Parameters
class UTask * user | Used for the callbacks for task completion. |
Remarks
Several ISmtpSend tasks can be called at once and the emails will be queued.
Code Examples
Initialize the Provider
#include "common/interface/smtp.h"
...
ISmtpProvider * smtpProvider = CreateSmtpProvider();
...
AppService * service = new AppService(iomux, localSocketProvider, tcpSocketProvider, tlsSocketProvider, ..., smtpProvider, &serviceArgs);
...
delete smtpProvider;
Create the ISmtp instance
app::app(IIoMux * const iomux, ISocketProvider * localSocketProvider, IWebserverPluginProvider * const webserverPluginProvider, IDatabaseProvider * databaseProvider, class Service * service, ISmtpProvider * smtpProvider, AppInstanceArgs * args) :
AppInstance(service, args)
{
this->smtp = smtpProvider->CreateSmtp(iomux, tcpSocketProvider, tlsSocketProvider, this, "145.253.157.7");
this->logFlags |= LOG_SMTP; // to show the flags generated by the SMTP class
}
app::~app()
{
if (webserverPlugin) delete webserverPlugin;
if (smtp) delete smtp;
}
Send Emails
SendEmail::SendEmail(class App * app): taskSmtp(this, &SendEmail::SmtpSendComplete, &SendEmail::SmtpSendFailed, &SendEmail::SmtpSendProgress)
{
...
}
SendEmail::~SendEmail()
{
...
}
void SendEmail::Send()
{
ISmtpSend * emailTask = appInstance->smtp->CreateSend("sender@innovaphone.com", "SenderName", "Subject", "sophos", "sophos.innovaphone.com", "usersmtp", "password");
emailTask->AddTo("receiver@innovaphone.com");
emailTask->AddTo("otherreceiver@innovaphone.com");
emailTask->AddBody("Body of the email...", "text/html", "ISO-8859-1");
emailTask->AddAttachment("test.txt");
emailTask->AddAttachment("Fish.png");
emailTask->AddAttachment("rfc821.pdf");
bufferrb = (char*)malloc(sizeof(char) * 4096);
emailTask->Start(&taskSmtp);
}
void SendEmail::SmtpSendComplete(class TaskSmtpSend * task)
{
...
}
void SendEmail::SmtpSendFailed(class TaskSmtpSend * task)
{
...
}
void SendEmail::SmtpSendProgress(class TaskSmtpSend * task, dword progress)
{
//SmtpSendProgress will be called for every attachment added. For each attachment it will be called until lastChunk will be set as true.
//progress indicates the number of the attachment requested by the task.
//It starts with "0" for the first filename added.
appInstance->smtp->SendChunk(ReadFiles(progress), len, lastChunk, progress);
}
char * SendEmail::ReadFiles(dword file) //Example function to get the attachments chunks.
{
char * path = (char*)"";
switch (file)
{
case 0:
path = (char*)"/path/test.txt";
break;
case 1:
path = (char*)"/path/Fish.png";
break;
case 2:
path = (char*)"/path/rfc821.pdf";
break;
default:
break;
}
if (!opened)
{
opened = true;
pFile = fopen(path, "rb");
fseek(pFile, 0, SEEK_END);
lSize = ftell(pFile);
rewind(pFile);
lastChunk = false;
bytesRead = 0;
}
if (!feof(pFile))
{
len = 0;
len = fread(bufferrb, 1, 4096, pFile);
bytesRead += len;
if (bytesRead >= lSize) lastChunk = true;
}
if (lastChunk)
{
opened = false;
fclose(pFile);
}
return bufferrb;
}