Command Line SMTP can be programmed using sockets very easily.
SMTP or Simple Mail Transfer Protocol has a set of commands to
be sent and received. If a program can send the command with
the protocol and data to the SMTP server, then it can easily
send e-mails. In fact even a telnet session at SMTP port 25
can be used to send e-mails, if the protocol is known
properly. This Command Line SMTP in Win32 article explains how
to use Win 32 to write an SMTP program.
The following is the set of commands from the SMTP RFC to be
sent to the SMTP server to make it listen and accept our
e-mails to be sent to the recipients.
Connect
to SMTP server using port 25
Expect 220
Send HELO myFQDN
Expect 250
Send MAIL FROM:<From-mail@myFQDN.com>
Expect 250
Send RCPT TO:<mail_address>
Expect 250
Send DATA
Expect 354
Send body of message
Send <CRLF>.<CRLF>
Expect 250
Send QUIT
Expect 221
Close connection
The above is the way an SMTP client and a SMTP server interact
between them. All the above strings sent to the Command
Line SMTP program, including the e-mail addresses should be
appended with \r\n. Otherwise it will not be considered as
the end of the line.
Also the received data will contain numbers like 250, 354
etc., in the front. These numbers mean either the messages is
accepted or rejected or unrecognized. 500 is the error
returned if the command is unrecognized.
Command
Line SMTP sample using Win32:
The following sample program can be used to send an e-mail to
the SMTP server.
#include <winsock2.h>
#include <windows.h>
#include <iostream.h>
#define MAX_LENGTH 1024
void main()
{
int s_len, r_len;
int skt_Smtp;
int success;
struct sockaddr_in
st_Sockaddr;
char
recv_Buf[MAX_LENGTH];
char
send_Buf[MAX_LENGTH];
//Initialize Sockets
WSADATA wsa;
WSAStartup(MAKEWORD(2,
0), &wsa);
skt_Smtp =
socket(AF_INET,SOCK_STREAM,0);
if (skt_Smtp < 0)
{
cout<< "Error Creating Socket"<<endl;
return;
}
else
{
st_Sockaddr.sin_family = AF_INET;
st_Sockaddr.sin_port = htons(25);
//Get
the IP address and initialize the structure
st_Sockaddr.sin_addr.s_addr = inet_addr("IPAddress");
success
= connect(skt_Smtp,(struct sockaddr *)
&st_Sockaddr,sizeof(st_Sockaddr));
r_len =
recv(skt_Smtp,recv_Buf,MAX_LENGTH,0);
recv_Buf[r_len] = '\0';
cout<<
recv_Buf<<endl;
//Say
Hello to the domain
strcpy(send_Buf,"HELO
sampledomain.com\r\n");
s_len =
send(skt_Smtp,send_Buf,strlen(send_Buf),0);
r_len =
recv(skt_Smtp,recv_Buf,MAX_LENGTH,0);
recv_Buf[r_len] = '\0';
cout<<
recv_Buf<<endl;
//Send
from address
strcpy(send_Buf
, "MAIL FROM:
frome-mailid@sampledomain.com\r\n");
s_len =
send(skt_Smtp,send_Buf,strlen(send_Buf),0);
r_len =
recv(skt_Smtp,recv_Buf,MAX_LENGTH,0);
recv_Buf[r_len] = '\0';
cout<<
recv_Buf<<endl;
//Send
RCPT address
strcpy(send_Buf,"RCPT
TO:<toemail-id@sampledomain.com>\r\n");
s_len =
send(skt_Smtp,send_Buf,strlen(send_Buf),0);
r_len =
recv(skt_Smtp,recv_Buf,MAX_LENGTH,0);
recv_Buf[r_len] = '\0';
cout<<
recv_Buf<<endl;
// Send
DATA
strcpy(send_Buf,"DATA\r\n");
s_len =
send(skt_Smtp,send_Buf,strlen(send_Buf),0);
r_len =
recv(skt_Smtp,recv_Buf,MAX_LENGTH,0);
recv_Buf[r_len] = '\0';
cout<<
recv_Buf<<endl;
// Send
DATA
strcpy(send_Buf,"Subject:Test Win32 command line SMTP
Subject\r\n\r\n");
s_len =
send(skt_Smtp,send_Buf,strlen(send_Buf),0);
//Send body
strcpy(send_Buf,"Test e-mail for Win32 command line
SMTP\r\n.\r\n");
s_len =
send(skt_Smtp,send_Buf,strlen(send_Buf),0);
r_len =
recv(skt_Smtp,recv_Buf,MAX_LENGTH,0);
recv_Buf[r_len] = '\0';
cout<<
recv_Buf<<endl;
//Send QUIT
strcpy(send_Buf,"QUIT\n");
s_len =
send(skt_Smtp,send_Buf,strlen(send_Buf),0);
r_len =
recv(skt_Smtp,recv_Buf,MAX_LENGTH,0);
recv_Buf[r_len] = '\0';
cout<<
recv_Buf<<endl;
closesocket(skt_Smtp);
}
WSACleanup();
}
This program can be compiled as a console application. The
items highlighted in
BOLD and BLUE
colors should be replaced with the right names.
Note: As this program uses sockets, this needs to be linked
with ws2_32.lib library. Refer for
more information on socket client.