Click here to Skip to main content
15,867,704 members
Articles / Desktop Programming / MFC
Article

CSMTPConnection v1.36

Rate me:
Please Sign up or sign in to vote.
4.94/5 (59 votes)
3 Mar 2000 728.7K   8.6K   160   194
An MFC class to encapsulate the SMTP protocol.

Welcome to CSMTPConnection, a freeware MFC class to support the SMTP protocol. SMTP for those not familiar with all the internet protocols is the protocol used to send internet email.

For detailed information about the Simple Mail Transfer Protocol you should read RFC 821,

Other documents that these classes refer to are RFC 2045 (which defines how MIME attachments are to be handled in a standard SMTP message) and RFC 822 (which defines the way standard headers which SMTP uses).

You can find numerous Web Servers which carry these documents by going to www.yahoo.com and look for RFC and 821, 822 or 2045.

Features
Usage
History
API Reference
Planned Enhancements
Contacting the Author

Features

  • Simple and clean C++ interface.
  • The interface provided is synchronous which provides an easier programming model than using asynchronous sockets.
  • The code does not rely on the MFC socket classes. These classes have a number of shortcomings, one of which causes problems when they are used in NT services.
  • The code can be used in a console application without any problems (Again this is not the case for the MFC socket classes).
  • A configurable timeout for the connection can be set through the class API.
  • The classes are fully Unicode compliant and include Unicode built options in the workspace file.
  • As of v1.1, the classes now fully supports sending file attachments.
  • Multi CC, BCC & Reply To support is included.
  • Support for regular email address formats and multiple email address parsing.

Usage

  • To use the class in your code simply include smtp.cpp in your project and #include smtp.h in which ever of your modules needs to make calls to the class.
  • Your code will need to include MFC either statically or dynamically.
  • You will need to have a functioning winsock stack installed and correctly initialised prior to calling any functions in CSMTPConnection. Depending on your application, this will involve calling either WSAStartup or AfxSocketInit at startup of your application.
  • You will also need to have afxtempl.h ,winsock.h or afxsock.h and afxpriv.h in your precompiled header. The code will work just aswell in a GUI or console app. The code should also work in a multithreaded application, although it has not be explicitly tested in this scenario.
  • To see the class in action, have a look at the code in InitInstance in the module "main.cpp". For example to send a message to the Author about this class, the code would look something like this (ignoring error handling):
C++
CSMTPConnection smtp;
smtp.Connect("mail.yourisp.com");

CSMTPMessage m;
m.AddRecipient(CSMTPAddress("pjn@indigo.ie"));
m.m_From = CSMTPAddress("you@someisp.com");
m.m_sSubject = "Here's my autoexec.bat file!";

CSMTPAttachment a;
a.Attach("c:\\autoexec.bat");
m.AddAttachment(&a);

smtp.SendMessage(m);

To send your autoexec.bat as a file attachment to me you would use the following code:

C++
CSMTPConnection smtp;
smtp.Connect("mail.yourisp.com");

CSMTPMessage m;
m.AddRecipient(CSMTPAddress("pjn@indigo.ie"));
m.m_From = CSMTPAddress("you@someisp.com");
m.m_sSubject = "Here's my autoexec.bat file!";

CSMTPAttachment a;
a.Attach("c:\\autoexec.bat");
m.AddAttachment(&a);

smtp.SendMessage(m);

History

V1.0 (26th May 1998)

  • Initial public release.

V1.1 (17th June 1998)

  • Fixed the case where a single dot occurs on its own in the body of a message
  • Classes now supports an optional "Reply-To" Header Field
  • Classes now fully supports file attachments
  • Some rework on the contents of the help file

V1.11 (18th June 1998)

  • Fixed a memory overwrite problem which was occurring with the buffer used for encoding base64 attachments.

V1.12 (27th June 1998)

  • The case where a line begins with a "." but contains other text is now also catered for. See RFC821, Section 4.5.2 for further details.
  • m_sBody in CSMTPMessage has now been made protected. Client applications now should call AddBody instead. This ensures that FixSingleDot is only called once even if the same message is sent a number of times.
  • Fixed a number of problems with how the MIME boundaries were defined and sent.
  • Got rid of an unreferenced formal parameter compiler warning when doing a release build.

