Crack The Code

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: SimpleSMTPEmailer.zip (Winsock version) SimpleSMTPEmailer.tar.gz (BSD Version)

 

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;

};