home *** CD-ROM | disk | FTP | other *** search
/ Internet Tools (CDV) / cdv_internet_tools.iso / KATALOG / ARCHIV / EMAIL / W21364.ZIP / BLAT.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-04  |  35.4 KB  |  1,323 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. #ifdef GENSOCK_STATIC_LINK
  17. HANDLE  dll_module_handle=0;
  18. #else
  19. HANDLE    gensock_lib = 0;
  20. #endif
  21.  
  22. int (FAR PASCAL *pgensock_connect) (char FAR * hostname, char FAR * service, socktag FAR * pst);
  23. int (FAR PASCAL *pgensock_getchar) (socktag st, int wait, char FAR * ch);
  24. int (FAR PASCAL *pgensock_put_data) (socktag st, char FAR * data, unsigned long length);
  25. int (FAR PASCAL *pgensock_close) (socktag st);
  26. int (FAR PASCAL *pgensock_gethostname) (char FAR * name, int namelen);
  27. int (FAR PASCAL *pgensock_put_data_buffered) (socktag st, char FAR * data, unsigned long length);
  28. int (FAR PASCAL *pgensock_put_data_flush) (socktag st);
  29.  
  30.  
  31. socktag SMTPSock;
  32. #define SERVER_SIZE    256     // #defines (bleah!) from Beverly Brown "beverly@datacube.com"
  33. #define SENDER_SIZE    256
  34. char SMTPHost[SERVER_SIZE];
  35. char Sender[SENDER_SIZE];
  36. char *Recipients;
  37. char my_hostname[1024];
  38. char *destination="";
  39. char *cc_list="";
  40. char *bcc_list="";
  41. char *loginname="";
  42. char *senderid="";
  43. char *subject="";
  44. int mime=0;
  45. int quiet=0;
  46. int uuencode=0;
  47. int base64=0;
  48. char my_hostname_wanted[1024]="";
  49.  
  50. char *usage[]=
  51. {
  52.  "Blat v1.7: WinNT console utility to mail a file via SMTP", 
  53.  "by P.Mendes, M.Neal, G.Vollant - http://gepasi.dbs.aber.ac.uk/softw/blat.html",
  54.  "syntax:",
  55.  "  Blat <filename> -t <recipient> [optional switches (see below)]",
  56.  "  Blat -install <server addr> <sender's addr> [-q]",
  57.  "  Blat -h [-q]",
  58. /* "",*/
  59.  "-install <server addr> <sender's addr>: set's default SMTP server and sender",
  60. /* "",*/
  61.  "<filename>     : file with the message body ('-' for console input,end with ^Z)",
  62.  "-t <recipient> : recipient list (comma separated)",
  63.  "-s <subj>      : subject line",
  64.  "-f <sender>    : overrides the default sender address (must be known to server)",
  65.  "-i <addr>      : a 'From:' address, not necessarily known to the SMTP server.",
  66.  "-c <recipient> : carbon copy recipient list (comma separated)",
  67.  "-b <recipient> : blind carbon copy recipient list (comma separated)",
  68.  "-h             : displays this help.",
  69.  "-mime          : MIME Quoted-Printable Content-Transfer-Encoding.",
  70.  "-q             : supresses *all* output.",
  71.  "-server <addr> : overrides the default SMTP server to be used.",
  72.  "-hostname <hst>: select the hostname used to send the message",
  73.  "-uuencode      : Send (binary) file UUEncoded",
  74.  "-base64        : Send (binary) file using base64 (binary Mime)",
  75.  "Note that if the '-i' option is used, <sender> is included in 'Reply-to:'",
  76.  "and 'Sender:' fields in the header of the message."
  77. };
  78. const NMLINES=22;
  79.  
  80. void
  81. gensock_error (char * function, int retval)
  82. {
  83.  if( ! quiet )
  84.  {
  85.   switch( retval )
  86.   {
  87.    case 4001: printf("Error: Malloc failed (possibly out of memory)."); break;
  88.    case 4002: printf("Error: Error sending data."); break;
  89.    case 4003: printf("Error: Error initializing gensock.dll."); break;
  90.    case 4004: printf("Error: Version not supported."); break;
  91.    case 4005: printf("Error: The winsock version specified by gensock is not supported by this winsock.dll."); break;
  92.    case 4006: printf("Error: Network not ready."); break;
  93.    case 4007: printf("Error: Can't resolve (mailserver) hostname."); break;
  94.    case 4008: printf("Error: Can't create a socket (too many simultaneous links?)"); break;
  95.    case 4009: printf("Error: Error reading socket."); break;
  96.    case 4010: printf("Error: Not a socket."); break;
  97.    case 4011: printf("Error: Busy."); break;
  98.    case 4012: printf("Error: Error closing socket."); break;
  99.    case 4013: printf("Error: Wait a bit (possible timeout)."); break;
  100.    case 4014: printf("Error: Can't resolve service."); break;
  101.    case 4015: printf("Error: Can't connect to mailserver (timed out if winsock.dll error 10060)"); break;
  102.    case 4016: printf("Error: Connection to mailserver was dropped."); break;
  103.    case 4017: printf("Error: Mail server refused connection."); break;
  104.    default:   printf("error %d in function '%s'", retval, function);
  105.   }
  106.  }
  107. }
  108.  
  109. // loads the GENSOCK DLL file
  110. int load_gensock()
  111. {
  112.   #ifdef GENSOCK_STATIC_LINK
  113.     pgensock_connect = gensock_connect;
  114.     pgensock_getchar = gensock_getchar ;
  115.     pgensock_put_data = gensock_put_data;
  116.     pgensock_close = gensock_close;
  117.     pgensock_gethostname=gensock_gethostname;
  118.     pgensock_put_data_buffered=gensock_put_data_buffered;
  119.     pgensock_put_data_flush=gensock_put_data_flush;
  120.     dll_module_handle = GetModuleHandle (NULL);
  121.   #else
  122.   if( (gensock_lib = LoadLibrary("gwinsock.dll")) == NULL )
  123.   {
  124.    if( (gensock_lib = LoadLibrary("gensock.dll")) == NULL )
  125.    {
  126.     if( ! quiet )
  127.      printf("Couldn't load either 'GWINSOCK.DLL' or 'GENSOCK.DLL'\nInstall one of these in your path.");
  128.     return -1;
  129.    }
  130.   }
  131.  
  132.   if( 
  133.      ( pgensock_connect = 
  134.       (  int (FAR PASCAL *)(char FAR *, char FAR *, socktag FAR *) )
  135.       GetProcAddress(gensock_lib, "gensock_connect")
  136.      ) == NULL
  137.     )
  138.   {
  139.    if( ! quiet )
  140.     printf("couldn't getprocaddress for gensock_connect\n");
  141.    return -1;
  142.   }
  143.  
  144.   if (
  145.       ( pgensock_getchar =
  146.        ( int (FAR PASCAL *) (socktag, int, char FAR *) )
  147.        GetProcAddress(gensock_lib, "gensock_getchar")
  148.       ) == NULL
  149.      )
  150.   {
  151.    if( ! quiet )
  152.     printf("couldn't getprocaddress for gensock_getchar\n");
  153.    return -1;
  154.   }
  155.  
  156.   if(
  157.      ( pgensock_put_data =
  158.        ( int (FAR PASCAL *) (socktag, char FAR *, unsigned long) )
  159.        GetProcAddress(gensock_lib, "gensock_put_data")
  160.      ) == NULL
  161.     )
  162.   {
  163.    if( ! quiet )
  164.     printf("couldn't getprocaddress for gensock_put_data\n");
  165.    return -1;
  166.   }
  167.  
  168.   if(
  169.      ( pgensock_close =
  170.        (int (FAR PASCAL *) (socktag) )
  171.        GetProcAddress(gensock_lib, "gensock_close")
  172.      ) == NULL
  173.     )
  174.   {
  175.    if( ! quiet )
  176.     printf("couldn't getprocaddress for gensock_close\n");
  177.    return -1;
  178.   }
  179.  
  180.   if(
  181.      ( pgensock_gethostname =
  182.        (int (FAR PASCAL *) (char FAR *, int) )       
  183.        GetProcAddress(gensock_lib, "gensock_gethostname")
  184.      ) == NULL
  185.     )
  186.   {
  187.    if( ! quiet )
  188.     printf("couldn't getprocaddress for gensock_gethostname\n");
  189.    return -1;
  190.   }
  191.  
  192.   if(
  193.      ( pgensock_put_data_buffered =
  194.        ( int (FAR PASCAL *) (socktag, char FAR *, unsigned long) )
  195.        GetProcAddress(gensock_lib, "gensock_put_data_buffered")
  196.      ) == NULL
  197.     )
  198.   {
  199.    if( ! quiet )
  200.     printf("couldn't getprocaddress for gensock_put_data_buffered\n");
  201.    return -1;
  202.   }
  203.  
  204.   if(
  205.      ( pgensock_put_data_flush =
  206.        ( int (FAR PASCAL *) (socktag) )
  207.        GetProcAddress(gensock_lib, "gensock_put_data_flush")
  208.      ) == NULL
  209.     )
  210.   {
  211.    if( ! quiet )
  212.     printf("couldn't getprocaddress for gensock_put_data_flush\n");
  213.    return -1;
  214.   }
  215.   #endif
  216.   return 0;
  217. }
  218.  
  219. int open_smtp_socket( void )
  220. {
  221.   int retval;
  222.   char SMTPHostWithoutPort[SERVER_SIZE];
  223.   char *port=NULL;
  224.   char *browseSMTPHost;
  225.  
  226.   strcpy(SMTPHostWithoutPort,SMTPHost);
  227.   browseSMTPHost = SMTPHostWithoutPort;
  228.   while ((*browseSMTPHost) != '\0')
  229.   {
  230.       if ((*browseSMTPHost) == ':')
  231.       {
  232.           *browseSMTPHost = '\0';
  233.           port = browseSMTPHost + 1;
  234.           break;
  235.       }
  236.       browseSMTPHost++;
  237.   }
  238.  
  239.  
  240.   /* load the library if it's not loaded */
  241. //  if (!gensock_lib)
  242.     if ( ( retval = load_gensock() ) ) return ( retval );
  243.  
  244.   if ( (retval = (*pgensock_connect) ((LPSTR) SMTPHostWithoutPort,
  245.                      (LPSTR)((port==NULL) ? "smtp" : port),
  246.                      &SMTPSock)))
  247.   {
  248.     if (retval == ERR_CANT_RESOLVE_SERVICE)
  249.     {
  250.      if ((retval = (*pgensock_connect) ((LPSTR)SMTPHostWithoutPort,
  251.                      (LPSTR)((port==NULL) ? "25" : port),
  252.                      &SMTPSock)))
  253.      {
  254.        gensock_error ("gensock_connect", retval);
  255.        return -1;
  256.      }
  257.     }
  258.   // error other than can't resolve service 
  259.     else
  260.     {
  261.      gensock_error ("gensock_connect", retval);
  262.      return -1;
  263.     }
  264.   }
  265.  
  266.   // we wait to do this until here because WINSOCK is
  267.   // guaranteed to be already initialized at this point.
  268.  
  269.   // get the local hostname (needed by SMTP) 
  270.   if ((retval = (*pgensock_gethostname) (my_hostname, sizeof(my_hostname))))
  271.   {
  272.     gensock_error ("gensock_gethostname", retval);
  273.     return -1;
  274.   }
  275.   return 0;
  276. }
  277.  
  278.  
  279. int close_smtp_socket( void )
  280. {
  281.   int retval;
  282.  
  283.   if( (retval = (*pgensock_close) (SMTPSock)) )
  284.   {
  285.     gensock_error ("gensock_close", retval);
  286.     return -1;
  287.   }
  288.   #ifdef GENSOCK_STATIC_LINK
  289.   #else
  290.   FreeLibrary( gensock_lib );
  291.   #endif
  292.   return (0);
  293. }
  294.  
  295. int get_smtp_line( void )
  296. {
  297.   char ch = '.';
  298.   char in_data [MAXOUTLINE];
  299.   char * index;
  300.   int retval = 0;
  301.  
  302.   index = in_data;
  303.  
  304.   while (ch != '\n')
  305.   {
  306.    if( (retval = (*pgensock_getchar) (SMTPSock, 0, &ch) ) )
  307.    {
  308.       gensock_error ("gensock_getchar", retval);
  309.       return -1;
  310.     }
  311.     else
  312.     {
  313.       *index = ch;
  314.       index++;
  315.     }
  316.   }
  317.  
  318.   /* this is to support multi-line responses, common with */
  319.   /* servers that speak ESMTP */
  320.  
  321.   /* I know, I know, it's a hack 8^) */
  322.   if( in_data[3] == '-' ) return( get_smtp_line() );
  323.   else return atoi(in_data);
  324. }
  325.  
  326. int put_smtp_line( socktag sock, char far * line, unsigned int nchars )
  327. {
  328.   int retval;
  329.  
  330.   if( (retval = (*pgensock_put_data) (sock, line, (unsigned long) nchars)))
  331.   {
  332.     gensock_error ("gensock_put_data", retval);
  333.     return -1;
  334.   }
  335.   return (0);
  336. }
  337.  
  338. int putline_internal (socktag sock, char * line, unsigned int nchars)
  339. {
  340.   int retval;
  341.  
  342.   if ((retval =
  343.        (*pgensock_put_data) (sock,
  344.                 (char FAR *) line,
  345.                 (unsigned long) nchars)))
  346.   {
  347.     switch (retval)
  348.     {
  349.      case ERR_NOT_CONNECTED:
  350.       gensock_error( "SMTP server has closed the connection", retval );
  351.       break;
  352.  
  353.      default:
  354.       gensock_error ("gensock_put_data", retval);
  355.     }
  356.     return -1;
  357.   }
  358.   return (0);
  359. }
  360.  
  361. void smtp_error (char * message)
  362. {
  363.  if( ! quiet )
  364.   printf("%s\n",message);
  365.  put_smtp_line (SMTPSock, "QUIT\r\n", 6);
  366.  // this is to wait for the 221 response from the server
  367.  get_smtp_line();
  368.  close_smtp_socket();
  369. }
  370.  
  371.  
  372. // 'destination' is the address the message is to be sent to
  373. // 'message' is a pointer to a null-terminated 'string' containing the 
  374. // entire text of the message. 
  375.  
  376. int prepare_smtp_message(char * MailAddress, char * destination, 
  377.                          const char* wanted_hostname)
  378. {
  379.   char out_data[MAXOUTLINE];
  380.   char str[1024];
  381.   char *ptr;
  382.   int len, startLen;
  383.  
  384.   if (wanted_hostname!=NULL)
  385.       if ((*wanted_hostname)=='\0')
  386.           wanted_hostname=NULL;
  387.  
  388.   if ( open_smtp_socket() ) return -1;
  389.  
  390.   if ( get_smtp_line() != 220 )
  391.   {
  392.     smtp_error ("SMTP server error");
  393.     return(-1);
  394.   }
  395.  
  396.   sprintf( out_data, "HELO %s\r\n", 
  397.       (wanted_hostname==NULL) ? my_hostname  : wanted_hostname);
  398.   put_smtp_line( SMTPSock, out_data, strlen (out_data) );
  399.  
  400.   if ( get_smtp_line() != 250 )
  401.   {
  402.     smtp_error ("SMTP server error");
  403.     return -1;
  404.   }
  405.  
  406.   sprintf (out_data, "MAIL From:<%s>\r\n", loginname);
  407.   put_smtp_line( SMTPSock, out_data, strlen (out_data) );
  408.  
  409.   if (get_smtp_line() != 250)
  410.   {
  411.     smtp_error ("The mail server doesn't like the sender name,\nhave you set your mail address correctly?");
  412.     return -1;
  413.   }
  414.  
  415.   // do a series of RCPT lines for each name in address line
  416.   for (ptr = destination; *ptr; ptr += len + 1)
  417.   {
  418.     // if there's only one token left, then len will = startLen,
  419.     // and we'll iterate once only
  420.     startLen = strlen (ptr);
  421.     if ((len = strcspn (ptr, " ,\n\t\r")) != startLen)
  422.     {
  423.       ptr[len] = '\0';            // replace delim with NULL char
  424.       while (strchr (" ,\n\t\r", ptr[len+1]))    // eat white space
  425.         ptr[len++] = '\0';
  426.     }
  427.  
  428.     sprintf (out_data, "RCPT To: <%s>\r\n", ptr);
  429.     putline_internal( SMTPSock, out_data, strlen (out_data) );
  430.  
  431.     if (get_smtp_line() != 250)
  432.     {
  433.       sprintf (str, "The mail server doesn't like the name %s.\nHave you set the 'To: ' field correctly?", ptr);
  434.       smtp_error (str);
  435.       return -1;
  436.     }
  437.  
  438.     if (len == startLen)    // last token, we're done
  439.       break;
  440.   }
  441.  
  442.   sprintf (out_data, "DATA\r\n");
  443.   put_smtp_line (SMTPSock, out_data, strlen (out_data));
  444.  
  445.   if (get_smtp_line() != 354)
  446.   {
  447.     smtp_error ("Mail server error accepting message data");
  448.     return -1;
  449.   }
  450.  
  451.   return(0);
  452.  
  453. }
  454.  
  455. int transform_and_send_edit_data( socktag sock, char * editptr )
  456. {
  457.   char *index;
  458.   char *header_end;
  459.   char previous_char = 'x';
  460.   unsigned int send_len;
  461.   int retval;
  462.   BOOL done = 0;
  463.  
  464.   send_len = lstrlen(editptr);
  465.   index = editptr;
  466.  
  467.   header_end = strstr (editptr, "\r\n\r\n");
  468.  
  469.   while (!done)
  470.   {
  471.     // room for extra char for double dot on end case
  472.     while ((unsigned int) (index - editptr) < send_len)
  473.     {
  474.       switch (*index)
  475.       {
  476.        case '.':
  477.                  if (previous_char == '\n')
  478.                   /* send _two_ dots... */
  479.                   if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) return (retval);
  480.                    if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) return (retval);
  481.                  break;
  482.        case '\r':
  483.                  // watch for soft-breaks in the header, and ignore them
  484.                  if (index < header_end && (strncmp (index, "\r\r\n", 3) == 0))
  485.                    index += 2;
  486.                  else
  487.                   if (previous_char != '\r')
  488.                    if ((retval = (*pgensock_put_data_buffered) (sock, index, 1)))
  489.                     return (retval);
  490.                   // soft line-break (see EM_FMTLINES), skip extra CR */
  491.                  break;
  492.        default:
  493.                if ((retval = (*pgensock_put_data_buffered) (sock, index, 1)))
  494.                 return (retval);
  495.       }
  496.       previous_char = *index;
  497.       index++;
  498.     }
  499.     if( (unsigned int) (index - editptr) == send_len) done = 1;
  500.   }
  501.  
  502.   // this handles the case where the user doesn't end the last
  503.   // line with a <return>
  504.  
  505.   if (editptr[send_len-1] != '\n')
  506.   {
  507.     if ((retval = (*pgensock_put_data_buffered) (sock, "\r\n.\r\n", 5)))
  508.       return (retval);
  509.   }
  510.   else
  511.     if ((retval = (*pgensock_put_data_buffered) (sock, ".\r\n", 3)))
  512.       return (retval);
  513.  
  514.   /* now make sure it's all sent... */
  515.   if ((retval = (*pgensock_put_data_flush)(sock))) return (retval);
  516.   return (TRUE);
  517. }
  518.  
  519.  
  520.  
  521. int send_smtp_edit_data (char * message)
  522. {
  523.   transform_and_send_edit_data( SMTPSock, message );
  524.  
  525.   if (get_smtp_line() != 250)
  526.   {
  527.     smtp_error ("Message not accepted by server");
  528.     return -1;
  529.   }
  530.   return(0);
  531. }
  532.  
  533.  
  534. int finish_smtp_message( void )
  535. {
  536.   int ret;
  537.  
  538.   ret = put_smtp_line( SMTPSock, "QUIT\r\n", 6 );
  539.   // wait for a 221 message from the server
  540.   get_smtp_line();
  541.   return ret; 
  542. }
  543.  
  544. // create a registry entries for this program 
  545. int CreateRegEntry( void )
  546. {
  547.   HKEY  hKey1;
  548.   DWORD  dwDisposition;
  549.   LONG   lRetCode;
  550.  
  551.   /* try to create the .INI file key */
  552.   lRetCode = RegCreateKeyEx ( HKEY_LOCAL_MACHINE,
  553.                               "SOFTWARE\\Public Domain\\Blat",
  554.                               0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE,NULL, &hKey1,&dwDisposition
  555.                             );
  556.  
  557.   /* if we failed, note it, and leave */
  558.   if (lRetCode != ERROR_SUCCESS)
  559.   {
  560.     if( ! quiet ) printf ("Error in creating blat key in the registry\n");
  561.     return 10;
  562.   }
  563.  
  564.   /* try to set a section value */
  565.   lRetCode = RegSetValueEx( hKey1,"SMTP server",0,REG_SZ, (BYTE *) &SMTPHost[0], (strlen(SMTPHost)+1));
  566.  
  567.   /* if we failed, note it, and leave */
  568.   if (lRetCode != ERROR_SUCCESS)
  569.   {
  570.     if( ! quiet ) printf ( "Error in setting SMTP server value in the registry\n");
  571.     return 11;
  572.   }
  573.   
  574.   /* try to set another section value */
  575.   lRetCode = RegSetValueEx( hKey1,"Sender",0,REG_SZ, (BYTE *) &Sender[0], (strlen(Sender)+1));
  576.  
  577.   /* if we failed, note it, and leave */
  578.   if (lRetCode != ERROR_SUCCESS)
  579.   {
  580.    if( ! quiet ) printf ( "Error in setting sender address value in the registry\n");
  581.     return 11;
  582.   }
  583.   
  584.   return 0;
  585. }
  586.  
  587. // get the registry entries for this program 
  588. int GetRegEntry( void )
  589. {
  590.   HKEY  hKey1;
  591.   DWORD  dwType;
  592.   DWORD  dwBytesRead;
  593.   LONG   lRetCode;
  594.  
  595.   // open the registry key in read mode
  596.   lRetCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  597.                            "SOFTWARE\\Public Domain\\Blat",
  598.                            0, KEY_READ, &hKey1
  599.                          );
  600.   if( lRetCode != ERROR_SUCCESS )
  601.   {
  602. //     if( ! quiet ) printf( "Failed to open registry key for Blat\n" );
  603.      return 12;
  604.   }
  605.   // set the size of the buffer to contain the data returned from the registry
  606.   // thanks to Beverly Brown "beverly@datacube.com" and "chick@cyberspace.com" for spotting it...
  607.   dwBytesRead=SERVER_SIZE;
  608.   // read the value of the SMTP server entry
  609.   lRetCode = RegQueryValueEx( hKey1, "SMTP server", NULL , &dwType, (BYTE *) &SMTPHost, &dwBytesRead); 
  610.   // if we failed, note it, and leave
  611.   if( lRetCode != ERROR_SUCCESS )
  612.   {
  613. //    if( ! quiet ) printf( "Failed to read SMTP server value from the registry\n" );
  614.     return 12;
  615.   }
  616.  
  617.   dwBytesRead=SENDER_SIZE;
  618.   // read the value of the SMTP server entry
  619.   lRetCode = RegQueryValueEx( hKey1, "Sender", NULL , &dwType, (BYTE *) &Sender, &dwBytesRead); 
  620.   // if we failed, note it, and leave
  621.   if( lRetCode != ERROR_SUCCESS )
  622.   {
  623. //    if( ! quiet ) printf( "Failed to read senders user name from the registry\n" );
  624.     return 12;
  625.   }
  626.  
  627.  return 0;
  628. }
  629.  
  630. LPCSTR GetNameWithoutPath(LPCSTR lpFn)
  631. {
  632. LPCSTR lpRet = lpFn ;
  633. LPCSTR lpNext ;
  634.   while ((*lpFn) != '\0')
  635.     {
  636.       if (((*lpFn) == ':') || ((*lpFn) == '\\')) lpRet = lpFn + 1;
  637.       lpNext=CharNext(lpFn);
  638.       lpFn = lpNext;
  639.     }
  640.   return lpRet;
  641. }
  642.  
  643. void douuencode(const char * filebuffer,char * tmpptr,DWORD filesize,const char* filename)
  644. {
  645.     char *sz=tmpptr;
  646.     sprintf(tmpptr,"begin 644 %s\x0d\x0a",GetNameWithoutPath(filename));
  647.     tmpptr += strlen(tmpptr);
  648.     while (filesize>0)
  649.     {
  650.         DWORD size_line = filesize;
  651.         if (size_line>45)
  652.             size_line=45;
  653.         filesize -= size_line;
  654.         *(tmpptr++) = ' ' + ((char)size_line);
  655.  
  656.         while (size_line>0)
  657.         {
  658.             *(tmpptr) = ((*(filebuffer) >> 2) & 0x3f) + 0x20;
  659.             if ((*tmpptr)==' ')
  660.                 *tmpptr='\x60';
  661.             tmpptr++;
  662.  
  663.             *(tmpptr) = (((*(filebuffer) << 4) & 060 | (*(filebuffer+1) >> 4) & 017) & 0x3f) + 0x20;
  664.             if ((*tmpptr)==' ')
  665.                 *tmpptr='\x60';
  666.             tmpptr++;
  667.  
  668.             *(tmpptr) = (((*(filebuffer+1) << 2) & 074 | (*(filebuffer+2) >> 6) & 03)  & 0x3f) + 0x20;
  669.             if ((*tmpptr)==' ')
  670.                 *tmpptr='\x60';
  671.             tmpptr++;
  672.  
  673.             *(tmpptr) = ((*(filebuffer+2) & 077) & 0x3f) + 0x20;
  674.             if ((*tmpptr)==' ')
  675.                 *tmpptr='\x60';
  676.             tmpptr++;
  677.  
  678.             filebuffer += 3;
  679.             if (size_line<3)
  680.                 size_line = 0;
  681.             else
  682.                 size_line -= 3;
  683.         }
  684.         *(tmpptr++) = '\x0d';
  685.         *(tmpptr++) = '\x0a';
  686.     }
  687.     strcpy(tmpptr,"\x60\x0d\x0a\x65\x6e\x64\x0d\x0a");
  688. }
  689.  
  690.  
  691. /*
  692.  * Encode a file into one or more MIME messages, each
  693.  * no larger than 'maxsize'.  A 'maxsize' of zero means no size limit.
  694.  * If 'applefile' is non-null, it is the first part of a multipart/appledouble
  695.  * pair.
  696.  */
  697. void dobase64(const char * filebuffer,char * tmpptr,DWORD filesize,const char* /* filename */)
  698. {
  699.     static char basis_64[] =
  700.        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  701.     char *sz=tmpptr;
  702.     
  703.     tmpptr += strlen(tmpptr);
  704.     while (filesize>0)
  705.     {
  706.         DWORD size_line = filesize;
  707.         if (size_line>54)
  708.             size_line=54;
  709.         filesize -= size_line;
  710.         // *(tmpptr++) = ' ' + ((char)size_line); */
  711.  
  712.         while (size_line>0)
  713.         {
  714.             *(tmpptr++) = basis_64[((*(filebuffer) >> 2) & 0x3f)] ;
  715.  
  716.             *(tmpptr++) = basis_64[(((*(filebuffer) << 4) & 060 | (*(filebuffer+1) >> 4) & 017) & 0x3f)] ;
  717.  
  718.             if (size_line>1)
  719.                 *(tmpptr++) = basis_64[(((*(filebuffer+1) << 2) & 074 | (*(filebuffer+2) >> 6) & 03)  & 0x3f)] ;
  720.             else
  721.                 *(tmpptr++) = '=';
  722.  
  723.             if (size_line>2)
  724.                 *(tmpptr++) = basis_64[((*(filebuffer+2) & 077) & 0x3f)] ;
  725.             else
  726.                 *(tmpptr++) = '=';
  727.  
  728.             filebuffer += 3;
  729.             if (size_line<3)
  730.                 size_line = 0;
  731.             else
  732.                 size_line -= 3;
  733.         }
  734.         *(tmpptr++) = '\x0d';
  735.         *(tmpptr++) = '\x0a';
  736.     }
  737.     *(tmpptr) = '\x0';
  738. }
  739.  
  740. // MIME Quoted-Printable Content-Transfer-Encoding
  741. #define MimeHexChar "0123456789ABCDEF"; 
  742. void ConvertToQuotedPrintable(char ThisChar, int * CurrPos, char * buffer) {
  743. int ThisValue;
  744. div_t result;
  745. // char buffer[8];
  746. char HexTable[17] = MimeHexChar;
  747.     
  748.     ThisValue = (256 + (unsigned int) ThisChar) % 256; 
  749.  
  750.     if    (ThisValue == 13) {
  751.         sprintf( buffer, "%s", "\0" );
  752.         return;
  753.     }
  754.     else if    (ThisValue == 10) {
  755.         sprintf( buffer, "%s", "\r\n" );
  756.         (*CurrPos) = 0;
  757.         return;
  758.     }
  759.     else if ((ThisValue < 33) | 
  760.             (ThisValue == 61) | 
  761.             (ThisValue > 126)) {
  762.         result = div(ThisValue,16); 
  763.         buffer[0] = '=';
  764.         (*CurrPos)++;
  765.         buffer[1] = HexTable[result.quot];
  766.         (*CurrPos)++;
  767.         buffer[2] = HexTable[result.rem];
  768.          (*CurrPos)++;
  769.         buffer[3] = '\0';
  770.     }
  771.     else {
  772.         buffer[0] = ThisChar;
  773.         (*CurrPos)++;
  774.         buffer[1] = '\0';
  775.     } 
  776.  
  777.        if (*CurrPos > 71) {
  778.         strcat(buffer, "=\r\n");     /* Add soft line break */
  779.         (*CurrPos) = 0;
  780.     }
  781. }
  782.  
  783.  
  784. int main( int argc,        /* Number of strings in array argv          */
  785.            char *argv[],    /* Array of command-line argument strings   */
  786.            char **envp )    /* Array of environment variable strings    */
  787. {
  788.  int next_arg=2;
  789.  int impersonating = 0;
  790.  int penguin = 0;
  791.  int i, j;
  792.  int retcode, regerr;
  793.  char tempdir[MAX_PATH+1];
  794.  char tempfile[MAX_PATH+1];
  795.  HANDLE fileh;
  796.  FILE *tf;
  797.  int hours, minutes;
  798.  OFSTRUCT of;
  799.  
  800.  
  801.  // by default Blat is very noisy!
  802.  quiet = 0;
  803.  
  804. // by default Blat does not use mime Quoted-Printable Content-Transfer-Encoding!
  805.  mime = 0;
  806.  
  807.  // by default Blat does not use UUEncode
  808.  uuencode= 0;
  809.  
  810.  // no tempfile so far...
  811.  tempfile[0] = '\0';
  812.  
  813.  if(argc<2)
  814.  {
  815.   // must have at least file name to send
  816.   for(i=0;i<NMLINES;i++) printf("%s\n",usage[i]);
  817.   return 1;
  818.  }
  819.  
  820.  for( i=1; i < argc; i++ ) {
  821.   if( lstrcmpi( "-q",argv[i] ) == 0 ) quiet = 1;
  822.   if( lstrcmpi( "-mime",argv[i] ) == 0 ) mime = 1;
  823.   if( lstrcmpi( "-uuencode",argv[i] ) == 0 ) uuencode = 1;
  824.   if( lstrcmpi( "-base64",argv[i] ) == 0 ) base64 = 1;
  825.  }
  826.  
  827.  // get file name from argv[1]
  828.  char *filename=argv[1];
  829.  
  830.  Sender[0] = '\0';
  831.  SMTPHost[0] = '\0';
  832.  
  833.  regerr = GetRegEntry();
  834.  
  835.  senderid  = Sender;
  836.  loginname = Sender;
  837.         
  838.  // thanks to Beverly Brown "beverly@datacube.com" for
  839.  // fixing the argument parsing, I "fixed" the brackets
  840.  // to conform approximately to our "style"  :-)
  841.  // Starts here
  842.  for(next_arg=1;next_arg < argc;next_arg++)
  843.  {
  844.     if(lstrcmpi("-h",argv[next_arg])==0)
  845.     {
  846.      if( ! quiet ) for(int i=0;i<NMLINES;i++) printf("%s\n",usage[i]);
  847.      return 1;
  848.     }
  849.  
  850.           // is argv[2] "-install"? If so, indicate error and return
  851.     else if(lstrcmpi("-install",argv[next_arg])==0)
  852.     {
  853.        if((argc == 3) || (argc == 4)) 
  854.              {
  855.             strcpy( SMTPHost, argv[++next_arg] );
  856.              if(argc == 4) 
  857.                  strcpy( Sender, argv[++next_arg] );
  858.             else
  859.                 strcpy( Sender, "" );
  860.              if( CreateRegEntry() == 0 ) 
  861.                  {
  862.                    if( ! quiet ) printf("\nSMTP server set to %s\n", SMTPHost );
  863.                  regerr = 0;
  864.                   return 0;
  865.                  }
  866.              }
  867.        else
  868.           {
  869.            if( ! quiet )
  870.             printf( "to set the SMTP server's address and the user name at that address do:\nblat -install server username");
  871.              return 6;
  872.           }
  873.     }
  874.  
  875.         // is argv[2] "-s"? If so, argv[3] is the subject
  876.     else if(lstrcmpi("-s",argv[next_arg])==0)
  877.     {
  878.      subject=argv[++next_arg];
  879.     }
  880.  
  881.        // is argv[2] "-c"? If so, argv[3] is the carbon-copy list
  882.     else if(lstrcmpi("-c",argv[next_arg])==0)
  883.     {
  884.      cc_list=argv[++next_arg];
  885.     }
  886.  
  887.        // is argv[2] "-b"? If so, argv[3] is the blind carbon-copy list
  888.     else if(lstrcmpi("-b",argv[next_arg])==0)
  889.     {
  890.      bcc_list=argv[++next_arg];
  891.     }
  892.  
  893.         // is next argv "-t"? If so, succeeding argv is the destination
  894.     else if(lstrcmpi("-t",argv[next_arg])==0)
  895.     {
  896.      destination=argv[++next_arg];
  897.     }
  898.  
  899.     // is next argv "-server"? If so, succeeding argv is the SMTPHost    
  900.     else if(lstrcmpi("-server",argv[next_arg])==0)
  901.     {
  902.      strcpy(SMTPHost,argv[++next_arg]);
  903.     }
  904.  
  905.     // is next argv "-hostname"? If so, succeeding argv is the SMTPHost    
  906.     else if(lstrcmpi("-hostname",argv[next_arg])==0)
  907.     {
  908.      strcpy(my_hostname_wanted,argv[++next_arg]);
  909.     }
  910.  
  911.      //is next argv '-f'? If so, succeeding argv is the loginname
  912.     else if(lstrcmp("-f",argv[next_arg])==0)
  913.       loginname=argv[++next_arg];
  914.  
  915.     else if(lstrcmp("-penguin",argv[next_arg])==0)
  916.     {
  917.      penguin = 1;
  918.     }
  919.     
  920.     // if next arg is a '-mime' just increase and continue looking
  921.     // we have already dealt with -mime at the beggining
  922.     else if(lstrcmp("-mime",argv[next_arg])==0)
  923.     {
  924.      next_arg++;
  925.     }
  926.     
  927.     // if next arg is a '-uuencode' just increase and continue looking
  928.     // we have already dealt with -uuencode at the beggining
  929.     else if(lstrcmp("-uuencode",argv[next_arg])==0)
  930.     {
  931.      next_arg++;
  932.     }
  933.     
  934.     // if next arg is a '-base64' just increase and continue looking
  935.     // we have already dealt with -base64 at the beggining
  936.     else if(lstrcmp("-base64",argv[next_arg])==0)
  937.     {
  938.      next_arg++;
  939.     }
  940.     
  941.     // if next arg is a '-q' just increase and continue looking
  942.     // we have already dealt with -q at the beggining
  943.     else if(lstrcmp("-q",argv[next_arg])==0)
  944.     {
  945.      next_arg++;
  946.     }
  947.  
  948.     //is next argv '-i'? If so, succeeding argv is the sender id
  949.     else if(lstrcmp("-i",argv[next_arg])==0)
  950.     {
  951.      senderid=argv[++next_arg];
  952.      impersonating = 1;
  953.     }
  954.     else if(next_arg == 1) 
  955.     {
  956.       if (lstrcmp(filename, "-") != 0)
  957.      {
  958.       if( lstrlen(filename)<=0 || OpenFile(filename,&of,OF_EXIST) == HFILE_ERROR )
  959.       {
  960.        if( ! quiet ) printf("%s does not exist\n",filename);
  961.         return 2;
  962.       }
  963.      }
  964.     } 
  965.     else 
  966.     {
  967.      if( ! quiet )
  968.       for(i=0;i<NMLINES;i++)
  969.         printf("%s\n",usage[i]);
  970.      return 1;
  971.     }
  972.  }
  973.  
  974.     if( regerr==12 ) printf( "Failed to open registry key for Blat\n" );
  975.  
  976.     // if we are not impersonating loginname is the same as the sender
  977.     if( ! impersonating )
  978.           senderid = loginname;
  979.  
  980.       // fixing the argument parsing
  981.       // Ends here
  982.  
  983.     if ((SMTPHost[0]=='\0')||(loginname[0]=='\0'))
  984.     {
  985.      if( ! quiet )
  986.      {
  987.       printf( "to set the SMTP server's address and the user name at that address do:\nblat -install server username\n");
  988.       printf( "or use '-server <server name>' and '-f <user name>'\n");
  989.       printf( "aborting, nothing sent\n" );
  990.      }
  991.      return 12;
  992.     }
  993.     
  994.     // make sure filename exists, get full pathname
  995.     if (lstrcmp(filename, "-") != 0)
  996.      if(lstrlen(filename)<=0 || OpenFile(filename,&of,OF_EXIST)==HFILE_ERROR)
  997.      {
  998.       if( ! quiet ) printf("%s does not exist\n",filename);
  999.       return 2;
  1000.      }
  1001.  
  1002.     // build temporary recipients list for parsing the "To:" line
  1003.     char *temp = new char [ strlen(destination) + strlen(cc_list) + strlen(bcc_list) + 4 ];
  1004.     // build the recipients list
  1005.     Recipients = new char [ strlen(destination) + strlen(cc_list) + strlen(bcc_list) + 4 ];
  1006.     
  1007.     // Parse the "To:" line
  1008.     for (i = j = 0; i < (int) strlen(destination); i++)
  1009.     {
  1010.       // strip white space
  1011.       while (destination[i]==' ')
  1012.         i++;
  1013.       // look for comments in brackets, and omit
  1014.       if (destination[i]=='(')
  1015.       {
  1016.         while (destination[i]!=')')
  1017.           i++;
  1018.         i++;
  1019.       }      
  1020.         // look for comments in quotes, and omit
  1021.         if (destination[i]=='\'')
  1022.       {
  1023.       i++;
  1024.         while (destination[i]!='\'')
  1025.           i++;
  1026.         i++;
  1027.       }      
  1028.       
  1029.       temp[j++] = destination[i];
  1030.     }
  1031.     temp[j] = '\0';               // End of list added! 
  1032.     strcpy( Recipients, temp);
  1033.  
  1034.     // Parse the "Cc:" line
  1035.     for (i = j = 0; i < (int) strlen(cc_list); i++)
  1036.     {
  1037.      // strip white space
  1038.      while (cc_list[i]==' ') i++;
  1039.      // look for comments in brackets, and omit
  1040.      if (cc_list[i]=='(')
  1041.      {
  1042.       while (cc_list[i]!=')') i++;
  1043.       i++;
  1044.      }      
  1045.        // look for comments in quotes, and omit
  1046.        if (cc_list[i]=='\'')
  1047.      {
  1048.       i++;
  1049.       while (cc_list[i]!='\'') i++;
  1050.       i++;
  1051.      }      
  1052.      temp[j++] = cc_list[i];
  1053.     }
  1054.     temp[j] = '\0';               // End of list added! 
  1055.     if( strlen(cc_list) > 0 )
  1056.     {
  1057.      strcat(Recipients, "," );
  1058.      strcat(Recipients, temp);
  1059.     }
  1060.  
  1061.     // Parse the "Bcc:" line
  1062.     for (i = j = 0; i < (int) strlen(bcc_list); i++)
  1063.     {
  1064.      // strip white space
  1065.      while (bcc_list[i]==' ') i++;
  1066.      // look for comments in brackets, and omit
  1067.      if (bcc_list[i]=='(')
  1068.      {
  1069.       while (bcc_list[i]!=')') i++;
  1070.       i++;
  1071.      }      
  1072.        // look for comments in quotes, and omit
  1073.        if (bcc_list[i]=='\'')
  1074.      {
  1075.       i++;
  1076.       while (bcc_list[i]!='\'') i++;
  1077.       i++;
  1078.      }      
  1079.      temp[j++] = bcc_list[i];
  1080.     }
  1081.     temp[j] = '\0';               // End of list added! 
  1082.     if( strlen(bcc_list) > 0 )
  1083.     {
  1084.      strcat(Recipients, "," );
  1085.      strcat(Recipients, temp);
  1086.     }
  1087.    
  1088.  
  1089.     // create a header for the message
  1090.     char tmpstr[0x200];
  1091.     char header[0x2000];
  1092.     int  headerlen;
  1093.     SYSTEMTIME curtime;
  1094.     TIME_ZONE_INFORMATION tzinfo;
  1095.     char * days[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
  1096.     char * months[] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  1097.     DWORD retval;
  1098.  
  1099.     GetLocalTime( &curtime );
  1100.     retval = GetTimeZoneInformation( &tzinfo );
  1101.     hours = (int) tzinfo.Bias / 60;
  1102.     minutes = (int) tzinfo.Bias % 60;
  1103.     if( retval == TIME_ZONE_ID_STANDARD ) 
  1104.     {
  1105.      hours += (int) tzinfo.StandardBias / 60;
  1106.      minutes += (int) tzinfo.StandardBias % 60;
  1107.     }
  1108.     else
  1109.       {
  1110.      hours += (int) tzinfo.DaylightBias / 60;
  1111.      minutes += (int) tzinfo.DaylightBias % 60;
  1112.     }
  1113.     
  1114.     // rfc1036 & rfc822 acceptable format
  1115.     // Mon, 29 Jun 94 02:15:23 GMT
  1116.     sprintf (tmpstr, "Date: %s, %.2d %s %.2d %.2d:%.2d:%.2d ",
  1117.       days[curtime.wDayOfWeek],
  1118.       curtime.wDay,
  1119.       months[curtime.wMonth - 1],
  1120.       curtime.wYear,
  1121.       curtime.wHour,
  1122.       curtime.wMinute,
  1123.       curtime.wSecond);
  1124.     strcpy( header, tmpstr );
  1125.  
  1126.     sprintf( tmpstr, "%+03d%02d", -hours, -minutes );
  1127.     //for(i=0;i<32;i++)
  1128.     //{
  1129.     // if( retval == TIME_ZONE_ID_STANDARD ) tmpstr[i] = (char) tzinfo.StandardName[i];
  1130.     // else tmpstr[i] = (char) tzinfo.DaylightName[i];
  1131.     //}
  1132.     strcat( header, tmpstr );
  1133.     strcat( header, "\r\n" );
  1134.     sprintf( tmpstr, "From: %s\r\n", senderid );
  1135.     strcat( header, tmpstr );
  1136.     if( impersonating )
  1137.     {
  1138.      sprintf( tmpstr, "Sender: %s\r\n", loginname );
  1139.      strcat( header, tmpstr );
  1140.     if (!(penguin == 1))
  1141.      {
  1142.      sprintf( tmpstr, "Reply-to: %s\r\n", loginname );
  1143.      strcat( header, tmpstr );
  1144.      }
  1145.     }
  1146.     if( *subject )
  1147.     {
  1148.      sprintf( tmpstr, "Subject: %s\r\n", subject );
  1149.      strcat( header, tmpstr );
  1150.     }
  1151.     else
  1152.     {
  1153.      if (!(penguin == 1))
  1154.      {
  1155.       if (lstrcmp(filename, "-") == 0)
  1156.        sprintf( tmpstr, "Subject: Contents of console input\r\n", filename );
  1157.       else
  1158.        sprintf( tmpstr, "Subject: Contents of file: %s\r\n", filename );
  1159.       strcat( header, tmpstr );
  1160.      }
  1161.     }
  1162.     
  1163.     sprintf( tmpstr, "To: %s\r\n", destination );
  1164.     strcat( header, tmpstr );
  1165.     if( *cc_list )
  1166.     {
  1167.      // Add line for the Carbon Copies
  1168.      sprintf( tmpstr, "Cc: %s\r\n", cc_list );
  1169.      strcat( header, tmpstr );
  1170.     }
  1171.  
  1172.     if ( mime ) 
  1173.     {
  1174.      // Indicate MIME version and type 
  1175.      sprintf( tmpstr, "MIME-Version: 1.0\r\n", cc_list );
  1176.      strcat( header, tmpstr );
  1177.      sprintf( tmpstr, "Content-Type: text/plain; charset=ISO-8859-1\r\n"  );
  1178.      strcat( header, tmpstr );
  1179.      sprintf( tmpstr, "Content-Transfer-Encoding: quoted-printable\r\n" );
  1180.      strcat( header, tmpstr );
  1181.     }
  1182.     else
  1183.     if ( base64 ) 
  1184.     {
  1185.      // Indicate MIME version and type 
  1186.      sprintf( tmpstr, "MIME-Version: 1.0\r\n", cc_list );
  1187.      strcat( header, tmpstr );
  1188.      sprintf( tmpstr, "Content-Type: application/octet-stream; name=\"%s\"\r\n",GetNameWithoutPath(filename)  );
  1189.      strcat( header, tmpstr );
  1190.      sprintf( tmpstr, "Content-Disposition: inline; filename=\"%s\"\r\n",GetNameWithoutPath(filename)  );
  1191.      strcat( header, tmpstr );
  1192.      sprintf( tmpstr, "Content-Transfer-Encoding: base64\r\n" );
  1193.      strcat( header, tmpstr );
  1194.     }
  1195.  
  1196.     strcat( header, "X-Mailer: <WinNT's Blat ver 1.7>\r\n" );
  1197.     
  1198.     if (!(penguin == 1))
  1199.         strcat( header, "\r\n" );
  1200.  
  1201.     headerlen = strlen( header );
  1202.  
  1203.     // if reading from the console, read everything into a temporary file first
  1204.     if (lstrcmp(filename, "-") == 0)
  1205.     {
  1206.      // create a unique temporary file name
  1207.      GetTempPath( MAX_PATH, tempdir );
  1208.      GetTempFileName( tempdir, "blt", 0, tempfile );
  1209.  
  1210.      // open the file in write mode
  1211.      tf = fopen(tempfile,"w");
  1212.      if( tf==NULL )
  1213.      {
  1214.       if( ! quiet ) printf("error opening temporary file %s, aborting\n",filename);
  1215.       delete [] Recipients;
  1216.       return 13;
  1217.      }
  1218.  
  1219.      do
  1220.      {
  1221.       i = getc( stdin );
  1222.       if(i != EOF) putc( i, tf );
  1223.      }
  1224.      while( i != EOF );
  1225.  
  1226.      fclose( tf );
  1227.      filename = tempfile;
  1228.     }
  1229.  
  1230.     //get the text of the file into a string buffer
  1231.     if((fileh=CreateFile(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,
  1232.                          FILE_FLAG_SEQUENTIAL_SCAN,NULL))==INVALID_HANDLE_VALUE)
  1233.     {
  1234.      if( ! quiet ) printf("error reading %s, aborting\n",filename);
  1235.      delete [] Recipients;
  1236.      return 3;
  1237.     }
  1238.     if(GetFileType(fileh)!=FILE_TYPE_DISK)
  1239.     {
  1240.      if( ! quiet ) printf("Sorry, I can only mail messages from disk files...\n");
  1241.      delete [] Recipients;
  1242.      return 4;
  1243.     }
  1244.     DWORD filesize = GetFileSize( fileh,NULL );
  1245.     // 0x1000 is for the minimal Mime/UUEncode header
  1246.     char *buffer = new char[(3*(filesize+filesize/72))+headerlen+1+0x1000+strlen(filename)];
  1247.     char *filebuffer = new char[filesize+1+4];
  1248.     char *tmpptr;
  1249.     char *q; 
  1250.     char *p; 
  1251.  
  1252.     // put the header at the top...
  1253.     strcpy( buffer, header );
  1254.     // point to the end of the header
  1255.     tmpptr = buffer + headerlen;
  1256.     // and put the whole file there
  1257.     DWORD dummy;
  1258.     if(!ReadFile(fileh,filebuffer,filesize,&dummy,NULL))
  1259.     {
  1260.      if( ! quiet ) printf("error reading %s, aborting\n",filename);
  1261.      CloseHandle(fileh);
  1262.      delete [] buffer;        
  1263.      delete [] filebuffer;        
  1264.      delete [] Recipients;
  1265.      return 5;
  1266.     }
  1267.     CloseHandle(fileh);
  1268.  
  1269.        q = filebuffer + filesize; 
  1270.     (*q) = '\0'; 
  1271.     (*(q+1)) = (*(q+2)) = (*(q+3)) = (*(q+4)) = '\0'; 
  1272.  
  1273.     if (mime)
  1274.     { // MIME Quoted-Printable Content-Transfer-Encoding
  1275.      int PosValue = 0; 
  1276.      int *Pos; 
  1277.      char workbuf [8]; 
  1278.      Pos = &PosValue; 
  1279.      p = filebuffer; 
  1280.      while (p < q) {
  1281.       ConvertToQuotedPrintable(*p,Pos, workbuf);
  1282.       strcat(tmpptr,workbuf); 
  1283.       *p++;
  1284.      } 
  1285.     }
  1286.     else
  1287.     if (base64)
  1288.       dobase64(filebuffer,tmpptr,filesize,filename);
  1289.     else
  1290.     if (uuencode)
  1291.       douuencode(filebuffer,tmpptr,filesize,filename);
  1292.     else
  1293.      strcpy( tmpptr, filebuffer );
  1294.  
  1295.  
  1296.     // delete the temporary file if it has been used
  1297.     if ( *tempfile ) remove( tempfile );
  1298.         
  1299.     // make some noise about what we are doing
  1300.     if( ! quiet )
  1301.     {    
  1302.      printf("Sending %s to %s\n",filename,(lstrlen(Recipients) ? Recipients : "<unspecified>"));
  1303.      if(lstrlen(subject)) printf("Subject:%s\n",subject);
  1304.      if(lstrlen(loginname)) printf("Login name is %s\n",loginname);
  1305.     }
  1306.  
  1307.   // send the message to the SMTP server!
  1308.   retcode = prepare_smtp_message( loginname, Recipients, my_hostname_wanted);
  1309.   if( !retcode )
  1310.   {
  1311.    retcode = send_smtp_edit_data( buffer ); 
  1312.    if( !retcode )
  1313.     finish_smtp_message();
  1314.    close_smtp_socket();
  1315.   }
  1316.  
  1317.   delete [] buffer;
  1318.   delete [] filebuffer;        
  1319.   delete [] Recipients;
  1320.   return (retcode);
  1321. }
  1322.  
  1323.