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();
}