5,660,782 members and growing! (15,147 online)
Email Password   helpLost your password?
Languages » C++ / CLI » Applications     Intermediate License: The Code Project Open License (CPOL)

SMTP client

By Jakub Piwowarczyk

The CSmtp class allows to send emails with attachments. It provides only AUTH LOGIN authentication.
C++ (VC6, C++), C++/CLI, C, Windows, Win32, Visual Studio (Visual Studio, VS6)

Posted: 24 Aug 2008
Updated: 24 Aug 2008
Views: 5,278
Bookmarked: 22 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
4 votes for this Article.
Popularity: 2.14 Rating: 3.56 out of 5
0 votes, 0.0%
1
1 vote, 25.0%
2
0 votes, 0.0%
3
3 votes, 75.0%
4
0 votes, 0.0%
5
Note: This is an unedited contribution. If this article is inappropriate, needs attention or copies someone else's work without reference then please Report This Article

Introduction

The CSmtp class allows to send emails from your program. The inspiration to write the CSmtp class was the article [1]. I have used the code of CFastSmtp and introduced the following changes:

  • some bags have been removed (i.e. free memory),
  • logining with authentication have been applied (AUTH LOGIN),
  • sending attachments have been added,
  • errors handling have been modified,
  • new headlines from MIME specifications (i.e. X-Priority) have been added.

Typical scenarios while sending the email

After successfull connection to the SMTP server, our client starts the conversation between the remote SMTP server. Each line send by the client ought to be finished by "\r\n". If you want to know more details, check [2], [3], [4], [5], [6], [7], [8] and [9]. In [2] was described original SMTP protocol (1982),in [4] were discussed SMTP extensions for authentication and MIME specification was improved in [5]-[9]. Example 3 failed becouse no TLS procedures were implemented in the CSmtp class. If you want to add TLS see OpenSSL. I have introduced the following notation: S - is a remote server, C - is our client, xxx - means information censured.

Example 1 - Connecting to smtp.wp.pl and using incorrect login or password

S: 220 smtp.wp.pl ESMTP
C: EHLO: mydomain.com
S: 250-smtp.wp.pl
   250-PIPELINING
   250-AUTH=LOGIN PLAIN
   250-AUTH LOGIN PLAIN
   250-STARTTLS
   250-SIZE
   250-X-RCPTLIMIT 100
   250-8BITMIME
C: AUTH LOGIN
S: 334 VXNlcm5hbWU6
C: Kioq
S: 334 UGFzc3dvcmQ6
C: Kioq
S: 535 blad autoryzacji, niepoprawny login lub haslo / auth failure

Example 2 - Connecting to smtp.wp.pl and using correct login and password

S: 220 smtp.wp.pl ESMTP
C: EHLO: mydomain.com
S: 250-smtp.wp.pl
   250-PIPELINING
   250-AUTH=LOGIN PLAIN
   250-AUTH LOGIN PLAIN
   250-STARTTLS
   250-SIZE
   250-X-RCPTLIMIT 100
   250-8BITMIME
C: AUTH LOGIN
S: 334 VXNlcm5hbWU6
C: xxx
S: 334 UGFzc3dvcmQ6
C: xxx
S: 235 go ahead
C: MAIL FROM:<me@mydomain.com>
S: 250 ok
C: RCPR TO:<friend@domain.com>
S: 250 ok
C: DATA
S: 234 go ahead
C: Date: Sun, 24 Aug 2008 22:43:45
   From: JP<mail@domain.com>
   X-Mailer: The Bat! (v3.02) Professional
   Replay-to:mail@domain.com
   X-Priority: 3 (Normal)
   To:<friend@domain.com>
   Subject: The message
   MIME Version 1.0
   Content-Type: multipart/mixed; boundary="__MESSAGE__ID__54yg6f6h6y456345"
   
   --__MESSAGE__ID__54yg6f6h6y456345
   Content-type: text/plain; charset=US-ASCII
   Content-Transfer-Encoding: 7bit

   This is my message.

   --__MESSAGE__ID__54yg6f6h6y456345
   Content-Type: application/x-msdownload; name="test.exe"
   Content-Transfer-Encoding: base64
   Content-Disposition: attachment; filename="test.exe"
   
   TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
   (...)
   SU5HWFhQQURESU5HUEFERElOR1hYUEFERElOR1BBRERJTkdYWFBBRERJTkdQQURESU5HWA==
   --__MESSAGE__ID__54yg6f6h6y456345
   Content-Type: application/x-msdownload; name="test2.jpg"
   Content-Transfer-Encoding: base64
   Content-Disposition: attachment; filename="test2.jpg"
   
   /9j/4Sv+RXhpZgAASUkqAAgAAAAJAA8BAgAGAAAAegAAABABAgAWAAAAgAAAABIBAwABAAAA
   (...)
   A6YxR5YJJ5zUu6ZW4+NjC24E4q5Dcox5I+lRI0iWAAV9aay+lTctoYTjrml+9irRmz//2Q==
   
   --__MESSAGE__ID__54yg6f6h6y456345--
   
   .
   
S: 250 ok xxx qp xxx
C: QUIT
S: 221 smtp.wp.pl   

Example 3 - Connecting to smtp.gmail.com

S: 220 mx.google.com ESMTP
   w28sm1561195uge.4
