diff options
Diffstat (limited to 'driver.c')
-rw-r--r-- | driver.c | 73 |
1 files changed, 48 insertions, 25 deletions
@@ -108,6 +108,7 @@ static int tagnum; static char shroud[PASSWORDLEN]; /* string to shroud in debug output */ static int mytimeout; /* value of nonreponse timeout */ static int msglen; /* actual message length */ +static int mimemsg; /* bitmask indicating MIME body-type */ /* use these to track what was happening when the nonresponse timer fired */ #define GENERAL_WAIT 0 /* unknown wait type */ @@ -639,7 +640,7 @@ int num; /* index of message */ char return_path[HOSTLEN + USERNAMELEN + 4]; int from_offs, reply_to_offs, resent_from_offs; int app_from_offs, sender_offs, resent_sender_offs; - int ctt_offs, env_offs; + int env_offs; char *headers, *received_for, *destaddr, *rcv, *cp; int n, linelen, oldlen, ch, remaining, skipcount; struct idlist *idp, *xmit_names; @@ -656,10 +657,11 @@ int num; /* index of message */ /* read message headers */ headers = received_for = NULL; from_offs = reply_to_offs = resent_from_offs = app_from_offs = - sender_offs = resent_sender_offs = ctt_offs = env_offs = -1; + sender_offs = resent_sender_offs = env_offs = -1; oldlen = 0; msglen = 0; skipcount = 0; + mimemsg = 0; for (remaining = fetchlen; remaining > 0 || protocol->delimited; remaining -= linelen) { @@ -880,8 +882,6 @@ int num; /* index of message */ else if (!strncasecmp("Resent_Sender:", line, 14)) resent_sender_offs = (line - headers); - else if (!strncasecmp("Content-Transfer-Encoding:", line, 26)) - ctt_offs = (line - headers); else if (!strncasecmp("Message-Id:", buf, 11)) { if (ctl->server.uidl) @@ -982,6 +982,16 @@ int num; /* index of message */ * In fact we have to, as this will tell us where to forward to. */ + /* Decode MIME encoded headers. We MUST do this before + * looking at the Content-Type / Content-Transfer-Encoding + * headers (RFC 2046). + */ + if (ctl->mimedecode) { + UnMimeHeader(headers); + } + /* Check for MIME headers indicating possible 8-bit data */ + mimemsg = MimeBodyType(headers); + /* * If there is a Return-Path address on the message, this was * almost certainly the MAIL FROM address given the originating @@ -1197,7 +1207,7 @@ int num; /* index of message */ } else { - char *ap, *ctt, options[MSGBUFSIZE], addr[128]; + char *ap, options[MSGBUFSIZE], addr[128]; /* build a connection to the SMTP listener */ if ((smtp_open(ctl) == -1)) @@ -1210,22 +1220,16 @@ int num; /* index of message */ } /* - * 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. + * Compute ESMTP options. */ options[0] = '\0'; - if (ctl->server.esmtp_options & ESMTP_8BITMIME) - if (ctl->pass8bits) + if (ctl->server.esmtp_options & ESMTP_8BITMIME) { + if (ctl->pass8bits || (mimemsg & MSG_IS_8BIT)) strcpy(options, " BODY=8BITMIME"); - else if ((ctt_offs >= 0) && (ctt = nxtaddr(headers + ctt_offs))) - { - if (!strcasecmp(ctt,"7BIT")) - strcpy(options, " BODY=7BIT"); - else if (!strcasecmp(ctt,"8BIT")) - strcpy(options, " BODY=8BITMIME"); - } + else if (mimemsg & MSG_IS_7BIT) + strcpy(options, " BODY=7BIT"); + } + if ((ctl->server.esmtp_options & ESMTP_SIZE) && reallen > 0) sprintf(options + strlen(options), " SIZE=%ld", reallen); @@ -1258,12 +1262,13 @@ int num; /* index of message */ * coming from this address, probably due to an * anti-spam domain exclusion. Respect this. Don't * try to ship the message, and don't prevent it from - * being deleted. Typical values. + * being deleted. Typical values: * * 571 = sendmail's "unsolicited email refused" * 501 = exim's old antispam response * 550 = exim's new antispam response (temporary) */ + SMTP_rset(ctl->smtp_socket); /* required by RFC1870 */ free(headers); free_str_list(&xmit_names); return(PS_REFUSED); @@ -1292,6 +1297,7 @@ int num; /* index of message */ return(PS_TRANSIENT); case 552: /* message exceeds fixed maximum message size */ + case 553: /* invalid sending domain */ /* * Permanent no-go condition on the * ESMTP server. Don't try to ship the message, @@ -1543,13 +1549,15 @@ int len; /* length of message */ flag forward; /* TRUE to forward */ { int linelen; - char buf[MSGBUFSIZE+1]; + unsigned char buf[MSGBUFSIZE+1]; + unsigned char *inbufp = buf; + flag issoftline = FALSE; /* pass through the text lines */ while (protocol->delimited || len > 0) { set_timeout(ctl->server.timeout); - if ((linelen = SockRead(sock, buf, sizeof(buf)-1)) == -1) + if ((linelen = SockRead(sock, inbufp, sizeof(buf)-1-(inbufp-buf)))==-1) { set_timeout(0); if (ctl->mda) @@ -1576,20 +1584,35 @@ flag forward; /* TRUE to forward */ len -= linelen; /* check for end of message */ - if (protocol->delimited && *buf == '.') - if (buf[1] == '\r' && buf[2] == '\n' && buf[3] == '\0') + if (protocol->delimited && *inbufp == '.') + if (inbufp[1] == '\r' && inbufp[2] == '\n' && inbufp[3] == '\0') break; - else if (buf[1] == '\n' && buf[2] == '\0') + else if (inbufp[1] == '\n' && inbufp[2] == '\0') break; else msglen--; /* subtract the size of the dot escape */ msglen += linelen; + if (ctl->mimedecode && (mimemsg & MSG_NEEDS_DECODE)) { + issoftline = UnMimeBodyline(&inbufp, (protocol->delimited && issoftline)); + if (issoftline && (sizeof(buf)-1-(inbufp-buf) < 200)) { + /* Soft linebreak, but less than 200 bytes left in + * input buffer. Rather than doing a buffer overrun, + * ignore the soft linebreak, NL-terminate data and + * deliver what we have now. + * (Who writes lines longer than 2K anyway?) + */ + *inbufp = '\n'; *(inbufp+1) = '\0'; + issoftline = 0; + } + } + /* ship out the text line */ - if (forward) + if (forward && (!issoftline)) { int n = stuffline(ctl, buf); + inbufp = buf; if (n < 0) { |