ATL SMTP Classes


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

Environment: Visual C++ 6.0, ATL 3.0, runs in Win9X/NT/2K


This is yet another set of lightweight, yet full-featured non-MFC SMTP classes to enable C++ programs to send outgoing mail.


  • Optional SMTP authentication (username/password)
  • Supports multiple recipients using CC and BCC fields
  • Supports multipart mixed, related and alternative MIME types
  • Supports any number of file attachments and alternative message bodies
  • Transfer-encoding using 7bit, 8bit, quoted-printable and base64.
  • Can optionally determine the transfer encoding based on content.
  • Looks up content-type from the registry. When not found, it uses application/octet-stream type.
  • CSmtp is overridable and has several event mechanisms to notify the parent of progress during transactions with the server.
  • UNICODE supported.

The source code is heavily documented, so I will concentrate on the basics of implementing SMTP support in your applications.


Setup is pretty straightforward.  Just insert the smtp.cpp, base64.cpp, smtp.h and base64.h files into a new ATL project or into your existing ATL project. A very simplistic .cpp file to implement SMTP would look like this:
#include "stdafx.h"
#include "resource.h"
#include "smtp.h"

// ... preamble excluded for clarity
extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, 
                                HINSTANCE /* hPrevInstance */, 
                                LPTSTR lpCmdLine, 
                                int /* nShowCmd */)
 CSmtp mail;
 CSmtpMessage msg;
 CSmtpAddress cc;
 CSmtpMessageBody body;
 CSmtpAttachment attach;

 // Initialize winsock  

 msg.Subject = _T("Testing");

 // Who the message is from
 msg.Sender.Name = _T("My Username");
 msg.Sender.Address = _T("myaddress@myemail.com");

 // Primary recipient
 msg.Recipient.Name = _T("Someone Else");
 msg.Recipient.Address = _T("someoneelse@somewhereelse.com");

 // Uncomment these lines to add a CC address
 //  cc.Name = _T("A CCd User");
 //  cc.Address = _T("ccuser@ccdaddress.com");
 //  msg.CC.Add(cc);

 // Uncomment these lines to add a BCC address
 //  cc.Name = _T("Yet Another CC");
 //  cc.Address = _T("YACC@somewhere.com");
 //  msg.BCC.Add(cc);

 // Assign a value to the message body
 body = _T("This is a test of the CSmtp class and its support classes, \
 CSmtpAddress, CSmtpMessage and CSmtpMessageBody.  The textual portion \
 of this message should be encoded in the \"quoted-printable\" transport \
 encoding scheme, because the lines in the message are more than 76 \
 characters long.\r\n\r\nThe CSmtpMessage class makes a best-guess \
 effort to determine the proper transport encoding to use to ensure the \
 data comes across in the format originally intended.\r\n");

 // Add the message body to the message

 // Here is an example of an alternate message body
 //  body = _T("<html><body>Hello World...</body></html>");
 //  body.Encoding = _T("text/html");
 //  msg.Message.Add(body);

 // Here are some samples of adding attachments to the message
 //  attach = _T("d:\\temp\\ntregmon.zip");
 //  msg.Attachments.Add(attach);
 //  attach = _T("d:\\src\\smtpapp\\readme.html");
 //  msg.Attachments.Add(attach);

 // Assign these values only if your SMTP server requires authentication
 mail.m_strUser = _T("myusername");
 mail.m_strPass = _T("mypassword");

 // Attempt to connect to the mailserver
 if (mail.Connect(_T("mail.mymailserver.com")))
  // Send the message and close the connection afterwards
  // Alternate one-shot method of sending a message
  // mail.SendMessage(_T("foo@bar.com"),
                      _T("My Subject"),
                      _T("This is the msg body"));

 return 0;

For added control, you can easily implement a class which inherits from the CSmtp class.  By providing your own implementation of SmtpWarning, SmtpError, SmtpCommandResponse and SmtpProgress, you can provide users with some visual indication of what is happening.  Furthermore, the SmtpWarning event is raised when authentication fails, either when the connection is first established, or in response to an outgoing mail request being made.  By overriding this event, you can provide users with a way of supplying credentials to be resumbitted to the SMTP server.

The CSmtpMessage class also supports the multipart/related MIME type, which is used most commonly to embed images and other items into an html message.  Here's an example of how to embed an image into a mail message using multipart/related:

CSmtpMessage msg;
CSmtpMessageBody body;
CSmtpAttachment  attach;

// The MimeType must be explicitly set for this type of message
msg.MimeType = mimeRelated;

body = _T("<html><body>This is an inline image<br> \
<img src="cid:1234567"></body></html>");

body.Encoding = _T("text/html");

attach = _T("c:\\web\\myimage.jpg");
attach.ContentId = _T("1234567");


I'm not sure about compatibility, but you can also reference the attachment by name, in which case, the code would be even simpler:

msg.MimeType = mimeRelated;

body = _T("<html><body>This is an inline image<br> \
<img src="myimage.jpg"></body></html>");

body.Encoding = _T("text/html");

attach = _T("c:\\web\\myimage.jpg");


I tested this on Outlook 2000 and it worked fine.  I'd be curious to note if this works for other e-mail applications.

