Win32 Command Line SMTP


   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 rn. 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);

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] = '';
cout<< recv_Buf<<endl;
//Say Hello to the domain
strcpy(send_Buf,"HELO sampledomain.comrn");
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] = '';
cout<< recv_Buf<<endl;
//Send from address
strcpy(
send_Buf, "MAIL FROM: frome-mailid@sampledomain.com");
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] = '';
cout<< recv_Buf<<endl;
//Send RCPT address
strcpy(send_Buf,"RCPT TO:<toemail-id@sampledomain.com>rn");
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] = '';
cout<< recv_Buf<<endl;
// Send DATA
strcpy(send_Buf,"DATArn");
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] = '';
cout<< recv_Buf<<endl;
// Send DATA
strcpy(send_Buf,"Subject:Test Win32 command line SMTP Subjectrnrn");
s_len = send(skt_Smtp,send_Buf,strlen(send_Buf),0);
//Send body
strcpy(send_Buf,"Test e-mail for Win32 command line SMTPrn.rn");
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] = '';
cout<< recv_Buf<<endl;
//Send QUIT
strcpy(send_Buf,"QUITn");
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] = '';

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.