]> Pileus Git - ~andy/fetchmail/commitdiff
First round ofmlong-delayed bug fixes.
authorEric S. Raymond <esr@thyrsus.com>
Thu, 17 Jul 2003 00:55:18 +0000 (00:55 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Thu, 17 Jul 2003 00:55:18 +0000 (00:55 -0000)
svn path=/trunk/; revision=3814

14 files changed:
NEWS
configure.in
fetchmail-features.html
fetchmail.c
fetchmail.man
fetchmail.py
fetchmailconf
imap.c
pop3.c
sink.c
todo.html
torturetest.glade
torturetest.py
transact.c

diff --git a/NEWS b/NEWS
index 20d09814f1686c35894add322f5340d558cd0aa1..33d6d0b268e02eff7c2563cf53a3ad8303810447 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,13 +2,22 @@
 
 (The `lines' figures total .c, .h, .l, and .y files under version control.)
 
+* German, Danish, Spanish, and Turkish translations updated.
+* Brian Sammon's patch to deal with malformed message lines containiing NULs.
+* Fai's patch to ignore all but the first Return-Path (some spams have
+  more than one of these).
+* Benjamin Drieu's ptch to properly byte-stuff when talking to BSNTP.
+  Fixes Debian bug #184469.
+* Benjamin Drieu's patch to enable auth=cram-md5.
+  Fixes Debian bug #185232.
+
 fetchmail-6.2.2 (Fri Feb 28 21:34:26 EST 2003), 22345 lines:
 
-* Sunil Shetye's patch to imprive behavior in empty messages.
+* Sunil Shetye's patch to improve behavior on empty messages.
 * Conform to RFC2595; reissue capability probes after successful 
   STARTTLS negotiation.
 * Sunil's patch to make handling of failed STARTTLS more graceful.
-* Sunil's JF2 fix patch for .fetchmailrc security fix.
+* Sunil's JF2 fix patch for .fetchmailrc security.
 * Christophe GIAUME <christophe@giaume.com> finished the implementation
   of RFC2177 IDLE.
 * Jason Tishler's fix patch for Cygwin.
@@ -32,7 +41,7 @@ fetchmail-6.2.0 (Fri Dec 13 00:10:07 EST 2002), 22235 lines:
 
 * Applied Steffen Esser's fix for a buffer-overflow bug in rfc822.c
 * Updated Danish, German, and Turkish translation files.
-* Sunil Sheye's SMTP timeout patch.
+* Sunil Shetye's SMTP timeout patch.
 
 There are 538 people on fetchmail-friends and 701 on fetchmail-announce.
 
index d087e4632d707a4204311d756b1738955611681a..6b86ebd042d3f4edd876746cf6d02dbd6fe3d5b3 100644 (file)
@@ -68,7 +68,7 @@ then
 fi
  
 dnl i18n
-ALL_LINGUAS="ca cs da de es fr gl ja pl pt_BR tr sk"
+ALL_LINGUAS="ca cs da de el es fr gl ja pl pt_BR tr sk"
 AM_GNU_GETTEXT
 dnl end i18n
 
index 76baad07ae9f45a0632bdb0a6f5a410453c32b16..cbb4663b4f7f112100faff9c2c709dc4b0160d6d 100644 (file)
@@ -18,7 +18,7 @@
 <tr>
 <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a></td>
 <td width="30%" align="center">To <a href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2003/02/28 10:58:25 $</td>
+<td width="30%" align="right">$Date: 2003/07/17 00:55:17 $</td>
 </tr>
 </table>
 
@@ -61,10 +61,10 @@ delivered-to headers looking exactly the same as the ones it adds
 himself, it bounces the message.</li>
 
 <li>Added --smtpname to set username and domain portion of SMTP
-"RCPT TO" command. &gt;fetchmail@mail.julianhaight.com&gt;.</li>
+"RCPT TO" command. &lt;fetchmail@mail.julianhaight.com&gt;.</li>
 
 <li>Added "from" server's IP address to inserted Received line
-&gt;fetchmail@mail.julianhaight.com&lt;.</li>
+&lt;fetchmail@mail.julianhaight.com&lt;.</li>
 
 <li>Fetchmail now runs on BeOS, thanks to David Reid
 &lt;david@jetnet.co.uk&gt;.</li>
@@ -280,7 +280,7 @@ be unique to fetchmail if I hadn't added it to fetchpop.)</li>
 <tr>
 <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a></td>
 <td width="30%" align="center">To <a href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2003/02/28 10:58:25 $</td>
+<td width="30%" align="right">$Date: 2003/07/17 00:55:17 $</td>
 </tr>
 </table>
 
index e541aa57cbcc0fcaf2e34578fc77d743d924f34c..8a0cdf0b36e212cc80d31e6abd450676762e84c8 100644 (file)
@@ -497,7 +497,7 @@ int main(int argc, char **argv)
     }
     else
     {
-       if (run.logfile && access(run.logfile, F_OK) == 0)
+       if (run.logfile && !nodetach && access(run.logfile, F_OK) == 0)
        {
            if (!freopen(run.logfile, "a", stdout))
                    report(stderr, GT_("could not open %s to append logs to \n"), run.logfile);
index ce90f441fa6777fab2093cfc1bcbab499061b971..86a01bd5530d3ca1b45d2107b1533fb3520b533d 100644 (file)
@@ -401,23 +401,25 @@ this option.  For the command-line option, the list values should
 be comma-separated.
 .TP
 .B \-m <command> | \-\-mda <command>
-(Keyword: mda)
-You can force mail to be passed to an MDA directly (rather than
-forwarded to port 25) with the --mda or -m option.  To avoid losing
-mail, use this option only with MDAs like procmail or sendmail that
-return a nonzero status on disk-full and other resource-exhaustion
-errors; the nonzero status tells fetchmail that delivery failed and
-prevents the message from being deleted off the server.  If
-\fIfetchmail\fR is running as root, it sets its userid to that of the
-target user while delivering mail through an MDA.  Some possible MDAs
-are "/usr/sbin/sendmail -i -f %F %T", "/usr/bin/deliver" and
-"/usr/bin/procmail -d %T" (but the latter is usually redundant as it's
-what SMTP listeners normally forward to).  Local delivery addresses
-will be inserted into the MDA command wherever you place a %T; the
-mail message's From address will be inserted where you place an %F.
-Do \fInot\fR use an MDA invocation like "sendmail -i -t" that
-dispatches on the contents of To/Cc/Bcc, it will create mail loops and
-bring the just wrath of many postmasters down upon your head.
+(Keyword: mda) You can force mail to be passed to an MDA directly
+(rather than forwarded to port 25) with the --mda or -m option.  To
+avoid losing mail, use this option only with MDAs like procmail or
+sendmail that return a nonzero status on disk-full and other
+resource-exhaustion errors; the nonzero status tells fetchmail that
+delivery failed and prevents the message from being deleted off the
+server.  If \fIfetchmail\fR is running as root, it sets its userid to
+that of the target user while delivering mail through an MDA.  Some
+possible MDAs are "/usr/sbin/sendmail -i -f %F %T", "/usr/bin/deliver"
+and "/usr/bin/procmail -d %T" (but the latter is usually redundant as
+it's what SMTP listeners normally forward to).  Local delivery
+addresses will be inserted into the MDA command wherever you place a
+%T; the mail message's From address will be inserted where you place
+an %F.  In both cases the addresses are enclosed in single quotes ('),
+after removing any single quotes they may contain, before the MDA
+command is passed to the shell.  Do \fInot\fR use an MDA invocation
+like "sendmail -i -t" that dispatches on the contents of To/Cc/Bcc, it
+will create mail loops and bring the just wrath of many postmasters
+down upon your head.
 .TP 
 .B \-\-lmtp
 (Keyword: lmtp)
@@ -1320,6 +1322,9 @@ T}
 interval       \&      T{
 Only check this site every N poll cycles; N is a numeric argument.
 T}
+tracepolls     \&      T{
+Add poll tracing information to the Received header
+T}
 netsec         \&      T{
 Pass in IPsec security option request.
 T}
@@ -1476,9 +1481,6 @@ T}
 expunge        -e      T{
 Perform an expunge on every #th message (IMAP and POP3 only)
 T}
-tracepolls     \&      T{
-Add poll tracing information to the Received header
-T}
 properties     \&      T{
 String value is ignored by fetchmail (may be used by extension scripts)
 T}
index ef3c521230313be5ee4e9ce9666f384694b8a8a3..889f59ab3af2dbff3f2d0d4e3b187d133d7c613f 100755 (executable)
@@ -49,17 +49,6 @@ KPOP_PORT    = 1109
 SIMAP_PORT     = 993
 SPOP3_PORT     = 995
 
-# authentication types
-A_ANY          = 0     # use the first method that works
-A_PASSWORD     = 1     # password authentication
-A_NTLM         = 2     # Microsoft NTLM protocol
-A_CRAM_MD5     = 3     # CRAM-MD5 shrouding (RFC2195)
-A_OTP          = 4     # One-time password (RFC1508)
-A_KERBEROS_V4  = 5     # authenticate w/ Kerberos V4
-A_KERBEROS_V5  = 6     # authenticate w/ Kerberos V5
-A_GSSAPI       = 7     # authenticate with GSSAPI
-A_SSH          = 8     # authentication at session level
-
 def DOTLINE(s):
     return (s[0] == '.' and (s[1]=='\r' or s[1]=='\n' or s[1]=='\0'))
 
@@ -174,11 +163,10 @@ class hostdata:
     akalist = []               # server name first, then akas
     localdomains = []          # list of pass-through domains
     protocol = None            # protocol type
-    service = None             # IPv6 service name
     netsec = None              # IPv6 security request
-    port = 0                   # TCP/IP service port number
+    port = None                        # TCP/IP service port number (name in IPV6)
     interval = 0               # cycles to skip between polls
-    authenticate = 'A_PASSWD'  # authentication mode to try
+    authenticate = 'password'  # authentication mode to try
     timeout = 300              # inactivity timout in seconds
     envelope = None            # envelope address list header
     envskip = 0                        # skip to numbered envelope header
@@ -210,6 +198,12 @@ class hostdata:
     lead_server = None         # ptr to lead query for this server
     esmtp_options = []         # ESMTP option list
 
+    def is_mailbox_protocol(self):
+         # We need to distinguish between mailbox and mailbag protocols.
+         # Under a mailbox protocol we're pulling mail for a speecific user.
+         # Under a mailbag protocol we're fetching mail for an entire domain.
+         return self.protocol != proto_etrn
+
 class query:
     "All the parameters of a fetchmail query."
     # mailserver connection controls
@@ -283,11 +277,346 @@ class query:
     mimemsg = 0                        # bitmask indicating MIME body-type
     digest = None
 
-    def mailbox_protocol(self):
-         # We need to distinguish between mailbox and mailbag protocols.
-         # Under a mailbox protocol we're pulling mail for a speecific user.
-         # Under a mailbag protocol we're fetching mail for an entire domain.
-         return self.server.protocol != proto_etrn
+    def dump(self):
+       print "Options for retrieving from %s@%s:" \
+              % (self.remotename, self.server.pollname)
+        if self.server.via and self.server.server.is_mailbox_protocol():
+           print "  Mail will be retrieved via %s" % self.server.via
+       if self.server.interval:
+           print "  Poll of this server will occur every %d intervals." \
+                  % self.server.interval;
+       if self.server.truename:
+           print "  True name of server is %s." % self.server.truename
+       if self.server.skip || outlevel >= O_VERBOSE:
+            if self.server.skip:
+                print "  Will not be queried when no host is specified."
+            else:
+                print "  Will not be queried when no host is specified."
+       if self.server.authenticate not in ('KERBEROS', 'GSSAPI', 'SSH'):
+            if not self.password:
+               print "  Password will be prompted for."
+           else if outlevel >= O_VERBOSE:
+                if self.server.protocol == proto_apop:
+                   print "  APOP secret = \"%s\"." % self.password
+               elif self.server.protocol == proto_rpop:
+                   print "  RPOP id = \"%s\"." % self.password
+               else
+                   print "  Password = \"%s\"." % self.password
+
+       if self.server.protocol == proto_pop3 \
+               and self.server.port == KPOP_PORT \
+               and self.server.authenticate.startswith("Kerberos"):
+            sys.stdout.write("  Protocol is KPOP with %s authentication" \
+                  % self.server.authenticate)
+       else
+           sys.stdout.write("  Protocol is %s" % self.server.protocol.name)
+        if ipv6:
+            if self.server.port:
+                sys.stdout.write(" (using service %s)" % self.server.port)
+            if (self.server.netsec)
+                sys.stdout.write(" (using network security options %s)" % self.server.netsec)
+        else:
+            if self.server.port:
+                sys.stdout.write(" (using port %d)" % self.server.port)
+            else if outlevel >= O_VERBOSE:
+                sys.stdout.write(" (using default port)")
+       if self.server.uidl and self.server.is_mailbox.protocol())
+           sys.stdout.write(" (forcing UIDL use)")
+        sys.stdout.write("\n")
+        print {
+        None :       "  All available authentication methods will be tried.",
+        'password' :    "  Password authentication will be forced.",
+        'NTLM' :        "  NTLM authentication will be forced.",
+        'OTP' :         "  OTP authentication will be forced.",
+        'CRAM-MD5'      "  CRAM-MD5 authentication will be forced.",
+        'GSSAPI' :      "  GSSAPI authentication will be forced.",
+        'Kerberos V4' : "  Kerberos V4 authentication will be forced.",
+        'Kerberos V5' : "  Kerberos V5 authentication will be forced.",
+        'ssh' :         "  End-to-end encryption will be assumed.",
+        }[self.server.authenticate]
+
+        if self.server.principal:
+           print "  Mail service principal is: %s" % self.server.principal
+       if self.use_ssl:
+           print "  SSL encrypted sessions enabled."
+       if self.sslproto:
+           print "  SSL protocol: %s." % self.sslproto;
+       if self.sslcertck:
+           print "  SSL server certificate checking enabled."
+           if self.sslcertpath:
+               print "  SSL trusted certificate directory: %s" % self.sslcertpath;
+       if self.sslfingerprint:
+               print "  SSL key fingerprint (checked against the server key): %s" % self.sslfingerprint;
+       if self.server.timeout > 0:
+           print "  Server nonresponse timeout is %d seconds" % self.server.timeout;
+       if self.server.is_mailbox_protocol(): 
+           if not self.mailboxes.id:
+               print "  Default mailbox selected."
+           else
+               print "  Selected mailboxes are: ", ", ".join(self.mailboxes)
+            flagarray = (
+                ('fetchall', 
+                 "%s messages will be retrieved (--all %s)."
+                 "All", "Only new")
+                ('keep', 
+                 "  Fetched messages %s be kept on the server (--keep %s)."
+                 "will", "will not")
+                ('flush',
+                "  Old messages %s be flushed before message retrieval (--flush %s).",
+                 "will", "will not")
+                ('rewrite',
+                "  Rewrite of server-local addresses is %s (norewrite %s).",
+                 "enabled", "disabled")
+                ('stripcr',
+                "  Carriage-return stripping is %s (stripcr %s).",
+                 "enabled", "disabled")
+                ('forcecr',
+                "  Carriage-return forcing is %s (forcecr %s).",
+                 "enabled", "disabled")
+                ('pass8bits',
+                 "  Interpretation of Content-Transfer-Encoding is %s (pass8bits %s).",
+                 "enabled", "disabled")
+                ('mimedecode',
+                 "  MIME decoding is %s (mimedecode %s).",
+                 "enabled", "disabled")
+                ('idle',
+                 "  Idle after poll is %s (idle %s).",
+                 "enabled", "disabled")
+                ('dropstatus',
+                 "  Nonempty Status lines will be %s (dropstatus %s)",
+                 "discarded", "kept")
+                ('dropdelivered',
+                 "  Delivered-To lines will be %s (dropdelivered %s)",
+                 "discarded", "kept")
+                )
+            for (attr, template, on, off) in flagarray:
+                flag = getattr(self, att)
+                if flag:
+                    onoff1 = on
+                    onoff2 = "on"
+                else:
+                    onoff1 = off
+                    onoff2 = "off"
+                print template % (onoff1, onoff2)
+           if self.limit:
+           {
+               if NUM_NONZERO(self.limit):
+                   print "  Message size limit is %d octets (--limit %d)." % 
+                          self.limit, self.limit);
+               else if outlevel >= O_VERBOSE:
+                   print "  No message size limit (--limit 0)."
+               if run.poll_interval > 0:
+                   print "  Message size warning interval is %d seconds (--warnings %d)." % 
+                          self.warnings, self.warnings);
+               else if outlevel >= O_VERBOSE:
+                   print "  Size warnings on every poll (--warnings 0)."
+           }
+           if NUM_NONZERO(self.fetchlimit):
+               print "  Received-message limit is %d (--fetchlimit %d)."),
+                      self.fetchlimit, self.fetchlimit);
+           else if outlevel >= O_VERBOSE:
+               print "  No received-message limit (--fetchlimit 0)."
+           if NUM_NONZERO(self.batchlimit):
+               print "  SMTP message batch limit is %d." % self.batchlimit);
+           else if outlevel >= O_VERBOSE:
+               print "  No SMTP message batch limit (--batchlimit 0)."
+           if MAILBOX_PROTOCOL(ctl):
+           {
+               if NUM_NONZERO(self.expunge):
+                   print "  Deletion interval between expunges forced to %d (--expunge %d)." % self.expunge, self.expunge);
+               else if outlevel >= O_VERBOSE:
+                   print "  No forced expunges (--expunge 0)."
+           }
+       }
+       else    /* ODMR or ETRN */
+       {
+           struct idlist *idp;
+
+           print "  Domains for which mail will be fetched are:"
+           for (idp = self.domainlist; idp; idp = idp.next:
+           {
+               printf(" %s", idp.id);
+               if not idp.val.status.mark:
+                   print " (default)"
+           }
+           printf("");
+       }
+       if self.bsmtp:
+           print "  Messages will be appended to %s as BSMTP" % visbuf(self.bsmtp
+       else if self.mda and MAILBOX_PROTOCOL(ctl):
+           print "  Messages will be delivered with \"%s\"." % visbuf(self.mda
+       else
+       {
+           struct idlist *idp;
+
+           if self.smtphunt:
+           {
+               print "  Messages will be %cMTP-forwarded to:" % 
+                      self.listener);
+               for (idp = self.smtphunt; idp; idp = idp.next:
+               {
+                   printf(" %s", idp.id);
+                   if not idp.val.status.mark:
+                       print " (default)"
+               }
+               printf("");
+           }
+           if self.smtpaddress:
+               print "  Host part of MAIL FROM line will be %s"),
+                      self.smtpaddress);
+           if self.smtpname:
+               print "  Address to be put in RCPT TO lines shipped to SMTP will be %s"),
+                      self.smtpname);
+       }
+       if MAILBOX_PROTOCOL(ctl):
+       {
+               if self.antispam != (struct idlist *)NULL:
+               {
+                   struct idlist *idp;
+
+                   print "  Recognized listener spam block responses are:"
+                   for (idp = self.antispam; idp; idp = idp.next:
+                       printf(" %d", idp.val.status.num);
+                   printf("");
+               }
+               else if outlevel >= O_VERBOSE:
+                   print "  Spam-blocking disabled"
+       }
+       if self.preconnect:
+           print "  Server connection will be brought up with \"%s\"."),
+                  visbuf(self.preconnect
+       else if outlevel >= O_VERBOSE:
+           print "  No pre-connection command."
+       if self.postconnect:
+           print "  Server connection will be taken down with \"%s\"."),
+                  visbuf(self.postconnect
+       else if outlevel >= O_VERBOSE:
+           print "  No post-connection command."
+       if MAILBOX_PROTOCOL(ctl)) {
+               if !self.localnames:
+                   print "  No localnames declared for this host."
+               else
+               {
+                   struct idlist *idp;
+                   int count = 0;
+
+                   for (idp = self.localnames; idp; idp = idp.next:
+                       ++count;
+
+                   if count > 1 || self.wildcard:
+                       print "  Multi-drop mode: "
+                   else
+                       print "  Single-drop mode: "
+
+                   print "%d local name(s) recognized." % count);
+                   if outlevel >= O_VERBOSE:
+                   {
+                       for (idp = self.localnames; idp; idp = idp.next:
+                           if idp.val.id2:
+                               printf("\t%s . %s", idp.id, idp.val.id2);
+                           else
+                               printf("\t%s", idp.id);
+                       if self.wildcard:
+                           fputs("\t*", stdout);
+                   }
+
+                   if count > 1 || self.wildcard:
+                   {
+                       print "  DNS lookup for multidrop addresses is %s."),
+                              self.server.dns ? GT_("enabled") : GT_("disabled"
+                       if self.server.dns:
+                       {
+                           print "  Server aliases will be compared with multidrop addresses by "
+                           if self.server.checkalias:
+                               print "IP address."
+                           else
+                               print "name."
+                       }
+                       if self.server.envelope == STRING_DISABLED:
+                           print "  Envelope-address routing is disabled"
+                       else
+                       {
+                           print "  Envelope header is assumed to be: %s"),
+                                  self.server.envelope ? self.server.envelope:GT_("Received"
+                           if self.server.envskip > 1 || outlevel >= O_VERBOSE:
+                               print "  Number of envelope header to be parsed: %d"),
+                                      self.server.envskip);
+                           if self.server.qvirtual:
+                               print "  Prefix %s will be removed from user id"),
+                                      self.server.qvirtual);
+                           else if outlevel >= O_VERBOSE) 
+                               print "  No prefix stripping"
+                       }
+
+                       if self.server.akalist:
+                       {
+                           struct idlist *idp;
+
+                           print "  Predeclared mailserver aliases:"
+                           for (idp = self.server.akalist; idp; idp = idp.next:
+                               printf(" %s", idp.id);
+                           putchar('');
+                       }
+                       if self.server.localdomains:
+                       {
+                           struct idlist *idp;
+
+                           print "  Local domains:"
+                           for (idp = self.server.localdomains; idp; idp = idp.next:
+                               printf(" %s", idp.id);
+                           putchar('');
+                       }
+                   }
+               }
+       }
+#if defined(linux) || defined(__FreeBSD__:
+       if self.server.interface:
+           print "  Connection must be through interface %s." % self.server.interface);
+       else if outlevel >= O_VERBOSE:
+           print "  No interface requirement specified."
+       if self.server.monitor:
+           print "  Polling loop will monitor %s." % self.server.monitor);
+       else if outlevel >= O_VERBOSE:
+           print "  No monitor interface specified."
+#endif
+
+       if self.server.plugin:
+           print "  Server connections will be made via plugin %s (--plugin %s)." % self.server.plugin, self.server.plugin);
+       else if outlevel >= O_VERBOSE:
+           print "  No plugin command specified."
+       if self.server.plugout:
+           print "  Listener connections will be made via plugout %s (--plugout %s)." % self.server.plugout, self.server.plugout);
+       else if outlevel >= O_VERBOSE:
+           print "  No plugout command specified."
+
+       if self.server.protocol > P_POP2 and MAILBOX_PROTOCOL(ctl):
+       {
+           if !self.oldsaved:
+               print "  No UIDs saved from this host."
+           else
+           {
+               struct idlist *idp;
+               int count = 0;
+
+               for (idp = self.oldsaved; idp; idp = idp.next:
+                   ++count;
+
+               print "  %d UIDs saved." % count);
+               if outlevel >= O_VERBOSE:
+                   for (idp = self.oldsaved; idp; idp = idp.next:
+                       printf("\t%s", idp.id);
+           }
+       }
+
+        if self.tracepolls:
+            print "  Poll trace information will be added to the Received header."
+        else if outlevel >= O_VERBOSE:
+            print "  No poll trace information will be added to the Received header.."
+
+       if self.properties:
+           print "  Pass-through properties \"%s\"." % self.properties
+
+
 
 if __name__ == '__main__':
     # C version queried FETCHMAILUSER, then USER, then LOGNAME.
index a6c3d1727e3b06a1971f10705984cd59f041e52a..86ab944574f4e1f4cada4d9441415c4eb3b928bf 100755 (executable)
@@ -1844,10 +1844,10 @@ whether to use POP or IMAP, and so forth).
        self.configbutton.pack()
 
        Message(self, text="""
-Use `Test fetchmail' to run fetchmail with debugging enabled.
+Use `Run fetchmail' to run fetchmail with debugging enabled.
 This is a good way to test out a new configuration.
 """, width=600).pack(side=TOP)
-       Button(self, text='Test fetchmail',fg='blue', command=self.test).pack()
+       Button(self, text='Run fetchmail',fg='blue', command=self.test).pack()
 
        Message(self, text="""
 Use `Run fetchmail' to run fetchmail in foreground.
diff --git a/imap.c b/imap.c
index c3ec139569857f807fc1426ffd7f069c6b80f7b5..3e6d80fc8ed4a45d6413b7235a4dde3af80e59d8 100644 (file)
--- a/imap.c
+++ b/imap.c
@@ -416,9 +416,8 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
      * in a challenge-response.
      */
 
-    if ((ctl->server.authenticate == A_ANY 
-        || ctl->server.authenticate == A_CRAM_MD5)
-       && strstr(capabilities, "AUTH=CRAM-MD5"))
+    if ((ctl->server.authenticate == A_ANY && strstr(capabilities, "AUTH=CRAM-MD5"))
+       || ctl->server.authenticate == A_CRAM_MD5)
     {
        if ((ok = do_cram_md5 (sock, "AUTHENTICATE", ctl, NULL)))
        {
diff --git a/pop3.c b/pop3.c
index 02e38c3f3a8b7221406a6a4ead00a668d6bff206..50673ffe9359d7bdd9b718010cfb3a12a9019e54 100644 (file)
--- a/pop3.c
+++ b/pop3.c
@@ -354,9 +354,8 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting)
        }
 #endif /* OPIE_ENABLE */
 
-       if (has_cram &&
-           (ctl->server.authenticate == A_CRAM_MD5 ||
-            ctl->server.authenticate == A_ANY))
+       if (ctl->server.authenticate == A_CRAM_MD5 || 
+           (has_cram && ctl->server.authenticate == A_ANY))
        {
            ok = do_cram_md5(sock, "AUTH", ctl, NULL);
            if (ok == PS_SUCCESS || ctl->server.authenticate != A_ANY)
diff --git a/sink.c b/sink.c
index aee27f7e01e0de81f5b8d33eae4f001abe10143d..a8395661adee7b1f9af3da971bc86215344e70c4 100644 (file)
--- a/sink.c
+++ b/sink.c
@@ -624,10 +624,15 @@ int stuffline(struct query *ctl, char *buf)
        }
         else /* if (!protocol->delimited)      -- not byte-stuffed already */
        {
-           if (!ctl->mda)
-               SockWrite(ctl->smtp_socket, buf, 1);    /* byte-stuff it */
-           else
-               /* leave it alone */;
+         if (!ctl->mda)      /* byte-stuff it */
+           {
+             if (!ctl->bsmtp)
+               SockWrite(ctl->smtp_socket, buf, 1);
+             else
+               {
+                 fwrite(buf, 1, 1, sinkfp);
+               }
+           }
        }
     }
 
index 762859499aeebce4a7a8394c14c9a05833d02a2c..5d695b5531043bf83241dfd3c26bb2232327d176 100644 (file)
--- a/todo.html
+++ b/todo.html
@@ -19,7 +19,7 @@ content="Known bugs and to-do items in fetchmail" />
 <tr>
 <td width="30%">Back to <a href="/~esr">Eric's Home Page</a></td>
 <td width="30%" align="center">Up to <a href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2003/02/28 21:57:59 $</td>
+<td width="30%" align="right">$Date: 2003/07/17 00:55:18 $</td>
 </tr>
 </table>
 
@@ -55,6 +55,8 @@ debugger and check this.</p>
 <p>In the SSL support, add authentication of Certifying Authority
 (Is this a Certifying Authority we recognize?).</p>
 
+<p>Debian wishlist item 181157: ssl key learning for self-signed certificates.</p>
+
 <p>Laszlo Vecsey writes: "I believe qmail uses a technique of
 writing temporary files to nfs, and then moving them into place to
 ensure that they're written. Actually a hardlink is made to the
@@ -80,7 +82,7 @@ reports.</p>
 <tr>
 <td width="30%">Back to <a href="/~esr">Eric's Home Page</a></td>
 <td width="30%" align="center">Up to <a href="/~esr/sitemap.html">Site Map</a></td>
-<td width="30%" align="right">$Date: 2003/02/28 21:57:59 $</td>
+<td width="30%" align="right">$Date: 2003/07/17 00:55:18 $</td>
 </tr>
 </table>
 
index 4f648a979f25875f3463cd4036ddc99921bb34aa..d2cf07ee5b16a8d3002563245922357958a64d38 100644 (file)
          <property name="visible">True</property>
          <property name="n_rows">9</property>
          <property name="n_columns">2</property>
-         <property name="homogeneous">True</property>
+         <property name="homogeneous">False</property>
          <property name="row_spacing">0</property>
          <property name="column_spacing">0</property>
 
          </child>
 
          <child>
-           <widget class="GtkHBox" id="hbox1">
+           <widget class="GtkEntry" id="host_entry">
+             <property name="visible">True</property>
+             <property name="can_focus">True</property>
+             <property name="editable">True</property>
+             <property name="visibility">True</property>
+             <property name="max_length">0</property>
+             <property name="text" translatable="yes"></property>
+             <property name="has_frame">True</property>
+             <property name="invisible_char" translatable="yes">*</property>
+             <property name="activates_default">False</property>
+           </widget>
+           <packing>
+             <property name="left_attach">1</property>
+             <property name="right_attach">2</property>
+             <property name="top_attach">0</property>
+             <property name="bottom_attach">1</property>
+             <property name="y_options"></property>
+           </packing>
+         </child>
+
+         <child>
+           <widget class="GtkHBox" id="hbox8">
              <property name="visible">True</property>
-             <property name="homogeneous">True</property>
+             <property name="homogeneous">False</property>
              <property name="spacing">0</property>
 
              <child>
-               <widget class="GtkRadioButton" id="POP3_radiobutton">
+               <widget class="GtkHBox" id="hbox1">
                  <property name="visible">True</property>
-                 <property name="can_focus">True</property>
-                 <property name="label" translatable="yes">POP3</property>
-                 <property name="use_underline">True</property>
-                 <property name="relief">GTK_RELIEF_NORMAL</property>
-                 <property name="active">False</property>
-                 <property name="inconsistent">False</property>
-                 <property name="draw_indicator">True</property>
+                 <property name="homogeneous">True</property>
+                 <property name="spacing">0</property>
+
+                 <child>
+                   <widget class="GtkRadioButton" id="POP3_radiobutton">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">POP3</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkRadioButton" id="APOP_radiobutton">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">APOP</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                     <property name="group">POP3_radiobutton</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
+
+                 <child>
+                   <widget class="GtkRadioButton" id="IMAP_radiobutton">
+                     <property name="visible">True</property>
+                     <property name="can_focus">True</property>
+                     <property name="label" translatable="yes">IMAP</property>
+                     <property name="use_underline">True</property>
+                     <property name="relief">GTK_RELIEF_NORMAL</property>
+                     <property name="active">False</property>
+                     <property name="inconsistent">False</property>
+                     <property name="draw_indicator">True</property>
+                     <property name="group">POP3_radiobutton</property>
+                   </widget>
+                   <packing>
+                     <property name="padding">0</property>
+                     <property name="expand">False</property>
+                     <property name="fill">False</property>
+                   </packing>
+                 </child>
                </widget>
                <packing>
                  <property name="padding">0</property>
-                 <property name="expand">False</property>
-                 <property name="fill">False</property>
+                 <property name="expand">True</property>
+                 <property name="fill">True</property>
                </packing>
              </child>
 
              <child>
-               <widget class="GtkRadioButton" id="APOP_radiobutton">
+               <widget class="GtkVSeparator" id="vseparator1">
                  <property name="visible">True</property>
-                 <property name="can_focus">True</property>
-                 <property name="label" translatable="yes">APOP</property>
-                 <property name="use_underline">True</property>
-                 <property name="relief">GTK_RELIEF_NORMAL</property>
-                 <property name="active">False</property>
-                 <property name="inconsistent">False</property>
-                 <property name="draw_indicator">True</property>
-                 <property name="group">POP3_radiobutton</property>
                </widget>
                <packing>
                  <property name="padding">0</property>
-                 <property name="expand">False</property>
-                 <property name="fill">False</property>
+                 <property name="expand">True</property>
+                 <property name="fill">True</property>
                </packing>
              </child>
 
              <child>
-               <widget class="GtkRadioButton" id="IMAP_radiobutton">
+               <widget class="GtkCheckButton" id="ssl_checkbox">
                  <property name="visible">True</property>
                  <property name="can_focus">True</property>
-                 <property name="label" translatable="yes">IMAP</property>
+                 <property name="label" translatable="yes">SSL</property>
                  <property name="use_underline">True</property>
                  <property name="relief">GTK_RELIEF_NORMAL</property>
                  <property name="active">False</property>
                  <property name="inconsistent">False</property>
                  <property name="draw_indicator">True</property>
-                 <property name="group">POP3_radiobutton</property>
                </widget>
                <packing>
                  <property name="padding">0</property>
-                 <property name="expand">False</property>
-                 <property name="fill">False</property>
+                 <property name="expand">True</property>
+                 <property name="fill">True</property>
                </packing>
              </child>
            </widget>
              <property name="y_options">fill</property>
            </packing>
          </child>
-
-         <child>
-           <widget class="GtkEntry" id="host_entry">
-             <property name="visible">True</property>
-             <property name="can_focus">True</property>
-             <property name="editable">True</property>
-             <property name="visibility">True</property>
-             <property name="max_length">0</property>
-             <property name="text" translatable="yes"></property>
-             <property name="has_frame">True</property>
-             <property name="invisible_char" translatable="yes">*</property>
-             <property name="activates_default">False</property>
-           </widget>
-           <packing>
-             <property name="left_attach">1</property>
-             <property name="right_attach">2</property>
-             <property name="top_attach">0</property>
-             <property name="bottom_attach">1</property>
-             <property name="y_options"></property>
-           </packing>
-         </child>
        </widget>
        <packing>
          <property name="padding">0</property>
-         <property name="expand">True</property>
-         <property name="fill">True</property>
+         <property name="expand">False</property>
+         <property name="fill">False</property>
        </packing>
       </child>
 
          <property name="spacing">0</property>
 
          <child>
-           <widget class="GtkButton" id="update_button">
+           <widget class="GtkButton" id="updatebutton">
              <property name="visible">True</property>
              <property name="can_default">True</property>
              <property name="can_focus">True</property>
-             <property name="label" translatable="yes">Update</property>
-             <property name="use_underline">True</property>
              <property name="relief">GTK_RELIEF_NORMAL</property>
+             <signal name="clicked" handler="on_updatebutton_clicked" last_modification_time="Wed, 16 Jul 2003 23:17:30 GMT"/>
+
+             <child>
+               <widget class="GtkAlignment" id="alignment4">
+                 <property name="visible">True</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xscale">0</property>
+                 <property name="yscale">0</property>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox6">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">2</property>
+
+                     <child>
+                       <widget class="GtkImage" id="image4">
+                         <property name="visible">True</property>
+                         <property name="stock">gtk-apply</property>
+                         <property name="icon_size">4</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkLabel" id="label14">
+                         <property name="visible">True</property>
+                         <property name="label" translatable="yes">Update</property>
+                         <property name="use_underline">True</property>
+                         <property name="use_markup">False</property>
+                         <property name="justify">GTK_JUSTIFY_LEFT</property>
+                         <property name="wrap">False</property>
+                         <property name="selectable">False</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
            </widget>
          </child>
 
          <child>
-           <widget class="GtkButton" id="button7">
+           <widget class="GtkButton" id="newbutton">
              <property name="visible">True</property>
              <property name="can_default">True</property>
              <property name="can_focus">True</property>
-             <property name="label" translatable="yes">New</property>
-             <property name="use_underline">True</property>
              <property name="relief">GTK_RELIEF_NORMAL</property>
              <signal name="clicked" handler="on_newbutton_clicked" last_modification_time="Wed, 16 Jul 2003 20:28:12 GMT"/>
+
+             <child>
+               <widget class="GtkAlignment" id="alignment1">
+                 <property name="visible">True</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xscale">0</property>
+                 <property name="yscale">0</property>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox3">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">2</property>
+
+                     <child>
+                       <widget class="GtkImage" id="image1">
+                         <property name="visible">True</property>
+                         <property name="stock">gtk-new</property>
+                         <property name="icon_size">4</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkLabel" id="label11">
+                         <property name="visible">True</property>
+                         <property name="label" translatable="yes">New</property>
+                         <property name="use_underline">True</property>
+                         <property name="use_markup">False</property>
+                         <property name="justify">GTK_JUSTIFY_LEFT</property>
+                         <property name="wrap">False</property>
+                         <property name="selectable">False</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
            </widget>
          </child>
 
          <child>
-           <widget class="GtkButton" id="button6">
+           <widget class="GtkButton" id="testbutton">
              <property name="visible">True</property>
              <property name="can_default">True</property>
              <property name="can_focus">True</property>
-             <property name="label" translatable="yes">Test</property>
-             <property name="use_underline">True</property>
              <property name="relief">GTK_RELIEF_NORMAL</property>
              <signal name="clicked" handler="on_testbutton_clicked" last_modification_time="Wed, 16 Jul 2003 20:28:23 GMT"/>
+
+             <child>
+               <widget class="GtkAlignment" id="alignment3">
+                 <property name="visible">True</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xscale">0</property>
+                 <property name="yscale">0</property>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox5">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">2</property>
+
+                     <child>
+                       <widget class="GtkImage" id="image3">
+                         <property name="visible">True</property>
+                         <property name="stock">gtk-execute</property>
+                         <property name="icon_size">4</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkLabel" id="label13">
+                         <property name="visible">True</property>
+                         <property name="label" translatable="yes">Test</property>
+                         <property name="use_underline">True</property>
+                         <property name="use_markup">False</property>
+                         <property name="justify">GTK_JUSTIFY_LEFT</property>
+                         <property name="wrap">False</property>
+                         <property name="selectable">False</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
            </widget>
          </child>
 
          <child>
-           <widget class="GtkButton" id="button5">
+           <widget class="GtkButton" id="quitbutton">
              <property name="visible">True</property>
              <property name="can_default">True</property>
              <property name="can_focus">True</property>
-             <property name="label" translatable="yes">Quit</property>
-             <property name="use_underline">True</property>
              <property name="relief">GTK_RELIEF_NORMAL</property>
              <signal name="clicked" handler="on_quitbutton_clicked" last_modification_time="Wed, 16 Jul 2003 20:08:46 GMT"/>
+
+             <child>
+               <widget class="GtkAlignment" id="alignment2">
+                 <property name="visible">True</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xscale">0</property>
+                 <property name="yscale">0</property>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox4">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">2</property>
+
+                     <child>
+                       <widget class="GtkImage" id="image2">
+                         <property name="visible">True</property>
+                         <property name="stock">gtk-quit</property>
+                         <property name="icon_size">4</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkLabel" id="label12">
+                         <property name="visible">True</property>
+                         <property name="label" translatable="yes">Quit</property>
+                         <property name="use_underline">True</property>
+                         <property name="use_markup">False</property>
+                         <property name="justify">GTK_JUSTIFY_LEFT</property>
+                         <property name="wrap">False</property>
+                         <property name="selectable">False</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
+           </widget>
+         </child>
+
+         <child>
+           <widget class="GtkButton" id="dumpbutton">
+             <property name="visible">True</property>
+             <property name="can_default">True</property>
+             <property name="can_focus">True</property>
+             <property name="relief">GTK_RELIEF_NORMAL</property>
+             <signal name="clicked" handler="on_dumpbutton_clicked" last_modification_time="Wed, 16 Jul 2003 23:34:47 GMT"/>
+
+             <child>
+               <widget class="GtkAlignment" id="alignment5">
+                 <property name="visible">True</property>
+                 <property name="xalign">0.5</property>
+                 <property name="yalign">0.5</property>
+                 <property name="xscale">0</property>
+                 <property name="yscale">0</property>
+
+                 <child>
+                   <widget class="GtkHBox" id="hbox7">
+                     <property name="visible">True</property>
+                     <property name="homogeneous">False</property>
+                     <property name="spacing">2</property>
+
+                     <child>
+                       <widget class="GtkImage" id="image5">
+                         <property name="visible">True</property>
+                         <property name="stock">gtk-print</property>
+                         <property name="icon_size">4</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+
+                     <child>
+                       <widget class="GtkLabel" id="label15">
+                         <property name="visible">True</property>
+                         <property name="label" translatable="yes">Dump</property>
+                         <property name="use_underline">True</property>
+                         <property name="use_markup">False</property>
+                         <property name="justify">GTK_JUSTIFY_LEFT</property>
+                         <property name="wrap">False</property>
+                         <property name="selectable">False</property>
+                         <property name="xalign">0.5</property>
+                         <property name="yalign">0.5</property>
+                         <property name="xpad">0</property>
+                         <property name="ypad">0</property>
+                       </widget>
+                       <packing>
+                         <property name="padding">0</property>
+                         <property name="expand">False</property>
+                         <property name="fill">False</property>
+                       </packing>
+                     </child>
+                   </widget>
+                 </child>
+               </widget>
+             </child>
            </widget>
          </child>
        </widget>
        <packing>
          <property name="padding">0</property>
-         <property name="expand">True</property>
-         <property name="fill">True</property>
+         <property name="expand">False</property>
+         <property name="fill">False</property>
        </packing>
       </child>
     </widget>
index c0c07e097798240bdc23c998d44a3317419b22cc..f8a3535cf3244071da0d9ad92e27341a942019c2 100755 (executable)
@@ -2,23 +2,27 @@
 
 import sys, getopt, os, smtplib, commands, time, gtk, gtk.glade
 
+protocols = ('POP3', 'APOP', 'IMAP',)
+
 class TestSite:
     temp = "/usr/tmp/torturestest-%d" % os.getpid()
 
     def __init__(self, line=None):
         "Initialize site data from the external representation."
-        self.site = ""
+        self.host = ""
         self.mailaddr = ""
         self.username = ""
         self.password = ""
         self.protocol = ""
+        self.ssl = ""
         self.options = ""
         self.capabilities = ""
         self.recognition = ""
         self.comment = ""
         if line:
             (self.host, self.mailaddr, self.username, self.password, \
-                self.protocol, self.options, self.capabilities, self.recognition, self.comment) = \
+             self.protocol, self.ssl, self.options, self.capabilities, \
+             self.recognition, self.comment) = \
                 line.strip().split(":")
         if not self.mailaddr:
             self.mailaddr = self.username
