ATL SMTP Classes

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

Overview

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

Features

  • 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

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  
 WSADATA wsa;
 WSAStartup(MAKEWORD(2,0),&wsa);

 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
 msg.Message.Add(body);

 // 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
  mail.SendMessage(msg);
  
  // Alternate one-shot method of sending a message
  // mail.SendMessage(_T("foo@bar.com"),
                      _T("someone@else.com"),
                      _T("My Subject"),
                      _T("This is the msg body"));
  mail.Close();
 }

 WSACleanup();
 
 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");

msg.Message.Add(body);
msg.Attachments.Add(attach);

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");

msg.Message.Add(body);
msg.Attachments.Add(attach);

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

Downloads

Download the source code - 16 Kb


Comments

  • Old president denounce is general assist absurd opinion on public affairs0

    Posted by zwvldhrvwj on 05/17/2013 06:16pm

    Old president denounce is general assist absurd [url=http://jordanscheap.page4.me/]air jordans cheap[/url] opinion on public affairs On Feburary 3 morning, a running fire of course of study of Wu Cheng of president of university of former overseas Chinese 3 small gain, to cardinal principle assist the opinion on public affairs of the near future undertakes denounce one by one, appeal concerned branch to appear personally the settlement that promotes an issue, bo Wenyuan article is as follows: General assist in stating on Feburary 1, say some popularizes an enterprise to be illicit look forward to, discover this morning oneself delete, answer truly cutout, because this formulation takes discrimination sex and violate policy of central reforming and opening. Look from contemporary company system, only the state-owend enterprise is mixed civilian look forward to, and company of last name of ultimate decision company and endowment do not decide by system of ownership only, this is the economics common sense of an at least. Party card government office and mass organizations all need to work inside constitution frame. Statement told us on Feburary 1, a few comrades do not study the policy policy of the party for a long time, thought stale, style is tough, make can do good thing to do bad thing, hurt the heart of most masses, the career that gives a party causes a loss. Communicating is the main way that settles people interior to contradict, still look at cardinal principle assist attach most importance to with people interest, whether to support the jumping-off place that serves as the job with the undergraduate, clutch remedy the job, correct error, do not tough act, painful Chou Zhe of the person that make kiss is fast. Appeal sincerely. CUBA changes a controversy the impact is very big, oneself cause bad effect to party and governmental figure, and also not be the problem that incident both sides can solve by oneself. Ask body of Ministry of Education to defend department to fulfill duty to appear personally solve, teach minister and undersecretary of be assigned personal responsibility for to appear personally please drive solve. No time to lose in doing the job, 10 thousand hope to cause take seriously. My the words of the lowly person carry little weight, fraught, 10 thousand look 10 thousand hope authorities takes seriously, 10 thousand look 10 thousand hope authorities sees this letter.

    Reply
  • Fix for filename truncation and other attachment problems

    Posted by ogomi on 03/28/2008 04: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

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

    Posted by nghiaduong_09 on 12/14/2005 11:08pm

    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

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

    Posted by nghiaduong_09 on 12/14/2005 11:07pm

    Dear All

    Reply
  • Thanks a lot Robert

    Posted by Legacy on 12/17/2003 12: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

    Reply
  • still doesnot work with attachment file in yahoo and hotmail

    Posted by Legacy on 12/05/2003 12: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 04: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

      Reply
    Reply
  • can we send mail without a SMTP server?

    Posted by Legacy on 12/03/2003 12: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.

    Reply
  • Good!!

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

    Originally posted by: Albert

    Thank you very much..

    Reply
  • Socket Error !!

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

    Originally posted by: Marc

    Hi,

    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?

    Regards
    Marc Schneider

    Reply
  • Thank you very much

    Posted by Legacy on 09/04/2003 12: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.

    Reply
  • Loading, Please Wait ...

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

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • You probably have several goals for your patient portal of choice. Is "community" one of them? With a bevy of vendors offering portal solutions, it can be challenging for a hospital to know where to start. Fortunately, YourCareCommunity helps ease the decision-making process. Read this white paper to learn more. "3 Ways Clinicians can Leverage a Patient Portal to Craft a Healthcare Community" is a published document owned by www.medhost.com

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds