SMTP Tutorial

 

 

If this helps you and you are feeling generous . . .

 

The Simple Mail Transfer Protocol is a very simple protocol designed to transfer text based electronic messages. It is used with the TCP protocol. SMTP is a transmission and reception protocol and does not actually define the format or content of the transmitted message, except that the data has 7-bit ASCII characters and that extra log information is added to the start of the delivered message to indicate the path that the message took. Because SMTP mail can only transfer 7-bit ASCII characters, it can’t handle attachments. For that, you have to use the Multi-purpose Internet Mail Extension (MIME). MIME uses the same sending and receiving protocol but has a different header.

 

An SMTP sender initiates a TCP connection. When this is successful it sends a series of commands to the receiver, and the receiver returns a single reply for each command. All commands and responses are sent with ASCII characters and are terminated with the characters ‘\r’ and ‘\n’ (0x0D & 0x0A in hex).

 

 

SMTP Commands

 

Command

Description

HELO domain

Sends an identification of the domain

MAIL FROM: sender address

Sends identification of the sender

RCPT FROM: receiver address

Sends identification of the recipient

DATA

Transfer text message

RSEY

Abort current mail transfer

QUIT

Shut down TCP connection

EXPN mailing list

Send back membership of mailing list

SEND FROM: sender-address

Send mail message to the terminal

VRFY username

Verify user name (username)

 

 

 

 

SMTP Responses

 

CMD

Description

CMD

Description

211

System status

500

Command not recognised due to a syntax error

214

Help message

501

Invalid parameters or arguments

220

Service ready

502

Command not currently implemented

221

Service closing transmission complete

503

Bad sequence of commands

250

Requested mail action completed successfully

504

Command parameter not currently available

251

Addressed user does not exist on system but will forward to receiver address

550

Mail box unavailable, requested action not taken

354

Indicate to the sender that the mail message can be sent. The end of the message is identified with“\r\n.\r\n\r\n”

551

The addressed user in not local, please try receiver address

421

Service is not available

552

Exceeded storage allocation, requested mail action aborted

450

Mailbox unavailable and the requested action was not taken

553

Mailbox name not allowed, requested action not taken

451

Local processing error, requested action aborted

554

Transaction failed

452

Insufficient storage, requested action not taken

 

 

 

 

 

Here is an example of an email transaction.

 

 

 

 

*I’m not sure if it matters what you put here. For all my mail sending app’s I used my LAN hostname with no problems.

 However doesn’t seem to work for any of my friend’s computers (they have broad band, I have dialup and I’m behind a proxy)

 so if someone could clear me up on this I would appreciate it.

 

SMTP Header

 

The data in the email message contains two parts: an SMTP header, and the message. The header holds information about the email such as:

 

 

Any computer involved in the transmission of the message can add to the header. Usually the email reading program will separate the header from the rest of the message and only displays certain items. A header usually contains a keyword followed by a semicolon then a list of arguments.

 

Here is an example of a complete email message (the comment lines don’t exist in a real message):

 

 

From samuel@samuel.com Mon Jan 02 15:48:32 2006             //This is the address of the sender, accompanied by the time it was sent

 

Received: from samuel.com ([123.123.123.012]) by gmail.com <samuel.supercamel@gmail.com>; Mon Jan 02 15:49:13 2006          //This says that the message was received from samuel.com by gmail.com at this date

 

Message-Id: <124fsd324@samuel.com>                          //This is a unique message id and can usually be ignored if you are sending your own emails

 

Date: Mon Jan 02 15:48:32 2006                                    //This is the date of the original message

 

From: Samuel <samuel@samuel.com>                            //This is the alias and email address of the sender

 

To: Samuel <samuel.supercamel@gmail.com>                    //The alias and address of the recipient

 

Subject: hey!                                                     //The subject

 

Hey Samuel                                                  //The message

 

        Just a quick note to remind myself of my other email address which doesn’t exist (it’s just for demonstration purposes).

 

From Samuel

 

 

The Code (C++)

 

This is based on Johnnie’s Winsock tutorials code.

 

#include <windows.h>

#include <winsock.h>

#include <stdio.h>

 

#define NETWORK_ERROR -1

#define NETWORK_OK     0

 

void ReportError(int, const char *);

 

 

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {

      WORD sockVersion;

      WSADATA wsaData;

      int nret;

 

      sockVersion = MAKEWORD(1, 1);

 

      WSAStartup(sockVersion, &wsaData);

 

 

      LPHOSTENT hostEntry;

 

      hostEntry = gethostbyname("smtp.tpg.com.au");   // This is the host’s name

 

      if (!hostEntry) {

            MessageBox(NULL, "Error obtaining host", "SMTP", MB_OK);

 

            WSACleanup();

            return -1;

      }

 

      SOCKET theSocket;

 

      theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

 

      if (theSocket == INVALID_SOCKET) {

            MessageBox(NULL, "Invalid socket", "SMTP", MB_OK);

 

            WSACleanup();

            return -1;

      }

 

      SOCKADDR_IN serverInfo;

 

      serverInfo.sin_family = AF_INET;

 

      serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);

 

      serverInfo.sin_port = htons(25);

     

      nret = connect(theSocket,

                   (LPSOCKADDR)&serverInfo,

                   sizeof(struct sockaddr));

 

      if (nret == SOCKET_ERROR) {

            MessageBox(NULL, "Error connecting to server", "SMTP", MB_OK);

            WSACleanup();

            return NETWORK_ERROR;

      }

 

 

      // Successfully connected!

    char buffer[1024];

    recv(theSocket, buffer, 128, 0);

    MessageBox(NULL, buffer, "Test", MB_OK);

   

    ZeroMemory(buffer, 512);

    sprintf(buffer, "HELO samuel\r\n");                    //Use GetComputerName for this

    send(theSocket, buffer, strlen(buffer), 0);

    ZeroMemory(buffer, 512);

    recv(theSocket, buffer, 512, 0);

   

    MessageBox(NULL, buffer, "Test", MB_OK);

    ZeroMemory(buffer, 512);

    sprintf(buffer, "MAIL FROM: someone@hotmail.com\r\n");

    send(theSocket, buffer, strlen(buffer), 0);

    ZeroMemory(buffer, 512);

    recv(theSocket, buffer, 512, 0);

    MessageBox(NULL, buffer, "Test", MB_OK);

   

    ZeroMemory(buffer, 512);

    sprintf(buffer, "RCPT TO: someoneelse@yahoo.com\r\n");

    send(theSocket, buffer, strlen(buffer), 0);

    ZeroMemory(buffer, 512);

    recv(theSocket, buffer, 512, 0);

    MessageBox(NULL, buffer, "Test", MB_OK);

   

    ZeroMemory(buffer, 512);

    sprintf(buffer, "DATA\r\n");

    send(theSocket, buffer, strlen(buffer), 0);

    ZeroMemory(buffer, 512);

    recv(theSocket, buffer, 512, 0);

    MessageBox(NULL, buffer, "Test", MB_OK);

   

    ZeroMemory(buffer, 512);

    char data[2048];

    ZeroMemory(data, 2048);

    strncat(data, "Date: Sat, 31 Dec 2005 1:06:54\r\n", 33);                                   //Im sure you could do a lot better than this

    strncat(data, "From: Some One <someone@hotmail.com>\r\n", 49);                        //Don’t follow my lazy example

    strncat(data, "To: Someone Else <someoneelse@gmail.com\r\n", 35);

    strncat(data, "Subject: Test\r\nHey!", 23);

    strncat(data, "Testing out my radical smtp skills\r\n.\r\n\r\n", 42);

    MessageBox(NULL, data, "Test", MB_OK);

    send(theSocket, data, strlen(data), 0);

    ZeroMemory(buffer, 1024);

    recv(theSocket, buffer, 512, 0);

    MessageBox(NULL, buffer, "Test", MB_OK);

   

    ZeroMemory(buffer, 512);

    sprintf(buffer, "QUIT\r\n");

    send(theSocket, buffer, strlen(buffer), 0);

    closesocket(theSocket);

    WSACleanup();

}

 

 

www.supercamel.co.nr