V1.2 (11 August 1998)

  • VC 5 project file is now provided instead of VC 4.x
  • Attachment array which the message class contains now uses references instead of pointers.
  • Now uses Sleep(0) to yield our time slice instead of Sleep(100), this is the preferred way of writting polling style code in Win32 without serverly impacting performance.
  • All trace statements now display the value as returned from GetLastError
  • A number of extra asserts have been added
  • AddMultipleRecipients has been added which supports added a number of recipients at one time from a single string
  • Extra trace statements have been added to help in debugging
  • A number of updates to the documentation.

V1.21 (12 September 1998)

  • Removed a couple of unreferenced variable compiler warnings discovered when the class was compiled on Visual C++ 6.0.
  • Fixed a major bug which was causing an ASSERT when the CSMTPAttachment destructor was being called in the InitInstance of the sample app. This was inadvertingly introduced for the 1.2 release. The fix is to revert fix 2) as done for v1.2. This new fix will also help to reduce the number of attachment images kept in memory at one time.
  • Fixed a few errors in this help file.

V1.3 (18 January 1999)

  • Full support has now been added for CC (Carbon Copy) & BCC (Blind Carbon Copy).

V1.31 (22 February 1999)

  • Added a Get and SetTitle method which allows a files attachment title to be different that the original filename.
  • Updated sample app to include a more descriptive subject line.
  • Default timeout for the code when a debug build is built has now been set to 60 seconds.
  • Improved the reading of responses back from the server by implementing a growable receive buffer.
  • Updated instructions on how the relavent RFC documents can be retrieved.

V1.32 (25 March 1999)

  • Now sleeps for 250 ms instead of yielding the time slice. This helps reduce CPU usage when waiting for data to arrive in the socket.

V1.33 (14 May 1999)

  • Updated documentation to refer to RFC 822.
  • Fixed a bug with the way the code generates time zone fields in the Date headers. Thanks to Randy A. Scott for reporting this bug.

V1.34 (10 September 1999)

  • Improved CSMTPMessage::GetHeader to include mime field even when no attachments are included.

V1.35 (5 October 1999)

  • Fixed 2 level 4 warnings when compiled using VC 6.

V1.36 (16 February 2000)

  • Fixed another compiler problem when compiled with VC 6.

API Reference

The API consists of the public member functions of the class CSMTPAddress, CSMTPMessage & CSMTPConnection

CSMTPAddress
CSMTPAttachment::Attach
CSMTPAttachment::GetFilename
CSMTPAttachment::GetEncodedBuffer
CSMTPAttachment::GetEncodedSize
CSMTPAttachment::SetTitle
CSMTPAttachment::GetTitle
CSMTPMessage::AddRecipient
CSMTPMessage::RemoveRecipient
CSMTPMessage::GetRecipient
CSMTPMessage::GetNumberOfRecipients
CSMTPMessage::AddAttachment
CSMTPMessage::RemoveAttachment
CSMTPMessage::GetAttachment
CSMTPMessage::GetNumberOfAttachments
CSMTPMessage::m_From
CSMTPMessage::m_sSubject
CSMTPMessage::AddBody
CSMTPMessage::AddMultipleRecipients
CSMTPMessage::m_sXMailer
CSMTPMessage::m_ReplyTo
CSMTPConnection::Connect
CSMTPConnection::Disconnect
CSMTPConnection::GetLastCommandResponse
CSMTPConnection::GetLastCommandResponseCode
CSMTPConnection::GetTimeoutCSMTPConnection::SetTimeout
CSMTPConnection::SendMessage

CSMTPAddress

Remarks

This class is an encapsulation of an address used in sending an email. It consists of 2 strings namely m_sFriendlyName and m_sEmailAddress. An example of constructing an address is:

CSMTPAddress a(_T("pjn@indigo.ie")); // or
CSMTPAddress b(_T("PJ Naughter"),_T("pjn@indigo.ie"));

The second form which includes a friendly address allows it to be used in "To" and "Reply-To" headers in the form "PJ Naughter <pjn@indigo.ie>"

One public class method is included called GetRegularFormat which returns the format just discussed.

See Also

CSMTPConnection::SendMessage

CSMTPAttachment::Attach

BOOL Attach(const CString& sFilename);

Return Value

TRUE if the file was successfully encoded as an attachment otherwise FALSE.

Parameters

sFilename A reference to the name of the file to setup as an attachment.

Remarks

Internally this function will perform a base64 encoding of the specified file and store the encoding in a private buffer ready for use when this attachment is associated with an SMTP message.

See Also

CSMTPMessage::AddAttachment

