aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS15
-rw-r--r--README2
-rw-r--r--driver.c46
-rw-r--r--fetchmail.h1
-rw-r--r--smtp.c60
-rw-r--r--smtp.h7
6 files changed, 120 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index 77dbc111..769d933f 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,21 @@
Release Notes:
------------------------------------------------------------------------------
+fetchmail-3.1 ()
+
+features --
+
+* Forwarding is now done via ESMTP where possible.
+
+* ESMTP 8BITMIME option is supported; when 8BITMIME is supported and the
+ Content-Transfer-Encoding header is 7BIT or 8BIT, it is appended to the
+ MAIL FROM command as a BODY option.
+
+bugs --
+
+* Compilation fixes for non-Linux machines.
+
+------------------------------------------------------------------------------
fetchmail-3.0 (Tue Jan 21 16:44:56 EST 1997)
features --
diff --git a/README b/README
index c97919d2..8b610fac 100644
--- a/README
+++ b/README
@@ -69,6 +69,8 @@ pop-perl5-1.2, popc, popmail-1.6 and upop) are marked with **.
* Strict conformance to relevant RFCs and good debugging options.
You could use fetchmail to test and debug server implementatations.
+ * Message and header processing are 8-bit clean.
+
* Carefully written, comprehensive and up-to-date man page describing
not only modes of operation but also (**) how to diagnose the most
common kinds of problems and what to do about deficient servers
diff --git a/driver.c b/driver.c
index 5c3f926f..53e1b96f 100644
--- a/driver.c
+++ b/driver.c
@@ -352,7 +352,22 @@ static FILE *smtp_open(struct query *ctl)
batchcount = 0;
}
- /* if no socket to this host is already set up, try to open one */
+ /* if no socket to this host is already set up, try to open ESMTP */
+ if (lead->smtp_sockfp == (FILE *)NULL)
+ {
+ if ((lead->smtp_sockfp = SockOpen(lead->smtphost, SMTP_PORT)) == (FILE *)NULL)
+ return((FILE *)NULL);
+ else if (SMTP_ok(lead->smtp_sockfp) != SM_OK
+ || SMTP_ehlo(lead->smtp_sockfp,
+ ctl->server.names->id,
+ &lead->server.esmtp_options) != SM_OK)
+ {
+ fclose(lead->smtp_sockfp);
+ lead->smtp_sockfp = (FILE *)NULL;
+ }
+ }
+
+ /* if opening for ESMTP failed, try SMTP */
if (lead->smtp_sockfp == (FILE *)NULL)
{
if ((lead->smtp_sockfp = SockOpen(lead->smtphost, SMTP_PORT)) == (FILE *)NULL)
@@ -378,7 +393,7 @@ char *realname; /* real name of host */
{
char buf [MSGBUFSIZE+1];
char *bufp, *headers, *fromhdr,*tohdr,*cchdr,*bcchdr,*received_for,*envto;
- char *fromptr, *toptr;
+ char *fromptr, *toptr, *ctthdr;
int n, oldlen, ch;
int inheaders, sizeticker;
FILE *sinkfp;
@@ -389,7 +404,7 @@ char *realname; /* real name of host */
/* read the message content from the server */
inheaders = 1;
- headers = fromhdr = tohdr = cchdr = bcchdr = received_for = envto = NULL;
+ headers = fromhdr = tohdr = cchdr = bcchdr = received_for = envto = ctthdr = NULL;
sizeticker = 0;
oldlen = 0;
while (delimited || len > 0)
@@ -469,6 +484,9 @@ char *realname; /* real name of host */
else if (!strncasecmp("Bcc:", bufp, 4))
bcchdr = bufp;
+ else if (!strncasecmp("Content-Transfer-Encoding:", bufp, 26))
+ ctthdr = bufp;
+
#ifdef HAVE_RES_SEARCH
else if (MULTIDROP(ctl) && !strncasecmp("Received:", bufp, 9))
received_for = parse_received(ctl, bufp);
@@ -578,7 +596,7 @@ char *realname; /* real name of host */
}
else
{
- char *ap;
+ char *ap, *ctt, options[MSGBUFSIZE];
/* build a connection to the SMTP listener */
if (!ctl->mda && ((sinkfp = smtp_open(ctl)) == NULL))
@@ -589,6 +607,20 @@ char *realname; /* real name of host */
}
/*
+ * Compute ESMTP options. It's a kluge to use nxtaddr()
+ * here because the contents of the Content-Transfer-Encoding
+ * headers isn't semantically an address. But it has the
+ * desired tokenizing effect.
+ */
+ if ((ctl->server.esmtp_options & ESMTP_8BITMIME)
+ && ctthdr
+ && (ctt = nxtaddr(ctthdr))
+ && (!strcasecmp(ctt,"7BIT")||!strcasecmp(ctt,"8BIT")))
+ sprintf(options, " BODY=%s", ctt);
+ else
+ options[0] = '\0';
+
+ /*
* Try to get the SMTP listener to take the header
* From address as MAIL FROM (this makes the logging
* nicer). If it won't, fall back on the calling-user
@@ -597,13 +629,13 @@ char *realname; /* real name of host */
*/
if (!fromhdr || !(ap = nxtaddr(fromhdr)))
{
- if (SMTP_from(sinkfp, user) != SM_OK)
+ if (SMTP_from(sinkfp, user, options)!=SM_OK)
{
error(0, 0, "%s not accepted as From address?", user);
return(PS_SMTP); /* should never happen */
}
}
- else if (SMTP_from(sinkfp, ap) != SM_OK)
+ else if (SMTP_from(sinkfp, ap, options)!=SM_OK)
if (smtp_response == 571)
{
/*
@@ -615,7 +647,7 @@ char *realname; /* real name of host */
sinkfp = (FILE *)NULL;
goto skiptext;
}
- else if (SMTP_from(sinkfp, user) != SM_OK)
+ else if (SMTP_from(sinkfp, user, options) != SM_OK)
return(PS_SMTP); /* should never happen */
/* now list the recipient addressees */
diff --git a/fetchmail.h b/fetchmail.h
index c1913f1a..d65c9c85 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -82,6 +82,7 @@ struct hostdata /* shared among all user connections to given server */
char *canonical_name; /* DNS canonical name of server host */
#endif /* HAVE_GETHOSTBYNAME */
struct hostdata *lead_server; /* ptr to lead query for this server */
+ int esmtp_options;
};
struct query
diff --git a/smtp.c b/smtp.c
index a5be0927..b8f08f74 100644
--- a/smtp.c
+++ b/smtp.c
@@ -17,6 +17,18 @@
#include "socket.h"
#include "smtp.h"
+struct opt
+{
+ char *name;
+ int value;
+};
+
+static struct opt extensions[] =
+{
+ {"8BITMIME", ESMTP_8BITMIME},
+ {(char *)NULL, 0},
+};
+
int smtp_response; /* numeric value of SMTP response code */
int SMTP_helo(FILE *sockfp,char *host)
@@ -31,14 +43,56 @@ int SMTP_helo(FILE *sockfp,char *host)
return ok;
}
-int SMTP_from(FILE *sockfp, char *from)
+int SMTP_ehlo(FILE *sockfp, char *host, int *opt)
+/* send a "EHLO" message to the SMTP listener, return extension status bits */
+{
+ int ok;
+ char buf[SMTPBUFSIZE], *ip;
+ struct opt *hp;
+
+ SockPrintf(sockfp,"EHLO %s\r\n", host);
+ if (outlevel == O_VERBOSE)
+ error(0, 0, "SMTP> EHLO %s", host);
+
+ *opt = 0;
+ while ((ip = SockGets(buf, sizeof(buf)-1, sockfp)))
+ {
+ int n = strlen(ip);
+
+ if (buf[strlen(buf)-1] == '\n')
+ buf[strlen(buf)-1] = '\0';
+ if (buf[strlen(buf)-1] == '\r')
+ buf[strlen(buf)-1] = '\r';
+ if (n < 4)
+ return SM_ERROR;
+ buf[n] = '\0';
+ if (outlevel == O_VERBOSE)
+ error(0, 0, "SMTP< %s", buf);
+ for (hp = extensions; hp->name; hp++)
+ if (!strncasecmp(hp->name, buf+4, strlen(hp->name)))
+ *opt |= hp->value;
+ smtp_response = atoi(buf);
+ if ((buf[0] == '1' || buf[0] == '2' || buf[0] == '3') && buf[3] == ' ')
+ return SM_OK;
+ else if (buf[3] != '-')
+ return SM_ERROR;
+ }
+ return SM_UNRECOVERABLE;
+}
+
+int SMTP_from(FILE *sockfp, char *from, char *opts)
/* send a "MAIL FROM:" message to the SMTP listener */
{
int ok;
+ struct opt *hp;
+ char buf[MSGBUFSIZE];
- SockPrintf(sockfp,"MAIL FROM:<%s>\r\n", from);
+ sprintf(buf, "MAIL FROM:<%s>", from);
+ if (opts)
+ strcat(buf, opts);
+ SockPrintf(sockfp,"%s\r\n", buf);
if (outlevel == O_VERBOSE)
- error(0, 0, "SMTP> MAIL FROM:<%s>", from);
+ error(0, 0, "SMTP> %s", buf);
ok = SMTP_ok(sockfp);
return ok;
}
diff --git a/smtp.h b/smtp.h
index cdcadd5a..ff3f7ac3 100644
--- a/smtp.h
+++ b/smtp.h
@@ -14,8 +14,13 @@
#define SM_ERROR 128
#define SM_UNRECOVERABLE 129
+/* ESMTP extension option masks (not all options are listed here) */
+#define ESMTP_8BITMIME 0x01
+#define ESMTP_SIZE 0x02
+
int SMTP_helo(FILE *sockfp,char *host);
-int SMTP_from(FILE *sockfp,char *from);
+int SMTP_ehlo(FILE *sockfp,char *host,int *opt);
+int SMTP_from(FILE *sockfp,char *from,char *opts);
int SMTP_rcpt(FILE *sockfp,char *to);
int SMTP_data(FILE *sockfp);
int SMTP_eom(FILE *sockfp);