// ngsmtp1.c: NET/guard+ SMTP client. Use gcc within Cygwin or other environment
// Vers. 1.05 - 05.Mar.2006
// k.d.walter@t-online.de

// Includes

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

// Defines

#define VERSION "1.05 - 05.Mar.2006"

// Functions: 1. main - The one and only ...

int main (int argc, char* argv[])
{
   int nLen= sizeof (struct sockaddr), nRet, s1;
   long lRet;
   char szBuf[1024];
   struct sockaddr_in saServer;
   struct tm *tmPtr;
   time_t currTime;

   // Check for IP address and port argument. Print usage if errors...

   if (argc != 4) {
      printf ("\n  Usage.: ngsmtp <SMTP Server> <RCPT TO> <\"E-Mail Message\">");
      printf ("\n  Sample: ngsmtp 192.168.0.1 info@ist1.de \"test message...\"\n");
      exit (0);
   }

   // Check for valid IP address

   lRet= inet_addr (argv[1]);
   if (lRet == INADDR_NONE) {
      printf ("\n  No valid IP address.\n");
      exit (0);
   }

   // Create a TCP/IP stream socket...

   s1= socket (AF_INET, SOCK_STREAM, 0);

   // ... and check for error...

   if (s1 < 0)  {
      printf ("\n  Can not create socket.\n");
      exit (0);
   }

   // Fill in the internet address structure...

   saServer.sin_family= AF_INET;                    // Address family
   saServer.sin_addr.s_addr= inet_addr (argv[1]);   // IP address
   saServer.sin_port= htons (25);                   // Portnumber
   memset (&(saServer.sin_zero), 0x00, 8);          // Zero the rest...

   // Connect to server...

   printf ("\n... Try to connect to %s:25.", argv[1]);
   fflush (stdout);
   nRet= connect (s1, (struct sockaddr *) &saServer, nLen);

   // Check for errors...

   if (nRet != 0)   {
      printf ("\n  Can not connect to SMTP server.\n");
      close (s1);
      exit (0);
   }

   // Wait for first server message (220 ...) ...

   memset (szBuf, 0, sizeof (szBuf));
   nRet= recv (s1, szBuf, sizeof (szBuf), 0);
   printf ("\nRX: %s", szBuf);

   // Get current time...

   (void) time (&currTime);
   tmPtr= localtime (&currTime);

   // Send "HELO ..." and wait for server answer (250 ...) ...

   sprintf (szBuf, "HELO user\r\n");
   printf ("\nTX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);
   memset (szBuf, 0, sizeof (szBuf));
   nRet= recv (s1, szBuf, sizeof (szBuf), 0);
   printf ("RX: %s", szBuf);
   if (strncmp (szBuf, "250", 3)) {          // Check for server answer "250"
      printf ("\nE1: SMTP server error.\n");
      close (s1);
      exit (0);
   }

   // Send "MAIL FROM: ..." and wait for server answer (250 ...) ...

   sprintf (szBuf, "MAIL FROM: <walter-m2m@htp-tel.de>\r\n");
   printf ("\nTX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);
   memset (szBuf, 0, sizeof (szBuf));
   nRet= recv (s1, szBuf, sizeof (szBuf), 0);
   printf ("RX: %s", szBuf);
   if (strncmp (szBuf, "250", 3)) {          // Check for server answer "250"
      printf ("\nE2: SMTP server error.\n");
      close (s1);
      exit (0);
   }

   // Send "RCPT TO: ..." and wait for server answer (250 ...) ...

   sprintf (szBuf, "RCPT TO: <%s>\r\n", argv[2]);
   printf ("\nTX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);
   memset (szBuf, 0, sizeof (szBuf));
   nRet= recv (s1, szBuf, sizeof (szBuf), 0);
   printf ("RX: %s", szBuf);
   if (strncmp (szBuf, "250", 3)) {          // Check for server answer "250"
      printf ("\nE3: SMTP server error.\n");
      close (s1);
      exit (0);
   }

   // Send "DATA" and wait for server answer (354 ...) ...

   sprintf (szBuf, "DATA\r\n");
   printf ("\nTX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);
   memset (szBuf, 0, sizeof (szBuf));
   nRet= recv (s1, szBuf, sizeof (szBuf), 0);
   printf ("RX: %s", szBuf);
   if (strncmp (szBuf, "354", 3)) {          // Check for server answer "354"
      printf ("\nE4: SMTP server error.\n");
      close (s1);
      exit (0);
   }

   // Send 1. line of header...

   sprintf (szBuf, "From: <walter-m2m@htp-tel.de>\r\n");
   printf ("\nTX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);

   // Send 2. line of header...

   sprintf (szBuf, "To: <%s>\r\n", argv[2]);
   printf ("TX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);

   // Send 3. line of header...

   sprintf (szBuf, "Subject: NET/guard+ - Current System State at %02d:%02d:%02d\r\n",
            tmPtr->tm_hour, tmPtr->tm_min, tmPtr->tm_sec);
   printf ("TX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);

   // Send 4. line of header with one blank line...

   sprintf (szBuf, "Content-type: text/plain\r\n\r\n");
   printf ("TX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);

   // Send one line of data with NET/guard+ version number and build date...

   sprintf (szBuf, "NET/guard+ SMTP Client Vers. "VERSION"\r\n");
   printf ("TX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);

   // Send one line of data as separator...

   sprintf (szBuf, "-----------------------------------------------\r\n");
   printf ("TX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);

   // Send one line of data with command line argument...

   sprintf (szBuf, "%s\r\n", argv[3]);
   printf ("TX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);

   // Send end of data and wait for server answer (250 ...) ...

   sprintf (szBuf, ".\r\n");
   printf ("TX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);
   memset (szBuf, 0, sizeof (szBuf));
   nRet= recv (s1, szBuf, sizeof (szBuf), 0);
   printf ("RX: %s", szBuf);
      if (strncmp (szBuf, "250", 3)) {          // Check for server answer "250"
      printf ("\nE5: SMTP server error.\n");
      close (s1);
      exit (0);
   }

   // Send "QUIT" and wait for server answer (221 ...) ...

   sprintf (szBuf, "QUIT\r\n");
   printf ("\nTX: %s", szBuf);
   send (s1, szBuf, strlen (szBuf), 0);
   memset (szBuf, 0, sizeof (szBuf));
   nRet= recv (s1, szBuf, sizeof (szBuf), 0);
   printf ("RX: %s", szBuf);
   if (strncmp (szBuf, "221", 3)) {          // Check for server answer "221"
      printf ("\nE6: SMTP server error.\n");
      close (s1);
      exit (0);
   }

   // OK: Exit this SMTP client code ...

   close (s1);
   exit (1);
}