CSMTPAttachment::GetFilename

CString GetFilename() const;

Return Value

Returns the name of the file this attachment represents

Parameters

None

Remarks

This will return just the "filename.ext" form of the filename. e.g. if you called Attach with the filename "c:\autoexec.bat", the return value from GetFilename will be "autoexec.bat".

CSMTPAttachment::GetEncodedBuffer

const char* GetEncodedBuffer() const;

Return Value

Returns the base64 encoded representation of the attachment

Parameters

None

Remarks

None

CSMTPAttachment::SetTitle

void SetTitle(const CString& sTitle);

Parameters

sTitle The new title of the file attachment

Remarks

Allows you to change the name of the attachment as it will appear in the email. By default it will be the filename of the file you add. Examples where this are useful are if you save a file to a temporary filename on your machine prior to emailing it to someone.

See Also

CSMTPMessage::GetTitle

CSMTPAttachment::GetTitle

CString GetTitle() const;

Return Value

The name of the attchement as it will appear in the email

See Also

CSMTPMessage::SetTitle

CSMTPMessage::AddRecipient

int AddRecipient(CSMTPAddress& recipient, RECIPIENT_TYPE RecipientType = TO);

Return Value

The index of the newly added recipient to the message.

Parameters

recipient A reference to the recipient to add to this message.

RecipientType The type of recipient to add. RECIPIENT_TYPE is an enum with the following three values: TO, CC & BCC

Remarks

Adds a recipient of the specified type to a message. This would normally be called at least once, prior to sending an email message.

See Also

CSMTPMessage::RemoveRecipient

CSMTPMessage::RemoveRecipient

void RemoveRecipient(int nIndex, RECIPIENT_TYPE RecipientType = TO);

Return Value

None.

Parameters

nIndex The index of the recipient to remove.

RecipientType The type of recipient "nIndex" refers to. RECIPIENT_TYPE is an enum with the following three values: TO, CC & BCC

Remarks

The corollary function of AddRecipient.

See Also

CSMTPMessage::AddRecipient

CSMTPMessage::GetRecipient

CSMTPAddress GetRecipient(int nIndex, RECIPIENT_TYPE RecipientType = TO) const;

Return Value

The recipient at the specified offset.

Parameters

nIndex The index of the recipient to retrieve.

RecipientType The type of recipient "nIndex" refers to. RECIPIENT_TYPE is an enum with the following three values: TO, CC & BCC

Remarks

Allows access to the array of recipients associated with a message.

See Also

CSMTPMessage::AddRecipient

CSMTPMessage::GetNumberOfRecipients

int GetNumberOfRecipients(RECIPIENT_TYPE RecipientType = TO) const;

Return Value

The number of recipients for this message.

Parameters

RecipientType The type of recipients to retreive the size for. RECIPIENT_TYPE is an enum with the following three values: TO, CC & BCC

Remarks

Returns the number of recipients this message is destined for.

See Also

CSMTPMessage::AddRecipient

CSMTPMessage::AddAttachment

int AddAttachment(CSMTPAttachment* pAttachment);

Return Value

The index of the newly added attachment to the message.

Parameters

pAttachment A pointer to the file attachment to add to this message.

Remarks

Adds an attachment to a message. Please bear in mind that internally a buffer will be allocated by this function and which is used while sending the attachment. This means that the "attachment" instance must remain valid during the lifetime of the call to CSMTPConnection::SendMessage

See Also

CSMTPMessage::RemoveAttachment CSMTPConnection::SendMessage

CSMTPMessage::RemoveAttachment

void RemoveAttachment(int nIndex);

Return Value

None.

Parameters

nIndex The index of the attachment to remove.

Remarks

The corollary function of AddAttachment.

See Also

CSMTPMessage::AddAttachment

CSMTPMessage::GetAttachment

CSMTPAttachment* GetAttachment(int nIndex) const;

Return Value

A pointer to the attachment at the specified offset.

Parameters

nIndex The index of the attachment to retrieve.

Remarks

Allows access to the array of attachments associated with a message.

See Also

CSMTPMessage::AddAttachment

CSMTPMessage::GetNumberOfAttachments

int GetNumberOfAttachments() const;

Return Value

The number of attachments for this message.

Parameters

None.

Remarks

Returns the number of attachments this message contains.

See Also

CSMTPMessage::AddAttachment

CSMTPMessage::m_From

Remarks

