Sending E-mail From a C Program
By David Phillips
June 3, 2009
The other day, I was working on one of my projects in C
and I needed the program to send out an e-mail. Most of the examples I
found were all in Java so I created my own that would work for what I needed it
to do.
It’s a simple function that takes some e-mail parameters
and the name of an SMTP server which it uses to fire off an e-mail.
It’s programmed to use the winsock libraries for the Windows Operating System. It can be modified to use BSD sockets without too much of an effort. If you are using it with Windows, make sure to set your linker to import ws2_32.lib.
Here are the C source files if you want to drop them into your existing project:
If you run the example on windows, you will see:

And then if you go check your e-mail, you should see:


test_email_util.c:
#include <stdio.h>
#include "emailutil.h"
int main(int
argc, char* argv[]){
int iSent =
send_email_smtp("smtp.west.cox.net",
"David Phillips",
"Test Mailer",
"david@crackthecode.us",
"david@crackthecode.us",
"Test e-mail",
"This is a test e-mail.",
SESMTP_ENABLE_TRACING);
if(iSent){
printf("E-mail
sent successfully.\n");
}
else{
printf("E-mail
could not be sent.\n");
}
return 0;
};
email_util.h
#ifndef
_EMAIL_UTIL
#define
SESMTP_NULL 0x0
#define
SESMTP_ENABLE_TRACING 0x1
/*
A simple e-mail function.
Sends an e-mail message
using the SMTP protocol.
Returns non-zero if email
sends successfully.
Example Usage:
---------------------------------------------
int iSent =
send_email_smtp("smtp.west.cox.net",
"David Phillips",
"Test Mailer",
"david@crackthecode.us",
"david@crackthecode.us",
"Test e-mail",
"This is a test e-mail.",
SESMTP_ENABLE_TRACING);
if(iSent){
printf("E-mail sent successfully.\n");
}
else{
printf("E-mail could not be sent.\n");
}
--------------------------------------------
*/
int
send_email_smtp(const char*
lpzSMTPServer,
const
char* lpzToName,
const char* lpzFromName,
const
char* lpzToEmail,
const
char* lpzFromEmail,
const
char* lpzSubject,
const
char* lpzMessage,
int iFlags);
#endif
email_util.c
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#include
<windows.h>
#include
<winsock.h>
#include
"emailutil.h"
#define
SMTP_WELL_KNOWN_PORT 25
typedef
struct{
const
char* lpzToName;
const
char* lpzFromName;
const
char* lpzToEmail;
const
char* lpzFromEmail;
const
char* lpzSubject;
const
char* lpzMessage;
}Email;
typedef
struct{
WORD
wVersionRequested;
/* socket dll version info */
WSADATA wsaData;
/* data for socket lib initialisation */
struct sockaddr_in address;
/* socket address stuff */
struct hostent * host;
/* host stuff */
float socklib_ver;
/* socket
dll version */
int iConnected;
SOCKET
sock;
char lpzSendBuffer[5000];
char lpzRecvBuffer[5000];
}TCPState;
typedef
struct{
int iMailSent;
TCPState*
lpTCPState;
const
char* lpzSMTPServer;
Email*
lpEmail;
int iFlags;
}SMTPMailer;
static
int recv_line(SOCKET sock,
char* lpzBuffer,
unsigned int
uiBuffLeng){
unsigned
int iRecv = 0;
memset(lpzBuffer, 0x0, uiBuffLeng);
while(iRecv
< uiBuffLeng){
iRecv
+= recv(sock, lpzBuffer + iRecv, 1, 0);
if(lpzBuffer[iRecv - 1] == '\n'){
break;
}
}
return
iRecv;
}
static
void smtp_protocol_recv(SMTPMailer* lpMailer){
recv_line(lpMailer->lpTCPState->sock,
lpMailer->lpTCPState->lpzRecvBuffer,
sizeof(lpMailer->lpTCPState->lpzRecvBuffer));
if(lpMailer->iFlags
& SESMTP_ENABLE_TRACING){
printf("%s", lpMailer->lpTCPState->lpzRecvBuffer);
}
};
static
void smtp_protocol_send(SMTPMailer* lpMailer){
send(lpMailer->lpTCPState->sock,
lpMailer->lpTCPState->lpzSendBuffer,
(int)strlen(lpMailer->lpTCPState->lpzSendBuffer),
0);
};
static
void smtp_protocol_send_and_recv(SMTPMailer* lpMailer){
smtp_protocol_send(lpMailer);
smtp_protocol_recv(lpMailer);
};
static
void transmit_email(SMTPMailer* lpMailer){
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"HELO
localhost\r\n");
smtp_protocol_send_and_recv(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"MAIL
FROM:<%s>\r\n",
lpMailer->lpEmail->lpzFromEmail);
smtp_protocol_send_and_recv(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"RCPT
TO:<%s>\r\n",
lpMailer->lpEmail->lpzToEmail);
smtp_protocol_send_and_recv(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"DATA\r\n");
smtp_protocol_send_and_recv(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"From:
%s <%s>\r\n",
lpMailer->lpEmail->lpzFromName,
lpMailer->lpEmail->lpzFromEmail);
smtp_protocol_send(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"To:
%s <%s>\r\n",
lpMailer->lpEmail->lpzToName,
lpMailer->lpEmail->lpzToEmail);
smtp_protocol_send(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"Subject:
%s\r\n",
lpMailer->lpEmail->lpzSubject);
smtp_protocol_send(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"%s\r\n",
lpMailer->lpEmail->lpzMessage);
smtp_protocol_send(lpMailer);
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"\r\n.\r\n");
smtp_protocol_send_and_recv(lpMailer);
if(strlen(lpMailer->lpTCPState->lpzRecvBuffer)
>= 3 &&
!strncmp("250", lpMailer->lpTCPState->lpzRecvBuffer,
3)){
lpMailer->iMailSent
= 1;
}
sprintf_s(lpMailer->lpTCPState->lpzSendBuffer,
sizeof(lpMailer->lpTCPState->lpzSendBuffer),
"QUIT\r\n");
smtp_protocol_send_and_recv(lpMailer);
};
static
void smtp_server_connect(SMTPMailer* lpMailer){
lpMailer->lpTCPState->wVersionRequested
= MAKEWORD( 1, 1 );
if(!WSAStartup(
lpMailer->lpTCPState->wVersionRequested, &lpMailer->lpTCPState->wsaData
)){
lpMailer->lpTCPState->socklib_ver
= (float)(HIBYTE( lpMailer->lpTCPState->wsaData.wVersion
) / 10.0);
lpMailer->lpTCPState->socklib_ver
+= LOBYTE( lpMailer->lpTCPState->wsaData.wVersion );
lpMailer->lpTCPState->sock
= socket(AF_INET, SOCK_STREAM, 0);
if(INVALID_SOCKET != lpMailer->lpTCPState->sock){
lpMailer->lpTCPState->address.sin_family = AF_INET;
lpMailer->lpTCPState->address.sin_port = htons(SMTP_WELL_KNOWN_PORT);
lpMailer->lpTCPState->host = gethostbyname(lpMailer->lpzSMTPServer);
if(NULL != lpMailer->lpTCPState->host){
lpMailer->lpTCPState->address.sin_addr.s_addr
= *((unsigned long
*) lpMailer->lpTCPState->host->h_addr);
lpMailer->lpTCPState->iConnected = !connect(lpMailer->lpTCPState->sock,
(struct sockaddr *) &lpMailer->lpTCPState->address,
sizeof(lpMailer->lpTCPState->address));
}
}
}
}
static
void smtp_server_disconnect(SMTPMailer* lpMailer){
if(lpMailer->lpTCPState){
memset(lpMailer->lpTCPState,
0x0, sizeof(TCPState));
}
WSACleanup();
/* clean up before exit */
};
static
void send_email(SMTPMailer* lpMailer){
smtp_server_connect(lpMailer);
if(lpMailer->lpTCPState->iConnected){
smtp_protocol_recv(lpMailer);
transmit_email(lpMailer);
}
smtp_server_disconnect(lpMailer);
};
int
send_email_smtp(const char*
lpzSMTPServer,
const
char* lpzToName,
const char* lpzFromName,
const
char* lpzToEmail,
const
char* lpzFromEmail,
const
char* lpzSubject,
const
char* lpzMessage,
int
iFlags){
TCPState tcpState;
Email email = {
lpzToName,
lpzFromName,
lpzToEmail,
lpzFromEmail,
lpzSubject,
lpzMessage
};
SMTPMailer smtpMailer = {
0,
&tcpState,
lpzSMTPServer,
&email,
iFlags
};
memset(&tcpState, 0x0,
sizeof(TCPState));
send_email(&smtpMailer);
return
smtpMailer.iMailSent;
};