From: Wietse Venema Date: Sun, 12 May 2002 05:00:00 +0000 (-0500) Subject: postfix-1.1.9-20020512 X-Git-Tag: v2.0.0~67 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b55eed2be26c9000c974644c9b850628f8acb9d;p=thirdparty%2Fpostfix.git postfix-1.1.9-20020512 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 6f3bce6f1..f34023646 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -6383,10 +6383,41 @@ Apologies for any names omitted. multiple Postfix instances. Text by Victor Duchovny, Morgan Stanley. File: README_FILES/FILTER_README. -Open problems: +20020510 + + Feature: header/body filters now log the origin of the + message that is being rejected. Files: smtpd/smtpd.c, + qmqpd/qmqpd.c, pickup/pickup.c, cleanup/cleanup_envelope.c, + cleanup/cleanup_message.c. Requested by Craig Sanders, if + I remember correctly. + + Feature: the Postfix SMTP client now passes on MIME body + type information (8bit, 7bit) received via SMTP, via MIME + headers, or via the sendmail command line. Files: + global/deliver_request.c, smtpd/smtpd.c, sendmail/sendmail.c, + cleanup/cleanup_envelope.c, cleanup/cleanup_message.c, + cleanup/cleanup_extracted.c, *qmgr/qmgr_message.c, + *qmgr/qmgr_deliver.c, smtp/smtp_proto.c, lmtp/lmtp_proto.c. + +20020511 + + Feature: bounces now specify the proper MIME encoding (8bit, + 7bit), depending on the MIME body type information received + via SMTP, via MIME headers, or via the sendmail command + line. Files: global/bounce.c, global/defer.c, global/abounce.c, + bounce/bounce_service.c, bounce/bounce_notify_util.c. - Low: smtpd should reply with the original recipient address, - or it should at least externalize it. +20020512 + + Cleanup: the SMTP client logged and bounced the CNAME + expanded recipient address, and thereby complicated trouble + shooting. File: src/smtp_proto.c. + + Bugfix: the SMTP and LMTP clients bounced the quoted + recipient address, resulting in too much quoting in bounce + reports. Files: src/smtp_proto.c, lmtp/lmtp_proto.c. + +Open problems: Low: all table lookups should consistently use internalized (unquoted) or externalized (quoted) forms as lookup keys. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index 69e7921d2..7fbd39fa1 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -12,6 +12,38 @@ snapshot release). Patches change the patchlevel and the release date. Snapshots change only the release date, unless they include the same bugfixes as a patch release. +Incompatible changes with Postfix snapshot 1.1.9-20020512 +========================================================= + +The Postfix SMTP client no longer uses the CNAME expanded recipient +address when logging delivery or when bouncing mail. This makes +trouble shooting somewhat easier. + +Postfix snapshot 1.1.9-20020512 queue files contain records that +are incompatible with "postqueue -r" on all Postfix versions prior +to 1.1 and release candidates. This happens whenever the sender +specifies MIME body type information via the SMTP `MAIL FROM' +command, via the `sendmail -B' command line option, or via the +Content-Transfer-Encoding: message header. + +Postfix snapshot 1.1.9-20020512 queue files may contain records +that are incompatible with "postqueue -r" on previous 1.1 Postfix +versions and release candidates. This happens whenever the sender +specifies the MIME body type only via the Content-Transfer-Encoding: +message header, and not via `MAIL FROM' or `sendmail -B'. + +Major changes with Postfix snapshot 1.1.9-20020512 +================================================== + +The Postfix SMTP and LMTP clients now properly pass on the MIME +body type information (7BIT or 8BITMIME), provided that the sender +properly specifies MIME body type information via the SMTP MAIL +FROM command, via the sendmail -B command line option, or via MIME +message headers. This includes mail that is returned as undeliverable. +Implementing MIME body type propagation was a low priority because +qmail didn't implement this, either. However, Postfix will not +convert 8BITMIME content into 7BIT, and probably never will. + Incompatible changes with Postfix snapshot 1.1.9-20020509 ========================================================= @@ -22,11 +54,11 @@ catch-all patterns. The appearance of user@domain1@domain2 addresses has changed. In mail headers, such addresses are now properly quoted as -"user@domain1"@domain2. This quoted form is now also expected on -the left-hand side of virtual and canonical lookup tables, but only -by some of the Postfix components. For now, it is better not to -use user@domain1@domain2 address forms on the left-hand side of -lookup tables. +"user@domain1"@domain2. As a side effect, this quoted form is now +also expected on the left-hand side of virtual and canonical lookup +tables, but only by some of the Postfix components. For now, it +is better not to use user@domain1@domain2 address forms on the +left-hand side of lookup tables. Incompatible changes with Postfix snapshot 1.1.8-20020508 ========================================================= diff --git a/postfix/html/bounce.8.html b/postfix/html/bounce.8.html index 76cde5196..548369f71 100644 --- a/postfix/html/bounce.8.html +++ b/postfix/html/bounce.8.html @@ -1,5 +1,4 @@
-
 BOUNCE(8)                                               BOUNCE(8)
 
 NAME
@@ -38,6 +37,7 @@ BOUNCE(8)                                               BOUNCE(8)
 STANDARDS
        RFC 822 (ARPA Internet Text Messages)
        RFC 1894 (Delivery Status Notifications)
+       RFC 2045 (Format of Internet Message Bodies)
 
 DIAGNOSTICS
        Problems and transactions are logged to syslogd(8).
@@ -90,6 +90,5 @@ BOUNCE(8)                                               BOUNCE(8)
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
-                                                                1
-
+                                                        BOUNCE(8)
 
diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index a4428fa0b..08e194752 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -1,5 +1,4 @@
-
 LMTP(8)                                                   LMTP(8)
 
 NAME
@@ -56,6 +55,7 @@ LMTP(8)                                                   LMTP(8)
 STANDARDS
        RFC 821 (SMTP protocol)
        RFC 1651 (SMTP service extensions)
+       RFC 1652 (8bit-MIME transport)
        RFC 1870 (Message Size Declaration)
        RFC 2033 (LMTP protocol)
        RFC 2197 (Pipelining)
@@ -265,6 +265,5 @@ LMTP(8)                                                   LMTP(8)
        P.O. Box 830688, MC34
        Richardson, TX 75083, USA
 
-                                                                1
-
+                                                          LMTP(8)
 
diff --git a/postfix/html/sendmail.1.html b/postfix/html/sendmail.1.html index 9daf15bd5..3ace513a4 100644 --- a/postfix/html/sendmail.1.html +++ b/postfix/html/sendmail.1.html @@ -57,92 +57,91 @@ SENDMAIL(1) SENDMAIL(1) The following options are recognized: - -B body_type (ignored) - The message body MIME type. Currently, Postfix - implements just-send-eight. + -B body_type + The message body MIME type: 7BIT or 8BITMIME. -C config_file (ignored :-) The path name of the sendmail.cf file. Postfix con- figuration files are kept in /etc/postfix. -F full_name - Set the sender full name. This is used only with + Set the sender full name. This is used only with messages that have no From: message header. -G (ignored) - Gateway (relay) submission, as opposed to initial + Gateway (relay) submission, as opposed to initial user submission. - -I Initialize alias database. See the newaliases com- + -I Initialize alias database. See the newaliases com- mand above. -L label (ignored) - The logging label. Use the syslog_name configura- + The logging label. Use the syslog_name configura- tion parameter instead. -N dsn (ignored) - Delivery status notification control. Currently, + Delivery status notification control. Currently, Postfix does not implement DSN. -R return_limit (ignored) - Limit the size of bounced mail. Use the - bounce_size_limit configuration parameter instead. + Limit the size of bounced mail. Use the + bounce_size_limit configuration parameter instead. -X log_file (ignored) - Log mailer traffic. Use the debug_peer_list and - debug_peer_level configuration parameters instead. + Log mailer traffic. Use the debug_peer_list and + debug_peer_level configuration parameters instead. -U (ignored) Initial user submission. - -V Variable Envelope Return Path. Given an envelope - sender address of the form owner-listname@origin, - each recipient user@domain receives mail with a + -V Variable Envelope Return Path. Given an envelope + sender address of the form owner-listname@origin, + each recipient user@domain receives mail with a personalized envelope sender address. - By default, the personalized envelope sender - address is owner-listname+user=domain@origin. The - default + and = characters are configurable with - the default_verp_delimiters configuration parame- + By default, the personalized envelope sender + address is owner-listname+user=domain@origin. The + default + and = characters are configurable with + the default_verp_delimiters configuration parame- ter. -Vxy As -V, but uses x and y as the VERP delimiter char- - acters, instead of the characters specified with - the default_verp_delimiters configuration parame- + acters, instead of the characters specified with + the default_verp_delimiters configuration parame- ter. - -bd Go into daemon mode. This mode of operation is + -bd Go into daemon mode. This mode of operation is implemented by executing the postfix start command. - -bi Initialize alias database. See the newaliases com- + -bi Initialize alias database. See the newaliases com- mand above. - -bm Read mail from standard input and arrange for + -bm Read mail from standard input and arrange for delivery. This is the default mode of operation. -bp List the mail queue. See the mailq command above. - -bs Stand-alone SMTP server mode. Read SMTP commands - from standard input, and write responses to stan- - dard output. In stand-alone SMTP server mode, UCE - restrictions and access controls are disabled by - default. To enable them, run the process as the + -bs Stand-alone SMTP server mode. Read SMTP commands + from standard input, and write responses to stan- + dard output. In stand-alone SMTP server mode, UCE + restrictions and access controls are disabled by + default. To enable them, run the process as the mail_owner user. - This mode of operation is implemented by running + This mode of operation is implemented by running the smtpd(8) daemon. -f sender Set the envelope sender address. This is the address where delivery problems are sent to, unless - the message contains an Errors-To: message header. + the message contains an Errors-To: message header. -h hop_count (ignored) - Hop count limit. Use the hopcount_limit configura- + Hop count limit. Use the hopcount_limit configura- tion parameter instead. - -i When reading a message from standard input, don't - treat a line with only a . character as the end of + -i When reading a message from standard input, don't + treat a line with only a . character as the end of input. -m (ignored) @@ -152,67 +151,67 @@ SENDMAIL(1) SENDMAIL(1) Backwards compatibility. -oAalias_database - Non-default alias database. Specify pathname or + Non-default alias database. Specify pathname or type:pathname. See postalias(1) for details. -o7 (ignored) -o8 (ignored) - The message body type. Currently, Postfix imple- + The message body type. Currently, Postfix imple- ments just-send-eight. - -oi When reading a message from standard input, don't - treat a line with only a . character as the end of + -oi When reading a message from standard input, don't + treat a line with only a . character as the end of input. -om (ignored) - The sender is never eliminated from alias etc. + The sender is never eliminated from alias etc. expansions. -o x value (ignored) - Set option x to value. Use the equivalent configu- + Set option x to value. Use the equivalent configu- ration parameter in main.cf instead. -r sender Set the envelope sender address. This is the address where delivery problems are sent to, unless - the message contains an Errors-To: message header. + the message contains an Errors-To: message header. - -q Attempt to deliver all queued mail. This is imple- + -q Attempt to deliver all queued mail. This is imple- mented by executing the postqueue(1) command. -qinterval (ignored) - The interval between queue runs. Use the + The interval between queue runs. Use the queue_run_delay configuration parameter instead. -qRsite - Schedule immediate delivery of all mail that is + Schedule immediate delivery of all mail that is queued for the named site. This option accepts only - site names that are eligible for the "fast flush" - service, and is implemented by executing the + site names that are eligible for the "fast flush" + service, and is implemented by executing the postqueue(1) command. See flush(8) for more infor- mation about the "fast flush" service. -qSsite - This command is not implemented. Use the slower + This command is not implemented. Use the slower sendmail -q command instead. - -t Extract recipients from message headers. This - requires that no recipients be specified on the + -t Extract recipients from message headers. This + requires that no recipients be specified on the command line. -v Enable verbose logging for debugging purposes. Mul- - tiple -v options make the software increasingly + tiple -v options make the software increasingly verbose. SECURITY - By design, this program is not set-user (or group) id. - However, it must handle data from untrusted users or - untrusted machines. Thus, the usual precautions need to + By design, this program is not set-user (or group) id. + However, it must handle data from untrusted users or + untrusted machines. Thus, the usual precautions need to be taken against malicious inputs. DIAGNOSTICS - Problems are logged to syslogd(8) and to the standard + Problems are logged to syslogd(8) and to the standard error stream. ENVIRONMENT @@ -224,7 +223,7 @@ SENDMAIL(1) SENDMAIL(1) MAIL_DEBUG Enable debugging with an external command, as spec- - ified with the debugger_command configuration + ified with the debugger_command configuration parameter. FILES @@ -232,13 +231,13 @@ SENDMAIL(1) SENDMAIL(1) /etc/postfix, configuration files CONFIGURATION PARAMETERS - See the Postfix main.cf file for syntax details and for - default values. Use the postfix reload command after a + See the Postfix main.cf file for syntax details and for + default values. Use the postfix reload command after a configuration change. alias_database - Default alias database(s) for newaliases. The - default value for this parameter is system-spe- + Default alias database(s) for newaliases. The + default value for this parameter is system-spe- cific. bounce_size_limit @@ -254,62 +253,62 @@ SENDMAIL(1) SENDMAIL(1) initialized. debug_peer_level - Increment in verbose logging level when a remote + Increment in verbose logging level when a remote host matches a pattern in the debug_peer_list parameter. debug_peer_list - List of domain or network patterns. When a remote - host matches a pattern, increase the verbose log- - ging level by the amount specified in the + List of domain or network patterns. When a remote + host matches a pattern, increase the verbose log- + ging level by the amount specified in the debug_peer_level parameter. default_verp_delimiters - The VERP delimiter characters that are used when - the -V command line option is specified without + The VERP delimiter characters that are used when + the -V command line option is specified without delimiter characters. fast_flush_domains List of domains that will receive "fast flush" ser- - vice (default: all domains that this system is - willing to relay mail to). This list specifies the - domains that Postfix accepts in the SMTP ETRN + vice (default: all domains that this system is + willing to relay mail to). This list specifies the + domains that Postfix accepts in the SMTP ETRN request and in the sendmail -qR command. fork_attempts - Number of attempts to fork() a process before giv- + Number of attempts to fork() a process before giv- ing up. fork_delay - Delay in seconds between successive fork() + Delay in seconds between successive fork() attempts. hopcount_limit Limit the number of Received: message headers. mail_owner - The owner of the mail queue and of most Postfix + The owner of the mail queue and of most Postfix processes. command_directory - Directory with Postfix support commands (default: + Directory with Postfix support commands (default: $program_directory). daemon_directory - Directory with Postfix daemon programs (default: + Directory with Postfix daemon programs (default: $program_directory). queue_directory - Top-level directory of the Postfix queue. This is + Top-level directory of the Postfix queue. This is also the root directory of Postfix daemons that run chrooted. queue_run_delay - The time between successive scans of the deferred + The time between successive scans of the deferred queue. verp_delimiter_filter - The characters that Postfix accepts as VERP delim- + The characters that Postfix accepts as VERP delim- iter characters. SEE ALSO @@ -324,7 +323,7 @@ SENDMAIL(1) SENDMAIL(1) syslogd(8) system logging LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index 047b3ddc9..ba92da536 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -43,6 +43,7 @@ SMTP(8) SMTP(8) STANDARDS RFC 821 (SMTP protocol) RFC 1651 (SMTP service extensions) + RFC 1652 (8bit-MIME transport) RFC 1870 (Message Size Declaration) RFC 2197 (Pipelining) RFC 2554 (AUTH command) diff --git a/postfix/man/man1/sendmail.1 b/postfix/man/man1/sendmail.1 index 10ca278c0..d493c8a4d 100644 --- a/postfix/man/man1/sendmail.1 +++ b/postfix/man/man1/sendmail.1 @@ -55,9 +55,8 @@ appropriate combination of command-line options. Some features are controlled by parameters in the \fBmain.cf\fR configuration file. The following options are recognized: -.IP "\fB-B \fIbody_type\fR (ignored)" -The message body MIME type. Currently, Postfix implements -\fBjust-send-eight\fR. +.IP "\fB-B \fIbody_type\fR" +The message body MIME type: \fB7BIT\fR or \fB8BITMIME\fR. .IP "\fB-C \fIconfig_file\fR (ignored :-)" The path name of the \fBsendmail.cf\fR file. Postfix configuration files are kept in \fB/etc/postfix\fR. diff --git a/postfix/man/man8/bounce.8 b/postfix/man/man8/bounce.8 index 02dc4cee6..a1afc3faa 100644 --- a/postfix/man/man8/bounce.8 +++ b/postfix/man/man8/bounce.8 @@ -41,6 +41,7 @@ themselves, and that depend on retry logic in their own client. .nf RFC 822 (ARPA Internet Text Messages) RFC 1894 (Delivery Status Notifications) +RFC 2045 (Format of Internet Message Bodies) .SH DIAGNOSTICS .ad .fi diff --git a/postfix/man/man8/lmtp.8 b/postfix/man/man8/lmtp.8 index b00dc9d35..c53e0033c 100644 --- a/postfix/man/man8/lmtp.8 +++ b/postfix/man/man8/lmtp.8 @@ -56,6 +56,7 @@ run chrooted at fixed low privilege. .nf RFC 821 (SMTP protocol) RFC 1651 (SMTP service extensions) +RFC 1652 (8bit-MIME transport) RFC 1870 (Message Size Declaration) RFC 2033 (LMTP protocol) RFC 2197 (Pipelining) diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index 00f07b8fd..196c16c74 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -48,6 +48,7 @@ run chrooted at fixed low privilege. .nf RFC 821 (SMTP protocol) RFC 1651 (SMTP service extensions) +RFC 1652 (8bit-MIME transport) RFC 1870 (Message Size Declaration) RFC 2197 (Pipelining) RFC 2554 (AUTH command) diff --git a/postfix/src/bounce/Makefile.in b/postfix/src/bounce/Makefile.in index 99e6d1af4..3d2327f38 100644 --- a/postfix/src/bounce/Makefile.in +++ b/postfix/src/bounce/Makefile.in @@ -136,6 +136,9 @@ bounce_notify_util.o: ../../include/mail_error.h bounce_notify_util.o: ../../include/name_mask.h bounce_notify_util.o: ../../include/bounce_log.h bounce_notify_util.o: ../../include/mail_date.h +bounce_notify_util.o: ../../include/mail_proto.h +bounce_notify_util.o: ../../include/iostuff.h +bounce_notify_util.o: ../../include/attr.h bounce_notify_util.o: bounce_service.h bounce_notify_verp.o: bounce_notify_verp.c bounce_notify_verp.o: ../../include/sys_defs.h diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index 3cb98cc00..00c40cd2d 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -33,6 +33,7 @@ /* STANDARDS /* RFC 822 (ARPA Internet Text Messages) /* RFC 1894 (Delivery Status Notifications) +/* RFC 2045 (Format of Internet Message Bodies) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* BUGS @@ -127,6 +128,7 @@ char *var_delay_rcpt; static VSTRING *queue_id; static VSTRING *queue_name; static VSTRING *recipient; +static VSTRING *encoding; static VSTRING *sender; static VSTRING *verp_delims; static VSTRING *why; @@ -186,8 +188,9 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, int flush) ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, - ATTR_TYPE_END) != 4) { + ATTR_TYPE_END) != 5) { msg_warn("malformed request"); return (-1); } @@ -200,8 +203,9 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, int flush) return (-1); } if (msg_verbose) - msg_info("bounce_notify_proto: service=%s queue=%s id=%s sender=%s", - service_name, STR(queue_name), STR(queue_id), STR(sender)); + msg_info("bounce_notify_proto: service=%s queue=%s id=%s encoding=%s sender=%s", + service_name, STR(queue_name), STR(queue_id), + STR(encoding), STR(sender)); /* * On request by the client, set up a trap to delete the log file in case @@ -214,7 +218,8 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, int flush) * Execute the request. */ return (bounce_notify_service(service_name, STR(queue_name), - STR(queue_id), STR(sender), flush)); + STR(queue_id), STR(encoding), + STR(sender), flush)); } /* bounce_verp_proto - bounce_notify server protocol, VERP style */ @@ -228,12 +233,13 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client, int flush) * Read and validate the client request. */ if (mail_command_server(client, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, - ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, - ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, - ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, - ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims, - ATTR_TYPE_END) != 5) { + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, + ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name, + ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, + ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims, + ATTR_TYPE_END) != 6) { msg_warn("malformed request"); return (-1); } @@ -251,9 +257,9 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client, int flush) return (-1); } if (msg_verbose) - msg_info("%s: service=%s queue=%s id=%s sender=%s delim=%s", + msg_info("%s: service=%s queue=%s id=%s encoding=%s sender=%s delim=%s", myname, service_name, STR(queue_name), STR(queue_id), - STR(sender), STR(verp_delims)); + STR(encoding), STR(sender), STR(verp_delims)); /* * On request by the client, set up a trap to delete the log file in case @@ -269,11 +275,12 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client, int flush) if (!*STR(sender) || !strcasecmp(STR(sender), mail_addr_double_bounce())) { msg_warn("request to send VERP-style notification of bounced mail"); return (bounce_notify_service(service_name, STR(queue_name), - STR(queue_id), STR(sender), flush)); + STR(queue_id), STR(encoding), + STR(sender), flush)); } else return (bounce_notify_verp(service_name, STR(queue_name), - STR(queue_id), STR(sender), - STR(verp_delims), flush)); + STR(queue_id), STR(encoding), + STR(sender), STR(verp_delims), flush)); } /* bounce_service - parse bounce command type and delegate */ @@ -349,6 +356,7 @@ static void post_jail_init(char *unused_name, char **unused_argv) queue_id = vstring_alloc(10); queue_name = vstring_alloc(10); recipient = vstring_alloc(10); + encoding = vstring_alloc(10); sender = vstring_alloc(10); verp_delims = vstring_alloc(10); why = vstring_alloc(10); diff --git a/postfix/src/bounce/bounce_notify_service.c b/postfix/src/bounce/bounce_notify_service.c index 284b6468e..21652f6b0 100644 --- a/postfix/src/bounce/bounce_notify_service.c +++ b/postfix/src/bounce/bounce_notify_service.c @@ -6,9 +6,11 @@ /* SYNOPSIS /* #include "bounce_service.h" /* -/* int bounce_notify_service(queue_name, queue_id, sender, flush) +/* int bounce_notify_service(queue_name, queue_id, encoding, +/* sender, flush) /* char *queue_name; /* char *queue_id; +/* char *encoding; /* char *sender; /* int flush; /* DESCRIPTION @@ -78,7 +80,8 @@ /* bounce_notify_service - send a bounce */ int bounce_notify_service(char *service, char *queue_name, - char *queue_id, char *recipient, int flush) + char *queue_id, char *encoding, + char *recipient, int flush) { BOUNCE_INFO *bounce_info; int bounce_status = 1; @@ -91,7 +94,8 @@ int bounce_notify_service(char *service, char *queue_name, /* * Initialize. Open queue file, bounce log, etc. */ - bounce_info = bounce_mail_init(service, queue_name, queue_id, flush); + bounce_info = bounce_mail_init(service, queue_name, queue_id, + encoding, flush); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ #define NULL_CLEANUP_FLAGS 0 diff --git a/postfix/src/bounce/bounce_notify_util.c b/postfix/src/bounce/bounce_notify_util.c index 926be4734..b6a919efd 100644 --- a/postfix/src/bounce/bounce_notify_util.c +++ b/postfix/src/bounce/bounce_notify_util.c @@ -12,10 +12,12 @@ /* .in -4 /* } BOUNCE_INFO; /* -/* BOUNCE_INFO *bounce_mail_init(service, queue_name, queue_id, flush) +/* BOUNCE_INFO *bounce_mail_init(service, queue_name, queue_id, +/* encoding, flush) /* const char *service; /* const char *queue_name; /* const char *queue_id; +/* const char *encoding; /* int flush; /* /* void bounce_mail_free(bounce_info) @@ -152,6 +154,7 @@ #include #include #include +#include /* Application-specific. */ @@ -162,7 +165,8 @@ /* bounce_mail_init - initialize */ BOUNCE_INFO *bounce_mail_init(const char *service, const char *queue_name, - const char *queue_id, int flush) + const char *queue_id, + const char *encoding, int flush) { BOUNCE_INFO *bounce_info; int rec_type; @@ -175,6 +179,16 @@ BOUNCE_INFO *bounce_mail_init(const char *service, const char *queue_name, bounce_info->service = service; bounce_info->queue_name = queue_name; bounce_info->queue_id = queue_id; + if (strcmp(encoding, MAIL_ATTR_ENC_8BIT) == 0) { + bounce_info->mime_encoding = "8bit"; + } else if (strcmp(encoding, MAIL_ATTR_ENC_7BIT) == 0) { + bounce_info->mime_encoding = "7bit"; + } else { + if (strcmp(encoding, MAIL_ATTR_ENC_NONE) != 0) + msg_warn("%s: unknown encoding: %.200s", + bounce_info->queue_id, encoding); + bounce_info->mime_encoding = 0; + } bounce_info->flush = flush; bounce_info->buf = vstring_alloc(100); bounce_info->arrival_time = 0; @@ -298,6 +312,9 @@ int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info, post_mail_fprintf(bounce, "Content-Type: %s; report-type=%s;", "multipart/report", "delivery-status"); post_mail_fprintf(bounce, "\tboundary=\"%s\"", bounce_info->mime_boundary); + if (bounce_info->mime_encoding) + post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", + bounce_info->mime_encoding); post_mail_fputs(bounce, ""); post_mail_fputs(bounce, "This is a MIME-encapsulated message."); @@ -522,6 +539,9 @@ int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info, "Undelivered Message Headers" : "Undelivered Message"); post_mail_fprintf(bounce, "Content-Type: %s", headers_only ? "text/rfc822-headers" : "message/rfc822"); + if (bounce_info->mime_encoding) + post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", + bounce_info->mime_encoding); post_mail_fputs(bounce, ""); /* diff --git a/postfix/src/bounce/bounce_notify_verp.c b/postfix/src/bounce/bounce_notify_verp.c index f1880bae0..da4606397 100644 --- a/postfix/src/bounce/bounce_notify_verp.c +++ b/postfix/src/bounce/bounce_notify_verp.c @@ -80,7 +80,8 @@ /* bounce_notify_verp - send a bounce */ int bounce_notify_verp(char *service, char *queue_name, - char *queue_id, char *recipient, + char *queue_id, char *encoding, + char *recipient, char *verp_delims, int flush) { char *myname = "bounce_notify_verp"; @@ -105,7 +106,8 @@ int bounce_notify_verp(char *service, char *queue_name, /* * Initialize. Open queue file, bounce log, etc. */ - bounce_info = bounce_mail_init(service, queue_name, queue_id, flush); + bounce_info = bounce_mail_init(service, queue_name, queue_id, + encoding, flush); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ #define NULL_CLEANUP_FLAGS 0 diff --git a/postfix/src/bounce/bounce_service.h b/postfix/src/bounce/bounce_service.h index 858609b79..889e8e9d6 100644 --- a/postfix/src/bounce/bounce_service.h +++ b/postfix/src/bounce/bounce_service.h @@ -26,12 +26,12 @@ extern int bounce_append_service(char *, char *, char *, char *); /* * bounce_notify_service.c */ -extern int bounce_notify_service(char *, char *, char *, char *, int); +extern int bounce_notify_service(char *, char *, char *, char *, char *, int); /* * bounce_notify_verp.c */ -extern int bounce_notify_verp(char *, char *, char *, char *, char *, int); +extern int bounce_notify_verp(char *, char *, char *, char *, char *, char *, int); /* * bounce_cleanup.c @@ -50,6 +50,7 @@ typedef struct { const char *service; /* bounce or defer */ const char *queue_name; /* incoming, etc. */ const char *queue_id; /* base name */ + const char *mime_encoding; /* null or encoding */ const char *mime_boundary; /* for MIME */ int flush; /* 0=defer, other=bounce */ VSTRING *buf; /* scratch pad */ @@ -59,7 +60,7 @@ typedef struct { BOUNCE_LOG *log_handle; /* open logfile */ } BOUNCE_INFO; -extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, int); +extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, int); extern void bounce_mail_free(BOUNCE_INFO *); extern int bounce_header(VSTREAM *, BOUNCE_INFO *, const char *); extern int bounce_boilerplate(VSTREAM *, BOUNCE_INFO *); diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 02ab36707..63da2cace 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -78,6 +78,9 @@ cleanup.o: ../../include/record.h cleanup.o: ../../include/rec_type.h cleanup.o: ../../include/mail_server.h cleanup.o: cleanup.h +cleanup.o: ../../include/nvtable.h +cleanup.o: ../../include/htable.h +cleanup.o: ../../include/mymalloc.h cleanup.o: ../../include/maps.h cleanup.o: ../../include/tok822.h cleanup.o: ../../include/resolve_clnt.h @@ -100,6 +103,8 @@ cleanup_api.o: ../../include/mail_params.h cleanup_api.o: ../../include/mail_stream.h cleanup_api.o: cleanup.h cleanup_api.o: ../../include/argv.h +cleanup_api.o: ../../include/nvtable.h +cleanup_api.o: ../../include/htable.h cleanup_api.o: ../../include/maps.h cleanup_api.o: ../../include/dict.h cleanup_api.o: ../../include/tok822.h @@ -113,6 +118,9 @@ cleanup_envelope.o: ../../include/vstring.h cleanup_envelope.o: ../../include/vbuf.h cleanup_envelope.o: ../../include/vstream.h cleanup_envelope.o: ../../include/mymalloc.h +cleanup_envelope.o: ../../include/stringops.h +cleanup_envelope.o: ../../include/nvtable.h +cleanup_envelope.o: ../../include/htable.h cleanup_envelope.o: ../../include/record.h cleanup_envelope.o: ../../include/rec_type.h cleanup_envelope.o: ../../include/cleanup_user.h @@ -138,11 +146,16 @@ cleanup_extracted.o: ../../include/vbuf.h cleanup_extracted.o: ../../include/vstream.h cleanup_extracted.o: ../../include/argv.h cleanup_extracted.o: ../../include/mymalloc.h +cleanup_extracted.o: ../../include/nvtable.h +cleanup_extracted.o: ../../include/htable.h cleanup_extracted.o: ../../include/cleanup_user.h cleanup_extracted.o: ../../include/record.h cleanup_extracted.o: ../../include/rec_type.h cleanup_extracted.o: ../../include/mail_params.h cleanup_extracted.o: ../../include/ext_prop.h +cleanup_extracted.o: ../../include/mail_proto.h +cleanup_extracted.o: ../../include/iostuff.h +cleanup_extracted.o: ../../include/attr.h cleanup_extracted.o: cleanup.h cleanup_extracted.o: ../../include/maps.h cleanup_extracted.o: ../../include/dict.h @@ -164,6 +177,9 @@ cleanup_init.o: ../../include/vstring.h cleanup_init.o: ../../include/vbuf.h cleanup_init.o: ../../include/vstream.h cleanup_init.o: ../../include/argv.h +cleanup_init.o: ../../include/nvtable.h +cleanup_init.o: ../../include/htable.h +cleanup_init.o: ../../include/mymalloc.h cleanup_init.o: ../../include/maps.h cleanup_init.o: ../../include/dict.h cleanup_init.o: ../../include/tok822.h @@ -186,6 +202,8 @@ cleanup_map11.o: ../../include/maps.h cleanup_map11.o: ../../include/quote_822_local.h cleanup_map11.o: ../../include/quote_flags.h cleanup_map11.o: cleanup.h +cleanup_map11.o: ../../include/nvtable.h +cleanup_map11.o: ../../include/htable.h cleanup_map11.o: ../../include/tok822.h cleanup_map11.o: ../../include/resolve_clnt.h cleanup_map11.o: ../../include/been_here.h @@ -207,6 +225,8 @@ cleanup_map1n.o: ../../include/quote_822_local.h cleanup_map1n.o: ../../include/quote_flags.h cleanup_map1n.o: ../../include/been_here.h cleanup_map1n.o: cleanup.h +cleanup_map1n.o: ../../include/nvtable.h +cleanup_map1n.o: ../../include/htable.h cleanup_map1n.o: ../../include/tok822.h cleanup_map1n.o: ../../include/resolve_clnt.h cleanup_map1n.o: ../../include/mail_stream.h @@ -227,6 +247,7 @@ cleanup_masquerade.o: ../../include/quote_822_local.h cleanup_masquerade.o: ../../include/quote_flags.h cleanup_masquerade.o: cleanup.h cleanup_masquerade.o: ../../include/vstream.h +cleanup_masquerade.o: ../../include/nvtable.h cleanup_masquerade.o: ../../include/maps.h cleanup_masquerade.o: ../../include/dict.h cleanup_masquerade.o: ../../include/been_here.h @@ -241,6 +262,9 @@ cleanup_message.o: ../../include/vstream.h cleanup_message.o: ../../include/argv.h cleanup_message.o: ../../include/split_at.h cleanup_message.o: ../../include/mymalloc.h +cleanup_message.o: ../../include/stringops.h +cleanup_message.o: ../../include/nvtable.h +cleanup_message.o: ../../include/htable.h cleanup_message.o: ../../include/record.h cleanup_message.o: ../../include/rec_type.h cleanup_message.o: ../../include/cleanup_user.h @@ -254,6 +278,9 @@ cleanup_message.o: ../../include/mail_date.h cleanup_message.o: ../../include/mail_addr.h cleanup_message.o: ../../include/is_header.h cleanup_message.o: ../../include/ext_prop.h +cleanup_message.o: ../../include/mail_proto.h +cleanup_message.o: ../../include/iostuff.h +cleanup_message.o: ../../include/attr.h cleanup_message.o: cleanup.h cleanup_message.o: ../../include/maps.h cleanup_message.o: ../../include/dict.h @@ -272,6 +299,9 @@ cleanup_out.o: ../../include/cleanup_user.h cleanup_out.o: ../../include/mail_params.h cleanup_out.o: cleanup.h cleanup_out.o: ../../include/argv.h +cleanup_out.o: ../../include/nvtable.h +cleanup_out.o: ../../include/htable.h +cleanup_out.o: ../../include/mymalloc.h cleanup_out.o: ../../include/maps.h cleanup_out.o: ../../include/dict.h cleanup_out.o: ../../include/tok822.h @@ -290,6 +320,9 @@ cleanup_out_recipient.o: cleanup.h cleanup_out_recipient.o: ../../include/vstring.h cleanup_out_recipient.o: ../../include/vbuf.h cleanup_out_recipient.o: ../../include/vstream.h +cleanup_out_recipient.o: ../../include/nvtable.h +cleanup_out_recipient.o: ../../include/htable.h +cleanup_out_recipient.o: ../../include/mymalloc.h cleanup_out_recipient.o: ../../include/maps.h cleanup_out_recipient.o: ../../include/dict.h cleanup_out_recipient.o: ../../include/tok822.h @@ -309,6 +342,9 @@ cleanup_rewrite.o: ../../include/quote_flags.h cleanup_rewrite.o: cleanup.h cleanup_rewrite.o: ../../include/vstream.h cleanup_rewrite.o: ../../include/argv.h +cleanup_rewrite.o: ../../include/nvtable.h +cleanup_rewrite.o: ../../include/htable.h +cleanup_rewrite.o: ../../include/mymalloc.h cleanup_rewrite.o: ../../include/maps.h cleanup_rewrite.o: ../../include/dict.h cleanup_rewrite.o: ../../include/been_here.h @@ -320,10 +356,12 @@ cleanup_state.o: ../../include/mymalloc.h cleanup_state.o: ../../include/vstring.h cleanup_state.o: ../../include/vbuf.h cleanup_state.o: ../../include/argv.h +cleanup_state.o: ../../include/htable.h cleanup_state.o: ../../include/been_here.h cleanup_state.o: ../../include/mail_params.h cleanup_state.o: cleanup.h cleanup_state.o: ../../include/vstream.h +cleanup_state.o: ../../include/nvtable.h cleanup_state.o: ../../include/maps.h cleanup_state.o: ../../include/dict.h cleanup_state.o: ../../include/tok822.h diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index 62e01f38f..082bd4e74 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -14,6 +14,7 @@ #include #include #include +#include /* * Global library. @@ -61,6 +62,7 @@ typedef struct CLEANUP_STATE { int end_seen; /* REC_TYPE_END seen */ int rcpt_count; /* recipient count */ char *reason; /* failure reason */ + NVTABLE *attr; /* queue file attribute list */ } CLEANUP_STATE; /* diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index 2f752e459..80cac48e3 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -38,11 +38,11 @@ /* These flags control the handling of data errors, and must be set /* before processing the first message record. /* .IP CLEANUP_FLAG_BOUNCE -/* The cleanup server is responsible for returning undeliverable +/* The cleanup server is responsible for returning undeliverable /* mail (too many hops, message too large) to the sender. /* .IP CLEANUP_FLAG_FILTER -/* Enable header/body filtering. This should be enabled only with mail -/* that enters Postfix, not with locally forwarded mail or with bounce +/* Enable header/body filtering. This should be enabled only with mail +/* that enters Postfix, not with locally forwarded mail or with bounce /* messages. /* .IP CLEANUP_FLAG_EXTRACT /* Extract recipients from message headers when no recipients are @@ -125,7 +125,7 @@ CLEANUP_STATE *cleanup_open(void) * that the runtime error handler can clean up in case of problems. */ state->handle = mail_stream_file(MAIL_QUEUE_INCOMING, - MAIL_CLASS_PUBLIC, var_queue_service, 0); + MAIL_CLASS_PUBLIC, var_queue_service, 0); state->dst = state->handle->stream; cleanup_path = mystrdup(VSTREAM_PATH(state->dst)); state->queue_id = mystrdup(state->handle->id); @@ -176,6 +176,7 @@ int cleanup_flush(CLEANUP_STATE *state) { char *junk; int status; + char *encoding; /* * Ignore recipient extraction alarms if (a) we did (not need to) extract @@ -235,7 +236,10 @@ int cleanup_flush(CLEANUP_STATE *state) "%s", state->reason ? state->reason : cleanup_strerror(state->errs)) == 0 && bounce_flush(BOUNCE_FLAG_CLEAN, MAIL_QUEUE_INCOMING, - state->queue_id, state->sender) == 0) { + state->queue_id, + (encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) ? + encoding : MAIL_ATTR_ENC_NONE, + state->sender) == 0) { state->errs = 0; } else { if (var_soft_bounce == 0) { diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index f4fd30e75..00858cc91 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -56,6 +56,8 @@ #include #include #include +#include +#include /* Global library. */ @@ -104,6 +106,10 @@ void cleanup_envelope(CLEANUP_STATE *state, int type, char *str, int len) static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, int len) { + char *attr_name; + char *attr_value; + const char *error_text; + if (type == REC_TYPE_MESG) { if (state->sender == 0 || state->time == 0) { msg_warn("%s: missing sender or time envelope record", @@ -196,6 +202,21 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, state->errs |= CLEANUP_STAT_BAD; return; } + } else if (type == REC_TYPE_ATTR) { + if (state->attr->used >= var_qattr_count_limit) { + msg_warn("%s: queue file attribute count exceeds safety limit: %d", + state->queue_id, var_qattr_count_limit); + state->errs |= CLEANUP_STAT_BAD; + return; + } + cleanup_out(state, type, buf, len); + if ((error_text = split_nameval(buf, &attr_name, &attr_value)) != 0) { + msg_warn("%s: malformed attribute: %s: %.100s", + state->queue_id, error_text, buf); + state->errs |= CLEANUP_STAT_BAD; + return; + } + nvtable_update(state->attr, attr_name, attr_value); } else { cleanup_out(state, type, buf, len); } diff --git a/postfix/src/cleanup/cleanup_extracted.c b/postfix/src/cleanup/cleanup_extracted.c index b9721bd88..df3bcd993 100644 --- a/postfix/src/cleanup/cleanup_extracted.c +++ b/postfix/src/cleanup/cleanup_extracted.c @@ -51,6 +51,7 @@ #include #include #include +#include /* Global library. */ @@ -59,6 +60,7 @@ #include #include #include +#include /* Application-specific. */ @@ -72,12 +74,23 @@ static void cleanup_extracted_process(CLEANUP_STATE *, int, char *, int); void cleanup_extracted(CLEANUP_STATE *state, int type, char *buf, int len) { + const char *encoding; /* * Start the extracted segment. */ cleanup_out_string(state, REC_TYPE_XTRA, ""); + /* + * Older Postfix versions didn't emit encoding information, so this + * record can only be optional. Putting this before the mandatory + * Return-Receipt-To and Errors-To ensures that the queue manager will + * pick up the content encoding before starting deliveries. + */ + if ((encoding = nvtable_find(state->attr, MAIL_ATTR_ENCODING)) != 0) + cleanup_out_format(state, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ENCODING, encoding); + /* * Always emit Return-Receipt-To and Errors-To records, and always emit * them ahead of extracted recipients, so that the queue manager does not diff --git a/postfix/src/cleanup/cleanup_init.c b/postfix/src/cleanup/cleanup_init.c index b3e7a0157..866527936 100644 --- a/postfix/src/cleanup/cleanup_init.c +++ b/postfix/src/cleanup/cleanup_init.c @@ -108,12 +108,14 @@ char *var_always_bcc; /* big brother */ int var_extra_rcpt_limit; /* recipient extract limit */ char *var_rcpt_witheld; /* recipients not disclosed */ char *var_masq_classes; /* what to masquerade */ +int var_qattr_count_limit; /* named attribute limit */ CONFIG_INT_TABLE cleanup_int_table[] = { VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0, VAR_HEADER_LIMIT, DEF_HEADER_LIMIT, &var_header_limit, 1, 0, VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0, VAR_EXTRA_RCPT_LIMIT, DEF_EXTRA_RCPT_LIMIT, &var_extra_rcpt_limit, 0, 0, + VAR_QATTR_COUNT_LIMIT, DEF_QATTR_COUNT_LIMIT, &var_qattr_count_limit, 1, 0, 0, }; diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 2d25dddcb..335715220 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -61,6 +61,8 @@ #include #include #include +#include +#include /* Global library. */ @@ -75,6 +77,7 @@ #include #include #include +#include /* Application-specific. */ @@ -263,6 +266,7 @@ static int cleanup_act(CLEANUP_STATE *state, char *context, char *buf, { const char *optional_text = value + strcspn(value, " \t"); int command_len = optional_text - value; + const char *origin; while (*optional_text && ISSPACE(*optional_text)) optional_text++; @@ -276,8 +280,10 @@ static int cleanup_act(CLEANUP_STATE *state, char *context, char *buf, state->reason = mystrdup(*optional_text ? optional_text : cleanup_strerror(CLEANUP_STAT_CONT)); state->errs |= CLEANUP_STAT_CONT; - msg_info("%s: reject: %s %.200s; from=<%s> to=<%s>: %s", - state->queue_id, context, buf, state->sender, + if ((origin = nvtable_find(state->attr, MAIL_ATTR_ORIGIN)) == 0) + origin = MAIL_ATTR_ORG_NONE; + msg_info("%s: reject: %s %.200s from %s; from=<%s> to=<%s>: %s", + state->queue_id, context, buf, origin, state->sender, state->recip ? state->recip : "unknown", state->reason); return (CLEANUP_ACT_KEEP); @@ -310,6 +316,20 @@ static void cleanup_header(CLEANUP_STATE *state) { char *myname = "cleanup_header"; HEADER_OPTS *hdr_opts; + char *hdrval; + struct code_map { + const char *name; + const char *encoding; + }; + static struct code_map code_map[] = { /* RFC 2045 */ + "7bit", MAIL_ATTR_ENC_7BIT, + "8bit", MAIL_ATTR_ENC_8BIT, + "binary", MAIL_ATTR_ENC_8BIT, /* XXX Violation */ + "quoted-printable", MAIL_ATTR_ENC_7BIT, + "base64", MAIL_ATTR_ENC_7BIT, + 0, + }; + struct code_map *cmp; if (msg_verbose) msg_info("%s: '%s'", myname, vstring_str(state->header_buf)); @@ -365,15 +385,28 @@ static void cleanup_header(CLEANUP_STATE *state) */ else { state->headers_seen |= (1 << hdr_opts->type); + hdrval = vstring_str(state->header_buf) + strlen(hdr_opts->name) + 2; + while (ISSPACE(*hdrval)) + hdrval++; + trimblanks(hdrval, 0); if (hdr_opts->type == HDR_MESSAGE_ID) - msg_info("%s: message-id=%s", state->queue_id, - vstring_str(state->header_buf) + strlen(hdr_opts->name) + 2); + msg_info("%s: message-id=%s", state->queue_id, hdrval); if (hdr_opts->type == HDR_RESENT_MESSAGE_ID) - msg_info("%s: resent-message-id=%s", state->queue_id, - vstring_str(state->header_buf) + strlen(hdr_opts->name) + 2); + msg_info("%s: resent-message-id=%s", state->queue_id, hdrval); if (hdr_opts->type == HDR_RECEIVED) if (++state->hop_count >= var_hopcount_limit) state->errs |= CLEANUP_STAT_HOPS; + if (hdr_opts->type == HDR_CONTENT_TRANSFER_ENCODING) { + if (nvtable_find(state->attr, MAIL_ATTR_ENCODING) == 0) { + for (cmp = code_map; cmp->name != 0; cmp++) { + if (strcasecmp(hdrval, cmp->name) == 0) { + nvtable_update(state->attr, MAIL_ATTR_ENCODING, + cmp->encoding); + break; + } + } + } + } if (CLEANUP_OUT_OK(state)) { if (hdr_opts->flags & HDR_OPT_RR) state->resent = "Resent-"; diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index bfe6bacf9..6df5fb894 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -38,6 +38,7 @@ #include #include #include +#include /* Global library. */ @@ -86,6 +87,7 @@ CLEANUP_STATE *cleanup_state_alloc(void) state->end_seen = 0; state->rcpt_count = 0; state->reason = 0; + state->attr = nvtable_create(10); return (state); } @@ -117,5 +119,6 @@ void cleanup_state_free(CLEANUP_STATE *state) been_here_free(state->dups); if (state->reason) myfree(state->reason); + nvtable_free(state->attr); myfree((char *) state); } diff --git a/postfix/src/global/abounce.c b/postfix/src/global/abounce.c index 821147886..3bb158889 100644 --- a/postfix/src/global/abounce.c +++ b/postfix/src/global/abounce.c @@ -6,44 +6,49 @@ /* SYNOPSIS /* #include /* -/* void abounce_flush(flags, queue, id, sender, callback, context) +/* void abounce_flush(flags, queue, id, encoding, sender, callback, context) /* int flags; /* const char *queue; /* const char *id; +/* const char *encoding; /* const char *sender; /* void (*callback)(int status, char *context); /* char *context; /* -/* void abounce_flush_verp(flags, queue, id, sender, verp, callback, context) +/* void abounce_flush_verp(flags, queue, id, encoding, sender, verp, callback, context) /* int flags; /* const char *queue; /* const char *id; +/* const char *encoding; /* const char *sender; /* const char *verp; /* void (*callback)(int status, char *context); /* char *context; /* -/* void adefer_flush(flags, queue, id, sender, callback, context) +/* void adefer_flush(flags, queue, id, encoding, sender, callback, context) /* int flags; /* const char *queue; /* const char *id; +/* const char *encoding; /* const char *sender; /* void (*callback)(int status, char *context); /* char *context; /* -/* void adefer_flush_verp(flags, queue, id, sender, verp, callback, context) +/* void adefer_flush_verp(flags, queue, id, encoding, sender, verp, callback, context) /* int flags; /* const char *queue; /* const char *id; +/* const char *encoding; /* const char *sender; /* const char *verp; /* void (*callback)(int status, char *context); /* char *context; /* -/* void adefer_warn(flags, queue, id, sender, callback, context) +/* void adefer_warn(flags, queue, id, encoding, sender, callback, context) /* int flags; /* const char *queue; /* const char *id; +/* const char *encoding; /* const char *sender; /* void (*callback)(int status, char *context); /* char *context; @@ -86,6 +91,8 @@ /* .IP id /* The message queue id if the original message file. The bounce log /* file has the same name as the original message file. +/* .IP encoding +/* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}. /* .IP sender /* The sender envelope address. /* .IP verp @@ -182,7 +189,9 @@ static void abounce_event(int unused_event, char *context) static void abounce_request_verp(const char *class, const char *service, int command, int flags, const char *queue, const char *id, - const char *sender, const char *verp, + const char *encoding, + const char *sender, + const char *verp, ABOUNCE_FN callback, char *context) { @@ -205,6 +214,7 @@ static void abounce_request_verp(const char *class, const char *service, ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp, ATTR_TYPE_END) == 0 @@ -218,23 +228,25 @@ static void abounce_request_verp(const char *class, const char *service, /* abounce_flush_verp - asynchronous bounce flush */ void abounce_flush_verp(int flags, const char *queue, const char *id, - const char *sender, const char *verp, - ABOUNCE_FN callback, char *context) + const char *encoding, const char *sender, + const char *verp, ABOUNCE_FN callback, + char *context) { abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service, - BOUNCE_CMD_VERP, flags, queue, id, sender, verp, - callback, context); + BOUNCE_CMD_VERP, flags, queue, id, encoding, + sender, verp, callback, context); } /* adefer_flush_verp - asynchronous defer flush */ void adefer_flush_verp(int flags, const char *queue, const char *id, - const char *sender, const char *verp, - ABOUNCE_FN callback, char *context) + const char *encoding, const char *sender, + const char *verp, ABOUNCE_FN callback, + char *context) { abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service, - BOUNCE_CMD_VERP, flags, queue, id, sender, verp, - callback, context); + BOUNCE_CMD_VERP, flags, queue, id, encoding, + sender, verp, callback, context); } /* abounce_request - suspend pseudo thread until server reply event */ @@ -242,9 +254,8 @@ void adefer_flush_verp(int flags, const char *queue, const char *id, static void abounce_request(const char *class, const char *service, int command, int flags, const char *queue, const char *id, - const char *sender, - ABOUNCE_FN callback, - char *context) + const char *encoding, const char *sender, + ABOUNCE_FN callback, char *context) { ABOUNCE *ap; @@ -265,6 +276,7 @@ static void abounce_request(const char *class, const char *service, ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_END) == 0 && vstream_fflush(ap->fp) == 0) { @@ -277,26 +289,29 @@ static void abounce_request(const char *class, const char *service, /* abounce_flush - asynchronous bounce flush */ void abounce_flush(int flags, const char *queue, const char *id, - const char *sender, ABOUNCE_FN callback, char *context) + const char *encoding, const char *sender, + ABOUNCE_FN callback, char *context) { abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH, - flags, queue, id, sender, callback, context); + flags, queue, id, encoding, sender, callback, context); } /* adefer_flush - asynchronous defer flush */ void adefer_flush(int flags, const char *queue, const char *id, - const char *sender, ABOUNCE_FN callback, char *context) + const char *encoding, const char *sender, + ABOUNCE_FN callback, char *context) { abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH, - flags, queue, id, sender, callback, context); + flags, queue, id, encoding, sender, callback, context); } /* adefer_warn - send copy of defer log to sender as warning bounce */ void adefer_warn(int flags, const char *queue, const char *id, - const char *sender, ABOUNCE_FN callback, char *context) + const char *encoding, const char *sender, + ABOUNCE_FN callback, char *context) { abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN, - flags, queue, id, sender, callback, context); + flags, queue, id, encoding, sender, callback, context); } diff --git a/postfix/src/global/abounce.h b/postfix/src/global/abounce.h index 69542383a..bcc70e2f6 100644 --- a/postfix/src/global/abounce.h +++ b/postfix/src/global/abounce.h @@ -21,12 +21,12 @@ */ typedef void (*ABOUNCE_FN) (int, char *); -extern void abounce_flush(int, const char *, const char *, const char *, ABOUNCE_FN, char *); -extern void adefer_flush(int, const char *, const char *, const char *, ABOUNCE_FN, char *); -extern void adefer_warn(int, const char *, const char *, const char *, ABOUNCE_FN, char *); +extern void abounce_flush(int, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *); +extern void adefer_flush(int, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *); +extern void adefer_warn(int, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *); -extern void abounce_flush_verp(int, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *); -extern void adefer_flush_verp(int, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *); +extern void abounce_flush_verp(int, const char *, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *); +extern void adefer_flush_verp(int, const char *, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *); /* LICENSE /* .ad diff --git a/postfix/src/global/bounce.c b/postfix/src/global/bounce.c index 67f97bb99..05648cbc3 100644 --- a/postfix/src/global/bounce.c +++ b/postfix/src/global/bounce.c @@ -23,10 +23,11 @@ /* const char *format; /* va_list ap; /* -/* int bounce_flush(flags, queue, id, sender) +/* int bounce_flush(flags, queue, id, encoding, sender) /* int flags; /* const char *queue; /* const char *id; +/* const char *encoding; /* const char *sender; /* DESCRIPTION /* This module implements the client interface to the message @@ -56,6 +57,8 @@ /* .IP id /* The message queue id if the original message file. The bounce log /* file has the same name as the original message file. +/* .IP encoding +/* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}. /* .IP sender /* The sender envelope address. /* .IP relay @@ -168,7 +171,7 @@ int vbounce_append(int flags, const char *id, const char *recipient, /* bounce_flush - flush the bounce log and deliver to the sender */ int bounce_flush(int flags, const char *queue, const char *id, - const char *sender) + const char *encoding, const char *sender) { /* @@ -182,6 +185,7 @@ int bounce_flush(int flags, const char *queue, const char *id, ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_END) == 0) { return (0); diff --git a/postfix/src/global/bounce.h b/postfix/src/global/bounce.h index 018b91a4f..11b91eaf5 100644 --- a/postfix/src/global/bounce.h +++ b/postfix/src/global/bounce.h @@ -25,7 +25,7 @@ extern int PRINTFLIKE(6, 7) bounce_append(int, const char *, const char *, const char *,...); extern int vbounce_append(int, const char *, const char *, const char *, time_t, const char *, va_list); -extern int bounce_flush(int, const char *, const char *, const char *); +extern int bounce_flush(int, const char *, const char *, const char *, const char *); extern int PRINTFLIKE(8, 9) bounce_recip(int, const char *, const char *, const char *, const char *, diff --git a/postfix/src/global/defer.c b/postfix/src/global/defer.c index dd331230e..862f3a6fd 100644 --- a/postfix/src/global/defer.c +++ b/postfix/src/global/defer.c @@ -23,10 +23,11 @@ /* const char *format; /* va_list ap; /* -/* int defer_flush(flags, queue, id, sender) +/* int defer_flush(flags, queue, id, encoding, sender) /* int flags; /* const char *queue; /* const char *id; +/* const char *encoding; /* const char *sender; /* /* int defer_warn(flags, queue, id, sender) @@ -70,6 +71,8 @@ /* .IP recipient /* A recipient address that is being deferred. The domain part /* of the address is marked dead (for a limited amount of time). +/* .IP encoding +/* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}. /* .IP sender /* The sender envelope address. /* .IP relay @@ -178,15 +181,16 @@ int vdefer_append(int flags, const char *id, const char *recipient, /* defer_flush - flush the defer log and deliver to the sender */ int defer_flush(int flags, const char *queue, const char *id, - const char *sender) + const char *encoding, const char *sender) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, - ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, - ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, - ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, - ATTR_TYPE_END) == 0) { + ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_FLUSH, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, + ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, + ATTR_TYPE_END) == 0) { return (0); } else { return (-1); @@ -200,12 +204,12 @@ int defer_warn(int flags, const char *queue, const char *id, const char *sender) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, - ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, - ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, - ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, - ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, - ATTR_TYPE_END) == 0) { + ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, + ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, + ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, + ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, + ATTR_TYPE_END) == 0) { return (0); } else { return (-1); diff --git a/postfix/src/global/defer.h b/postfix/src/global/defer.h index d23e2d664..18bbbddd9 100644 --- a/postfix/src/global/defer.h +++ b/postfix/src/global/defer.h @@ -29,7 +29,7 @@ extern int PRINTFLIKE(6, 7) defer_append(int, const char *, const char *, const char *, time_t, const char *,...); extern int vdefer_append(int, const char *, const char *, const char *, time_t, const char *, va_list); -extern int defer_flush(int, const char *, const char *, const char *); +extern int defer_flush(int, const char *, const char *, const char *, const char *); extern int defer_warn(int, const char *, const char *, const char *); diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c index 35c83e780..75dd3c61b 100644 --- a/postfix/src/global/deliver_request.c +++ b/postfix/src/global/deliver_request.c @@ -15,6 +15,7 @@ /* long data_offset; /* long data_size; /* char *nexthop; +/* char *encoding; /* char *sender; /* char *errors_to; /* char *return_receipt; @@ -169,6 +170,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) static VSTRING *queue_name; static VSTRING *queue_id; static VSTRING *nexthop; + static VSTRING *encoding; static VSTRING *address; static VSTRING *errors_to; static VSTRING *return_receipt; @@ -183,6 +185,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) queue_name = vstring_alloc(10); queue_id = vstring_alloc(10); nexthop = vstring_alloc(10); + encoding = vstring_alloc(10); address = vstring_alloc(10); errors_to = vstring_alloc(10); return_receipt = vstring_alloc(10); @@ -199,11 +202,12 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &request->data_offset, ATTR_TYPE_LONG, MAIL_ATTR_SIZE, &request->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, address, ATTR_TYPE_STR, MAIL_ATTR_ERRTO, errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, return_receipt, ATTR_TYPE_LONG, MAIL_ATTR_TIME, &request->arrival_time, - ATTR_TYPE_END) != 10) + ATTR_TYPE_END) != 11) return (-1); if (mail_open_ok(vstring_str(queue_name), vstring_str(queue_id), &st, &path) == 0) @@ -212,6 +216,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) request->queue_name = mystrdup(vstring_str(queue_name)); request->queue_id = mystrdup(vstring_str(queue_id)); request->nexthop = mystrdup(vstring_str(nexthop)); + request->encoding = mystrdup(vstring_str(encoding)); request->sender = mystrdup(vstring_str(address)); request->errors_to = mystrdup(vstring_str(errors_to)); request->return_receipt = mystrdup(vstring_str(return_receipt)); @@ -274,6 +279,7 @@ static DELIVER_REQUEST *deliver_request_alloc(void) request->queue_name = 0; request->queue_id = 0; request->nexthop = 0; + request->encoding = 0; request->sender = 0; request->errors_to = 0; request->return_receipt = 0; @@ -296,6 +302,8 @@ static void deliver_request_free(DELIVER_REQUEST *request) myfree(request->queue_id); if (request->nexthop) myfree(request->nexthop); + if (request->encoding) + myfree(request->encoding); if (request->sender) myfree(request->sender); if (request->errors_to) diff --git a/postfix/src/global/deliver_request.h b/postfix/src/global/deliver_request.h index 45c205523..bf4f135b5 100644 --- a/postfix/src/global/deliver_request.h +++ b/postfix/src/global/deliver_request.h @@ -33,6 +33,7 @@ typedef struct DELIVER_REQUEST { long data_offset; /* offset to message */ long data_size; /* message size */ char *nexthop; /* next hop name */ + char *encoding; /* content encoding */ char *sender; /* envelope sender */ char *errors_to; /* error report address */ char *return_receipt; /* confirm receipt address */ diff --git a/postfix/src/global/header_opts.c b/postfix/src/global/header_opts.c index f4d60544e..a31f651c6 100644 --- a/postfix/src/global/header_opts.c +++ b/postfix/src/global/header_opts.c @@ -51,6 +51,7 @@ static HEADER_OPTS header_opts[] = { "Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP, "Bcc", HDR_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP, "Cc", HDR_CC, HDR_OPT_XRECIP, + "Content-Transfer-Encoding", HDR_CONTENT_TRANSFER_ENCODING, 0, "Content-Length", HDR_CONTENT_LENGTH, HDR_OPT_DROP, "Delivered-To", HDR_DELIVERED_TO, 0, "Date", HDR_DATE, 0, diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 1552c5e9c..7a1d62dd2 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -1486,6 +1486,13 @@ extern int var_db_create_buf; #define DEF_DB_READ_BUF (128 *1024) extern int var_db_read_buf; + /* + * Named queue file attributes. + */ +#define VAR_QATTR_COUNT_LIMIT "queue_file_attribute_count_limit" +#define DEF_QATTR_COUNT_LIMIT 100 +extern int var_qattr_count_limit; + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index adadcda60..bb4e5caef 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -98,6 +98,21 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_TRANSPORT "transport" #define MAIL_ATTR_NEXTHOP "nexthop" + /* + * The following attribute names are stored in queue files. Changing this + * means lots of work to maintain backwards compatibility with queued mail. + */ +#define MAIL_ATTR_ENCODING "encoding" /* internal encoding */ +#define MAIL_ATTR_ENC_8BIT "8bit" /* 8BITMIME equivalent */ +#define MAIL_ATTR_ENC_7BIT "7bit" /* 7BIT equivalent */ +#define MAIL_ATTR_ENC_NONE "" /* encoding unknown */ +#define MAIL_ATTR_CLIENT_NAME "client_name" /* client hostname */ +#define MAIL_ATTR_CLIENT_ADDR "client_address" /* client address */ +#define MAIL_ATTR_HELO_NAME "helo_name" /* SMTP helo name */ +#define MAIL_ATTR_ORIGIN "message_origin" /* hostname[address] */ +#define MAIL_ATTR_ORG_NONE "unknown" /* origin unknown */ +#define MAIL_ATTR_ORG_LOCAL "local" /* local submission */ + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 051405c8c..8370958da 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only, unless they include the same bugfix as a patch release. */ -#define MAIL_RELEASE_DATE "20020509" +#define MAIL_RELEASE_DATE "20020512" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "1.1.9-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/post_mail.c b/postfix/src/global/post_mail.c index 425b1a52d..02e3faf0e 100644 --- a/postfix/src/global/post_mail.c +++ b/postfix/src/global/post_mail.c @@ -152,6 +152,8 @@ static void post_mail_init(VSTREAM *stream, const char *sender, * size record. */ rec_fprintf(stream, REC_TYPE_TIME, "%ld", (long) now); + rec_fprintf(stream, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ORIGIN, MAIL_ATTR_ORG_LOCAL); rec_fputs(stream, REC_TYPE_FROM, sender); rec_fputs(stream, REC_TYPE_RCPT, recipient); rec_fputs(stream, REC_TYPE_MESG, ""); diff --git a/postfix/src/global/rec_type.h b/postfix/src/global/rec_type.h index f1caaa466..0c3257a5d 100644 --- a/postfix/src/global/rec_type.h +++ b/postfix/src/global/rec_type.h @@ -55,10 +55,16 @@ * The types of records that I expect to see while processing different * record groups. The first member in each set is the record type that * indicates the end of that record group. + * + * XXX A records in the extracted segment are generated only by the cleanup + * server, and are not supposed to be present in locally submitted mail, as + * this is "postfix internal" information. However, the pickup server has to + * allow for the presence of A records in the extracted segment, because it + * can be requested to re-process already queued mail with `postsuper -r'. */ #define REC_TYPE_ENVELOPE "MCTFILSDROWVA" #define REC_TYPE_CONTENT "XLN" -#define REC_TYPE_EXTRACT "EDROPre" /* NOT A */ +#define REC_TYPE_EXTRACT "EDROPreA" #define REC_TYPE_NOEXTRACT "E" /* diff --git a/postfix/src/lmtp/Makefile.in b/postfix/src/lmtp/Makefile.in index 98939cb5a..2422e352f 100644 --- a/postfix/src/lmtp/Makefile.in +++ b/postfix/src/lmtp/Makefile.in @@ -163,6 +163,9 @@ lmtp_proto.o: ../../include/off_cvt.h lmtp_proto.o: ../../include/mark_corrupt.h lmtp_proto.o: ../../include/quote_821_local.h lmtp_proto.o: ../../include/quote_flags.h +lmtp_proto.o: ../../include/mail_proto.h +lmtp_proto.o: ../../include/iostuff.h +lmtp_proto.o: ../../include/attr.h lmtp_proto.o: lmtp.h lmtp_proto.o: ../../include/argv.h lmtp_proto.o: lmtp_sasl.h diff --git a/postfix/src/lmtp/lmtp.c b/postfix/src/lmtp/lmtp.c index 17a5e9c59..aa9aaf350 100644 --- a/postfix/src/lmtp/lmtp.c +++ b/postfix/src/lmtp/lmtp.c @@ -46,6 +46,7 @@ /* STANDARDS /* RFC 821 (SMTP protocol) /* RFC 1651 (SMTP service extensions) +/* RFC 1652 (8bit-MIME transport) /* RFC 1870 (Message Size Declaration) /* RFC 2033 (LMTP protocol) /* RFC 2197 (Pipelining) diff --git a/postfix/src/lmtp/lmtp_proto.c b/postfix/src/lmtp/lmtp_proto.c index 4a247950f..6dffbc729 100644 --- a/postfix/src/lmtp/lmtp_proto.c +++ b/postfix/src/lmtp/lmtp_proto.c @@ -117,6 +117,7 @@ #include #include #include +#include /* Application-specific. */ @@ -294,12 +295,12 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state) * Macros for readability. XXX Aren't LMTP addresses supposed to be case * insensitive? */ -#define REWRITE_ADDRESS(addr) do { \ - if (*(addr)) { \ - quote_821_local(state->scratch, addr, QUOTE_FLAG_8BITCLEAN); \ - myfree(addr); \ - addr = mystrdup(vstring_str(state->scratch)); \ - lowercase(addr); \ +#define REWRITE_ADDRESS(dst, src) do { \ + if (*(src)) { \ + quote_821_local(dst, src, QUOTE_FLAG_8BITCLEAN); \ + lowercase(vstring_str(dst)); \ + } else { \ + vstring_strcpy(dst, src); \ } \ } while (0) @@ -357,12 +358,21 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state) * Build the MAIL FROM command. */ case LMTP_STATE_MAIL: - if (*request->sender) - REWRITE_ADDRESS(request->sender); - vstring_sprintf(next_command, "MAIL FROM:<%s>", request->sender); - if (state->features & LMTP_FEATURE_SIZE) + REWRITE_ADDRESS(state->scratch, request->sender); + vstring_sprintf(next_command, "MAIL FROM:<%s>", + vstring_str(state->scratch)); + if (state->features & LMTP_FEATURE_SIZE) /* RFC 1652 */ vstring_sprintf_append(next_command, " SIZE=%lu", request->data_size); + if (state->features & LMTP_FEATURE_8BITMIME) { + if (strcmp(request->encoding, MAIL_ATTR_ENC_8BIT) == 0) + vstring_strcat(next_command, " BODY=8BITMIME"); + else if (strcmp(request->encoding, MAIL_ATTR_ENC_7BIT) == 0) + vstring_strcat(next_command, " BODY=7BIT"); + else if (strcmp(request->encoding, MAIL_ATTR_ENC_NONE) != 0) + msg_warn("%s: unknown content encoding: %s", + request->queue_id, request->encoding); + } next_state = LMTP_STATE_RCPT; break; @@ -372,8 +382,9 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state) */ case LMTP_STATE_RCPT: rcpt = request->rcpt_list.info + send_rcpt; - REWRITE_ADDRESS(rcpt->address); - vstring_sprintf(next_command, "RCPT TO:<%s>", rcpt->address); + REWRITE_ADDRESS(state->scratch, rcpt->address); + vstring_sprintf(next_command, "RCPT TO:<%s>", + vstring_str(state->scratch)); if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len) next_state = LMTP_STATE_DATA; break; diff --git a/postfix/src/nqmgr/Makefile.in b/postfix/src/nqmgr/Makefile.in index 7396348c8..cb465cfa8 100644 --- a/postfix/src/nqmgr/Makefile.in +++ b/postfix/src/nqmgr/Makefile.in @@ -209,6 +209,9 @@ qmgr_message.o: ../../include/maps.h qmgr_message.o: ../../include/opened.h qmgr_message.o: ../../include/resolve_local.h qmgr_message.o: ../../include/verp_sender.h +qmgr_message.o: ../../include/mail_proto.h +qmgr_message.o: ../../include/iostuff.h +qmgr_message.o: ../../include/attr.h qmgr_message.o: ../../include/resolve_clnt.h qmgr_message.o: qmgr.h qmgr_message.o: ../../include/scan_dir.h diff --git a/postfix/src/nqmgr/qmgr.h b/postfix/src/nqmgr/qmgr.h index 8749c3560..9607268f6 100644 --- a/postfix/src/nqmgr/qmgr.h +++ b/postfix/src/nqmgr/qmgr.h @@ -266,6 +266,7 @@ struct QMGR_MESSAGE { long data_offset; /* data seek offset */ char *queue_name; /* queue name */ char *queue_id; /* queue file */ + char *encoding; /* content encoding */ char *sender; /* complete address */ char *verp_delims; /* VERP delimiters */ char *errors_to; /* error report address */ diff --git a/postfix/src/nqmgr/qmgr_active.c b/postfix/src/nqmgr/qmgr_active.c index 722d81073..b4b7f9c48 100644 --- a/postfix/src/nqmgr/qmgr_active.c +++ b/postfix/src/nqmgr/qmgr_active.c @@ -283,6 +283,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) abounce_flush(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, qmgr_active_done_2_bounce_flush, (char *) message); @@ -290,6 +291,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) abounce_flush_verp(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, message->verp_delims, qmgr_active_done_2_bounce_flush, @@ -370,6 +372,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) adefer_flush(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, qmgr_active_done_3_defer_flush, (char *) message); @@ -377,6 +380,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) adefer_flush_verp(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, message->verp_delims, qmgr_active_done_3_defer_flush, @@ -389,6 +393,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) adefer_warn(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, qmgr_active_done_3_defer_warn, (char *) message); diff --git a/postfix/src/nqmgr/qmgr_deliver.c b/postfix/src/nqmgr/qmgr_deliver.c index 394b267d6..d8de110c9 100644 --- a/postfix/src/nqmgr/qmgr_deliver.c +++ b/postfix/src/nqmgr/qmgr_deliver.c @@ -166,6 +166,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset, ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt, diff --git a/postfix/src/nqmgr/qmgr_message.c b/postfix/src/nqmgr/qmgr_message.c index d5bde3a3d..fac420478 100644 --- a/postfix/src/nqmgr/qmgr_message.c +++ b/postfix/src/nqmgr/qmgr_message.c @@ -122,6 +122,7 @@ #include #include #include +#include /* Client stubs. */ @@ -153,6 +154,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name, message->data_offset = 0; message->queue_id = mystrdup(queue_id); message->queue_name = mystrdup(queue_name); + message->encoding = 0; message->sender = 0; message->errors_to = 0; message->return_receipt = 0; @@ -283,6 +285,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message) long save_offset = message->rcpt_offset; /* save a flag */ char *start; int recipient_limit; + const char *error_text; + char *name; + char *value; /* * Initialize. No early returns or we have a memory leak. @@ -404,6 +409,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message) break; } } + } else if (rec_type == REC_TYPE_ATTR) { + if ((error_text = split_nameval(start, &name, &value)) != 0) { + msg_warn("%s: bad attribute: %s: %.200s", + message->queue_id, error_text, start); + break; + } + if (strcmp(name, MAIL_ATTR_ENCODING) == 0) + if (message->encoding == 0) + message->encoding = mystrdup(value); } else if (rec_type == REC_TYPE_ERTO) { if (message->errors_to == 0) { message->errors_to = mystrdup(start); @@ -447,6 +461,8 @@ static int qmgr_message_read(QMGR_MESSAGE *message) message->errors_to = mystrdup(""); if (message->return_receipt == 0) message->return_receipt = mystrdup(""); + if (message->encoding == 0) + message->encoding = mystrdup(MAIL_ATTR_ENC_NONE); /* * Clean up. @@ -926,6 +942,8 @@ void qmgr_message_free(QMGR_MESSAGE *message) qmgr_job_free(job); myfree(message->queue_id); myfree(message->queue_name); + if (message->encoding) + myfree(message->encoding); if (message->sender) myfree(message->sender); if (message->verp_delims) diff --git a/postfix/src/pickup/Makefile.in b/postfix/src/pickup/Makefile.in index a9006d5ed..a30d18800 100644 --- a/postfix/src/pickup/Makefile.in +++ b/postfix/src/pickup/Makefile.in @@ -62,6 +62,7 @@ pickup.o: ../../include/vbuf.h pickup.o: ../../include/vstream.h pickup.o: ../../include/set_ugid.h pickup.o: ../../include/safe_open.h +pickup.o: ../../include/stringops.h pickup.o: ../../include/mail_queue.h pickup.o: ../../include/mail_open_ok.h pickup.o: ../../include/mymalloc.h diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 7bf7d5835..4ec76b434 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -92,6 +92,7 @@ #include #include #include +#include /* Global library. */ @@ -159,13 +160,21 @@ static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, { int type; int check_first = (*expected == REC_TYPE_CONTENT[0]); + const char *error_text; + char *attr_name; + char *attr_value; /* * Limit the input record size. All front-end programs should protect the * mail system against unreasonable inputs. This also requires that we * limit the size of envelope records written by the local posting agent. + * * As time stamp we use the scrutinized queue file modification time, and * ignore the time stamp embedded in the queue file. + * + * Allow attribute records if the queue file is owned by the mail system + * (postsuper -r) or if the attribute specifies the MIME body type + * (sendmail -B). */ for (;;) { if ((type = rec_get(qfile, buf, var_line_limit)) < 0 @@ -181,6 +190,28 @@ static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, info->rcpt = mystrdup(vstring_str(buf)); if (type == REC_TYPE_TIME) continue; + if (type == REC_TYPE_ATTR) { + if ((error_text = split_nameval(vstring_str(buf), &attr_name, + &attr_value)) != 0) { + msg_warn("uid=%ld: malformed attribute record: %s: %.200s", + (long) info->st.st_uid, error_text, vstring_str(buf)); + continue; + } +#define STREQ(x,y) (strcmp(x,y) == 0) + + if (info->st.st_uid == var_owner_uid + || (STREQ(attr_name, MAIL_ATTR_ENCODING) + && (STREQ(attr_value, MAIL_ATTR_ENC_7BIT) + || STREQ(attr_value, MAIL_ATTR_ENC_8BIT) + || STREQ(attr_value, MAIL_ATTR_ENC_NONE)))) { + rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s", + attr_name, attr_value); + continue; + } + msg_warn("uid=%ld: ignoring attribute record: %.200s=%.200s", + (long) info->st.st_uid, attr_name, attr_value); + continue; + } if (type == REC_TYPE_FILT && *expected == REC_TYPE_ENVELOPE[0]) continue; else { @@ -239,6 +270,12 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, if (*var_filter_xport) rec_fprintf(cleanup, REC_TYPE_FILT, "%s", var_filter_xport); + /* + * Origin is local. + */ + rec_fprintf(cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ORIGIN, MAIL_ATTR_ORG_LOCAL); + /* * Copy the message envelope segment. Allow only those records that we * expect to see in the envelope section. The envelope segment must @@ -322,7 +359,6 @@ static int pickup_file(PICKUP_INFO *info) int status; VSTREAM *qfile; VSTREAM *cleanup; - int fd; /* * Open the submitted file. If we cannot open it, and we're not having a @@ -331,8 +367,8 @@ static int pickup_file(PICKUP_INFO *info) * Perhaps we should save "bad" files elsewhere for further inspection. * XXX How can we delete a file when open() fails with ENOENT? */ - qfile = safe_open(info->path, O_RDONLY | O_NONBLOCK, 0, - (struct stat *) 0, -1, -1, buf); + qfile = safe_open(info->path, O_RDONLY | O_NONBLOCK, 0, + (struct stat *) 0, -1, -1, buf); if (qfile == 0) { if (errno != ENOENT) msg_warn("open input file %s: %s", info->path, vstring_str(buf)); diff --git a/postfix/src/qmgr/Makefile.in b/postfix/src/qmgr/Makefile.in index 19f24d7e6..92ef4a93f 100644 --- a/postfix/src/qmgr/Makefile.in +++ b/postfix/src/qmgr/Makefile.in @@ -193,6 +193,9 @@ qmgr_message.o: ../../include/maps.h qmgr_message.o: ../../include/opened.h qmgr_message.o: ../../include/resolve_local.h qmgr_message.o: ../../include/verp_sender.h +qmgr_message.o: ../../include/mail_proto.h +qmgr_message.o: ../../include/iostuff.h +qmgr_message.o: ../../include/attr.h qmgr_message.o: ../../include/resolve_clnt.h qmgr_message.o: qmgr.h qmgr_message.o: ../../include/scan_dir.h diff --git a/postfix/src/qmgr/qmgr.h b/postfix/src/qmgr/qmgr.h index 9839c07c2..4f15f8c90 100644 --- a/postfix/src/qmgr/qmgr.h +++ b/postfix/src/qmgr/qmgr.h @@ -226,6 +226,7 @@ struct QMGR_MESSAGE { long data_offset; /* data seek offset */ char *queue_name; /* queue name */ char *queue_id; /* queue file */ + char *encoding; /* content encoding */ char *sender; /* complete address */ char *verp_delims; /* VERP delimiters */ char *errors_to; /* error report address */ diff --git a/postfix/src/qmgr/qmgr_active.c b/postfix/src/qmgr/qmgr_active.c index 722d81073..b4b7f9c48 100644 --- a/postfix/src/qmgr/qmgr_active.c +++ b/postfix/src/qmgr/qmgr_active.c @@ -283,6 +283,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) abounce_flush(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, qmgr_active_done_2_bounce_flush, (char *) message); @@ -290,6 +291,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) abounce_flush_verp(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, message->verp_delims, qmgr_active_done_2_bounce_flush, @@ -370,6 +372,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) adefer_flush(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, qmgr_active_done_3_defer_flush, (char *) message); @@ -377,6 +380,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) adefer_flush_verp(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, message->verp_delims, qmgr_active_done_3_defer_flush, @@ -389,6 +393,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) adefer_warn(BOUNCE_FLAG_KEEP, message->queue_name, message->queue_id, + message->encoding, message->errors_to, qmgr_active_done_3_defer_warn, (char *) message); diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c index 45c0a6cdd..64b170c26 100644 --- a/postfix/src/qmgr/qmgr_deliver.c +++ b/postfix/src/qmgr/qmgr_deliver.c @@ -161,6 +161,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, message->data_offset, ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, + ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_ERRTO, message->errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, message->return_receipt, diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index 3aa4de849..9433f8773 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -113,6 +113,7 @@ #include #include #include +#include /* Client stubs. */ @@ -143,6 +144,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name, message->data_offset = 0; message->queue_id = mystrdup(queue_id); message->queue_name = mystrdup(queue_name); + message->encoding = 0; message->sender = 0; message->errors_to = 0; message->return_receipt = 0; @@ -203,6 +205,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message) char *start; struct stat st; int nrcpt = 0; + const char *error_text; + char *name; + char *value; /* * Initialize. No early returns or we have a memory leak. @@ -294,6 +299,15 @@ static int qmgr_message_read(QMGR_MESSAGE *message) } if (vstream_fseek(message->fp, extra_offset, SEEK_SET) < 0) msg_fatal("seek file %s: %m", VSTREAM_PATH(message->fp)); + } else if (rec_type == REC_TYPE_ATTR) { + if ((error_text = split_nameval(start, &name, &value)) != 0) { + msg_warn("%s: bad attribute: %s: %.200s", + message->queue_id, error_text, start); + break; + } + if (strcmp(name, MAIL_ATTR_ENCODING) == 0) + if (message->encoding == 0) + message->encoding = mystrdup(value); } else if (rec_type == REC_TYPE_ERTO) { if (message->errors_to == 0) message->errors_to = mystrdup(start); @@ -336,6 +350,8 @@ static int qmgr_message_read(QMGR_MESSAGE *message) message->errors_to = mystrdup(""); if (message->return_receipt == 0) message->return_receipt = mystrdup(""); + if (message->encoding == 0) + message->encoding = mystrdup(MAIL_ATTR_ENC_NONE); /* * Clean up. @@ -761,6 +777,8 @@ void qmgr_message_free(QMGR_MESSAGE *message) msg_panic("qmgr_message_free: queue file is open"); myfree(message->queue_id); myfree(message->queue_name); + if (message->encoding) + myfree(message->encoding); if (message->sender) myfree(message->sender); if (message->verp_delims) diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 9ccd01eeb..47106e990 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -245,6 +245,18 @@ static void qmqpd_copy_sender(QMQPD_STATE *state) state->sender = mystrndup(STR(state->buf), LEN(state->buf)); } +/* qmqpd_write_attributes - save session attributes */ + +static void qmqpd_write_attributes(QMQPD_STATE *state) +{ + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_CLIENT_NAME, state->name); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_CLIENT_ADDR, state->addr); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ORIGIN, state->namaddr); +} + /* qmqpd_copy_recipients - copy message recipients */ static void qmqpd_copy_recipients(QMQPD_STATE *state) @@ -503,6 +515,11 @@ static void qmqpd_receive(QMQPD_STATE *state) */ qmqpd_copy_sender(state); + /* + * Record some session attributes. + */ + qmqpd_write_attributes(state); + /* * Read and write the envelope recipients, including the optional big * brother recipient. diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index ea054f656..138f38be1 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -49,9 +49,8 @@ /* controlled by parameters in the \fBmain.cf\fR configuration file. /* /* The following options are recognized: -/* .IP "\fB-B \fIbody_type\fR (ignored)" -/* The message body MIME type. Currently, Postfix implements -/* \fBjust-send-eight\fR. +/* .IP "\fB-B \fIbody_type\fR" +/* The message body MIME type: \fB7BIT\fR or \fB8BITMIME\fR. /* .IP "\fB-C \fIconfig_file\fR (ignored :-)" /* The path name of the \fBsendmail.cf\fR file. Postfix configuration /* files are kept in \fB/etc/postfix\fR. @@ -347,8 +346,8 @@ char *verp_delims; /* enqueue - post one message */ -static void enqueue(const int flags, const char *sender, const char *full_name, - char **recipients) +static void enqueue(const int flags, const char *encoding, const char *sender, + const char *full_name, char **recipients) { VSTRING *buf; VSTREAM *dst; @@ -428,6 +427,8 @@ static void enqueue(const int flags, const char *sender, const char *full_name, rec_fputs(dst, REC_TYPE_FROM, saved_sender); if (verp_delims && *saved_sender == 0) msg_fatal("-V option requires non-null sender address"); + if (encoding) + rec_fprintf(dst, REC_TYPE_ATTR, "%s=%s", MAIL_ATTR_ENCODING, encoding); if (verp_delims) rec_fputs(dst, REC_TYPE_VERP, verp_delims); if (recipients) { @@ -538,6 +539,7 @@ int main(int argc, char **argv) int n; int flags = SM_FLAG_DEFAULT; char *site_to_flush = 0; + char *encoding = 0; /* * Be consistent with file permissions. @@ -664,6 +666,14 @@ int main(int argc, char **argv) break; case 'n': msg_fatal_status(EX_USAGE, "-%c option not supported", c); + case 'B': + if (strcmp(optarg, "8BITMIME") == 0)/* RFC 1652 */ + encoding = MAIL_ATTR_ENC_8BIT; + else if (strcmp(optarg, "7BIT") == 0) /* RFC 1652 */ + encoding = MAIL_ATTR_ENC_7BIT; + else + msg_fatal_status(EX_USAGE, "-B option needs 8BITMIME or 7BIT"); + break; case 'F': /* full name */ full_name = optarg; break; @@ -779,7 +789,7 @@ int main(int argc, char **argv) /* NOTREACHED */ case SM_MODE_ENQUEUE: if (site_to_flush == 0) { - enqueue(flags, sender, full_name, argv + OPTIND); + enqueue(flags, encoding, sender, full_name, argv + OPTIND); exit(0); } if (argv[OPTIND]) diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index 0dc84f510..d1cbbcfd8 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -167,6 +167,8 @@ smtp_proto.o: ../../include/off_cvt.h smtp_proto.o: ../../include/mark_corrupt.h smtp_proto.o: ../../include/quote_821_local.h smtp_proto.o: ../../include/quote_flags.h +smtp_proto.o: ../../include/mail_proto.h +smtp_proto.o: ../../include/attr.h smtp_proto.o: smtp.h smtp_proto.o: ../../include/argv.h smtp_proto.o: smtp_sasl.h diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index c4eddd07f..a25d7eb4d 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -38,6 +38,7 @@ /* STANDARDS /* RFC 821 (SMTP protocol) /* RFC 1651 (SMTP service extensions) +/* RFC 1652 (8bit-MIME transport) /* RFC 1870 (Message Size Declaration) /* RFC 2197 (Pipelining) /* RFC 2554 (AUTH command) diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 8274466ff..fe9d2a177 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -100,6 +100,7 @@ #include #include #include +#include /* Application-specific. */ @@ -303,20 +304,20 @@ int smtp_xfer(SMTP_STATE *state) /* * Macros for readability. */ -#define REWRITE_ADDRESS(addr) do { \ - if (*(addr)) { \ - quote_821_local(state->scratch, addr, QUOTE_FLAG_8BITCLEAN); \ - smtp_unalias_addr(state->scratch2, vstring_str(state->scratch)); \ - myfree(addr); \ - addr = mystrdup(vstring_str(state->scratch2)); \ +#define REWRITE_ADDRESS(dst, mid, src) do { \ + if (*(src)) { \ + quote_821_local(mid, src, QUOTE_FLAG_8BITCLEAN); \ + smtp_unalias_addr(dst, vstring_str(mid)); \ + } else { \ + vstring_strcpy(dst, src); \ } \ } while (0) -#define QUOTE_ADDRESS(addr) do { \ - if (*(addr)) { \ - quote_821_local(state->scratch, addr, QUOTE_FLAG_8BITCLEAN); \ - myfree(addr); \ - addr = mystrdup(vstring_str(state->scratch)); \ +#define QUOTE_ADDRESS(dst, src) do { \ + if (*(src)) { \ + quote_821_local(dst, src, QUOTE_FLAG_8BITCLEAN); \ + } else { \ + vstring_strcpy(dst, src); \ } \ } while (0) @@ -408,14 +409,25 @@ int smtp_xfer(SMTP_STATE *state) */ case SMTP_STATE_MAIL: if (var_disable_dns == 0) { - REWRITE_ADDRESS(request->sender); + REWRITE_ADDRESS(state->scratch, state->scratch2, + request->sender); } else { - QUOTE_ADDRESS(request->sender); + QUOTE_ADDRESS(state->scratch, request->sender); } - vstring_sprintf(next_command, "MAIL FROM:<%s>", request->sender); - if (state->features & SMTP_FEATURE_SIZE) + vstring_sprintf(next_command, "MAIL FROM:<%s>", + vstring_str(state->scratch)); + if (state->features & SMTP_FEATURE_SIZE) /* RFC 1652 */ vstring_sprintf_append(next_command, " SIZE=%lu", request->data_size); + if (state->features & SMTP_FEATURE_8BITMIME) { + if (strcmp(request->encoding, MAIL_ATTR_ENC_8BIT) == 0) + vstring_strcat(next_command, " BODY=8BITMIME"); + else if (strcmp(request->encoding, MAIL_ATTR_ENC_7BIT) == 0) + vstring_strcat(next_command, " BODY=7BIT"); + else if (strcmp(request->encoding, MAIL_ATTR_ENC_NONE) != 0) + msg_warn("%s: unknown content encoding: %s", + request->queue_id, request->encoding); + } next_state = SMTP_STATE_RCPT; break; @@ -426,11 +438,13 @@ int smtp_xfer(SMTP_STATE *state) case SMTP_STATE_RCPT: rcpt = request->rcpt_list.info + send_rcpt; if (var_disable_dns == 0) { - REWRITE_ADDRESS(rcpt->address); + REWRITE_ADDRESS(state->scratch, state->scratch2, + rcpt->address); } else { - QUOTE_ADDRESS(rcpt->address); + QUOTE_ADDRESS(state->scratch, rcpt->address); } - vstring_sprintf(next_command, "RCPT TO:<%s>", rcpt->address); + vstring_sprintf(next_command, "RCPT TO:<%s>", + vstring_str(state->scratch)); if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len) next_state = SMTP_STATE_DATA; break; diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 866804198..0da6928fd 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -130,6 +130,8 @@ smtpd.o: ../../include/verp_sender.h smtpd.o: ../../include/string_list.h smtpd.o: ../../include/match_list.h smtpd.o: ../../include/match_ops.h +smtpd.o: ../../include/quote_822_local.h +smtpd.o: ../../include/quote_flags.h smtpd.o: ../../include/mail_server.h smtpd.o: smtpd_token.h smtpd.o: smtpd.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index fdd063caf..ddc016bc9 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -655,6 +655,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) int narg; char *arg; char *verp_delims = 0; + char *encoding = 0; state->msg_size = 0; @@ -695,10 +696,11 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) } for (narg = 3; narg < argc; narg++) { arg = argv[narg].strval; - if (strcasecmp(arg, "BODY=8BITMIME") == 0 - || strcasecmp(arg, "BODY=7BIT") == 0) { - /* void */ ; - } else if (strncasecmp(arg, "SIZE=", 5) == 0) { + if (strcasecmp(arg, "BODY=8BITMIME") == 0) { /* RFC 1652 */ + encoding = MAIL_ATTR_ENC_8BIT; + } else if (strcasecmp(arg, "BODY=7BIT") == 0) { /* RFC 1652 */ + encoding = MAIL_ATTR_ENC_7BIT; + } else if (strncasecmp(arg, "SIZE=", 5) == 0) { /* RFC 1870 */ /* Reject non-numeric size. */ if (!alldig(arg + 5)) { state->error_mask |= MAIL_ERROR_PROTOCOL; @@ -771,6 +773,18 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) if (*var_filter_xport) rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport); rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval); + if (encoding != 0) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ENCODING, encoding); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_CLIENT_NAME, state->name); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_CLIENT_ADDR, state->addr); + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_ORIGIN, state->namaddr); + if (state->helo_name != 0) + rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s", + MAIL_ATTR_HELO_NAME, state->helo_name); if (verp_delims) rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims); state->sender = mystrdup(argv[2].strval); diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 4580b1624..32868885c 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -26,7 +26,7 @@ SRCS = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \ unix_connect.c unix_listen.c unix_trigger.c unsafe.c username.c \ valid_hostname.c vbuf.c vbuf_print.c vstream.c vstream_popen.c \ vstring.c vstring_vstream.c watchdog.c writable.c write_buf.c \ - write_wait.c strcasecmp.c + write_wait.c strcasecmp.c nvtable.c OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \ attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \ chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \ @@ -54,7 +54,7 @@ OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \ unix_connect.o unix_listen.o unix_trigger.o unsafe.o username.o \ valid_hostname.o vbuf.o vbuf_print.o vstream.o vstream_popen.o \ vstring.o vstring_vstream.o watchdog.o writable.o write_buf.o \ - write_wait.o $(STRCASE) + write_wait.o nvtable.o $(STRCASE) HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \ connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \ dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \ @@ -71,7 +71,8 @@ HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \ scan_dir.h set_eugid.h set_ugid.h sigdelay.h spawn_command.h \ split_at.h stat_as.h stringops.h sys_defs.h timed_connect.h \ timed_wait.h trigger.h username.h valid_hostname.h vbuf.h \ - vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h + vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h \ + nvtable.h TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ stream_test.c dup2_pass_on_exec.c WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \ @@ -922,6 +923,11 @@ non_blocking.o: non_blocking.c non_blocking.o: sys_defs.h non_blocking.o: msg.h non_blocking.o: iostuff.h +nvtable.o: nvtable.c +nvtable.o: sys_defs.h +nvtable.o: mymalloc.h +nvtable.o: htable.h +nvtable.o: nvtable.h open_as.o: open_as.c open_as.o: sys_defs.h open_as.o: msg.h diff --git a/postfix/src/util/dict.c b/postfix/src/util/dict.c index 92fedc57e..e19587781 100644 --- a/postfix/src/util/dict.c +++ b/postfix/src/util/dict.c @@ -407,7 +407,7 @@ static int dict_eval_action(int type, VSTRING *buf, char *ptr) char *myname = "dict_eval_action"; const char *pp; - if (msg_verbose) + if (msg_verbose > 1) msg_info("%s: type %s buf %s context %s \"%s\" %s", myname, type == MAC_PARSE_VARNAME ? "variable" : "literal", STR(buf), ctxt->dict_name, STR(ctxt->buf), diff --git a/postfix/src/util/nvtable.c b/postfix/src/util/nvtable.c new file mode 100644 index 000000000..693f693da --- /dev/null +++ b/postfix/src/util/nvtable.c @@ -0,0 +1,122 @@ +/*++ +/* NAME +/* nvtable 3 +/* SUMMARY +/* attribute list manager +/* SYNOPSIS +/* #include +/* +/* typedef struct { +/* .in +4 +/* char *key; +/* char *value; +/* /* private fields... */ +/* .in -4 +/* } NVTABLE_INFO; +/* +/* NVTABLE *nvtable_create(size) +/* int size; +/* +/* NVTABLE_INFO *nvtable_update(table, key, value) +/* NVTABLE *table; +/* const char *key; +/* const char *value; +/* +/* char *nvtable_find(table, key) +/* NVTABLE *table; +/* const char *key; +/* +/* NVTABLE_INFO *nvtable_locate(table, key) +/* NVTABLE *table; +/* const char *key; +/* +/* void nvtable_delete(table, key) +/* NVTABLE *table; +/* const char *key; +/* +/* void nvtable_free(table) +/* NVTABLE *table; +/* +/* void nvtable_walk(table, action, ptr) +/* NVTABLE *table; +/* void (*action)(NVTABLE_INFO *, char *ptr); +/* char *ptr; +/* +/* NVTABLE_INFO **nvtable_list(table) +/* NVTABLE *table; +/* DESCRIPTION +/* This module maintains one or more attribute lists. It provides a +/* more convenient interface than hash tables, although it uses the +/* same underlying implementation. Each attribute list entry consists +/* of a unique string-valued lookup key and a string value. +/* +/* nvtable_create() creates a table of the specified size and returns a +/* pointer to the result. +/* +/* nvtable_update() stores or updates a (key, value) pair in the specified +/* table and returns a pointer to the resulting entry. The key and the +/* value are copied. +/* +/* nvtable_find() returns the value that was stored under the given key, +/* or a null pointer if it was not found. In order to distinguish +/* a null value from a non-existent value, use nvtable_locate(). +/* +/* nvtable_locate() returns a pointer to the entry that was stored +/* for the given key, or a null pointer if it was not found. +/* +/* nvtable_delete() removes one entry that was stored under the given key. +/* +/* nvtable_free() destroys a hash table, including contents. +/* +/* nvtable_walk() invokes the action function for each table entry, with +/* a pointer to the entry as its argument. The ptr argument is passed +/* on to the action function. +/* +/* nvtable_list() returns a null-terminated list of pointers to +/* all elements in the named table. The list should be passed to +/* myfree(). +/* RESTRICTIONS +/* A callback function should not modify the attribute list that is +/* specified to its caller. +/* DIAGNOSTICS +/* The following conditions are reported and cause the program to +/* terminate immediately: memory allocation failure; an attempt +/* to delete a non-existent entry. +/* SEE ALSO +/* mymalloc(3) memory management wrapper +/* htable(3) hash table manager +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* C library */ + +#include + +/* Utility library. */ + +#include +#include +#include + +/* nvtable_update - update or enter (key, value) pair */ + +NVTABLE_INFO *nvtable_update(NVTABLE * table, const char *key, const char *value) +{ + NVTABLE_INFO *ht; + + if ((ht = htable_locate(table, key)) != 0) { + myfree(ht->value); + } else { + ht = htable_enter(table, key, (char *) 0); + } + ht->value = mystrdup(value); + return (ht); +} diff --git a/postfix/src/util/nvtable.h b/postfix/src/util/nvtable.h new file mode 100644 index 000000000..b2bccaf8f --- /dev/null +++ b/postfix/src/util/nvtable.h @@ -0,0 +1,44 @@ +#ifndef _NVTABLE_H_INCLUDED_ +#define _NVTABLE_H_INCLUDED_ + +/*++ +/* NAME +/* nvtable 3h +/* SUMMARY +/* attribute list manager +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include +#include + +typedef struct HTABLE NVTABLE; +typedef struct HTABLE_INFO NVTABLE_INFO; + +#define nvtable_create(size) htable_create(size) +#define nvtable_locate(table, key) htable_locate((table), (key)) +#define nvtable_walk(table, action, ptr) htable_walk((table), (action), (ptr)) +#define nvtable_list(table) htable_list(table) +#define nvtable_find(table, key) htable_find((table), (key)) +#define nvtable_delete(table, key) htable_delete((table), (key), myfree) +#define nvtable_free(table) htable_free((table), myfree) + +extern NVTABLE_INFO *nvtable_update(NVTABLE *, const char *, const char *); + +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +#endif