home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / ntcode / blat01 / blat.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  19.2 KB  |  758 lines

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <iostream.h>
  5. /* generic socket DLL support */
  6. #include "gensock.h"
  7.  
  8. #ifdef WIN32         
  9.   #define __far far
  10.   #define huge far
  11.   #define __near near
  12. #endif               
  13.  
  14. #define MAXOUTLINE 255
  15.  
  16. HANDLE    gensock_lib = 0;
  17.  
  18. int (FAR PASCAL *pgensock_connect) (char FAR * hostname, char FAR * service, socktag FAR * pst);
  19. int (FAR PASCAL *pgensock_getchar) (socktag st, int wait, char FAR * ch);
  20. int (FAR PASCAL *pgensock_put_data) (socktag st, char FAR * data, unsigned long length);
  21. int (FAR PASCAL *pgensock_close) (socktag st);
  22. int (FAR PASCAL *pgensock_gethostname) (char FAR * name, int namelen);
  23. int (FAR PASCAL *pgensock_put_data_buffered) (socktag st, char FAR * data, unsigned long length);
  24. int (FAR PASCAL *pgensock_put_data_flush) (socktag st);
  25.  
  26.  
  27. socktag SMTPSock;
  28. char SMTPHost[128];
  29. char Sender[128];
  30. char *Recipients;
  31. char my_hostname[1024];
  32. char *destination="";
  33. char *cc_list="";
  34. char *loginname="";
  35. char *senderid="";
  36. char *subject="";
  37.  
  38. char *usage[]= {
  39. "Blat: WinNT console utility to mail a file to a user via SMTP",
  40. "",
  41. "syntax:",
  42. "Blat <filename> [-s <subject>] -t <recipient> -f <address> [-i <address>]",
  43. "Blat -SMTP <server address>",
  44. "Blat -h",
  45. "",
  46. "-SMTP <server address> <senders address>: set's the address of the SMTP server to be used",
  47. "",
  48. "<filename>: the file with the message body",
  49. "-s <subject>: the (optional) subject line",
  50. "-t <recipient>: the recipient's address",
  51. "-f <sender>: the sender's address (must be known to the SMTP server)",
  52. "-i <address>: a 'From:' address, not necessarily known to the SMTP server.",
  53. "-h: displays this help.",
  54. "",
  55. "Note that if the '-i' option is used, <sender> is included in 'Reply-to:'",
  56. "and 'Sender:' fields in the header of the message."
  57. };
  58. const NMLINES=18;
  59.  
  60. void
  61. gensock_error (char * function, int retval)
  62. {
  63.   cout << "error " << retval << " in function '" << function;
  64. }
  65.  
  66. // loads the GENSOCK DLL file
  67. int load_gensock()
  68. {
  69.   if( (gensock_lib = LoadLibrary("gensock.dll")) == NULL )
  70.   {
  71.     cout << "Couldn't load 'GENSOCK.DLL'\n";
  72.     return -1;
  73.   }
  74.  
  75.   if( 
  76.      ( pgensock_connect = 
  77.       (  int (FAR PASCAL *)(char FAR *, char FAR *, socktag FAR *) )
  78.       GetProcAddress(gensock_lib, "gensock_connect")
  79.      ) == NULL
  80.     )
  81.   {
  82.     cout << "couldn't getprocaddress for gensock_connect\n";
  83.     return -1;
  84.   }
  85.  
  86.   if (
  87.       ( pgensock_getchar =
  88.        ( int (FAR PASCAL *) (socktag, int, char FAR *) )
  89.        GetProcAddress(gensock_lib, "gensock_getchar")
  90.       ) == NULL
  91.      )
  92.   {
  93.     cout << "couldn't getprocaddress for gensock_getchar\n";
  94.     return -1;
  95.   }
  96.  
  97.   if(
  98.      ( pgensock_put_data =
  99.        ( int (FAR PASCAL *) (socktag, char FAR *, unsigned long) )
  100.        GetProcAddress(gensock_lib, "gensock_put_data")
  101.      ) == NULL
  102.     )
  103.   {
  104.     cout << "couldn't getprocaddress for gensock_put_data\n";
  105.     return -1;
  106.   }
  107.  
  108.   if(
  109.      ( pgensock_close =
  110.        (int (FAR PASCAL *) (socktag) )
  111.        GetProcAddress(gensock_lib, "gensock_close")
  112.      ) == NULL
  113.     )
  114.   {
  115.     cout << "couldn't getprocaddress for gensock_close\n";
  116.     return -1;
  117.   }
  118.  
  119.   if(
  120.      ( pgensock_gethostname =
  121.        (int (FAR PASCAL *) (char FAR *, int) )       
  122.        GetProcAddress(gensock_lib, "gensock_gethostname")
  123.      ) == NULL
  124.     )
  125.   {
  126.     cout << "couldn't getprocaddress for gensock_gethostname\n";
  127.     return -1;
  128.   }
  129.  
  130.   if(
  131.      ( pgensock_put_data_buffered =
  132.        ( int (FAR PASCAL *) (socktag, char FAR *, unsigned long) )
  133.        GetProcAddress(gensock_lib, "gensock_put_data_buffered")
  134.      ) == NULL
  135.     )
  136.   {
  137.     cout << "couldn't getprocaddress for gensock_put_data_buffered\n";
  138.     return -1;
  139.   }
  140.  
  141.   if(
  142.      ( pgensock_put_data_flush =
  143.        ( int (FAR PASCAL *) (socktag) )
  144.        GetProcAddress(gensock_lib, "gensock_put_data_flush")
  145.      ) == NULL
  146.     )
  147.   {
  148.     cout << "couldn't getprocaddress for gensock_put_data_flush\n";
  149.     return -1;
  150.   }
  151.  
  152.   return 0;
  153. }
  154.  
  155. int open_smtp_socket( void )
  156. {
  157.   int retval;
  158.  
  159.   /* load the library if it's not loaded */
  160. //  if (!gensock_lib)
  161.     if ( ( retval = load_gensock() ) ) return ( retval );
  162.  
  163.   if ( (retval = (*pgensock_connect) ((LPSTR) SMTPHost,
  164.                      (LPSTR)"smtp",
  165.                      &SMTPSock)))
  166.   {
  167.     if (retval == ERR_CANT_RESOLVE_SERVICE)
  168.     {
  169.      if ((retval = (*pgensock_connect) ((LPSTR)SMTPHost,
  170.                      (LPSTR)"25",
  171.                      &SMTPSock)))
  172.      {
  173.        gensock_error ("gensock_connect", retval);
  174.        return -1;
  175.      }
  176.     }
  177.   // error other than can't resolve service 
  178.     else
  179.     {
  180.      gensock_error ("gensock_connect", retval);
  181.      return -1;
  182.     }
  183.   }
  184.  
  185.   // we wait to do this until here because WINSOCK is
  186.   // guaranteed to be already initialized at this point.
  187.  
  188.   // get the local hostname (needed by SMTP) 
  189.   if ((retval = (*pgensock_gethostname) (my_hostname, sizeof(my_hostname))))
  190.   {
  191.     gensock_error ("gensock_gethostname", retval);
  192.     return -1;
  193.   }
  194. //  strcpy( my_hostname, "pcfchb.dbs.aber.ac.uk");
  195.   return 0;
  196. }
  197.  
  198.  
  199. int close_smtp_socket( void )
  200. {
  201.   int retval;
  202.  
  203.   if( (retval = (*pgensock_close) (SMTPSock)) )
  204.   {
  205.     gensock_error ("gensock_close", retval);
  206.     return -1;
  207.   }
  208.   FreeLibrary( gensock_lib );
  209.   return (0);
  210. }
  211.  
  212. int get_smtp_line( void )
  213. {
  214.   char ch = '.';
  215.   char in_data [MAXOUTLINE];
  216.   char * index;
  217.   int retval = 0;
  218.  
  219.   index = in_data;
  220.  
  221.   while (ch != '\n')
  222.   {
  223.    if( (retval = (*pgensock_getchar) (SMTPSock, 0, &ch) ) )
  224.    {
  225.       gensock_error ("gensock_getchar", retval);
  226.       return -1;
  227.     }
  228.     else
  229.     {
  230.       *index = ch;
  231.       index++;
  232.     }
  233.   }
  234.  
  235.   /* this is to support multi-line responses, common with */
  236.   /* servers that speak ESMTP */
  237.  
  238.   /* I know, I know, it's a hack 8^) */
  239.   if( in_data[3] == '-' ) return( get_smtp_line() );
  240.   else return atoi(in_data);
  241. }
  242.  
  243. int put_smtp_line( socktag sock, char far * line, unsigned int nchars )
  244. {
  245.   int retval;
  246.  
  247.   if( (retval = (*pgensock_put_data) (sock, line, (unsigned long) nchars)))
  248.   {
  249.     gensock_error ("gensock_put_data", retval);
  250.     return -1;
  251.   }
  252.   return (0);
  253. }
  254.  
  255. int putline_internal (socktag sock, char * line, unsigned int nchars)
  256. {
  257.   int retval;
  258.  
  259.   if ((retval =
  260.        (*pgensock_put_data) (sock,
  261.                 (char FAR *) line,
  262.                 (unsigned long) nchars)))
  263.   {
  264.     switch (retval)
  265.     {
  266.      case ERR_NOT_CONNECTED:
  267.       gensock_error( "SMTP server has closed the connection", retval );
  268.       break;
  269.  
  270.      default:
  271.       gensock_error ("gensock_put_data", retval);
  272.     }
  273.     return -1;
  274.   }
  275.   return (0);
  276. }
  277.  
  278. void smtp_error (char * message)
  279. {
  280.   cout << message << "\n";
  281.   put_smtp_line (SMTPSock, "QUIT\r\n", 6);
  282.   close_smtp_socket();
  283. }
  284.  
  285.  
  286. // 'destination' is the address the message is to be sent to
  287. // 'message' is a pointer to a null-terminated 'string' containing the 
  288. // entire text of the message. 
  289.  
  290. int prepare_smtp_message(char * MailAddress, char * destination)
  291. {
  292.   char out_data[MAXOUTLINE];
  293.   char str[1024];
  294.   char *ptr;
  295.   int len, startLen;
  296.  
  297.   if ( open_smtp_socket() ) return -1;
  298.  
  299.   if ( get_smtp_line() != 220 )
  300.   {
  301.     smtp_error ("SMTP server error");
  302.     return(-1);
  303.   }
  304.  
  305.   sprintf( out_data, "HELO %s\r\n", my_hostname );
  306.   put_smtp_line( SMTPSock, out_data, strlen (out_data) );
  307.  
  308.   if ( get_smtp_line() != 250 )
  309.   {
  310.     smtp_error ("SMTP server error");
  311.     return -1;
  312.   }
  313.  
  314.   sprintf (out_data, "MAIL From:<%s>\r\n", loginname);
  315.   put_smtp_line( SMTPSock, out_data, strlen (out_data) );
  316.  
  317.   if (get_smtp_line() != 250)
  318.   {
  319.     smtp_error ("The mail server doesn't like the sender name,\nhave you set your mail address correctly?");
  320.     return -1;
  321.   }
  322.  
  323.   // do a series of RCPT lines for each name in address line
  324.   for (ptr = destination; *ptr; ptr += len + 1)
  325.   {
  326.     // if there's only one token left, then len will = startLen,
  327.     // and we'll iterate once only
  328.     startLen = strlen (ptr);
  329.     if ((len = strcspn (ptr, " ,\n\t\r")) != startLen)
  330.     {
  331.       ptr[len] = '\0';            // replace delim with NULL char
  332.       while (strchr (" ,\n\t\r", ptr[len+1]))    // eat white space
  333.         ptr[len++] = '\0';
  334.     }
  335.  
  336.     sprintf (out_data, "RCPT To: <%s>\r\n", ptr);
  337.     putline_internal( SMTPSock, out_data, strlen (out_data) );
  338.  
  339.     if (get_smtp_line() != 250)
  340.     {
  341.       sprintf (str, "The mail server doesn't like the name %s.\nHave you set the 'To: ' field correctly?", ptr);
  342.       smtp_error (str);
  343.       return -1;
  344.     }
  345.  
  346.     if (len == startLen)    // last token, we're done
  347.       break;
  348.   }
  349.  
  350.   sprintf (out_data, "DATA\r\n");
  351.   put_smtp_line (SMTPSock, out_data, strlen (out_data));
  352.  
  353.   if (get_smtp_line() != 354)
  354.   {
  355.     smtp_error ("Mail server error accepting message data");
  356.     return -1;
  357.   }
  358.  
  359.   return(0);
  360.  
  361. }
  362.  
  363. int transform_and_send_edit_data( socktag sock, char * editptr )
  364. {
  365.   char *index;
  366.   char *header_end;
  367.   char previous_char = 'x';
  368.   unsigned int send_len;
  369.   int retval;
  370.   BOOL done = 0;
  371.  
  372.   send_len = lstrlen(editptr);
  373.   index = editptr;
  374.  
  375.   header_end = strstr (editptr, "\r\n\r\n");
  376.  
  377.   while (!done)
  378.   {
  379.     // room for extra char for double dot on end case
  380.     while ((unsigned int) (index - editptr) < send_len)
  381.     {
  382.       switch (*index)
  383.       {
  384.        case '.':
  385.                  if (previous_char == '\n')
  386.                   /* send _two_ dots... */
  387.                   if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) return (retval);
  388.                    if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) return (retval);
  389.                  break;
  390.        case '\r':
  391.                  // watch for soft-breaks in the header, and ignore them
  392.                  if (index < header_end && (strncmp (index, "\r\r\n", 3) == 0))
  393.                    index += 2;
  394.                  else
  395.                   if (previous_char != '\r')
  396.                    if ((retval = (*pgensock_put_data_buffered) (sock, index, 1)))
  397.                     return (retval);
  398.                   // soft line-break (see EM_FMTLINES), skip extra CR */
  399.                  break;
  400.        default:
  401.                if ((retval = (*pgensock_put_data_buffered) (sock, index, 1)))
  402.                 return (retval);
  403.       }
  404.       previous_char = *index;
  405.       index++;
  406.     }
  407.     if( (unsigned int) (index - editptr) == send_len) done = 1;
  408.   }
  409.  
  410.   // this handles the case where the user doesn't end the last
  411.   // line with a <return>
  412.  
  413.   if (editptr[send_len-1] != '\n')
  414.   {
  415.     if ((retval = (*pgensock_put_data_buffered) (sock, "\r\n.\r\n", 5)))
  416.       return (retval);
  417.   }
  418.   else
  419.     if ((retval = (*pgensock_put_data_buffered) (sock, ".\r\n", 3)))
  420.       return (retval);
  421.  
  422.   /* now make sure it's all sent... */
  423.   if ((retval = (*pgensock_put_data_flush)(sock))) return (retval);
  424.   return (TRUE);
  425. }
  426.  
  427.  
  428.  
  429. int send_smtp_edit_data (char * message)
  430. {
  431.   transform_and_send_edit_data( SMTPSock, message );
  432.  
  433.   if (get_smtp_line() != 250)
  434.   {
  435.     smtp_error ("Message not accepted by server");
  436.     return -1;
  437.   }
  438.   return(0);
  439. }
  440.  
  441.  
  442. int finish_smtp_message( void )
  443. {
  444.   return put_smtp_line( SMTPSock, "QUIT\r\n", 6 );
  445. }
  446.  
  447. // create a registry entries for this program 
  448. int CreateRegEntry( void )
  449. {
  450.   HKEY  hKey1;
  451.   DWORD  dwDisposition;
  452.   LONG   lRetCode;
  453.  
  454.   /* try to create the .INI file key */
  455.   lRetCode = RegCreateKeyEx ( HKEY_LOCAL_MACHINE,
  456.                               "SOFTWARE\\Public Domain\\Blat",
  457.                               0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE,NULL, &hKey1,&dwDisposition
  458.                             );
  459.  
  460.   /* if we failed, note it, and leave */
  461.   if (lRetCode != ERROR_SUCCESS)
  462.   {
  463.     printf ("Error in creating blat key in the registry\n");
  464.     return 10;
  465.   }
  466.  
  467.   /* try to set a section value */
  468.   lRetCode = RegSetValueEx( hKey1,"SMTP server",0,REG_SZ, (BYTE *) &SMTPHost[0], (strlen(SMTPHost)+1));
  469.  
  470.   /* if we failed, note it, and leave */
  471.   if (lRetCode != ERROR_SUCCESS)
  472.   {
  473.     printf ( "Error in setting SMTP server value in the registry\n");
  474.     return 11;
  475.   }
  476.   
  477.   /* try to set another section value */
  478.   lRetCode = RegSetValueEx( hKey1,"Sender",0,REG_SZ, (BYTE *) &Sender[0], (strlen(Sender)+1));
  479.  
  480.   /* if we failed, note it, and leave */
  481.   if (lRetCode != ERROR_SUCCESS)
  482.   {
  483.     printf ( "Error in setting sender address value in the registry\n");
  484.     return 11;
  485.   }
  486.   
  487.   return 0;
  488. }
  489.  
  490. // get the registry entries for this program 
  491. int GetRegEntry( void )
  492. {
  493.   HKEY  hKey1;
  494.   DWORD  dwType;
  495.   DWORD  dwBytesRead;
  496.   LONG   lRetCode;
  497.  
  498.   // open the registry key in read mode
  499.   lRetCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  500.                            "SOFTWARE\\Public Domain\\Blat",
  501.                            0, KEY_READ, &hKey1
  502.                          );
  503.  
  504.   // read the value of the SMTP server entry
  505.   lRetCode = RegQueryValueEx( hKey1, "SMTP server", NULL , &dwType, (BYTE *) &SMTPHost, &dwBytesRead); 
  506.   // if we failed, note it, and leave
  507.   if( lRetCode != ERROR_SUCCESS )
  508.   {
  509.     printf( "Error in reading SMTP server value from the registry\n" );
  510.     return 12;
  511.   }
  512.  
  513.   // read the value of the SMTP server entry
  514.   lRetCode = RegQueryValueEx( hKey1, "Sender", NULL , &dwType, (BYTE *) &Sender, &dwBytesRead); 
  515.   // if we failed, note it, and leave
  516.   if( lRetCode != ERROR_SUCCESS )
  517.   {
  518.     printf( "Error in reading senders user name from the registry\n" );
  519.     return 12;
  520.   }
  521.  
  522.  return 0;
  523. }
  524.  
  525.  
  526. int main( int argc,        /* Number of strings in array argv          */
  527.            char *argv[],    /* Array of command-line argument strings   */
  528.            char **envp )    /* Array of environment variable strings    */
  529. {
  530.  
  531.     if(argc<2)
  532.     {
  533.      // must have at least file name to send
  534.      for(int i=0;i<NMLINES;i++) cout<<usage[i]<<'\n';
  535.      return 1;
  536.     }
  537.  
  538.     // check for SMTP server initialization
  539.     if((argc>=3) && (lstrcmpi("-SMTP",argv[1])==0))
  540.     {
  541.      strcpy( SMTPHost, argv[2] );
  542.      if (*(argv[3])) 
  543.      strcpy( Sender, argv[3] );
  544.      else
  545.      strcpy( Sender, "" );
  546.  
  547.      if( CreateRegEntry() == 0 )
  548.       printf("\nSMTP server set to %s\n", SMTPHost );
  549.      return 0;
  550.     }
  551.     else
  552.      if( GetRegEntry() )
  553.      {
  554.       printf( "to set the SMTP server's address and the user name at that address do:\nblat -SMTP server username\n");
  555.       printf( "aborting, nothing sent\n" );
  556.       return 12;
  557.      }
  558.  
  559.     // get file name from argv[1]
  560.     char *filename=argv[1];
  561.  
  562.     // make sure filename exists, get full pathname
  563.     OFSTRUCT of;
  564.     if(lstrlen(filename)<=0 || OpenFile(filename,&of,OF_EXIST)==HFILE_ERROR)
  565.     {
  566.      cout<<filename<<" does not exist\n";        
  567.      return 2;
  568.     }
  569.  
  570.     int next_arg=2;
  571.     int impersonating = 0;
  572.     senderid  = Sender;
  573.     loginname = Sender;
  574.  
  575.     for(;argc >= (next_arg+2);)
  576.     {
  577.      if(lstrcmpi("-h",argv[next_arg])==0)
  578.      {
  579.        for(int i=0;i<NMLINES;i++) cout<<usage[i]<<'\n';
  580.       return 1;
  581.      }
  582.  
  583.         // is argv[2] "-SMTP"? If so, indicate error and return
  584.      if(lstrcmpi("-SMTP",argv[next_arg])==0)
  585.      {
  586.       printf( "to set the SMTP server's address and the user name at that address do:\nblat -SMTP server username");
  587.       return 6;
  588.      }
  589.  
  590.         // is argv[2] "-s"? If so, argv[3] is the subject
  591.      if(lstrcmpi("-s",argv[next_arg])==0)
  592.      {
  593.       subject=argv[next_arg+1];
  594.       next_arg += 2;
  595.      }
  596.  
  597.         // is argv[2] "-c"? If so, argv[3] is the carbon-copy list
  598.      if(lstrcmpi("-c",argv[next_arg])==0)
  599.      {
  600.       cc_list=argv[next_arg+1];
  601.       next_arg += 2;
  602.      }
  603.  
  604.         // is next argv "-t"? If so, succeeding argv is the destination
  605.      if(lstrcmpi("-t",argv[next_arg])==0)
  606.      {
  607.       destination=argv[next_arg+1];
  608.       next_arg += 2;
  609.      }
  610.  
  611.      //is next argv '-f'? If so, succeeding argv is the loginname
  612.      if(lstrcmp("-f",argv[next_arg])==0)
  613.      {
  614.       loginname=argv[next_arg+1];
  615.       next_arg += 2;
  616.       if( ! impersonating ) senderid = loginname;
  617.      }    
  618.  
  619.      //is next argv '-i'? If so, succeeding argv is the sender id
  620.      if(lstrcmp("-i",argv[next_arg])==0)
  621.      {
  622.       senderid=argv[next_arg+1];
  623.       next_arg += 2;
  624.       impersonating = 1;
  625.      }
  626.     }
  627.  
  628.     // build the recipients list
  629.     Recipients = new char [ strlen(destination) + strlen(cc_list) + 2 ];
  630.     strcpy( Recipients, destination );
  631.     if( strlen(cc_list) > 0 )
  632.     {
  633.      strcat(Recipients, "," );
  634.      strcat(Recipients, cc_list );
  635.     }
  636.  
  637.     // create a header for the message
  638.     char tmpstr[256];
  639.     char header[1024];
  640.     int  headerlen;
  641.     SYSTEMTIME curtime;
  642.     TIME_ZONE_INFORMATION tzinfo;
  643.     char * days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  644.     char * months[] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  645.     DWORD retval;
  646.  
  647.     GetLocalTime( &curtime );
  648.     retval = GetTimeZoneInformation( &tzinfo );
  649.   
  650.     // rfc1036&rfc822 acceptable format
  651.     // Mon, 29 Jun 94 02:15:23 GMT
  652.     sprintf (tmpstr, "Date: %s, %.2d %s %.2d %.2d:%.2d:%.2d ",
  653.       days[curtime.wDayOfWeek],
  654.       curtime.wDay,
  655.       months[curtime.wMonth - 1],
  656.       curtime.wYear,
  657.       curtime.wHour,
  658.       curtime.wMinute,
  659.       curtime.wSecond);
  660.     strcpy( header, tmpstr );
  661.     for(int i=0;i<32;i++)
  662.     {
  663.      if( retval == TIME_ZONE_ID_STANDARD ) tmpstr[i] = (char) tzinfo.StandardName[i];
  664.      else tmpstr[i] = (char) tzinfo.DaylightName[i];
  665.     }
  666.     strcat( header, tmpstr );
  667.     strcat( header, "\r\n" );
  668.     sprintf( tmpstr, "From: %s\r\n", senderid );
  669.     strcat( header, tmpstr );
  670.     if( impersonating )
  671.     {
  672.      sprintf( tmpstr, "Sender: %s\r\n", loginname );
  673.      strcat( header, tmpstr );
  674.      sprintf( tmpstr, "Reply-to: %s\r\n", loginname );
  675.      strcat( header, tmpstr );
  676.     }
  677.     if( *subject )
  678.     {
  679.      sprintf( tmpstr, "Subject: %s\r\n", subject );
  680.      strcat( header, tmpstr );
  681.     }
  682.     else
  683.     {
  684.      sprintf( tmpstr, "Subject: Contents of file: %s\r\n", filename );
  685.      strcat( header, tmpstr );
  686.     }
  687.     
  688.     sprintf( tmpstr, "To: %s\r\n", destination );
  689.     strcat( header, tmpstr );
  690.     if( *cc_list )
  691.     {
  692.      // Add line for the Carbon Copies
  693.      sprintf( tmpstr, "Cc: %s\r\n", cc_list );
  694.      strcat( header, tmpstr );
  695.     }
  696.     strcat( header, "X-Mailer: <WinNT's Blat ver 1.0>\r\n" );
  697.     strcat( header, "\r\n" );
  698.  
  699.     headerlen = strlen( header );
  700.  
  701.     //get the text of the file into a string buffer
  702.     HANDLE fileh;
  703.     if((fileh=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
  704.                          FILE_FLAG_SEQUENTIAL_SCAN,NULL))==INVALID_HANDLE_VALUE)
  705.     {
  706.      cout<<"error reading "<<filename<<", aborting\n";        
  707.      delete [] Recipients;
  708.      return 3;
  709.     }
  710.     if(GetFileType(fileh)!=FILE_TYPE_DISK)
  711.     {
  712.      cout<<"Sorry, I can only mail messages from disk files...\n";        
  713.      delete [] Recipients;
  714.      return 4;
  715.     }
  716.     DWORD filesize = GetFileSize( fileh,NULL );
  717.     char *buffer = new char[filesize+headerlen+1];
  718.     char *tmpptr;
  719.  
  720.     // put the header at the top...
  721.     strcpy( buffer, header );
  722.     // point to the end of the header
  723.     tmpptr = buffer + headerlen;
  724.     // and put the whole file there
  725.     DWORD dummy;
  726.     if(!ReadFile(fileh,tmpptr,filesize,&dummy,NULL))
  727.     {
  728.      cout<<"error reading "<<filename<<", aborting\n";
  729.      CloseHandle(fileh);
  730.      delete [] buffer;        
  731.      delete [] Recipients;
  732.      return 5;
  733.     }
  734.     CloseHandle(fileh);
  735.         
  736.     cout<<"Sending "<<filename<<" to "<<(lstrlen(Recipients)?
  737.         Recipients:"<unspecified>")<<'\n';
  738.     if(lstrlen(subject))
  739.         cout<<"Subject:"<<subject<<'\n';
  740.     if(lstrlen(loginname))
  741.         cout<<"Login name is "<<loginname<<'\n';
  742.  
  743.   if( !prepare_smtp_message( loginname, Recipients ) )
  744.   {
  745.    if( !send_smtp_edit_data( buffer ) )
  746.     finish_smtp_message();
  747.    close_smtp_socket();
  748.   }
  749.  
  750.   delete [] buffer;
  751.   delete [] Recipients;
  752.   return 0;
  753. }
  754.  
  755.  
  756.  
  757.  
  758.