@@ -27,9 +31,9 @@ class TestSite:
         self.output = None
 
     def allattrs(self):
-        "Return a tuple consisting of alll this site's attributes."
+        "Return a tuple consisting of all this site's attributes."
         return (self.host, self.mailaddr, self.username, self.password, \
-                self.protocol, self.options, self.capabilities, \
+                self.protocol, self.ssl, self.options, self.capabilities, \
                 self.recognition, self.comment)
 
     def __repr__(self):
@@ -43,6 +47,7 @@ class TestSite:
               "Username: %s\n" \
               "Password: %s\n" \
               "Protocol: %s\n" \
+              "SSL: %s\n" \
               "Options: %s\n" \
               "Capabilities: %s\n" \
               "Recognition: %s\n" \
@@ -51,9 +56,13 @@ class TestSite:
 
     def entryprint(self):
         "Print a .fetchmailrc entry corresponding to a site entry."
-        return "poll %s-%s via %s with proto %s %s\n" \
-               "   user %s there with password '%s' is esr here\n\n" \
+        rep = "poll %s-%s via %s with proto %s %s\n" \
+               "   user %s there with password '%s' is esr here" \
                % (self.host,self.protocol,self.host,self.protocol,self.options,self.username,self.password)
+        if self.ssl and self.ssl != 'False':
+            rep += " options ssl"
+        rep += "\n\n"
+        return rep
 
     def tableprint(self):
         "Print an HTML server-type table entry."
