This tutorial introduces how to send email in Visual C++ using SMTP. It also demonstrates SSL, S/MIME, Embedded Images, Email Queue and Multiple Threads usage.
Sections:
To better demonstrate how to send email using SMTP protocol, let’s create a Visual C++ Win32 console project at first.
EASendMail is a SMTP component which supports all operations of SMTP/ESMTP protocols (RFC 821, RFC 822, RFC 2554). Before you can use the following example codes, you should download the EASendMail Installer and install it on your machine at first.
To use EASendMail SMTP ActiveX Object in your C++ project, the first step is “Add
header files of EASendMail to your project”. Please go to C:\Program Files\EASendMail\Include\tlh
or C:\Program Files (x86)\EASendMail\Include\tlh
folder,
find easendmailobj.tlh
and easendmailobj.tli
, and then copy these
files to your project folder.
Now add the following codes to the project and change From
, To
, Server
, User
and
Password
to corresponding value.
#include "stdafx.h"
#include <tchar.h>
#include <Windows.h>
#include "EASendMailObj.tlh"
using namespace EASendMailObjLib;
const int ConnectNormal = 0;
const int ConnectSSLAuto = 1;
const int ConnectSTARTTLS = 2;
const int ConnectDirectSSL = 3;
const int ConnectTryTLS = 4;
int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
IMailPtr oSmtp = NULL;
oSmtp.CreateInstance(__uuidof(EASendMailObjLib::Mail));
oSmtp->LicenseCode = _T("TryIt");
// Set your sender email address
oSmtp->FromAddr = _T("test@emailarchitect.net");
// Add recipient email address
oSmtp->AddRecipientEx(_T("support@emailarchitect.net"), 0);
// Set email subject
oSmtp->Subject = _T("simple email from Visual C++ project");
// Set email body
oSmtp->BodyText = _T("this is a test email sent from Visual C++ project, do not reply");
// Your SMTP server address
oSmtp->ServerAddr = _T("smtp.emailarchitect.net");
// User and password for ESMTP authentication, if your server doesn't
// require User authentication, please remove the following codes.
oSmtp->UserName = _T("test@emailarchitect.net");
oSmtp->Password = _T("testpassword");
// Most mordern SMTP servers require SSL/TLS connection now.
// ConnectTryTLS means if server supports SSL/TLS, SSL/TLS will be used automatically.
oSmtp->ConnectType = ConnectTryTLS;
// If your SMTP server uses 587 port
// oSmtp->ServerPort = 587;
// If your SMTP server requires SSL/TLS connection on 25/587/465 port
// oSmtp->ServerPort = 25; // 25 or 587 or 465
// oSmtp->ConnectType = ConnectSSLAuto;
_tprintf(_T("Start to send email ...\r\n"));
if(oSmtp->SendMail() == 0)
{
_tprintf(_T("email was sent successfully!\r\n"));
}
else
{
_tprintf(_T("failed to send email with the following error: %s\r\n"),
(const TCHAR*)oSmtp->GetLastErrDescription());
}
return 0;
}
If you set everything right, you can get “email was sent successfully”. If you get “failed to send email with the following error:”, then please have a look at the following section.
When you execute above example code, if it returned an error about “Networking connection/Socket” or “No such host”, it is likely that your SMTP server address is not correct. If it threw an exception about “5xx Relay denied”, it is likely that you did not set user authentication. Another common error is “5xx Must issue a STARTTLS command first” or “No supported authentication marshal found!”, that is because your SMTP server requires user authentication under SSL connection. You can set the SSL connection to solve this problem. You can learn more detail in Troubleshooting section.
TLS is the successor of SSL, more and more SMTP servers require TLS 1.2 encryption now.
If your operating system is Windows XP/Vista/Windows 7/Windows 2003/2008/2008 R2/2012/2012 R2
,
and you got connection error with SSL/TLS connection,
you need to enable TLS 1.2 protocol in your operating system like this:
Enable TLS 1.2 on Windows XP/Vista/7/10/Windows 2008/2008 R2/2012
Because each email account provider has different server address, so you should query your SMTP server address from your email account provider. To prevent spreading email from the server, most SMTP servers also require user authentication. User name is your email address or your email address without domain part, it depends on your email provider setting.
Finally, if you have already set your account in your email client such as Outlook or Window Mail, you can query your SMTP server address, user in your email client. For example, you can choose menu -> “Tools” - > - “Accounts” - > “Your email account” - > “Properties” - > “Servers” in Outlook express or Windows Mail to get your SMTP server, user. Using EASendMail to send email does not require you have email client installed on your machine or MAPI, however you can query your exist email accounts in your email client.
// For single email address (From, ReplyTo, ReturnPath), the syntax can be:
// ["][display name]["]<email address>.
// For example:
"Tester, T" <test@adminsystem.com>
Tester <test@adminsystem.com>
<test@adminsystem.com>
test@adminsystem.com
// For mulitple email address (To, CC, Bcc), the syntax can be:
// [single email],[single email]...
// (,;\r\n) can be used to separate multiple email addresses.
// For example:
"Tester, T" <test1@adminsystem.com>, Tester2 <test2@adminsystem.com>,
<test3@adminsystem.com>, test4@adminsystem.com
[Visual C++ Example - Email syntax]
To better understand the email address syntax, please refer to the following codes.
oSmtp->FromAddr = _T("Tester<test@adminsystem.com>");
oSmtp->FromAddr = _T("test@adminsystem.com");
oSmtp->FromAddr = _T("<test@adminsystem.com>");
// Using AddRecipientEx to add To, Cc and Bcc in Visual C++
// Multiple addresses are separated with (,)
// The syntax is like this: "test@adminsystem.com, test1@adminsystem.com"
oSmtp->AddRecipientEx(_T("test1@adminsystem.com, test2@adminsystem.com"), 0);
oSmtp->AddRecipientEx(_T("Test1<test@adminsystem.com>, Test2<test2@adminsystem.com>"), 0);
// You can also add carbon copy (CC) or blind carbon copy (BCC) in the email.
oSmtp->AddRecipientEx(_T("CC recipient<cc@adminsystem.com>"), 1);
oSmtp->AddRecipientEx(_T("Bcc recipient<bcc@adminsystem.com>"), 2);
If you want to set another email address to get the replied email rather than your From address, you can use ReplyTo property.
If you want to set another email address to get the delivery report rather than your From address, you can use ReturnPath property.
If you want to set Higher or Lower priority to your email, you can use Priority prority
[Visual C++ Example - ReplyTo, ReturnPath and Priority]
oSmtp->FromAddr = _T("Tester <test@emailarchitect.net>");
// Set the Reply-To address
oSmtp->ReplyTo = _T("replyto@@emailarchitect.net");
// Set the email address to receive delivery report
oSmtp->ReturnPath = _T("report@emailarchitect.net");
// Set high priority
oSmtp->Priority = 1
When you send email in above simple VC++ project, if it returned an error, please have a look at the following tips:
This error means DNS server cannot resolve SMTP server, you should check if you input correct server address. If your server address is correct, you should check if your DNS server setting is correct.
This error means there is a problem with networking connection to SMTP server. You can use Windows built-in Telnet command to detect the networking connection.
Note
Notice: in Windows 2008/Windows 8 or later version, Telnet Client
is not installed
by default, you should enable this command in Control Panel
-> Programs and
Features
-> Turn Windows feature on or off
-> have Telnet Client
checked.
Under DOS command prompt, input “telnet [serveraddress] [port]”:
telnet mail.emailarchitect.net 25
press enter.
If the networking connection to your SMTP server is good, it should return a message
like 220 ...
. If it returns Could not open connection to ...
, that means the
networking connection to SMTP server is bad, or outbound 25 port is blocked by anti-virus
software, firewall or ISP. Please have a look at the following screenshot:
25 port is the default SMTP server port to receive email. However, some ISP block outbound 25 port to prevent user to send email directly to other SMTP server. Therefore, many email providers also provide an alternative port 587 to receive email from such users. 465 port is the common port used to receive email over implicit SSL connection. If you use telnet to test 465 port, it doesn’t return the “220…”, because it requires SSL hand shake. But if the connection is ok, telnet returns a flash cursor.
This error means SMTP server blocks your IP address or email content. You can try to set user/password in your codes to do user authentication and try it again. If email client set user authentication, most SMTP servers do not check client source IP address in black list.
TThis error means user authentication is failed, you should check whether you input correct user/password. Password is always case-sensitive.
For anti-spam policy, most SMTP servers do not accept the email to outbound domain without user authentication. You should set user/password in the codes and try it again.
This error means SMTP server requires SSL/TLS connection. You should enable SSL/TLS connection like this:
// If your smtp server requires TLS connection, please add this line
oSmtp->ConnectType = 1;
This error means SMTP server doesn’t support user authentication or it requires user authentication over SSL/TLS connection. You can try to remove user/password in your codes and try it again.
If SMTP server returns an error, it usually returns description about this error. Some descriptions also include a HTTP link, you can go to this linked web page to learn more detail. You can also use the following codes to generate a log file to learn all SMTP session between client and server.
[VC++ - Using log file to detect SMTP server response - Example]
oSmtp->LogFileName = _T("d:\\smtp.txt");
If you sent email successfully without error, that means the email has been submitted to the SMTP server. The SMTP server will deliver the email in background, if the email couldn’t be delivered, a Failure Report (NDS) will be sent back to your sender email address.
To retrieve and parse Failure Report (NDS), you should monitor your sender mailbox. I recommend that you use EAGetMail to monitor your sender mailbox using POP3/IMAP4/Exchange WebDAV/Exchange Web Service protocol. After you installed EAGetMail on your machine, there are several full samples named “parse_report.*” for VB6, Delphi, Visual C++ in the installation path.
Email tracking is used to verify that emails are actually read by recipients. There are two common solutions: Read Receipt and Linked Image Tracking
To learn more detail about Process Bounced Email (Non-Delivery Report) and Email Tracking, please have a look at this topic: Process Bounced Email (Non-Delivery Report) and Email Tracking
If you are a mail listing provider and send bulk emails every day, of course you don’t want your emails are blocked or moved to Junk folder of the recipient mailbox.
To increase the inbox delivery rate of your messages, make sure that all recipients on your distribution lists actually want to receive the mail. Have a look the topic for some tips on how to make sure your messages are welcomed by most email providers:
Seperate builds of run-time dll for 32 and x64 platform
File | Platform |
Installation Path\Lib\native\x86\EASendMailObj.dll | 32 bit |
Installation Path\Lib\native\x64\EASendMailObj.dll | 64 bit |
Standard EXE
For VB6, C++, Delphi or other standard exe application, you can distribute EASendMailObj.dll with your application to target machine without COM-registration and installer. To learn more detail, please have a look at Registration-free COM with Manifest File.
Script
For ASP, VBScript, VBA, MS SQL Stored Procedure, you need to install EASendMail on target machine by EASendMail installer, both 32bit/x64 DLL are installed and registered.
Next Section
In this section, I introduced how to send email in a simple VC++ project using SMTP protocol. At next section I will introduce how to send email over SSL/TLS connection.
Appendix
Comments
If you have any comments or questions about above example codes, please click here to add your comments.