C: EHLO: mydomain.com
S: 250-mx.google.com at your service [xxx.xxx.xxx.xxx],
   250-SIZE 28311552
   250-8BITMIME
   250-STARTTLS
   250 ENHANCEDSTATUSCODES
C: AUTH LOGIN
S: 530 5.7.0 Must issue a STARTTLS command first. w28sm1561195uge.4

Example 4 - Connecting to smtp.bizmail.yahoo.com and using incorrect login or password

S: 220 smtp103.biz.mail.re2.yahoo.com ESMTP
C: EHLO: mydomain.com
S: 250-smtp103.biz.mail.re2.yahoo.com
   250-AUTH LOGIN PLAIN XYMCOOKIE
   250-PIPELINING
   250-8BITMIME
C: AUTH LOGIN
S: 334 VXNlcm5hbWU6
C: dG9t
S: 334 UGFzc3dvcmQ6
C: bmVyb24xMg==
S: 535 authorization failed (#5.7.0)

Implementation of the CSmtp class

  1. Initialise winsock2 (function: WSAStartup)
  2. Connect to the remote server (functions: gethostbyname, gethostbyaddr, socket, htons, getservbyname)
  3. Introduce yourself - EHLO <SP> <domain> <CRLF>
  4. Send AUTH LOGIN <CRLF> and another commands described in "Typical scenarios while sending the email" (functions: send, recv)
  5. Finish conversation with QUIT <CRLF>
  6. Free winsock2 resources (function: WSACleanup)

Usage

#include "CSmtp.h"
#include <conio.h>

int main()
{
    CSmtp mail;

    if(mail.GetLastError() != CSMTP_NO_ERROR)
    {
        printf("Unable to initialise winsock2.\n");
        return -1;
    }

    mail.SetLogin("***");
    mail.SetPassword("***");
    mail.SetSenderName("JP");
    mail.SetSenderMail("mail@domain.com");
    mail.SetReplyTo("mail@domain.com");
    mail.SetSubject("The message");
    mail.AddRecipient("friend@domain.com");
    mail.SetXPriority(XPRIORITY_NORMAL);
    mail.SetXMailer("The Bat! (v3.02) Professional");
    mail.SetMessageBody("This is my message.");
    mail.AddAttachment("c:\\test.exe");
    mail.AddAttachment("c:\\test2.jpg");

    if( !mail.ConnectServer("smtp.wp.pl",25) ) 
    {
        printf("Unable to connect to the server.\n");
        return -1;
    }
    
    if( mail.Send() )
        printf("The mail was send successfully.\n");
    else
        printf("Unable to send the mail.\n");

    mail.Disconnect();
    return 0;
}

Author's notices

  1. If you will have problems to send the email use the Visual Studio's debuger and analyse the conversation between your SMTP server, perhaps your server needs differend kind of the authentication or doesn't need it at all.
  2. You are not allowed to use CSmtp class to produce the spam.

Bibliography

  1. CFastSmtp - Fast and easy SMTP class...
  2. SIMPLE MAIL TRANSFER PROTOCOL RFC 821
  3. STANDARD FOR THE FORMAT OF ARPA INTERNET TEXT MESSAGES RFC 822
  4. SMTP Service Extension for Authentication RFC 2554
  5. MIME: Format of Internet Message Bodies RFC 2045
  6. MIME: Media Types RFC 2046
  7. MIME: Message Header Extensions for Non-ASCII Text RFC 2047
  8. MIME: Registration Procedures RFC 2048
  9. MIME: Conformance Criteria and Examples RFC 2049

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jakub Piwowarczyk



Occupation: Engineer
Company: Technical University of Lodz
Location: Poland Poland

Other popular C++ / CLI articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 16 of 16 (Total in Forum: 16) (Refresh)FirstPrevNext
GeneralSome remarksmemberMember 46086130:43 12 Nov '08  
GeneralRe: Some remarksmemberJakub Piwowarczyk12:34 15 Nov '08  
GeneralRe: Some remarksmemberMember 46086131:48 17 Nov '08  
GeneralInvalid Date: header (not RFC 2822)membertamoxifeno5:02 5 Nov '08  
GeneralRe: Invalid Date: header (not RFC 2822)memberJakub Piwowarczyk12:27 15 Nov '08  
GeneralCan use with MFC?membermc823:02 25 Oct '08  
GeneralRe: Can use with MFC?memberJakub Piwowarczyk4:08 26 Oct '08  
GeneralRe: Can use with MFC?membermc816:43 26 Oct '08  
GeneralUnnessessary boundary markers when no attachments sentmemberGeoffrey Armstrong1:43 31 Aug '08  
GeneralRe: Unnessessary boundary markers when no attachments sentmemberJakub Piwowarczyk4:34 31 Aug '08  
GeneralAny idea, for other language implementationmemberashu fouzdar21:33 26 Aug '08  
GeneralRe: Any idea, for other language implementationmemberJakub Piwowarczyk1:13 27 Aug '08  
GeneralRe: Any idea, for other language implementationmemberashu fouzdar1:15 27 Aug '08  
Generalwhere is the source code ?membergndnet0:40 25 Aug '08  
GeneralRe: where is the source code ?memberJakub Piwowarczyk0:54 25 Aug '08  
GeneralRe: where is the source code ?membergndnet1:09 25 Aug '08  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 24 Aug 2008
Editor: Chris Maunder
Copyright 2008 by Jakub Piwowarczyk
Everything else Copyright © CodeProject, 1999-2008
Web09 | Advertise on the Code Project