@@ -84,14 +93,20 @@ class TestSite:
         server.sendmail(fromaddr, toaddr, msg)
         server.quit()
 
-    def fetch(self):
+    def fetch(self, logfile=False):
         "Run a mail fetch on this site."
         try:
             ofp = open(TestSite.temp, "w")
-            ofp.write('defaults mda "(echo; echo \'From torturetest\' `date`; cat) >>TEST.LOG"\n')
+            if logfile:
+                mda = "(echo; echo \'From torturetest\' `date`;cat) >>TEST.LOG"
+            else:
+                mda = 'cat'
+            ofp.write('defaults mda "%s"\n' % mda)
             ofp.write(self.entryprint())
             ofp.close()
             (self.status, self.output) = commands.getstatusoutput("fetchmail -d0 -v -f - <%s"%TestSite.temp)
+            if self.status:
+                os.system("cat " + TestSite.temp)
         finally:
             os.remove(TestSite.temp)
 
@@ -121,6 +136,7 @@ class TortureGUI:
         # File in initial values
         self.combo = self.wtree.get_widget("combo1")
         self.combo.set_popdown_strings(map(lambda x: x.comment, sitelist))
+        self.sslcheck = self.wtree.get_widget("ssl_checkbox")
         self.site = sitelist[0]
         self.display(self.site)
 
