
/* CGI program to write email to an smtp server (port 25). */
/* Search for "alton-moore.net" below and replace it with  */
/* the host name of the machine this CGI is running on.    */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <fcntl.h>
#include <unistd.h>

extern int errno;  /* Error codes are returned here. */

struct hostent *hostent;
struct sockaddr_in sockaddr;
int sock,status,hostaddr,smtp_port=25,socket_option=0;
char buffer[4096];
fd_set socket_read_status;
struct timeval socket_time_structure;

#define TIMEOUT_SECONDS 30
#define BUFFER_SIZE 16000
time_t current_time,hold_time;

char smtp_server[128],smtp_account[32],smtp_password[32],smtp_recipient[64],
     smtp_subject[64];
char temp_string[BUFFER_SIZE],email_body[BUFFER_SIZE],
     form_data_string[BUFFER_SIZE],form_data_string_2[BUFFER_SIZE];
int message_number,temp_int,temp_int_2,temp_string_pointer;
char message_number_string[8],byte_count_string[8],temp_char;
int byte_count,byte_count_string_pointer,bytes_printed;


/*----------------------------- Subroutines ----------------------------------*/

#include "web_based_email.h"


/*----------------------------- Main Program ---------------------------------*/
int main(void)
{
printf("Content-type: text/html\n");  /* We have to return this line first. */
printf("\n");

printf("<HTML>\n");
printf("<HEAD>\n");
printf("<H2>SMTP Session Results</H2>\n");
printf("</HEAD>\n");
printf("<BODY>\n");

gets(form_data_string);  /* Get form data and clean up. */
temp_int = 0;
temp_int_2 = 0;
while (form_data_string[temp_int])
  {
  if (form_data_string[temp_int] == '+')  /* Convert + to spaces. */
    {
    form_data_string_2[temp_int_2++] = ' ';
    temp_int++;
    continue;
    }
  if (form_data_string[temp_int] == '%')  /* Escape character received? */
    {
    if (form_data_string[temp_int+1] == 0)  /* Inappropriate? */
      {
      printf("Error: % was the last character in the input buffer.\n");
      break;
      }
    if (form_data_string[temp_int+1] == '%')
      {
      form_data_string_2[temp_int_2++] = '%';
      temp_int++; temp_int++;
      continue;
      }
    /* Translate the next 2 characters from hex to one ascii character. */
    switch (form_data_string[temp_int+1])
      {
      case '0' :
      case '1' :
      case '2' :
      case '3' :
      case '4' :
      case '5' :
      case '6' :
      case '7' :
      case '8' :
      case '9' : temp_char = form_data_string[temp_int+1] - 48; break;
      case 'A' :
      case 'B' :
      case 'C' :
      case 'D' :
      case 'E' :
      case 'F' : temp_char = form_data_string[temp_int+1] - 55; break;
      }
    temp_char *= 16;
    switch (form_data_string[temp_int+2])
      {
      case '0' :
      case '1' :
      case '2' :
      case '3' :
      case '4' :
      case '5' :
      case '6' :
      case '7' :
      case '8' :
      case '9' : temp_char += form_data_string[temp_int+2] - 48; break;
      case 'A' :
      case 'B' :
      case 'C' :
      case 'D' :
      case 'E' :
      case 'F' : temp_char += form_data_string[temp_int+2] - 55; break;
      }
    form_data_string_2[temp_int_2++] = temp_char;
    temp_int++; temp_int++; temp_int++;
    continue;
    }
  /* Just copy the current character. */
  form_data_string_2[temp_int_2++] = form_data_string[temp_int];
  temp_int++;
  }
strcpy(form_data_string,form_data_string_2);  /* Move the manipulated string back to the original. */

/* Figure out smtp information and load variables. */
find_field_in_form_data_string("smtp_server");
strcpy(smtp_server,temp_string);
find_field_in_form_data_string("smtp_account");
strcpy(smtp_account,temp_string);
find_field_in_form_data_string("smtp_password");
strcpy(smtp_password,temp_string);
find_field_in_form_data_string("smtp_recipient");
strcpy(smtp_recipient,temp_string);
find_field_in_form_data_string("smtp_subject");
strcpy(smtp_subject,temp_string);
find_field_in_form_data_string("email_body");
strcpy(email_body,temp_string);

/* Leave this in for a while for debugging. */
/*
printf("<PRE>\n");
printf("String length of form_data_string: %d\n",strlen(form_data_string));
printf("form_data_string: %s\n",form_data_string);
printf("</PRE>\n");
*/


/* Now get connected. */
strcpy(temp_string,smtp_server);
hostent = gethostbyname(temp_string);  /* Do DNS lookup. */
if (hostent == NULL)
  {
  printf("Couldn't resolve SMTP server address; quitting.\n");
  goto exit_program;
  }

sock = socket(AF_INET,SOCK_STREAM,0);  /* Allocate a socket. */
if (sock < 0)
  {
  printf("Unable to allocate a socket; quitting.\n");
  goto exit_program;
  }

/* Initialize sockaddr fields. */
memset(&sockaddr,0,sizeof(sockaddr));
sockaddr.sin_family = AF_INET;
memcpy((char *)&(sockaddr.sin_addr.s_addr),(char *)hostent->h_addr_list[0],
 (size_t)hostent->h_length);
sockaddr.sin_port = htons(smtp_port);

/* Connect to remote port now. */
if (connect(sock,(struct sockaddr *)&sockaddr,sizeof(sockaddr)) < 0)
  {
  printf("Unable to connect to your SMTP server; quitting.\n");
  close(sock);
  goto exit_program;
  }
fcntl(sock,F_SETFL,O_NONBLOCK);  /* Set socket to non-blocking. */

/*-------------------------------------*/
/* Now we're ready to talk with the SMTP server, with text messages. */

/* Get welcome message from server. */
if (get_message_from_socket())
  {
  printf("Didn't get welcome message from smtp server; quitting.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"220 ",4))  /* Not ok? */
  {
  printf("Bad welcome message from SMTP server: %s\n",temp_string);
  goto shut_down_and_close;
  }

strcpy(buffer,"HELO www.alton-moore.net\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting HELO response from smtp server.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"250 ",4))  /* Not ok? */
  {
  printf("Bad HELO response from server: %s\n",temp_string);
  goto shut_down_and_close;
  }

strcpy(buffer,"MAIL FROM: ");
strcat(buffer,smtp_account);
strcat(buffer,"@");
strcat(buffer,smtp_server);
strcat(buffer,"\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting MAIL FROM response from smtp server.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"250 ",4))  /* Not ok? */
  {
  printf("Bad MAIL FROM response from server: %s\n",temp_string);
  goto shut_down_and_close;
  }

strcpy(buffer,"RCPT TO: ");
strcat(buffer,smtp_recipient);
strcat(buffer,"\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting RCPT TO response from smtp server.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"250 ",4))  /* Didn't get +OK? */
  {
  printf("Bad RCPT TO response from server; quitting.\n");
  goto shut_down_and_close;
  }

strcpy(buffer,"DATA\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting DATA response from server; quitting.\n");
  goto shut_down_and_close;
  }
if (strncmp(temp_string,"354 ",4))
  {
  printf("Bad DATA response from server; quitting.\n");
  goto shut_down_and_close;
  }

/* This is a test of making the subject work. */
strcpy(buffer,"Subject: ");
strcat(buffer,smtp_subject);
strcat(buffer,"\r\n");
write(sock,buffer,strlen(buffer));

strcpy(buffer,email_body);
strcat(buffer,"\r\n");
write(sock,buffer,strlen(buffer));
strcpy(buffer,".\r\n");  /* The terminating period. */
write(sock,buffer,strlen(buffer));

/* Now log out from the smtp server. */
strcpy(buffer,"QUIT\r\n");
write(sock,buffer,strlen(buffer));
if (get_message_from_socket())
  {
  printf("Error getting QUIT response from smtp server.\n");
  goto shut_down_and_close;
  }
printf("Result from SMTP server: %s\n",temp_string);


/*-------------------------------------*/
shut_down_and_close:
shutdown(sock,2);
close(sock);

exit_program:
printf("<HR>\n");
printf("Please send any comments on this web-based email system to\n");
printf("<A HREF=""mailto:alton@alton-moore.net"">Alton Moore</A>.\n");
printf("</BODY>\n");
printf("</HTML>\n");

return(0);
}