This is the address of the person from which the message is being sent. You would normally set this value to your email address prior to sending a message.

See Also

CSMTPAddress

CSMTPMessage::m_sSubject

Remarks

The subject line of the message in the form of a CString. You would normally set this value to something meaningful prior to sending a message.

CSMTPMessage::AddBody

void AddBody(const CString& sBody);

Return Value

None.

Parameters

sBody A reference to the text to add to the body of the message.

Remarks

Internally this function will ensure that the contents of the string conforms to the standards required for an SMTP message. Prior to v1.12 a public member m_sBody was available. Client applications now should call AddBody instead. This ensures that the internal function FixSingleDot is only called once even if the same message is sent a number of times.

See Also

CSMTPMessage::AddAttachment

CSMTPMessage::AddMultipleRecipients

BOOL AddMultipleRecipients(const CString& sRecipients);

Return Value

TRUE if the string was successfully parsed for recipients otherwise FALSE.

.Parameters

sRecipients A string containing a number of recipient addresses.

Remarks

This function allows the class to add a number of recipients quickly without having to create a single CSMTPAddress for each recipient. The delimters allowed in the string are ";" and "," and friendly names can be specified with "<", ">" delimiters. An example of a valid string is:

face="Times New Roman">"PJ Naughter <pjn@indigo.ie> , My Boss <someboss@company.com> ; Joe <joe@ms.com>"

See Also

CSMTPMessage::AddRecipient

CSMTPMessage::m_sXMailer

Remarks

The X-Mailer field which will be included in the email address. By default it is set to _T("CSMTPConnection v1.21"). You are free to change this prior to sending an email message from your application.

CSMTPMessage::m_ReplyTo

Remarks

This is the address of the person to which any replies to this message should be sent. This is an optional field which is normally not required to be present as you would normally want replies to your messages to be sent directly back to the sender of the message. By default this field is not sent with a SMTP message is sent.

See Also

CSMTPAddress

CSMTPConnection::Connect

BOOL Connect(LPCTSTR pszHostName, int nPort = 25);

Return Value

If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call ::GetLastError.

Parameters

pszHostName The network address of the socket to connect to: a machine name such as "mail.yourisp.com", or a dotted number such as "128.56.22.8".

nPort This is the port number on which to connect. The default value is 25 which is the default SMTP port number.

Remarks

Call this member function to establish a connection to a SMTP mail server.

See Also

CSMTPConnection::Disconnect

CSMTPConnection::Disconnect

BOOL Disconnect();

Return Value

If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call ::GetLastError.

Parameters

None.

Remarks

The corollary function of Connect.

See Also

CSMTPConnection::Connect

CSMTPConnection::GetLastCommandResponse

CString GetLastCommandResponse() const;

Return Value

The last command response from the server as a CString.

Parameters

None.

Remarks

The CSMTPConnection class can return additional text information along with most errors. This extended error information can be retrieved by using the GetLastCommandResponse function after an unsuccessful function call. GetLastCommandResponse can be called multiple times until another CSMTPConnection function is called which sends an SMTP command.

See Also

CSMTPConnection::GetLastCommandResponseCode

CSMTPConnection::GetLastCommandResponseCode

int GetLastCommandResponseCode() const;

Return Value

The last command response from the server as a CString.

Parameters

None.

Remarks

The CSMTPConnection class can return additional text information along with most errors. This extended error information can be retrieved by using the GetLastCommandResponse function after an unsuccessful function call. Embedded within each SMTP response is a 3 digit error code. The GetLastCommandResponseCode retrieves this value.

See Also

CSMTPConnection::GetLastCommandResponse

CSMTPConnection::GetTimeout

DWORD GetTimeout() const;

Return Value

The timeout in milliseconds which the code will wait for responses from the SMTP server.

Parameters

None.

Remarks

Since CSMTPConnection provides a synchronous API, a timeout mechanism is provided. By default the value is 2 seconds in release mode and 20 seconds in debug mode. The value is larger in debug mode so that the code does not time out when you are debugging it.

See Also

CSMTPConnection::SetTimeout

CSMTPConnection::SetTimeout

void SetTimeout(DWORD dwTimeout) const;

Return Value

None.

Parameters

dwTimeout The new timeout value in milliseconds.

Remarks

Sets the timeout to use for connections to the SMTP server.

See Also

CSMTPConnection::GetTimeout

CSMTPConnection::SendMessage

BOOL SendMessage(const CSMTPMessage& Message) const;

