Home » Blog [programming]
date 25.Mar.2012

■ It can't be that hard sending an email from a program?


I didn't need to send emails programmatically until I developed crack tracker. I always had the impression that it wouldn't be that big a deal. Email is an ancient internet communication protocol, so surely there would be a simple windows API like SendThisEmailPlease(), right? Actually figuring out how to send emails consistently from windows is maddeningly complex — and that's just finding out what system component you need!

The first API you will encounter in google is MAPISendMail, which offers a basic functionality through the email client (MS Outlook, Thunderbird, LiveMail etc) installed on the computer running your program. Windows compatibility is excellent, working as far back as windows 95, but it isn't perfect. Depending on which email client furnishes the outgoing email, you may or may or may not be able to send attachments; sometimes it fails completely when the client is/isn't running in the background. Not very robust. Also it will not send UTF-8 encoded messages and cannot do silent delivery — you always see the Outlook etc email composition window before the email is sent.

Your quest for the elusive simple email API will then lead you to mailto protocol, which is just meant for lightweight use from websites, not from a C++ program. It won't do attachments in most cases, and it has all the other ailments of MAPISendMail. A clever trick to ensure email attachments is SendTo shell extension that appears when you right click on files in windows explorer. The menu command Mail recipient will attach any file and send it through your email client, but that's all the control you have: you can't choose a recipient address programmatically for instance.

Then there's extended MAPI. This gives you good control, only it doesn't work for every email client. What if your program is running on a PC where there's only Thunderbird installed? You cannot force your customers to buy MS Outlook or install windows live mail just so that you can send emails using extended MAPI. In the bin with this one too.

Send emails using a remote SMTP server

For real control over the email sending process you must go low level and use an outgoing SMTP server, just like those email client programs do it. This means that your user will have to setup the SMTP server to use your program, and you have the hassle of securely storing passwords, but that's what it takes for robust, fully featured email delivery. With low-level SMTP you will have all these features:

All this control doesn't come free though. You will suddenly realize the complexities of actually sending emails doing text conversations with the SMTP server, ensuring a secure encrypted SSL connection and everything else simple MAPI does automatically behind the scenes.

Back to google for some SMTP code samples... You will find a lot of C++ code, from simple classes without SSL to monstrous implementations larger than your whole source code and cross dependencies you'd rather do without. At this point, like me, you may be about to throw the towel and buy some SMTP component with royalty free distribution to include with your program (see the references below for some links), if you don't mind adding ~1MB extra to your distribution.

Deus ex machina: CDOSYS.DLL

In windows programming there always is some solution for any problem you may be having, albeit not easy to find. Surely all these years somebody has written code for secure SMTP emails? Yes, they have, it is a standard windows DLL component called CDOSYS.DLL (Collaboration Data Objects), and it's available from windows 2000 onwards (sorry no win98), in all windows installations, regardless of the email client, exchange server and what have you. It is primarily aimed for scripting languages but if you know your COM and have heard of IDispatch and dual interfaces you will be pleased to discover that microsoft put everything you may imagine in this SMTP library.

It can do the lot, HTML, attachments, unicode messages, supports secure SSL. As you will see from the online reference, you need two objects, CDO.Configuration to setup the server login details, and CDO.Message to compose and send each email. There are many code samples (mostly in kindergarden languages like VB and C# :) but you can easily turn them in C++ using the CDO header files <cdosys.h> and <cdosys_i.c> and remember that a CDO:: namespace is in effect.

If you use gmail as your SMTP server, remember to use port 465 and enable SSL using cdoSMTPUseSSL on the server configuration object. I don't think CDOSYS supports TLS encryption so port 587 is out, but usually all you need is port 25 for plain text and 465 for SSL encryption.

This wraps up my 2-year journey towards SMTP nirvana. I hope this condensed version helps someone among you!

References for further reading

Post a comment on this topic »

Share |

©2002-2012 ZABKAT, all rights reserved | Privacy policy | Sitemap