Version History

  • Version 1.7 - 06/18/2001
    • Modified the code that gets the GMT offset and the code that parses the date/time as per Noa Karsten's suggestions.
    • Added an FD_ZERO(&set) to the last part of SendCmd(), since I use the set twice and only zero it out once. Submitted by Marc Allen.
    • Removed the requirement that a message have a body and/or an attachment in order to send it. This allows you to send a message containing only a header. Submitted by Marc Allen.
  • Version 1.6 - 04/04/2001
    • Apparently older versions of the STL do not have the clear() method for basic_string's. I modified the code to use erase() instead.
    • Added #include <atlbase.h> to the smtp.h file, which will allow any app (even non-ATL apps) to use these classes without problems.
  • Version 1.5 - 03/30/2001
    • Guess I should have checked EncodeQuotedPrintable() as well, since it did the same thing BreakMessage() did in adding an extranneous CRLF to the end of any text it processed. Fixed.
  • Version 1.4 - 03/12/2001
    • BreakMesage() added an extranneous CRLF to the end of any text it processed, which is now fixed. Certainly not a big deal, but it caused text attachments to not be 100% identical to the original.
  • Version 1.3 - 03/11/2001
    • Added a new class, CSmtpMimePart, to which the CSmtpAttachment and CSmtpMessageBody classes now inherit. This was done for future expansion. CSmtpMimePart has a new ContentId string value for optionally assigning a unique content ID value to body parts and attachments. This was done to support the multipart/related enhancement.
    • Added a MessageId member to the CSmtpMessage class to allow users to optionally specify a message ID.
    • Added a boolean Inline member variable to CSmtpAttachment to allow users to specify that the content-disposition is Inline rather than Attachment.
    • Support for multipart/related messages, which can be used for sending html messages with embedded images.
    • Modifed CSmtpMessage, adding a new MimeType member variable so the user can specify a certain type of MIME format to use when coding the message.
    • Fixed a bug where multipart/alternative messages with multiple message bodies were not properly processed when attachments were also included in the message.
    • Some small optimizations during the CSmtpMessage::Parse routine
  • Version 1.2 - 03/10/2001
    • Vastly improved the time it takes to break a message, which was dog slow with large attachments. My bad.
    • Added another overridable, SmtpProgress() which is called during the CSmtp::SendCmd() function when there is a large quantity of data being sent over the wire.
    • Added CMD_BLOCK_SIZE to support the above new feature
    • Added support for UNICODE builds
    • Added the CSmtpAttachment class for better control and expandability for attachments.
    • Added alternative implementations for CSmtp::SendMessage which make it easier to send simple messages via a single function call.
    • Added a constructor to CSmtpAddress for assigning default values during initialization.
    • Added a #pragma comment(lib,"wsock32.lib") to the smtp.h so you don't have to modify your project's linker options


Download the source code - 16 Kb


  • Mr

    Posted by Andy Watt on 10/13/2014 05:44pm

    I've used this class in a small project which needed to send notifications - after extending it slightly so it can change message priorities, it's perfect! Nice work, it's so fully featured it'll cope with what the application will need to do in future. BTW, it's compiling and running under VS2013 without any issues (legacy MFC project).

  • Fix for filename truncation and other attachment problems

    Posted by ogomi on 03/28/2008 11:23pm

    I discovered a bug in the code where it is not closing the file name with a trailing double quote. This causes some SMTP servers to truncate the attachment file name (and probably some other undesireable side-effects). The fix is to add the 3rd line below (after line 497 of the smtp.cpp file):
    strDest += _T(";\r\n\tfilename=\"");
    strDest += pszFile;
    strDest += _T("\"");
    Hope this helps. O

  • please send me smtpsimpson.zip! thanks so much !

    Posted by nghiaduong_09 on 12/15/2005 07:08am

    Dear All ! I can't get smtpsimpson.zip file in CodeGuru page! Please send it to me! nghiaduong_09@yahoo.com Thank you very much ! Best Regards NghiaDuong

  • please send me smtpsimpson.zip! thanks so much !

    Posted by nghiaduong_09 on 12/15/2005 07:07am

    Dear All

  • Thanks a lot Robert

    Posted by Legacy on 12/17/2003 08:00am

    Originally posted by: Dinesh Sharma

    Thank you very much Robert
    I have added few of my own changes to CSMTPmessagBody
    Basically I have oveloaded + , += operators for this class So that you can do concatenation for the message text

  • still doesnot work with attachment file in yahoo and hotmail

    Posted by Legacy on 12/05/2003 08:00am

    Originally posted by: user

    I sent a mail with an attachment to yahoo email account.
    it sent ok but the name of the attached file changed to
    UNKNOWN_PARAMETER_VALUE and the content is corruptted...

    Do u have any ideas ?

    • Missing closing quote in attachment filenames

      Posted by ogomi on 03/28/2008 11:17pm

      I discovered a bug in the code where it is not closing the file name with a trailing double quote. This causes some SMTP servers to truncate the attachment file name (and probably some other undesireable side-effects). The fix is to add the 3rd line below (after line 497 of the smtp.cpp file): strDest += _T(";\r\n\tfilename=\""); strDest += pszFile; strDest += _T("\""); Hope this helps. O

  • can we send mail without a SMTP server?

    Posted by Legacy on 12/03/2003 08:00am

    Originally posted by: kenny

    Is there any public use SMTP server that we can use ?

    Is this possible to send mail without a SMTP server ?

    Thanks....your code is great.

  • Good!!

    Posted by Legacy on 10/11/2003 07:00am

    Originally posted by: Albert

    Thank you very much..

  • Socket Error !!

    Posted by Legacy on 09/25/2003 07:00am

    Originally posted by: Marc


    the first email sending works OK !

    If I then try a sending with a wrong password,
    the sending fails! OK !

    And now I try with the correct password again, but
    I can't get a correct sending!

    Stopping and restarting the program doesn't helps.

    The connect() function always brings a SOCKET_ERROR.

    Do you have an idea?

    Marc Schneider

  • Thank you very much

    Posted by Legacy on 09/04/2003 07:00am

    Originally posted by: Stuart Ledwich

    This is a wonderful easy to use and well structured piece of code. I have managed to slot it into my service application very easily. Thank you again.

  • Loading, Please Wait ...

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date