home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / vsoup128.zip / smtp.cc < prev    next >
C/C++ Source or Header  |  1997-02-06  |  7KB  |  272 lines

  1. //  $Id: smtp.cc 1.22 1997/02/06 09:57:38 hardy Exp $
  2. //
  3. //  This progam/module was written by Hardy Griech based on ideas and
  4. //  pieces of code from Chin Huang (cthuang@io.org).  Bug reports should
  5. //  be submitted to rgriech@ibm.net.
  6. //
  7. //  This file is part of soup++ for OS/2.  Soup++ including this file
  8. //  is freeware.  There is no warranty of any kind implied.  The terms
  9. //  of the GNU Gernal Public Licence are valid for this piece of software.
  10. //
  11. //  Send mail reply packet using SMTP directly
  12. //
  13.  
  14.  
  15. #include <ctype.h>
  16. #include <string.h>
  17.  
  18. #include "global.hh"
  19. #include "mts.hh"
  20. #include "smtp.hh"
  21. #include "socket.hh"
  22. #include "util.hh"
  23.  
  24.  
  25.  
  26. void smtpClose(TSocket &socket)
  27. //
  28. //  close SMTP connection
  29. //
  30. {
  31. #ifdef DEBUG
  32.     printfT( "smtpClose(): QUIT\n" );
  33. #endif
  34.     socket.printf("QUIT\n");
  35.     socket.close();
  36. }   // smtpClose
  37.  
  38.  
  39.  
  40. static int getSmtpReply( TSocket &socket, const char *response)
  41. //
  42. //  get a response from the SMTP server and test it
  43. //  on correct response a '1' is returned    
  44. //
  45. {
  46.     char buf[BUFSIZ];
  47.  
  48.     do {
  49.     buf[3] = '\0';
  50.     if (socket.gets(buf, BUFSIZ) == NULL) {
  51.         areas.mailPrintf1( 1, "Expecting SMTP %s reply, got nothing\n",
  52.                    response, buf );
  53.         return 0;
  54.     }
  55.     } while (buf[3] == '-');        /* wait until not a continuation */
  56.  
  57.     if (strncmp(buf, response, 3) != 0) {
  58.     areas.mailPrintf1(1, "Expecting SMTP %s reply, got %s\n", response, buf);
  59.     }
  60.     return (buf[0] == *response);    /* only first digit really matters */
  61. }   // getSmtpReply
  62.  
  63.  
  64.  
  65. int smtpConnect ( TSocket &socket )
  66. //
  67. //  Open socket and intialize connection to SMTP server.
  68. //  return value != 0  -->  ok
  69. //
  70. {
  71.     const char *localhost;
  72.  
  73.     if (socket.open( smtpInfo.host,"smtp","tcp",smtpInfo.port ) < 0)
  74.     return 0;
  75.  
  76.     if ( !getSmtpReply(socket, "220")) {
  77.     areas.mailPrintf1( 1,"Disconnecting from %s\n", smtpInfo.host);
  78.     smtpClose(socket);
  79.     return 0;
  80.     }
  81.  
  82.     localhost = socket.getLocalhost();
  83.     socket.printf("HELO %s\n", localhost );
  84. #ifdef DEBUG
  85.     printfT( "localhost: %s\n",localhost );
  86. #endif
  87.     delete localhost;
  88.  
  89.     if ( !getSmtpReply(socket, "250")) {
  90.     areas.mailPrintf1( 1,"Disconnecting from %s\n", smtpInfo.host);
  91.     smtpClose(socket);
  92.     return 0;
  93.     }
  94.     return 1;
  95. }   // smtpConnect
  96.     
  97.  
  98.  
  99. static int sendSmtpRcpt( TSocket &socket, const char *buf )
  100. //
  101. //  Send RCPT command.
  102. //
  103. {
  104.     areas.mailPrintf1(1,"%s: mailing to %s\n", progname, buf);
  105.     socket.printf( "RCPT TO:<%s>\n", buf );
  106.     return getSmtpReply(socket, "250");
  107. }   // sendSmtpRcpt
  108.  
  109.  
  110.  
  111. static int putAddresses( TSocket &socket, char *addresses )
  112. //
  113. //  Send an RCPT command for each address in the address list.
  114. //
  115. {
  116.     const char *srcEnd;
  117.     char *startAddr;
  118.     char *endAddr;
  119.     char saveCh;
  120.     const char *addr;
  121.     
  122.     srcEnd = strchr(addresses, '\0');
  123.     startAddr = addresses;
  124.  
  125.     while (startAddr < srcEnd) {
  126.     endAddr = findAddressSep(startAddr);
  127.     saveCh = *endAddr;
  128.     *endAddr = '\0';
  129.     addr = extractAddress(startAddr);
  130.     if (addr) {
  131.         if ( !sendSmtpRcpt(socket, addr)) {
  132.         //// delete addr;
  133.         return 0;
  134.         }
  135.         //// delete addr;
  136.     }
  137.     *endAddr = saveCh;
  138.     startAddr = endAddr + 1;
  139.     }
  140.     return 1;
  141. }   // putAddresses
  142.  
  143.  
  144.  
  145. int smtpMail( TSocket &socket, TFile &file, size_t bytes)
  146. //
  147. //  Send message to SMTP server.
  148. //  To all recipients the same message will be sent, i.e. Bcc is not handled
  149. //  in a special way!  sendmail handles it the same way...
  150. //
  151. {
  152.     const char *addr;
  153.     char buf[BUFSIZ];
  154.     const char *from;
  155.     char   *resentTo;
  156.     long   offset;
  157.     size_t count;
  158.     int    sol;                 // start of line
  159.     int    ll;                  // line length
  160.  
  161.     /* Look for From header and send MAIL command to SMTP server. */
  162.     from = getHeader(file, "From");
  163.     if (from == NULL || (addr = extractAddress(from)) == NULL) {
  164.     areas.mailPrintf1( 1,"%s: no address in From header\n", progname );
  165.     if (from != NULL)
  166.         delete from;
  167.     return 0;
  168.     }
  169.     areas.mailPrintf1(1,"%s: mailing from %s\n", progname, addr);
  170.     socket.printf("MAIL FROM:<%s>\n", addr);
  171.     //// delete from;
  172.     //// delete addr;
  173.     if ( !getSmtpReply(socket, "250")) {
  174.     return 0;
  175.     }
  176.  
  177.     offset = file.tell();
  178.     if ((resentTo = (char *)getHeader(file, "Resent-To")) != NULL) {
  179.     //
  180.     //  Send to address on Resent-To header
  181.     //  Continuation is allowed
  182.     //
  183.     /* Send to address on Resent-To header. */
  184.     if ( !putAddresses(socket, resentTo))
  185.         return 0;
  186.     //// delete resentTo;
  187.  
  188.     while (file.fgets(buf,sizeof(buf),1) != NULL) {
  189.         if (buf[0] != ' ' && buf[0] != '\t')
  190.         break;
  191.         if ( !putAddresses(socket, buf))
  192.         return 0;
  193.     }
  194.     }
  195.     else {
  196.     //
  197.     //  Send to addresses on To, Cc and Bcc headers.
  198.     //
  199.     int more = file.fgets(buf, sizeof(buf), 1) != NULL;
  200.     while (more) {
  201.         if (buf[0] == '\0')
  202.         break;
  203.  
  204.         if (isHeader(buf, "To")  ||  isHeader(buf, "Cc")  ||  isHeader(buf, "Bcc")) {
  205.         //
  206.         //  first skip the To/Cc/Bcc field, then transmit the address
  207.         //
  208.         char *addrs;
  209.         for (addrs = buf;  *addrs != '\0' && !isspace(*addrs);  ++addrs)
  210.             ;
  211.         if ( !putAddresses(socket, addrs))
  212.             return 0;
  213.  
  214.         //
  215.         //  Read next line and check if it is a continuation line.
  216.         //
  217.         while ((more = (file.fgets(buf,sizeof(buf),1) != NULL))) {
  218.             if (buf[0] != ' ' && buf[0] != '\t')
  219.             break;
  220.             if ( !putAddresses(socket, buf))
  221.             return 0;
  222.         }
  223.         
  224.         continue;
  225.         }
  226.     
  227.         more = file.fgets(buf, sizeof(buf), 1) != NULL;
  228.     }
  229.     }
  230.  
  231.     /* Send the DATA command and the mail message line by line. */
  232.     socket.printf("DATA\n");
  233.     if ( !getSmtpReply(socket, "354")) {
  234.     return 0;
  235.     }
  236.  
  237.     file.seek(offset, SEEK_SET);
  238.     count    = bytes;
  239.     sol      = 1;            // start of line
  240.     while (file.fgets(buf, sizeof(buf)) != NULL  &&  count > 0) {
  241.     //
  242.     //  replace trailing "\r\n" with "\n"
  243.     //
  244.     ll  = strlen(buf);
  245.     if (strcmp( buf+ll-2,"\r\n" ) == 0)
  246.         strcpy( buf+ll-2,"\n" );
  247.  
  248.     if (sol  &&  buf[0] == '.') {
  249.         //
  250.         //  is this a bug or a feature of SMTP?
  251.         //  the line "..\n" will be treated as EOA.
  252.         //  If there is a trailing blank, everything seems ok.
  253.         //
  254.         if (strcmp(buf,".\n") == 0)
  255.         socket.printf( ".. \n" );
  256.         else
  257.         socket.printf( ".%s",buf );
  258.     }
  259.     else
  260.         socket.printf( "%s",buf );
  261.     sol = (buf[strlen(buf)-1] == '\n');
  262.     count -= ll;
  263.     }
  264.     file.seek(offset+bytes, SEEK_SET);
  265.  
  266.     socket.printf(".\n");
  267.     if ( !getSmtpReply(socket, "250"))
  268.     return 0;
  269.  
  270.     return 1;
  271. }   // smtpMail
  272.