home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / winsock / wvnsc926 / wvsckgen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  18.1 KB  |  756 lines

  1. /* Interface to GENSOCK module */
  2. /* $Id: wvsckgen.c 1.19 1994/09/22 00:16:59 jcooper Exp $ */
  3.  
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include "wvglob.h"
  7. #include "winvn.h"
  8. #pragma hdrstop
  9. #include <stdlib.h>
  10. #include <stdio.h> /* for sprintf */
  11. #include <stdarg.h> /* for varargs stuff */
  12.  
  13. #define MAXSENDLEN 32767
  14. #define COMMBUFSIZE    1600
  15.  
  16. /* generic socket DLL support */
  17. #include "gensock.h"
  18.  
  19. char    CommBuff[COMMBUFSIZE];
  20. int    CommBuffIdx = COMMBUFSIZE + 1;
  21. int    CharsInCommBuff = 0;
  22.  
  23. socktag    NNTPSock;
  24. socktag SMTPSock;
  25. char my_hostname[1024];
  26.  
  27. /* functions the rest of winvn expects to see */
  28. void PutCommLine(char *line);
  29. void PutCommData(char *data, unsigned int length);
  30.  
  31. int MRRReadComm(void);
  32. void MRRCloseComm(void);
  33. int MRRInitComm(void);
  34. int send_smtp_message(char * destination, char * message);
  35. int forward_smtp_message (char * destination, TypDoc * Doc);
  36.  
  37. /* internal to this file */
  38. int close_smtp_socket(void);
  39. int open_smtp_socket(void);
  40. void smtp_error (char * message);
  41. int send_smtp_article (char * destination, TypDoc *Doc);
  42. int send_smtp_edit_data (char * message);
  43. int prepare_smtp_message (char * destination);
  44. int finish_smtp_message (void);
  45. int get_smtp_line (void);
  46. int put_smtp_line (socktag sock, char far * line, unsigned int nchars);
  47. int send_cc_article (char * destination, char * editstr);
  48.  
  49. HINSTANCE    gensock_lib = 0;
  50.  
  51. int (FAR PASCAL *pgensock_connect) (char FAR * hostname, char FAR * service, socktag FAR * pst);
  52. int (FAR PASCAL *pgensock_getchar) (socktag st, int wait, char FAR * ch);
  53. int (FAR PASCAL *pgensock_put_data) (socktag st, char FAR * data, unsigned long length);
  54. int (FAR PASCAL *pgensock_close) (socktag st);
  55. int (FAR PASCAL *pgensock_gethostname) (char FAR * name, int namelen);
  56. int (FAR PASCAL *pgensock_put_data_buffered) (socktag st, char FAR * data, unsigned long length);
  57. int (FAR PASCAL *pgensock_put_data_flush) (socktag st);
  58.  
  59.  
  60. /*-- function MRRReadComm ---------------------------------------
  61.  *
  62.  *  Reads characters from the NNTP Socket
  63.  */
  64.  
  65. #define ERROR_BUFFER_SIZE 1024
  66.  
  67. void
  68. complain (char *fmt, ... )
  69. {
  70.   va_list marker;
  71.   char    message[ERROR_BUFFER_SIZE];
  72.   int done = 0;
  73.  
  74.   /* Write text to a string and output the string. */
  75.   va_start(marker, fmt);
  76.   _vsnprintf(message, ERROR_BUFFER_SIZE, fmt, marker);
  77.   va_end(marker);
  78.   MessageBox (hWndConf, message, "WinVN GenSock Library Error", MB_OK);
  79. }
  80.  
  81. void
  82. gensock_error (char * function, int retval)
  83. {
  84.   char error_string[512];
  85.   int len;
  86.  
  87.   len = LoadString (hInst, retval, error_string, sizeof(error_string));
  88.   complain ("error %d in function '%s', '%s'",
  89.         retval,
  90.         function,
  91.         len == 0 ? "[couldn't get error string]" : error_string);
  92. }
  93.  
  94. int MRRReadComm()
  95. {
  96.   int retval;
  97.   unsigned char ch;
  98.  
  99.   /* we set wait = 1, sortof non-blocking */
  100.   if ((retval = (*pgensock_getchar) (NNTPSock, 1, &ch))) {
  101.     switch (retval) {
  102.     case WAIT_A_BIT:
  103.     case ERR_BUSY:
  104.       break;
  105.     case ERR_NOT_CONNECTED:
  106.       Initializing = INIT_NOT_CONNECTED;
  107.       SendMessage (hWndConf, (UINT) WM_COMMAND,
  108.                (WPARAM) IDM_DISCONNECT, (LPARAM) 0);
  109.       complain ("NNTP server has closed the connection");
  110.       return (-1);
  111.       break;
  112.     default:
  113.       gensock_error ("gensock_getchar", retval);
  114.     }
  115.     return (-1);
  116.   }
  117.   else
  118.     return ((int)ch);
  119. }
  120.  
  121. int
  122. putline_internal (socktag sock, char * line, unsigned int nchars)
  123. {
  124.   int retval;
  125.  
  126.   if ((retval =
  127.        (*pgensock_put_data) (sock,
  128.                 (char FAR *) line,
  129.                 (unsigned long) nchars))) {
  130.     switch (retval) {
  131.     case ERR_NOT_CONNECTED:
  132.       Initializing = INIT_NOT_CONNECTED;
  133.       SendMessage (hWndConf, (UINT) WM_COMMAND,
  134.                (WPARAM) IDM_DISCONNECT, (LPARAM) 0);
  135.       complain ("NNTP server has closed the connection");
  136.       return (-1);
  137.       break;
  138.  
  139.     default:
  140.       gensock_error ("gensock_put_data", retval);
  141.     }
  142.     return (-1);
  143.   }
  144.   return (0);
  145. }
  146.  
  147. /* PutCommLine takes a string, sends it, followed by
  148.  * \r\n.  All one-line sends in winvn should use this.
  149.  */
  150.  
  151. void
  152. PutCommLine (char * line)
  153. {
  154.   putline_internal (NNTPSock, line, lstrlen(line));
  155.   putline_internal (NNTPSock, "\r\n", 2);
  156. }
  157.  
  158. /* Use this function for sending larger chunks of data.
  159.  * the text data from an Edit class window can be sent
  160.  * using this function
  161.  */
  162.  
  163. void
  164. PutCommData (char * data, unsigned int length)
  165. {
  166.   putline_internal (NNTPSock, data, length);
  167. }
  168.  
  169. /*-- function MRRCloseComm -----------------------------------------
  170.  *
  171.  *  Close the communications port, serial or TCP.
  172.  */
  173. void MRRCloseComm ()
  174. {
  175.   (*pgensock_close)(NNTPSock);
  176.   NNTPSock = (socktag) 0;
  177.   FreeLibrary(gensock_lib);
  178.   gensock_lib = 0;
  179. }
  180.  
  181. int
  182. load_gensock()
  183. {
  184.   if ((gensock_lib = LoadLibrary(GenSockDLL)) < HINSTANCE_ERROR) {
  185.     char message[256];
  186.     wsprintf (message, "Couldn't load '%s'", GenSockDLL);
  187.     complain (message);
  188.     gensock_lib = 0;
  189.     return (-1);
  190.   }
  191.  
  192.   if (((FARPROC)pgensock_connect =
  193.        GetProcAddress(gensock_lib, "gensock_connect")) == NULL) {
  194.     complain ("couldn't getprocaddress for gensock_connect");
  195.     return (-1);
  196.   }
  197.  
  198.   if (((FARPROC)pgensock_getchar =
  199.        GetProcAddress(gensock_lib, "gensock_getchar")) == NULL) {
  200.     complain ("couldn't getprocaddress for gensock_getchar");
  201.     return (-1);
  202.   }
  203.  
  204.   if (((FARPROC)pgensock_put_data =
  205.        GetProcAddress(gensock_lib, "gensock_put_data")) == NULL) {
  206.     complain ("couldn't getprocaddress for gensock_put_data");
  207.     return (-1);
  208.   }
  209.  
  210.   if (((FARPROC)pgensock_close =
  211.        GetProcAddress(gensock_lib, "gensock_close")) == NULL) {
  212.     complain ("couldn't getprocaddress for gensock_close");
  213.     return (-1);
  214.   }
  215.  
  216.   if (((FARPROC)pgensock_gethostname =
  217.        GetProcAddress(gensock_lib, "gensock_gethostname")) == NULL) {
  218.     complain ("couldn't getprocaddress for gensock_gethostname");
  219.     return (-1);
  220.   }
  221.  
  222.   if (((FARPROC)pgensock_put_data_buffered =
  223.        GetProcAddress(gensock_lib, "gensock_put_data_buffered")) == NULL) {
  224.     complain ("couldn't getprocaddress for gensock_put_data_buffered");
  225.     return (-1);
  226.   }
  227.  
  228.   if (((FARPROC)pgensock_put_data_flush =
  229.        GetProcAddress(gensock_lib, "gensock_put_data_flush")) == NULL) {
  230.     complain ("couldn't getprocaddress for gensock_put_data_flush");
  231.     return (-1);
  232.   }
  233.  
  234.   return (0);
  235. }
  236.  
  237.  
  238. int
  239. MRRInitComm()
  240. {
  241.   int retval;
  242.  
  243.   /* load the library if it's not loaded */
  244.   if (!gensock_lib) {
  245.     if ((retval = load_gensock())) {
  246.       return (retval);
  247.     }
  248.   }
  249.  
  250.   /* to keep our sanity, we will quietly try '119' in case it fails */
  251.   if ((retval = (*pgensock_connect) ((LPSTR)NNTPHost,
  252.                      (LPSTR)NNTPService,
  253.                      &NNTPSock))) {
  254.     if (retval == ERR_CANT_RESOLVE_SERVICE) {
  255.       if ((retval = (*pgensock_connect) ((LPSTR)NNTPHost,
  256.                      (LPSTR)"119",
  257.                      &NNTPSock))) {
  258.     gensock_error ("gensock_connect", retval);
  259.     return (-1);
  260.       }
  261.     }
  262.     /* error other than can't resolve service */
  263.     else {
  264.       gensock_error ("gensock_connect", retval);
  265.       return (-1);
  266.     }
  267.   }
  268.  
  269.   IgnoreCommCh = '\r';
  270.   EOLCommCh = '\n';
  271.  
  272.   CommLinePtr = CommLineIn;
  273.   CommState = ST_ESTABLISH_COMM;
  274.   CommBusy = FALSE;
  275.   return (0);
  276. }
  277.  
  278. /* ---------------------------------------------------------------------------
  279.  * transform_and_send_edit_data
  280.  */
  281.  
  282. int transform_and_send_edit_data (socktag sock, char * editptr)
  283. {
  284.   char *index;
  285.   char *header_end;
  286.   char previous_char = 'x';
  287.   unsigned int send_len;
  288.   int retval;
  289.   BOOL done = 0;
  290.  
  291.   send_len = lstrlen(editptr);
  292.   index = editptr;
  293.  
  294.   header_end = strstr (editptr, "\r\n\r\n");
  295.  
  296.   while (!done) {
  297.     /* room for extra char for double dot on end case */
  298.     while ((unsigned int) (index - editptr) < send_len) {
  299.       switch (*index) {
  300.       case '.':
  301.     if (previous_char == '\n') {
  302.       /* send _two_ dots... */
  303.       if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
  304.         return (retval);
  305.       }
  306.     }
  307.     if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
  308.       return (retval);
  309.     }
  310.     break;
  311.       case '\r':
  312.     /* watch for soft-breaks in the header, and ignore them */
  313.  
  314.     if (index < header_end && (strncmp (index, "\r\r\n", 3) == 0)) {
  315.       index = index + 2;
  316.       break;
  317.     }
  318.     else {
  319.       if (previous_char != '\r') {
  320.         if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
  321.           return (retval);
  322.         }
  323.       }
  324.       /* soft line-break (see EM_FMTLINES), skip extra CR */
  325.       break;
  326.     }
  327.  
  328.       default:
  329.     if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
  330.       return (retval);
  331.     }
  332.       }
  333.     previous_char = *index;
  334.     index++;
  335.     }
  336.     if ( (unsigned int) (index - editptr) == send_len) {
  337.       done = 1;
  338.     }
  339.   }
  340.  
  341.   /* this handles the case where the user doesn't end the last
  342.    * line with a <return>
  343.    */
  344.  
  345.   if (editptr[send_len-1] != '\n') {
  346.     if ((retval = (*pgensock_put_data_buffered) (sock, "\r\n.\r\n", 5))) {
  347.       return (retval);
  348.     }
  349.   }
  350.   else {
  351.     if ((retval = (*pgensock_put_data_buffered) (sock, ".\r\n", 3))) {
  352.       return (retval);
  353.     }
  354.   }
  355.  
  356.   /* now make sure it's all sent... */
  357.   if ((retval = (*pgensock_put_data_flush)(sock))) {
  358.     return (retval);
  359.   }
  360.   return (TRUE);
  361. }
  362.  
  363. int
  364. post_edit_data (char * edit_data)
  365. {
  366.   return (transform_and_send_edit_data (NNTPSock, edit_data));
  367. }
  368.  
  369. int open_smtp_socket ()
  370. {
  371.   int retval;
  372.  
  373.  
  374.   /* load the library if it's not loaded */
  375.   if (!gensock_lib) {
  376.     if ((retval = load_gensock())) {
  377.       return (retval);
  378.     }
  379.   }
  380.  
  381.   if ((retval = (*pgensock_connect) ((LPSTR)SMTPHost,
  382.                      (LPSTR)"smtp",
  383.                      &SMTPSock))) {
  384.     if (retval == ERR_CANT_RESOLVE_SERVICE) {
  385.       if ((retval = (*pgensock_connect) ((LPSTR)SMTPHost,
  386.                      (LPSTR)"25",
  387.                      &SMTPSock))) {
  388.     gensock_error ("gensock_connect", retval);
  389.     return (-1);
  390.       }
  391.     }
  392.     /* error other than can't resolve service */
  393.     else {
  394.       gensock_error ("gensock_connect", retval);
  395.       return (-1);
  396.     }
  397.   }
  398.  
  399.   /* we wait to do this until here because WINSOCK is
  400.    * guaranteed to be already initialized at this point.
  401.    */
  402.  
  403.   /* get the local hostname (needed by SMTP) */
  404.   if ((retval = (*pgensock_gethostname) (my_hostname, sizeof(my_hostname)))) {
  405.     gensock_error ("gensock_gethostname", retval);
  406.     return (-1);
  407.   }
  408.  
  409. }
  410.  
  411. int close_smtp_socket()
  412. {
  413.   int retval;
  414.  
  415.   if ((retval = (*pgensock_close) (SMTPSock))) {
  416.     gensock_error ("gensock_close", retval);
  417.     return (-1);
  418.   }
  419.  
  420.   /* in case we're _not_ connected to a NNTP server, and
  421.    * we just used SMTP mail only, then we probably want to
  422.    * close the library...
  423.    */
  424.  
  425.   if (!NNTPSock) {
  426.     FreeLibrary(gensock_lib);
  427.     gensock_lib = 0;
  428.   }
  429.  
  430.   return (0);
  431. }
  432.  
  433. /* 'destination' is the address the message is to be sent to */
  434. /* 'message' is a pointer to a null-terminated 'string' containing the */
  435. /* entire text of the message. */
  436.  
  437. int prepare_smtp_message(char * destination)
  438. {
  439.   char out_data[MAXOUTLINE];
  440.   char *ptr;
  441.   int len, startLen;
  442.  
  443.   if (open_smtp_socket())
  444.     return (-1);
  445.  
  446.   if (get_smtp_line() != 220) {
  447.     smtp_error ("SMTP server error");
  448.     return(-1);
  449.   }
  450.  
  451.   sprintf (out_data, "HELO %s\r\n", my_hostname);
  452.   put_smtp_line (SMTPSock, out_data, strlen (out_data));
  453.  
  454.   if (get_smtp_line() != 250) {
  455.     smtp_error ("SMTP server error");
  456.     return (-1);
  457.   }
  458.  
  459.   sprintf (out_data, "MAIL From:<%s>\r\n", MailAddress);
  460.   put_smtp_line (SMTPSock, out_data, strlen (out_data));
  461.  
  462.   if (get_smtp_line() != 250) {
  463.     smtp_error ("The mail server doesn't like the sender name, "
  464.         "have you set your mail address correctly?");
  465.     return (-1);
  466.   }
  467.  
  468.   // do a series of RCPT lines for each name in address line
  469.   for (ptr = destination; *ptr; ptr += len + 1)
  470.   {
  471.     // if there's only one token left, then len will = startLen,
  472.     // and we'll iterate once only
  473.     startLen = strlen (ptr);
  474.     if ((len = strcspn (ptr, " ,\n\t\r")) != startLen)
  475.     {
  476.       ptr[len] = '\0';            // replace delim with NULL char
  477.       while (strchr (" ,\n\t\r", ptr[len+1]))    // eat white space
  478.         ptr[len++] = '\0';
  479.     }
  480.  
  481.     sprintf (out_data, "RCPT To: <%s>\r\n", ptr);
  482.     putline_internal (SMTPSock, out_data, strlen (out_data));
  483.  
  484.     if (get_smtp_line() != 250)
  485.     {
  486.       sprintf (str, "The mail server doesn't like the name %s.  "
  487.                     "Have you set the 'To: ' field correctly?", ptr);
  488.       smtp_error (str);
  489.       return (-1);
  490.     }
  491.  
  492.     if (len == startLen)    // last token, we're done
  493.       break;
  494.   }
  495.  
  496.   sprintf (out_data, "DATA\r\n");
  497.   put_smtp_line (SMTPSock, out_data, strlen (out_data));
  498.  
  499.   if (get_smtp_line() != 354) {
  500.     smtp_error ("Mail server error accepting message data");
  501.     return (-1);
  502.   }
  503.  
  504.   return(0);
  505.  
  506. }
  507.  
  508. int send_smtp_edit_data (char * message)
  509. {
  510.   transform_and_send_edit_data (SMTPSock, message);
  511.  
  512.   if (get_smtp_line() != 250) {
  513.     smtp_error ("Message not accepted by server");
  514.     return (-1);
  515.   }
  516.   return(0);
  517. }
  518.  
  519. int
  520. finish_smtp_message () {
  521.   return (put_smtp_line (SMTPSock, "QUIT\r\n", 6));
  522. }
  523.  
  524. int get_smtp_line ()
  525. {
  526.   char ch = '.';
  527.   char in_data [MAXOUTLINE];
  528.   char * index;
  529.   int retval = 0;
  530.  
  531.   index = in_data;
  532.  
  533.   while (ch != '\n') {
  534.     if ((retval = (*pgensock_getchar) (SMTPSock, 0, &ch))) {
  535.       gensock_error ("gensock_getchar", retval);
  536.       return (-1);
  537.     }
  538.     else {
  539.       *index = ch;
  540.       index++;
  541.     }
  542.   }
  543.  
  544.   /* this is to support multi-line responses, common with */
  545.   /* servers that speak ESMTP */
  546.  
  547.   /* I know, I know, it's a hack 8^) */
  548.   if (in_data[3] == '-')
  549.     return (get_smtp_line());
  550.   else
  551.     return (atoi(in_data));
  552. }
  553.  
  554. int put_smtp_line (socktag sock, char far * line, unsigned int nchars)
  555. {
  556.   int retval;
  557.  
  558.   if ((retval = (*pgensock_put_data) (sock, line, (unsigned long) nchars))) {
  559.     gensock_error ("gensock_put_data", retval);
  560.     return (-1);
  561.   }
  562.   return (0);
  563. }
  564.  
  565. void smtp_error (char * message)
  566. {
  567.   MessageBox (hWndConf, message, "WinVN", MB_OK);
  568.   put_smtp_line (SMTPSock, "QUIT\r\n", 6);
  569.   close_smtp_socket();
  570. }
  571.  
  572.  
  573. int send_smtp_message (char * destination, char * message)
  574. {
  575.   if (!prepare_smtp_message (destination))
  576.     if (!send_smtp_edit_data (message))
  577.       if (!finish_smtp_message ()) {
  578.     close_smtp_socket();
  579.     return (0);
  580.       }
  581.  
  582.   close_smtp_socket();
  583.   return (1);
  584. }
  585.  
  586. int forward_smtp_message (char * destination, TypDoc * Doc)
  587. {
  588.   int retval;
  589.  
  590.   if ((retval = prepare_smtp_message (destination))) {
  591.     complain ("prepare_smtp_message returned %d\r\n", retval);
  592.     return (retval);
  593.   }
  594.   else if ((retval = send_smtp_article (destination, Doc))) {
  595.     complain ("send_smtp_article returned %d\r\n", retval);
  596.     return (retval);
  597.   }
  598.   else if ((retval = finish_smtp_message())) {
  599.     complain ("finish_smtp_message() returned %d\r\n", retval);
  600.     close_smtp_socket();
  601.     return (retval);
  602.   }
  603.   close_smtp_socket();
  604.   return (1);
  605. }
  606.  
  607. // testing new buffered stuff...
  608.  
  609. int send_smtp_article (char * destination, TypDoc * Doc)
  610. {
  611.   HANDLE hBlock;
  612.   unsigned int Offset;
  613.   TypLineID MyLineID;
  614.   TypBlock far *BlockPtr;
  615.   TypLine far *LinePtr;
  616.   int retval;
  617.   char line [MAXOUTLINE], temp [MAXOUTLINE];
  618.  
  619.   _snprintf(line,
  620.         MAXOUTLINE,
  621.         "From: %s (%s)\r\n",
  622.         MailAddress,
  623.         UserName);
  624.  
  625.  
  626.   if ((retval =
  627.        (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen(line)))) {
  628.     return (retval);
  629.   }
  630.  
  631.   _snprintf(line,
  632.         MAXOUTLINE,
  633.         "To: %s\r\n",
  634.         destination);
  635.  
  636.  
  637.   if ((retval =
  638.        (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen(line)))) {
  639.     return (retval);
  640.   }
  641.  
  642.   /* find the subject line */
  643.   TopOfDoc (Doc, &BlockPtr, &LinePtr);
  644.   *line = '\0';
  645.   while (ExtractTextLine (Doc, LinePtr, temp, MAXOUTLINE - 1))
  646.     {
  647.     if (!_strnicmp(temp, "subject:", 8))
  648.       {
  649.         _snprintf(line,
  650.              MAXOUTLINE,
  651.          "Subject: %s (fwd)\r\n", 
  652.          &temp[8]);
  653.         break;
  654.       }
  655.       if (!NextLine (&BlockPtr, &LinePtr))
  656.        break;
  657.     }
  658.   if (*line && (retval =
  659.        (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen(line)))) {
  660.     return (retval);
  661.   }
  662.   
  663.   _snprintf(line,
  664.         MAXOUTLINE,
  665.         "\r\n[article forwarded from %s (%s)]\r\n\r\n",
  666.         UserName,
  667.         MailAddress);
  668.  
  669.   if ((retval =
  670.        (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen(line)))) {
  671.     return (retval);
  672.   }
  673.  
  674.   TopOfDoc (Doc, &BlockPtr, &LinePtr);
  675.   while (ExtractTextLine (Doc, LinePtr, line, MAXOUTLINE - 1))
  676.     {
  677.       /* double a leading dot */
  678.       if (line[0] == '.') {
  679.     if ((retval = (*pgensock_put_data_buffered) (SMTPSock, ".", 1))) {
  680.       return (retval);
  681.     }
  682.       }
  683.       strcat (line, "\r\n");
  684.  
  685.       if ((retval =
  686.        (*pgensock_put_data_buffered) (SMTPSock, line, strlen(line)))) {
  687.     return (retval);
  688.       }
  689.  
  690.       if (!NextLine (&BlockPtr, &LinePtr))
  691.     break;
  692.     }
  693.   UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID);
  694.  
  695.   if ((retval =
  696.        (*pgensock_put_data_buffered) (SMTPSock, "\r\n.\r\n", 5))) {
  697.     return (retval);
  698.   }
  699.   if ((retval =
  700.        (*pgensock_put_data_flush) (SMTPSock))) {
  701.     return (retval);
  702.   }
  703.  
  704.   if ((retval = get_smtp_line()) != 250) {
  705.     complain("Send Failed. get_smtp_line() returned %d\r\n", retval);
  706.   }
  707.  
  708.  return (0);
  709. }
  710.  
  711.  
  712. int cc_smtp_message (char * destination, char * editstr)
  713. {
  714.   int retval;
  715.  
  716.   if ((retval = prepare_smtp_message (destination))) {
  717.     complain ("prepare_smtp_message returned %d\r\n", retval);
  718.     return (retval);
  719.   }
  720.   else if ((retval = send_cc_article (destination, editstr))) {
  721.     complain ("send_cc_article returned %d\r\n", retval);
  722.     return (retval);
  723.   }
  724.   else if ((retval = finish_smtp_message())) {
  725.     complain ("finish_smtp_message() returned %d\r\n", retval);
  726.     close_smtp_socket();
  727.     return (retval);
  728.   }
  729.   close_smtp_socket();
  730.   return (1);
  731. }
  732.  
  733. int send_cc_article (char * destination, char * editstr)
  734. {
  735.   char line [MAXOUTLINE];
  736.   int retval;
  737.   
  738.   _snprintf(line,
  739.         MAXOUTLINE,
  740.         "To: %s\r\n",
  741.         destination);
  742.  
  743.   if ((retval =
  744.       (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen(line)))) {
  745.     return (retval);
  746.   }
  747.  
  748.   if ((retval =
  749.       send_smtp_edit_data (editstr))) {
  750.     return (retval);
  751.   }
  752.  
  753.  return (0);
  754. }
  755.  
  756.