@@ -131,6 +147,7 @@ class TortureGUI:
                     'on_newbutton_clicked',
                     'on_testbutton_clicked',
                     'on_quitbutton_clicked',
+                    'on_dumpbutton_clicked',
                     'on_combo_entry1_activate'):
            mydict[key] = getattr(self, key)
        self.wtree.signal_autoconnect(mydict)
@@ -164,22 +181,32 @@ class TortureGUI:
     def display(self, site):
         for member in TortureGUI.field_map:
             self.set_widget(member + "_entry", getattr(site, member))
-        for proto in ('POP3', 'APOP', 'IMAP'):
+        for proto in protocols:
             self.wtree.get_widget(proto + "_radiobutton").set_active(site.protocol == proto)
-        self.combo.entry.set_text(self.site.comment)
+        self.sslcheck.set_active(int(site.ssl != '' and site.ssl != 'False'))
+        self.combo.entry.set_text(site.comment)
 
     def update(self, site):
         for member in TortureGUI.field_map:
             setattr(site, member, self.get_widget(member + "_entry"))
-            for proto in ('POP3', 'APOP', 'IMAP'):
-                if self.wtree.get_widget(proto + "_radiobutton").get_active():
-                    site.proto = proto
+        for proto in protocols:
+            if self.wtree.get_widget(proto + "_radiobutton").get_active():
+                site.protocol = proto
+        if self.wtree.get_widget("ssl_checkbox").get_active():
+            site.ssl = "True"
+        else:
+            site.ssl = "False"
 
     # Housekeeping
     def on_torturetest_destroy(self, obj):
         gtk.mainquit()
     def on_updatebutton_clicked(self, obj):
