home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pine / imap-3.0 / non-ANSI / c-client / mtest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-19  |  16.8 KB  |  653 lines

  1. /*
  2.  * Program:    Mail library test program
  3.  *
  4.  * Author:    Mark Crispin
  5.  *        Networks and Distributed Computing
  6.  *        Computing & Communications
  7.  *        University of Washington
  8.  *        Administration Building, AG-44
  9.  *        Seattle, WA  98195
  10.  *        Internet: MRC@CAC.Washington.EDU
  11.  *
  12.  * Date:    8 July 1988
  13.  * Last Edited:    19 June 1993
  14.  *
  15.  * Sponsorship:    The original version of this work was developed in the
  16.  *        Symbolic Systems Resources Group of the Knowledge Systems
  17.  *        Laboratory at Stanford University in 1987-88, and was funded
  18.  *        by the Biomedical Research Technology Program of the National
  19.  *        Institutes of Health under grant number RR-00785.
  20.  *
  21.  * Original version Copyright 1988 by The Leland Stanford Junior University.
  22.  * Copyright 1993 by the University of Washington.
  23.  *
  24.  *  Permission to use, copy, modify, and distribute this software and its
  25.  * documentation for any purpose and without fee is hereby granted, provided
  26.  * that the above copyright notices appear in all copies and that both the
  27.  * above copyright notices and this permission notice appear in supporting
  28.  * documentation, and that the name of the University of Washington or The
  29.  * Leland Stanford Junior University not be used in advertising or publicity
  30.  * pertaining to distribution of the software without specific, written prior
  31.  * permission.  This software is made available "as is", and
  32.  * THE UNIVERSITY OF WASHINGTON AND THE LELAND STANFORD JUNIOR UNIVERSITY
  33.  * DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD TO THIS SOFTWARE,
  34.  * INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  35.  * FITNESS FOR A PARTICULAR PURPOSE, AND IN NO EVENT SHALL THE UNIVERSITY OF
  36.  * WASHINGTON OR THE LELAND STANFORD JUNIOR UNIVERSITY BE LIABLE FOR ANY
  37.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  38.  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  39.  * CONTRACT, TORT (INCLUDING NEGLIGENCE) OR STRICT LIABILITY, ARISING OUT OF
  40.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  41.  *
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <ctype.h>
  46. #include <signal.h>
  47. #include "mail.h"
  48. #include "osdep.h"
  49. #if unix
  50. #include <pwd.h>
  51. #include <netdb.h>
  52. #endif
  53. #ifdef noErr
  54. #include <MacTCPCommonTypes.h>
  55. #include <AddressXlation.h>
  56. #endif
  57. #include "rfc822.h"
  58. #include "smtp.h"
  59. #include "nntp.h"
  60. #include "misc.h"
  61.  
  62.  
  63. char *curhst = NIL;        /* currently connected host */
  64. char *curusr = NIL;        /* current login user */
  65. char personalname[256];        /* user's personal name */
  66. extern DRIVER imapdriver,bezerkdriver,tenexdriver,mboxdriver,mhdriver,
  67.  newsdriver,nntpdriver,dummydriver,dawzdriver;
  68.  
  69. static char *hostlist[] = {    /* SMTP server host list */
  70.   "mailhost",
  71.   "localhost",
  72.   NIL
  73. };
  74.  
  75. static char *newslist[] = {    /* Netnews server host list */
  76.   "news",
  77.   NIL
  78. };
  79.  
  80. void main  ();
  81. void mm  ();
  82. void header  ();
  83. void display_body  ();
  84. void status  ();
  85. void prompt  ();
  86. void smtptest  ();
  87.  
  88. /* Main program - initialization */
  89.  
  90. void main ()
  91. {
  92.   MAILSTREAM *stream = NIL;
  93.   char tmp[MAILTMPLEN];
  94.   long debug;
  95. #ifdef noErr
  96.   size_t *base = (size_t *) 0x000908;
  97.                 /* increase stack size on a Mac */
  98.   SetApplLimit ((Ptr) (*base - (size_t) 65535L));
  99. #endif
  100. #if unix
  101.   char *name;
  102.   char *suffix;
  103.   struct passwd *pwd;
  104.   struct hostent *host_name;
  105.   gethostname (tmp,MAILTMPLEN);    /* get local name */
  106.                 /* get it in full form */
  107.   curhst = (host_name = gethostbyname (tmp)) ?
  108.     cpystr (host_name->h_name) : cpystr (tmp);
  109.                 /* get user name and passwd entry */
  110.   if (name = (char *) getlogin ()) pwd = getpwnam (name);
  111.   else {
  112.     pwd = getpwuid (getuid ());    /* get it this way if detached, etc */
  113.     name = pwd->pw_name;
  114.   }
  115.   curusr = cpystr (name);    /* current user is this name */
  116.   strcpy (tmp,pwd->pw_gecos);    /* probably not necessay but be safe */
  117.                 /* dyke out the office and phone poop */
  118.   if (suffix = strchr (tmp,',')) suffix[0] = '\0';
  119.   strcpy (personalname,tmp);    /* make a permanent copy of it */
  120. #else
  121.   prompt ("Personal name: ",personalname);
  122.   curusr = cpystr ("somebody");
  123.   curhst = cpystr ("someplace");
  124. #endif
  125.   puts ("MTest -- C client test program");
  126.   mail_link (&imapdriver);    /* link in IMAP driver */
  127. #ifdef MSDOS
  128.   mail_link (&dawzdriver);    /* link in dawz mail driver */
  129.   mail_link (&nntpdriver);    /* link in NNTP driver */
  130.   mail_link (&dummydriver);    /* finally dummy driver at the end */
  131. #endif
  132. #if unix
  133.   mail_link (&tenexdriver);    /* link in Tenex mail driver */
  134.   mail_link (&mhdriver);    /* link in mh mail driver */
  135.   mail_link (&mboxdriver);    /* link in mbox mail driver */
  136.   mail_link (&bezerkdriver);    /* link in Berkeley mail driver */
  137.   mail_link (&newsdriver);    /* link in netnews mail driver */
  138.   mail_link (&nntpdriver);    /* link in NNTP driver */
  139.   mail_link (&dummydriver);    /* finally dummy driver at the end */
  140. #endif
  141.                 /* user wants protocol telemetry? */
  142.   prompt ("Debug protocol (y/n)?",tmp);
  143.   ucase (tmp);
  144.   debug = (tmp[0] == 'Y') ? T : NIL;
  145.   do {
  146.     prompt ("Mailbox ('?' for help): ",tmp);
  147.     if (!strcmp (tmp,"?")) {
  148.       puts ("Enter INBOX, mailbox name, or IMAP mailbox as {host}mailbox");
  149.       puts ("Known local mailboxes:");
  150.       mail_find (NIL,"*");
  151.       puts ("or just hit return to quit");
  152.     }
  153.     else if (tmp[0]) stream = mail_open (stream,tmp,debug ? OP_DEBUG : NIL);
  154.   } while (!stream && tmp[0]);
  155.   mm (stream,debug);        /* run user interface if opened */
  156. #ifdef noErr
  157.                 /* clean up resolver */
  158.   if (resolveropen) CloseResolver ();
  159. #endif
  160. }
  161.  
  162. /* MM command loop
  163.  * Accepts: MAIL stream
  164.  */
  165.  
  166. void mm (stream,debug)
  167.     MAILSTREAM *stream;
  168.     long debug;
  169. {
  170.   char cmd[256],cmdx[128];
  171.   char *arg;
  172.   long i;
  173.   long last = 0;
  174.   BODY *body;
  175.   status (stream);        /* first report message status */
  176.   while (stream) {
  177.     prompt ("MTest>",cmd);    /* prompt user, get command */
  178.                 /* get argument */
  179.     if (arg = strchr (cmd,' ')) *arg++ = '\0';
  180.     switch (*ucase (cmd)) {    /* dispatch based on command */
  181.     case 'B':            /* Body command */
  182.       if (arg) last = atoi (arg);
  183.       else if (last == 0 ) {
  184.     puts ("?Missing message number");
  185.     break;
  186.       }
  187.       if (last > 0 && last <= stream->nmsgs) {
  188.     mail_fetchstructure (stream,last,&body);
  189.     if (body) display_body (body,NIL,(long) 0);
  190.     else puts ("%No body information available");
  191.       }
  192.       else puts ("?Bad message number");
  193.       break;
  194.     case 'C':            /* Check command */
  195.       mail_check (stream);
  196.       status (stream);
  197.       break;
  198.     case 'D':            /* Delete command */
  199.       if (arg) last = atoi (arg);
  200.       else {
  201.     if (last == 0) {
  202.       puts ("?Missing message number");
  203.       break;
  204.     }
  205.     arg = cmd;
  206.     sprintf (arg,"%ld",last);
  207.       }
  208.       if (last > 0 && last <= stream->nmsgs)
  209.     mail_setflag (stream,arg,"\\DELETED");
  210.       else puts ("?Bad message number");
  211.       break;
  212.     case 'E':            /* Expunge command */
  213.       mail_expunge (stream);
  214.       last = 0;
  215.       break;
  216.     case 'F':            /* Find command */
  217.       if (!arg) arg = "*";
  218.       puts ("Subscribed mailboxes:");
  219.       mail_find (NIL,arg);
  220.       puts ("Subscribed bboards:");
  221.       mail_find_bboards (NIL,arg);
  222.       puts ("Known mailboxes:");
  223.       mail_find_all (NIL,arg);
  224.       puts ("Known bboards:");
  225.       mail_find_all_bboard (NIL,arg);
  226.       if ((*stream->mailbox == '{') ||
  227.       ((*stream->mailbox == '*') && (stream->mailbox[1] == '{'))) {
  228.     puts ("Remote Subscribed mailboxes:");
  229.     mail_find (stream,arg);
  230.     puts ("Remote Subscribed bboards:");
  231.     mail_find_bboards (stream,arg);
  232.     puts ("Remote known mailboxes:");
  233.     mail_find_all (stream,arg);
  234.     puts ("Remote known bboards:");
  235.     mail_find_all_bboard (stream,arg);
  236.       }
  237.       break;
  238.     case 'G':
  239.       mail_gc (stream,GC_ENV|GC_TEXTS|GC_ELT);
  240.       break;
  241.     case 'H':            /* Headers command */
  242.       if (arg) {
  243.     if (!(last = atoi (arg))) {
  244.       mail_search (stream,arg);
  245.       for (i = 1; i <= stream->nmsgs; ++i)
  246.         if (mail_elt (stream,i)->searched) header (stream,i);
  247.       break;
  248.     }
  249.       }
  250.       else if (last == 0) {
  251.     puts ("?Missing message number");
  252.     break;
  253.       }
  254.       if (last > 0 && last <= stream->nmsgs) header (stream,last);
  255.       else puts ("?Bad message number");
  256.       break;
  257.     case 'M':
  258.       prompt ("Destination: ",cmdx);
  259.       mail_move (stream,arg,cmdx);
  260.       break;
  261.     case 'N':            /* New mailbox command */
  262.       if (!arg) {
  263.     puts ("?Missing mailbox");
  264.     break;
  265.       }
  266.                 /* get the new mailbox */
  267.       while (!(stream = mail_open (stream,arg,debug)))
  268.     prompt ("Mailbox: ",arg);
  269.       last = 0;
  270.       status (stream);
  271.       break;
  272.     case 'Q':            /* Quit command */
  273.       mail_close (stream);
  274.       stream = NIL;
  275.       break;
  276.     case 'S':            /* Send command */
  277.       smtptest (debug);
  278.       break;
  279.     case 'T':            /* Type command */
  280.       if (arg) last = atoi (arg);
  281.       else if (last == 0 ) {
  282.     puts ("?Missing message number");
  283.     break;
  284.       }
  285.       if (last > 0 && last <= stream->nmsgs) {
  286.     printf ("%s",mail_fetchheader (stream,last));
  287.     puts (mail_fetchtext (stream,last));
  288.       }
  289.       else puts ("?Bad message number");
  290.       break;
  291.     case 'U':            /* Undelete command */
  292.       if (arg) last = atoi (arg);
  293.       else {
  294.     if (last == 0 ) {
  295.       puts ("?Missing message number");
  296.       break;
  297.     }
  298.     arg = cmd;
  299.     sprintf (arg,"%ld",last);
  300.       }
  301.       if (last > 0 && last <= stream->nmsgs)
  302.     mail_clearflag (stream,arg,"\\DELETED");
  303.       else puts ("?Bad message number");
  304.       break;
  305.     case 'X':            /* Xit command */
  306.       mail_expunge (stream);
  307.       mail_close (stream);
  308.       stream = NIL;
  309.       break;
  310.     case '+':
  311.       mail_debug (stream); debug = T;
  312.       break;
  313.     case '-':
  314.       mail_nodebug (stream); debug = NIL;
  315.       break;
  316.     case '?':            /* ? command */
  317.       puts ("Body, Check, Delete, Expunge, Find, GC, Headers, Move,");
  318.       puts (" New Mailbox, Quit, Send, Type, Undelete, Xit,");
  319.       puts (" +, -, or <RETURN> for next message");
  320.       break;
  321.     case '\0':        /* null command (type next message) */
  322.       if (last > 0 && last++ < stream->nmsgs) {
  323.     printf ("%s",mail_fetchheader (stream,last));
  324.     puts (mail_fetchtext (stream,last));
  325.       }
  326.       else puts ("%No next message");
  327.       break;
  328.     default:            /* bogus command */
  329.       printf ("?Unrecognized command: %s\n",cmd);
  330.       break;
  331.     }
  332.   }
  333. }
  334.  
  335. /* MM display header
  336.  * Accepts: IMAP2 stream
  337.  *        message number
  338.  */
  339.  
  340. void header (stream,msgno)
  341.     MAILSTREAM *stream;
  342.     long msgno;
  343. {
  344.   unsigned long i;
  345.   char tmp[256];
  346.   char *t;
  347.   MESSAGECACHE *cache = mail_elt (stream,msgno);
  348.   mail_fetchstructure (stream,msgno,NIL);
  349.   tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
  350.   tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
  351.   tmp[2] = cache->flagged ? 'F' : ' ';
  352.   tmp[3] = cache->answered ? 'A' : ' ';
  353.   tmp[4] = cache->deleted ? 'D' : ' ';
  354.   sprintf (tmp+5,"%4ld) ",cache->msgno);
  355.   mail_date (tmp+11,cache);
  356.   tmp[17] = ' ';
  357.   tmp[18] = '\0';
  358.   mail_fetchfrom (tmp+18,stream,msgno,(long) 20);
  359.   strcat (tmp," ");
  360.   if (i = cache->user_flags) {
  361.     strcat (tmp,"{");
  362.     while (i) {
  363.       strcat (tmp,stream->user_flags[find_rightmost_bit (&i)]);
  364.       if (i) strcat (tmp," ");
  365.     }
  366.     strcat (tmp,"} ");
  367.   }
  368.   mail_fetchsubject (t = tmp + strlen (tmp),stream,msgno,(long) 25);
  369.   sprintf (t += strlen (t)," (%ld chars)",cache->rfc822_size);
  370.   puts (tmp);
  371. }
  372.  
  373. /* MM display body
  374.  * Accepts: BODY structure pointer
  375.  *        prefix string
  376.  *        index
  377.  */
  378.  
  379. void display_body (body,pfx,i)
  380.     BODY *body;
  381.     char *pfx;
  382.     long i;
  383. {
  384.   char tmp[256];
  385.   char *s = tmp;
  386.   PARAMETER *par;
  387.   PART *part;            /* multipart doesn't have a row to itself */
  388.   if (body->type == TYPEMULTIPART) {
  389.                 /* if not first time, extend prefix */
  390.     if (pfx) sprintf (tmp,"%s%ld.",pfx,++i);
  391.     else tmp[0] = '\0';
  392.     for (i = 0,part = body->contents.part; part; part = part->next)
  393.       display_body (&part->body,tmp,i++);
  394.   }
  395.   else {            /* non-multipart, output oneline descriptor */
  396.     if (!pfx) pfx = "";        /* dummy prefix if top level */
  397.     sprintf (s," %s%ld %s",pfx,++i,body_types[body->type]);
  398.     if (body->subtype) sprintf (s += strlen (s),"/%s",body->subtype);
  399.     if (body->description) sprintf (s += strlen (s)," (%s)",body->description);
  400.     if (par = body->parameter) do
  401.       sprintf (s += strlen (s),";%s=%s",par->attribute,par->value);
  402.     while (par = par->next);
  403.     if (body->id) sprintf (s += strlen (s),", id = %s",body->id);
  404.     switch (body->type) {    /* bytes or lines depending upon body type */
  405.     case TYPEMESSAGE:        /* encapsulated message */
  406.     case TYPETEXT:        /* plain text */
  407.       sprintf (s += strlen (s)," (%ld lines)",body->size.lines);
  408.       break;
  409.     default:
  410.       sprintf (s += strlen (s)," (%ld bytes)",body->size.bytes);
  411.       break;
  412.     }
  413.     puts (tmp);            /* output this line */
  414.                 /* encapsulated message? */
  415.     if (body->type == TYPEMESSAGE && (body = body->contents.msg.body)) {
  416.       if (body->type == TYPEMULTIPART) display_body (body,pfx,i-1);
  417.       else {            /* build encapsulation prefix */
  418.     sprintf (tmp,"%s%ld.",pfx,i);
  419.     display_body (body,tmp,(long) 0);
  420.       }
  421.     }
  422.   }
  423. }
  424.  
  425. /* MM status report
  426.  * Accepts: MAIL stream
  427.  */
  428.  
  429. void status (stream)
  430.     MAILSTREAM *stream;
  431. {
  432.   long i;
  433.   char date[50];
  434.   rfc822_date (date);
  435.   puts (date);
  436.   if (stream) {
  437.     if (stream->mailbox) printf ("Mailbox: %s, %ld messages, %ld recent\n",
  438.                  stream->mailbox,stream->nmsgs,stream->recent);
  439.     else puts ("%No mailbox is open on this stream");
  440.     if (stream->user_flags[0]) {
  441.       printf ("Keywords: %s",stream->user_flags[0]);
  442.       for (i = 1; i < NUSERFLAGS && stream->user_flags[i]; ++i)
  443.     printf (", %s",stream->user_flags[i]);
  444.       puts ("");
  445.     }
  446.   }
  447. }
  448.  
  449.  
  450. /* Prompt user for input
  451.  * Accepts: pointer to prompt message
  452.  *          pointer to input buffer
  453.  */
  454.  
  455. void prompt (msg,txt)
  456.     char *msg;
  457.     char *txt;
  458. {
  459.   printf ("%s",msg);
  460.   gets (txt);
  461. }
  462.  
  463. /* Interfaces to C-client */
  464.  
  465.  
  466. void mm_searched (stream,number)
  467.     MAILSTREAM *stream;
  468.     long number;
  469. {
  470. }
  471.  
  472.  
  473. void mm_exists (stream,number)
  474.     MAILSTREAM *stream;
  475.     long number;
  476. {
  477. }
  478.  
  479.  
  480. void mm_expunged (stream,number)
  481.     MAILSTREAM *stream;
  482.     long number;
  483. {
  484. }
  485.  
  486.  
  487. void mm_notify (stream,string,errflg)
  488.     MAILSTREAM *stream;
  489.     char *string;
  490.     long errflg;
  491. {
  492.   mm_log (string,errflg);
  493. }
  494.  
  495.  
  496. void mm_mailbox (string)
  497.     char *string;
  498. {
  499.   putchar (' ');
  500.   puts (string);
  501. }
  502.  
  503.  
  504. void mm_bboard (string)
  505.     char *string;
  506. {
  507.   putchar (' ');
  508.   puts (string);
  509. }
  510.  
  511. void mm_log (string,errflg)
  512.     char *string;
  513.     long errflg;
  514. {
  515.   switch ((short) errflg) {
  516.   case NIL:
  517.     printf ("[%s]\n",string);
  518.     break;
  519.   case PARSE:
  520.   case WARN:
  521.     printf ("%%%s\n",string);
  522.     break;
  523.   case ERROR:
  524.     printf ("?%s\n",string);
  525.     break;
  526.   }
  527. }
  528.  
  529.  
  530. void mm_dlog (string)
  531.     char *string;
  532. {
  533.   puts (string);
  534. }
  535.  
  536.  
  537. void mm_login (host,user,pwd,trial)
  538.     char *host;
  539.     char *user;
  540.     char *pwd;
  541.     long trial;
  542. {
  543.   char tmp[MAILTMPLEN];
  544.   if (curhst) fs_give ((void **) &curhst);
  545.   curhst = (char *) fs_get (1+strlen (host));
  546.   strcpy (curhst,host);
  547.   sprintf (tmp,"{%s} username: ",host);
  548.   prompt (tmp,user);
  549.   if (curusr) fs_give ((void **) &curusr);
  550.   curusr = (char *) fs_get (1+strlen (user));
  551.   strcpy (curusr,user);
  552.   prompt ("password: ",pwd);
  553. }
  554.  
  555.  
  556. void mm_critical (stream)
  557.     MAILSTREAM *stream;
  558. {
  559. }
  560.  
  561.  
  562. void mm_nocritical (stream)
  563.     MAILSTREAM *stream;
  564. {
  565. }
  566.  
  567.  
  568. long mm_diskerror (stream,errcode,serious)
  569.     MAILSTREAM *stream;
  570.     long errcode;
  571.     long serious;
  572. {
  573. #if unix
  574.   kill (getpid (),SIGSTOP);
  575. #else
  576.   abort ();
  577. #endif
  578.   return NIL;
  579. }
  580.  
  581.  
  582. void mm_fatal (string)
  583.     char *string;
  584. {
  585.   printf ("?%s\n",string);
  586. }
  587.  
  588. /* SMTP tester */
  589.  
  590. void smtptest (debug)
  591.     long debug;
  592. {
  593.   SMTPSTREAM *stream = NIL;
  594.   char line[MAILTMPLEN];
  595.   unsigned char *text = (unsigned char *) fs_get (8*MAILTMPLEN);
  596.   ENVELOPE *msg = mail_newenvelope ();
  597.   BODY *body = mail_newbody ();
  598.   sprintf (line,"%s <%s@%s>",personalname,curusr,curhst);
  599.   rfc822_parse_adrlist (&msg->from,line,curhst);
  600.   sprintf (line,"%s@%s",curusr,curhst);
  601.   rfc822_parse_adrlist (&msg->return_path,line,curhst);
  602.   prompt ("To: ",line);
  603.   rfc822_parse_adrlist (&msg->to,line,curhst);
  604.   if (msg->to) {
  605.     prompt ("cc: ",line);
  606.     rfc822_parse_adrlist (&msg->cc,line,curhst);
  607.   }
  608.   else {
  609.     prompt ("Newsgroups: ",line);
  610.     if (*line) msg->newsgroups = cpystr (line);
  611.     else {
  612.       mail_free_body (&body);
  613.       mail_free_envelope (&msg);
  614.       fs_give ((void **) &text);
  615.     }
  616.   }
  617.   prompt ("Subject: ",line);
  618.   msg->subject = cpystr (line);
  619.   puts (" Msg (end with a line with only a '.'):");
  620.   body->type = TYPETEXT;
  621.   *text = '\0';
  622.   while (gets (line)) {
  623.     if (line[0] == '.') {
  624.       if (line[1] == '\0') break;
  625.       else strcat ((char *) text,".");
  626.     }
  627.     strcat ((char *) text,line);
  628.     strcat ((char *) text,"\015\012");
  629.   }
  630.   body->contents.text = text;
  631.   rfc822_date (line);
  632.   msg->date = (char *) fs_get (1+strlen (line));
  633.   strcpy (msg->date,line);
  634.   if (msg->to) {
  635.     puts ("Sending...");
  636.     if (stream = smtp_open (hostlist,debug)) {
  637.       if (smtp_mail (stream,"MAIL",msg,body)) puts ("[Ok]");
  638.       else printf ("[Failed - %s]\n",stream->reply);
  639.     }
  640.   }
  641.   else {
  642.     puts ("Posting...");
  643.     if (stream = nntp_open (newslist,debug)) {
  644.       if (nntp_mail (stream,msg,body)) puts ("[Ok]");
  645.       else printf ("[Failed - %s]\n",stream->reply);
  646.     }
  647.   }
  648.   if (stream) smtp_close (stream);
  649.   else puts ("[Can't open connection to any server]");
  650.   mail_free_envelope (&msg);
  651.   mail_free_body (&body);
  652. }
  653.