From: Wietse Venema Date: Mon, 14 Jul 2014 01:22:45 +0000 (+1000) Subject: postfix-2.12-20140713-nonprod X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fheads%2F20140713-nonprod;p=thirdparty%2Fpostfix.git postfix-2.12-20140713-nonprod --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 7e5e9966f..72fb4dbbb 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -15805,7 +15805,7 @@ Apologies for any names omitted. Robustness: skip LDAP queries with non-UTF-8 search strings (in anticipation of UTF8SMTP support). File: global/dict_ldap.c. - Strict UTF-8 validator per RFC 3629. File: util/valid_utf_8.c. + Strict UTF-8 validator per RFC 3629. File: util/valid_utf8_string.c. 20100601 @@ -20123,12 +20123,6 @@ Apologies for any names omitted. Files: global/mail_params.h, mantools/postlink, proto/postconf.proto, smtpd/smtpd.c, smtpd/smtpd_check.c. -20140708 - - Bugfix (introduced 20140701): did not restore jumpbuf - while evaluatingsmtpd_policy_service_default_action. - Viktor Dukhovni. File: smtpd/smtpd_check.c. - 20140709 Cleanup: bitrot in unused function. File: global/defer.c. @@ -20136,3 +20130,89 @@ Apologies for any names omitted. Cleanup: add SYSLIBS minus static libraries while building Postfix shared-library objects. Files: makedefs, util/Makefile.in, global/Makefile.in, dns/Makefile.in, master/Makefile.in/. + +20140708 + + Bugfix (introduced 20140701): did not restore jumpbuf while + evaluatingsmtpd_policy_service_default_action. Viktor + Dukhovni. File: smtpd/smtpd_check.c. + + Feature: VERY PRELIMINARY support for SMTPUTF8 based on an + initial implementation by Arnt Gulbrandsen, funded by CNNIC. + This implements the syntax of SMTP commands and DSN delivery + status notifications. It does not address the problem that + the same domain name may show up in different forms: an + UTF8-encoded name with non-ASCII charaters, or an IDNA-encoded + (xn--mumble) name with ASCII-only characters. This means + that access policies, mydestination, virtual_*_domains and + relay_domans will have to understand both forms in order + to provide complete coverage. For now, SMTPUTF8 support + must not be enabled except for testing. + +20140710 + + Portability: add '-Wl,--enable-new-dtags' to the linker + command line with building with Postfix shared libraries + on Linux. Viktor Dukhovni. file: makedefs. + +20140711 + + Background: What is SMTPUTF8 autodetection? Postfix cannot + rely solely on the sender's declaration that a message + requires SMTPUTF8 support, because UTF8 may be introduced + during local processing (for example, the client hostname + in Postfix's Received: header, adding @$myorigin or .$mydomain + to an incomplete address, address rewriting, alias expansion, + automatic BCC recipients, local forwarding, and modifications + made by header checks or Milter applications). This means + that some form of autodetection is needed that a message + requires SMTPUTF8 support. + + Cleanup: don't try to distinguish between UTF that is already + present in a message or envelope, and UTF8 that is introduced + during local processing (see above). Maintaining this + distinction is too problematic. + + Cleanup: mailing list friendliness. Allow delivery of + SMTPUTF8 mail to non-SMTPUTF8 servers when a message has + no UTF8 headers, no UTF8 envelope sender, and when the + specific delivery request contains no UTF8 envelope recipient. + This is needed for mailing lists that may have a mix of + UTF8 and non-UTF8 subscriber addresses. File: global/smtputf8.h, + smtp/smtp_proto.c. + + Cleanup: moved all SMTPUTF8 detection to the cleanup server, + so that it can apply equally to sendmail command-line + submission, forwarded mail, postmaster notifications, + delivery status notifications, mail received with the qmqpd + server, address verification probes, as well as UTF8 + introduced during local processing (see above). Files: + cleanup/cleanup_out.c, cleanup/cleanup_addr.c. + + Cleanup: store the SMTPUTF8 message (i.e. non-recipient) + flags in the first queue file record, so that the queue + manager can find the information without having to read + every queue file record. Files: cleanup/cleanup_final.c, + *qmgr/qmgr_message.c. + +20140713 + + Interoperability: new parameter smtputf8_autodetect_classes + for selective autodetection that a message requires UTF8SMTP + support. During the initial SMTPUTF8 rollout, this is limited + by default to Postfix sendmail command-line submissions and + address verification probes. Sites that introduce UTF8 + during local processing (see above) will have to enable + SMTPUTF8 autodetection for all mail sources. This feature + shares infrastructure with the older internal_filter_classes + feature. Files: bounce/bounce_notify_service.c, + bounce/bounce_notify_verp.c, bounce/bounce_one_service.c, + bounce/bounce_trace_service.c, bounce/bounce_warn_service.c, + global/int_filt.c, global/mail_proto.h, global/smtputf8.c, + local/forward.c, pickup/pickup.c, qmqpd/qmqpd.c, smtp/smtp_chat.c, + smtpd/smtpd.c, smtpd/smtpd_chat.c, verify/verify.c. + + Feature: preliminary message/global support. This does not + yet parse encoded message/global (such as message/global + sent through an non-8BITMIME system). Such mail cannot yet + be inspected with header_checks. File: global/mime_state.c. diff --git a/postfix/INSTALL b/postfix/INSTALL index f30acde50..c467364d1 100644 --- a/postfix/INSTALL +++ b/postfix/INSTALL @@ -519,6 +519,10 @@ The following is an extensive list of names and values. || |platforms that are known to support this | || |feature. | ||_____________________________|______________________________________________| +|| |Do not build with EAI (SMTPUTF8) support. By | +||-DNO_EAI |default, EAI support is compiled in when the | +|| |"icuuc" library and header files are found. | +||_____________________________|______________________________________________| || |Do not build with IPv6 support. By default, | || |IPv6 support is compiled in on platforms that | ||-DNO_IPV6 |are known to have IPv6 support. Note: this | diff --git a/postfix/README_FILES/INSTALL b/postfix/README_FILES/INSTALL index e4e5f33e9..5a6a4211a 100644 --- a/postfix/README_FILES/INSTALL +++ b/postfix/README_FILES/INSTALL @@ -519,6 +519,10 @@ The following is an extensive list of names and values. || |platforms that are known to support this | || |feature. | |_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | +|| |Do not build with EAI (SMTPUTF8) support. By | +||-DNO_EAI |default, EAI support is compiled in when the | +|| |"icuuc" library and header files are found. | +|_|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ | || |Do not build with IPv6 support. By default, | || |IPv6 support is compiled in on platforms that | ||-DNO_IPV6 |are known to have IPv6 support. Note: this | diff --git a/postfix/TODO b/postfix/TODO new file mode 100644 index 000000000..712622316 --- /dev/null +++ b/postfix/TODO @@ -0,0 +1,48 @@ +Why do we send SMTPUTF_FLAG_RECIPIENT in bounce requests when +bouncing a single recipient? + +Should we encode headers with RFC 2047, when that is the only +reason that Postfix cannot deliver to a non-UTF8SMTP server? + +Items below this line are closed. + +Submit DSNs with SMTPUTF8 auto-detection. This requires parsing +the headers of message/global, message/global-headers, +and message/global-delivery-status. + +Forward local mail with SMTPUTF8 auto-detection, but don't +break mail that would have been delivered prior to SMTPUTF8 +support. + +mailinglist support: if a message requires SMTPUTF8 only because +some recipient addresses are UTF8, then deliveries to other domains +should not require SMTPUTF8. This means that Postfix needs to +maintain multiple flags: + +1) The message has UTF8 header values. This is a queue file property. + +2) The message has an UTF8 sender address. This is also a queue +file property. + +3) A specific delivery request contains UTF8 recipients. This is +a delivery-request property. + +Only in cases 1) or 2) should all deliveries require SMTPUTF8. +Otherwise, only cases 3) require SMTPUTF8, and all other +deliveries can use lagacy SMTP. + +Is an smtputf8 bounce always 8bit? + +What happens when address rewriting or aliasing introduces non-ASCII +domains or addresses? + +printable() stricter UTF8 parsing. + +lowercase() find a way to enable/disable UTF8 + +qmqpd support. + +sendmail: auto-detect or command-line flag? + +bounce: don't scan the entire queue file for smtputf8 info. Just +like encoding, receive smtputf8 info in the "bounce flush" request. diff --git a/postfix/html/INSTALL.html b/postfix/html/INSTALL.html index 06d9c3128..fd477a71f 100644 --- a/postfix/html/INSTALL.html +++ b/postfix/html/INSTALL.html @@ -730,6 +730,10 @@ this feature. EPOLL support. By default, EPOLL support is compiled in on platforms that are known to support this feature. + -DNO_EAI Do not build with EAI +(SMTPUTF8) support. By default, EAI support is compiled in when +the "icuuc" library and header files are found. + -DNO_IPV6 Do not build with IPv6 support. By default, IPv6 support is compiled in on platforms that are known to have IPv6 support. Note: this directive is for debugging diff --git a/postfix/html/bounce.8.html b/postfix/html/bounce.8.html index 8d7d38f08..13264ac98 100644 --- a/postfix/html/bounce.8.html +++ b/postfix/html/bounce.8.html @@ -13,7 +13,7 @@ BOUNCE(8) BOUNCE(8) bounce [generic Postfix daemon options] DESCRIPTION - The bounce(8) daemon maintains per-message log files with delivery sta- + The bounce(8) daemon maintains per-message log files with delivery sta‐ tus information. Each log file is named after the queue file that it corresponds to, and is kept in a queue subdirectory named after the service name in the master.cf file (either bounce, defer or trace). @@ -21,15 +21,15 @@ BOUNCE(8) BOUNCE(8) The bounce(8) daemon processes two types of service requests: - o Append a recipient (non-)delivery status record to a per-message + · Append a recipient (non-)delivery status record to a per-message log file. - o Enqueue a delivery status notification message, with a copy of a + · Enqueue a delivery status notification message, with a copy of a per-message log file and of the corresponding message. When the delivery status notification message is enqueued successfully, the per-message log file is deleted. - The software does a best notification effort. A non-delivery notifica- + The software does a best notification effort. A non-delivery notifica‐ tion is sent even when the log file or the original message cannot be read. @@ -46,6 +46,9 @@ BOUNCE(8) BOUNCE(8) RFC 3464 (Delivery Status Notifications) RFC 3834 (Auto-Submitted: message header) RFC 5322 (Internet Message Format) + RFC 6531 (Internationalized SMTP) + RFC 6532 (Internationalized Message Format) + RFC 6533 (Internationalized Delivery Status Notifications) DIAGNOSTICS Problems and transactions are logged to syslogd(8). @@ -67,8 +70,8 @@ BOUNCE(8) BOUNCE(8) Postfix versions before 2.0. bounce_notice_recipient (postmaster) - The recipient of postmaster notifications with the message head- - ers of mail that Postfix did not deliver and of SMTP conversa- + The recipient of postmaster notifications with the message head‐ + ers of mail that Postfix did not deliver and of SMTP conversa‐ tion transcripts of mail that Postfix did not receive. bounce_size_limit (50000) @@ -79,7 +82,7 @@ BOUNCE(8) BOUNCE(8) Pathname of a configuration file with bounce message templates. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -87,7 +90,7 @@ BOUNCE(8) BOUNCE(8) request before it is terminated by a built-in watchdog timer. delay_notice_recipient (postmaster) - The recipient of postmaster notifications with the message head- + The recipient of postmaster notifications with the message head‐ ers of mail that cannot be delivered within $delay_warning_time time units. @@ -137,9 +140,15 @@ BOUNCE(8) BOUNCE(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". + Available in Postfix 2.12 and later: + + smtputf8_autodetect_classes (sendmail, verify) + Detect that a message requires SMTPUTF8 support for the speci‐ + fied mail origin classes. + FILES /var/spool/postfix/bounce/* non-delivery records /var/spool/postfix/defer/* non-delivery records diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index a3489bd6b..6bb8491b4 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -18,28 +18,28 @@ CLEANUP(8) CLEANUP(8) The cleanup(8) daemon always performs the following transformations: - o Insert missing message headers: (Resent-) From:, To:, Message- + · Insert missing message headers: (Resent-) From:, To:, Message- Id:, and Date:. - o Transform envelope and header addresses to the standard - user@fully-qualified-domain form that is expected by other Post- + · Transform envelope and header addresses to the standard + user@fully-qualified-domain form that is expected by other Post‐ fix programs. This task is delegated to the trivial-rewrite(8) daemon. - o Eliminate duplicate envelope recipient addresses. + · Eliminate duplicate envelope recipient addresses. The following address transformations are optional: - o Optionally, rewrite all envelope and header addresses according + · Optionally, rewrite all envelope and header addresses according to the mappings specified in the canonical(5) lookup tables. - o Optionally, masquerade envelope sender addresses and message + · Optionally, masquerade envelope sender addresses and message header addresses (i.e. strip host or domain information below all domains listed in the masquerade_domains parameter, except for user names listed in masquerade_exceptions). By default, address masquerading does not affect envelope recipients. - o Optionally, expand envelope recipients according to information + · Optionally, expand envelope recipients according to information found in the virtual(5) lookup tables. The cleanup(8) daemon performs sanity checks on the content of each @@ -107,7 +107,7 @@ CLEANUP(8) CLEANUP(8) header_checks (empty) Optional lookup tables for content inspection of primary non- - MIME message headers, as specified in the header_checks(5) man- + MIME message headers, as specified in the header_checks(5) man‐ ual page. Available in Postfix version 2.0 and later: @@ -122,18 +122,18 @@ CLEANUP(8) CLEANUP(8) page. nested_header_checks ($header_checks) - Optional lookup tables for content inspection of non-MIME mes- + Optional lookup tables for content inspection of non-MIME mes‐ sage headers in attached messages, as described in the header_checks(5) manual page. Available in Postfix version 2.3 and later: message_reject_characters (empty) - The set of characters that Postfix will reject in message con- + The set of characters that Postfix will reject in message con‐ tent. message_strip_characters (empty) - The set of characters that Postfix will remove from message con- + The set of characters that Postfix will remove from message con‐ tent. BEFORE QUEUE MILTER CONTROLS @@ -147,7 +147,7 @@ CLEANUP(8) CLEANUP(8) does not arrive via the Postfix smtpd(8) server. milter_protocol (6) - The mail filter protocol version and optional protocol exten- + The mail filter protocol version and optional protocol exten‐ sions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. @@ -156,14 +156,14 @@ CLEANUP(8) CLEANUP(8) unavailable or mis-configured. milter_macro_daemon_name ($myhostname) - The {daemon_name} macro value for Milter (mail filter) applica- + The {daemon_name} macro value for Milter (mail filter) applica‐ tions. milter_macro_v ($mail_name $mail_version) The {v} macro value for Milter (mail filter) applications. milter_connect_timeout (30s) - The time limit for connecting to a Milter (mail filter) applica- + The time limit for connecting to a Milter (mail filter) applica‐ tion, and for negotiating protocol options. milter_command_timeout (30s) @@ -233,7 +233,7 @@ CLEANUP(8) CLEANUP(8) Reject mail with 8-bit text in message headers. strict_8bitmime_body (no) - Reject 8-bit message body text without 8-bit MIME content encod- + Reject 8-bit message body text without 8-bit MIME content encod‐ ing information. strict_mime_encoding_domain (no) @@ -243,7 +243,7 @@ CLEANUP(8) CLEANUP(8) Available in Postfix version 2.5 and later: detect_8bit_encoding_header (yes) - Automatically detect 8BITMIME body content by looking at Con- + Automatically detect 8BITMIME body content by looking at Con‐ tent-Transfer-Encoding: message headers; historically, this behavior was hard-coded to be "always on". @@ -293,8 +293,8 @@ CLEANUP(8) CLEANUP(8) masquerade_exceptions (empty) Optional list of user names that are not subjected to address - masquerading, even when their address matches $masquer- - ade_domains. + masquerading, even when their address matches $masquer‐ + ade_domains. propagate_unmatched_extensions (canonical, virtual) What address lookup tables copy an address extension from the @@ -325,7 +325,7 @@ CLEANUP(8) CLEANUP(8) mapping. sender_canonical_classes (envelope_sender, header_sender) - What addresses are subject to sender_canonical_maps address map- + What addresses are subject to sender_canonical_maps address map‐ ping. remote_header_rewrite_domain (empty) @@ -335,7 +335,7 @@ CLEANUP(8) CLEANUP(8) RESOURCE AND RATE CONTROLS duplicate_filter_limit (1000) - The maximal number of addresses remembered by the address dupli- + The maximal number of addresses remembered by the address dupli‐ cate filter for aliases(5) or virtual(5) alias expansion, or for showq(8) queue displays. @@ -382,7 +382,7 @@ CLEANUP(8) CLEANUP(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -390,7 +390,7 @@ CLEANUP(8) CLEANUP(8) request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal point when log- + The maximal number of digits after the decimal point when log‐ ging sub-second delay values. delay_warning_time (0h) @@ -434,7 +434,7 @@ CLEANUP(8) CLEANUP(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". Available in Postfix version 2.1 and later: diff --git a/postfix/html/defer.8.html b/postfix/html/defer.8.html index 8d7d38f08..13264ac98 100644 --- a/postfix/html/defer.8.html +++ b/postfix/html/defer.8.html @@ -13,7 +13,7 @@ BOUNCE(8) BOUNCE(8) bounce [generic Postfix daemon options] DESCRIPTION - The bounce(8) daemon maintains per-message log files with delivery sta- + The bounce(8) daemon maintains per-message log files with delivery sta‐ tus information. Each log file is named after the queue file that it corresponds to, and is kept in a queue subdirectory named after the service name in the master.cf file (either bounce, defer or trace). @@ -21,15 +21,15 @@ BOUNCE(8) BOUNCE(8) The bounce(8) daemon processes two types of service requests: - o Append a recipient (non-)delivery status record to a per-message + · Append a recipient (non-)delivery status record to a per-message log file. - o Enqueue a delivery status notification message, with a copy of a + · Enqueue a delivery status notification message, with a copy of a per-message log file and of the corresponding message. When the delivery status notification message is enqueued successfully, the per-message log file is deleted. - The software does a best notification effort. A non-delivery notifica- + The software does a best notification effort. A non-delivery notifica‐ tion is sent even when the log file or the original message cannot be read. @@ -46,6 +46,9 @@ BOUNCE(8) BOUNCE(8) RFC 3464 (Delivery Status Notifications) RFC 3834 (Auto-Submitted: message header) RFC 5322 (Internet Message Format) + RFC 6531 (Internationalized SMTP) + RFC 6532 (Internationalized Message Format) + RFC 6533 (Internationalized Delivery Status Notifications) DIAGNOSTICS Problems and transactions are logged to syslogd(8). @@ -67,8 +70,8 @@ BOUNCE(8) BOUNCE(8) Postfix versions before 2.0. bounce_notice_recipient (postmaster) - The recipient of postmaster notifications with the message head- - ers of mail that Postfix did not deliver and of SMTP conversa- + The recipient of postmaster notifications with the message head‐ + ers of mail that Postfix did not deliver and of SMTP conversa‐ tion transcripts of mail that Postfix did not receive. bounce_size_limit (50000) @@ -79,7 +82,7 @@ BOUNCE(8) BOUNCE(8) Pathname of a configuration file with bounce message templates. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -87,7 +90,7 @@ BOUNCE(8) BOUNCE(8) request before it is terminated by a built-in watchdog timer. delay_notice_recipient (postmaster) - The recipient of postmaster notifications with the message head- + The recipient of postmaster notifications with the message head‐ ers of mail that cannot be delivered within $delay_warning_time time units. @@ -137,9 +140,15 @@ BOUNCE(8) BOUNCE(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". + Available in Postfix 2.12 and later: + + smtputf8_autodetect_classes (sendmail, verify) + Detect that a message requires SMTPUTF8 support for the speci‐ + fied mail origin classes. + FILES /var/spool/postfix/bounce/* non-delivery records /var/spool/postfix/defer/* non-delivery records diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index 6a85843d1..b05dc45cd 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -14,7 +14,7 @@ SMTP(8) SMTP(8) DESCRIPTION The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery - protocols. It processes message delivery requests from the queue man- + protocols. It processes message delivery requests from the queue man‐ ager. Each request specifies a queue file, a sender address, a domain or host to deliver to, and recipient information. This program expects to be run from the master(8) process manager. @@ -46,7 +46,7 @@ SMTP(8) SMTP(8) domainname domainname:port - Look up the mail exchangers for the specified domain, and con- + Look up the mail exchangers for the specified domain, and con‐ nect to the specified port (default: smtp). [hostname] @@ -59,7 +59,7 @@ SMTP(8) SMTP(8) [address]:port Connect to the host at the specified address, and connect to the - specified port (default: smtp). An IPv6 address must be format- + specified port (default: smtp). An IPv6 address must be format‐ ted as [ipv6:address]. LMTP DESTINATION SYNTAX @@ -107,13 +107,15 @@ SMTP(8) SMTP(8) RFC 3463 (Enhanced Status Codes) RFC 4954 (AUTH command) RFC 5321 (SMTP protocol) + RFC 6531 (Internationalized SMTP) + RFC 6533 (Internationalized Delivery Status Notifications) DIAGNOSTICS Problems and transactions are logged to syslogd(8). Corrupted message files are marked so that the queue manager can move them to the corrupt queue for further inspection. - Depending on the setting of the notify_classes parameter, the postmas- + Depending on the setting of the notify_classes parameter, the postmas‐ ter is notified of bounces, protocol problems, and of other trouble. BUGS @@ -131,7 +133,7 @@ SMTP(8) SMTP(8) there is no support for TLS, and connections are cached in-process, making it ineffective when the client is used for multiple domains. - Most smtp_xxx configuration parameters have an lmtp_xxx "mirror" param- + Most smtp_xxx configuration parameters have an lmtp_xxx "mirror" param‐ eter for the equivalent LMTP feature. This document describes only those LMTP-related parameters that aren't simply "mirror" parameters. @@ -242,7 +244,7 @@ SMTP(8) SMTP(8) send_cyrus_sasl_authzid (no) When authenticating to a remote SMTP or LMTP server with the default setting "no", send no SASL authoriZation ID (authzid); - send only the SASL authentiCation ID (authcid) plus the auth- + send only the SASL authentiCation ID (authcid) plus the auth‐ cid's password. Available in Postfix version 2.5 and later: @@ -264,7 +266,7 @@ SMTP(8) SMTP(8) Available in Postfix version 2.6 and later: tcp_windowsize (0) - An optional workaround for routers that break TCP window scal- + An optional workaround for routers that break TCP window scal‐ ing. Available in Postfix version 2.8 and later: @@ -278,7 +280,7 @@ SMTP(8) SMTP(8) Change the behavior of the smtp_*_timeout time limits, from a time limit per read or write system call, to a time limit to send or receive a complete record (an SMTP command line, SMTP - response line, SMTP message content line, or TLS protocol mes- + response line, SMTP message content line, or TLS protocol mes‐ sage). smtp_send_dummy_mail_auth (no) @@ -294,7 +296,7 @@ SMTP(8) SMTP(8) smtp_delivery_status_filter ($default_delivery_status_filter) Optional filter for the smtp(8) delivery agent to change the - delivery status code or explanatory text of successful or unsuc- + delivery status code or explanatory text of successful or unsuc‐ cessful deliveries. MIME PROCESSING CONTROLS @@ -321,13 +323,13 @@ SMTP(8) SMTP(8) Enable SASL authentication in the Postfix SMTP client. smtp_sasl_password_maps (empty) - Optional Postfix SMTP client lookup tables with one user- + Optional Postfix SMTP client lookup tables with one user‐ name:password entry per remote hostname or domain, or sender address when sender-dependent authentication is enabled. smtp_sasl_security_options (noplaintext, noanonymous) Postfix SMTP client SASL security options; as of Postfix 2.3 the - list of available features depends on the SASL client implemen- + list of available features depends on the SASL client implemen‐ tation that is selected with smtp_sasl_type. Available in Postfix version 2.2 and later: @@ -341,7 +343,7 @@ SMTP(8) SMTP(8) smtp_sender_dependent_authentication (no) Enable sender-dependent authentication in the Postfix SMTP client; this is available only with SASL authentication, and - disables SMTP connection caching to ensure that mail from dif- + disables SMTP connection caching to ensure that mail from dif‐ ferent senders will use the appropriate credentials. smtp_sasl_path (empty) @@ -356,7 +358,7 @@ SMTP(8) SMTP(8) Available in Postfix version 2.5 and later: smtp_sasl_auth_cache_name (empty) - An optional table to prevent repeated SASL authentication fail- + An optional table to prevent repeated SASL authentication fail‐ ures with the same remote SMTP server hostname, username and password. @@ -395,7 +397,7 @@ SMTP(8) SMTP(8) smtp_tls_CAfile (empty) A file containing CA certificates of root CAs trusted to sign - either remote SMTP server certificates or intermediate CA cer- + either remote SMTP server certificates or intermediate CA cer‐ tificates. smtp_tls_CApath (empty) @@ -416,7 +418,7 @@ SMTP(8) SMTP(8) smtp_tls_mandatory_exclude_ciphers (empty) Additional list of ciphers or cipher types to exclude from the - Postfix SMTP client cipher list at mandatory TLS security lev- + Postfix SMTP client cipher list at mandatory TLS security lev‐ els. smtp_tls_dcert_file (empty) @@ -437,7 +439,7 @@ SMTP(8) SMTP(8) smtp_tls_policy_maps (empty) Optional lookup tables with the Postfix SMTP client TLS security - policy by next-hop destination; when a non-empty value is speci- + policy by next-hop destination; when a non-empty value is speci‐ fied, this overrides the obsolete smtp_tls_per_site parameter. smtp_tls_mandatory_protocols (!SSLv2) @@ -486,8 +488,8 @@ SMTP(8) SMTP(8) Available in Postfix version 2.4 and later: - smtp_sasl_tls_verified_security_options ($smtp_sasl_tls_secu- - rity_options) + smtp_sasl_tls_verified_security_options ($smtp_sasl_tls_secu‐‐ + rity_options) The SASL authentication security options that the Postfix SMTP client uses for TLS encrypted SMTP sessions with a verified server certificate. @@ -496,8 +498,8 @@ SMTP(8) SMTP(8) smtp_tls_fingerprint_cert_match (empty) List of acceptable remote SMTP server certificate fingerprints - for the "fingerprint" TLS security level (smtp_tls_secu- - rity_level = fingerprint). + for the "fingerprint" TLS security level (smtp_tls_secu‐‐ + rity_level = fingerprint). smtp_tls_fingerprint_digest (md5) The message digest algorithm used to construct remote SMTP @@ -514,18 +516,18 @@ SMTP(8) SMTP(8) use with opportunistic TLS encryption. smtp_tls_eccert_file (empty) - File with the Postfix SMTP client ECDSA certificate in PEM for- + File with the Postfix SMTP client ECDSA certificate in PEM for‐ mat. smtp_tls_eckey_file ($smtp_tls_eccert_file) - File with the Postfix SMTP client ECDSA private key in PEM for- + File with the Postfix SMTP client ECDSA private key in PEM for‐ mat. Available in Postfix version 2.7 and later: smtp_tls_block_early_mail_reply (no) Try to detect a mail hijacking attack based on a TLS protocol - vulnerability (CVE-2009-3555), where an attacker prepends mali- + vulnerability (CVE-2009-3555), where an attacker prepends mali‐ cious HELO, MAIL, RCPT, DATA commands to a Postfix SMTP client TLS session. @@ -570,7 +572,7 @@ SMTP(8) SMTP(8) smtp_tls_per_site (empty) Optional lookup tables with the Postfix SMTP client TLS usage - policy by next-hop destination and by remote SMTP server host- + policy by next-hop destination and by remote SMTP server host‐ name. smtp_tls_cipherlist (empty) @@ -578,17 +580,17 @@ SMTP(8) SMTP(8) cipher list. RESOURCE AND RATE CONTROLS - smtp_destination_concurrency_limit ($default_destination_concur- - rency_limit) - The maximal number of parallel deliveries to the same destina- + smtp_destination_concurrency_limit ($default_destination_concur‐‐ + rency_limit) + The maximal number of parallel deliveries to the same destina‐ tion via the smtp message delivery transport. smtp_destination_recipient_limit ($default_destination_recipient_limit) - The maximal number of recipients per message for the smtp mes- + The maximal number of recipients per message for the smtp mes‐ sage delivery transport. smtp_connect_timeout (30s) - The Postfix SMTP client time limit for completing a TCP connec- + The Postfix SMTP client time limit for completing a TCP connec‐ tion, or zero (use the operating system built-in time limit). smtp_helo_timeout (300s) @@ -601,7 +603,7 @@ SMTP(8) SMTP(8) and for receiving the initial remote LMTP server response. smtp_xforward_timeout (300s) - The Postfix SMTP client time limit for sending the XFORWARD com- + The Postfix SMTP client time limit for sending the XFORWARD com‐ mand, and for receiving the remote SMTP server response. smtp_mail_timeout (300s) @@ -661,7 +663,7 @@ SMTP(8) SMTP(8) has a high volume of mail in the active queue. smtp_connection_reuse_time_limit (300s) - The amount of time during which Postfix will use an SMTP connec- + The amount of time during which Postfix will use an SMTP connec‐ tion repeatedly. smtp_connection_cache_time_limit (2s) @@ -671,7 +673,7 @@ SMTP(8) SMTP(8) Available in Postfix version 2.3 and later: connection_cache_protocol_timeout (5s) - Time limit for connection cache connect, send or receive opera- + Time limit for connection cache connect, send or receive opera‐ tions. Available in Postfix version 2.9 and later: @@ -680,7 +682,7 @@ SMTP(8) SMTP(8) Change the behavior of the smtp_*_timeout time limits, from a time limit per read or write system call, to a time limit to send or receive a complete record (an SMTP command line, SMTP - response line, SMTP message content line, or TLS protocol mes- + response line, SMTP message content line, or TLS protocol mes‐ sage). Available in Postfix version 2.11 and later: @@ -690,6 +692,17 @@ SMTP(8) SMTP(8) that an SMTP session may be reused before it is closed, or zero (no limit). +SMTPUTF8 CONTROLS + Preliminary SMTPUTF8 support is introduced with Postfix 2.12. + + smtputf8_enable (no) + Enable experimental SMTPUTF8 support for the protocols described + in RFC 6531..6533. + + smtputf8_autodetect_classes (sendmail, verify) + Enable SMTPUTF8 autodetection for the specified mail origin + classes. + TROUBLE SHOOTING CONTROLS debug_peer_level (2) The increment in verbose logging level when a remote client or @@ -702,7 +715,7 @@ SMTP(8) SMTP(8) error_notice_recipient (postmaster) The recipient of postmaster notifications about mail delivery - problems that are caused by policy, resource, software or proto- + problems that are caused by policy, resource, software or proto‐ col errors. internal_mail_filter_classes (empty) @@ -719,7 +732,7 @@ SMTP(8) SMTP(8) detects a "mail loops back to myself" error condition. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -727,7 +740,7 @@ SMTP(8) SMTP(8) request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal point when log- + The maximal number of digits after the decimal point when log‐ ging sub-second delay values. disable_dns_lookups (no) @@ -747,7 +760,7 @@ SMTP(8) SMTP(8) lmtp_assume_final (no) When a remote LMTP server announces no DSN support, assume that - the server performs final delivery, and send "delivered" deliv- + the server performs final delivery, and send "delivered" deliv‐ ery status notifications instead of "relayed". lmtp_tcp_port (24) @@ -802,7 +815,7 @@ SMTP(8) SMTP(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". Available with Postfix 2.2 and earlier: diff --git a/postfix/html/local.8.html b/postfix/html/local.8.html index 67245eb16..aaa635cef 100644 --- a/postfix/html/local.8.html +++ b/postfix/html/local.8.html @@ -19,7 +19,7 @@ LOCAL(8) LOCAL(8) to, and one or more recipients. This program expects to be run from the master(8) process manager. - The local(8) daemon updates queue files and marks recipients as fin- + The local(8) daemon updates queue files and marks recipients as fin‐ ished, or it informs the queue manager that delivery should be tried again at a later time. Delivery status reports are sent to the bounce(8), defer(8) or trace(8) daemon as appropriate. @@ -41,15 +41,15 @@ LOCAL(8) LOCAL(8) Upon delivery, the local delivery agent tries each pathname in the list until a file is found. - Delivery via ~/.forward files is done with the privileges of the recip- + Delivery via ~/.forward files is done with the privileges of the recip‐ ient. Thus, ~/.forward like files must be readable by the recipient, and their parent directory needs to have "execute" permission for the recipient. - The forward_path parameter is subject to interpolation of $user (recip- + The forward_path parameter is subject to interpolation of $user (recip‐ ient username), $home (recipient home directory), $shell (recipient shell), $recipient (complete recipient address), $extension (recipient - address extension), $domain (recipient domain), $local (entire recipi- + address extension), $domain (recipient domain), $local (entire recipi‐ ent address localpart) and $recipient_delimiter. The forms ${name?value} and ${name:value} expand conditionally to value when $name is (is not) defined. Characters that may have special meaning to @@ -57,14 +57,14 @@ LOCAL(8) LOCAL(8) acceptable characters is specified with the forward_expansion_filter configuration parameter. - An alias or ~/.forward file may list any combination of external com- + An alias or ~/.forward file may list any combination of external com‐ mands, destination file names, :include: directives, or mail addresses. - See aliases(5) for a precise description. Each line in a user's .for- + See aliases(5) for a precise description. Each line in a user's .for‐‐ ward file has the same syntax as the right-hand part of an alias. When an address is found in its own alias expansion, delivery is made to the user instead. When a user is listed in the user's own ~/.forward - file, delivery is made to the user's mailbox instead. An empty ~/.for- + file, delivery is made to the user's mailbox instead. An empty ~/.for‐‐ ward file means do not forward mail. In order to prevent the mail system from using up unreasonable amounts @@ -72,7 +72,7 @@ LOCAL(8) LOCAL(8) are broken up into chunks of length line_length_limit. While expanding aliases, ~/.forward files, and so on, the program - attempts to avoid duplicate deliveries. The duplicate_filter_limit con- + attempts to avoid duplicate deliveries. The duplicate_filter_limit con‐ figuration parameter limits the number of remembered recipients. MAIL FORWARDING @@ -98,16 +98,16 @@ LOCAL(8) LOCAL(8) Mailbox delivery can be delegated to an external command specified with the mailbox_command_maps and mailbox_command configuration parameters. - The command executes with the privileges of the recipient user (excep- + The command executes with the privileges of the recipient user (excep‐ tions: secondary groups are not enabled; in case of delivery as root, the command executes with the privileges of default_privs). Mailbox delivery can be delegated to alternative message transports - specified in the master.cf file. The mailbox_transport_maps and mail- - box_transport configuration parameters specify an optional message + specified in the master.cf file. The mailbox_transport_maps and mail‐‐ + box_transport configuration parameters specify an optional message transport that is to be used for all local recipients, regardless of - whether they are found in the UNIX passwd database. The fall- - back_transport_maps and fallback_transport parameters specify an + whether they are found in the UNIX passwd database. The fall‐‐ + back_transport_maps and fallback_transport parameters specify an optional message transport for recipients that are not found in the aliases(5) or UNIX passwd database. @@ -117,7 +117,7 @@ LOCAL(8) LOCAL(8) to Postfix, prepends an optional Delivered-To: header with the final envelope recipient address, prepends a Return-Path: header with the envelope sender address, prepends a > character to lines beginning with - "From ", and appends an empty line. The mailbox is locked for exclu- + "From ", and appends an empty line. The mailbox is locked for exclu‐ sive access while delivery is in progress. In case of problems, an attempt is made to truncate the mailbox to its original length. @@ -129,23 +129,23 @@ LOCAL(8) LOCAL(8) EXTERNAL COMMAND DELIVERY The allow_mail_to_commands configuration parameter restricts delivery - to external commands. The default setting (alias, forward) forbids com- + to external commands. The default setting (alias, forward) forbids com‐ mand destinations in :include: files. - Optionally, the process working directory is changed to the path speci- + Optionally, the process working directory is changed to the path speci‐ fied with command_execution_directory (Postfix 2.2 and later). Failure to change directory causes mail to be deferred. - The command_execution_directory parameter value is subject to interpo- + The command_execution_directory parameter value is subject to interpo‐ lation of $user (recipient username), $home (recipient home directory), $shell (recipient shell), $recipient (complete recipient address), $extension (recipient address extension), $domain (recipient domain), $local (entire recipient address localpart) and $recipient_delimiter. The forms ${name?value} and ${name:value} expand conditionally to value - when $name is (is not) defined. Characters that may have special mean- + when $name is (is not) defined. Characters that may have special mean‐ ing to the shell or file system are replaced by underscores. The list - of acceptable characters is specified with the execution_direc- - tory_expansion_filter configuration parameter. + of acceptable characters is specified with the execution_direc‐‐ + tory_expansion_filter configuration parameter. The command is executed directly where possible. Assistance by the shell (/bin/sh on UNIX systems) is used only when the command contains @@ -154,7 +154,7 @@ LOCAL(8) LOCAL(8) A limited amount of command output (standard output and standard error) is captured for inclusion with non-delivery status reports. A command - is forcibly terminated if it does not complete within com- + is forcibly terminated if it does not complete within com‐‐ mand_time_limit seconds. Command exit status codes are expected to follow the conventions defined in <sysexits.h>. Exit status 0 means normal successful completion. @@ -164,9 +164,9 @@ LOCAL(8) LOCAL(8) command output begins with an enhanced status code, this status code takes precedence over the non-zero exit status. - A limited amount of message context is exported via environment vari- + A limited amount of message context is exported via environment vari‐ ables. Characters that may have special meaning to the shell are - replaced by underscores. The list of acceptable characters is speci- + replaced by underscores. The list of acceptable characters is speci‐ fied with the command_expansion_filter configuration parameter. SHELL The recipient user's login shell. @@ -195,7 +195,7 @@ LOCAL(8) LOCAL(8) SENDER The entire sender address. - Additional remote client information is made available via the follow- + Additional remote client information is made available via the follow‐ ing environment variables: CLIENT_ADDRESS @@ -241,7 +241,7 @@ LOCAL(8) LOCAL(8) / for qmail-compatible maildir delivery. The allow_mail_to_files configuration parameter restricts delivery to - external files. The default setting (alias, forward) forbids file des- + external files. The default setting (alias, forward) forbids file des‐ tinations in :include: files. In the case of UNIX-style mailbox delivery, the local(8) daemon @@ -266,7 +266,7 @@ LOCAL(8) LOCAL(8) to separate address extensions from local recipient names. For example, with "recipient_delimiter = +", mail for name+foo is - delivered to the alias name+foo or to the alias name, to the destina- + delivered to the alias name+foo or to the alias name, to the destina‐ tions listed in ~name/.forward+foo or in ~name/.forward, to the mailbox owned by the user name, or it is sent back as undeliverable. @@ -287,13 +287,13 @@ LOCAL(8) LOCAL(8) files are marked so that the queue manager can move them to the corrupt queue afterwards. - Depending on the setting of the notify_classes parameter, the postmas- + Depending on the setting of the notify_classes parameter, the postmas‐ ter is notified of bounces and of other trouble. SECURITY The local(8) delivery agent needs a dual personality 1) to access the - private Postfix queue and IPC mechanisms, 2) to impersonate the recipi- - ent and deliver to recipient-specified files or commands. It is there- + private Postfix queue and IPC mechanisms, 2) to impersonate the recipi‐ + ent and deliver to recipient-specified files or commands. It is there‐ fore security sensitive. The local(8) delivery agent disallows regular expression substitution @@ -307,11 +307,11 @@ LOCAL(8) LOCAL(8) BUGS For security reasons, the message delivery status of external commands or of external files is never checkpointed to file. As a result, the - program may occasionally deliver more than once to a command or exter- + program may occasionally deliver more than once to a command or exter‐ nal file. Better safe than sorry. Mutually-recursive aliases or ~/.forward files are not detected early. - The resulting mail forwarding loop is broken by the use of the Deliv- + The resulting mail forwarding loop is broken by the use of the Deliv‐‐ ered-To: message header. CONFIGURATION PARAMETERS @@ -333,8 +333,8 @@ LOCAL(8) LOCAL(8) owner_request_special (yes) Give special treatment to owner-listname and listname-request - address localparts: don't split such addresses when the recipi- - ent_delimiter is set to "-". + address localparts: don't split such addresses when the recipi‐ + ent_delimiter is set to "-". sun_mailtool_compatibility (no) Obsolete SUN mailtool compatibility feature. @@ -350,7 +350,7 @@ LOCAL(8) LOCAL(8) Available in Postfix version 2.5.3 and later: strict_mailbox_ownership (yes) - Defer delivery when a mailbox file is not owned by its recipi- + Defer delivery when a mailbox file is not owned by its recipi‐ ent. reset_owner_alias (no) @@ -368,8 +368,8 @@ LOCAL(8) LOCAL(8) DELIVERY METHOD CONTROLS The precedence of local(8) delivery methods from high to low is: aliases, .forward files, mailbox_transport_maps, mailbox_transport, - mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_direc- - tory, fallback_transport_maps, fallback_transport, and luser_relay. + mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_direc‐ + tory, fallback_transport_maps, fallback_transport, and luser_relay. alias_maps (see 'postconf -d' output) The alias databases that are used for local(8) delivery. @@ -444,16 +444,16 @@ LOCAL(8) LOCAL(8) Time limit for delivery to external commands. duplicate_filter_limit (1000) - The maximal number of addresses remembered by the address dupli- + The maximal number of addresses remembered by the address dupli‐ cate filter for aliases(5) or virtual(5) alias expansion, or for showq(8) queue displays. local_destination_concurrency_limit (2) The maximal number of parallel deliveries via the local mail - delivery transport to the same recipient (when "local_destina- - tion_recipient_limit = 1") or the maximal number of parallel - deliveries to the same local domain (when "local_destina- - tion_recipient_limit > 1"). + delivery transport to the same recipient (when "local_destina‐ + tion_recipient_limit = 1") or the maximal number of parallel + deliveries to the same local domain (when "local_destina‐ + tion_recipient_limit > 1"). local_destination_recipient_limit (1) The maximal number of recipients per message delivery via the @@ -472,8 +472,8 @@ LOCAL(8) LOCAL(8) command_expansion_filter (see 'postconf -d' output) Restrict the characters that the local(8) delivery agent allows - in $name expansions of $mailbox_command and $command_execu- - tion_directory. + in $name expansions of $mailbox_command and $command_execu‐ + tion_directory. default_privs (nobody) The default rights used by the local(8) delivery agent for @@ -492,12 +492,12 @@ LOCAL(8) LOCAL(8) Available in Postfix version 2.5.3 and later: strict_mailbox_ownership (yes) - Defer delivery when a mailbox file is not owned by its recipi- + Defer delivery when a mailbox file is not owned by its recipi‐ ent. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -505,7 +505,7 @@ LOCAL(8) LOCAL(8) request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal point when log- + The maximal number of digits after the decimal point when log‐ ging sub-second delay values. export_environment (see 'postconf -d' output) @@ -517,7 +517,7 @@ LOCAL(8) LOCAL(8) internal communication channel. local_command_shell (empty) - Optional shell program for local(8) delivery to non-Postfix com- + Optional shell program for local(8) delivery to non-Postfix com‐ mand. max_idle (100s) @@ -529,7 +529,7 @@ LOCAL(8) LOCAL(8) process will service before terminating voluntarily. prepend_delivered_header (command, file, forward) - The message delivery contexts where the Postfix local(8) deliv- + The message delivery contexts where the Postfix local(8) deliv‐ ery agent prepends a Delivered-To: message header with the address that the mail was delivered to. @@ -560,7 +560,7 @@ LOCAL(8) LOCAL(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". FILES diff --git a/postfix/html/mailq.1.html b/postfix/html/mailq.1.html index 5a535363d..bd2ea89bd 100644 --- a/postfix/html/mailq.1.html +++ b/postfix/html/mailq.1.html @@ -19,7 +19,7 @@ SENDMAIL(1) SENDMAIL(1) sendmail -I DESCRIPTION - The Postfix sendmail(1) command implements the Postfix to Sendmail com- + The Postfix sendmail(1) command implements the Postfix to Sendmail com‐ patibility interface. For the sake of compatibility with existing applications, some Sendmail command-line options are recognized but silently ignored. @@ -29,7 +29,7 @@ SENDMAIL(1) SENDMAIL(1) arranges for delivery. Postfix sendmail(1) relies on the postdrop(1) command to create a queue file in the maildrop directory. - Specific command aliases are provided for other common modes of opera- + Specific command aliases are provided for other common modes of opera‐ tion: mailq List the mail queue. Each entry shows the queue file ID, message @@ -41,7 +41,7 @@ SENDMAIL(1) SENDMAIL(1) * The message is in the active queue, i.e. the message is selected for delivery. - ! The message is in the hold queue, i.e. no further deliv- + ! The message is in the hold queue, i.e. no further deliv‐ ery attempt will be made until the mail is taken off hold. @@ -51,7 +51,7 @@ SENDMAIL(1) SENDMAIL(1) newaliases Initialize the alias database. If no input file is specified (with the -oA option, see below), the program processes the - file(s) specified with the alias_database configuration parame- + file(s) specified with the alias_database configuration parame‐ ter. If no alias database type is specified, the program uses the type specified with the default_database_type configuration parameter. This mode of operation is implemented by running the @@ -87,7 +87,7 @@ SENDMAIL(1) SENDMAIL(1) -bi Initialize alias database. See the newaliases command above. -bl Go into daemon mode. To accept only local connections as with - Sendmail's -bl option, specify "inet_interfaces = loopback" in + Sendmail´s -bl option, specify "inet_interfaces = loopback" in the Postfix main.cf configuration file. -bm Read mail from standard input and arrange for delivery. This is @@ -118,12 +118,12 @@ SENDMAIL(1) SENDMAIL(1) before 2.3. With all Postfix versions, you can specify a directory pathname - with the MAIL_CONFIG environment variable to override the loca- + with the MAIL_CONFIG environment variable to override the loca‐ tion of configuration files. -F full_name Set the sender full name. This overrides the NAME environment - variable, and is used only with messages that have no From: mes- + variable, and is used only with messages that have no From: mes‐ sage header. -f sender @@ -132,8 +132,8 @@ SENDMAIL(1) SENDMAIL(1) the Errors-To: message header overrides the error return address. - -G Gateway (relay) submission, as opposed to initial user submis- - sion. Either do not rewrite addresses at all, or update incom- + -G Gateway (relay) submission, as opposed to initial user submis‐ + sion. Either do not rewrite addresses at all, or update incom‐ plete addresses with the domain information specified with remote_header_rewrite_domain. @@ -145,7 +145,7 @@ SENDMAIL(1) SENDMAIL(1) -I Initialize alias database. See the newaliases command above. - -i When reading a message from standard input, don't treat a line + -i When reading a message from standard input, don´t treat a line with only a . character as the end of input. -L label (ignored) @@ -179,17 +179,17 @@ SENDMAIL(1) SENDMAIL(1) -o7 (ignored) -o8 (ignored) - To send 8-bit or binary content, use an appropriate MIME encap- + To send 8-bit or binary content, use an appropriate MIME encap‐ sulation and specify the appropriate -B command-line option. - -oi When reading a message from standard input, don't treat a line + -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. expansions. -o x value (ignored) - Set option x to value. Use the equivalent configuration parame- + Set option x to value. Use the equivalent configuration parame‐ ter in main.cf instead. -r sender @@ -209,25 +209,25 @@ SENDMAIL(1) SENDMAIL(1) This option is ignored before Postfix version 2.10. - -q Attempt to deliver all queued mail. This is implemented by exe- + -q Attempt to deliver all queued mail. This is implemented by exe‐ cuting the postqueue(1) command. Warning: flushing undeliverable mail frequently will result in poor delivery performance of all other mail. -qinterval (ignored) - The interval between queue runs. Use the queue_run_delay config- + The interval between queue runs. Use the queue_run_delay config‐ uration parameter instead. -qIqueueid Schedule immediate delivery of mail with the specified queue ID. - This option is implemented by executing the postqueue(1) com- + This option is implemented by executing the postqueue(1) com‐ mand, and is available with Postfix version 2.4 and later. -qRsite Schedule immediate delivery of all mail that is queued for the - named site. This option accepts only site names that are eligi- - ble for the "fast flush" service, and is implemented by execut- + named site. This option accepts only site names that are eligi‐ + ble for the "fast flush" service, and is implemented by execut‐ ing the postqueue(1) command. See flush(8) for more information about the "fast flush" service. @@ -262,12 +262,12 @@ SENDMAIL(1) SENDMAIL(1) -XVxy (Postfix 2.2 and earlier: -Vxy) As -XV, but uses x and y as the VERP delimiter characters, - instead of the characters specified with the default_verp_delim- - iters configuration parameter. + instead of the characters specified with the default_verp_delim‐‐ + iters configuration parameter. - -v Send an email report of the first delivery attempt (Postfix ver- - sions 2.1 and later). Mail delivery always happens in the back- - ground. When multiple -v options are given, enable verbose log- + -v Send an email report of the first delivery attempt (Postfix ver‐ + sions 2.1 and later). Mail delivery always happens in the back‐ + ground. When multiple -v options are given, enable verbose log‐ ging for debugging purposes. -X log_file (ignored) @@ -297,9 +297,9 @@ SENDMAIL(1) SENDMAIL(1) no From: message header. See also the -F option above. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant to this pro- - gram. The text below provides only a parameter summary. See post- - conf(5) for more details including examples. + The following main.cf parameters are especially relevant to this pro‐ + gram. The text below provides only a parameter summary. See post‐‐ + conf(5) for more details including examples. COMPATIBILITY CONTROLS Available with Postfix 2.9 and later: @@ -335,8 +335,8 @@ SENDMAIL(1) SENDMAIL(1) List of users who are authorized to view the queue. authorized_submit_users (static:anyone) - List of users who are authorized to submit mail with the send- - mail(1) command (and with the privileged postdrop(1) helper com- + List of users who are authorized to submit mail with the send‐‐ + mail(1) command (and with the privileged postdrop(1) helper com‐ mand). RESOURCE AND RATE CONTROLS @@ -363,7 +363,7 @@ SENDMAIL(1) SENDMAIL(1) the Postfix "fast flush" service. fast_flush_domains ($relay_domains) - Optional list of destinations that are eligible for per-destina- + Optional list of destinations that are eligible for per-destina‐ tion logfiles with mail that is queued to those destinations. VERP CONTROLS @@ -386,7 +386,7 @@ SENDMAIL(1) SENDMAIL(1) The location of all postfix administrative commands. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_directory (see 'postconf -d' output) @@ -400,13 +400,6 @@ SENDMAIL(1) SENDMAIL(1) The time after which the sender receives a copy of the message headers of mail that is still queued. - enable_errors_to (no) - Report mail delivery errors to the address specified with the - non-standard Errors-To: message header, instead of the envelope - sender address (this feature is removed with Postfix version - 2.2, is turned off by default with Postfix version 2.1, and is - always turned on with older Postfix versions). - mail_owner (postfix) The UNIX system account that owns the Postfix queue and most Postfix daemon processes. @@ -424,7 +417,7 @@ SENDMAIL(1) SENDMAIL(1) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". FILES diff --git a/postfix/html/newaliases.1.html b/postfix/html/newaliases.1.html index 5a535363d..bd2ea89bd 100644 --- a/postfix/html/newaliases.1.html +++ b/postfix/html/newaliases.1.html @@ -19,7 +19,7 @@ SENDMAIL(1) SENDMAIL(1) sendmail -I DESCRIPTION - The Postfix sendmail(1) command implements the Postfix to Sendmail com- + The Postfix sendmail(1) command implements the Postfix to Sendmail com‐ patibility interface. For the sake of compatibility with existing applications, some Sendmail command-line options are recognized but silently ignored. @@ -29,7 +29,7 @@ SENDMAIL(1) SENDMAIL(1) arranges for delivery. Postfix sendmail(1) relies on the postdrop(1) command to create a queue file in the maildrop directory. - Specific command aliases are provided for other common modes of opera- + Specific command aliases are provided for other common modes of opera‐ tion: mailq List the mail queue. Each entry shows the queue file ID, message @@ -41,7 +41,7 @@ SENDMAIL(1) SENDMAIL(1) * The message is in the active queue, i.e. the message is selected for delivery. - ! The message is in the hold queue, i.e. no further deliv- + ! The message is in the hold queue, i.e. no further deliv‐ ery attempt will be made until the mail is taken off hold. @@ -51,7 +51,7 @@ SENDMAIL(1) SENDMAIL(1) newaliases Initialize the alias database. If no input file is specified (with the -oA option, see below), the program processes the - file(s) specified with the alias_database configuration parame- + file(s) specified with the alias_database configuration parame‐ ter. If no alias database type is specified, the program uses the type specified with the default_database_type configuration parameter. This mode of operation is implemented by running the @@ -87,7 +87,7 @@ SENDMAIL(1) SENDMAIL(1) -bi Initialize alias database. See the newaliases command above. -bl Go into daemon mode. To accept only local connections as with - Sendmail's -bl option, specify "inet_interfaces = loopback" in + Sendmail´s -bl option, specify "inet_interfaces = loopback" in the Postfix main.cf configuration file. -bm Read mail from standard input and arrange for delivery. This is @@ -118,12 +118,12 @@ SENDMAIL(1) SENDMAIL(1) before 2.3. With all Postfix versions, you can specify a directory pathname - with the MAIL_CONFIG environment variable to override the loca- + with the MAIL_CONFIG environment variable to override the loca‐ tion of configuration files. -F full_name Set the sender full name. This overrides the NAME environment - variable, and is used only with messages that have no From: mes- + variable, and is used only with messages that have no From: mes‐ sage header. -f sender @@ -132,8 +132,8 @@ SENDMAIL(1) SENDMAIL(1) the Errors-To: message header overrides the error return address. - -G Gateway (relay) submission, as opposed to initial user submis- - sion. Either do not rewrite addresses at all, or update incom- + -G Gateway (relay) submission, as opposed to initial user submis‐ + sion. Either do not rewrite addresses at all, or update incom‐ plete addresses with the domain information specified with remote_header_rewrite_domain. @@ -145,7 +145,7 @@ SENDMAIL(1) SENDMAIL(1) -I Initialize alias database. See the newaliases command above. - -i When reading a message from standard input, don't treat a line + -i When reading a message from standard input, don´t treat a line with only a . character as the end of input. -L label (ignored) @@ -179,17 +179,17 @@ SENDMAIL(1) SENDMAIL(1) -o7 (ignored) -o8 (ignored) - To send 8-bit or binary content, use an appropriate MIME encap- + To send 8-bit or binary content, use an appropriate MIME encap‐ sulation and specify the appropriate -B command-line option. - -oi When reading a message from standard input, don't treat a line + -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. expansions. -o x value (ignored) - Set option x to value. Use the equivalent configuration parame- + Set option x to value. Use the equivalent configuration parame‐ ter in main.cf instead. -r sender @@ -209,25 +209,25 @@ SENDMAIL(1) SENDMAIL(1) This option is ignored before Postfix version 2.10. - -q Attempt to deliver all queued mail. This is implemented by exe- + -q Attempt to deliver all queued mail. This is implemented by exe‐ cuting the postqueue(1) command. Warning: flushing undeliverable mail frequently will result in poor delivery performance of all other mail. -qinterval (ignored) - The interval between queue runs. Use the queue_run_delay config- + The interval between queue runs. Use the queue_run_delay config‐ uration parameter instead. -qIqueueid Schedule immediate delivery of mail with the specified queue ID. - This option is implemented by executing the postqueue(1) com- + This option is implemented by executing the postqueue(1) com‐ mand, and is available with Postfix version 2.4 and later. -qRsite Schedule immediate delivery of all mail that is queued for the - named site. This option accepts only site names that are eligi- - ble for the "fast flush" service, and is implemented by execut- + named site. This option accepts only site names that are eligi‐ + ble for the "fast flush" service, and is implemented by execut‐ ing the postqueue(1) command. See flush(8) for more information about the "fast flush" service. @@ -262,12 +262,12 @@ SENDMAIL(1) SENDMAIL(1) -XVxy (Postfix 2.2 and earlier: -Vxy) As -XV, but uses x and y as the VERP delimiter characters, - instead of the characters specified with the default_verp_delim- - iters configuration parameter. + instead of the characters specified with the default_verp_delim‐‐ + iters configuration parameter. - -v Send an email report of the first delivery attempt (Postfix ver- - sions 2.1 and later). Mail delivery always happens in the back- - ground. When multiple -v options are given, enable verbose log- + -v Send an email report of the first delivery attempt (Postfix ver‐ + sions 2.1 and later). Mail delivery always happens in the back‐ + ground. When multiple -v options are given, enable verbose log‐ ging for debugging purposes. -X log_file (ignored) @@ -297,9 +297,9 @@ SENDMAIL(1) SENDMAIL(1) no From: message header. See also the -F option above. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant to this pro- - gram. The text below provides only a parameter summary. See post- - conf(5) for more details including examples. + The following main.cf parameters are especially relevant to this pro‐ + gram. The text below provides only a parameter summary. See post‐‐ + conf(5) for more details including examples. COMPATIBILITY CONTROLS Available with Postfix 2.9 and later: @@ -335,8 +335,8 @@ SENDMAIL(1) SENDMAIL(1) List of users who are authorized to view the queue. authorized_submit_users (static:anyone) - List of users who are authorized to submit mail with the send- - mail(1) command (and with the privileged postdrop(1) helper com- + List of users who are authorized to submit mail with the send‐‐ + mail(1) command (and with the privileged postdrop(1) helper com‐ mand). RESOURCE AND RATE CONTROLS @@ -363,7 +363,7 @@ SENDMAIL(1) SENDMAIL(1) the Postfix "fast flush" service. fast_flush_domains ($relay_domains) - Optional list of destinations that are eligible for per-destina- + Optional list of destinations that are eligible for per-destina‐ tion logfiles with mail that is queued to those destinations. VERP CONTROLS @@ -386,7 +386,7 @@ SENDMAIL(1) SENDMAIL(1) The location of all postfix administrative commands. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_directory (see 'postconf -d' output) @@ -400,13 +400,6 @@ SENDMAIL(1) SENDMAIL(1) The time after which the sender receives a copy of the message headers of mail that is still queued. - enable_errors_to (no) - Report mail delivery errors to the address specified with the - non-standard Errors-To: message header, instead of the envelope - sender address (this feature is removed with Postfix version - 2.2, is turned off by default with Postfix version 2.1, and is - always turned on with older Postfix versions). - mail_owner (postfix) The UNIX system account that owns the Postfix queue and most Postfix daemon processes. @@ -424,7 +417,7 @@ SENDMAIL(1) SENDMAIL(1) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". FILES diff --git a/postfix/html/pickup.8.html b/postfix/html/pickup.8.html index 343fcc3b9..46c492e97 100644 --- a/postfix/html/pickup.8.html +++ b/postfix/html/pickup.8.html @@ -52,12 +52,12 @@ PICKUP(8) PICKUP(8) specified transport:destination. receive_override_options (empty) - Enable or disable recipient validation, built-in content filter- + Enable or disable recipient validation, built-in content filter‐ ing, or address mapping. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. ipc_timeout (3600s) @@ -90,7 +90,7 @@ PICKUP(8) PICKUP(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". SEE ALSO diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html index 48a9075ef..9751ca319 100644 --- a/postfix/html/postconf.5.html +++ b/postfix/html/postconf.5.html @@ -16372,6 +16372,78 @@ key. This is intended behavior.

Postfix 2.3 and later use smtpd_tls_security_level instead.

+ + +
smtputf8_autodetect_classes +(default: sendmail, verify)
+ +

Detect that a message requires SMTPUTF8 support for the specified +mail origin classes. This is a workaround to avoid chicken-and-egg +problems during the initial SMTPUTF8 roll-out in environments with +pre-existing mail flows that contain UTF8. Those mail flows should +not break because Postfix suddenly refuses to deliver such mail +to down-stream MTAs that don't announce SMTPUTF8 support.

+ +

The problem is that Postfix cannot rely solely on the sender's +declaration that a message requires SMTPUTF8 support, because UTF8 +may be introduced during local processing (for example, the client +hostname in Postfix's Received: header, adding @$myorigin or +.$mydomain to an incomplete address, address rewriting, alias +expansion, automatic BCC recipients, local forwarding, and changes +made by header checks or Milter applications).

+ +

For now, the default is to enable "SMTPUTF8 required" autodetection +only for Postfix sendmail command-line submissions and address +verification probes. This may change once SMTPUTF8 support achieves +world domination. However, sites that add UTF8 content via local +processing (see above) should autodetect the need for SMTPUTF8 +support for all email.

+ +

Specify one or more of the following:

+ +
+ +
sendmail
Submission with the Postfix +sendmail(1) command.
+ +
smtpd
Mail received with the smtpd(8) +daemon.
+ +
qmqpd
Mail received with the qmqpd(8) +daemon.
+ +
forward
Local forwarding or aliasing. +
+ +
bounce
Submission by the bounce(8) daemon. +
+ +
notify
Postmaster notification from the +smtp(8) or smtpd(8) daemon.
+ +
verify
Address verification probe from the +verify(8) daemon.
+ +
all
Enable SMTPUTF8 autodetection for all +mail.
+ +
+ +

This feature is available in Postfix 2.12 and later.

+ + +
+ +
smtputf8_enable +(default: no)
+ +

Enable experimental SMTPUTF8 support for the protocols described +in RFC 6531..6533. This requires that Postfix is built to support +these protocols.

+ +

This feature is available in Postfix 2.12 and later.

+ +
soft_bounce @@ -16544,6 +16616,18 @@ FROM and RCPT TO addresses.

+ + +
strict_smtputf8 +(default: no)
+ +

Enable stricter enforcement of the SMTPUTF8 protocol. The Postfix +SMTP server accepts UTF8 sender or recipient addresses only when +the client requests an SMTPUTF8 mail transaction.

+ +

This feature is available in Postfix 2.12 and later.

+ +
sun_mailtool_compatibility diff --git a/postfix/html/postdrop.1.html b/postfix/html/postdrop.1.html index 489cf22e9..6a142c74d 100644 --- a/postfix/html/postdrop.1.html +++ b/postfix/html/postdrop.1.html @@ -48,15 +48,15 @@ POSTDROP(1) POSTDROP(1) of set-group ID privileges, a non-standard directory is allowed only if: - o The name is listed in the standard main.cf file with the + · The name is listed in the standard main.cf file with the alternate_config_directories configuration parameter. - o The command is invoked by the super-user. + · The command is invoked by the super-user. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant to this pro- - gram. The text below provides only a parameter summary. See post- - conf(5) for more details including examples. + The following main.cf parameters are especially relevant to this pro‐ + gram. The text below provides only a parameter summary. See post‐‐ + conf(5) for more details including examples. alternate_config_directories (empty) A list of non-default Postfix configuration directories that may @@ -64,7 +64,7 @@ POSTDROP(1) POSTDROP(1) via the MAIL_CONFIG environment parameter. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. import_environment (see 'postconf -d' output) @@ -79,7 +79,7 @@ POSTDROP(1) POSTDROP(1) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". trigger_timeout (10s) @@ -89,8 +89,8 @@ POSTDROP(1) POSTDROP(1) Available in Postfix version 2.2 and later: authorized_submit_users (static:anyone) - List of users who are authorized to submit mail with the send- - mail(1) command (and with the privileged postdrop(1) helper com- + List of users who are authorized to submit mail with the send‐‐ + mail(1) command (and with the privileged postdrop(1) helper com‐ mand). FILES diff --git a/postfix/html/qmqpd.8.html b/postfix/html/qmqpd.8.html index 48b870d09..49167e99f 100644 --- a/postfix/html/qmqpd.8.html +++ b/postfix/html/qmqpd.8.html @@ -13,12 +13,12 @@ QMQPD(8) QMQPD(8) qmqpd [generic Postfix daemon options] DESCRIPTION - The Postfix QMQP server receives one message per connection. Each mes- + The Postfix QMQP server receives one message per connection. Each mes‐ sage is piped through the cleanup(8) daemon, and is placed into the incoming queue as one single queue file. The program expects to be run from the master(8) process manager. - The QMQP server implements one access policy: only explicitly autho- + The QMQP server implements one access policy: only explicitly autho‐ rized client hosts are allowed to use the service. SECURITY @@ -34,7 +34,7 @@ QMQPD(8) QMQPD(8) It is therefore not possible to reject individual recipients. The QMQP protocol requires the server to receive the entire message - before replying. If a message is malformed, or if any netstring compo- + before replying. If a message is malformed, or if any netstring compo‐ nent is longer than acceptable, Postfix replies immediately and closes the connection. It is left up to the client to handle the situation. @@ -52,12 +52,19 @@ QMQPD(8) QMQPD(8) specified transport:destination. receive_override_options (empty) - Enable or disable recipient validation, built-in content filter- + Enable or disable recipient validation, built-in content filter‐ ing, or address mapping. +SMTPUTF8 CONTROLS + Preliminary SMTPUTF8 support is introduced with Postfix 2.12. + + smtputf8_autodetect_classes (sendmail, verify) + Detect that a message requires SMTPUTF8 support for the speci‐ + fied mail origin classes. + RESOURCE AND RATE CONTROLS line_length_limit (2048) - Upon input, long lines are chopped up into pieces of at most + Upon input, long lines are chopped up into pieces of at most this length; upon delivery, long lines are reconstructed. hopcount_limit (50) @@ -65,47 +72,47 @@ QMQPD(8) QMQPD(8) in the primary message headers. message_size_limit (10240000) - The maximal size in bytes of a message, including envelope + The maximal size in bytes of a message, including envelope information. qmqpd_timeout (300s) - The time limit for sending or receiving information over the + The time limit for sending or receiving information over the network. TROUBLE SHOOTING CONTROLS debug_peer_level (2) - The increment in verbose logging level when a remote client or + The increment in verbose logging level when a remote client or server matches a pattern in the debug_peer_list parameter. debug_peer_list (empty) - Optional list of remote client or server hostname or network + Optional list of remote client or server hostname or network address patterns that cause the verbose logging level to increase by the amount specified in $debug_peer_level. soft_bounce (no) - Safety net to keep mail queued that would otherwise be returned + Safety net to keep mail queued that would otherwise be returned to the sender. TARPIT CONTROLS qmqpd_error_delay (1s) - How long the Postfix QMQP server will pause before sending a + How long the Postfix QMQP server will pause before sending a negative reply to the remote QMQP client. MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to handle a + How much time a Postfix daemon process may take to handle a request before it is terminated by a built-in watchdog timer. ipc_timeout (3600s) - The time limit for sending or receiving information over an + The time limit for sending or receiving information over an internal communication channel. max_idle (100s) - The maximum amount of time that an idle Postfix daemon process + The maximum amount of time that an idle Postfix daemon process waits for an incoming connection before terminating voluntarily. max_use (100) @@ -119,7 +126,7 @@ QMQPD(8) QMQPD(8) The process name of a Postfix command or daemon process. qmqpd_authorized_clients (empty) - What remote QMQP clients are allowed to connect to the Postfix + What remote QMQP clients are allowed to connect to the Postfix QMQP server port. queue_directory (see 'postconf -d' output) @@ -129,12 +136,12 @@ QMQPD(8) QMQPD(8) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + The mail system name that is prepended to the process name in + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". verp_delimiter_filter (-=+) - The characters Postfix accepts as VERP delimiter characters on + The characters Postfix accepts as VERP delimiter characters on the Postfix sendmail(1) command line and in SMTP commands. Available in Postfix version 2.5 and later: diff --git a/postfix/html/sendmail.1.html b/postfix/html/sendmail.1.html index 5a535363d..bd2ea89bd 100644 --- a/postfix/html/sendmail.1.html +++ b/postfix/html/sendmail.1.html @@ -19,7 +19,7 @@ SENDMAIL(1) SENDMAIL(1) sendmail -I DESCRIPTION - The Postfix sendmail(1) command implements the Postfix to Sendmail com- + The Postfix sendmail(1) command implements the Postfix to Sendmail com‐ patibility interface. For the sake of compatibility with existing applications, some Sendmail command-line options are recognized but silently ignored. @@ -29,7 +29,7 @@ SENDMAIL(1) SENDMAIL(1) arranges for delivery. Postfix sendmail(1) relies on the postdrop(1) command to create a queue file in the maildrop directory. - Specific command aliases are provided for other common modes of opera- + Specific command aliases are provided for other common modes of opera‐ tion: mailq List the mail queue. Each entry shows the queue file ID, message @@ -41,7 +41,7 @@ SENDMAIL(1) SENDMAIL(1) * The message is in the active queue, i.e. the message is selected for delivery. - ! The message is in the hold queue, i.e. no further deliv- + ! The message is in the hold queue, i.e. no further deliv‐ ery attempt will be made until the mail is taken off hold. @@ -51,7 +51,7 @@ SENDMAIL(1) SENDMAIL(1) newaliases Initialize the alias database. If no input file is specified (with the -oA option, see below), the program processes the - file(s) specified with the alias_database configuration parame- + file(s) specified with the alias_database configuration parame‐ ter. If no alias database type is specified, the program uses the type specified with the default_database_type configuration parameter. This mode of operation is implemented by running the @@ -87,7 +87,7 @@ SENDMAIL(1) SENDMAIL(1) -bi Initialize alias database. See the newaliases command above. -bl Go into daemon mode. To accept only local connections as with - Sendmail's -bl option, specify "inet_interfaces = loopback" in + Sendmail´s -bl option, specify "inet_interfaces = loopback" in the Postfix main.cf configuration file. -bm Read mail from standard input and arrange for delivery. This is @@ -118,12 +118,12 @@ SENDMAIL(1) SENDMAIL(1) before 2.3. With all Postfix versions, you can specify a directory pathname - with the MAIL_CONFIG environment variable to override the loca- + with the MAIL_CONFIG environment variable to override the loca‐ tion of configuration files. -F full_name Set the sender full name. This overrides the NAME environment - variable, and is used only with messages that have no From: mes- + variable, and is used only with messages that have no From: mes‐ sage header. -f sender @@ -132,8 +132,8 @@ SENDMAIL(1) SENDMAIL(1) the Errors-To: message header overrides the error return address. - -G Gateway (relay) submission, as opposed to initial user submis- - sion. Either do not rewrite addresses at all, or update incom- + -G Gateway (relay) submission, as opposed to initial user submis‐ + sion. Either do not rewrite addresses at all, or update incom‐ plete addresses with the domain information specified with remote_header_rewrite_domain. @@ -145,7 +145,7 @@ SENDMAIL(1) SENDMAIL(1) -I Initialize alias database. See the newaliases command above. - -i When reading a message from standard input, don't treat a line + -i When reading a message from standard input, don´t treat a line with only a . character as the end of input. -L label (ignored) @@ -179,17 +179,17 @@ SENDMAIL(1) SENDMAIL(1) -o7 (ignored) -o8 (ignored) - To send 8-bit or binary content, use an appropriate MIME encap- + To send 8-bit or binary content, use an appropriate MIME encap‐ sulation and specify the appropriate -B command-line option. - -oi When reading a message from standard input, don't treat a line + -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. expansions. -o x value (ignored) - Set option x to value. Use the equivalent configuration parame- + Set option x to value. Use the equivalent configuration parame‐ ter in main.cf instead. -r sender @@ -209,25 +209,25 @@ SENDMAIL(1) SENDMAIL(1) This option is ignored before Postfix version 2.10. - -q Attempt to deliver all queued mail. This is implemented by exe- + -q Attempt to deliver all queued mail. This is implemented by exe‐ cuting the postqueue(1) command. Warning: flushing undeliverable mail frequently will result in poor delivery performance of all other mail. -qinterval (ignored) - The interval between queue runs. Use the queue_run_delay config- + The interval between queue runs. Use the queue_run_delay config‐ uration parameter instead. -qIqueueid Schedule immediate delivery of mail with the specified queue ID. - This option is implemented by executing the postqueue(1) com- + This option is implemented by executing the postqueue(1) com‐ mand, and is available with Postfix version 2.4 and later. -qRsite Schedule immediate delivery of all mail that is queued for the - named site. This option accepts only site names that are eligi- - ble for the "fast flush" service, and is implemented by execut- + named site. This option accepts only site names that are eligi‐ + ble for the "fast flush" service, and is implemented by execut‐ ing the postqueue(1) command. See flush(8) for more information about the "fast flush" service. @@ -262,12 +262,12 @@ SENDMAIL(1) SENDMAIL(1) -XVxy (Postfix 2.2 and earlier: -Vxy) As -XV, but uses x and y as the VERP delimiter characters, - instead of the characters specified with the default_verp_delim- - iters configuration parameter. + instead of the characters specified with the default_verp_delim‐‐ + iters configuration parameter. - -v Send an email report of the first delivery attempt (Postfix ver- - sions 2.1 and later). Mail delivery always happens in the back- - ground. When multiple -v options are given, enable verbose log- + -v Send an email report of the first delivery attempt (Postfix ver‐ + sions 2.1 and later). Mail delivery always happens in the back‐ + ground. When multiple -v options are given, enable verbose log‐ ging for debugging purposes. -X log_file (ignored) @@ -297,9 +297,9 @@ SENDMAIL(1) SENDMAIL(1) no From: message header. See also the -F option above. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant to this pro- - gram. The text below provides only a parameter summary. See post- - conf(5) for more details including examples. + The following main.cf parameters are especially relevant to this pro‐ + gram. The text below provides only a parameter summary. See post‐‐ + conf(5) for more details including examples. COMPATIBILITY CONTROLS Available with Postfix 2.9 and later: @@ -335,8 +335,8 @@ SENDMAIL(1) SENDMAIL(1) List of users who are authorized to view the queue. authorized_submit_users (static:anyone) - List of users who are authorized to submit mail with the send- - mail(1) command (and with the privileged postdrop(1) helper com- + List of users who are authorized to submit mail with the send‐‐ + mail(1) command (and with the privileged postdrop(1) helper com‐ mand). RESOURCE AND RATE CONTROLS @@ -363,7 +363,7 @@ SENDMAIL(1) SENDMAIL(1) the Postfix "fast flush" service. fast_flush_domains ($relay_domains) - Optional list of destinations that are eligible for per-destina- + Optional list of destinations that are eligible for per-destina‐ tion logfiles with mail that is queued to those destinations. VERP CONTROLS @@ -386,7 +386,7 @@ SENDMAIL(1) SENDMAIL(1) The location of all postfix administrative commands. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_directory (see 'postconf -d' output) @@ -400,13 +400,6 @@ SENDMAIL(1) SENDMAIL(1) The time after which the sender receives a copy of the message headers of mail that is still queued. - enable_errors_to (no) - Report mail delivery errors to the address specified with the - non-standard Errors-To: message header, instead of the envelope - sender address (this feature is removed with Postfix version - 2.2, is turned off by default with Postfix version 2.1, and is - always turned on with older Postfix versions). - mail_owner (postfix) The UNIX system account that owns the Postfix queue and most Postfix daemon processes. @@ -424,7 +417,7 @@ SENDMAIL(1) SENDMAIL(1) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". FILES diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index 6a85843d1..b05dc45cd 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -14,7 +14,7 @@ SMTP(8) SMTP(8) DESCRIPTION The Postfix SMTP+LMTP client implements the SMTP and LMTP mail delivery - protocols. It processes message delivery requests from the queue man- + protocols. It processes message delivery requests from the queue man‐ ager. Each request specifies a queue file, a sender address, a domain or host to deliver to, and recipient information. This program expects to be run from the master(8) process manager. @@ -46,7 +46,7 @@ SMTP(8) SMTP(8) domainname domainname:port - Look up the mail exchangers for the specified domain, and con- + Look up the mail exchangers for the specified domain, and con‐ nect to the specified port (default: smtp). [hostname] @@ -59,7 +59,7 @@ SMTP(8) SMTP(8) [address]:port Connect to the host at the specified address, and connect to the - specified port (default: smtp). An IPv6 address must be format- + specified port (default: smtp). An IPv6 address must be format‐ ted as [ipv6:address]. LMTP DESTINATION SYNTAX @@ -107,13 +107,15 @@ SMTP(8) SMTP(8) RFC 3463 (Enhanced Status Codes) RFC 4954 (AUTH command) RFC 5321 (SMTP protocol) + RFC 6531 (Internationalized SMTP) + RFC 6533 (Internationalized Delivery Status Notifications) DIAGNOSTICS Problems and transactions are logged to syslogd(8). Corrupted message files are marked so that the queue manager can move them to the corrupt queue for further inspection. - Depending on the setting of the notify_classes parameter, the postmas- + Depending on the setting of the notify_classes parameter, the postmas‐ ter is notified of bounces, protocol problems, and of other trouble. BUGS @@ -131,7 +133,7 @@ SMTP(8) SMTP(8) there is no support for TLS, and connections are cached in-process, making it ineffective when the client is used for multiple domains. - Most smtp_xxx configuration parameters have an lmtp_xxx "mirror" param- + Most smtp_xxx configuration parameters have an lmtp_xxx "mirror" param‐ eter for the equivalent LMTP feature. This document describes only those LMTP-related parameters that aren't simply "mirror" parameters. @@ -242,7 +244,7 @@ SMTP(8) SMTP(8) send_cyrus_sasl_authzid (no) When authenticating to a remote SMTP or LMTP server with the default setting "no", send no SASL authoriZation ID (authzid); - send only the SASL authentiCation ID (authcid) plus the auth- + send only the SASL authentiCation ID (authcid) plus the auth‐ cid's password. Available in Postfix version 2.5 and later: @@ -264,7 +266,7 @@ SMTP(8) SMTP(8) Available in Postfix version 2.6 and later: tcp_windowsize (0) - An optional workaround for routers that break TCP window scal- + An optional workaround for routers that break TCP window scal‐ ing. Available in Postfix version 2.8 and later: @@ -278,7 +280,7 @@ SMTP(8) SMTP(8) Change the behavior of the smtp_*_timeout time limits, from a time limit per read or write system call, to a time limit to send or receive a complete record (an SMTP command line, SMTP - response line, SMTP message content line, or TLS protocol mes- + response line, SMTP message content line, or TLS protocol mes‐ sage). smtp_send_dummy_mail_auth (no) @@ -294,7 +296,7 @@ SMTP(8) SMTP(8) smtp_delivery_status_filter ($default_delivery_status_filter) Optional filter for the smtp(8) delivery agent to change the - delivery status code or explanatory text of successful or unsuc- + delivery status code or explanatory text of successful or unsuc‐ cessful deliveries. MIME PROCESSING CONTROLS @@ -321,13 +323,13 @@ SMTP(8) SMTP(8) Enable SASL authentication in the Postfix SMTP client. smtp_sasl_password_maps (empty) - Optional Postfix SMTP client lookup tables with one user- + Optional Postfix SMTP client lookup tables with one user‐ name:password entry per remote hostname or domain, or sender address when sender-dependent authentication is enabled. smtp_sasl_security_options (noplaintext, noanonymous) Postfix SMTP client SASL security options; as of Postfix 2.3 the - list of available features depends on the SASL client implemen- + list of available features depends on the SASL client implemen‐ tation that is selected with smtp_sasl_type. Available in Postfix version 2.2 and later: @@ -341,7 +343,7 @@ SMTP(8) SMTP(8) smtp_sender_dependent_authentication (no) Enable sender-dependent authentication in the Postfix SMTP client; this is available only with SASL authentication, and - disables SMTP connection caching to ensure that mail from dif- + disables SMTP connection caching to ensure that mail from dif‐ ferent senders will use the appropriate credentials. smtp_sasl_path (empty) @@ -356,7 +358,7 @@ SMTP(8) SMTP(8) Available in Postfix version 2.5 and later: smtp_sasl_auth_cache_name (empty) - An optional table to prevent repeated SASL authentication fail- + An optional table to prevent repeated SASL authentication fail‐ ures with the same remote SMTP server hostname, username and password. @@ -395,7 +397,7 @@ SMTP(8) SMTP(8) smtp_tls_CAfile (empty) A file containing CA certificates of root CAs trusted to sign - either remote SMTP server certificates or intermediate CA cer- + either remote SMTP server certificates or intermediate CA cer‐ tificates. smtp_tls_CApath (empty) @@ -416,7 +418,7 @@ SMTP(8) SMTP(8) smtp_tls_mandatory_exclude_ciphers (empty) Additional list of ciphers or cipher types to exclude from the - Postfix SMTP client cipher list at mandatory TLS security lev- + Postfix SMTP client cipher list at mandatory TLS security lev‐ els. smtp_tls_dcert_file (empty) @@ -437,7 +439,7 @@ SMTP(8) SMTP(8) smtp_tls_policy_maps (empty) Optional lookup tables with the Postfix SMTP client TLS security - policy by next-hop destination; when a non-empty value is speci- + policy by next-hop destination; when a non-empty value is speci‐ fied, this overrides the obsolete smtp_tls_per_site parameter. smtp_tls_mandatory_protocols (!SSLv2) @@ -486,8 +488,8 @@ SMTP(8) SMTP(8) Available in Postfix version 2.4 and later: - smtp_sasl_tls_verified_security_options ($smtp_sasl_tls_secu- - rity_options) + smtp_sasl_tls_verified_security_options ($smtp_sasl_tls_secu‐‐ + rity_options) The SASL authentication security options that the Postfix SMTP client uses for TLS encrypted SMTP sessions with a verified server certificate. @@ -496,8 +498,8 @@ SMTP(8) SMTP(8) smtp_tls_fingerprint_cert_match (empty) List of acceptable remote SMTP server certificate fingerprints - for the "fingerprint" TLS security level (smtp_tls_secu- - rity_level = fingerprint). + for the "fingerprint" TLS security level (smtp_tls_secu‐‐ + rity_level = fingerprint). smtp_tls_fingerprint_digest (md5) The message digest algorithm used to construct remote SMTP @@ -514,18 +516,18 @@ SMTP(8) SMTP(8) use with opportunistic TLS encryption. smtp_tls_eccert_file (empty) - File with the Postfix SMTP client ECDSA certificate in PEM for- + File with the Postfix SMTP client ECDSA certificate in PEM for‐ mat. smtp_tls_eckey_file ($smtp_tls_eccert_file) - File with the Postfix SMTP client ECDSA private key in PEM for- + File with the Postfix SMTP client ECDSA private key in PEM for‐ mat. Available in Postfix version 2.7 and later: smtp_tls_block_early_mail_reply (no) Try to detect a mail hijacking attack based on a TLS protocol - vulnerability (CVE-2009-3555), where an attacker prepends mali- + vulnerability (CVE-2009-3555), where an attacker prepends mali‐ cious HELO, MAIL, RCPT, DATA commands to a Postfix SMTP client TLS session. @@ -570,7 +572,7 @@ SMTP(8) SMTP(8) smtp_tls_per_site (empty) Optional lookup tables with the Postfix SMTP client TLS usage - policy by next-hop destination and by remote SMTP server host- + policy by next-hop destination and by remote SMTP server host‐ name. smtp_tls_cipherlist (empty) @@ -578,17 +580,17 @@ SMTP(8) SMTP(8) cipher list. RESOURCE AND RATE CONTROLS - smtp_destination_concurrency_limit ($default_destination_concur- - rency_limit) - The maximal number of parallel deliveries to the same destina- + smtp_destination_concurrency_limit ($default_destination_concur‐‐ + rency_limit) + The maximal number of parallel deliveries to the same destina‐ tion via the smtp message delivery transport. smtp_destination_recipient_limit ($default_destination_recipient_limit) - The maximal number of recipients per message for the smtp mes- + The maximal number of recipients per message for the smtp mes‐ sage delivery transport. smtp_connect_timeout (30s) - The Postfix SMTP client time limit for completing a TCP connec- + The Postfix SMTP client time limit for completing a TCP connec‐ tion, or zero (use the operating system built-in time limit). smtp_helo_timeout (300s) @@ -601,7 +603,7 @@ SMTP(8) SMTP(8) and for receiving the initial remote LMTP server response. smtp_xforward_timeout (300s) - The Postfix SMTP client time limit for sending the XFORWARD com- + The Postfix SMTP client time limit for sending the XFORWARD com‐ mand, and for receiving the remote SMTP server response. smtp_mail_timeout (300s) @@ -661,7 +663,7 @@ SMTP(8) SMTP(8) has a high volume of mail in the active queue. smtp_connection_reuse_time_limit (300s) - The amount of time during which Postfix will use an SMTP connec- + The amount of time during which Postfix will use an SMTP connec‐ tion repeatedly. smtp_connection_cache_time_limit (2s) @@ -671,7 +673,7 @@ SMTP(8) SMTP(8) Available in Postfix version 2.3 and later: connection_cache_protocol_timeout (5s) - Time limit for connection cache connect, send or receive opera- + Time limit for connection cache connect, send or receive opera‐ tions. Available in Postfix version 2.9 and later: @@ -680,7 +682,7 @@ SMTP(8) SMTP(8) Change the behavior of the smtp_*_timeout time limits, from a time limit per read or write system call, to a time limit to send or receive a complete record (an SMTP command line, SMTP - response line, SMTP message content line, or TLS protocol mes- + response line, SMTP message content line, or TLS protocol mes‐ sage). Available in Postfix version 2.11 and later: @@ -690,6 +692,17 @@ SMTP(8) SMTP(8) that an SMTP session may be reused before it is closed, or zero (no limit). +SMTPUTF8 CONTROLS + Preliminary SMTPUTF8 support is introduced with Postfix 2.12. + + smtputf8_enable (no) + Enable experimental SMTPUTF8 support for the protocols described + in RFC 6531..6533. + + smtputf8_autodetect_classes (sendmail, verify) + Enable SMTPUTF8 autodetection for the specified mail origin + classes. + TROUBLE SHOOTING CONTROLS debug_peer_level (2) The increment in verbose logging level when a remote client or @@ -702,7 +715,7 @@ SMTP(8) SMTP(8) error_notice_recipient (postmaster) The recipient of postmaster notifications about mail delivery - problems that are caused by policy, resource, software or proto- + problems that are caused by policy, resource, software or proto‐ col errors. internal_mail_filter_classes (empty) @@ -719,7 +732,7 @@ SMTP(8) SMTP(8) detects a "mail loops back to myself" error condition. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -727,7 +740,7 @@ SMTP(8) SMTP(8) request before it is terminated by a built-in watchdog timer. delay_logging_resolution_limit (2) - The maximal number of digits after the decimal point when log- + The maximal number of digits after the decimal point when log‐ ging sub-second delay values. disable_dns_lookups (no) @@ -747,7 +760,7 @@ SMTP(8) SMTP(8) lmtp_assume_final (no) When a remote LMTP server announces no DSN support, assume that - the server performs final delivery, and send "delivered" deliv- + the server performs final delivery, and send "delivered" deliv‐ ery status notifications instead of "relayed". lmtp_tcp_port (24) @@ -802,7 +815,7 @@ SMTP(8) SMTP(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". Available with Postfix 2.2 and earlier: diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index 0810ca7a2..4842b0153 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -18,7 +18,7 @@ SMTPD(8) SMTPD(8) The SMTP server accepts network connection requests and performs zero or more SMTP transactions per connection. Each received message is piped through the cleanup(8) daemon, and is placed into the incoming - queue as one single queue file. For this mode of operation, the pro- + queue as one single queue file. For this mode of operation, the pro‐ gram expects to be run from the master(8) process manager. Alternatively, the SMTP server be can run in stand-alone mode; this is @@ -31,7 +31,7 @@ SMTPD(8) SMTPD(8) The SMTP server implements a variety of policies for connection requests, and for parameters given to HELO, ETRN, MAIL FROM, VRFY and - RCPT TO commands. They are detailed below and in the main.cf configura- + RCPT TO commands. They are detailed below and in the main.cf configura‐ tion file. SECURITY @@ -57,11 +57,13 @@ SMTPD(8) SMTPD(8) RFC 4409 (Message submission) RFC 4954 (AUTH command) RFC 5321 (SMTP protocol) + RFC 6531 (Internationalized SMTP) + RFC 6533 (Internationalized Delivery Status Notifications) DIAGNOSTICS Problems and transactions are logged to syslogd(8). - Depending on the setting of the notify_classes parameter, the postmas- + Depending on the setting of the notify_classes parameter, the postmas‐ ter is notified of bounces, protocol problems, policy violations, and of other trouble. @@ -127,13 +129,13 @@ SMTPD(8) SMTPD(8) smtpd_tls_always_issue_session_ids (yes) Force the Postfix SMTP server to issue a TLS session id, even - when TLS session caching is turned off (smtpd_tls_ses- - sion_cache_database is empty). + when TLS session caching is turned off (smtpd_tls_ses‐ + sion_cache_database is empty). Available in Postfix version 2.6 and later: tcp_windowsize (0) - An optional workaround for routers that break TCP window scal- + An optional workaround for routers that break TCP window scal‐ ing. Available in Postfix version 2.7 and later: @@ -144,8 +146,8 @@ SMTPD(8) SMTPD(8) Available in Postfix version 2.9 and later: smtpd_per_record_deadline (normal: no, overload: yes) - Change the behavior of the smtpd_timeout and smtpd_start- - tls_timeout time limits, from a time limit per read or write + Change the behavior of the smtpd_timeout and smtpd_start‐ + tls_timeout time limits, from a time limit per read or write system call, to a time limit to send or receive a complete record (an SMTP command line, SMTP response line, SMTP message content line, or TLS protocol message). @@ -155,7 +157,7 @@ SMTPD(8) SMTPD(8) Postfix address rewriting. receive_override_options (empty) - Enable or disable recipient validation, built-in content filter- + Enable or disable recipient validation, built-in content filter‐ ing, or address mapping. Available in Postfix version 2.2 and later: @@ -165,8 +167,8 @@ SMTPD(8) SMTPD(8) update incomplete addresses with the domain name in $myorigin or $mydomain; either don't rewrite message headers from other clients at all, or rewrite message headers and update incomplete - addresses with the domain specified in the remote_header_re- - write_domain parameter. + addresses with the domain specified in the remote_header_re‐ + write_domain parameter. BEFORE-SMTPD PROXY AGENT Available in Postfix version 2.10 and later: @@ -182,7 +184,7 @@ SMTPD(8) SMTPD(8) AFTER QUEUE EXTERNAL CONTENT INSPECTION CONTROLS As of version 1.0, Postfix can be configured to send new mail to an external content filter AFTER the mail is queued. This content filter - is expected to inject mail back into a (Postfix or other) MTA for fur- + is expected to inject mail back into a (Postfix or other) MTA for fur‐ ther delivery. See the FILTER_README document for details. content_filter (empty) @@ -192,19 +194,19 @@ SMTPD(8) SMTPD(8) BEFORE QUEUE EXTERNAL CONTENT INSPECTION CONTROLS As of version 2.1, the Postfix SMTP server can be configured to send incoming mail to a real-time SMTP-based content filter BEFORE mail is - queued. This content filter is expected to inject mail back into Post- - fix. See the SMTPD_PROXY_README document for details on how to config- + queued. This content filter is expected to inject mail back into Post‐ + fix. See the SMTPD_PROXY_README document for details on how to config‐ ure and operate this feature. smtpd_proxy_filter (empty) The hostname and TCP port of the mail filtering proxy server. smtpd_proxy_ehlo ($myhostname) - How the Postfix SMTP server announces itself to the proxy fil- + How the Postfix SMTP server announces itself to the proxy fil‐ ter. smtpd_proxy_options (empty) - List of options that control how the Postfix SMTP server commu- + List of options that control how the Postfix SMTP server commu‐ nicates with a before-queue content filter. smtpd_proxy_timeout (100s) @@ -215,15 +217,15 @@ SMTPD(8) SMTPD(8) As of version 2.3, Postfix supports the Sendmail version 8 Milter (mail filter) protocol. These content filters run outside Postfix. They can inspect the SMTP command stream and the message content, and can - request modifications before mail is queued. For details see the MIL- - TER_README document. + request modifications before mail is queued. For details see the MIL‐ + TER_README document. smtpd_milters (empty) A list of Milter (mail filter) applications for new mail that arrives via the Postfix smtpd(8) server. milter_protocol (6) - The mail filter protocol version and optional protocol exten- + The mail filter protocol version and optional protocol exten‐ sions for communication with a Milter application; prior to Postfix 2.6 the default protocol is 2. @@ -232,14 +234,14 @@ SMTPD(8) SMTPD(8) unavailable or mis-configured. milter_macro_daemon_name ($myhostname) - The {daemon_name} macro value for Milter (mail filter) applica- + The {daemon_name} macro value for Milter (mail filter) applica‐ tions. milter_macro_v ($mail_name $mail_version) The {v} macro value for Milter (mail filter) applications. milter_connect_timeout (30s) - The time limit for connecting to a Milter (mail filter) applica- + The time limit for connecting to a Milter (mail filter) applica‐ tion, and for negotiating protocol options. milter_command_timeout (30s) @@ -289,7 +291,7 @@ SMTPD(8) SMTPD(8) Available in Postfix version 2.1 and later: receive_override_options (empty) - Enable or disable recipient validation, built-in content filter- + Enable or disable recipient validation, built-in content filter‐ ing, or address mapping. EXTERNAL CONTENT INSPECTION CONTROLS @@ -299,7 +301,7 @@ SMTPD(8) SMTPD(8) Available in Postfix version 2.1 and later: smtpd_authorized_xforward_hosts (empty) - What remote SMTP clients are allowed to use the XFORWARD fea- + What remote SMTP clients are allowed to use the XFORWARD fea‐ ture. SASL AUTHENTICATION CONTROLS @@ -321,7 +323,7 @@ SMTPD(8) SMTPD(8) smtpd_sasl_security_options (noanonymous) Postfix SMTP server SASL security options; as of Postfix 2.3 the - list of available features depends on the SASL server implemen- + list of available features depends on the SASL server implemen‐ tation that is selected with smtpd_sasl_type. smtpd_sender_login_maps (empty) @@ -358,7 +360,7 @@ SMTPD(8) SMTPD(8) Available in Postfix version 2.5 and later: cyrus_sasl_config_path (empty) - Search path for Cyrus SASL application configuration files, cur- + Search path for Cyrus SASL application configuration files, cur‐ rently used only to locate the $smtpd_sasl_path.conf file. Available in Postfix version 2.11 and later: @@ -373,7 +375,7 @@ SMTPD(8) SMTPD(8) smtpd_tls_security_level (empty) The SMTP TLS security level for the Postfix SMTP server; when a - non-empty value is specified, this overrides the obsolete param- + non-empty value is specified, this overrides the obsolete param‐ eters smtpd_use_tls and smtpd_enforce_tls. smtpd_sasl_tls_security_options ($smtpd_sasl_security_options) @@ -386,25 +388,25 @@ SMTPD(8) SMTPD(8) smtpd_tls_CAfile (empty) A file containing (PEM format) CA certificates of root CAs - trusted to sign either remote SMTP client certificates or inter- + trusted to sign either remote SMTP client certificates or inter‐ mediate CA certificates. smtpd_tls_CApath (empty) A directory containing (PEM format) CA certificates of root CAs - trusted to sign either remote SMTP client certificates or inter- + trusted to sign either remote SMTP client certificates or inter‐ mediate CA certificates. smtpd_tls_always_issue_session_ids (yes) Force the Postfix SMTP server to issue a TLS session id, even - when TLS session caching is turned off (smtpd_tls_ses- - sion_cache_database is empty). + when TLS session caching is turned off (smtpd_tls_ses‐ + sion_cache_database is empty). smtpd_tls_ask_ccert (no) Ask a remote SMTP client for a client certificate. smtpd_tls_auth_only (no) When TLS encryption is optional in the Postfix SMTP server, do - not announce or accept SASL authentication over unencrypted con- + not announce or accept SASL authentication over unencrypted con‐ nections. smtpd_tls_ccert_verifydepth (9) @@ -443,7 +445,7 @@ SMTPD(8) SMTPD(8) smtpd_tls_mandatory_exclude_ciphers (empty) Additional list of ciphers or cipher types to exclude from the - Postfix SMTP server cipher list at mandatory TLS security lev- + Postfix SMTP server cipher list at mandatory TLS security lev‐ els. smtpd_tls_mandatory_protocols (!SSLv2) @@ -503,11 +505,11 @@ SMTPD(8) SMTPD(8) use with opportunistic TLS encryption. smtpd_tls_eccert_file (empty) - File with the Postfix SMTP server ECDSA certificate in PEM for- + File with the Postfix SMTP server ECDSA certificate in PEM for‐ mat. smtpd_tls_eckey_file ($smtpd_tls_eccert_file) - File with the Postfix SMTP server ECDSA private key in PEM for- + File with the Postfix SMTP server ECDSA private key in PEM for‐ mat. smtpd_tls_eecdh_grade (see 'postconf -d' output) @@ -525,7 +527,7 @@ SMTPD(8) SMTPD(8) Available in Postfix version 2.8 and later: tls_preempt_cipherlist (no) - With SSLv3 and later, use the Postfix SMTP server's cipher pref- + With SSLv3 and later, use the Postfix SMTP server's cipher pref‐ erence order instead of the remote client's cipher preference order. @@ -559,10 +561,24 @@ SMTPD(8) SMTPD(8) Obsolete Postfix < 2.3 control for the Postfix SMTP server TLS cipher list. +SMTPUTF8 CONTROLS + Preliminary SMTPUTF8 support is introduced with Postfix 2.12. + + smtputf8_enable (no) + Enable experimental SMTPUTF8 support for the protocols described + in RFC 6531..6533. + + strict_smtputf8 (no) + Enable stricter enforcement of the SMTPUTF8 protocol. + + smtputf8_autodetect_classes (sendmail, verify) + Detect that a message requires SMTPUTF8 support for the speci‐ + fied mail origin classes. + VERP SUPPORT CONTROLS - With VERP style delivery, each recipient of a message receives a cus- + With VERP style delivery, each recipient of a message receives a cus‐ tomized copy of the message with his/her own recipient address encoded - in the envelope sender address. The VERP_README file describes config- + in the envelope sender address. The VERP_README file describes config‐ uration and operation details of Postfix support for variable envelope return path addresses. VERP style delivery is requested with the SMTP XVERP command or with the "sendmail -V" command-line option and is @@ -578,13 +594,13 @@ SMTPD(8) SMTPD(8) Available in Postfix version 1.1 and 2.0: authorized_verp_clients ($mynetworks) - What remote SMTP clients are allowed to specify the XVERP com- + What remote SMTP clients are allowed to specify the XVERP com‐ mand. Available in Postfix version 2.1 and later: smtpd_authorized_verp_clients ($authorized_verp_clients) - What remote SMTP clients are allowed to specify the XVERP com- + What remote SMTP clients are allowed to specify the XVERP com‐ mand. TROUBLE SHOOTING CONTROLS @@ -604,7 +620,7 @@ SMTPD(8) SMTPD(8) error_notice_recipient (postmaster) The recipient of postmaster notifications about mail delivery - problems that are caused by policy, resource, software or proto- + problems that are caused by policy, resource, software or proto‐ col errors. internal_mail_filter_classes (empty) @@ -637,7 +653,7 @@ SMTPD(8) SMTPD(8) KNOWN VERSUS UNKNOWN RECIPIENT CONTROLS As of Postfix version 2.0, the SMTP server rejects mail for unknown - recipients. This prevents the mail queue from clogging up with undeliv- + recipients. This prevents the mail queue from clogging up with undeliv‐ erable MAILER-DAEMON messages. Additional information on this topic is in the LOCAL_RECIPIENT_README and ADDRESS_CLASS_README documents. @@ -673,8 +689,8 @@ SMTPD(8) SMTPD(8) local_recipient_maps (proxy:unix:passwd.byname $alias_maps) Lookup tables with all names or addresses of local recipients: a - recipient address is local when its domain matches $mydestina- - tion, $inet_interfaces or $proxy_interfaces. + recipient address is local when its domain matches $mydestina‐ + tion, $inet_interfaces or $proxy_interfaces. unknown_local_recipient_reject_code (550) The numerical Postfix SMTP server response code when a recipient @@ -693,7 +709,7 @@ SMTPD(8) SMTPD(8) unknown_relay_recipient_reject_code (550) The numerical Postfix SMTP server reply code when a recipient - address matches $relay_domains, and relay_recipient_maps speci- + address matches $relay_domains, and relay_recipient_maps speci‐ fies a list of lookup tables that does not match the recipient address. @@ -711,7 +727,7 @@ SMTPD(8) SMTPD(8) unknown_virtual_alias_reject_code (550) The Postfix SMTP server reply code when a recipient address - matches $virtual_alias_domains, and $virtual_alias_maps speci- + matches $virtual_alias_domains, and $virtual_alias_maps speci‐ fies a list of lookup tables that does not match the recipient address. @@ -730,7 +746,7 @@ SMTPD(8) SMTPD(8) unknown_virtual_mailbox_reject_code (550) The Postfix SMTP server reply code when a recipient address matches $virtual_mailbox_domains, and $virtual_mailbox_maps - specifies a list of lookup tables that does not match the recip- + specifies a list of lookup tables that does not match the recip‐ ient address. RESOURCE AND RATE CONTROLS @@ -742,7 +758,7 @@ SMTPD(8) SMTPD(8) this length; upon delivery, long lines are reconstructed. queue_minfree (0) - The minimal amount of free space in bytes in the queue file sys- + The minimal amount of free space in bytes in the queue file sys‐ tem that is needed to receive mail. message_size_limit (10240000) @@ -768,7 +784,7 @@ SMTPD(8) SMTPD(8) Attempt to look up the remote SMTP client hostname, and verify that the name matches the client IP address. - The per SMTP client connection count and request rate limits are imple- + The per SMTP client connection count and request rate limits are imple‐ mented in co-operation with the anvil(8) service, and are available in Postfix version 2.2 and later. @@ -804,8 +820,8 @@ SMTPD(8) SMTPD(8) Available in Postfix version 2.9 and later: smtpd_per_record_deadline (normal: no, overload: yes) - Change the behavior of the smtpd_timeout and smtpd_start- - tls_timeout time limits, from a time limit per read or write + Change the behavior of the smtpd_timeout and smtpd_start‐ + tls_timeout time limits, from a time limit per read or write system call, to a time limit to send or receive a complete record (an SMTP command line, SMTP response line, SMTP message content line, or TLS protocol message). @@ -869,7 +885,7 @@ SMTPD(8) SMTPD(8) The default action when an SMTPD policy service request fails. smtpd_policy_service_request_limit (0) - The maximal number of requests per SMTPD policy service connec- + The maximal number of requests per SMTPD policy service connec‐ tion, or zero (no limit). smtpd_policy_service_try_limit (2) @@ -877,7 +893,7 @@ SMTPD(8) SMTPD(8) request before giving up. smtpd_policy_service_retry_delay (1s) - The delay between attempts to resend a failed SMTPD policy ser- + The delay between attempts to resend a failed SMTPD policy ser‐ vice request. ACCESS CONTROLS @@ -892,7 +908,7 @@ SMTPD(8) SMTPD(8) $smtpd_helo_restrictions. parent_domain_matches_subdomains (see 'postconf -d' output) - What Postfix features match subdomains of "domain.tld" automati- + What Postfix features match subdomains of "domain.tld" automati‐ cally, instead of requiring an explicit ".domain.tld" pattern. smtpd_client_restrictions (empty) @@ -923,7 +939,7 @@ SMTPD(8) SMTPD(8) allow_untrusted_routing (no) Forward mail with sender-specified routing - (user[@%!]remote[@%!]site) from untrusted clients to destina- + (user[@%!]remote[@%!]site) from untrusted clients to destina‐ tions matching $relay_domains. smtpd_restriction_classes (empty) @@ -974,12 +990,12 @@ SMTPD(8) SMTPD(8) smtpd_recipient_restrictions. SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS - Postfix version 2.1 introduces sender and recipient address verifica- + Postfix version 2.1 introduces sender and recipient address verifica‐ tion. This feature is implemented by sending probe email messages that are not actually delivered. This feature is requested via the reject_unverified_sender and reject_unverified_recipient access restrictions. The status of verification probes is maintained by the - verify(8) server. See the file ADDRESS_VERIFICATION_README for infor- + verify(8) server. See the file ADDRESS_VERIFICATION_README for infor‐ mation about how to configure and operate the Postfix sender/recipient address verification service. @@ -988,7 +1004,7 @@ SMTPD(8) SMTPD(8) of an address verification request in progress. address_verify_poll_delay (3s) - The delay between queries for the completion of an address veri- + The delay between queries for the completion of an address veri‐ fication request in progress. address_verify_sender ($double_bounce_sender) @@ -1001,7 +1017,7 @@ SMTPD(8) SMTPD(8) unverified_recipient_reject_code (450) The numerical Postfix SMTP server response when a recipient - address is rejected by the reject_unverified_recipient restric- + address is rejected by the reject_unverified_recipient restric‐ tion. Available in Postfix version 2.6 and later: @@ -1027,8 +1043,8 @@ SMTPD(8) SMTPD(8) fails due to a temporary error condition. unverified_recipient_tempfail_action ($reject_tempfail_action) - The Postfix SMTP server's action when reject_unverified_recipi- - ent fails due to a temporary error condition. + The Postfix SMTP server's action when reject_unverified_recipi‐ + ent fails due to a temporary error condition. Available with Postfix 2.9 and later: @@ -1089,7 +1105,7 @@ SMTPD(8) SMTPD(8) reject_unknown_client_hostname restriction. unknown_hostname_reject_code (450) - The numerical Postfix SMTP server response code when the host- + The numerical Postfix SMTP server response code when the host‐ name specified with the HELO or EHLO command is rejected by the reject_unknown_helo_hostname restriction. @@ -1101,8 +1117,8 @@ SMTPD(8) SMTPD(8) multi_recipient_bounce_reject_code (550) The numerical Postfix SMTP server response code when a remote - SMTP client request is blocked by the reject_multi_recipi- - ent_bounce restriction. + SMTP client request is blocked by the reject_multi_recipi‐ + ent_bounce restriction. rbl_reply_maps (empty) Optional lookup tables with RBL response templates. @@ -1119,8 +1135,8 @@ SMTPD(8) SMTPD(8) fails due to a temporary error condition. unknown_helo_hostname_tempfail_action ($reject_tempfail_action) - The Postfix SMTP server's action when reject_unknown_helo_host- - name fails due to an temporary error condition. + The Postfix SMTP server's action when reject_unknown_helo_host‐ + name fails due to an temporary error condition. unknown_address_tempfail_action ($reject_tempfail_action) The Postfix SMTP server's action when @@ -1129,7 +1145,7 @@ SMTPD(8) SMTPD(8) MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -1140,7 +1156,7 @@ SMTPD(8) SMTPD(8) The location of all postfix administrative commands. double_bounce_sender (double-bounce) - The sender address of postmaster notifications that are gener- + The sender address of postmaster notifications that are gener‐ ated by the mail system. ipc_timeout (3600s) @@ -1167,7 +1183,7 @@ SMTPD(8) SMTPD(8) The internet hostname of this mail system. mynetworks (see 'postconf -d' output) - The list of "trusted" remote SMTP clients that have more privi- + The list of "trusted" remote SMTP clients that have more privi‐ leges than "strangers". myorigin ($myhostname) @@ -1197,13 +1213,13 @@ SMTPD(8) SMTPD(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". Available in Postfix version 2.2 and later: smtpd_forbidden_commands (CONNECT, GET, POST) - List of commands that cause the Postfix SMTP server to immedi- + List of commands that cause the Postfix SMTP server to immedi‐ ately terminate the session with a 221 code. Available in Postfix version 2.5 and later: diff --git a/postfix/html/trace.8.html b/postfix/html/trace.8.html index 8d7d38f08..13264ac98 100644 --- a/postfix/html/trace.8.html +++ b/postfix/html/trace.8.html @@ -13,7 +13,7 @@ BOUNCE(8) BOUNCE(8) bounce [generic Postfix daemon options] DESCRIPTION - The bounce(8) daemon maintains per-message log files with delivery sta- + The bounce(8) daemon maintains per-message log files with delivery sta‐ tus information. Each log file is named after the queue file that it corresponds to, and is kept in a queue subdirectory named after the service name in the master.cf file (either bounce, defer or trace). @@ -21,15 +21,15 @@ BOUNCE(8) BOUNCE(8) The bounce(8) daemon processes two types of service requests: - o Append a recipient (non-)delivery status record to a per-message + · Append a recipient (non-)delivery status record to a per-message log file. - o Enqueue a delivery status notification message, with a copy of a + · Enqueue a delivery status notification message, with a copy of a per-message log file and of the corresponding message. When the delivery status notification message is enqueued successfully, the per-message log file is deleted. - The software does a best notification effort. A non-delivery notifica- + The software does a best notification effort. A non-delivery notifica‐ tion is sent even when the log file or the original message cannot be read. @@ -46,6 +46,9 @@ BOUNCE(8) BOUNCE(8) RFC 3464 (Delivery Status Notifications) RFC 3834 (Auto-Submitted: message header) RFC 5322 (Internet Message Format) + RFC 6531 (Internationalized SMTP) + RFC 6532 (Internationalized Message Format) + RFC 6533 (Internationalized Delivery Status Notifications) DIAGNOSTICS Problems and transactions are logged to syslogd(8). @@ -67,8 +70,8 @@ BOUNCE(8) BOUNCE(8) Postfix versions before 2.0. bounce_notice_recipient (postmaster) - The recipient of postmaster notifications with the message head- - ers of mail that Postfix did not deliver and of SMTP conversa- + The recipient of postmaster notifications with the message head‐ + ers of mail that Postfix did not deliver and of SMTP conversa‐ tion transcripts of mail that Postfix did not receive. bounce_size_limit (50000) @@ -79,7 +82,7 @@ BOUNCE(8) BOUNCE(8) Pathname of a configuration file with bounce message templates. config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) @@ -87,7 +90,7 @@ BOUNCE(8) BOUNCE(8) request before it is terminated by a built-in watchdog timer. delay_notice_recipient (postmaster) - The recipient of postmaster notifications with the message head- + The recipient of postmaster notifications with the message head‐ ers of mail that cannot be delivered within $delay_warning_time time units. @@ -137,9 +140,15 @@ BOUNCE(8) BOUNCE(8) syslog_name (see 'postconf -d' output) The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". + Available in Postfix 2.12 and later: + + smtputf8_autodetect_classes (sendmail, verify) + Detect that a message requires SMTPUTF8 support for the speci‐ + fied mail origin classes. + FILES /var/spool/postfix/bounce/* non-delivery records /var/spool/postfix/defer/* non-delivery records diff --git a/postfix/html/verify.8.html b/postfix/html/verify.8.html index 82da5940d..7e3ce33a0 100644 --- a/postfix/html/verify.8.html +++ b/postfix/html/verify.8.html @@ -72,8 +72,8 @@ VERIFY(8) VERIFY(8) principle. CONFIGURATION PARAMETERS - Changes to main.cf are not picked up automatically, as verify(8) pro- - cesses are long-lived. Use the command "postfix reload" after a config- + Changes to main.cf are not picked up automatically, as verify(8) pro‐ + cesses are long-lived. Use the command "postfix reload" after a config‐ uration change. The text below provides only a parameter summary. See postconf(5) for @@ -116,7 +116,7 @@ VERIFY(8) VERIFY(8) Available with Postfix 2.7 and later: address_verify_cache_cleanup_interval (12h) - The amount of time between verify(8) address verification data- + The amount of time between verify(8) address verification data‐ base cleanup runs. PROBE MESSAGE ROUTING CONTROLS @@ -125,15 +125,15 @@ VERIFY(8) VERIFY(8) message routing mechanisms. address_verify_relayhost ($relayhost) - Overrides the relayhost parameter setting for address verifica- + Overrides the relayhost parameter setting for address verifica‐ tion probes. address_verify_transport_maps ($transport_maps) - Overrides the transport_maps parameter setting for address veri- + Overrides the transport_maps parameter setting for address veri‐ fication probes. address_verify_local_transport ($local_transport) - Overrides the local_transport parameter setting for address ver- + Overrides the local_transport parameter setting for address ver‐ ification probes. address_verify_virtual_transport ($virtual_transport) @@ -141,7 +141,7 @@ VERIFY(8) VERIFY(8) verification probes. address_verify_relay_transport ($relay_transport) - Overrides the relay_transport parameter setting for address ver- + Overrides the relay_transport parameter setting for address ver‐ ification probes. address_verify_default_transport ($default_transport) @@ -150,29 +150,36 @@ VERIFY(8) VERIFY(8) Available in Postfix 2.3 and later: - address_verify_sender_dependent_relayhost_maps ($sender_depen- - dent_relayhost_maps) + address_verify_sender_dependent_relayhost_maps ($sender_depen‐‐ + dent_relayhost_maps) Overrides the sender_dependent_relayhost_maps parameter setting for address verification probes. Available in Postfix 2.7 and later: - address_verify_sender_dependent_default_transport_maps ($sender_depen- - dent_default_transport_maps) + address_verify_sender_dependent_default_transport_maps ($sender_depen‐‐ + dent_default_transport_maps) Overrides the sender_dependent_default_transport_maps parameter setting for address verification probes. +SMTPUTF8 CONTROLS + Preliminary SMTPUTF8 support is introduced with Postfix 2.12. + + smtputf8_autodetect_classes (sendmail, verify) + Enable SMTPUTF8 autodetection for the specified mail origin + classes. + MISCELLANEOUS CONTROLS config_directory (see 'postconf -d' output) - The default location of the Postfix main.cf and master.cf con- + The default location of the Postfix main.cf and master.cf con‐ figuration files. daemon_timeout (18000s) - How much time a Postfix daemon process may take to handle a + How much time a Postfix daemon process may take to handle a request before it is terminated by a built-in watchdog timer. ipc_timeout (3600s) - The time limit for sending or receiving information over an + The time limit for sending or receiving information over an internal communication channel. process_id (read-only) @@ -188,8 +195,8 @@ VERIFY(8) VERIFY(8) The syslog facility of Postfix logging. syslog_name (see 'postconf -d' output) - The mail system name that is prepended to the process name in - syslog records, so that "smtpd" becomes, for example, "post- + The mail system name that is prepended to the process name in + syslog records, so that "smtpd" becomes, for example, "post‐ fix/smtpd". SEE ALSO diff --git a/postfix/makedefs b/postfix/makedefs index de8139dfa..80c1e3c62 100644 --- a/postfix/makedefs +++ b/postfix/makedefs @@ -49,6 +49,8 @@ # Do not build with Linux EPOLL support. # By default, EPOLL support is compiled in on platforms that # are known to support it. +# .IP \fB-DNO_EAI\fR +# Do not build with EAI (SMTPUTF8) support. # .IP \fB-DNO_IPV6\fR # Do not build with IPv6 support. # By default, IPv6 support is compiled in on platforms that @@ -426,7 +428,7 @@ EOF : ${SHLIB_SUFFIX=.so} : ${SHLIB_CFLAGS=-fPIC} : ${SHLIB_LD='gcc -shared -Wl,-soname,${LIB}'} - : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'} + : ${SHLIB_RPATH='-Wl,--enable-new-dtags -Wl,-rpath,${SHLIB_DIR}'} : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"} : ${PLUGIN_LD='gcc -shared'} ;; @@ -464,7 +466,7 @@ EOF : ${SHLIB_SUFFIX=.so} : ${SHLIB_CFLAGS=-fPIC} : ${SHLIB_LD='gcc -shared -Wl,-soname,${LIB}'} - : ${SHLIB_RPATH='-Wl,-rpath,${SHLIB_DIR}'} + : ${SHLIB_RPATH='-Wl,--enable-new-dtags -Wl,-rpath,${SHLIB_DIR}'} : ${SHLIB_ENV="LD_LIBRARY_PATH=`pwd`/lib"} : ${PLUGIN_LD='gcc -shared'} ;; @@ -658,6 +660,45 @@ EOF rm -f makedefs.test makedefs.test.[co] esac +# +# Look for ICU and enable unicode email if available. This tests +# a different function that Postfix uses in order to avoid having UTF8 +# in this file. The two functions use the same data structures, so they +# should be equivalent for testing purposes. +# +case "$CCARGS" in + *-DNO_EAI*) ;; + *) trap 'rm -f makedefs.test makedefs.test.[co]' 1 2 3 15 + cat >makedefs.test.c <<'EOF' +#include +#include + +int main(int argc, char **argv) +{ + char buf[1024]; + UErrorCode error = U_ZERO_ERROR; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + UIDNA *idna = uidna_openUTS46(UIDNA_DEFAULT, &error); + + exit(uidna_labelToUnicodeUTF8(idna, + "xn--lgbbat1ad8j", /* an arabic TLD */ + 15, + buf, + sizeof(buf), + &info, + &error) != 14); +} +EOF + ${CC-gcc} -o makedefs.test makedefs.test.c -I/usr/local/include \ + -L/usr/local/lib -licuuc >/dev/null 2>&1 + if ./makedefs.test 2>/dev/null ; then + SYSLIBS="$SYSLIBS -L/usr/local/lib -licuuc" + else + CCARGS="$CCARGS -DNO_EAI" + fi + rm -f makedefs.test makedefs.test.[co] +esac + # # OpenSSL has no configuration query utility, but we don't try to # guess. We assume includes in /usr/include/openssl and libraries in diff --git a/postfix/man/man1/sendmail.1 b/postfix/man/man1/sendmail.1 index 8d6e461e1..537f8340c 100644 --- a/postfix/man/man1/sendmail.1 +++ b/postfix/man/man1/sendmail.1 @@ -388,12 +388,6 @@ and \fBpostmap\fR(1) commands. .IP "\fBdelay_warning_time (0h)\fR" The time after which the sender receives a copy of the message headers of mail that is still queued. -.IP "\fBenable_errors_to (no)\fR" -Report mail delivery errors to the address specified with the -non-standard Errors-To: message header, instead of the envelope -sender address (this feature is removed with Postfix version 2.2, is -turned off by default with Postfix version 2.1, and is always turned on -with older Postfix versions). .IP "\fBmail_owner (postfix)\fR" The UNIX system account that owns the Postfix queue and most Postfix daemon processes. diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5 index 31c6253e3..ae33675b8 100644 --- a/postfix/man/man5/postconf.5 +++ b/postfix/man/man5/postconf.5 @@ -11191,6 +11191,69 @@ key. This is intended behavior. .PP This feature is available in Postfix 2.2 and later. With Postfix 2.3 and later use smtpd_tls_security_level instead. +.SH smtputf8_autodetect_classes (default: sendmail, verify) +Detect that a message requires SMTPUTF8 support for the specified +mail origin classes. This is a workaround to avoid chicken-and-egg +problems during the initial SMTPUTF8 roll-out in environments with +pre-existing mail flows that contain UTF8. Those mail flows should +not break because Postfix suddenly refuses to deliver such mail +to down-stream MTAs that don't announce SMTPUTF8 support. +.PP +The problem is that Postfix cannot rely solely on the sender's +declaration that a message requires SMTPUTF8 support, because UTF8 +may be introduced during local processing (for example, the client +hostname in Postfix's Received: header, adding @$myorigin or +\&.$mydomain to an incomplete address, address rewriting, alias +expansion, automatic BCC recipients, local forwarding, and changes +made by header checks or Milter applications). +.PP +For now, the default is to enable "SMTPUTF8 required" autodetection +only for Postfix sendmail command-line submissions and address +verification probes. This may change once SMTPUTF8 support achieves +world domination. However, sites that add UTF8 content via local +processing (see above) should autodetect the need for SMTPUTF8 +support for all email. +.PP +Specify one or more of the following: +.IP "\fB sendmail \fR" +Submission with the Postfix +\fBsendmail\fR(1) command. +.br +.IP "\fB smtpd \fR" +Mail received with the \fBsmtpd\fR(8) +daemon. +.br +.IP "\fB qmqpd \fR" +Mail received with the \fBqmqpd\fR(8) +daemon. +.br +.IP "\fB forward \fR" +Local forwarding or aliasing. +.br +.IP "\fB bounce \fR" +Submission by the \fBbounce\fR(8) daemon. +.br +.IP "\fB notify \fR" +Postmaster notification from the +\fBsmtp\fR(8) or \fBsmtpd\fR(8) daemon. +.br +.IP "\fB verify \fR" +Address verification probe from the +\fBverify\fR(8) daemon. +.br +.IP "\fB all \fR" +Enable SMTPUTF8 autodetection for all +mail. +.br +.br +.PP +This feature is available in Postfix 2.12 and later. +.SH smtputf8_enable (default: no) +Enable experimental SMTPUTF8 support for the protocols described +in RFC 6531..6533. This requires that Postfix is built to support +these protocols. +.PP +This feature is available in Postfix 2.12 and later. .SH soft_bounce (default: no) Safety net to keep mail queued that would otherwise be returned to the sender. This parameter disables locally-generated bounces, @@ -11273,6 +11336,12 @@ from poorly written software. .PP By default, the Postfix SMTP server accepts RFC 822 syntax in MAIL FROM and RCPT TO addresses. +.SH strict_smtputf8 (default: no) +Enable stricter enforcement of the SMTPUTF8 protocol. The Postfix +SMTP server accepts UTF8 sender or recipient addresses only when +the client requests an SMTPUTF8 mail transaction. +.PP +This feature is available in Postfix 2.12 and later. .SH sun_mailtool_compatibility (default: no) Obsolete SUN mailtool compatibility feature. Instead, use "mailbox_delivery_lock = dotlock". diff --git a/postfix/man/man8/bounce.8 b/postfix/man/man8/bounce.8 index 41f5183d4..76a315357 100644 --- a/postfix/man/man8/bounce.8 +++ b/postfix/man/man8/bounce.8 @@ -48,6 +48,9 @@ RFC 3462 (Delivery Status Notifications) RFC 3464 (Delivery Status Notifications) RFC 3834 (Auto-Submitted: message header) RFC 5322 (Internet Message Format) +RFC 6531 (Internationalized SMTP) +RFC 6532 (Internationalized Message Format) +RFC 6533 (Internationalized Delivery Status Notifications) .SH DIAGNOSTICS .ad .fi @@ -123,6 +126,11 @@ The syslog facility of Postfix logging. .IP "\fBsyslog_name (see 'postconf -d' output)\fR" The mail system name that is prepended to the process name in syslog records, so that "smtpd" becomes, for example, "postfix/smtpd". +.PP +Available in Postfix 2.12 and later: +.IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +Detect that a message requires SMTPUTF8 support for the specified +mail origin classes. .SH "FILES" .na .nf diff --git a/postfix/man/man8/qmqpd.8 b/postfix/man/man8/qmqpd.8 index 758a5dcab..e5c9e0d70 100644 --- a/postfix/man/man8/qmqpd.8 +++ b/postfix/man/man8/qmqpd.8 @@ -66,6 +66,15 @@ specified \fItransport:destination\fR. .IP "\fBreceive_override_options (empty)\fR" Enable or disable recipient validation, built-in content filtering, or address mapping. +.SH "SMTPUTF8 CONTROLS" +.na +.nf +.ad +.fi +Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +.IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +Detect that a message requires SMTPUTF8 support for the specified +mail origin classes. .SH "RESOURCE AND RATE CONTROLS" .na .nf diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index f723f1be9..6d8d116b7 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -110,6 +110,8 @@ RFC 3461 (SMTP DSN Extension) RFC 3463 (Enhanced Status Codes) RFC 4954 (AUTH command) RFC 5321 (SMTP protocol) +RFC 6531 (Internationalized SMTP) +RFC 6533 (Internationalized Delivery Status Notifications) .SH DIAGNOSTICS .ad .fi @@ -605,6 +607,18 @@ Available in Postfix version 2.11 and later: When SMTP connection caching is enabled, the number of times that an SMTP session may be reused before it is closed, or zero (no limit). +.SH "SMTPUTF8 CONTROLS" +.na +.nf +.ad +.fi +Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +.IP "\fBsmtputf8_enable (no)\fR" +Enable experimental SMTPUTF8 support for the protocols described +in RFC 6531..6533. +.IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +Enable SMTPUTF8 autodetection for the specified mail origin +classes. .SH "TROUBLE SHOOTING CONTROLS" .na .nf diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index e521a89aa..91a3a35f0 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -63,6 +63,8 @@ RFC 3848 (ESMTP transmission types) RFC 4409 (Message submission) RFC 4954 (AUTH command) RFC 5321 (SMTP protocol) +RFC 6531 (Internationalized SMTP) +RFC 6533 (Internationalized Delivery Status Notifications) .SH DIAGNOSTICS .ad .fi @@ -506,6 +508,20 @@ and require that clients use TLS encryption. .IP "\fBsmtpd_tls_cipherlist (empty)\fR" Obsolete Postfix < 2.3 control for the Postfix SMTP server TLS cipher list. +.SH "SMTPUTF8 CONTROLS" +.na +.nf +.ad +.fi +Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +.IP "\fBsmtputf8_enable (no)\fR" +Enable experimental SMTPUTF8 support for the protocols described +in RFC 6531..6533. +.IP "\fBstrict_smtputf8 (no)\fR" +Enable stricter enforcement of the SMTPUTF8 protocol. +.IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +Detect that a message requires SMTPUTF8 support for the specified +mail origin classes. .SH "VERP SUPPORT CONTROLS" .na .nf diff --git a/postfix/man/man8/verify.8 b/postfix/man/man8/verify.8 index 92f380cce..5f579a18d 100644 --- a/postfix/man/man8/verify.8 +++ b/postfix/man/man8/verify.8 @@ -168,6 +168,15 @@ Available in Postfix 2.7 and later: .IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR" Overrides the sender_dependent_default_transport_maps parameter setting for address verification probes. +.SH "SMTPUTF8 CONTROLS" +.na +.nf +.ad +.fi +Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +.IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +Enable SMTPUTF8 autodetection for the specified mail origin +classes. .SH "MISCELLANEOUS CONTROLS" .na .nf diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink index 513ab23b9..61b9a92f9 100755 --- a/postfix/mantools/postlink +++ b/postfix/mantools/postlink @@ -1049,6 +1049,12 @@ while (<>) { s;\btlsproxy_tls_security_level\b;$&;g; s;\btlsproxy_use_tls\b;$&;g; + # SMTPUTF8 + + s;\bsmtputf8_enable\b;$&;g; + s;\bstrict_smtputf8\b;$&;g; + s;\bsmtputf8_autodetect_classes\b;$&;g; + # Service-defined parameters... s;\bpolicy_time_limit\b;$&;g; diff --git a/postfix/proto/INSTALL.html b/postfix/proto/INSTALL.html index 2e43d3242..7636ce690 100644 --- a/postfix/proto/INSTALL.html +++ b/postfix/proto/INSTALL.html @@ -730,6 +730,10 @@ this feature. EPOLL support. By default, EPOLL support is compiled in on platforms that are known to support this feature. + -DNO_EAI Do not build with EAI +(SMTPUTF8) support. By default, EAI support is compiled in when +the "icuuc" library and header files are found. + -DNO_IPV6 Do not build with IPv6 support. By default, IPv6 support is compiled in on platforms that are known to have IPv6 support. Note: this directive is for debugging diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 5b614ccbf..45d49c092 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -16042,3 +16042,75 @@ request before giving up. Specify a value greater than zero.

service request. Specify a value greater than zero.

This feature is available in Postfix 2.12 and later.

+ +%PARAM smtputf8_enable no + +

Enable experimental SMTPUTF8 support for the protocols described +in RFC 6531..6533. This requires that Postfix is built to support +these protocols.

+ +

This feature is available in Postfix 2.12 and later.

+ +%PARAM strict_smtputf8 no + +

Enable stricter enforcement of the SMTPUTF8 protocol. The Postfix +SMTP server accepts UTF8 sender or recipient addresses only when +the client requests an SMTPUTF8 mail transaction.

+ +

This feature is available in Postfix 2.12 and later.

+ +%PARAM smtputf8_autodetect_classes sendmail, verify + +

Detect that a message requires SMTPUTF8 support for the specified +mail origin classes. This is a workaround to avoid chicken-and-egg +problems during the initial SMTPUTF8 roll-out in environments with +pre-existing mail flows that contain UTF8. Those mail flows should +not break because Postfix suddenly refuses to deliver such mail +to down-stream MTAs that don't announce SMTPUTF8 support.

+ +

The problem is that Postfix cannot rely solely on the sender's +declaration that a message requires SMTPUTF8 support, because UTF8 +may be introduced during local processing (for example, the client +hostname in Postfix's Received: header, adding @$myorigin or +.$mydomain to an incomplete address, address rewriting, alias +expansion, automatic BCC recipients, local forwarding, and changes +made by header checks or Milter applications).

+ +

For now, the default is to enable "SMTPUTF8 required" autodetection +only for Postfix sendmail command-line submissions and address +verification probes. This may change once SMTPUTF8 support achieves +world domination. However, sites that add UTF8 content via local +processing (see above) should autodetect the need for SMTPUTF8 +support for all email.

+ +

Specify one or more of the following:

+ +
+ +
sendmail
Submission with the Postfix +sendmail(1) command.
+ +
smtpd
Mail received with the smtpd(8) +daemon.
+ +
qmqpd
Mail received with the qmqpd(8) +daemon.
+ +
forward
Local forwarding or aliasing. +
+ +
bounce
Submission by the bounce(8) daemon. +
+ +
notify
Postmaster notification from the +smtp(8) or smtpd(8) daemon.
+ +
verify
Address verification probe from the +verify(8) daemon.
+ +
all
Enable SMTPUTF8 autodetection for all +mail.
+ +
+ +

This feature is available in Postfix 2.12 and later.

diff --git a/postfix/src/bounce/Makefile.in b/postfix/src/bounce/Makefile.in index f070b2182..c73d71133 100644 --- a/postfix/src/bounce/Makefile.in +++ b/postfix/src/bounce/Makefile.in @@ -169,16 +169,18 @@ bounce_notify_service.o: ../../include/deliver_request.h bounce_notify_service.o: ../../include/dsn.h bounce_notify_service.o: ../../include/dsn_buf.h bounce_notify_service.o: ../../include/dsn_mask.h -bounce_notify_service.o: ../../include/int_filt.h +bounce_notify_service.o: ../../include/iostuff.h bounce_notify_service.o: ../../include/mail_addr.h bounce_notify_service.o: ../../include/mail_error.h bounce_notify_service.o: ../../include/mail_params.h +bounce_notify_service.o: ../../include/mail_proto.h bounce_notify_service.o: ../../include/mail_queue.h bounce_notify_service.o: ../../include/msg.h bounce_notify_service.o: ../../include/msg_stats.h bounce_notify_service.o: ../../include/name_mask.h bounce_notify_service.o: ../../include/post_mail.h bounce_notify_service.o: ../../include/rcpt_buf.h +bounce_notify_service.o: ../../include/rec_type.h bounce_notify_service.o: ../../include/recipient_list.h bounce_notify_service.o: ../../include/sys_defs.h bounce_notify_service.o: ../../include/vbuf.h @@ -195,7 +197,6 @@ bounce_notify_util.o: ../../include/dsn.h bounce_notify_util.o: ../../include/dsn_buf.h bounce_notify_util.o: ../../include/dsn_mask.h bounce_notify_util.o: ../../include/events.h -bounce_notify_util.o: ../../include/int_filt.h bounce_notify_util.o: ../../include/iostuff.h bounce_notify_util.o: ../../include/is_header.h bounce_notify_util.o: ../../include/lex_822.h @@ -233,16 +234,18 @@ bounce_notify_verp.o: ../../include/deliver_request.h bounce_notify_verp.o: ../../include/dsn.h bounce_notify_verp.o: ../../include/dsn_buf.h bounce_notify_verp.o: ../../include/dsn_mask.h -bounce_notify_verp.o: ../../include/int_filt.h +bounce_notify_verp.o: ../../include/iostuff.h bounce_notify_verp.o: ../../include/mail_addr.h bounce_notify_verp.o: ../../include/mail_error.h bounce_notify_verp.o: ../../include/mail_params.h +bounce_notify_verp.o: ../../include/mail_proto.h bounce_notify_verp.o: ../../include/mail_queue.h bounce_notify_verp.o: ../../include/msg.h bounce_notify_verp.o: ../../include/msg_stats.h bounce_notify_verp.o: ../../include/name_mask.h bounce_notify_verp.o: ../../include/post_mail.h bounce_notify_verp.o: ../../include/rcpt_buf.h +bounce_notify_verp.o: ../../include/rec_type.h bounce_notify_verp.o: ../../include/recipient_list.h bounce_notify_verp.o: ../../include/sys_defs.h bounce_notify_verp.o: ../../include/vbuf.h @@ -260,15 +263,17 @@ bounce_one_service.o: ../../include/deliver_request.h bounce_one_service.o: ../../include/dsn.h bounce_one_service.o: ../../include/dsn_buf.h bounce_one_service.o: ../../include/dsn_mask.h -bounce_one_service.o: ../../include/int_filt.h +bounce_one_service.o: ../../include/iostuff.h bounce_one_service.o: ../../include/mail_addr.h bounce_one_service.o: ../../include/mail_error.h bounce_one_service.o: ../../include/mail_params.h +bounce_one_service.o: ../../include/mail_proto.h bounce_one_service.o: ../../include/msg.h bounce_one_service.o: ../../include/msg_stats.h bounce_one_service.o: ../../include/name_mask.h bounce_one_service.o: ../../include/post_mail.h bounce_one_service.o: ../../include/rcpt_buf.h +bounce_one_service.o: ../../include/rec_type.h bounce_one_service.o: ../../include/recipient_list.h bounce_one_service.o: ../../include/sys_defs.h bounce_one_service.o: ../../include/vbuf.h @@ -316,16 +321,18 @@ bounce_trace_service.o: ../../include/deliver_request.h bounce_trace_service.o: ../../include/dsn.h bounce_trace_service.o: ../../include/dsn_buf.h bounce_trace_service.o: ../../include/dsn_mask.h -bounce_trace_service.o: ../../include/int_filt.h +bounce_trace_service.o: ../../include/iostuff.h bounce_trace_service.o: ../../include/mail_addr.h bounce_trace_service.o: ../../include/mail_error.h bounce_trace_service.o: ../../include/mail_params.h +bounce_trace_service.o: ../../include/mail_proto.h bounce_trace_service.o: ../../include/mail_queue.h bounce_trace_service.o: ../../include/msg.h bounce_trace_service.o: ../../include/msg_stats.h bounce_trace_service.o: ../../include/name_mask.h bounce_trace_service.o: ../../include/post_mail.h bounce_trace_service.o: ../../include/rcpt_buf.h +bounce_trace_service.o: ../../include/rec_type.h bounce_trace_service.o: ../../include/recipient_list.h bounce_trace_service.o: ../../include/sys_defs.h bounce_trace_service.o: ../../include/vbuf.h @@ -340,15 +347,17 @@ bounce_warn_service.o: ../../include/cleanup_user.h bounce_warn_service.o: ../../include/dsn.h bounce_warn_service.o: ../../include/dsn_buf.h bounce_warn_service.o: ../../include/dsn_mask.h -bounce_warn_service.o: ../../include/int_filt.h +bounce_warn_service.o: ../../include/iostuff.h bounce_warn_service.o: ../../include/mail_addr.h bounce_warn_service.o: ../../include/mail_error.h bounce_warn_service.o: ../../include/mail_params.h +bounce_warn_service.o: ../../include/mail_proto.h bounce_warn_service.o: ../../include/mail_queue.h bounce_warn_service.o: ../../include/msg.h bounce_warn_service.o: ../../include/name_mask.h bounce_warn_service.o: ../../include/post_mail.h bounce_warn_service.o: ../../include/rcpt_buf.h +bounce_warn_service.o: ../../include/rec_type.h bounce_warn_service.o: ../../include/recipient_list.h bounce_warn_service.o: ../../include/sys_defs.h bounce_warn_service.o: ../../include/vbuf.h diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index 3c52e7aea..ec76f38f3 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -40,6 +40,9 @@ /* RFC 3464 (Delivery Status Notifications) /* RFC 3834 (Auto-Submitted: message header) /* RFC 5322 (Internet Message Format) +/* RFC 6531 (Internationalized SMTP) +/* RFC 6532 (Internationalized Message Format) +/* RFC 6533 (Internationalized Delivery Status Notifications) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* CONFIGURATION PARAMETERS @@ -111,6 +114,11 @@ /* .IP "\fBsyslog_name (see 'postconf -d' output)\fR" /* The mail system name that is prepended to the process name in syslog /* records, so that "smtpd" becomes, for example, "postfix/smtpd". +/* .PP +/* Available in Postfix 2.12 and later: +/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +/* Detect that a message requires SMTPUTF8 support for the specified +/* mail origin classes. /* FILES /* /var/spool/postfix/bounce/* non-delivery records /* /var/spool/postfix/defer/* non-delivery records @@ -275,11 +283,12 @@ static int bounce_append_proto(char *service_name, VSTREAM *client) static int bounce_notify_proto(char *service_name, VSTREAM *client, int (*service) (int, char *, char *, char *, - char *, char *, char *, int, + char *, int, char *, char *, int, BOUNCE_TEMPLATES *)) { const char *myname = "bounce_notify_proto"; int flags; + int smtputf8; int dsn_ret; /* @@ -290,10 +299,11 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, 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_INT, MAIL_ATTR_SMTPUTF8, &smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, - ATTR_TYPE_END) != 7) { + ATTR_TYPE_END) != 8) { msg_warn("malformed request"); return (-1); } @@ -311,9 +321,10 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, } printable(STR(dsn_envid), '?'); if (msg_verbose) - msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s sender=%s envid=%s ret=0x%x", + msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x", myname, flags, service_name, STR(queue_name), STR(queue_id), - STR(encoding), STR(sender), STR(dsn_envid), dsn_ret); + STR(encoding), smtputf8, STR(sender), STR(dsn_envid), + dsn_ret); /* * On request by the client, set up a trap to delete the log file in case @@ -326,7 +337,7 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, * Execute the request. */ return (service(flags, service_name, STR(queue_name), - STR(queue_id), STR(encoding), + STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, bounce_templates)); } @@ -337,6 +348,7 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client) { const char *myname = "bounce_verp_proto"; int flags; + int smtputf8; int dsn_ret; /* @@ -347,11 +359,12 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client) 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_INT, MAIL_ATTR_SMTPUTF8, &smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp_delims, - ATTR_TYPE_END) != 8) { + ATTR_TYPE_END) != 9) { msg_warn("malformed request"); return (-1); } @@ -374,9 +387,9 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client) return (-1); } if (msg_verbose) - msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s sender=%s envid=%s ret=0x%x delim=%s", + msg_info("%s: flags=0x%x service=%s queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s ret=0x%x delim=%s", myname, flags, service_name, STR(queue_name), - STR(queue_id), STR(encoding), STR(sender), + STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, STR(verp_delims)); /* @@ -393,12 +406,12 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client) 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(flags, service_name, STR(queue_name), - STR(queue_id), STR(encoding), + STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, bounce_templates)); } else return (bounce_notify_verp(flags, service_name, STR(queue_name), - STR(queue_id), STR(encoding), + STR(queue_id), STR(encoding), smtputf8, STR(sender), STR(dsn_envid), dsn_ret, STR(verp_delims), bounce_templates)); } @@ -409,6 +422,7 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) { const char *myname = "bounce_one_proto"; int flags; + int smtputf8; int dsn_ret; /* @@ -419,12 +433,13 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) 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_INT, MAIL_ATTR_SMTPUTF8, &smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf, ATTR_TYPE_FUNC, dsb_scan, (void *) dsn_buf, - ATTR_TYPE_END) != 9) { + ATTR_TYPE_END) != 10) { msg_warn("malformed request"); return (-1); } @@ -465,10 +480,10 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) * RECIPIENT_FROM_RCPT_BUF(). */ if (msg_verbose) - msg_info("%s: flags=0x%x queue=%s id=%s encoding=%s sender=%s envid=%s dsn_ret=0x%x orig_to=%s to=%s off=%ld dsn_orig=%s notif=0x%x stat=%s act=%s why=%s", + msg_info("%s: flags=0x%x queue=%s id=%s encoding=%s smtputf8=%d sender=%s envid=%s dsn_ret=0x%x orig_to=%s to=%s off=%ld dsn_orig=%s notif=0x%x stat=%s act=%s why=%s", myname, flags, STR(queue_name), STR(queue_id), - STR(encoding), STR(sender), STR(dsn_envid), dsn_ret, - STR(rcpt_buf->orig_addr), STR(rcpt_buf->address), + STR(encoding), smtputf8, STR(sender), STR(dsn_envid), + dsn_ret, STR(rcpt_buf->orig_addr), STR(rcpt_buf->address), rcpt_buf->offset, STR(rcpt_buf->dsn_orcpt), rcpt_buf->dsn_notify, STR(dsn_buf->status), STR(dsn_buf->action), STR(dsn_buf->reason)); @@ -477,8 +492,9 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) * Execute the request. */ return (bounce_one_service(flags, STR(queue_name), STR(queue_id), - STR(encoding), STR(sender), STR(dsn_envid), - dsn_ret, rcpt_buf, dsn_buf, bounce_templates)); + STR(encoding), smtputf8, STR(sender), + STR(dsn_envid), dsn_ret, rcpt_buf, + dsn_buf, bounce_templates)); } /* bounce_service - parse bounce command type and delegate */ diff --git a/postfix/src/bounce/bounce_notify_service.c b/postfix/src/bounce/bounce_notify_service.c index 75c490082..7ded894ca 100644 --- a/postfix/src/bounce/bounce_notify_service.c +++ b/postfix/src/bounce/bounce_notify_service.c @@ -6,12 +6,15 @@ /* SYNOPSIS /* #include "bounce_service.h" /* -/* int bounce_notify_service(flags, queue_name, queue_id, encoding, -/* sender, dsn_envid, dsn_ret, templates) +/* int bounce_notify_service(flags, service, queue_name, queue_id, +/* encoding, smtputf8, sender, dsn_envid, +/* dsn_ret, templates) /* int flags; +/* char *service; /* char *queue_name; /* char *queue_id; /* char *encoding; +/* int smtputf8; /* char *sender; /* char *dsn_envid; /* int dsn_ret; @@ -72,6 +75,7 @@ #include #include #include +#include /* Application-specific. */ @@ -83,8 +87,9 @@ int bounce_notify_service(int flags, char *service, char *queue_name, char *queue_id, char *encoding, - char *recipient, char *dsn_envid, - int dsn_ret, BOUNCE_TEMPLATES *ts) + int smtputf8, char *recipient, + char *dsn_envid, int dsn_ret, + BOUNCE_TEMPLATES *ts) { BOUNCE_INFO *bounce_info; int bounce_status = 1; @@ -129,7 +134,8 @@ int bounce_notify_service(int flags, char *service, char *queue_name, * notification is enabled. */ bounce_info = bounce_mail_init(service, queue_name, queue_id, - encoding, dsn_envid, ts->failure); + encoding, smtputf8, dsn_envid, + ts->failure); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ #define NULL_TRACE_FLAGS 0 @@ -174,7 +180,7 @@ int bounce_notify_service(int flags, char *service, char *queue_name, postmaster = var_2bounce_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { @@ -213,7 +219,7 @@ int bounce_notify_service(int flags, char *service, char *queue_name, */ else { if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { @@ -267,7 +273,7 @@ int bounce_notify_service(int flags, char *service, char *queue_name, postmaster = var_bounce_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { count = -1; diff --git a/postfix/src/bounce/bounce_notify_util.c b/postfix/src/bounce/bounce_notify_util.c index 9cdf264ff..8103f4766 100644 --- a/postfix/src/bounce/bounce_notify_util.c +++ b/postfix/src/bounce/bounce_notify_util.c @@ -12,21 +12,23 @@ /* .in -4 /* } BOUNCE_INFO; /* -/* BOUNCE_INFO *bounce_mail_init(service, queue_name, queue_id, -/* encoding, dsn_envid, template) +/* BOUNCE_INFO *bounce_mail_init(service, queue_name, queue_id, encoding, +/* smtputf8, dsn_envid, template) /* const char *service; /* const char *queue_name; /* const char *queue_id; /* const char *encoding; +/* int smtputf8; /* const char *dsn_envid; /* const BOUNCE_TEMPLATE *template; /* /* BOUNCE_INFO *bounce_mail_one_init(queue_name, queue_id, encoding, -/* dsn_envid, dsn_notify, rcpt_buf, -/* dsn_buf, template) +/* smtputf8, dsn_envid, dsn_notify, +/* rcpt_buf, dsn_buf, template) /* const char *queue_name; /* const char *queue_id; /* const char *encoding; +/* int smtputf8; /* int dsn_notify; /* const char *dsn_envid; /* RCPT_BUF *rcpt_buf; @@ -211,6 +213,7 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service, const char *queue_name, const char *queue_id, const char *encoding, + int smtputf8, const char *dsn_envid, RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf, @@ -228,7 +231,15 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service, 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->smtputf8 = smtputf8; + /* Fix 20140708: propagate smtputf8 attribute to bounce message. */ + bounce_info->smtputf8_attr = + vstring_export(vstring_sprintf(vstring_alloc(20), "%s=%d", + MAIL_ATTR_SMTPUTF8, smtputf8)); + /* Fix 20140708: override MIME encoding: addresses may be 8bit. */ + if (bounce_info->smtputf8) { + bounce_info->mime_encoding = "8bit"; + } else 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"; @@ -359,6 +370,7 @@ BOUNCE_INFO *bounce_mail_init(const char *service, const char *queue_name, const char *queue_id, const char *encoding, + int smtputf8, const char *dsn_envid, BOUNCE_TEMPLATE *template) { @@ -385,7 +397,7 @@ BOUNCE_INFO *bounce_mail_init(const char *service, dsn_buf = dsb_create(); } bounce_info = bounce_mail_alloc(service, queue_name, queue_id, encoding, - dsn_envid, rcpt_buf, dsn_buf, + smtputf8, dsn_envid, rcpt_buf, dsn_buf, template, log_handle); return (bounce_info); } @@ -395,6 +407,7 @@ BOUNCE_INFO *bounce_mail_init(const char *service, BOUNCE_INFO *bounce_mail_one_init(const char *queue_name, const char *queue_id, const char *encoding, + int smtputf8, const char *dsn_envid, RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf, @@ -406,8 +419,8 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name, * Initialize the bounce_info structure for just one recipient. */ bounce_info = bounce_mail_alloc("none", queue_name, queue_id, encoding, - dsn_envid, rcpt_buf, dsn_buf, template, - (BOUNCE_LOG *) 0); + smtputf8, dsn_envid, rcpt_buf, dsn_buf, + template, (BOUNCE_LOG *) 0); return (bounce_info); } @@ -428,6 +441,7 @@ void bounce_mail_free(BOUNCE_INFO *bounce_info) bounce_info->queue_id); vstring_free(bounce_info->buf); vstring_free(bounce_info->sender); + myfree(bounce_info->smtputf8_attr); myfree(bounce_info->mail_name); myfree((char *) bounce_info->mime_boundary); myfree((char *) bounce_info); @@ -483,6 +497,10 @@ int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info, post_mail_fprintf(bounce, "Content-Description: %s", "Notification"); post_mail_fprintf(bounce, "Content-Type: %s; charset=%s", "text/plain", bounce_template_charset(template)); + /* Fix 20140709: addresses may be 8bit. */ + if (bounce_info->smtputf8) + post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", + bounce_info->mime_encoding); post_mail_fputs(bounce, ""); return (vstream_ferror(bounce)); @@ -602,7 +620,12 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary); post_mail_fprintf(bounce, "Content-Description: %s", "Delivery report"); - post_mail_fprintf(bounce, "Content-Type: %s", "message/delivery-status"); + post_mail_fprintf(bounce, "Content-Type: message/%sdelivery-status", + bounce_info->smtputf8 ? "global-" : ""); + /* Fix 20140709: addresses may be 8bit. */ + if (bounce_info->smtputf8) + post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", + bounce_info->mime_encoding); /* * According to RFC 1894: The body of a message/delivery-status consists @@ -621,9 +644,15 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) } post_mail_fprintf(bounce, "X-%s-Queue-ID: %s", bounce_info->mail_name, bounce_info->queue_id); + /* Fix 20140708: use "utf-8" or "rfc822" as appropriate. */ if (VSTRING_LEN(bounce_info->sender) > 0) - post_mail_fprintf(bounce, "X-%s-Sender: rfc822; %s", - bounce_info->mail_name, STR(bounce_info->sender)); + post_mail_fprintf(bounce, "X-%s-Sender: %s; %s", + bounce_info->mail_name, bounce_info->smtputf8 + && STR(bounce_info->sender)[0] + && !allascii(STR(bounce_info->sender)) + && valid_utf8_string(STR(bounce_info->sender), + VSTRING_LEN(bounce_info->sender)) ? + "utf-8" : "rfc822", STR(bounce_info->sender)); if (bounce_info->arrival_time > 0) post_mail_fprintf(bounce, "Arrival-Date: %s", mail_date(bounce_info->arrival_time)); @@ -638,7 +667,13 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) DSN *dsn = &bounce_info->dsn_buf->dsn; post_mail_fputs(bounce, ""); - post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s", rcpt->address); + /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ + post_mail_fprintf(bounce, "Final-Recipient: %s; %s", + bounce_info->smtputf8 && rcpt->address[0] + && !allascii(rcpt->address) + && valid_utf8_string(rcpt->address, + strlen(rcpt->address)) ? + "utf-8" : "rfc822", rcpt->address); /* * XXX DSN @@ -662,8 +697,13 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info) if (NON_NULL_EMPTY(rcpt->dsn_orcpt)) { post_mail_fprintf(bounce, "Original-Recipient: %s", rcpt->dsn_orcpt); } else if (NON_NULL_EMPTY(rcpt->orig_addr)) { - post_mail_fprintf(bounce, "Original-Recipient: rfc822; %s", - rcpt->orig_addr); + /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ + post_mail_fprintf(bounce, "Original-Recipient: %s; %s", + bounce_info->smtputf8 && rcpt->orig_addr[0] + && !allascii(rcpt->orig_addr) + && valid_utf8_string(rcpt->orig_addr, + strlen(rcpt->orig_addr)) ? + "utf-8" : "rfc822", rcpt->orig_addr); } post_mail_fprintf(bounce, "Action: %s", IS_FAILURE_TEMPLATE(bounce_info->template) ? @@ -755,9 +795,14 @@ int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info, "Undelivered " : "", headers_only == DSN_RET_HDRS ? "Message Headers" : "Message"); - post_mail_fprintf(bounce, "Content-Type: %s", - headers_only == DSN_RET_HDRS ? - "text/rfc822-headers" : "message/rfc822"); + if (bounce_info->smtputf8) + post_mail_fprintf(bounce, "Content-Type: message/%s", + headers_only == DSN_RET_HDRS ? + "global-headers" : "global"); + else + post_mail_fprintf(bounce, "Content-Type: %s", + headers_only == DSN_RET_HDRS ? + "text/rfc822-headers" : "message/rfc822"); if (bounce_info->mime_encoding) post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", bounce_info->mime_encoding); diff --git a/postfix/src/bounce/bounce_notify_verp.c b/postfix/src/bounce/bounce_notify_verp.c index 3968c73aa..bfaf7dece 100644 --- a/postfix/src/bounce/bounce_notify_verp.c +++ b/postfix/src/bounce/bounce_notify_verp.c @@ -6,12 +6,16 @@ /* SYNOPSIS /* #include "bounce_service.h" /* -/* int bounce_notify_verp(flags, service, queue_name, queue_id, sender, +/* int bounce_notify_verp(flags, service, queue_name, queue_id, +/* encoding, smtputf8, sender, /* dsn_envid, dsn_ret, verp_delims, /* templates) /* int flags; +/* char *service; /* char *queue_name; /* char *queue_id; +/* char *encoding; +/* int smtputf8; /* char *sender; /* char *dsn_envid; /* int dsn_ret; @@ -74,6 +78,7 @@ #include #include #include +#include /* Application-specific. */ @@ -85,9 +90,9 @@ int bounce_notify_verp(int flags, char *service, char *queue_name, char *queue_id, char *encoding, - char *recipient, char *dsn_envid, - int dsn_ret, char *verp_delims, - BOUNCE_TEMPLATES *ts) + int smtputf8, char *recipient, + char *dsn_envid, int dsn_ret, + char *verp_delims, BOUNCE_TEMPLATES *ts) { const char *myname = "bounce_notify_verp"; BOUNCE_INFO *bounce_info; @@ -113,7 +118,8 @@ int bounce_notify_verp(int flags, char *service, char *queue_name, * Initialize. Open queue file, bounce log, etc. */ bounce_info = bounce_mail_init(service, queue_name, queue_id, - encoding, dsn_envid, ts->failure); + encoding, smtputf8, dsn_envid, + ts->failure); /* * If we have no recipient list then we can't send VERP replies. Send @@ -128,8 +134,9 @@ int bounce_notify_verp(int flags, char *service, char *queue_name, vstring_strcpy(rcpt_buf->address, "(recipient address unavailable)"); (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf); bounce_status = bounce_one_service(flags, queue_name, queue_id, - encoding, recipient, dsn_envid, - dsn_ret, rcpt_buf, dsn_buf, ts); + encoding, smtputf8, recipient, + dsn_envid, dsn_ret, rcpt_buf, + dsn_buf, ts); rcpb_free(rcpt_buf); dsb_free(dsn_buf); bounce_mail_free(bounce_info); @@ -160,7 +167,7 @@ int bounce_notify_verp(int flags, char *service, char *queue_name, } else { verp_sender(verp_buf, verp_delims, recipient, rcpt); if ((bounce = post_mail_fopen_nowait(NULL_SENDER, STR(verp_buf), - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { @@ -219,7 +226,7 @@ int bounce_notify_verp(int flags, char *service, char *queue_name, postmaster = var_bounce_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { if (bounce_header(bounce, bounce_info, postmaster, diff --git a/postfix/src/bounce/bounce_one_service.c b/postfix/src/bounce/bounce_one_service.c index 7a3da8230..08c77ccec 100644 --- a/postfix/src/bounce/bounce_one_service.c +++ b/postfix/src/bounce/bounce_one_service.c @@ -7,12 +7,13 @@ /* #include "bounce_service.h" /* /* int bounce_one_service(flags, queue_name, queue_id, encoding, -/* orig_sender, envid, ret, +/* smtputf8, orig_sender, envid, ret, /* rcpt_buf, dsn_buf, templates) /* int flags; /* char *queue_name; /* char *queue_id; /* char *encoding; +/* int smtputf8; /* char *orig_sender; /* char *envid; /* int ret; @@ -74,6 +75,7 @@ #include #include #include +#include /* Application-specific. */ @@ -84,10 +86,10 @@ /* bounce_one_service - send a bounce for one recipient */ int bounce_one_service(int flags, char *queue_name, char *queue_id, - char *encoding, char *orig_sender, - char *dsn_envid, int dsn_ret, - RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf, - BOUNCE_TEMPLATES *ts) + char *encoding, int smtputf8, + char *orig_sender, char *dsn_envid, + int dsn_ret, RCPT_BUF *rcpt_buf, + DSN_BUF *dsn_buf, BOUNCE_TEMPLATES *ts) { BOUNCE_INFO *bounce_info; int bounce_status = 1; @@ -101,8 +103,8 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id, * Initialize. Open queue file, bounce log, etc. */ bounce_info = bounce_mail_one_init(queue_name, queue_id, encoding, - dsn_envid, rcpt_buf, dsn_buf, - ts->failure); + smtputf8, dsn_envid, rcpt_buf, + dsn_buf, ts->failure); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ #define NULL_TRACE_FLAGS 0 @@ -147,7 +149,7 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id, } else { if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), var_2bounce_rcpt, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { @@ -183,7 +185,7 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id, bounce_status = 0; } else { if ((bounce = post_mail_fopen_nowait(NULL_SENDER, orig_sender, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { @@ -228,7 +230,7 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id, */ if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), var_bounce_rcpt, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { if (bounce_header(bounce, bounce_info, var_bounce_rcpt, diff --git a/postfix/src/bounce/bounce_service.h b/postfix/src/bounce/bounce_service.h index 0a9bc4d02..9ba5ca503 100644 --- a/postfix/src/bounce/bounce_service.h +++ b/postfix/src/bounce/bounce_service.h @@ -31,27 +31,27 @@ extern int bounce_append_service(int, char *, char *, RECIPIENT *, DSN *); /* * bounce_notify_service.c */ -extern int bounce_notify_service(int, char *, char *, char *, char *, char *, char *, int, BOUNCE_TEMPLATES *); +extern int bounce_notify_service(int, char *, char *, char *, char *, int, char *, char *, int, BOUNCE_TEMPLATES *); /* * bounce_warn_service.c */ -extern int bounce_warn_service(int, char *, char *, char *, char *, char *, char *, int, BOUNCE_TEMPLATES *); +extern int bounce_warn_service(int, char *, char *, char *, char *, int, char *, char *, int, BOUNCE_TEMPLATES *); /* * bounce_trace_service.c */ -extern int bounce_trace_service(int, char *, char *, char *, char *, char *, char *, int, BOUNCE_TEMPLATES *); +extern int bounce_trace_service(int, char *, char *, char *, char *, int, char *, char *, int, BOUNCE_TEMPLATES *); /* * bounce_notify_verp.c */ -extern int bounce_notify_verp(int, char *, char *, char *, char *, char *, char *, int, char *, BOUNCE_TEMPLATES *); +extern int bounce_notify_verp(int, char *, char *, char *, char *, int, char *, char *, int, char *, BOUNCE_TEMPLATES *); /* * bounce_one_service.c */ -extern int bounce_one_service(int, char *, char *, char *, char *, char *, int, RCPT_BUF *, DSN_BUF *, BOUNCE_TEMPLATES *); +extern int bounce_one_service(int, char *, char *, char *, int, char *, char *, int, RCPT_BUF *, DSN_BUF *, BOUNCE_TEMPLATES *); /* * bounce_cleanup.c @@ -84,12 +84,14 @@ typedef struct { DSN_BUF *dsn_buf; /* delivery status info */ BOUNCE_LOG *log_handle; /* open logfile */ char *mail_name; /* $mail_name, cooked */ + int smtputf8; /* SMTPUTF8 requested */ + char *smtputf8_attr; /* pre-formatted record value */ } BOUNCE_INFO; /* */ -extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, const char *, BOUNCE_TEMPLATE *); -extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, const char *, RCPT_BUF *, DSN_BUF *, BOUNCE_TEMPLATE *); +extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, const char *, int, const char *, BOUNCE_TEMPLATE *); +extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, int, const char *, RCPT_BUF *, DSN_BUF *, BOUNCE_TEMPLATE *); extern void bounce_mail_free(BOUNCE_INFO *); extern int bounce_header(VSTREAM *, BOUNCE_INFO *, const char *, int); extern int bounce_boilerplate(VSTREAM *, BOUNCE_INFO *); diff --git a/postfix/src/bounce/bounce_template.c b/postfix/src/bounce/bounce_template.c index ed67c81e5..7888a1867 100644 --- a/postfix/src/bounce/bounce_template.c +++ b/postfix/src/bounce/bounce_template.c @@ -286,6 +286,10 @@ static void bounce_template_parse_buffer(BOUNCE_TEMPLATE *tp) /* * Parse pseudo-header labels and values. + * + * XXX EAI: allow UTF8 in template headers when responding to SMTPUTF8 + * message. Sending SMTPUTF8 in reponse to non-SMTPUTF8 mail would make + * no sense. */ #define GETLINE(line, buf) \ (((line) = (buf)) != 0 ? ((buf) = split_at((buf), '\n'), (line)) : 0) diff --git a/postfix/src/bounce/bounce_trace_service.c b/postfix/src/bounce/bounce_trace_service.c index 824931d60..3b340c303 100644 --- a/postfix/src/bounce/bounce_trace_service.c +++ b/postfix/src/bounce/bounce_trace_service.c @@ -6,12 +6,15 @@ /* SYNOPSIS /* #include "bounce_service.h" /* -/* int bounce_trace_service(flags, queue_name, queue_id, encoding, -/* sender, char *envid, int ret, templates) +/* int bounce_trace_service(flags, service, queue_name, queue_id, +/* encoding, smtputf8, sender, envid, +/* ret, templates) /* int flags; +/* char *service; /* char *queue_name; /* char *queue_id; /* char *encoding; +/* int smtputf8; /* char *sender; /* char *envid; /* int ret; @@ -64,6 +67,7 @@ #include #include #include +#include #include /* USR_VRFY and RECORD flags */ /* Application-specific. */ @@ -76,6 +80,7 @@ int bounce_trace_service(int flags, char *service, char *queue_name, char *queue_id, char *encoding, + int smtputf8, char *recipient, char *dsn_envid, int unused_dsn_ret, BOUNCE_TEMPLATES *ts) @@ -134,7 +139,7 @@ int bounce_trace_service(int flags, char *service, char *queue_name, #define NON_DSN_FLAGS (DEL_REQ_FLAG_USR_VRFY | DEL_REQ_FLAG_RECORD) bounce_info = bounce_mail_init(service, queue_name, queue_id, - encoding, dsn_envid, + encoding, smtputf8, dsn_envid, flags & NON_DSN_FLAGS ? ts->verify : ts->success); @@ -171,7 +176,7 @@ int bounce_trace_service(int flags, char *service, char *queue_name, */ new_id = vstring_alloc(10); if ((bounce = post_mail_fopen_nowait(sender, recipient, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { count = -1; diff --git a/postfix/src/bounce/bounce_warn_service.c b/postfix/src/bounce/bounce_warn_service.c index f4b62c75b..a961bd8b8 100644 --- a/postfix/src/bounce/bounce_warn_service.c +++ b/postfix/src/bounce/bounce_warn_service.c @@ -6,12 +6,15 @@ /* SYNOPSIS /* #include "bounce_service.h" /* -/* int bounce_warn_service(flags, queue_name, queue_id, encoding, -/* sender, envid, dsn_ret, templates) +/* int bounce_warn_service(flags, service, queue_name, queue_id, +/* encoding, smtputf8, sender, envid, +/* dsn_ret, templates) /* int flags; +/* char *service; /* char *queue_name; /* char *queue_id; /* char *encoding; +/* int smtputf8; /* char *sender; /* char *envid; /* int dsn_ret; @@ -72,6 +75,7 @@ #include #include #include +#include /* Application-specific. */ @@ -83,8 +87,9 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name, char *queue_id, char *encoding, - char *recipient, char *dsn_envid, - int dsn_ret, BOUNCE_TEMPLATES *ts) + int smtputf8, char *recipient, + char *dsn_envid, int dsn_ret, + BOUNCE_TEMPLATES *ts) { BOUNCE_INFO *bounce_info; int bounce_status = 1; @@ -119,7 +124,7 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name, * notify_classes restrictions. */ bounce_info = bounce_mail_init(service, queue_name, queue_id, - encoding, dsn_envid, ts->delay); + encoding, smtputf8, dsn_envid, ts->delay); #define NULL_SENDER MAIL_ADDR_EMPTY /* special address */ #define NULL_TRACE_FLAGS 0 @@ -164,7 +169,7 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name, postmaster = var_delay_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { @@ -202,7 +207,7 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name, */ else { if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { @@ -252,7 +257,7 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name, postmaster = var_delay_rcpt; if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(), postmaster, - INT_FILT_MASK_BOUNCE, + MAIL_SRC_MASK_BOUNCE, NULL_TRACE_FLAGS, new_id)) != 0) { count = -1; diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 25d04197d..c6c5e74b4 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -587,6 +587,7 @@ cleanup_addr.o: ../../include/mymalloc.h cleanup_addr.o: ../../include/nvtable.h cleanup_addr.o: ../../include/rec_type.h cleanup_addr.o: ../../include/resolve_clnt.h +cleanup_addr.o: ../../include/smtputf8.h cleanup_addr.o: ../../include/string_list.h cleanup_addr.o: ../../include/stringops.h cleanup_addr.o: ../../include/sys_defs.h @@ -628,6 +629,7 @@ cleanup_api.o: ../../include/nvtable.h cleanup_api.o: ../../include/rec_type.h cleanup_api.o: ../../include/recipient_list.h cleanup_api.o: ../../include/resolve_clnt.h +cleanup_api.o: ../../include/smtputf8.h cleanup_api.o: ../../include/string_list.h cleanup_api.o: ../../include/sys_defs.h cleanup_api.o: ../../include/tok822.h @@ -737,6 +739,7 @@ cleanup_envelope.o: ../../include/rec_type.h cleanup_envelope.o: ../../include/recipient_list.h cleanup_envelope.o: ../../include/record.h cleanup_envelope.o: ../../include/resolve_clnt.h +cleanup_envelope.o: ../../include/smtputf8.h cleanup_envelope.o: ../../include/string_list.h cleanup_envelope.o: ../../include/stringops.h cleanup_envelope.o: ../../include/sys_defs.h @@ -1053,8 +1056,10 @@ cleanup_out.o: ../../include/nvtable.h cleanup_out.o: ../../include/rec_type.h cleanup_out.o: ../../include/record.h cleanup_out.o: ../../include/resolve_clnt.h +cleanup_out.o: ../../include/smtputf8.h cleanup_out.o: ../../include/split_at.h cleanup_out.o: ../../include/string_list.h +cleanup_out.o: ../../include/stringops.h cleanup_out.o: ../../include/sys_defs.h cleanup_out.o: ../../include/tok822.h cleanup_out.o: ../../include/vbuf.h diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index eca0785c6..fec0cf867 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -122,6 +122,11 @@ typedef struct CLEANUP_STATE { struct CLEANUP_REGION *free_regions;/* unused regions */ struct CLEANUP_REGION *body_regions;/* regions with body content */ struct CLEANUP_REGION *curr_body_region; + + /* + * Internationalization. + */ + int smtputf8; /* what support is desired */ } CLEANUP_STATE; /* diff --git a/postfix/src/cleanup/cleanup_addr.c b/postfix/src/cleanup/cleanup_addr.c index f8e0596c4..f869f0357 100644 --- a/postfix/src/cleanup/cleanup_addr.c +++ b/postfix/src/cleanup/cleanup_addr.c @@ -93,12 +93,14 @@ #include #include #include +#include /* Application-specific. */ #include "cleanup.h" #define STR vstring_str +#define LEN VSTRING_LEN #define IGNORE_EXTENSION (char **) 0 /* cleanup_addr_sender - process envelope sender record */ @@ -138,6 +140,14 @@ void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf) && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM)) cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); } + /* Fix 20140711: Auto-detect an UTF8 sender. */ + if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) + && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + state->smtputf8 |= SMTPUTF8_FLAG_SENDER; + /* Fix 20140713: request SMTPUTF8 support selectively. */ + if (state->flags & CLEANUP_FLAG_AUTOUTF8) + state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; + } CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr); if (state->sender) /* XXX Can't happen */ myfree(state->sender); @@ -187,6 +197,13 @@ void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf) && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); } + /* Fix 20140711: Auto-detect an UTF8 recipient. */ + if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) + && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + /* Fix 20140713: request SMTPUTF8 support selectively. */ + if (state->flags & CLEANUP_FLAG_AUTOUTF8) + state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; + } cleanup_out_recipient(state, state->dsn_orcpt, state->dsn_notify, state->orig_rcpt, STR(clean_addr)); if (state->recip) /* This can happen */ @@ -233,6 +250,13 @@ void cleanup_addr_bcc_dsn(CLEANUP_STATE *state, const char *bcc, && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) cleanup_masquerade_internal(state, clean_addr, cleanup_masq_domains); } + /* Fix 20140711: Auto-detect an UTF8 recipient. */ + if (var_smtputf8_enable && *STR(clean_addr) && !allascii(STR(clean_addr)) + && valid_utf8_string(STR(clean_addr), LEN(clean_addr))) { + /* Fix 20140713: request SMTPUTF8 support selectively. */ + if (state->flags & CLEANUP_FLAG_AUTOUTF8) + state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; + } cleanup_out_recipient(state, dsn_orcpt, dsn_notify, STR(clean_addr), STR(clean_addr)); vstring_free(clean_addr); diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index ffcd93f80..7e7c43c41 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -75,6 +75,11 @@ /* to translate the result into human-readable text. /* /* cleanup_free() destroys its argument. +/* .IP CLEANUP_FLAG_SMTPUTF8 +/* Request SMTPUTF8 support when delivering mail. +/* .IP CLEANUP_FLAG_AUTOUTF8 +/* Autodetection: request SMTPUTF8 support if the message +/* contains an UTF8 message header, sender, or recipient. /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* SEE ALSO @@ -112,6 +117,7 @@ #include #include #include +#include /* Milter library. */ @@ -193,6 +199,8 @@ void cleanup_control(CLEANUP_STATE *state, int flags) } else { state->err_mask = ~0; } + if (state->flags & CLEANUP_FLAG_SMTPUTF8) + state->smtputf8 = SMTPUTF8_FLAG_REQUESTED; } /* cleanup_flush - finish queue file */ diff --git a/postfix/src/cleanup/cleanup_bounce.c b/postfix/src/cleanup/cleanup_bounce.c index 2118b96d9..361875ec7 100644 --- a/postfix/src/cleanup/cleanup_bounce.c +++ b/postfix/src/cleanup/cleanup_bounce.c @@ -229,14 +229,14 @@ int cleanup_bounce(CLEANUP_STATE *state) bounce_err = bounce_flush(BOUNCE_FLAG_CLEAN, state->queue_name, state->queue_id, - encoding, state->sender, dsn_envid, - dsn_ret); + encoding, state->smtputf8, state->sender, + dsn_envid, dsn_ret); } else { bounce_err = bounce_flush_verp(BOUNCE_FLAG_CLEAN, state->queue_name, state->queue_id, - encoding, state->sender, dsn_envid, - dsn_ret, state->verp_delims); + encoding, state->smtputf8, state->sender, + dsn_envid, dsn_ret, state->verp_delims); } if (bounce_err != 0) { msg_warn("%s: bounce message failure", state->queue_id); diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index 1f5aa51f1..261542ba8 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -44,6 +44,7 @@ #include #include #include +#include /* ssscanf() */ #include /* Utility library. */ @@ -66,6 +67,7 @@ #include #include #include +#include /* Application-specific. */ @@ -93,7 +95,8 @@ void cleanup_envelope(CLEANUP_STATE *state, int type, (REC_TYPE_SIZE_CAST2) 0, /* content offset */ (REC_TYPE_SIZE_CAST3) 0, /* recipient count */ (REC_TYPE_SIZE_CAST4) 0, /* qmgr options */ - (REC_TYPE_SIZE_CAST5) 0); /* content length */ + (REC_TYPE_SIZE_CAST5) 0, /* content length */ + (REC_TYPE_SIZE_CAST6) 0); /* smtputf8 */ /* * Pass control to the actual envelope processing routine. @@ -340,13 +343,19 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, /* * Initial envelope non-recipient record processing. + * + * If the message was requeued with "postsuper -r" use their + * SMTPUTF8_REQUESTED flag. */ if (state->flags & CLEANUP_FLAG_INRCPT) /* Tell qmgr that recipient records are mixed with other information. */ state->qmgr_opts |= QMGR_READ_FLAG_MIXED_RCPT_OTHER; - if (type == REC_TYPE_SIZE) - /* Use our own SIZE record instead. */ + if (type == REC_TYPE_SIZE) { + /* Use our own SIZE record, except for the SMTPUTF8_REQUESTED flag. */ + (void) sscanf(buf, "%*s $*s %*s %*s %*s %d", &state->smtputf8); + state->smtputf8 &= SMTPUTF8_FLAG_REQUESTED; return; + } if (mapped_type == REC_TYPE_CTIME) /* Use our own expiration time base record instead. */ return; diff --git a/postfix/src/cleanup/cleanup_final.c b/postfix/src/cleanup/cleanup_final.c index fc482c5d0..db77fc741 100644 --- a/postfix/src/cleanup/cleanup_final.c +++ b/postfix/src/cleanup/cleanup_final.c @@ -73,5 +73,6 @@ void cleanup_final(CLEANUP_STATE *state) (REC_TYPE_SIZE_CAST2) state->data_offset, (REC_TYPE_SIZE_CAST3) state->rcpt_count, (REC_TYPE_SIZE_CAST4) state->qmgr_opts, - (REC_TYPE_SIZE_CAST5) state->cont_length); + (REC_TYPE_SIZE_CAST5) state->cont_length, + (REC_TYPE_SIZE_CAST6) state->smtputf8); } diff --git a/postfix/src/cleanup/cleanup_out.c b/postfix/src/cleanup/cleanup_out.c index 904208071..8905fad37 100644 --- a/postfix/src/cleanup/cleanup_out.c +++ b/postfix/src/cleanup/cleanup_out.c @@ -80,6 +80,7 @@ #include #include #include +#include /* Global library. */ @@ -88,11 +89,14 @@ #include #include #include +#include /* Application-specific. */ #include "cleanup.h" +#define STR vstring_str + /* cleanup_out - output one single record */ void cleanup_out(CLEANUP_STATE *state, int type, const char *string, ssize_t len) @@ -170,6 +174,16 @@ void cleanup_out_header(CLEANUP_STATE *state, VSTRING *header_buf) char *next_line; ssize_t line_len; + /* + * Fix 20140711: Auto-detect the presence of a non-ASCII header. + */ + if (var_smtputf8_enable && *STR(header_buf) && !allascii(STR(header_buf))) { + state->smtputf8 |= SMTPUTF8_FLAG_HEADER; + /* Fix 20140713: request SMTPUTF8 support selectively. */ + if (state->flags & CLEANUP_FLAG_AUTOUTF8) + state->smtputf8 |= SMTPUTF8_FLAG_REQUESTED; + } + /* * Prepend a tab to continued header lines that went through the address * rewriting machinery. See cleanup_fold_header(state) below for the form diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index 50e90f158..340d32d62 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -127,6 +127,7 @@ CLEANUP_STATE *cleanup_state_alloc(VSTREAM *src) state->milter_ext_rcpt = 0; state->milter_err_text = 0; state->free_regions = state->body_regions = state->curr_body_region = 0; + state->smtputf8 = 0; return (state); } diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index 2498f4fa4..3efa489fb 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -32,7 +32,8 @@ SRCS = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \ match_service.c mail_conf_nint.c addr_match_list.c mail_conf_nbool.c \ smtp_reply_footer.c safe_ultostr.c verify_sender_addr.c \ dict_memcache.c mail_version.c memcache_proto.c server_acl.c \ - mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c + mkmap_fail.c haproxy_srvr.c dsn_filter.c dynamicmaps.c uxtext.c \ + smtputf8.c OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \ clnt_stream.o conv_time.o db_common.o debug_peer.o debug_process.o \ @@ -66,8 +67,8 @@ OBJS = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \ match_service.o mail_conf_nint.o addr_match_list.o mail_conf_nbool.o \ smtp_reply_footer.o safe_ultostr.o verify_sender_addr.o \ dict_memcache.o mail_version.o memcache_proto.o server_acl.o \ - mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o \ - $(NON_PLUGIN_MAP_OBJ) + mkmap_fail.o haproxy_srvr.o dsn_filter.o dynamicmaps.o uxtext.o \ + smtputf8.o $(NON_PLUGIN_MAP_OBJ) # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these maps, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. @@ -99,7 +100,7 @@ HDRS = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \ fold_addr.h header_body_checks.h data_redirect.h match_service.h \ addr_match_list.h smtp_reply_footer.h safe_ultostr.h \ verify_sender_addr.h dict_memcache.h memcache_proto.h server_acl.h \ - haproxy_srvr.h dsn_filter.h dynamicmaps.h + haproxy_srvr.h dsn_filter.h dynamicmaps.h uxtext.h smtputf8.h TESTSRC = rec2stream.c stream2rec.c recdump.c DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE) CFLAGS = $(DEBUG) $(OPT) $(DEFS) @@ -113,7 +114,7 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \ verify_clnt xtext anvil_clnt scache ehlo_mask \ valid_mailhost_addr own_inet_addr header_body_checks \ data_redirect addr_match_list safe_ultostr verify_sender_addr \ - mail_version mail_dict server_acl + mail_version mail_dict server_acl uxtext LIBS = ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX) LIB_DIR = ../../lib @@ -305,6 +306,11 @@ strip_addr: $(LIB) $(LIBS) $(CC) -DTEST $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) mv junk $@.o +uxtext: $(LIB) $(LIBS) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) + mv junk $@.o + verify_clnt: $(LIB) $(LIBS) mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS) @@ -1252,15 +1258,19 @@ input_transp.o: cleanup_user.h input_transp.o: input_transp.c input_transp.o: input_transp.h input_transp.o: mail_params.h +int_filt.o: ../../include/attr.h +int_filt.o: ../../include/iostuff.h int_filt.o: ../../include/msg.h int_filt.o: ../../include/name_mask.h int_filt.o: ../../include/sys_defs.h int_filt.o: ../../include/vbuf.h +int_filt.o: ../../include/vstream.h int_filt.o: ../../include/vstring.h int_filt.o: cleanup_user.h int_filt.o: int_filt.c int_filt.o: int_filt.h int_filt.o: mail_params.h +int_filt.o: mail_proto.h is_header.o: ../../include/sys_defs.h is_header.o: is_header.c is_header.o: is_header.h @@ -1951,7 +1961,6 @@ post_mail.o: ../../include/vbuf.h post_mail.o: ../../include/vstream.h post_mail.o: ../../include/vstring.h post_mail.o: cleanup_user.h -post_mail.o: int_filt.h post_mail.o: mail_date.h post_mail.o: mail_params.h post_mail.o: mail_proto.h @@ -2203,6 +2212,19 @@ smtp_stream.o: ../../include/vstring.h smtp_stream.o: ../../include/vstring_vstream.h smtp_stream.o: smtp_stream.c smtp_stream.o: smtp_stream.h +smtputf8.o: ../../include/attr.h +smtputf8.o: ../../include/iostuff.h +smtputf8.o: ../../include/msg.h +smtputf8.o: ../../include/name_mask.h +smtputf8.o: ../../include/sys_defs.h +smtputf8.o: ../../include/vbuf.h +smtputf8.o: ../../include/vstream.h +smtputf8.o: ../../include/vstring.h +smtputf8.o: cleanup_user.h +smtputf8.o: mail_params.h +smtputf8.o: mail_proto.h +smtputf8.o: smtputf8.c +smtputf8.o: smtputf8.h split_addr.o: ../../include/split_at.h split_addr.o: ../../include/sys_defs.h split_addr.o: mail_addr.h @@ -2323,6 +2345,12 @@ user_acl.o: mypwd.h user_acl.o: string_list.h user_acl.o: user_acl.c user_acl.o: user_acl.h +uxtext.o: ../../include/msg.h +uxtext.o: ../../include/sys_defs.h +uxtext.o: ../../include/vbuf.h +uxtext.o: ../../include/vstring.h +uxtext.o: uxtext.c +uxtext.o: uxtext.h valid_mailhost_addr.o: ../../include/msg.h valid_mailhost_addr.o: ../../include/myaddrinfo.h valid_mailhost_addr.o: ../../include/sys_defs.h diff --git a/postfix/src/global/abounce.c b/postfix/src/global/abounce.c index 76abd0bd6..51a7a5bfe 100644 --- a/postfix/src/global/abounce.c +++ b/postfix/src/global/abounce.c @@ -6,24 +6,26 @@ /* SYNOPSIS /* #include /* -/* void abounce_flush(flags, queue, id, encoding, sender, +/* void abounce_flush(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret, callback, context) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; /* void (*callback)(int status, char *context); /* char *context; /* -/* void abounce_flush_verp(flags, queue, id, encoding, sender, +/* void abounce_flush_verp(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret, verp, callback, context) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; @@ -31,24 +33,26 @@ /* void (*callback)(int status, char *context); /* char *context; /* -/* void adefer_flush(flags, queue, id, encoding, sender, +/* void adefer_flush(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret, callback, context) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; /* void (*callback)(int status, char *context); /* char *context; /* -/* void adefer_flush_verp(flags, queue, id, encoding, sender, +/* void adefer_flush_verp(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret, verp, callback, context) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; @@ -56,24 +60,26 @@ /* void (*callback)(int status, char *context); /* char *context; /* -/* void adefer_warn(flags, queue, id, encoding, sender, +/* void adefer_warn(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret, callback, context) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; /* void (*callback)(int status, char *context); /* char *context; /* -/* void atrace_flush(flags, queue, id, encoding, sender, +/* void atrace_flush(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret, callback, context) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; @@ -132,6 +138,8 @@ /* file has the same name as the original message file. /* .IP encoding /* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}. +/* .IP smtputf8 +/* The level of SMTPUTF8 support (to be defined). /* .IP sender /* The sender envelope address. /* .IP dsn_envid @@ -257,6 +265,7 @@ static void abounce_request_verp(const char *class, const char *service, int command, int flags, const char *queue, const char *id, const char *encoding, + int smtputf8, const char *sender, const char *dsn_envid, int dsn_ret, @@ -284,13 +293,14 @@ static void abounce_request_verp(const char *class, const char *service, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_STR, MAIL_ATTR_VERPDL, verp, ATTR_TYPE_END) == 0 && vstream_fflush(ap->fp) == 0) { - ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, + ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, (char *) ap, ABOUNCE_TIMEOUT); } else { abounce_done(ap, -1); @@ -300,27 +310,28 @@ 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 *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - const char *verp, ABOUNCE_FN callback, + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, const char *verp, + ABOUNCE_FN callback, char *context) { abounce_request_verp(MAIL_CLASS_PRIVATE, var_bounce_service, - BOUNCE_CMD_VERP, flags, queue, id, encoding, + BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, sender, dsn_envid, dsn_ret, verp, callback, context); } /* adefer_flush_verp - asynchronous defer flush */ void adefer_flush_verp(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - const char *verp, ABOUNCE_FN callback, - char *context) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, const char *verp, + ABOUNCE_FN callback, char *context) { flags |= BOUNCE_FLAG_DELRCPT; abounce_request_verp(MAIL_CLASS_PRIVATE, var_defer_service, - BOUNCE_CMD_VERP, flags, queue, id, encoding, + BOUNCE_CMD_VERP, flags, queue, id, encoding, smtputf8, sender, dsn_envid, dsn_ret, verp, callback, context); } @@ -329,7 +340,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 *encoding, const char *sender, + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, int dsn_ret, ABOUNCE_FN callback, char *context) { @@ -353,12 +365,13 @@ static void abounce_request(const char *class, const char *service, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, ATTR_TYPE_END) == 0 && vstream_fflush(ap->fp) == 0) { - ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, + ABOUNCE_EVENT_ENABLE(vstream_fileno(ap->fp), abounce_event, (char *) ap, ABOUNCE_TIMEOUT); } else { abounce_done(ap, -1); @@ -368,48 +381,49 @@ 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 *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - ABOUNCE_FN callback, char *context) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, ABOUNCE_FN callback, + char *context) { abounce_request(MAIL_CLASS_PRIVATE, var_bounce_service, BOUNCE_CMD_FLUSH, - flags, queue, id, encoding, sender, dsn_envid, dsn_ret, - callback, context); + flags, queue, id, encoding, smtputf8, sender, dsn_envid, + dsn_ret, callback, context); } /* adefer_flush - asynchronous defer flush */ void adefer_flush(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - ABOUNCE_FN callback, char *context) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, ABOUNCE_FN callback, char *context) { flags |= BOUNCE_FLAG_DELRCPT; abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_FLUSH, - flags, queue, id, encoding, sender, dsn_envid, dsn_ret, - callback, context); + flags, queue, id, encoding, smtputf8, sender, dsn_envid, + dsn_ret, 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 *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - ABOUNCE_FN callback, char *context) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, ABOUNCE_FN callback, char *context) { abounce_request(MAIL_CLASS_PRIVATE, var_defer_service, BOUNCE_CMD_WARN, - flags, queue, id, encoding, sender, dsn_envid, dsn_ret, - callback, context); + flags, queue, id, encoding, smtputf8, sender, dsn_envid, + dsn_ret, callback, context); } /* atrace_flush - asynchronous trace flush */ void atrace_flush(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - ABOUNCE_FN callback, char *context) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, ABOUNCE_FN callback, char *context) { abounce_request(MAIL_CLASS_PRIVATE, var_trace_service, BOUNCE_CMD_TRACE, - flags, queue, id, encoding, sender, dsn_envid, dsn_ret, - callback, context); + flags, queue, id, encoding, smtputf8, sender, dsn_envid, + dsn_ret, callback, context); } diff --git a/postfix/src/global/abounce.h b/postfix/src/global/abounce.h index dc4264b6b..18141be21 100644 --- a/postfix/src/global/abounce.h +++ b/postfix/src/global/abounce.h @@ -21,13 +21,13 @@ */ typedef void (*ABOUNCE_FN) (int, char *); -extern void abounce_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); -extern void adefer_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); -extern void adefer_warn(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); -extern void atrace_flush(int, const char *, const char *, const char *, const char *, const char *, int, ABOUNCE_FN, char *); +extern void abounce_flush(int, const char *, const char *, const char *, int, const char *, const char *, int, ABOUNCE_FN, char *); +extern void adefer_flush(int, const char *, const char *, const char *, int, const char *, const char *, int, ABOUNCE_FN, char *); +extern void adefer_warn(int, const char *, const char *, const char *, int, const char *, const char *, int, ABOUNCE_FN, char *); +extern void atrace_flush(int, const char *, const char *, const char *, int, const char *, const char *, int, ABOUNCE_FN, char *); -extern void abounce_flush_verp(int, const char *, const char *, const char *, const char *, const char *, int, const char *, ABOUNCE_FN, char *); -extern void adefer_flush_verp(int, const char *, const char *, const char *, const char *, const char *, int, const char *, ABOUNCE_FN, char *); +extern void abounce_flush_verp(int, const char *, const char *, const char *, int, const char *, const char *, int, const char *, ABOUNCE_FN, char *); +extern void adefer_flush_verp(int, const char *, const char *, const char *, int, const char *, const char *, int, const char *, ABOUNCE_FN, char *); /* LICENSE /* .ad diff --git a/postfix/src/global/bounce.c b/postfix/src/global/bounce.c index e246ce3ea..94e7df75b 100644 --- a/postfix/src/global/bounce.c +++ b/postfix/src/global/bounce.c @@ -14,33 +14,36 @@ /* const char *relay; /* DSN *dsn; /* -/* int bounce_flush(flags, queue, id, encoding, sender, +/* int bounce_flush(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; /* -/* int bounce_flush_verp(flags, queue, id, encoding, sender, -/* dsn_envid, dsn_ret, verp_delims) +/* int bounce_flush_verp(flags, queue, id, encoding, smtputf8, +/* sender, dsn_envid, dsn_ret, verp_delims) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; /* const char *verp_delims; /* -/* int bounce_one(flags, queue, id, encoding, sender, envid, ret, -/* stats, recipient, relay, dsn) +/* int bounce_one(flags, queue, id, encoding, smtputf8, sender, +/* dsn_envid, ret, stats, recipient, relay, dsn) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; @@ -62,12 +65,13 @@ /* RECIPIENT *rcpt; /* const char *relay; /* -/* int bounce_one_intern(flags, queue, id, encoding, sender, envid, ret, -/* stats, recipient, relay, dsn) +/* int bounce_one_intern(flags, queue, id, encoding, smtputf8, sender, +/* dsn_envid, ret, stats, recipient, relay, dsn) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; @@ -147,6 +151,8 @@ /* This information is used for syslogging only. /* .IP encoding /* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}. +/* .IP smtputf8 +/* The level of SMTPUTF8 support (to be defined). /* .IP sender /* The sender envelope address. /* .IP dsn_envid @@ -233,7 +239,7 @@ int bounce_append(int flags, const char *id, MSG_STATS *stats, * DSN filter (Postfix 2.12). */ if (delivery_status_filter != 0 - && (dsn_res = dsn_filter_lookup(delivery_status_filter, &my_dsn)) != 0) { + && (dsn_res = dsn_filter_lookup(delivery_status_filter, &my_dsn)) != 0) { if (dsn_res->status[0] == '4') return (defer_append_intern(flags, id, stats, rcpt, relay, dsn_res)); my_dsn = *dsn_res; @@ -335,8 +341,9 @@ int bounce_append_intern(int flags, const char *id, MSG_STATS *stats, /* bounce_flush - flush the bounce log and deliver to the sender */ int bounce_flush(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret) { /* @@ -351,6 +358,7 @@ int bounce_flush(int flags, const char *queue, const char *id, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, @@ -367,9 +375,9 @@ int bounce_flush(int flags, const char *queue, const char *id, /* bounce_flush_verp - verpified notification */ int bounce_flush_verp(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - const char *verp_delims) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, const char *verp_delims) { /* @@ -384,6 +392,7 @@ int bounce_flush_verp(int flags, const char *queue, const char *id, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, @@ -401,9 +410,9 @@ int bounce_flush_verp(int flags, const char *queue, const char *id, /* bounce_one - send notice for one recipient */ int bounce_one(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - MSG_STATS *stats, RECIPIENT *rcpt, + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn) { DSN my_dsn = *dsn; @@ -421,22 +430,23 @@ int bounce_one(int flags, const char *queue, const char *id, * DSN filter (Postfix 2.12). */ if (delivery_status_filter != 0 - && (dsn_res = dsn_filter_lookup(delivery_status_filter, &my_dsn)) != 0) { + && (dsn_res = dsn_filter_lookup(delivery_status_filter, &my_dsn)) != 0) { if (dsn_res->status[0] == '4') return (defer_append_intern(flags, id, stats, rcpt, relay, dsn_res)); my_dsn = *dsn_res; } - return (bounce_one_intern(flags, queue, id, encoding, sender, dsn_envid, - dsn_ret, stats, rcpt, relay, &my_dsn)); + return (bounce_one_intern(flags, queue, id, encoding, smtputf8, sender, + dsn_envid, dsn_ret, stats, rcpt, relay, &my_dsn)); } /* bounce_one_intern - send notice for one recipient */ int bounce_one_intern(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - MSG_STATS *stats, RECIPIENT *rcpt, - const char *relay, DSN *dsn) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, MSG_STATS *stats, + RECIPIENT *rcpt, const char *relay, + DSN *dsn) { DSN my_dsn = *dsn; int status; @@ -489,6 +499,7 @@ int bounce_one_intern(int flags, const char *queue, const char *id, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, diff --git a/postfix/src/global/bounce.h b/postfix/src/global/bounce.h index b72503edb..e2d67bd3a 100644 --- a/postfix/src/global/bounce.h +++ b/postfix/src/global/bounce.h @@ -27,11 +27,11 @@ */ extern int bounce_append(int, const char *, MSG_STATS *, RECIPIENT *, const char *, DSN *); -extern int bounce_flush(int, const char *, const char *, const char *, +extern int bounce_flush(int, const char *, const char *, const char *, int, const char *, const char *, int); -extern int bounce_flush_verp(int, const char *, const char *, const char *, +extern int bounce_flush_verp(int, const char *, const char *, const char *, int, const char *, const char *, int, const char *); -extern int bounce_one(int, const char *, const char *, const char *, +extern int bounce_one(int, const char *, const char *, const char *, int, const char *, const char *, int, MSG_STATS *, RECIPIENT *, const char *, DSN *); @@ -79,7 +79,7 @@ extern DSN_FILTER *delivery_status_filter; extern int bounce_append_intern(int, const char *, MSG_STATS *, RECIPIENT *, const char *, DSN *); extern int bounce_one_intern(int, const char *, const char *, const char *, - const char *, const char *, + int, const char *, const char *, int, MSG_STATS *, RECIPIENT *, const char *, DSN *); diff --git a/postfix/src/global/cleanup_strflags.c b/postfix/src/global/cleanup_strflags.c index d2a687c83..11c7e0881 100644 --- a/postfix/src/global/cleanup_strflags.c +++ b/postfix/src/global/cleanup_strflags.c @@ -53,6 +53,7 @@ static struct cleanup_flag_map cleanup_flag_map[] = { CLEANUP_FLAG_MAP_OK, "enable_address_mapping", CLEANUP_FLAG_MILTER, "enable_milters", CLEANUP_FLAG_SMTP_REPLY, "enable_smtp_reply", + CLEANUP_FLAG_SMTPUTF8, "smtputf8_requested", }; /* cleanup_strflags - map flags code to printable string */ diff --git a/postfix/src/global/cleanup_user.h b/postfix/src/global/cleanup_user.h index 0a098d3da..a4de82a65 100644 --- a/postfix/src/global/cleanup_user.h +++ b/postfix/src/global/cleanup_user.h @@ -23,6 +23,8 @@ #define CLEANUP_FLAG_MAP_OK (1<<5) /* Ok to map addresses */ #define CLEANUP_FLAG_MILTER (1<<6) /* Enable Milter applications */ #define CLEANUP_FLAG_SMTP_REPLY (1<<7) /* Enable SMTP reply */ +#define CLEANUP_FLAG_SMTPUTF8 (1<<8) /* SMTPUTF8 requested */ +#define CLEANUP_FLAG_AUTOUTF8 (1<<9) /* Autodetect SMTPUTF8 */ #define CLEANUP_FLAG_FILTER_ALL (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_MILTER) /* diff --git a/postfix/src/global/defer.c b/postfix/src/global/defer.c index 7ca6071d4..110d2fc91 100644 --- a/postfix/src/global/defer.c +++ b/postfix/src/global/defer.c @@ -14,32 +14,35 @@ /* const char *relay; /* DSN *dsn; /* -/* int defer_flush(flags, queue, id, encoding, sender, +/* int defer_flush(flags, queue, id, encoding, smtputf8, sender, /* dsn_envid, dsn_ret) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; /* -/* int defer_warn(flags, queue, id, encoding, sender, -/* dsn_envid, dsn_ret) +/* int defer_warn(flags, queue, id, encoding, smtputf8, sender, + dsn_envid, dsn_ret) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; /* -/* int defer_one(flags, queue, id, encoding, sender, envid, ret, -/* stats, recipient, relay, dsn) +/* int defer_one(flags, queue, id, encoding, smtputf8, sender, +/* dsn_envid, ret, stats, recipient, relay, dsn) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; +/* int smtputf8; /* const char *sender; /* const char *dsn_envid; /* int dsn_ret; @@ -125,6 +128,8 @@ /* Delivery status. See dsn(3). The specified action is ignored. /* .IP encoding /* The body content encoding: MAIL_ATTR_ENC_{7BIT,8BIT,NONE}. +/* .IP smtputf8 +/* The level of SMTPUTF8 support (to be defined). /* .IP sender /* The sender envelope address. /* .IP dsn_envid @@ -289,8 +294,9 @@ int defer_append_intern(int flags, const char *id, MSG_STATS *stats, /* defer_flush - flush the defer log and deliver to the sender */ int defer_flush(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret) + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret) { flags |= BOUNCE_FLAG_DELRCPT; @@ -300,6 +306,7 @@ int defer_flush(int flags, const char *queue, const char *id, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, @@ -314,8 +321,8 @@ int defer_flush(int flags, const char *queue, const char *id, * do not flush the log */ int defer_warn(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *envid, int dsn_ret) + const char *encoding, int smtputf8, + const char *sender, const char *envid, int dsn_ret) { if (mail_command_client(MAIL_CLASS_PRIVATE, var_defer_service, ATTR_TYPE_INT, MAIL_ATTR_NREQ, BOUNCE_CMD_WARN, @@ -323,6 +330,7 @@ int defer_warn(int flags, const char *queue, const char *id, ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, dsn_ret, @@ -336,9 +344,9 @@ int defer_warn(int flags, const char *queue, const char *id, /* defer_one - defer mail for one recipient */ int defer_one(int flags, const char *queue, const char *id, - const char *encoding, const char *sender, - const char *dsn_envid, int dsn_ret, - MSG_STATS *stats, RECIPIENT *rcpt, + const char *encoding, int smtputf8, + const char *sender, const char *dsn_envid, + int dsn_ret, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn) { DSN my_dsn = *dsn; @@ -358,9 +366,9 @@ int defer_one(int flags, const char *queue, const char *id, if (delivery_status_filter != 0 && (dsn_res = dsn_filter_lookup(delivery_status_filter, &my_dsn)) != 0) { if (dsn_res->status[0] == '5') - return (bounce_one_intern(flags, queue, id, encoding, sender, - dsn_envid, dsn_ret, stats, rcpt, - relay, dsn_res)); + return (bounce_one_intern(flags, queue, id, encoding, smtputf8, + sender, dsn_envid, dsn_ret, stats, + rcpt, relay, dsn_res)); my_dsn = *dsn_res; } return (defer_append_intern(flags, id, stats, rcpt, relay, &my_dsn)); diff --git a/postfix/src/global/defer.h b/postfix/src/global/defer.h index 90f94e20d..a015052f5 100644 --- a/postfix/src/global/defer.h +++ b/postfix/src/global/defer.h @@ -21,11 +21,11 @@ */ extern int defer_append(int, const char *, MSG_STATS *, RECIPIENT *, const char *, DSN *); -extern int defer_flush(int, const char *, const char *, const char *, +extern int defer_flush(int, const char *, const char *, const char *, int, const char *, const char *, int); -extern int defer_warn(int, const char *, const char *, const char *, +extern int defer_warn(int, const char *, const char *, const char *, int, const char *, const char *, int); -extern int defer_one(int, const char *, const char *, const char *, +extern int defer_one(int, const char *, const char *, const char *, int, const char *, const char *, int, MSG_STATS *, RECIPIENT *, const char *, DSN *); diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index 0eaa45ddf..01b70b942 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -105,6 +105,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, ATTR_TYPE_LONG, MAIL_ATTR_SIZE, request->data_size, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, nexthop, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, request->encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, request->smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, request->sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, request->dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, request->dsn_ret, diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c index e32e82fb9..1eccd7d21 100644 --- a/postfix/src/global/deliver_request.c +++ b/postfix/src/global/deliver_request.c @@ -208,6 +208,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) static VSTRING *dsn_envid; static RCPT_BUF *rcpt_buf; int rcpt_count; + int smtputf8; int dsn_ret; /* @@ -247,6 +248,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) 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_INT, MAIL_ATTR_SMTPUTF8, &smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, address, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, &dsn_ret, @@ -265,7 +267,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) ATTR_TYPE_STR, MAIL_ATTR_LOG_IDENT, log_ident, ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context, ATTR_TYPE_INT, MAIL_ATTR_RCPT_COUNT, &rcpt_count, - ATTR_TYPE_END) != 22) { + ATTR_TYPE_END) != 23) { msg_warn("%s: error receiving common attributes", myname); return (-1); } @@ -281,6 +283,8 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) request->queue_id = mystrdup(vstring_str(queue_id)); request->nexthop = mystrdup(vstring_str(nexthop)); request->encoding = mystrdup(vstring_str(encoding)); + /* Fix 20140708: dedicated smtputf8 attribute with its own flags. */ + request->smtputf8 = smtputf8; request->sender = mystrdup(vstring_str(address)); request->client_name = mystrdup(vstring_str(client_name)); request->client_addr = mystrdup(vstring_str(client_addr)); diff --git a/postfix/src/global/deliver_request.h b/postfix/src/global/deliver_request.h index d2ca7719d..8ab36fc1a 100644 --- a/postfix/src/global/deliver_request.h +++ b/postfix/src/global/deliver_request.h @@ -36,6 +36,7 @@ typedef struct DELIVER_REQUEST { long data_size; /* message size */ char *nexthop; /* next hop name */ char *encoding; /* content encoding */ + int smtputf8; /* SMTPUTF8 level */ char *sender; /* envelope sender */ MSG_STATS msg_stats; /* time profile */ RECIPIENT_LIST rcpt_list; /* envelope recipients */ diff --git a/postfix/src/global/dict_ldap.c b/postfix/src/global/dict_ldap.c index ba603a604..0b7bf8027 100644 --- a/postfix/src/global/dict_ldap.c +++ b/postfix/src/global/dict_ldap.c @@ -1340,7 +1340,7 @@ static const char *dict_ldap_lookup(DICT *dict, const char *name) /* * Don't frustrate future attempts to make Postfix UTF-8 transparent. */ - if (!valid_utf_8(name, strlen(name))) { + if (!valid_utf8_string(name, strlen(name))) { if (msg_verbose) msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", myname, dict_ldap->parser->name, name); diff --git a/postfix/src/global/dict_sqlite.c b/postfix/src/global/dict_sqlite.c index 8eb0da2f7..9f68a0d97 100644 --- a/postfix/src/global/dict_sqlite.c +++ b/postfix/src/global/dict_sqlite.c @@ -165,7 +165,7 @@ static const char *dict_sqlite_lookup(DICT *dict, const char *name) /* * Don't frustrate future attempts to make Postfix UTF-8 transparent. */ - if (!valid_utf_8(name, strlen(name))) { + if (!valid_utf8_string(name, strlen(name))) { if (msg_verbose) msg_info("%s: %s: Skipping lookup of non-UTF-8 key '%s'", myname, dict_sqlite->parser->name, name); diff --git a/postfix/src/global/ehlo_mask.c b/postfix/src/global/ehlo_mask.c index 9c60dc749..1671beb3e 100644 --- a/postfix/src/global/ehlo_mask.c +++ b/postfix/src/global/ehlo_mask.c @@ -18,6 +18,7 @@ /* #define EHLO_MASK_XFORWARD (1<<9) /* #define EHLO_MASK_ENHANCEDSTATUSCODES (1<<10) /* #define EHLO_MASK_DSN (1<<11) +/* #define EHLO_MASK_SMTPUTF8 (1<<12) /* #define EHLO_MASK_SILENT (1<<15) /* /* int ehlo_mask(keyword_list) @@ -75,6 +76,7 @@ static const NAME_MASK ehlo_mask_table[] = { "STARTTLS", EHLO_MASK_STARTTLS, "ENHANCEDSTATUSCODES", EHLO_MASK_ENHANCEDSTATUSCODES, "DSN", EHLO_MASK_DSN, + "EHLO_MASK_SMTPUTF8", EHLO_MASK_SMTPUTF8, "SILENT-DISCARD", EHLO_MASK_SILENT, /* XXX In-band signaling */ 0, }; diff --git a/postfix/src/global/ehlo_mask.h b/postfix/src/global/ehlo_mask.h index 62256f112..3ef2a2d87 100644 --- a/postfix/src/global/ehlo_mask.h +++ b/postfix/src/global/ehlo_mask.h @@ -27,6 +27,7 @@ #define EHLO_MASK_XFORWARD (1<<9) #define EHLO_MASK_ENHANCEDSTATUSCODES (1<<10) #define EHLO_MASK_DSN (1<<11) +#define EHLO_MASK_SMTPUTF8 (1<<12) #define EHLO_MASK_SILENT (1<<15) extern int ehlo_mask(const char *); diff --git a/postfix/src/global/int_filt.c b/postfix/src/global/int_filt.c index a93a3e698..7c5f8b51f 100644 --- a/postfix/src/global/int_filt.c +++ b/postfix/src/global/int_filt.c @@ -14,13 +14,14 @@ /* the internal_mail_filter_classes configuration parameter. /* /* Specify one of the following: -/* .IP INT_FILT_MASK_NONE -/* Mail that must be excluded from inspection (address probes, etc.). -/* .IP INT_FILT_MASK_NOTIFY +/* .IP MAIL_SRC_MASK_NOTIFY /* Postmaster notifications from the smtpd(8) and smtp(8) /* protocol adapters. -/* .IP INT_FILT_MASK_BOUNCE +/* .IP MAIL_SRC_MASK_BOUNCE /* Delivery status notifications from the bounce(8) server. +/* .PP +/* Other MAIL_SRC_MASK_XXX arguments are permited but will +/* have no effect. /* DIAGNOSTICS /* Fatal: invalid mail category name. /* LICENSE @@ -47,6 +48,7 @@ #include #include +#include #include /* int_filt_flags - map mail class to submission flags */ @@ -54,8 +56,13 @@ int int_filt_flags(int class) { static const NAME_MASK table[] = { - INT_FILT_CLASS_NOTIFY, INT_FILT_MASK_NOTIFY, - INT_FILT_CLASS_BOUNCE, INT_FILT_MASK_BOUNCE, + MAIL_SRC_NAME_NOTIFY, MAIL_SRC_MASK_NOTIFY, + MAIL_SRC_NAME_BOUNCE, MAIL_SRC_MASK_BOUNCE, + MAIL_SRC_NAME_SENDMAIL, 0, + MAIL_SRC_NAME_SMTPD, 0, + MAIL_SRC_NAME_QMQPD, 0, + MAIL_SRC_NAME_FORWARD, 0, + MAIL_SRC_NAME_VERIFY, 0, 0, }; int filtered_classes = 0; diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index f7b2d2ce1..a6e479ff3 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -124,6 +124,9 @@ /* bool var_long_queue_ids; /* bool var_daemon_open_fatal; /* char *var_dsn_filter; +/* int var_smtputf8_enable +/* int var_strict_smtputf8; +/* char *var_smtputf8_autoclass; /* /* void mail_params_init() /* @@ -316,6 +319,9 @@ bool var_multi_enable; bool var_long_queue_ids; bool var_daemon_open_fatal; char *var_dsn_filter; +int var_smtputf8_enable; +int var_strict_smtputf8; +char *var_smtputf8_autoclass; const char null_format_string[1] = ""; @@ -598,6 +604,7 @@ void mail_params_init() /* multi_instance_wrapper may have dependencies but not dependents. */ VAR_MULTI_WRAPPER, DEF_MULTI_WRAPPER, &var_multi_wrapper, 0, 0, VAR_DSN_FILTER, DEF_DSN_FILTER, &var_dsn_filter, 0, 0, + VAR_SMTPUTF8_AUTOCLASS, DEF_SMTPUTF8_AUTOCLASS, &var_smtputf8_autoclass, 1, 0, 0, }; static const CONFIG_STR_FN_TABLE function_str_defaults_2[] = { @@ -659,6 +666,8 @@ void mail_params_init() VAR_CYRUS_SASL_AUTHZID, DEF_CYRUS_SASL_AUTHZID, &var_cyrus_sasl_authzid, VAR_MULTI_ENABLE, DEF_MULTI_ENABLE, &var_multi_enable, VAR_LONG_QUEUE_IDS, DEF_LONG_QUEUE_IDS, &var_long_queue_ids, + VAR_SMTPUTF8_ENABLE, DEF_SMTPUTF8_ENABLE, &var_smtputf8_enable, + VAR_STRICT_SMTPUTF8, DEF_STRICT_SMTPUTF8, &var_strict_smtputf8, 0, }; const char *cp; @@ -734,6 +743,16 @@ void mail_params_init() dict_db_cache_size = var_db_read_buf; dict_lmdb_map_size = var_lmdb_map_size; inet_windowsize = var_inet_windowsize; + temp_utf8_kludge = var_smtputf8_enable; + + /* + * Report run-time versus compile-time discrepancies. + */ +#ifdef NO_IDNA + if (var_smtputf8_enable) + msg_warn("%s is true, but EAI support is not compiled in", + VAR_SMTPUTF8_ENABLE); +#endif /* * Variables whose defaults are determined at runtime, after other diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 877d89c03..3b402a708 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -3822,6 +3822,22 @@ extern char *var_shlib_dir; #endif extern char *var_meta_dir; + /* + * SMTPUTF8 support. + */ +#define VAR_SMTPUTF8_ENABLE "smtputf8_enable" +#define DEF_SMTPUTF8_ENABLE 0 +extern int var_smtputf8_enable; + +#define VAR_STRICT_SMTPUTF8 "strict_smtputf8" +#define DEF_STRICT_SMTPUTF8 0 +extern int var_strict_smtputf8; + +#define VAR_SMTPUTF8_AUTOCLASS "smtputf8_autodetect_classes" +#define DEF_SMTPUTF8_AUTOCLASS MAIL_SRC_NAME_SENDMAIL ", " \ + MAIL_SRC_NAME_VERIFY +extern char *var_smtputf8_autoclass; + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 976b12590..d9979ec2d 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -61,6 +61,32 @@ #define MAIL_SERVICE_DNSBLOG "dnsblog" #define MAIL_SERVICE_TLSPROXY "tlsproxy" + /* + * Mail source classes. Used to specify policy decisions for content + * inspection and SMTPUTF8 detection. + */ +#define MAIL_SRC_NAME_SENDMAIL "sendmail" /* sendmail(1) */ +#define MAIL_SRC_NAME_SMTPD "smtpd" /* smtpd(8) */ +#define MAIL_SRC_NAME_QMQPD "qmqpd" /* qmqpd(8) */ +#define MAIL_SRC_NAME_FORWARD "forward" /* local(8) forward/alias */ +#define MAIL_SRC_NAME_BOUNCE "bounce"/* bounce(8) */ +#define MAIL_SRC_NAME_NOTIFY "notify"/* protocol etc. errors */ +#define MAIL_SRC_NAME_VERIFY "verify"/* protocol etc. errors */ +#define MAIL_SRC_NAME_ALL "all" /* all sources */ + +#define MAIL_SRC_MASK_SENDMAIL (1<<0) /* sendmail(1) */ +#define MAIL_SRC_MASK_SMTPD (1<<1) /* smtpd(8) */ +#define MAIL_SRC_MASK_QMQPD (1<<2) /* qmqpd(8) */ +#define MAIL_SRC_MASK_FORWARD (1<<3) /* local(8) forward/alias */ +#define MAIL_SRC_MASK_BOUNCE (1<<4) /* bounce(8) */ +#define MAIL_SRC_MASK_NOTIFY (1<<5) /* protocol etc. errors */ +#define MAIL_SRC_MASK_VERIFY (1<<6) /* protocol etc. errors */ + +#define MAIL_SRC_MASK_ALL \ + ( MAIL_SRC_MASK_SENDMAIL | MAIL_SRC_MASK_SMTPD \ + | MAIL_SRC_MASK_QMQPD | MAIL_SRC_MASK_FORWARD \ + | MAIL_SRC_MASK_BOUNCE | MAIL_SRC_MASK_NOTIFY) + /* * Well-known socket or FIFO directories. The main difference is in file * access permissions. @@ -244,6 +270,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_DSN_RET "ret_flags" /* dsn full/headers */ #define MAIL_ATTR_DSN_NOTIFY "notify_flags" /* dsn notify flags */ #define MAIL_ATTR_DSN_ORCPT "dsn_orig_rcpt" /* dsn original recipient */ +#define MAIL_ATTR_SMTPUTF8 "smtputf8" /* RFC6531 support */ /* * TLSPROXY support. diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 48e87fe72..8c24fd99c 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20140709" +#define MAIL_RELEASE_DATE "20140713" #define MAIL_VERSION_NUMBER "2.12" #ifdef SNAPSHOT diff --git a/postfix/src/global/mime_state.c b/postfix/src/global/mime_state.c index bac033d16..71cd14989 100644 --- a/postfix/src/global/mime_state.c +++ b/postfix/src/global/mime_state.c @@ -129,11 +129,6 @@ /* .IP MIME_OPT_REPORT_NESTING /* Report errors that set the MIME_ERR_NESTING error flag /* (see above). -/* .IP MIME_OPT_RECURSE_ALL_MESSAGE -/* Recurse into message/anything types other than message/rfc822. -/* This feature can detect "bad" information in headers of -/* message/partial and message/external-body types. It must -/* not be used with 8-bit -> 7-bit MIME transformations. /* .IP MIME_OPT_DOWNGRADE /* Transform content that claims to be 8-bit into quoted-printable. /* Where appropriate, update Content-Transfer-Encoding: message @@ -335,6 +330,7 @@ struct MIME_STATE { #define MIME_STYPE_RFC822 2 #define MIME_STYPE_PARTIAL 3 #define MIME_STYPE_EXTERN_BODY 4 +#define MIME_STYPE_GLOBAL 5 /* * MIME parser states. We steal from the public interface. @@ -591,6 +587,8 @@ static void mime_state_content_type(MIME_STATE *state, state->curr_stype = MIME_STYPE_PARTIAL; else if (TOKEN_MATCH(state->token[2], "external-body")) state->curr_stype = MIME_STYPE_EXTERN_BODY; + else if (TOKEN_MATCH(state->token[2], "global")) + state->curr_stype = MIME_STYPE_GLOBAL; } return; } @@ -963,8 +961,14 @@ int mime_state_update(MIME_STATE *state, int rec_type, if (len == 0) { state->body_offset = 0; /* XXX */ if (state->curr_ctype == MIME_CTYPE_MESSAGE) { - if (state->curr_stype == MIME_STYPE_RFC822 - || (state->static_flags & MIME_OPT_RECURSE_ALL_MESSAGE)) + if (state->curr_stype == MIME_STYPE_RFC822) + SET_MIME_STATE(state, MIME_STATE_NESTED, + MIME_CTYPE_TEXT, MIME_STYPE_PLAIN, + MIME_ENC_7BIT, MIME_ENC_7BIT); + else if (state->curr_stype == MIME_STYPE_GLOBAL + && ((state->static_flags & MIME_OPT_DOWNGRADE) == 0 + || state->curr_domain == MIME_ENC_7BIT)) + /* XXX EAI: inspect encoded message/global. */ SET_MIME_STATE(state, MIME_STATE_NESTED, MIME_CTYPE_TEXT, MIME_STYPE_PLAIN, MIME_ENC_7BIT, MIME_ENC_7BIT); diff --git a/postfix/src/global/post_mail.c b/postfix/src/global/post_mail.c index 22deb4fdb..230f4c3c1 100644 --- a/postfix/src/global/post_mail.c +++ b/postfix/src/global/post_mail.c @@ -6,28 +6,28 @@ /* SYNOPSIS /* #include /* -/* VSTREAM *post_mail_fopen(sender, recipient, filter_class, trace_flags, +/* VSTREAM *post_mail_fopen(sender, recipient, source_class, trace_flags, /* queue_id) /* const char *sender; /* const char *recipient; -/* int filter_class; +/* int source_class; /* int trace_flags; /* VSTRING *queue_id; /* /* VSTREAM *post_mail_fopen_nowait(sender, recipient, -/* filter_class, trace_flags, queue_id) +/* source_class, trace_flags, queue_id) /* const char *sender; /* const char *recipient; -/* int filter_class; +/* int source_class; /* int trace_flags; /* VSTRING *queue_id; /* /* void post_mail_fopen_async(sender, recipient, -/* filter_class, trace_flags, +/* source_class, trace_flags, /* queue_id, notify, context) /* const char *sender; /* const char *recipient; -/* int filter_class; +/* int source_class; /* int trace_flags; /* VSTRING *queue_id; /* void (*notify)(VSTREAM *stream, char *context); @@ -95,11 +95,12 @@ /* .IP recipient /* The recipient envelope address. It is up to the application /* to produce To: headers. -/* .IP filter_class -/* The internal mail filtering class, as defined in -/* \fB\fR. Depending on the setting of the -/* internal_mail_filter_classes parameter the message will or -/* won't be subject to content inspection. +/* .IP source_class +/* The message source class, as defined in \fB\fR. +/* Depending on the setting of the internal_mail_source_classes +/* and smtputf8_autodetect_classes parameters, the message +/* will or won't be subject to content inspection or SMTPUTF8 +/* autodetection. /* .IP trace_flags /* Message tracing flags as specified in \fB\fR. /* .IP queue_id @@ -171,7 +172,7 @@ typedef struct { char *sender; char *recipient; - int filter_class; + int source_class; int trace_flags; POST_MAIL_NOTIFY notify; void *context; @@ -183,14 +184,15 @@ typedef struct { static void post_mail_init(VSTREAM *stream, const char *sender, const char *recipient, - int filter_class, int trace_flags, + int source_class, int trace_flags, VSTRING *queue_id) { VSTRING *id = queue_id ? queue_id : vstring_alloc(100); struct timeval now; const char *date; - int cleanup_flags = - int_filt_flags(filter_class) | CLEANUP_FLAG_MASK_INTERNAL; + int cleanup_flags = + int_filt_flags(source_class) | CLEANUP_FLAG_MASK_INTERNAL + | smtputf8_autodetect(source_class); GETTIMEOFDAY(&now); date = mail_date(now.tv_sec); @@ -235,13 +237,13 @@ static void post_mail_init(VSTREAM *stream, const char *sender, /* post_mail_fopen - prepare for posting a message */ VSTREAM *post_mail_fopen(const char *sender, const char *recipient, - int filter_class, int trace_flags, + int source_class, int trace_flags, VSTRING *queue_id) { VSTREAM *stream; stream = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); - post_mail_init(stream, sender, recipient, filter_class, trace_flags, + post_mail_init(stream, sender, recipient, source_class, trace_flags, queue_id); return (stream); } @@ -249,14 +251,14 @@ VSTREAM *post_mail_fopen(const char *sender, const char *recipient, /* post_mail_fopen_nowait - prepare for posting a message */ VSTREAM *post_mail_fopen_nowait(const char *sender, const char *recipient, - int filter_class, int trace_flags, + int source_class, int trace_flags, VSTRING *queue_id) { VSTREAM *stream; if ((stream = mail_connect(MAIL_CLASS_PUBLIC, var_cleanup_service, BLOCKING)) != 0) - post_mail_init(stream, sender, recipient, filter_class, trace_flags, + post_mail_init(stream, sender, recipient, source_class, trace_flags, queue_id); return (stream); } @@ -282,7 +284,7 @@ static void post_mail_open_event(int event, char *context) event_disable_readwrite(vstream_fileno(state->stream)); non_blocking(vstream_fileno(state->stream), BLOCKING); post_mail_init(state->stream, state->sender, - state->recipient, state->filter_class, + state->recipient, state->source_class, state->trace_flags, state->queue_id); myfree(state->sender); myfree(state->recipient); @@ -333,7 +335,7 @@ static void post_mail_open_event(int event, char *context) /* post_mail_fopen_async - prepare for posting a message */ void post_mail_fopen_async(const char *sender, const char *recipient, - int filter_class, int trace_flags, + int source_class, int trace_flags, VSTRING *queue_id, void (*notify) (VSTREAM *, void *), void *context) @@ -345,7 +347,7 @@ void post_mail_fopen_async(const char *sender, const char *recipient, state = (POST_MAIL_STATE *) mymalloc(sizeof(*state)); state->sender = mystrdup(sender); state->recipient = mystrdup(recipient); - state->filter_class = filter_class; + state->source_class = source_class; state->trace_flags = trace_flags; state->notify = notify; state->context = context; diff --git a/postfix/src/global/post_mail.h b/postfix/src/global/post_mail.h index b76a2510e..f679ba4ac 100644 --- a/postfix/src/global/post_mail.h +++ b/postfix/src/global/post_mail.h @@ -21,7 +21,7 @@ * Global library. */ #include -#include +#include /* * External interface. diff --git a/postfix/src/global/rec_type.h b/postfix/src/global/rec_type.h index f6668cdc8..aab4ab364 100644 --- a/postfix/src/global/rec_type.h +++ b/postfix/src/global/rec_type.h @@ -124,12 +124,13 @@ * * See also: REC_TYPE_PTR_FORMAT below. */ -#define REC_TYPE_SIZE_FORMAT "%15ld %15ld %15ld %15ld %15ld" +#define REC_TYPE_SIZE_FORMAT "%15ld %15ld %15ld %15ld %15ld %15ld" #define REC_TYPE_SIZE_CAST1 long /* Vmailer extra offs - data offs */ #define REC_TYPE_SIZE_CAST2 long /* Postfix 1.0 data offset */ #define REC_TYPE_SIZE_CAST3 long /* Postfix 1.0 recipient count */ #define REC_TYPE_SIZE_CAST4 long /* Postfix 2.1 qmgr flags */ #define REC_TYPE_SIZE_CAST5 long /* Postfix 2.4 content length */ +#define REC_TYPE_SIZE_CAST6 long /* Postfix 2.12 smtputf8 flags */ /* * The warn record specifies when the next warning that the message was diff --git a/postfix/src/global/smtputf8.c b/postfix/src/global/smtputf8.c new file mode 100644 index 000000000..d86e08421 --- /dev/null +++ b/postfix/src/global/smtputf8.c @@ -0,0 +1,95 @@ +/*++ +/* NAME +/* smtputf8 3 +/* SUMMARY +/* SMTPUTF8 support +/* SYNOPSIS +/* #include +/* +/* int smtputf8_autodetect(class) +/* int class; +/* DESCRIPTION +/* smtputf8_autodetect() determines whether the cleanup server +/* should perform SMTPUTF8 detection, depending on the declared +/* source class and the setting of the smtputf8_autodetect_classes +/* configuration parameter. +/* +/* Specify one of the following: +/* .IP MAIL_SRC_MASK_SENDMAIL +/* Submission with the Postfix sendmail(1) command. +/* .IP MAIL_SRC_MASK_SMTPD +/* Mail received with the smtpd(8) daemon. +/* .IP MAIL_SRC_MASK_QMQPD +/* Mail received with the qmqpd(8) daemon. +/* .IP MAIL_SRC_MASK_FORWARD +/* Local forwarding or aliasing. +/* .IP MAIL_SRC_MASK_BOUNCE +/* Submission by the bounce(8) daemon. +/* .IP MAIL_SRC_MASK_NOTIFY +/* Postmaster notification from the smtp(8) or smtpd(8) daemon. +/* .IP MAIL_SRC_MASK_VERIFY +/* Address verification probe. +/* DIAGNOSTICS +/* Panic: no valid class argument. +/* +/* Specify one of the following: +/* Warning: the smtputf8_autodetect_classes parameter specifies +/* an invalid source category name. +/* 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 +/*--*/ + +/* System library. */ + +#include + +/* Utility library. */ + +#include +#include + +/* Global library. */ + +#include +#include +#include +#include + +/* smtputf8_autodetect - enable SMTPUTF8 autodetection */ + +int smtputf8_autodetect(int class) +{ + const char myname[] = "smtputf8_autodetect"; + static const NAME_MASK table[] = { + MAIL_SRC_NAME_SENDMAIL, MAIL_SRC_MASK_SENDMAIL, + MAIL_SRC_NAME_SMTPD, MAIL_SRC_MASK_SMTPD, + MAIL_SRC_NAME_QMQPD, MAIL_SRC_MASK_QMQPD, + MAIL_SRC_NAME_FORWARD, MAIL_SRC_MASK_FORWARD, + MAIL_SRC_NAME_BOUNCE, MAIL_SRC_MASK_BOUNCE, + MAIL_SRC_NAME_NOTIFY, MAIL_SRC_MASK_NOTIFY, + MAIL_SRC_NAME_VERIFY, MAIL_SRC_MASK_VERIFY, + MAIL_SRC_NAME_ALL, MAIL_SRC_MASK_ALL, + 0, + }; + int autodetect_classes = 0; + + if (class == 0 || (class & ~MAIL_SRC_MASK_ALL) != 0) + msg_panic("%s: bad source class: %d", myname, class); + if (*var_smtputf8_autoclass) { + autodetect_classes = + name_mask(VAR_SMTPUTF8_AUTOCLASS, table, var_smtputf8_autoclass); + if (autodetect_classes == 0) + msg_warn("%s: bad input: %s", VAR_SMTPUTF8_AUTOCLASS, + var_smtputf8_autoclass); + if (autodetect_classes & class) + return (CLEANUP_FLAG_AUTOUTF8); + } + return (0); +} diff --git a/postfix/src/global/smtputf8.h b/postfix/src/global/smtputf8.h new file mode 100644 index 000000000..1758fc887 --- /dev/null +++ b/postfix/src/global/smtputf8.h @@ -0,0 +1,111 @@ +#ifndef _SMTPUTF8_H_INCLUDED_ +#define _SMTPUTF8_H_INCLUDED_ + +/*++ +/* NAME +/* smtputf8 3h +/* SUMMARY +/* SMTPUTF8 support +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Avoiding chicken-and-egg problems during the initial SMTPUTF8 roll-out in + * environments with pre-existing mail flows that contain UTF8. + * + * Prior to SMTPUTF8, mail flows that contain UTF8 worked because the vast + * majority of MTAs is perfectly capable of handling UTF8 in addres + * localparts (and in headers), even if pre-SMTPUTF8 standards do not + * support this practice. + * + * When turning on Postfix SMTPUTF8 support for the first time, we don't want + * to suddenly break pre-existing mail flows that contain UTF8 because 1) a + * client does not request SMTPUTF8 support, and because 2) a down-stream + * MTA does not announce SMTPUTF8 support. + * + * While 1) is easy enough to avoid (keep accepting UTF8 in addres localparts + * just like Postfix has always done), 2) presents a thornier problem. The + * root cause of that problem is the need for SMTPUTF8 autodetection. + * + * What is SMTPUTF8 autodetection? Postfix cannot rely solely on the sender's + * declaration that a message requires SMTPUTF8 support, because UTF8 may be + * introduced during local processing (for example, the client hostname in + * Postfix's Received: header, adding @$myorigin or .$mydomain to an + * incomplete address, address rewriting, alias expansion, automatic BCC + * recipients, local forwarding, and changes made by header checks or Milter + * applications). + * + * In summary, after local processing has happened, Postfix may decide that a + * message requires SMTPUTF8 support, even when that message initially did + * not require SMTPUTF8 support. This could make the message undeliverable + * to destinations that do not support SMTPUTF8. In an environment with + * pre-existing mail flows that contain UTF8, we want to avoid disrupting + * those mail flows when rolling out SMTPUTF8 support. + * + * For the vast majority of sites, the simplest solution is to autodetect + * SMTPUTF8 support only for Postfix sendmail command-line submissions, at + * least as long as SMTPUTF8 support has not yet achieved wold domination. + * + * However, sites that add UTF8 content via local processing (see above) should + * autodetect SMTPUTF8 support for all email. + * + * smtputf8_autodetect() uses the setting of the smtputf8_autodetect_classes + * parameter, and the mail source classes defined in mail_params.h. + */ +extern int smtputf8_autodetect(int); + + /* + * The flag SMTPUTF8_FLAG_REQUESTED is raised on request by the sender, or + * when a queue file contains at least one UTF8 envelope recipient. + * + * The flag SMTPUTF8_FLAG_HEADER is raised when a queue file contains at least + * one UTF8 message header. + * + * The flag SMTPUTF8_FLAG_SENDER is raised when a queue file contains an UTF8 + * envelope sender. + * + * The three flags SMTPUTF8_FLAG_REQUESTED/HEADER/SENDER are stored in the + * queue file, the three flags are sent with delivery requests to Postfix + * delivery agents, and the three flags are sent with "flush" requests to + * the bounce daemon to ensure that the resulting notification message will + * have a content-transfer-encoding of 8bit. + * + * In the near future, mailing lists will have a mix of UTF8 and non-UTF8 + * subscribers. With the following flag, Postfix can require SMTPUTF8 + * delivery only when it is really required. + * + * The flag SMTPUTF8_FLAG_RECIPIENT is raised when a delivery request (NOT: + * message) contains at least one UTF8 envelope recipient. The flag is NOT + * stored in the queue file, and the flag sent in requests to the bounce + * daemon ONLY when bouncing a single recipient. The flag is used ONLY in + * requests to Postfix delivery agents, to give Postfix flexibility when + * delivering messages to non-SMTPUTF8 servers. + * + * If a delivery request has none of the flags SMTPUTF8_FLAG_RECIPIENT, + * SMTPUTF8_FLAG_SENDER, or SMTPUTF8_FLAG_HEADER, then the message can + * safely be delivered to a non-SMTPUTF8 server. + * + * To relax this requirement, implement RFC2047 header encoding in the Postfix + * SMTP client, and adjust the SMTPUTF8_MASK_ALWAYS macro. + */ +#define SMTPUTF8_FLAG_REQUESTED (1<<0) /* queue file/delivery/bounce request */ +#define SMTPUTF8_FLAG_HEADER (1<<1) /* queue file/delivery/bounce request */ +#define SMTPUTF8_FLAG_SENDER (1<<2) /* queue file/delivery/bounce request */ +#define SMTPUTF8_FLAG_RECIPIENT (1<<3) /* delivery request only */ + +#define SMTPUTF8_MASK_ALWAYS (SMTPUTF8_FLAG_HEADER | SMTPUTF8_FLAG_SENDER) + +/* 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 diff --git a/postfix/src/global/uxtext.c b/postfix/src/global/uxtext.c new file mode 100644 index 000000000..ccd0d84a8 --- /dev/null +++ b/postfix/src/global/uxtext.c @@ -0,0 +1,263 @@ +/*++ +/* NAME +/* uxtext 3 +/* SUMMARY +/* quote/unquote text, xtext style. +/* SYNOPSIS +/* #include +/* +/* VSTRING *uxtext_quote(quoted, unquoted, special) +/* VSTRING *quoted; +/* const char *unquoted; +/* const char *special; +/* +/* VSTRING *uxtext_quote_append(unquoted, quoted, special) +/* VSTRING *unquoted; +/* const char *quoted; +/* const char *special; +/* +/* VSTRING *uxtext_unquote(unquoted, quoted) +/* VSTRING *unquoted; +/* const char *quoted; +/* +/* VSTRING *uxtext_unquote_append(unquoted, quoted) +/* VSTRING *unquoted; +/* const char *quoted; +/* DESCRIPTION +/* uxtext_quote() takes a null-terminated UTF8 string and +/* replaces characters \, <33(10) and >126(10), as well as +/* characters specified with "special" with \x{XX}, XX being +/* a 2-6-digit uppercase hexadecimal equivalent. +/* +/* uxtext_quote_append() is like uxtext_quote(), but appends +/* the conversion result to the result buffer. +/* +/* uxtext_unquote() performs the opposite transformation. This +/* function understands lowercase, uppercase, and mixed case +/* \x{XX...} sequences. The result value is the unquoted +/* argument in case of success, a null pointer otherwise. +/* +/* uxtext_unquote_append() is like uxtext_unquote(), but appends +/* the conversion result to the result buffer. +/* BUGS +/* This module cannot process null characters in data. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Arnt Gulbrandsen +/* +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include + +/* Utility library. */ + +#include "msg.h" +#include "vstring.h" +#include "uxtext.h" + +/* Application-specific. */ + +#define STR(x) vstring_str(x) +#define LEN(x) VSTRING_LEN(x) + +/* uxtext_quote_append - append unquoted data to quoted data */ + +VSTRING *uxtext_quote_append(VSTRING *quoted, const char *unquoted, + const char *special) +{ + unsigned const char *cp; + int ch; + + for (cp = (unsigned const char *) unquoted; (ch = *cp) != 0; cp++) { + /* Fix 20140709: the '\' character must always be quoted. */ + if (ch != '\\' && ch > 32 && ch < 127 + && (*special == 0 || strchr(special, ch) == 0)) { + VSTRING_ADDCH(quoted, ch); + } else { + + /* + * had RFC6533 been written like 6531 and 6532, this else clause + * would be one line long. + */ + int unicode = 0; + int pick = 0; + + if (ch < 0x80) { + //0000 0000 - 0000 007 F 0x xxxxxx + unicode = ch; + } else if ((ch & 0xe0) == 0xc0) { + //0000 0080 - 0000 07 FF 110 xxxxx 10 xxxxxx + unicode = (ch & 0x1f); + pick = 1; + } else if ((ch & 0xf0) == 0xe0) { + //0000 0800 - 0000 FFFF 1110 xxxx 10 xxxxxx 10 xxxxxx + unicode = (ch & 0x0f); + pick = 2; + } else if ((ch & 0xf8) == 0xf0) { + //0001 0000 - 001 F FFFF 11110 xxx 10 xxxxxx 10 xxxxxx 10 xxxxxx + unicode = (ch & 0x07); + pick = 3; + } else if ((ch & 0xfc) == 0xf8) { + //0020 0000 - 03 FF FFFF 111110 xx 10 xxxxxx 10 xxxxxx...10 xxxxxx + unicode = (ch & 0x03); + pick = 4; + } else if ((ch & 0xfe) == 0xfc) { + //0400 0000 - 7 FFF FFFF 1111110 x 10 xxxxxx...10 xxxxxx + unicode = (ch & 0x01); + pick = 5; + } else { + return (0); + } + while (pick > 0) { + ch = *++cp; + if ((ch & 0xc0) != 0x80) + return (0); + unicode = unicode << 6 | (ch & 0x3f); + pick--; + } + vstring_sprintf_append(quoted, "\\x{%02X}", unicode); + } + } + VSTRING_TERMINATE(quoted); + return (quoted); +} + +/* uxtext_quote - unquoted data to quoted */ + +VSTRING *uxtext_quote(VSTRING *quoted, const char *unquoted, const char *special) +{ + VSTRING_RESET(quoted); + uxtext_quote_append(quoted, unquoted, special); + return (quoted); +} + +/* uxtext_unquote_append - quoted data to unquoted */ + +VSTRING *uxtext_unquote_append(VSTRING *unquoted, const char *quoted) +{ + const char *cp; + int ch; + + for (cp = quoted; (ch = *cp) != 0; cp++) { + if (ch == '\\' && cp[1] == 'x' && cp[2] == '{') { + cp += 2; + int unicode = 0; + + while ((ch = *++cp) != '}') { + if (ISDIGIT(ch)) + unicode = (unicode << 4) + (ch - '0'); + else if (ch >= 'a' && ch <= 'f') + unicode = (unicode << 4) + (ch - 'a' + 10); + else if (ch >= 'A' && ch <= 'F') + unicode = (unicode << 4) + (ch - 'A' + 10); + else + return (0); /* also covers the null + * terminator */ + if (unicode > 0x10ffff) + return (0); + } + + /* + * the following block is from + * https://github.com/aox/aox/blob/master/encodings/utf.cpp, with + * permission by the authors. + */ + if (unicode < 0x80) { + VSTRING_ADDCH(unquoted, (char) unicode); + } else if (unicode < 0x800) { + VSTRING_ADDCH(unquoted, 0xc0 | ((char) (unicode >> 6))); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode & 0x3f))); + } else if (unicode < 0x10000) { + VSTRING_ADDCH(unquoted, 0xe0 | ((char) (unicode >> 12))); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 6) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode & 0x3f))); + } else if (unicode < 0x200000) { + VSTRING_ADDCH(unquoted, 0xf0 | ((char) (unicode >> 18))); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 12) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 6) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode & 0x3f))); + } else if (unicode < 0x4000000) { + VSTRING_ADDCH(unquoted, 0xf8 | ((char) (unicode >> 24))); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 18) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 12) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 6) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode & 0x3f))); + } else { + VSTRING_ADDCH(unquoted, 0xfc | ((char) (unicode >> 30))); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 24) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 18) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 12) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode >> 6) & 0x3f)); + VSTRING_ADDCH(unquoted, 0x80 | ((char) (unicode & 0x3f))); + } + } else { + VSTRING_ADDCH(unquoted, ch); + } + } + VSTRING_TERMINATE(unquoted); + return (unquoted); +} + +/* uxtext_unquote - quoted data to unquoted */ + +VSTRING *uxtext_unquote(VSTRING *unquoted, const char *quoted) +{ + VSTRING_RESET(unquoted); + uxtext_unquote_append(unquoted, quoted); + return (unquoted); +} + +#ifdef TEST + + /* + * Proof-of-concept test program: convert to quoted and back. + */ +#include + +#define BUFLEN 1024 + +static ssize_t read_buf(VSTREAM *fp, VSTRING *buf) +{ + ssize_t len; + + VSTRING_RESET(buf); + len = vstream_fread(fp, STR(buf), vstring_avail(buf)); + VSTRING_AT_OFFSET(buf, len); /* XXX */ + VSTRING_TERMINATE(buf); + return (len); +} + +int main(int unused_argc, char **unused_argv) +{ + VSTRING *unquoted = vstring_alloc(BUFLEN); + VSTRING *quoted = vstring_alloc(100); + ssize_t len; + + while ((len = read_buf(VSTREAM_IN, unquoted)) > 0) { + uxtext_quote(quoted, STR(unquoted), "+="); + if (uxtext_unquote(unquoted, STR(quoted)) == 0) + msg_fatal("bad input: %.100s", STR(quoted)); + if (LEN(unquoted) != len) + msg_fatal("len %ld != unquoted len %ld", + (long) len, (long) LEN(unquoted)); + if (vstream_fwrite(VSTREAM_OUT, STR(unquoted), LEN(unquoted)) != LEN(unquoted)) + msg_fatal("write error: %m"); + } + vstream_fflush(VSTREAM_OUT); + vstring_free(unquoted); + vstring_free(quoted); + return (0); +} + +#endif diff --git a/postfix/src/global/uxtext.h b/postfix/src/global/uxtext.h new file mode 100644 index 000000000..761adf9e8 --- /dev/null +++ b/postfix/src/global/uxtext.h @@ -0,0 +1,38 @@ +#ifndef _UXTEXT_H_INCLUDED_ +#define _UXTEXT_H_INCLUDED_ + +/*++ +/* NAME +/* uxtext 3h +/* SUMMARY +/* quote/unquote text, RFC 6533 style. +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface. + */ +extern VSTRING *uxtext_quote(VSTRING *, const char *, const char *); +extern VSTRING *uxtext_quote_append(VSTRING *, const char *, const char *); +extern VSTRING *uxtext_unquote(VSTRING *, const char *); +extern VSTRING *uxtext_unquote_append(VSTRING *, 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 diff --git a/postfix/src/local/Makefile.in b/postfix/src/local/Makefile.in index 1471a6327..552b00efc 100644 --- a/postfix/src/local/Makefile.in +++ b/postfix/src/local/Makefile.in @@ -297,6 +297,7 @@ forward.o: ../../include/recipient_list.h forward.o: ../../include/record.h forward.o: ../../include/resolve_clnt.h forward.o: ../../include/sent.h +forward.o: ../../include/smtputf8.h forward.o: ../../include/stringops.h forward.o: ../../include/sys_defs.h forward.o: ../../include/tok822.h diff --git a/postfix/src/local/forward.c b/postfix/src/local/forward.c index fb7da4f2e..90843b3b0 100644 --- a/postfix/src/local/forward.c +++ b/postfix/src/local/forward.c @@ -79,6 +79,7 @@ #include #include #include +#include /* Application-specific. */ @@ -147,7 +148,9 @@ static FORWARD_INFO *forward_open(DELIVER_REQUEST *request, const char *sender) info->queue_id = mystrdup(STR(buffer)); GETTIMEOFDAY(&info->posting_time); -#define FORWARD_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_INTERNAL) +#define FORWARD_CLEANUP_FLAGS \ + (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_MASK_INTERNAL \ + | smtputf8_autodetect(MAIL_SRC_MASK_FORWARD)) attr_print(cleanup, ATTR_FLAG_NONE, ATTR_TYPE_INT, MAIL_ATTR_FLAGS, FORWARD_CLEANUP_FLAGS, diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c index 0da3b7025..6b82dd321 100644 --- a/postfix/src/local/local.c +++ b/postfix/src/local/local.c @@ -707,6 +707,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service) state.msg_attr.fp = rqst->fp; state.msg_attr.offset = rqst->data_offset; state.msg_attr.encoding = rqst->encoding; + state.msg_attr.smtputf8 = rqst->smtputf8; state.msg_attr.sender = rqst->sender; state.msg_attr.dsn_envid = rqst->dsn_envid; state.msg_attr.dsn_ret = rqst->dsn_ret; diff --git a/postfix/src/local/local.h b/postfix/src/local/local.h index 0e9656de4..4052000c9 100644 --- a/postfix/src/local/local.h +++ b/postfix/src/local/local.h @@ -72,6 +72,7 @@ typedef struct DELIVER_ATTR { char *queue_id; /* mail queue id */ long offset; /* data offset */ char *encoding; /* MIME encoding */ + int smtputf8; /* from delivery request */ const char *sender; /* taken from envelope */ char *dsn_envid; /* DSN envelope ID */ int dsn_ret; /* DSN headers/full */ @@ -134,7 +135,7 @@ typedef struct LOCAL_STATE { attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \ DSN_FROM_DSN_BUF(attr.why) #define BOUNCE_ONE_ATTR(attr) \ - attr.queue_name, attr.queue_id, attr.encoding, \ + attr.queue_name, attr.queue_id, attr.encoding, attr.smtputf8, \ attr.sender, attr.dsn_envid, attr.dsn_ret, \ &attr.msg_stats, &attr.rcpt, attr.relay, \ DSN_FROM_DSN_BUF(attr.why) diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in index 5d3bacc0d..34314f764 100644 --- a/postfix/src/master/Makefile.in +++ b/postfix/src/master/Makefile.in @@ -96,7 +96,6 @@ event_server.o: ../../include/deliver_request.h event_server.o: ../../include/dict.h event_server.o: ../../include/dsn.h event_server.o: ../../include/dsn_buf.h -event_server.o: ../../include/dsn_filter.h event_server.o: ../../include/events.h event_server.o: ../../include/htable.h event_server.o: ../../include/iostuff.h @@ -302,7 +301,6 @@ multi_server.o: ../../include/deliver_request.h multi_server.o: ../../include/dict.h multi_server.o: ../../include/dsn.h multi_server.o: ../../include/dsn_buf.h -multi_server.o: ../../include/dsn_filter.h multi_server.o: ../../include/events.h multi_server.o: ../../include/htable.h multi_server.o: ../../include/iostuff.h @@ -343,7 +341,6 @@ single_server.o: ../../include/deliver_request.h single_server.o: ../../include/dict.h single_server.o: ../../include/dsn.h single_server.o: ../../include/dsn_buf.h -single_server.o: ../../include/dsn_filter.h single_server.o: ../../include/events.h single_server.o: ../../include/htable.h single_server.o: ../../include/iostuff.h @@ -384,7 +381,6 @@ trigger_server.o: ../../include/deliver_request.h trigger_server.o: ../../include/dict.h trigger_server.o: ../../include/dsn.h trigger_server.o: ../../include/dsn_buf.h -trigger_server.o: ../../include/dsn_filter.h trigger_server.o: ../../include/events.h trigger_server.o: ../../include/htable.h trigger_server.o: ../../include/iostuff.h diff --git a/postfix/src/oqmgr/Makefile.in b/postfix/src/oqmgr/Makefile.in index 780061d71..09d52367c 100644 --- a/postfix/src/oqmgr/Makefile.in +++ b/postfix/src/oqmgr/Makefile.in @@ -168,6 +168,7 @@ qmgr_deliver.o: ../../include/mymalloc.h qmgr_deliver.o: ../../include/rcpt_print.h qmgr_deliver.o: ../../include/recipient_list.h qmgr_deliver.o: ../../include/scan_dir.h +qmgr_deliver.o: ../../include/smtputf8.h qmgr_deliver.o: ../../include/stringops.h qmgr_deliver.o: ../../include/sys_defs.h qmgr_deliver.o: ../../include/vbuf.h diff --git a/postfix/src/oqmgr/qmgr.h b/postfix/src/oqmgr/qmgr.h index 802ce12ee..6d61eb45b 100644 --- a/postfix/src/oqmgr/qmgr.h +++ b/postfix/src/oqmgr/qmgr.h @@ -298,6 +298,7 @@ struct QMGR_MESSAGE { char *sender; /* complete address */ char *dsn_envid; /* DSN envelope ID */ int dsn_ret; /* DSN headers/full */ + int smtputf8; /* requires unicode */ char *verp_delims; /* VERP delimiters */ char *filter_xport; /* filtering transport */ char *inspect_xport; /* inspecting transport */ diff --git a/postfix/src/oqmgr/qmgr_active.c b/postfix/src/oqmgr/qmgr_active.c index d93a2cd10..c3e446cb5 100644 --- a/postfix/src/oqmgr/qmgr_active.c +++ b/postfix/src/oqmgr/qmgr_active.c @@ -296,6 +296,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -306,6 +307,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -389,6 +391,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -441,6 +444,7 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -451,6 +455,7 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -466,6 +471,7 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, diff --git a/postfix/src/oqmgr/qmgr_deliver.c b/postfix/src/oqmgr/qmgr_deliver.c index ce81fd702..3a0e9f32e 100644 --- a/postfix/src/oqmgr/qmgr_deliver.c +++ b/postfix/src/oqmgr/qmgr_deliver.c @@ -71,6 +71,7 @@ #include #include #include +#include /* Application-specific. */ @@ -135,6 +136,16 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) MSG_STATS stats; char *sender; int flags; + int smtputf8 = message->smtputf8; + const char *addr; + + /* + * Todo: integrate with code up-stream that builds the delivery request. + */ + for (recipient = list.info; recipient < list.info + list.len; recipient++) + if (var_smtputf8_enable && (addr = recipient->address)[0] + && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) + smtputf8 |= SMTPUTF8_FLAG_RECIPIENT; /* * If variable envelope return path is requested, change prefix+@origin @@ -162,6 +173,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->cont_length, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, entry->queue->nexthop, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, message->smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, message->dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, message->dsn_ret, diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c index e2f923741..cb87d367b 100644 --- a/postfix/src/oqmgr/qmgr_message.c +++ b/postfix/src/oqmgr/qmgr_message.c @@ -168,6 +168,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name, message->sender = 0; message->dsn_envid = 0; message->dsn_ret = 0; + message->smtputf8 = 0; message->filter_xport = 0; message->inspect_xport = 0; message->redirect_addr = 0; @@ -516,10 +517,11 @@ static int qmgr_message_read(QMGR_MESSAGE *message) continue; if (rec_type == REC_TYPE_SIZE) { if (message->data_offset == 0) { - if ((count = sscanf(start, "%ld %ld %d %d %ld", + if ((count = sscanf(start, "%ld %ld %d %d %ld %d", &message->data_size, &message->data_offset, &nrcpt, &message->rflags, - &message->cont_length)) >= 3) { + &message->cont_length, + &message->smtputf8)) >= 3) { /* Postfix >= 1.0 (a.k.a. 20010228). */ if (message->data_offset <= 0 || message->data_size <= 0) { msg_warn("%s: invalid size record: %.100s", diff --git a/postfix/src/pickup/Makefile.in b/postfix/src/pickup/Makefile.in index ea876c22a..613cc8768 100644 --- a/postfix/src/pickup/Makefile.in +++ b/postfix/src/pickup/Makefile.in @@ -80,6 +80,7 @@ pickup.o: ../../include/record.h pickup.o: ../../include/safe_open.h pickup.o: ../../include/scan_dir.h pickup.o: ../../include/set_ugid.h +pickup.o: ../../include/smtputf8.h pickup.o: ../../include/stringops.h pickup.o: ../../include/sys_defs.h pickup.o: ../../include/vbuf.h diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 5fc5c1ca3..02f1608f4 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -139,6 +139,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -198,7 +199,7 @@ static int cleanup_service_error_reason(PICKUP_INFO *info, int status, */ if (reason == 0 || *reason == 0) msg_warn("%s: error writing %s: %s", - info->path, info->id, cleanup_strerror(status)); + info->path, info->id, cleanup_strerror(status)); return ((status & (CLEANUP_STAT_BAD | CLEANUP_STAT_RCPT)) ? REMOVE_MESSAGE_FILE : KEEP_MESSAGE_FILE); } @@ -465,6 +466,8 @@ static int pickup_file(PICKUP_INFO *info) /* As documented in postsuper(1). */ if (MAIL_IS_REQUEUED(info)) cleanup_flags &= ~CLEANUP_FLAG_MILTER; + else + cleanup_flags |= smtputf8_autodetect(MAIL_SRC_MASK_SENDMAIL); cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service); if (attr_scan(cleanup, ATTR_FLAG_STRICT, diff --git a/postfix/src/postscreen/Makefile.in b/postfix/src/postscreen/Makefile.in index a5951b32c..a15f41afb 100644 --- a/postfix/src/postscreen/Makefile.in +++ b/postfix/src/postscreen/Makefile.in @@ -296,6 +296,7 @@ postscreen_smtpd.o: ../../include/argv.h postscreen_smtpd.o: ../../include/attr.h postscreen_smtpd.o: ../../include/dict.h postscreen_smtpd.o: ../../include/dict_cache.h +postscreen_smtpd.o: ../../include/dns.h postscreen_smtpd.o: ../../include/ehlo_mask.h postscreen_smtpd.o: ../../include/events.h postscreen_smtpd.o: ../../include/htable.h @@ -313,6 +314,7 @@ postscreen_smtpd.o: ../../include/mymalloc.h postscreen_smtpd.o: ../../include/name_code.h postscreen_smtpd.o: ../../include/name_mask.h postscreen_smtpd.o: ../../include/server_acl.h +postscreen_smtpd.o: ../../include/sock_addr.h postscreen_smtpd.o: ../../include/string_list.h postscreen_smtpd.o: ../../include/stringops.h postscreen_smtpd.o: ../../include/sys_defs.h @@ -328,6 +330,7 @@ postscreen_starttls.o: ../../include/attr.h postscreen_starttls.o: ../../include/connect.h postscreen_starttls.o: ../../include/dict.h postscreen_starttls.o: ../../include/dict_cache.h +postscreen_starttls.o: ../../include/dns.h postscreen_starttls.o: ../../include/events.h postscreen_starttls.o: ../../include/htable.h postscreen_starttls.o: ../../include/iostuff.h @@ -342,6 +345,7 @@ postscreen_starttls.o: ../../include/mymalloc.h postscreen_starttls.o: ../../include/name_code.h postscreen_starttls.o: ../../include/name_mask.h postscreen_starttls.o: ../../include/server_acl.h +postscreen_starttls.o: ../../include/sock_addr.h postscreen_starttls.o: ../../include/string_list.h postscreen_starttls.o: ../../include/stringops.h postscreen_starttls.o: ../../include/sys_defs.h diff --git a/postfix/src/postscreen/postscreen_smtpd.c b/postfix/src/postscreen/postscreen_smtpd.c index 77bb8f475..6e8fa0de6 100644 --- a/postfix/src/postscreen/postscreen_smtpd.c +++ b/postfix/src/postscreen/postscreen_smtpd.c @@ -337,6 +337,9 @@ static void psc_smtpd_format_ehlo_reply(VSTRING *buf, int discard_mask PSC_EHLO_APPEND(saved_len, psc_temp, "250-8BITMIME\r\n"); if ((discard_mask & EHLO_MASK_DSN) == 0) PSC_EHLO_APPEND(saved_len, psc_temp, "250-DSN\r\n"); + /* Fix 20140708: announce SMTPUTF8. */ + if (var_smtputf8_enable && (discard_mask & EHLO_MASK_SMTPUTF8) == 0) + PSC_EHLO_APPEND(saved_len, psc_temp, "250-SMTPUTF8\r\n"); STR(psc_temp)[saved_len + 3] = ' '; } diff --git a/postfix/src/qmgr/Makefile.in b/postfix/src/qmgr/Makefile.in index 1286518ea..6bf8824da 100644 --- a/postfix/src/qmgr/Makefile.in +++ b/postfix/src/qmgr/Makefile.in @@ -170,6 +170,7 @@ qmgr_deliver.o: ../../include/mymalloc.h qmgr_deliver.o: ../../include/rcpt_print.h qmgr_deliver.o: ../../include/recipient_list.h qmgr_deliver.o: ../../include/scan_dir.h +qmgr_deliver.o: ../../include/smtputf8.h qmgr_deliver.o: ../../include/stringops.h qmgr_deliver.o: ../../include/sys_defs.h qmgr_deliver.o: ../../include/vbuf.h diff --git a/postfix/src/qmgr/qmgr.h b/postfix/src/qmgr/qmgr.h index 6737e42c0..d5f48453d 100644 --- a/postfix/src/qmgr/qmgr.h +++ b/postfix/src/qmgr/qmgr.h @@ -343,6 +343,7 @@ struct QMGR_MESSAGE { char *sender; /* complete address */ char *dsn_envid; /* DSN envelope ID */ int dsn_ret; /* DSN headers/full */ + int smtputf8; /* requires unicode */ char *verp_delims; /* VERP delimiters */ char *filter_xport; /* filtering transport */ char *inspect_xport; /* inspecting transport */ diff --git a/postfix/src/qmgr/qmgr_active.c b/postfix/src/qmgr/qmgr_active.c index d93a2cd10..c3e446cb5 100644 --- a/postfix/src/qmgr/qmgr_active.c +++ b/postfix/src/qmgr/qmgr_active.c @@ -296,6 +296,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -306,6 +307,7 @@ void qmgr_active_done(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -389,6 +391,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -441,6 +444,7 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -451,6 +455,7 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, @@ -466,6 +471,7 @@ static void qmgr_active_done_25_generic(QMGR_MESSAGE *message) message->queue_name, message->queue_id, message->encoding, + message->smtputf8, message->sender, message->dsn_envid, message->dsn_ret, diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c index 2fbb0493e..49f3ac1aa 100644 --- a/postfix/src/qmgr/qmgr_deliver.c +++ b/postfix/src/qmgr/qmgr_deliver.c @@ -76,6 +76,7 @@ #include #include #include +#include /* Application-specific. */ @@ -140,6 +141,16 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) MSG_STATS stats; char *sender; int flags; + int smtputf8 = message->smtputf8; + const char *addr; + + /* + * Todo: integrate with code up-stream that builds the delivery request. + */ + for (recipient = list.info; recipient < list.info + list.len; recipient++) + if (var_smtputf8_enable && (addr = recipient->address)[0] + && !allascii(addr) && valid_utf8_string(addr, strlen(addr))) + smtputf8 |= SMTPUTF8_FLAG_RECIPIENT; /* * If variable envelope return path is requested, change prefix+@origin @@ -167,6 +178,7 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) ATTR_TYPE_LONG, MAIL_ATTR_SIZE, message->cont_length, ATTR_TYPE_STR, MAIL_ATTR_NEXTHOP, entry->queue->nexthop, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, message->encoding, + ATTR_TYPE_INT, MAIL_ATTR_SMTPUTF8, smtputf8, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, ATTR_TYPE_STR, MAIL_ATTR_DSN_ENVID, message->dsn_envid, ATTR_TYPE_INT, MAIL_ATTR_DSN_RET, message->dsn_ret, diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index e6bbaf65c..19323467d 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -179,6 +179,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name, message->sender = 0; message->dsn_envid = 0; message->dsn_ret = 0; + message->smtputf8 = 0; message->filter_xport = 0; message->inspect_xport = 0; message->redirect_addr = 0; @@ -557,10 +558,11 @@ static int qmgr_message_read(QMGR_MESSAGE *message) continue; if (rec_type == REC_TYPE_SIZE) { if (message->data_offset == 0) { - if ((count = sscanf(start, "%ld %ld %d %d %ld", + if ((count = sscanf(start, "%ld %ld %d %d %ld %d", &message->data_size, &message->data_offset, &message->rcpt_unread, &message->rflags, - &message->cont_length)) >= 3) { + &message->cont_length, + &message->smtputf8)) >= 3) { /* Postfix >= 1.0 (a.k.a. 20010228). */ if (message->data_offset <= 0 || message->data_size <= 0) { msg_warn("%s: invalid size record: %.100s", diff --git a/postfix/src/qmqpd/Makefile.in b/postfix/src/qmqpd/Makefile.in index 4a0098e2c..74cab19d6 100644 --- a/postfix/src/qmqpd/Makefile.in +++ b/postfix/src/qmqpd/Makefile.in @@ -89,6 +89,7 @@ qmqpd.o: ../../include/quote_flags.h qmqpd.o: ../../include/rec_type.h qmqpd.o: ../../include/recipient_list.h qmqpd.o: ../../include/record.h +qmqpd.o: ../../include/smtputf8.h qmqpd.o: ../../include/sys_defs.h qmqpd.o: ../../include/vbuf.h qmqpd.o: ../../include/verp_sender.h diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index 6b8f4f610..7e01485cc 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -50,6 +50,13 @@ /* .IP "\fBreceive_override_options (empty)\fR" /* Enable or disable recipient validation, built-in content /* filtering, or address mapping. +/* SMTPUTF8 CONTROLS +/* .ad +/* .fi +/* Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +/* Detect that a message requires SMTPUTF8 support for the specified +/* mail origin classes. /* RESOURCE AND RATE CONTROLS /* .ad /* .fi @@ -187,6 +194,7 @@ #include #include #include +#include /* Single-threaded server skeleton. */ @@ -241,6 +249,7 @@ static void qmqpd_open_file(QMQPD_STATE *state) */ cleanup_flags = input_transp_cleanup(CLEANUP_FLAG_MASK_EXTERNAL, qmqpd_input_transp_mask); + cleanup_flags |= smtputf8_autodetect(MAIL_SRC_MASK_QMQPD); state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 83dac65af..d68a294d1 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -360,12 +360,6 @@ /* .IP "\fBdelay_warning_time (0h)\fR" /* The time after which the sender receives a copy of the message /* headers of mail that is still queued. -/* .IP "\fBenable_errors_to (no)\fR" -/* Report mail delivery errors to the address specified with the -/* non-standard Errors-To: message header, instead of the envelope -/* sender address (this feature is removed with Postfix version 2.2, is -/* turned off by default with Postfix version 2.1, and is always turned on -/* with older Postfix versions). /* .IP "\fBmail_owner (postfix)\fR" /* The UNIX system account that owns the Postfix queue and most Postfix /* daemon processes. diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index bc284e68d..65bdd39e0 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -151,6 +151,7 @@ smtp_addr.o: ../../include/inet_proto.h smtp_addr.o: ../../include/mail_params.h smtp_addr.o: ../../include/maps.h smtp_addr.o: ../../include/match_list.h +smtp_addr.o: ../../include/midna.h smtp_addr.o: ../../include/mime_state.h smtp_addr.o: ../../include/msg.h smtp_addr.o: ../../include/msg_stats.h @@ -187,11 +188,12 @@ smtp_chat.o: ../../include/dsn_util.h smtp_chat.o: ../../include/header_body_checks.h smtp_chat.o: ../../include/header_opts.h smtp_chat.o: ../../include/htable.h -smtp_chat.o: ../../include/int_filt.h +smtp_chat.o: ../../include/iostuff.h smtp_chat.o: ../../include/line_wrap.h smtp_chat.o: ../../include/mail_addr.h smtp_chat.o: ../../include/mail_error.h smtp_chat.o: ../../include/mail_params.h +smtp_chat.o: ../../include/mail_proto.h smtp_chat.o: ../../include/maps.h smtp_chat.o: ../../include/match_list.h smtp_chat.o: ../../include/mime_state.h @@ -331,7 +333,6 @@ smtp_map11.o: ../../include/string_list.h smtp_map11.o: ../../include/sys_defs.h smtp_map11.o: ../../include/tls.h smtp_map11.o: ../../include/tok822.h -smtp_map11.o: ../../include/valid_hostname.h smtp_map11.o: ../../include/vbuf.h smtp_map11.o: ../../include/vstream.h smtp_map11.o: ../../include/vstring.h @@ -380,6 +381,7 @@ smtp_proto.o: ../../include/record.h smtp_proto.o: ../../include/resolve_clnt.h smtp_proto.o: ../../include/scache.h smtp_proto.o: ../../include/smtp_stream.h +smtp_proto.o: ../../include/smtputf8.h smtp_proto.o: ../../include/sock_addr.h smtp_proto.o: ../../include/split_at.h smtp_proto.o: ../../include/string_list.h @@ -387,6 +389,7 @@ smtp_proto.o: ../../include/stringops.h smtp_proto.o: ../../include/sys_defs.h smtp_proto.o: ../../include/tls.h smtp_proto.o: ../../include/tok822.h +smtp_proto.o: ../../include/uxtext.h smtp_proto.o: ../../include/vbuf.h smtp_proto.o: ../../include/vstream.h smtp_proto.o: ../../include/vstring.h @@ -689,6 +692,7 @@ smtp_tls_policy.o: ../../include/sys_defs.h smtp_tls_policy.o: ../../include/tls.h smtp_tls_policy.o: ../../include/tok822.h smtp_tls_policy.o: ../../include/valid_hostname.h +smtp_tls_policy.o: ../../include/valid_utf8_hostname.h smtp_tls_policy.o: ../../include/vbuf.h smtp_tls_policy.o: ../../include/vstream.h smtp_tls_policy.o: ../../include/vstring.h diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index 15ecda163..158c273e6 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -96,6 +96,8 @@ /* RFC 3463 (Enhanced Status Codes) /* RFC 4954 (AUTH command) /* RFC 5321 (SMTP protocol) +/* RFC 6531 (Internationalized SMTP) +/* RFC 6533 (Internationalized Delivery Status Notifications) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* Corrupted message files are marked so that the queue manager can @@ -571,6 +573,16 @@ /* When SMTP connection caching is enabled, the number of times /* that an SMTP session may be reused before it is closed, or zero (no /* limit). +/* SMTPUTF8 CONTROLS +/* .ad +/* .fi +/* Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +/* .IP "\fBsmtputf8_enable (no)\fR" +/* Enable experimental SMTPUTF8 support for the protocols described +/* in RFC 6531..6533. +/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +/* Enable SMTPUTF8 autodetection for the specified mail origin +/* classes. /* TROUBLE SHOOTING CONTROLS /* .ad /* .fi diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h index 70f8dbe67..c21aa65a5 100644 --- a/postfix/src/smtp/smtp.h +++ b/postfix/src/smtp/smtp.h @@ -221,6 +221,7 @@ typedef struct SMTP_STATE { #define SMTP_FEATURE_XFORWARD_PORT (1<<18) #define SMTP_FEATURE_EARLY_TLS_MAIL_REPLY (1<<19) /* CVE-2009-3555 */ #define SMTP_FEATURE_XFORWARD_IDENT (1<<20) +#define SMTP_FEATURE_SMTPUTF8 (1<<21) /* RFC 6531 */ /* * Features that passivate under the endpoint. diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c index deba52f7b..4a684ae70 100644 --- a/postfix/src/smtp/smtp_addr.c +++ b/postfix/src/smtp/smtp_addr.c @@ -85,6 +85,7 @@ #include #include #include +#include /* Global library. */ @@ -342,7 +343,7 @@ static DNS_RR *smtp_truncate_self(DNS_RR *addr_list, unsigned pref) /* smtp_domain_addr - mail exchanger address lookup */ -DNS_RR *smtp_domain_addr(char *name, DNS_RR **mxrr, int misc_flags, +DNS_RR *smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags, DSN_BUF *why, int *found_myself) { DNS_RR *mx_names; @@ -351,6 +352,7 @@ DNS_RR *smtp_domain_addr(char *name, DNS_RR **mxrr, int misc_flags, unsigned best_pref; unsigned best_found; int r = 0; /* Resolver flags */ + const char *aname; dsb_reset(why); /* Paranoia */ @@ -367,6 +369,17 @@ DNS_RR *smtp_domain_addr(char *name, DNS_RR **mxrr, int misc_flags, if (smtp_dns_support == SMTP_DNS_DNSSEC) r |= RES_USE_DNSSEC; + /* + * IDNA support. + */ +#ifndef NO_EAI + if (!allascii(name) && (aname = midna_utf8_to_ascii(name)) != 0) { + if (msg_verbose) + msg_info("%s asciified to %s", name, aname); + } else +#endif + aname = name; + /* * Look up the mail exchanger hosts listed for this name. Sort the * results by preference. Look up the corresponding host addresses, and @@ -409,21 +422,21 @@ DNS_RR *smtp_domain_addr(char *name, DNS_RR **mxrr, int misc_flags, * at hostnames provides a partial solution for MX hosts behind a NAT * gateway. */ - switch (dns_lookup(name, T_MX, r, &mx_names, (VSTRING *) 0, why->reason)) { + switch (dns_lookup(aname, T_MX, r, &mx_names, (VSTRING *) 0, why->reason)) { default: dsb_status(why, "4.4.3"); if (var_ign_mx_lookup_err) - addr_list = smtp_host_addr(name, misc_flags, why); + addr_list = smtp_host_addr(aname, misc_flags, why); break; case DNS_INVAL: dsb_status(why, "5.4.4"); if (var_ign_mx_lookup_err) - addr_list = smtp_host_addr(name, misc_flags, why); + addr_list = smtp_host_addr(aname, misc_flags, why); break; case DNS_FAIL: dsb_status(why, "5.4.3"); if (var_ign_mx_lookup_err) - addr_list = smtp_host_addr(name, misc_flags, why); + addr_list = smtp_host_addr(aname, misc_flags, why); break; case DNS_OK: mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any); @@ -472,7 +485,7 @@ DNS_RR *smtp_domain_addr(char *name, DNS_RR **mxrr, int misc_flags, } break; case DNS_NOTFOUND: - addr_list = smtp_host_addr(name, misc_flags, why); + addr_list = smtp_host_addr(aname, misc_flags, why); break; } @@ -489,18 +502,30 @@ DNS_RR *smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why) { DNS_RR *addr_list; int res_opt = 0; + const char *ahost; dsb_reset(why); /* Paranoia */ if (smtp_dns_support == SMTP_DNS_DNSSEC) res_opt |= RES_USE_DNSSEC; + /* + * IDNA support. + */ +#ifndef NO_EAI + if (!allascii(host) && (ahost = midna_utf8_to_ascii(host)) != 0) { + if (msg_verbose) + msg_info("%s asciified to %s", host, ahost); + } else +#endif + ahost = host; + /* * If the host is specified by numerical address, just convert the * address to internal form. Otherwise, the host is specified by name. */ #define PREF0 0 - addr_list = smtp_addr_one((DNS_RR *) 0, host, res_opt, PREF0, why); + addr_list = smtp_addr_one((DNS_RR *) 0, ahost, res_opt, PREF0, why); if (addr_list && (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT) && smtp_find_self(addr_list) != 0) { diff --git a/postfix/src/smtp/smtp_addr.h b/postfix/src/smtp/smtp_addr.h index cf0b6898c..8f20961e5 100644 --- a/postfix/src/smtp/smtp_addr.h +++ b/postfix/src/smtp/smtp_addr.h @@ -17,7 +17,7 @@ * Internal interfaces. */ extern DNS_RR *smtp_host_addr(const char *, int, DSN_BUF *); -extern DNS_RR *smtp_domain_addr(char *, DNS_RR **, int, DSN_BUF *, int *); +extern DNS_RR *smtp_domain_addr(const char *, DNS_RR **, int, DSN_BUF *, int *); /* LICENSE /* .ad diff --git a/postfix/src/smtp/smtp_chat.c b/postfix/src/smtp/smtp_chat.c index 5e2f82c7d..f11b37c89 100644 --- a/postfix/src/smtp/smtp_chat.c +++ b/postfix/src/smtp/smtp_chat.c @@ -458,7 +458,7 @@ void smtp_chat_notify(SMTP_SESSION *session) notice = post_mail_fopen_nowait(mail_addr_double_bounce(), var_error_rcpt, - INT_FILT_MASK_NOTIFY, + MAIL_SRC_MASK_NOTIFY, NULL_TRACE_FLAGS, NO_QUEUE_ID); if (notice == 0) { msg_warn("postmaster notify: %m"); diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c index 19c374fa6..acff1eba4 100644 --- a/postfix/src/smtp/smtp_connect.c +++ b/postfix/src/smtp/smtp_connect.c @@ -979,6 +979,7 @@ static void smtp_connect_inet(SMTP_STATE *state, const char *nexthop, session->state = state; #ifdef USE_TLS session->tls = state->tls; /* TEMPORARY */ + /* XXX: EAI: Convert to A-label here or in TLS library */ session->tls_nexthop = domain; /* for TLS_LEV_SECURE */ #endif if (addr->pref == domain_best_pref) diff --git a/postfix/src/smtp/smtp_map11.c b/postfix/src/smtp/smtp_map11.c index 8d7f75817..96326ebe6 100644 --- a/postfix/src/smtp/smtp_map11.c +++ b/postfix/src/smtp/smtp_map11.c @@ -62,7 +62,6 @@ #include #include #include -#include /* Global library. */ diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 1661eee83..7be90fbbe 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -147,6 +147,8 @@ #include #include #include +#include +#include /* Application-specific. */ @@ -231,6 +233,11 @@ char *xfer_request[SMTP_STATE_LAST] = { "QUIT command", }; + /* + * Note: MIME downgrade never happens for mail that must be delivered with + * SMTPUTF8 (the sender requested SMTPUTF8, AND the delivery request + * involves at least one UTF-8 envelope address or header value. + */ #define SMTP_MIME_DOWNGRADE(session, request) \ (var_disable_mime_oconv == 0 \ && (session->features & SMTP_FEATURE_8BITMIME) == 0 \ @@ -547,6 +554,9 @@ int smtp_helo(SMTP_STATE *state) } else if (strcasecmp(word, "DSN") == 0) { if ((discard_mask & EHLO_MASK_DSN) == 0) session->features |= SMTP_FEATURE_DSN; + } else if (strcasecmp(word, "SMTPUTF8") == 0) { + if ((discard_mask & EHLO_MASK_SMTPUTF8) == 0) + session->features |= SMTP_FEATURE_SMTPUTF8; } n++; } @@ -556,6 +566,59 @@ int smtp_helo(SMTP_STATE *state) msg_info("server features: 0x%x size %.0f", session->features, (double) session->size_limit); + /* + * Decide if this delivery requires SMTPUTF8 server support. + * + * For now, we require that the remote SMTP server supports SMTPUTF8 when + * the sender requested SMTPUTF8 support. + * + * XXX EAI Refine this to: the sender requested SMTPUTF8 support AND the + * delivery request involves at least one UTF-8 envelope address or + * header value. + * + * If the sender requested SMTPUTF8 support but the delivery request + * involves no UTF-8 envelope address or header value, then we could + * still deliver such mail to a non-SMTPUTF8 server, except that we must + * either uxtext-encode ORCPT parameters or not send them. We cannot + * encode the ORCPT in xtext, because legacy SMTP requires that the + * unencoded address consist entirely of printable (graphic and white + * space) characters from the US-ASCII repertoire (RFC 3461 section 4). A + * correct uxtext encoder will produce a result that an xtext decoder + * will pass through unchanged. + * + * XXX Should we try to encode headers with RFC 2047 when delivering to a + * non-SMTPUTF8 server? That could make life easier for mailing lists. + */ +#define DELIVERY_REQUIRES_SMTPUTF8 \ + ((request->smtputf8 & SMTPUTF8_FLAG_REQUESTED) \ + && (request->smtputf8 & ~SMTPUTF8_FLAG_REQUESTED)) + + /* + * Require that the server supports SMTPUTF8 when delivery requires + * SMTPUTF8. + * + * Fix 20140706: moved this before negotiating TLS, AUTH, and so on. + */ + if ((session->features & SMTP_FEATURE_SMTPUTF8) == 0 + && DELIVERY_REQUIRES_SMTPUTF8) + return (smtp_mesg_fail(state, DSN_BY_LOCAL_MTA, + SMTP_RESP_FAKE(&fake, "5.6.7"), + "SMTPUTF8 is required, " + "but was not offered by host %s", + session->namaddr)); + + /* + * Fix 20140706: don't do silly things when the remote server announces + * SMTPUTF8 but not 8BITMIME support. Our primary mission is to deliver + * mail, not to force people into compliance. + */ + if ((session->features & SMTP_FEATURE_SMTPUTF8) != 0 + && (session->features & SMTP_FEATURE_8BITMIME) == 0) { + msg_info("host %s offers SMTPUTF8 support, but not 8BITMIME", + session->namaddr); + session->features |= SMTP_FEATURE_8BITMIME; + } + /* * We use SMTP command pipelining if the server said it supported it. * Since we use blocking I/O, RFC 2197 says that we should inspect the @@ -1378,6 +1441,18 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, dsn_ret_str(request->dsn_ret)); } + /* + * Request SMTPUTF8 when the remote SMTP server supports + * SMTPUTF8. + * + * If the sender requested SMTPUTF8 but the remote SMTP server does + * not support SMTPUTF8, then we have already determined earlier + * that delivering this message without SMTPUTF8 will not break + * the SMTPUTF8 promise that was made to the sender. + */ + if ((session->features & SMTP_FEATURE_SMTPUTF8) != 0) + vstring_strcat(next_command, " SMTPUTF8"); + /* * We authenticate the local MTA only, but not the sender. */ @@ -1432,17 +1507,33 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, vstring_str(session->scratch)); if (session->features & SMTP_FEATURE_DSN) { /* XXX DSN xtext encode address value not type. */ - if (rcpt->dsn_orcpt[0]) { - xtext_quote(session->scratch, rcpt->dsn_orcpt, "+="); - vstring_sprintf_append(next_command, " ORCPT=%s", - vstring_str(session->scratch)); - } else if (rcpt->orig_addr[0]) { + const char *orcpt_type_addr = rcpt->dsn_orcpt; + + /* Fix 20140706: don't use empty rcpt->orig_addr. */ + if (orcpt_type_addr[0] == 0 && rcpt->orig_addr[0] != 0) { quote_822_local(session->scratch, rcpt->orig_addr); - vstring_sprintf(session->scratch2, "rfc822;%s", + vstring_sprintf(session->scratch2, "%s;%s", + /* Fix 20140707: sender must request SMTPUTF8. */ + (request->smtputf8 != 0 + && !allascii(vstring_str(session->scratch))) ? + "utf-8" : "rfc822", vstring_str(session->scratch)); - xtext_quote(session->scratch, vstring_str(session->scratch2), "+="); - vstring_sprintf_append(next_command, " ORCPT=%s", - vstring_str(session->scratch)); + orcpt_type_addr = vstring_str(session->scratch2); + } + if (orcpt_type_addr[0] != 0) { + /* Fix 20140706: don't send unquoted ORCPT. */ + /* Fix 20140707: quoting method must match orcpt type. */ + /* Fix 20140707: handle uxtext encoder errors. */ + if (strncasecmp(orcpt_type_addr, "utf-8;", 6) == 0) { + if (uxtext_quote(session->scratch, + orcpt_type_addr, "+=") != 0) + vstring_sprintf_append(next_command, " ORCPT=%s", + vstring_str(session->scratch)); + } else { + xtext_quote(session->scratch, orcpt_type_addr, "="); + vstring_sprintf_append(next_command, " ORCPT=%s", + vstring_str(session->scratch)); + } } if (rcpt->dsn_notify) vstring_sprintf_append(next_command, " NOTIFY=%s", diff --git a/postfix/src/smtp/smtp_tls_policy.c b/postfix/src/smtp/smtp_tls_policy.c index f280810e1..59118f2b3 100644 --- a/postfix/src/smtp/smtp_tls_policy.c +++ b/postfix/src/smtp/smtp_tls_policy.c @@ -98,7 +98,7 @@ #include #include #include -#include +#include #include /* Global library. */ @@ -375,7 +375,7 @@ static void tls_policy_lookup(SMTP_TLS_POLICY *tls, int *site_level, * * XXX UNIX-domain connections query with the pathname as destination. */ - if (!valid_hostname(site_name, DONT_GRIPE)) { + if (!valid_utf8_hostname(var_smtputf8_enable, site_name, DONT_GRIPE)) { tls_policy_lookup_one(tls, site_level, site_name, site_class); return; } diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 4e3397d0e..7fcc49d26 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -207,6 +207,7 @@ smtpd.o: ../../include/recipient_list.h smtpd.o: ../../include/record.h smtpd.o: ../../include/resolve_clnt.h smtpd.o: ../../include/smtp_stream.h +smtpd.o: ../../include/smtputf8.h smtpd.o: ../../include/sock_addr.h smtpd.o: ../../include/split_at.h smtpd.o: ../../include/string_list.h @@ -215,6 +216,7 @@ smtpd.o: ../../include/sys_defs.h smtpd.o: ../../include/tls.h smtpd.o: ../../include/tls_proxy.h smtpd.o: ../../include/tok822.h +smtpd.o: ../../include/uxtext.h smtpd.o: ../../include/valid_hostname.h smtpd.o: ../../include/valid_mailhost_addr.h smtpd.o: ../../include/vbuf.h @@ -239,7 +241,6 @@ smtpd_chat.o: ../../include/argv.h smtpd_chat.o: ../../include/attr.h smtpd_chat.o: ../../include/cleanup_user.h smtpd_chat.o: ../../include/dns.h -smtpd_chat.o: ../../include/int_filt.h smtpd_chat.o: ../../include/iostuff.h smtpd_chat.o: ../../include/line_wrap.h smtpd_chat.o: ../../include/mac_expand.h @@ -303,6 +304,7 @@ smtpd_check.o: ../../include/mail_stream.h smtpd_check.o: ../../include/maps.h smtpd_check.o: ../../include/match_list.h smtpd_check.o: ../../include/match_parent_style.h +smtpd_check.o: ../../include/midna.h smtpd_check.o: ../../include/milter.h smtpd_check.o: ../../include/msg.h smtpd_check.o: ../../include/msg_stats.h @@ -328,6 +330,7 @@ smtpd_check.o: ../../include/sys_defs.h smtpd_check.o: ../../include/tls.h smtpd_check.o: ../../include/valid_hostname.h smtpd_check.o: ../../include/valid_mailhost_addr.h +smtpd_check.o: ../../include/valid_utf8_hostname.h smtpd_check.o: ../../include/vbuf.h smtpd_check.o: ../../include/verify_clnt.h smtpd_check.o: ../../include/vstream.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 8784cf236..efdd50255 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -53,6 +53,8 @@ /* RFC 4409 (Message submission) /* RFC 4954 (AUTH command) /* RFC 5321 (SMTP protocol) +/* RFC 6531 (Internationalized SMTP) +/* RFC 6533 (Internationalized Delivery Status Notifications) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* @@ -470,6 +472,18 @@ /* .IP "\fBsmtpd_tls_cipherlist (empty)\fR" /* Obsolete Postfix < 2.3 control for the Postfix SMTP server TLS /* cipher list. +/* SMTPUTF8 CONTROLS +/* .ad +/* .fi +/* Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +/* .IP "\fBsmtputf8_enable (no)\fR" +/* Enable experimental SMTPUTF8 support for the protocols described +/* in RFC 6531..6533. +/* .IP "\fBstrict_smtputf8 (no)\fR" +/* Enable stricter enforcement of the SMTPUTF8 protocol. +/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +/* Detect that a message requires SMTPUTF8 support for the specified +/* mail origin classes. /* VERP SUPPORT CONTROLS /* .ad /* .fi @@ -1122,8 +1136,10 @@ #include #include #include +#include #include #include +#include /* Single-threaded server skeleton. */ @@ -1812,6 +1828,8 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) EHLO_APPEND(state, "8BITMIME"); if ((discard_mask & EHLO_MASK_DSN) == 0) EHLO_APPEND(state, "DSN"); + if (var_smtputf8_enable && (discard_mask & EHLO_MASK_SMTPUTF8) == 0) + EHLO_APPEND(state, "SMTPUTF8"); /* * Send the reply. @@ -1892,6 +1910,10 @@ static int mail_open_stream(SMTPD_STATE *state) cleanup_flags = input_transp_cleanup(CLEANUP_FLAG_MASK_EXTERNAL, smtpd_input_transp_mask) | CLEANUP_FLAG_SMTP_REPLY; + if (state->flags & SMTPD_FLAG_SMTPUTF8) + cleanup_flags |= CLEANUP_FLAG_SMTPUTF8; + else + cleanup_flags |= smtputf8_autodetect(MAIL_SRC_MASK_SMTPD); state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service); if (state->dest == 0 @@ -2185,7 +2207,7 @@ static int extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg, if ((STR(state->addr_buf)[0] == 0 && !allow_empty_addr) || (strict_rfc821 && STR(state->addr_buf)[0] == '@') || (SMTPD_STAND_ALONE(state) == 0 - && smtpd_check_addr(STR(state->addr_buf)) != 0)) { + && smtpd_check_addr(state, STR(state->addr_buf)) != 0)) { msg_warn("Illegal address syntax from %s in %s command: %s", state->namaddr, state->where, printable(STR(arg->vstrval), '?')); @@ -2313,6 +2335,10 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "552 5.3.4 Message size exceeds file system imposed limit"); return (-1); } + } else if (var_smtputf8_enable + && (state->ehlo_discard_mask & EHLO_MASK_SMTPUTF8) == 0 + && strcasecmp(arg, "SMTPUTF8") == 0) { /* RFC 6531 */ + state->flags |= SMTPD_FLAG_SMTPUTF8; #ifdef USE_SASL_AUTH } else if (strncasecmp(arg, "AUTH=", 5) == 0) { if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) { @@ -2430,6 +2456,19 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) } } + /* + * Historically, Postfix does not forbid 8-bit envelope addresses. + * Changing this would be a compatibility break. That can't happen in the + * forseeable future. + */ + if (var_strict_smtputf8 && (state->flags & SMTPD_FLAG_SMTPUTF8) == 0) { + if (*STR(state->addr_buf) && !allascii(STR(state->addr_buf))) { + mail_reset(state); + smtpd_chat_reply(state, "553 5.6.7 Must declare SMTPUTF8 to send unicode address"); + return (-1); + } + } + /* * Check the queue file space, if applicable. The optional before-filter * speed-adjust buffers use disk space. However, we don't know if they @@ -2640,8 +2679,10 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) vstring_strcpy(state->dsn_orcpt_buf, arg + 6); if (dsn_orcpt_addr || (coded_addr = split_at(STR(state->dsn_orcpt_buf), ';')) == 0 - || xtext_unquote(state->dsn_buf, coded_addr) == 0 - || *(dsn_orcpt_type = STR(state->dsn_orcpt_buf)) == 0) { + || *(dsn_orcpt_type = STR(state->dsn_orcpt_buf)) == 0 + || (strcasecmp(dsn_orcpt_type, "utf-8") == 0 ? + uxtext_unquote(state->dsn_buf, coded_addr) == 0 : + xtext_unquote(state->dsn_buf, coded_addr) == 0)) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 5.5.4 Error: Bad ORCPT parameter syntax"); @@ -2662,6 +2703,19 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) state->error_mask |= MAIL_ERROR_POLICY; return (-1); } + + /* + * Historically, Postfix does not forbid 8-bit envelope addresses. + * Changing this would be a compatibility break. That can't happen in the + * forseeable future. + */ + if (var_strict_smtputf8 && (state->flags & SMTPD_FLAG_SMTPUTF8) == 0) { + if (*STR(state->addr_buf) && !allascii(STR(state->addr_buf))) { + mail_reset(state); + smtpd_chat_reply(state, "553 5.6.7 Must declare SMTPUTF8 to send unicode address"); + return (-1); + } + } if (SMTPD_STAND_ALONE(state) == 0) { const char *verify_sender; @@ -2919,6 +2973,8 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) const CLEANUP_STAT_DETAIL *detail; const char *rfc3848_sess; const char *rfc3848_auth; + const char *with_protocol = (state->flags & SMTPD_FLAG_SMTPUTF8) ? + "UTF8SMTP" : state->protocol; #ifdef USE_TLS VSTRING *peer_CN; @@ -3081,7 +3137,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) state->cleanup ? "\tby %s (%s) with %s%s%s id %s" : "\tby %s (%s) with %s%s%s", var_myhostname, var_mail_name, - state->protocol, rfc3848_sess, + with_protocol, rfc3848_sess, rfc3848_auth, state->queue_id); quote_822_local(state->buffer, state->recipient); out_fprintf(out_stream, REC_TYPE_NORM, @@ -3092,7 +3148,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) state->cleanup ? "\tby %s (%s) with %s%s%s id %s;" : "\tby %s (%s) with %s%s%s;", var_myhostname, var_mail_name, - state->protocol, rfc3848_sess, + with_protocol, rfc3848_sess, rfc3848_auth, state->queue_id); out_fprintf(out_stream, REC_TYPE_NORM, "\t%s", mail_date(state->arrival_time.tv_sec)); @@ -3399,6 +3455,7 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) { const char *err = 0; int rate; + int smtputf8 = 0; /* * The SMTP standard (RFC 821) disallows unquoted special characters in @@ -3429,9 +3486,17 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "502 5.5.1 VRFY command is disabled"); return (-1); } + /* Fix 20140707: handle missing address. */ + if (var_smtputf8_enable + && (state->ehlo_discard_mask & EHLO_MASK_SMTPUTF8) == 0 + && argc > 1 && strcasecmp(argv[argc - 1].strval, "SMTPUTF8") == 0) { + argc--; /* RFC 6531 */ + smtputf8 = 1; + } if (argc < 2) { state->error_mask |= MAIL_ERROR_PROTOCOL; - smtpd_chat_reply(state, "501 5.5.4 Syntax: VRFY address"); + smtpd_chat_reply(state, "501 5.5.4 Syntax: VRFY address%s", + var_smtputf8_enable ? " [SMTPUTF8]" : ""); return (-1); } @@ -3468,6 +3533,14 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) smtpd_chat_reply(state, "501 5.1.3 Bad recipient address syntax"); return (-1); } + /* Fix 20140707: Check the VRFY command. */ + if (smtputf8 == 0 && var_strict_smtputf8) { + if (*STR(state->addr_buf) && !allascii(STR(state->addr_buf))) { + mail_reset(state); + smtpd_chat_reply(state, "553 5.6.7 Must declare SMTPUTF8 to send unicode address"); + return (-1); + } + } /* Use state->addr_buf, with the unquoted result from extract_addr() */ if (SMTPD_STAND_ALONE(state) == 0 && (err = smtpd_check_rcpt(state, STR(state->addr_buf))) != 0) { @@ -3524,6 +3597,8 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) /* * As an extension to RFC 1985 we also allow an RFC 2821 address literal * enclosed in []. + * + * XXX EAI: Convert to ASCII and use that form internally. */ if (!valid_hostname(argv[1].strval, DONT_GRIPE) && !valid_mailhost_literal(argv[1].strval, DONT_GRIPE)) { @@ -3694,6 +3769,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) if (name_status != SMTPD_PEER_CODE_OK) { attr_value = CLIENT_NAME_UNKNOWN; } else { + /* XXX EAI */ if (!valid_hostname(attr_value, DONT_GRIPE)) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s", @@ -3719,6 +3795,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) if (name_status != SMTPD_PEER_CODE_OK) { attr_value = CLIENT_NAME_UNKNOWN; } else { + /* XXX EAI */ if (!valid_hostname(attr_value, DONT_GRIPE)) { state->error_mask |= MAIL_ERROR_PROTOCOL; smtpd_chat_reply(state, "501 5.5.4 Bad %s syntax: %s", @@ -3987,6 +4064,7 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv) if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) { attr_value = CLIENT_NAME_UNKNOWN; } else { + /* XXX EAI */ neuter(attr_value, NEUTER_CHARACTERS, '?'); if (!valid_hostname(attr_value, DONT_GRIPE)) { state->error_mask |= MAIL_ERROR_PROTOCOL; @@ -5489,7 +5567,7 @@ int main(int argc, char **argv) #endif VAR_SMTPD_ACL_PERM_LOG, DEF_SMTPD_ACL_PERM_LOG, &var_smtpd_acl_perm_log, 0, 0, VAR_SMTPD_UPROXY_PROTO, DEF_SMTPD_UPROXY_PROTO, &var_smtpd_uproxy_proto, 0, 0, - VAR_SMTPD_POLICY_DEF_ACTION, DEF_SMTPD_POLICY_DEF_ACTION, &var_smtpd_policy_def_action, 1, 0, + VAR_SMTPD_POLICY_DEF_ACTION, DEF_SMTPD_POLICY_DEF_ACTION, &var_smtpd_policy_def_action, 1, 0, 0, }; static const CONFIG_RAW_TABLE raw_table[] = { diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index 8bd11763c..5677684cd 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -190,9 +190,11 @@ typedef struct { #define SMTPD_FLAG_HANGUP (1<<0) /* 421/521 disconnect */ #define SMTPD_FLAG_ILL_PIPELINING (1<<1) /* inappropriate pipelining */ #define SMTPD_FLAG_AUTH_USED (1<<2) /* don't reuse SASL state */ +#define SMTPD_FLAG_SMTPUTF8 (1<<3) /* RFC 6531/2 transaction */ /* Security: don't reset SMTPD_FLAG_AUTH_USED. */ -#define SMTPD_MASK_MAIL_KEEP ~0 /* keep all after MAIL reset */ +#define SMTPD_MASK_MAIL_KEEP \ + ~(SMTPD_FLAG_SMTPUTF8) /* Fix 20140706 */ #define SMTPD_STATE_XFORWARD_INIT (1<<0) /* xforward preset done */ #define SMTPD_STATE_XFORWARD_NAME (1<<1) /* client name received */ diff --git a/postfix/src/smtpd/smtpd_chat.c b/postfix/src/smtpd/smtpd_chat.c index a1016cd9c..7549b5c37 100644 --- a/postfix/src/smtpd/smtpd_chat.c +++ b/postfix/src/smtpd/smtpd_chat.c @@ -264,7 +264,7 @@ void smtpd_chat_notify(SMTPD_STATE *state) notice = post_mail_fopen_nowait(mail_addr_double_bounce(), var_error_rcpt, - INT_FILT_MASK_NOTIFY, + MAIL_SRC_MASK_NOTIFY, NULL_TRACE_FLAGS, NO_QUEUE_ID); if (notice == 0) { msg_warn("postmaster notify: %m"); diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index 8850cff70..eded7b908 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -9,7 +9,8 @@ /* /* void smtpd_check_init() /* -/* int smtpd_check_addr(address) +/* int smtpd_check_addr(state, address) +/* SMTPD_STATE *state; /* const char *address; /* /* char *smtpd_check_rewrite(state) @@ -204,6 +205,8 @@ #include #include #include +#include +#include /* DNS library. */ @@ -1180,7 +1183,7 @@ static int reject_invalid_hostname(SMTPD_STATE *state, char *name, test_name = dup_if_truncate(name); /* - * Validate the hostname. + * Validate the HELO/EHLO hostname. Fix 20140706: EAI not allowed here. */ if (!valid_hostname(test_name, DONT_GRIPE) && !valid_hostaddr(test_name, DONT_GRIPE)) /* XXX back compat */ @@ -1218,9 +1221,11 @@ static int reject_non_fqdn_hostname(SMTPD_STATE *state, char *name, test_name = dup_if_truncate(name); /* - * Validate the hostname. + * Validate the hostname. For backwards compatibility, permit non-ASCII + * names only when the client requested SMTPUTF8 support. */ - if (!valid_hostname(test_name, DONT_GRIPE) || !strchr(test_name, '.')) + if (valid_utf8_hostname(state->flags & SMTPD_FLAG_SMTPUTF8, + test_name, DONT_GRIPE) == 0 || strchr(test_name, '.') == 0) stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, var_non_fqdn_code, "5.5.2", "<%s>: %s rejected: need fully-qualified hostname", @@ -1843,9 +1848,11 @@ static int reject_non_fqdn_address(SMTPD_STATE *state, char *addr, test_dom = dup_if_truncate(domain); /* - * Validate the domain. + * Validate the domain. For backwards compatibility, permit non-ASCII + * names only when the client requested SMTPUTF8 support. */ - if (!*test_dom || !valid_hostname(test_dom, DONT_GRIPE) || !strchr(test_dom, '.')) + if (!*test_dom || !valid_utf8_hostname(state->flags & SMTPD_FLAG_SMTPUTF8, + test_dom, DONT_GRIPE) || !strchr(test_dom, '.')) stat = smtpd_check_reject(state, MAIL_ERROR_POLICY, var_non_fqdn_code, "4.5.2", "<%s>: %s rejected: need fully-qualified address", @@ -3399,6 +3406,7 @@ static const SMTPD_RBL_STATE *find_dnsxl_domain(SMTPD_STATE *state, const char *reply_addr; const char *byte_codes; const char *suffix; + const char *adomain; /* * Extract the domain, tack on the RBL domain name and query the DNS for @@ -3416,13 +3424,27 @@ static const SMTPD_RBL_STATE *find_dnsxl_domain(SMTPD_STATE *state, * the name has an alphanumerical prefix. We play safe, and skip both * RHSBL and RHSWL queries for names ending in a numerical suffix. */ - if (domain[0] == 0 || valid_hostname(domain, DONT_GRIPE) == 0) + if (domain[0] == 0) return (SMTPD_CHECK_DUNNO); suffix = strrchr(domain, '.'); if (alldig(suffix == 0 ? domain : suffix + 1)) return (SMTPD_CHECK_DUNNO); - query = vstring_alloc(100); + /* + * Fix 20140706: convert domain to ASCII. + * + * Caution: early returns must not leak adomain. + */ +#ifndef NO_EAI + if (!allascii(domain) && (adomain = midna_utf8_to_ascii(domain)) != 0) { + if (msg_verbose) + msg_info("%s asciified to %s", domain, adomain); + } else +#endif + adomain = domain; + + if (valid_hostname(domain, DONT_GRIPE) == 0) + query = vstring_alloc(100); vstring_sprintf(query, "%s.%s", domain, rbl_domain); reply_addr = split_at(STR(query), '='); rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query)); @@ -4380,10 +4402,11 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions, /* smtpd_check_addr - address sanity check */ -int smtpd_check_addr(const char *addr) +int smtpd_check_addr(SMTPD_STATE *state, const char *addr) { const RESOLVE_REPLY *resolve_reply; const char *myname = "smtpd_check_addr"; + const char *domain; if (msg_verbose) msg_info("%s: addr=%s", myname, addr); @@ -4398,6 +4421,18 @@ int smtpd_check_addr(const char *addr) resolve_reply = smtpd_resolve_addr(addr); if (resolve_reply->flags & RESOLVE_FLAG_ERROR) return (-1); + + /* + * Backwards compatibility: if the client does not request SMTPUTF8 + * support, then behave like Postfix < 2.12 trivial-rewrite, and don't + * allow non-ASCII email domains. Historically, Postfix does not reject + * UTF8 etc. in the address localpart. + */ + if ((state->flags & SMTPD_FLAG_SMTPUTF8) == 0 + && (domain = strrchr(STR(resolve_reply->recipient), '@')) != 0 + && *(domain += 1) != 0 && !allascii(domain)) + return (-1); + return (0); } diff --git a/postfix/src/smtpd/smtpd_check.h b/postfix/src/smtpd/smtpd_check.h index b76a4990f..fb415914d 100644 --- a/postfix/src/smtpd/smtpd_check.h +++ b/postfix/src/smtpd/smtpd_check.h @@ -13,7 +13,7 @@ * External interface. */ extern void smtpd_check_init(void); -extern int smtpd_check_addr(const char *); +extern int smtpd_check_addr(SMTPD_STATE *, const char *); extern char *smtpd_check_rewrite(SMTPD_STATE *); extern char *smtpd_check_client(SMTPD_STATE *); extern char *smtpd_check_helo(SMTPD_STATE *, char *); diff --git a/postfix/src/tls/Makefile.in b/postfix/src/tls/Makefile.in index 3daf50b51..814ba384c 100644 --- a/postfix/src/tls/Makefile.in +++ b/postfix/src/tls/Makefile.in @@ -44,7 +44,7 @@ root_tests: $(LIB): $(OBJS) $(AR) $(ARFL) $(LIB) $? $(RANLIB) $(LIB) - $(SHLIB_LD) -o $(LIB) $(OBJS) + $(SHLIB_LD) -o $(LIB) $(OBJS) $(SHLIB_SYSLIBS) $(LIB_DIR)/$(LIB): $(LIB) cp $(LIB) $(LIB_DIR) diff --git a/postfix/src/trivial-rewrite/Makefile.in b/postfix/src/trivial-rewrite/Makefile.in index 516c851d8..80dce5997 100644 --- a/postfix/src/trivial-rewrite/Makefile.in +++ b/postfix/src/trivial-rewrite/Makefile.in @@ -91,6 +91,7 @@ resolve.o: ../../include/sys_defs.h resolve.o: ../../include/tok822.h resolve.o: ../../include/valid_hostname.h resolve.o: ../../include/valid_mailhost_addr.h +resolve.o: ../../include/valid_utf8_hostname.h resolve.o: ../../include/vbuf.h resolve.o: ../../include/vstream.h resolve.o: ../../include/vstring.h diff --git a/postfix/src/trivial-rewrite/resolve.c b/postfix/src/trivial-rewrite/resolve.c index d9a709e30..f571869d4 100644 --- a/postfix/src/trivial-rewrite/resolve.c +++ b/postfix/src/trivial-rewrite/resolve.c @@ -57,7 +57,7 @@ #include #include #include -#include +#include #include #include @@ -329,7 +329,6 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, tree->head = tok822_scan(var_empty_addr, &tree->tail); continue; } - /* XXX Re-resolve with @$myhostname for backwards compatibility. */ if (domain == 0 && saved_domain == 0) { tok822_sub_append(tree, tok822_alloc('@', (char *) 0)); @@ -382,7 +381,8 @@ static void resolve_addr(RES_CONTEXT *rp, char *sender, char *addr, if (*rcpt_domain == '[') { if (!valid_mailhost_literal(rcpt_domain, DONT_GRIPE)) *flags |= RESOLVE_FLAG_ERROR; - } else if (!valid_hostname(rcpt_domain, DONT_GRIPE)) { + } else if (!valid_utf8_hostname(var_smtputf8_enable, rcpt_domain, + DONT_GRIPE)) { if (var_resolve_num_dom && valid_hostaddr(rcpt_domain, DONT_GRIPE)) { vstring_insert(nextrcpt, rcpt_domain - STR(nextrcpt), "[", 1); vstring_strcat(nextrcpt, "]"); diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 5a03a52f4..2320099b4 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -33,11 +33,12 @@ SRCS = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \ write_buf.c sane_basename.c format_tv.c allspace.c \ allascii.c load_file.c killme_after.c vstream_tweak.c \ pass_trigger.c edit_file.c inet_windowsize.c \ - unix_pass_fd_fix.c dict_cache.c valid_utf_8.c dict_thash.c \ + unix_pass_fd_fix.c dict_cache.c valid_utf8_string.c dict_thash.c \ ip_match.c nbbio.c base32_code.c dict_test.c \ dict_fail.c msg_rate_delay.c dict_surrogate.c warn_stat.c \ dict_sockmap.c line_number.c recv_pass_attr.c pass_accept.c \ - poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c + poll_fd.c timecmp.c slmdb.c dict_pipe.c dict_random.c \ + valid_utf8_hostname.c midna.c OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \ attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \ @@ -72,11 +73,12 @@ OBJS = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \ write_buf.o sane_basename.o format_tv.o allspace.o \ allascii.o load_file.o killme_after.o vstream_tweak.o \ pass_trigger.o edit_file.o inet_windowsize.o \ - unix_pass_fd_fix.o dict_cache.o valid_utf_8.o dict_thash.o \ + unix_pass_fd_fix.o dict_cache.o valid_utf8_string.o dict_thash.o \ ip_match.o nbbio.o base32_code.o dict_test.o \ dict_fail.o msg_rate_delay.o dict_surrogate.o warn_stat.o \ dict_sockmap.o line_number.o recv_pass_attr.o pass_accept.o \ - poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o + poll_fd.o timecmp.o $(NON_PLUGIN_MAP_OBJ) dict_pipe.o dict_random.o \ + valid_utf8_hostname.o midna.o # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf. # When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ), # otherwise it sets the PLUGIN_* macros. @@ -104,7 +106,8 @@ HDRS = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \ vstring_vstream.h watchdog.h format_tv.h load_file.h killme_after.h \ edit_file.h dict_cache.h dict_thash.h ip_match.h nbbio.h base32_code.h \ dict_fail.h warn_stat.h dict_sockmap.h line_number.h timecmp.h \ - slmdb.h compat_va_copy.h dict_pipe.h dict_random.h + slmdb.h compat_va_copy.h dict_pipe.h dict_random.h \ + valid_utf8_hostname.h midna.h TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \ stream_test.c dup2_pass_on_exec.c DEFS = -I. -D$(SYSTYPE) @@ -122,8 +125,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ attr_scan0 host_port attr_scan_plain attr_print_plain htable \ unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \ myaddrinfo myaddrinfo4 inet_proto sane_basename format_tv \ - valid_utf_8 ip_match base32_code msg_rate_delay netstring \ - vstream timecmp dict_cache + valid_utf8_string ip_match base32_code msg_rate_delay netstring \ + vstream timecmp dict_cache midna PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) LIB_DIR = ../../lib @@ -459,7 +462,7 @@ format_tv: $(LIB) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o -valid_utf_8: $(LIB) +valid_utf8_string: $(LIB) mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o @@ -499,6 +502,11 @@ dict_cache: $(LIB) $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o +midna: $(LIB) + mv $@.o junk + $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) + mv junk $@.o + tests: valid_hostname_test mac_expand_test dict_test unescape_test \ hex_quote_test ctable_test inet_addr_list_test base64_code_test \ attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \ @@ -1092,11 +1100,11 @@ dict_open.o: dict_nis.h dict_open.o: dict_nisplus.h dict_open.o: dict_open.c dict_open.o: dict_pcre.h +dict_open.o: dict_pipe.h dict_open.o: dict_random.h dict_open.o: dict_regexp.h dict_open.o: dict_sdbm.h dict_open.o: dict_sockmap.h -dict_open.o: dict_pipe.h dict_open.o: dict_static.h dict_open.o: dict_tcp.h dict_open.o: dict_thash.h @@ -1127,6 +1135,19 @@ dict_pcre.o: vbuf.h dict_pcre.o: vstream.h dict_pcre.o: vstring.h dict_pcre.o: warn_stat.h +dict_pipe.o: argv.h +dict_pipe.o: dict.h +dict_pipe.o: dict_pipe.c +dict_pipe.o: dict_pipe.h +dict_pipe.o: htable.h +dict_pipe.o: msg.h +dict_pipe.o: myflock.h +dict_pipe.o: mymalloc.h +dict_pipe.o: stringops.h +dict_pipe.o: sys_defs.h +dict_pipe.o: vbuf.h +dict_pipe.o: vstream.h +dict_pipe.o: vstring.h dict_random.o: argv.h dict_random.o: dict.h dict_random.o: dict_random.c @@ -1186,19 +1207,6 @@ dict_sockmap.o: sys_defs.h dict_sockmap.o: vbuf.h dict_sockmap.o: vstream.h dict_sockmap.o: vstring.h -dict_pipe.o: argv.h -dict_pipe.o: dict.h -dict_pipe.o: dict_pipe.c -dict_pipe.o: dict_pipe.h -dict_pipe.o: htable.h -dict_pipe.o: msg.h -dict_pipe.o: myflock.h -dict_pipe.o: mymalloc.h -dict_pipe.o: stringops.h -dict_pipe.o: sys_defs.h -dict_pipe.o: vbuf.h -dict_pipe.o: vstream.h -dict_pipe.o: vstring.h dict_static.o: argv.h dict_static.o: dict.h dict_static.o: dict_static.c @@ -1239,6 +1247,7 @@ dict_tcp.o: vstring.h dict_tcp.o: vstring_vstream.h dict_test.o: argv.h dict_test.o: dict.h +dict_test.o: dict_db.h dict_test.o: dict_lmdb.h dict_test.o: dict_test.c dict_test.o: msg.h @@ -1406,6 +1415,7 @@ host_port.o: split_at.h host_port.o: stringops.h host_port.o: sys_defs.h host_port.o: valid_hostname.h +host_port.o: valid_utf8_hostname.h host_port.o: vbuf.h host_port.o: vstring.h htable.o: htable.c @@ -1513,6 +1523,8 @@ load_file.o: vbuf.h load_file.o: vstream.h load_file.o: warn_stat.h load_lib.o: load_lib.c +load_lib.o: load_lib.h +load_lib.o: msg.h load_lib.o: sys_defs.h lowercase.o: lowercase.c lowercase.o: stringops.h @@ -1580,6 +1592,12 @@ match_ops.o: sys_defs.h match_ops.o: vbuf.h match_ops.o: vstream.h match_ops.o: vstring.h +midna.o: ctable.h +midna.o: midna.c +midna.o: midna.h +midna.o: msg.h +midna.o: mymalloc.h +midna.o: sys_defs.h msg.o: msg.c msg.o: msg.h msg.o: msg_output.h @@ -2001,11 +2019,21 @@ valid_hostname.o: valid_hostname.c valid_hostname.o: valid_hostname.h valid_hostname.o: vbuf.h valid_hostname.o: vstring.h -valid_utf_8.o: stringops.h -valid_utf_8.o: sys_defs.h -valid_utf_8.o: valid_utf_8.c -valid_utf_8.o: vbuf.h -valid_utf_8.o: vstring.h +valid_utf8_hostname.o: midna.h +valid_utf8_hostname.o: msg.h +valid_utf8_hostname.o: mymalloc.h +valid_utf8_hostname.o: stringops.h +valid_utf8_hostname.o: sys_defs.h +valid_utf8_hostname.o: valid_hostname.h +valid_utf8_hostname.o: valid_utf8_hostname.c +valid_utf8_hostname.o: valid_utf8_hostname.h +valid_utf8_hostname.o: vbuf.h +valid_utf8_hostname.o: vstring.h +valid_utf8_string.o: stringops.h +valid_utf8_string.o: sys_defs.h +valid_utf8_string.o: valid_utf8_string.c +valid_utf8_string.o: vbuf.h +valid_utf8_string.o: vstring.h vbuf.o: sys_defs.h vbuf.o: vbuf.c vbuf.o: vbuf.h diff --git a/postfix/src/util/host_port.c b/postfix/src/util/host_port.c index 644d8b7d6..defa3b455 100644 --- a/postfix/src/util/host_port.c +++ b/postfix/src/util/host_port.c @@ -17,6 +17,9 @@ /* name or address, and the service name or port number. /* The input string is modified. /* +/* Host/domain names are validated with valid_utf8_hostname(), +/* and host addresses are validated with valid_hostaddr(). +/* /* The following input formats are understood (null means /* a null pointer argument): /* @@ -88,8 +91,8 @@ #include #include -#include -#include +#include /* XXX temp_utf8_kludge */ +#include /* Global library. */ @@ -154,7 +157,8 @@ const char *host_port(char *buf, char **host, char *def_host, * Final sanity checks. We're still sloppy, allowing bare numerical * network addresses instead of requiring proper [ipaddress] forms. */ - if (*host != def_host && !valid_hostname(*host, DONT_GRIPE) + if (*host != def_host + && !valid_utf8_hostname(temp_utf8_kludge, *host, DONT_GRIPE) && !valid_hostaddr(*host, DONT_GRIPE)) return ("valid hostname or network address required"); if (*port != def_service && ISDIGIT(**port) && !alldig(*port)) diff --git a/postfix/src/util/midna.c b/postfix/src/util/midna.c new file mode 100644 index 000000000..320f2d4a1 --- /dev/null +++ b/postfix/src/util/midna.c @@ -0,0 +1,149 @@ +/*++ +/* NAME +/* midna 3 +/* SUMMARY +/* Postfix domain name conversion +/* SYNOPSIS +/* #include +/* +/* int midna_cache_size; +/* +/* const char *midna_utf8_to_ascii( +/* const char *name) +/* DESCRIPTION +/* The functions in this module transform domain names from +/* or to IDNA form. The result is cached to avoid repeated +/* conversion of the same name. +/* +/* midna_utf8_to_ascii() converts an UTF-8 domain name to +/* ASCII. The result is a null pointer in case of error. +/* +/* midna_cache_size specifies the size of the conversion result +/* cache. This value is used only once, upon the first lookup +/* request. +/* SEE ALSO +/* msg(3) diagnostics interface +/* DIAGNOSTICS +/* Fatal errors: memory allocation problem. +/* Warnings: conversion error. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Arnt Gulbrandsen +/* +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + + /* + * System library. + */ +#include +#include + +#ifndef NO_EAI +#include + + /* + * Utility library. + */ +#include +#include +#include +#include + + /* + * Application-specific. + */ +#define DEF_MIDNA_CACHE_SIZE 100 + +int midna_cache_size = DEF_MIDNA_CACHE_SIZE; + +/* midna_utf8_to_ascii_create - convert UTF8 domain to ASCII */ + +static void *midna_utf8_to_ascii_create(const char *name, void *unused_context) +{ + const char myname[] = "midna_utf8_to_ascii_create"; + char buf[1024]; /* XXX */ + UErrorCode error = U_ZERO_ERROR; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + UIDNA *idna; + int anl; + + idna = uidna_openUTS46(UIDNA_DEFAULT, &error); + anl = uidna_nameToASCII_UTF8(idna, + name, strlen(name), + buf, sizeof(buf), + &info, + &error); + uidna_close(idna); + if (U_SUCCESS(error) && info.errors == 0 && anl > 0) { + return (mystrndup(buf, anl)); + } else { + msg_warn("%s: Problem translating domain \"%s\" to IDNA form: %s", + myname, name, u_errorName(error)); + return (0); + } +} + +/* midna_utf8_to_ascii_free - cache element destructor */ + +static void midna_utf8_to_ascii_free(void *value, void *unused_context) +{ + if (value) + myfree(value); +} + +/* midna_utf8_to_ascii - convert UTF8 hostname to ASCII */ + +const char *midna_utf8_to_ascii(const char *name) +{ + static CTABLE *midna_utf8_to_ascii_cache = 0; + + if (midna_utf8_to_ascii_cache == 0) + midna_utf8_to_ascii_cache = ctable_create(midna_cache_size, + midna_utf8_to_ascii_create, + midna_utf8_to_ascii_free, + (void *) 0); + return (ctable_locate(midna_utf8_to_ascii_cache, name)); +} + +#ifdef TEST + + /* + * Test program - reads hostnames from stdin, reports invalid hostnames to + * stderr. + */ +#include + +#include /* XXX temp_utf8_kludge */ +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + VSTRING *buffer = vstring_alloc(1); + const char *res; + + msg_vstream_init(argv[0], VSTREAM_ERR); + msg_verbose = 1; + temp_utf8_kludge = 1; + + while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { + msg_info("testing: \"%s\"", vstring_str(buffer)); + res = midna_utf8_to_ascii(vstring_str(buffer)); + if (res != 0) + msg_info("result: \"%s\"", res); + } + exit(0); +} + +#endif + +#endif diff --git a/postfix/src/util/midna.h b/postfix/src/util/midna.h new file mode 100644 index 000000000..97e3978ff --- /dev/null +++ b/postfix/src/util/midna.h @@ -0,0 +1,30 @@ +#ifndef _MIDNA_H_INCLUDED_ +#define _MIDNA_H_INCLUDED_ + +/*++ +/* NAME +/* mail_idna 3h +/* SUMMARY +/* domain name conversion +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * External interface. + */ +extern const char *midna_utf8_to_ascii(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 diff --git a/postfix/src/util/printable.c b/postfix/src/util/printable.c index 9e27f94d4..1ba0731c7 100644 --- a/postfix/src/util/printable.c +++ b/postfix/src/util/printable.c @@ -6,19 +6,24 @@ /* SYNOPSIS /* #include /* +/* int temp_utf8_kludge; +/* /* char *printable(buffer, replacement) /* char *buffer; /* int replacement; /* DESCRIPTION -/* printable() replaces non-ASCII or non-printable characters in its input -/* by the given replacement. +/* printable() replaces non-printable characters +/* in its input with the given replacement. +/* +/* temp_utf8_kludge controls whether UTF8 is considered printable. +/* By default, non-ASCII text is replaced. /* /* Arguments: /* .IP buffer /* The null-terminated input string. /* .IP replacement /* Replacement value for characters in \fIbuffer\fR that do not -/* pass the isprint(3) test. +/* pass the ASCII isprint(3) test or that are not valid UTF8. /* LICENSE /* .ad /* .fi @@ -39,13 +44,31 @@ #include "stringops.h" +int temp_utf8_kludge = 0; + char *printable(char *string, int replacement) { - char *cp; + unsigned char *cp; int ch; - for (cp = string; (ch = *(unsigned char *) cp) != 0; cp++) - if (!ISASCII(ch) || !ISPRINT(ch)) + /* + * XXX Replace invalid UTF8 sequences (too short, over-long encodings, + * out-of-range code points, etc). See valid_utf8_string.c. + */ + cp = (unsigned char *) string; + while ((ch = *cp) != 0) { + if (ISASCII(ch) && ISPRINT(ch)) { + /* ok */ + } else if (temp_utf8_kludge && ch >= 194 && ch <= 254 + && cp[1] >= 128 && cp[1] < 192) { + /* UTF8; skip the rest of the bytes in the character. */ + while (cp[1] >= 128 && cp[1] < 192) + cp++; + } else { + /* Not ASCII and not UTF8. */ *cp = replacement; + } + cp++; + } return (string); } diff --git a/postfix/src/util/stringops.h b/postfix/src/util/stringops.h index 85d2a747e..5b30bdaa4 100644 --- a/postfix/src/util/stringops.h +++ b/postfix/src/util/stringops.h @@ -19,6 +19,7 @@ /* * External interface. */ +extern int temp_utf8_kludge; extern char *printable(char *, int); extern char *neuter(char *, const char *, int); extern char *lowercase(char *); @@ -41,7 +42,7 @@ extern int allprint(const char *); extern int allspace(const char *); extern int allascii(const char *); extern const char *split_nameval(char *, char **, char **); -extern int valid_utf_8(const char *, ssize_t); +extern int valid_utf8_string(const char *, ssize_t); /* LICENSE /* .ad diff --git a/postfix/src/util/valid_utf8_hostname.c b/postfix/src/util/valid_utf8_hostname.c new file mode 100644 index 000000000..40bfa2ced --- /dev/null +++ b/postfix/src/util/valid_utf8_hostname.c @@ -0,0 +1,86 @@ +/*++ +/* NAME +/* valid_utf8_hostname 3 +/* SUMMARY +/* validate (maybe UTF-8) domain name +/* SYNOPSIS +/* #include +/* +/* int valid_utf8_hostname( +/* int enable_utf8, +/* const char *domain, +/* int gripe) +/* DESCRIPTION +/* valid_utf8_hostname() is a wrapper around valid_hostname(). +/* If EAI support is compiled in, and enable_utf8 is true, the +/* name is converted from UTF-8 to ASCII per IDNA rules, before +/* invoking valid_hostname(). +/* SEE ALSO +/* valid_hostname(3) STD3 hostname validation. +/* DIAGNOSTICS +/* Fatal errors: memory allocation problem. +/* Warnings: malformed domain name. +/* 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 +/*--*/ + + /* + * System library. + */ +#include + + /* + * Utility library. + */ +#include +#include +#include +#include +#include +#include + +/* valid_utf8_hostname - validate internationalized domain name */ + +int valid_utf8_hostname(int enable_utf8, const char *name, int gripe) +{ + const char myname[] = "valid_utf8_hostname"; + const char *aname; + int ret; + + /* + * Trivial cases first. + */ + if (*name == 0) { + if (gripe) + msg_warn("%s: empty domain name", myname); + return (0); + } + + /* + * Convert domain name to ASCII form. + */ +#ifndef NO_EAI + if (enable_utf8 && !allascii(name)) { + if ((aname = midna_utf8_to_ascii(name)) == 0) { + if (gripe) + msg_warn("%s: malformed UTF-8 domain name", myname); + return (0); + } + } else +#endif + aname = name; + + /* + * Validate the name per STD3 (if the IDNA routines didn't already). + */ + ret = valid_hostname(aname, gripe); + + return (ret); +} diff --git a/postfix/src/util/valid_utf8_hostname.h b/postfix/src/util/valid_utf8_hostname.h new file mode 100644 index 000000000..0c0b41f48 --- /dev/null +++ b/postfix/src/util/valid_utf8_hostname.h @@ -0,0 +1,35 @@ +#ifndef _VALID_UTF8_HOSTNAME_H_INCLUDED_ +#define _VALID_UTF8_HOSTNAME_H_INCLUDED_ + +/*++ +/* NAME +/* valid_utf8_hostname 3h +/* SUMMARY +/* validate (maybe UTF-8) domain name +/* SYNOPSIS +/* #include +/* DESCRIPTION +/* .nf + + /* + * Utility library. + */ +#include + + /* + * External interface + */ +extern int valid_utf8_hostname(int, const char *, int); + +/* 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 diff --git a/postfix/src/util/valid_utf_8.c b/postfix/src/util/valid_utf8_string.c similarity index 85% rename from postfix/src/util/valid_utf_8.c rename to postfix/src/util/valid_utf8_string.c index f953e63c8..96b5b4db8 100644 --- a/postfix/src/util/valid_utf_8.c +++ b/postfix/src/util/valid_utf8_string.c @@ -1,16 +1,16 @@ /*++ /* NAME -/* valid_utf_8 3 +/* valid_utf8_string 3 /* SUMMARY /* predicate if string is valid UTF-8 /* SYNOPSIS /* #include /* -/* int valid_utf_8(str, len) +/* int valid_utf8_string(str, len) /* const char *str; /* ssize_t len; /* DESCRIPTION -/* valid_utf_8() determines if a string satisfies the UTF-8 +/* valid_utf8_string() determines if a string satisfies the UTF-8 /* definition in RFC 3629. That is, it contains proper encodings /* of code points U+0000..U+10FFFF, excluding over-long encodings /* and excluding U+D800..U+DFFF surrogates. @@ -46,9 +46,9 @@ #include -/* valid_utf_8 - validate string according to RFC 3629 */ +/* valid_utf8_string - validate string according to RFC 3629 */ -int valid_utf_8(const char *str, ssize_t len) +int valid_utf8_string(const char *str, ssize_t len) { const unsigned char *end = (const unsigned char *) str + len; const unsigned char *cp; @@ -74,7 +74,7 @@ int valid_utf_8(const char *str, ssize_t len) if (UNEXPECTED(c0 < 0xc2) || UNEXPECTED(cp + 1 >= end) /* Require UTF-8 tail byte. */ - || UNEXPECTED((ch = *++cp) < 0x80) || UNEXPECTED(ch > 0xbf)) + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) return (0); } /* Three-byte encodings. */ @@ -85,7 +85,7 @@ int valid_utf_8(const char *str, ssize_t len) /* Exclude U+D800..U+DFFF. */ || UNEXPECTED(ch > (c0 == 0xed ? 0x9f : 0xbf)) /* Require UTF-8 tail byte. */ - || UNEXPECTED((ch = *++cp) < 0x80) || UNEXPECTED(ch > 0xbf)) + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) return (0); } /* Four-byte encodings. */ @@ -96,9 +96,9 @@ int valid_utf_8(const char *str, ssize_t len) /* Exclude code points above U+10FFFF. */ || UNEXPECTED(ch > (c0 == 0xf4 ? 0x8f : 0xbf)) /* Require UTF-8 tail byte. */ - || UNEXPECTED((ch = *++cp) < 0x80) || UNEXPECTED(ch > 0xbf) + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80) /* Require UTF-8 tail byte. */ - || UNEXPECTED((ch = *++cp) < 0x80) || UNEXPECTED(ch > 0xbf)) + || UNEXPECTED(((ch = *++cp) & 0xc0) != 0x80)) return (0); } /* Invalid: c0 >= 0xf5 */ @@ -126,7 +126,7 @@ int main(void) VSTRING *buf = vstring_alloc(1); while (vstring_get_nonl(buf, VSTREAM_IN) != VSTREAM_EOF) { - vstream_printf("%c", (LEN(buf) && !valid_utf_8(STR(buf), LEN(buf))) ? + vstream_printf("%c", (LEN(buf) && !valid_utf8_string(STR(buf), LEN(buf))) ? '!' : ' '); vstream_fwrite(VSTREAM_OUT, STR(buf), LEN(buf)); vstream_printf("\n"); diff --git a/postfix/src/verify/Makefile.in b/postfix/src/verify/Makefile.in index 932893057..7ae6f4ed8 100644 --- a/postfix/src/verify/Makefile.in +++ b/postfix/src/verify/Makefile.in @@ -70,7 +70,6 @@ verify.o: ../../include/dict_ht.h verify.o: ../../include/dsn.h verify.o: ../../include/events.h verify.o: ../../include/htable.h -verify.o: ../../include/int_filt.h verify.o: ../../include/iostuff.h verify.o: ../../include/mail_conf.h verify.o: ../../include/mail_params.h diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c index b45835802..e60d4fae2 100644 --- a/postfix/src/verify/verify.c +++ b/postfix/src/verify/verify.c @@ -148,6 +148,13 @@ /* .IP "\fBaddress_verify_sender_dependent_default_transport_maps ($sender_dependent_default_transport_maps)\fR" /* Overrides the sender_dependent_default_transport_maps parameter /* setting for address verification probes. +/* SMTPUTF8 CONTROLS +/* .ad +/* .fi +/* Preliminary SMTPUTF8 support is introduced with Postfix 2.12. +/* .IP "\fBsmtputf8_autodetect_classes (sendmail, verify)\fR" +/* Enable SMTPUTF8 autodetection for the specified mail origin +/* classes. /* MISCELLANEOUS CONTROLS /* .ad /* .fi @@ -499,7 +506,7 @@ static void verify_query_service(VSTREAM *client_stream) msg_info("PROBE %s status=%d probed=%ld updated=%ld", STR(addr), addr_status, now, updated); post_mail_fopen_async(make_verify_sender_addr(), STR(addr), - INT_FILT_MASK_NONE, + MAIL_SRC_MASK_VERIFY, DEL_REQ_FLAG_MTA_VRFY, (VSTRING *) 0, verify_post_mail_action, diff --git a/postfix/utf8test.eml b/postfix/utf8test.eml new file mode 100644 index 000000000..397990db6 --- /dev/null +++ b/postfix/utf8test.eml @@ -0,0 +1,4 @@ +To: jøran@blåbærsyltetøy.gulbrandsen.priv.no +Subject: test + +Blah. diff --git a/postfix/utf8test2.eml b/postfix/utf8test2.eml new file mode 100644 index 000000000..268d509d8 --- /dev/null +++ b/postfix/utf8test2.eml @@ -0,0 +1,4 @@ +To: jøran@blåbærsyltetøy.gulbrandsen.priv.no. +Subject: test + +Blah.