-        self.update()
+        self.update(self.site)
+        print self.site
+        if self.site.comment:
+            self.combo.entry.set_text(self.site.comment)
+        else:
+            self.combo.entry.set_text(self.site.host)
     def on_newbutton_clicked(self, obj):
         global sitelist
         sitelist = [TestSite()] + sitelist
@@ -187,11 +214,13 @@ class TortureGUI:
         self.display(self.site)
         self.combo.entry.set_text("")
     def on_testbutton_clicked(self, obj):
-        self.site.fetch()
-        print site.output
+        self.site.fetch(False)
+        print self.site.output
     def on_quitbutton_clicked(self, obj):
         gtk.mainquit()
-    
+    def on_dumpbutton_clicked(self, obj):
+        print `self.site`
+
     def on_combo_entry1_activate(self, obj):
         key = self.combo.entry.get_text()
         for site in sitelist:
@@ -274,7 +303,7 @@ if __name__ == "__main__":
         os.system("fetchmail -q")
         for site in sitelist:
             print "Testing " + site.id()
-            site.fetch()
+            site.fetch(True)
             if verbose:
                 print site.output
             if site.failed():
index 6674a3ff4ca4a79e5dee23a7121cf1459fc6e5c9..fb8fb0436dcc3f663608c049b1471610088f76a8 100644 (file)
@@ -381,6 +381,7 @@ int readheaders(int sock,
     flag               headers_ok, has_nuls;
     int                        olderrs, good_addresses, bad_addresses;
     int                        retain_mail = 0;
+    flag               already_has_return_path = FALSE;
 
     sizeticker = 0;
     has_nuls = headers_ok = FALSE;
@@ -676,9 +677,15 @@ int readheaders(int sock,
         * not trigger bounces if delivery fails.  What we *do* need to do is
         * make sure we never try to rewrite such a blank Return-Path.  We
         * handle this with a check for <> in the rewrite logic above.
+        *
+        * Also, if an email has multiple Return-Path: statement, we only
+        * read the first occurance, as some spam email has more than one
+        * Return-Path.
+        *
         */
-       if (!strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line)))
+       if ((already_has_return_path==FALSE) && !strncasecmp("Return-Path:", line, 12) && (cp = nxtaddr(line)))
        {
+           already_has_return_path = TRUE;
            strncpy(msgblk.return_path, cp, sizeof(msgblk.return_path));
            msgblk.return_path[sizeof(msgblk.return_path)-1] = '\0';
            if (!ctl->mda) {