aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS15
-rw-r--r--configure.in2
-rw-r--r--fetchmail-features.html8
-rw-r--r--fetchmail.c2
-rw-r--r--fetchmail.man42
-rwxr-xr-xfetchmail.py367
-rwxr-xr-xfetchmailconf4
-rw-r--r--imap.c5
-rw-r--r--pop3.c5
-rw-r--r--sink.c13
-rw-r--r--todo.html6
-rw-r--r--torturetest.glade457
-rwxr-xr-xtorturetest.py65
-rw-r--r--transact.c9
14 files changed, 853 insertions, 147 deletions
diff --git a/NEWS b/NEWS
index 20d09814..33d6d0b2 100644
--- 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.
diff --git a/configure.in b/configure.in
index d087e463..6b86ebd0 100644
--- a/configure.in
+++ b/configure.in
@@ -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
diff --git a/fetchmail-features.html b/fetchmail-features.html
index 76baad07..cbb4663b 100644
--- a/fetchmail-features.html
+++ b/fetchmail-features.html
@@ -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>
diff --git a/fetchmail.c b/fetchmail.c
index e541aa57..8a0cdf0b 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -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);
diff --git a/fetchmail.man b/fetchmail.man
index ce90f441..86a01bd5 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -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}
diff --git a/fetchmail.py b/fetchmail.py
index ef3c5212..889f59ab 100755
--- a/fetchmail.py
+++ b/fetchmail.py
@@ -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.
diff --git a/fetchmailconf b/fetchmailconf
index a6c3d172..86ab9445 100755
--- a/fetchmailconf
+++ b/fetchmailconf
@@ -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 c3ec1395..3e6d80fc 100644
--- 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 02e38c3f..50673ffe 100644
--- 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 aee27f7e..a8395661 100644
--- 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);
+ }
+ }
}
}
diff --git a/todo.html b/todo.html
index 76285949..5d695b55 100644
--- 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>
diff --git a/torturetest.glade b/torturetest.glade
index 4f648a97..d2cf07ee 100644
--- a/torturetest.glade
+++ b/torturetest.glade
@@ -107,7 +107,7 @@
<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>
@@ -475,64 +475,127 @@
</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>
@@ -545,32 +608,11 @@
<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>
@@ -592,56 +634,339 @@
<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>
diff --git a/torturetest.py b/torturetest.py
index c0c07e09..f8a3535c 100755
--- a/torturetest.py
+++ b/torturetest.py
@@ -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():
diff --git a/transact.c b/transact.c
index 6674a3ff..fb8fb043 100644
--- a/transact.c
+++ b/transact.c
@@ -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) {