Return Value

If the function succeeds, the return value is TRUE. If the function fails, the return value is FALSE. To get extended error information, call ::GetLastError.

Parameters

Message A const reference to the message to send.

Remarks

Sends the specified message using the server which it is currently connected to.

See Also

CSMTPMessage

Planned Enhancements

  • Package the code up into an OCX, COM Interface or DLL to allow non MFC apps to use the code.
  • Provide a better sample app. At the moment, it's very much a test program which tests all of the functions.
  • If you have any other suggested improvements, please let me know so that I can incorporate them into the next release.

Contacting the Author

Please send any comments or bug reports to me via email. For any updates to this article, check my site here.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralThank you for this. Pin
Joan M25-Apr-12 8:23
professionalJoan M25-Apr-12 8:23 
QuestionError 300 - CSMTP_COMMAND_MAIL_FROM Pin
AlexEvans18-Jun-11 12:19
AlexEvans18-Jun-11 12:19 
QuestionIs there any way to set sender-IP manually in smtp? Pin
Member 18940854-Apr-11 2:21
Member 18940854-Apr-11 2:21 
QuestionHELP: Can it attach more than 1 attachment? Pin
Curious 200913-Dec-10 7:40
Curious 200913-Dec-10 7:40 
AnswerRe: HELP: Can it attach more than 1 attachment? Pin
MarcoLaws28-Sep-16 21:58
MarcoLaws28-Sep-16 21:58 
AnswerError : "550 must be authenticated" Pin
josthubert30-Jan-10 4:36
josthubert30-Jan-10 4:36 
GeneralRe: Error : "550 must be authenticated" Pin
Anders Gustafsson22-Apr-10 3:20
Anders Gustafsson22-Apr-10 3:20 
GeneralATL server has also a CSMTPConnection [modified] Pin
Gast12813-Sep-09 2:55
Gast12813-Sep-09 2:55 
QuestionJust why AFX & ATL ? Pin
Ahmed Han8-Jun-09 11:23
Ahmed Han8-Jun-09 11:23 
AnswerRe: Just why AFX & ATL ? Pin
pjnaughter14-Oct-09 13:51
pjnaughter14-Oct-09 13:51 
Generallicense restrictions Pin
clintM23-Apr-09 2:50
clintM23-Apr-09 2:50 
AnswerRe: license restrictions Pin
pjnaughter14-Oct-09 13:49
pjnaughter14-Oct-09 13:49 
GeneralCPJNSMTPConnection v2.82 error Cannot open include file: 'SocMFC.h': No such file or directory Pin
jogarcia31-Jan-09 12:43
jogarcia31-Jan-09 12:43 
AnswerRe: CPJNSMTPConnection v2.82 error Cannot open include file: 'SocMFC.h': No such file or directory Pin
pjnaughter14-Oct-09 13:48
pjnaughter14-Oct-09 13:48 
GeneralCSMTPConnection - &gt; An unexpected RCPT response was received Pin
AlexEvans30-Dec-08 18:05
AlexEvans30-Dec-08 18:05 
GeneralDate localization Pin
andy125-May-07 11:50
andy125-May-07 11:50 
AnswerRe: Date localization Pin
pjnaughter18-Nov-07 13:28
pjnaughter18-Nov-07 13:28 
Generalhttp://naughter.spaces.live.com/blog/ Pin
MewMew200028-Apr-07 19:54
MewMew200028-Apr-07 19:54 
GeneralPassword Pin
Freudi_t21-Mar-07 5:59
Freudi_t21-Mar-07 5:59 
AnswerRe: Password Pin
pjnaughter8-May-07 11:13
pjnaughter8-May-07 11:13 
GeneralFormat the email body Pin
cmaxzh6-Mar-07 8:09
cmaxzh6-Mar-07 8:09 
GeneralRe: Format the email body Pin
pjnaughter8-May-07 11:16
pjnaughter8-May-07 11:16 
QuestionIf you don't know a mail server name for a mail address? Pin
TongGao Tang4-Mar-07 10:07
TongGao Tang4-Mar-07 10:07 
AnswerRe: If you don't know a mail server name for a mail address? Pin
pjnaughter8-May-07 11:17
pjnaughter8-May-07 11:17 
GeneralDoing this in C# is much cleaner.... Pin
Christopher Stratmann18-Dec-06 7:25
Christopher Stratmann18-Dec-06 7:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.