From: Wietse Venema
Date: Thu, 12 Jan 2006 05:00:00 +0000 (-0500)
Subject: postfix-2.3-20060112
X-Git-Tag: v2.3-RC1~24
X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a934ab940e9c88458f95ace79535047f9b57541c;p=thirdparty%2Fpostfix.git
postfix-2.3-20060112
---
diff --git a/postfix/.indent.pro b/postfix/.indent.pro
index 772688817..1d5e8ce8e 100644
--- a/postfix/.indent.pro
+++ b/postfix/.indent.pro
@@ -19,6 +19,7 @@
-TBOUNCE_INFO
-TBOUNCE_LOG
-TBOUNCE_LOG_DSN_BUF
+-TBOUNCE_LOG_FORGE
-TBOUNCE_LOG_RCPT_BUF
-TBOUNCE_STAT
-TBOUNCE_TEMPLATE
@@ -91,7 +92,7 @@
-TDSN
-TDSN_BUF
-TDSN_SPLIT
--TDSN_VAR
+-TDSN_STAT
-TEXPAND_ATTR
-TFILE
-TFORWARD_INFO
@@ -169,7 +170,6 @@
-TRCPT_BUF
-TRECIPIENT
-TRECIPIENT_LIST
--TRECIPIENT_VAR
-TREC_TYPE_NAME
-TRESOLVE_REPLY
-TRESPONSE
diff --git a/postfix/HISTORY b/postfix/HISTORY
index 87355d1e6..8a4f3200f 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -11692,6 +11692,8 @@ Apologies for any names omitted.
20051229
+ The following workaround was removed 20060103.
+
Workaround: when mail is still queued after 3000 seconds,
the SMTP client no longer pipelines the DOT+QUIT commands.
The 20050929 paranoia about malformed server replies
@@ -11727,8 +11729,108 @@ Apologies for any names omitted.
The administrator still has the option to turn off pipelining
by hand if loss of mail is a concern.
+20060103
+
+ Bugfix: the 20051217 fix (when a SASL client password is
+ found, defer delivery when no server-announced mechanism
+ survives the smtp_sasl_mechanism_filter) did the mechanism
+ test too early, so that it could trip up with deliveries
+ to servers that we don't have a SASL password for. Files:
+ smtp/smtp_sasl_proto.c, smtp/smtp_proto.c.
+
+20060104
+
+ Safety: new "smtp_cname_overrides_servername" parameter.
+ The default value ("no") is NOT backwards compatible. This
+ avoids surprises with the hostname that is used for logging,
+ SASL password lookup, TLS policy decisions, or TLS certificate
+ verification. The change makes the 20051221 behavior more
+ configurable. Files: smtp/smtp_addr.c, smtp/smtp_connect.c,
+ proto/postconf.proto.
+
+20060105
+
+ Cleanup: removed the unused DSN "code" attribute; removed
+ surrogate SMTP replies for errors that were not reported
+ by a remote SMTP server, making several DSN-related functions
+ and macros redundant; cleaned up some bizarre code for DSN
+ attribute memory management in the SMTP client.
+
+20060106
+
+ Cleanup: eliminated the global smtp_errno variable, which
+ had become redundant after introducing DSN support. Files:
+ smtp/smtp_addr.c, smtp/smtp_connect.c.
+
+20060107
+
+ Cleanup: removed more bizarre code for DSN attribute memory
+ management in the queue manager, bounce server, and in
+ delivery agents.
+
+20060109
+
+ Bugfix: smtp_sasl_tls_opts was unimplemented. File:
+ smtp/smtp_sasl_proto.c.
+
+ Cleanup: more bounce logfile code cleanup. Files:
+ global/bounce_log.c, bounce/bounce_notify_util.c,
+ bounce/bounce.c, bounce/bounce_notify_verp.c,
+ bounce/bounce_one_service.c, showq/showq.c
+
+20060110
+
+ Cleanup: more bounce logfile code cleanup. Files:
+ global/bounce_log.c, bounce/bounce_notify_util.c.
+
+ Bugfix: the VERP bouncer never handled the case of a missing
+ bounce logfile. Found while doing more logfile code cleanup.
+ File: bounce/bounce_notify_verp.c.
+
+ Feature: smtp_sasl_tls_verified_security_options for
+ connections where the server certificate passed verification.
+ The default value is $smtp_sasl_tls_security_options, which
+ in turn defaults to $smtp_sasl_security_options.
+
+20060111
+
+ Optimization: mystrdup() and mystrndup() now return a pointer
+ to a fixed read-only memory location instead of allocating
+ memory for zero-length null-terminated strings. This saves
+ lots of memory for unused recipient attributes. If this
+ change causes problems (for example, you have an ancient
+ sscanf() implementation that writes to its input) then
+ compile Postfix with -DNO_SHARED_EMPTY_STRINGS.
+
+ Cleanup: eliminated null pointer members in DSN structures.
+ Instead we now use the optimized mystrdup() for empty
+ strings. For safety sake we keep the tests for null pointers
+ in input, but we always produce empty strings on output.
+ Files: global/dsn.c, global/dsn.h, global/dsn_buf.h,
+ global/dsn_print.c.
+
+ Cleanup: eliminated ad-hoc code for passing recipients in
+ the queue manager delivery request protocol. Postfix now
+ uses proper object activation/passivation instead. Files:
+ *qmgr/qmgr_deliver.c, global/deliver_request.c,
+ global/deliver_pass.c.
+
+20060112
+
+ Feature: to simplify debugging the bounce server logs the
+ old and new queue ID when notifying the sender or postmaster.
+ Files: global/post_mail.c, bounce/bounce_notify_service.c,
+ bounce/bounce_one_service.c, bounce/bounce_notify_verp.c,
+ bounce/bounce_warn_service.c, bounce/bounce_trace_service.c.
+
Open problems:
+ Privacy: remove local command/pathname details from remote
+ delivery status reports, and log them via local msg_warn().
+
+ Remove defer(8) and trace(8) references and man pages. These
+ are services not program names.
+
"postsuper -r" no longer resets the message arrival time,
because pickup(8) no longer overrides queue file time stamp
information. This can be a problem when mail "on hold" is
diff --git a/postfix/README_FILES/OVERVIEW b/postfix/README_FILES/OVERVIEW
index 1d9ae180f..c9d40269f 100644
--- a/postfix/README_FILES/OVERVIEW
+++ b/postfix/README_FILES/OVERVIEW
@@ -210,11 +210,12 @@ queues.
Network -> smtpd(8) <-> anvil(8)
- * The bounce(8), defer(8) and trace(8) servers each maintain their own queue
- directory trees with per-message logfiles. This information is used to send
- delivery or non-delivery notifications to the sender.
+ * The bounce(8) server implements the bounce, defer and trace services, which
+ maintain separate directory trees with per-message logfiles. This
+ information is used to send delivery or non-delivery notifications to the
+ sender.
- The trace(8) service implements support for the Postfix "sendmail -bv" and
+ The trace service implements support for the Postfix "sendmail -bv" and
"sendmail -v" commands which produce reports about how Postfix delivers
mail, and is available with Postfix version 2.1 and later. See DEBUG_README
for examples.
@@ -227,8 +228,8 @@ queues.
| v v
(Non-) bounce(8) Queue id,
- delivery <- defer(8) <- recipient,
- notice trace(8) status
+ delivery <- defer <- recipient,
+ notice trace status
^ |
| v
diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES
index fe5033314..96233b96b 100644
--- a/postfix/RELEASE_NOTES
+++ b/postfix/RELEASE_NOTES
@@ -17,6 +17,23 @@ Incompatibility with Postfix 2.1 and earlier
If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
before proceeding.
+Incompatibility with snapshot 20060112
+======================================
+
+The queue manager delivery request protocol has changed. You must
+reload Postfix when upgrading. If you omit this step, delivery
+agents complain with "warning: unexpected attribute original_recipient"
+and mail will not be delivered.
+
+The Postfix SMTP/LMTP client by default no longer allows DNS CNAME
+records to override the server hostname that is used for logging,
+SASL password lookup, TLS policy selection and TLS server certificate
+verification. Specify "smtp_cname_overrides_servername = no" to get
+the old behavior.
+
+Postfix DSN reports no longer make up their own surrogate SMTP
+replies for errors that were not reported by a remote SMTP server.
+
Incompatibility with snapshot 20060103
======================================
diff --git a/postfix/html/bounce.5.html b/postfix/html/bounce.5.html
index b4900f166..104247f9e 100644
--- a/postfix/html/bounce.5.html
+++ b/postfix/html/bounce.5.html
@@ -48,10 +48,10 @@ BOUNCE(5) BOUNCE(5)
appear in the delayed mail notification text.
Once the result is satisfactory, copy the template to the
- Postfix configuration directory and specify in main.cf
+ Postfix configuration directory and specify in main.cf
something like:
- /etc/postfix/main.cf:
+ /etc/postfix/main.cf:
bounce_template_file = /etc/postfix/bounce.cf
TEMPLATE FILE FORMAT
@@ -68,33 +68,41 @@ BOUNCE(5) BOUNCE(5)
with the shell or with Perl (template_name = <<'EOF').
Here is an example:
- # The failure template is used for undeliverable mail.
+ # The failure template is used for undeliverable mail.
- failure_template = <<EOF
- Charset: us-ascii
- From: MAILER-DAEMON (Mail Delivery System)
- Subject: Undelivered Mail Returned to Sender
- Postmaster-Subject: Postmaster Copy: Undelivered Mail
+ failure_template = <<EOF
+ Charset: us-ascii
+ From: MAILER-DAEMON (Mail Delivery System)
+ Subject: Undelivered Mail Returned to Sender
+ Postmaster-Subject: Postmaster Copy: Undelivered Mail
- This is the $mail_name program at host $myhostname.
+ This is the $mail_name program at host $myhostname.
- I'm sorry to have to inform you that your message could not
- be delivered to one or more recipients. It's attached below.
+ I'm sorry to have to inform you that your message could not
+ be delivered to one or more recipients. It's attached below.
- For further assistance, please send mail to <postmaster>
+ For further assistance, please send mail to <postmaster>
- If you do so, please include this problem report. You can
- delete your own text from the attached returned message.
+ If you do so, please include this problem report. You can
+ delete your own text from the attached returned message.
- The $mail_name program
- EOF
+ The $mail_name program
+ EOF
- No special meaning is given to the backslash character or
- to leading whitespace; these are always taken literally.
+ The usage and specification of bounce templates is subject
+ to the following restrictions:
- Outside the << context, lines beginning with "#" are
- ignored, as are empty lines, and lines consisting of
- whitespace only.
+ o No special meaning is given to the backslash char-
+ acter or to leading whitespace; these are always
+ taken literally.
+
+ o Inside the << context, the "$" character is spe-
+ cial. To produce a "$" character as output, specify
+ "$$".
+
+ o Outside the << context, lines beginning with "#"
+ are ignored, as are empty lines, and lines consist-
+ ing of whitespace only.
Examples of all templates can be found in the file
bounce.cf.default in the Postfix configuration directory.
@@ -137,7 +145,7 @@ BOUNCE(5) BOUNCE(5)
o Template message headers must not span multiple
lines.
- o Template message headers must not contain main.cf
+ o Template message headers must not contain main.cf
$parameters.
o Template message headers must contain ASCII charac-
@@ -146,8 +154,8 @@ BOUNCE(5) BOUNCE(5)
TEMPLATE MESSAGE TEXT FORMAT
The second portion of a bounce template consists of mes-
sage text. As the above example shows, template message
- text may contain main.cf $parameters. Besides the parame-
- ters that are defined in main.cf, the following parameters
+ text may contain main.cf $parameters. Besides the parame-
+ ters that are defined in main.cf, the following parameters
are treated specially depending on the suffix that is
appended to their name.
diff --git a/postfix/html/bounce.8.html b/postfix/html/bounce.8.html
index b63647871..da749a991 100644
--- a/postfix/html/bounce.8.html
+++ b/postfix/html/bounce.8.html
@@ -17,7 +17,7 @@ BOUNCE(8) BOUNCE(8)
delivery status 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). This pro-
+ master.cf file (either bounce, defer or trace). This pro-
gram expects to be run from the master(8) process manager.
The bounce(8) daemon processes two types of service
@@ -52,7 +52,7 @@ BOUNCE(8) BOUNCE(8)
Problems and transactions are logged to syslogd(8).
CONFIGURATION PARAMETERS
- Changes to main.cf are picked up automatically, as
+ Changes to main.cf are picked up automatically, as
bounce(8) processes run for only a limited amount of time.
Use the command "postfix reload" to speed up a change.
@@ -82,8 +82,8 @@ BOUNCE(8) BOUNCE(8)
sage templates.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
- master.cf configuration files.
+ The default location of the Postfix main.cf and
+ master.cf configuration files.
daemon_timeout (18000s)
How much time a Postfix daemon process may take to
diff --git a/postfix/html/discard.8.html b/postfix/html/discard.8.html
index 01fd6d459..2fb77c2e1 100644
--- a/postfix/html/discard.8.html
+++ b/postfix/html/discard.8.html
@@ -47,7 +47,7 @@ DISCARD(8) DISCARD(8)
ble.
CONFIGURATION PARAMETERS
- Changes to main.cf are picked up automatically as dis-
+ Changes to main.cf are picked up automatically as dis-
card(8) processes run for only a limited amount of time.
Use the command "postfix reload" to speed up a change.
@@ -55,8 +55,8 @@ DISCARD(8) DISCARD(8)
postconf(5) for more details including examples.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
- master.cf configuration files.
+ The default location of the Postfix main.cf and
+ master.cf configuration files.
daemon_timeout (18000s)
How much time a Postfix daemon process may take to
diff --git a/postfix/html/error.8.html b/postfix/html/error.8.html
index 338b6c9fd..5cf408609 100644
--- a/postfix/html/error.8.html
+++ b/postfix/html/error.8.html
@@ -47,7 +47,7 @@ ERROR(8) ERROR(8)
ble.
CONFIGURATION PARAMETERS
- Changes to main.cf are picked up automatically as error(8)
+ Changes to main.cf are picked up automatically as error(8)
processes run for only a limited amount of time. Use the
command "postfix reload" to speed up a change.
@@ -65,8 +65,8 @@ ERROR(8) ERROR(8)
mail that Postfix did not receive.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
- master.cf configuration files.
+ The default location of the Postfix main.cf and
+ master.cf configuration files.
daemon_timeout (18000s)
How much time a Postfix daemon process may take to
diff --git a/postfix/html/pipe.8.html b/postfix/html/pipe.8.html
index faa3c00f4..8eda4d5f3 100644
--- a/postfix/html/pipe.8.html
+++ b/postfix/html/pipe.8.html
@@ -32,19 +32,19 @@ PIPE(8) PIPE(8)
SINGLE-RECIPIENT DELIVERY
Some external commands cannot handle more than one recipi-
ent per delivery request. Examples of such transports are
- pagers, fax machines, and so on.
+ pagers or fax machines.
To prevent Postfix from sending multiple recipients per
delivery request, specify
transport_destination_recipient_limit = 1
- in the Postfix main.cf file, where transport is the name
- in the first column of the Postfix master.cf entry for the
+ in the Postfix main.cf file, where transport is the name
+ in the first column of the Postfix master.cf entry for the
pipe-based delivery transport.
COMMAND ATTRIBUTE SYNTAX
- The external command attributes are given in the master.cf
+ The external command attributes are given in the master.cf
file at the end of a service definition. The syntax is as
follows:
@@ -330,7 +330,7 @@ PIPE(8) PIPE(8)
fore security sensitive.
CONFIGURATION PARAMETERS
- Changes to main.cf are picked up automatically as pipe(8)
+ Changes to main.cf are picked up automatically as pipe(8)
processes run for only a limited amount of time. Use the
command "postfix reload" to speed up a change.
@@ -360,8 +360,8 @@ PIPE(8) PIPE(8)
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
- master.cf configuration files.
+ The default location of the Postfix main.cf and
+ master.cf configuration files.
daemon_timeout (18000s)
How much time a Postfix daemon process may take to
diff --git a/postfix/html/postconf.5.html b/postfix/html/postconf.5.html
index 44758e17e..6a8686f24 100644
--- a/postfix/html/postconf.5.html
+++ b/postfix/html/postconf.5.html
@@ -3091,6 +3091,17 @@ programs.
+
+
+lmtp_cname_overrides_servername
+(default: yes)
+
+ The LMTP-specific version of the smtp_cname_overrides_servername
+configuration parameter. See there for details.
+
+ This feature is available in Postfix 2.3 and later.
+
+
lmtp_connect_timeout
@@ -3582,7 +3593,7 @@ Example:
lmtp_sasl_tls_security_options
-(default: $var_lmtp_sasl_opts)
+(default: $lmtp_sasl_security_options)
The LMTP-specific version of the smtp_sasl_tls_security_options
configuration parameter. See there for details.
@@ -3590,6 +3601,18 @@ configuration parameter. See there for details.
This feature is available in Postfix 2.3 and later.
+
+
+lmtp_sasl_tls_verified_security_options
+(default: $lmtp_sasl_tls_security_options)
+
+ The LMTP-specific version of the
+smtp_sasl_tls_verified_security_options configuration parameter.
+See there for details.
+
+ This feature is available in Postfix 2.3 and later.
+
+
lmtp_sasl_type
@@ -6399,6 +6422,22 @@ IP hosting, but can be a problem on multi-homed firewalls. See the
but this form is not recommended here.
+
+
+smtp_cname_overrides_servername
+(default: version dependent)
+
+ Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification. The value "no"
+hardens Postfix smtp_tls_per_site hostname-based policies against
+false hostname information in DNS CNAME records, and makes SASL
+password file lookups more predictable. This is the default setting
+as of Postfix 2.3.
+
+ This feature is available in Postfix 2.2.9 and later.
+
+
smtp_connect_timeout
@@ -7192,6 +7231,18 @@ Example:
client uses for TLS encrypted SMTP sessions.
+
+
+smtp_sasl_tls_verified_security_options
+(default: $smtp_sasl_tls_security_options)
+
+ The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate.
+
+ This feature is available in Postfix 2.3 and later.
+
+
smtp_sasl_type
@@ -7527,12 +7578,47 @@ server certificate was issued by a trusted CA.
- Special hint for enforcement mode: since no secure DNS lookup
-mechanism is available, the recommended setup is: specify local
-transport(5) table entries for sensitive domains with explicit
-smtp:[mailhost] destinations (since you can assure security of this
-table unlike DNS), then specify MUST for these mail hosts in the
-smtp_tls_per_site table.
+ Special hints for enforcement mode: since no secure DNS lookup
+mechanism is available, the recommended setup is:
+
+
+
+- Postfix 2.2.9
+
+-
+
+- Specify "smtp_cname_overrides_servername = no". This avoids
+false hostname information in DNS CNAME records that could bypass
+a hostname-based TLS usage policy.
+
+
- Specify local transport(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy.
+
+
- Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+
+
+
+- Postfix < 2.2.9
+
+-
+
+- Specify local transport(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy, but cannot avoid false hostname
+information in DNS CNAME records.
+
+
- Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+
+
+
+
+
+
diff --git a/postfix/html/showq.8.html b/postfix/html/showq.8.html
index 2638a0f60..5cb1f446f 100644
--- a/postfix/html/showq.8.html
+++ b/postfix/html/showq.8.html
@@ -40,7 +40,7 @@ SHOWQ(8) SHOWQ(8)
the maildrop directory.
CONFIGURATION PARAMETERS
- Changes to main.cf are picked up automatically as showq(8)
+ Changes to main.cf are picked up automatically as showq(8)
processes run for only a limited amount of time. Use the
command "postfix reload" to speed up a change.
@@ -48,8 +48,8 @@ SHOWQ(8) SHOWQ(8)
postconf(5) for more details including examples.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
- master.cf configuration files.
+ The default location of the Postfix main.cf and
+ master.cf configuration files.
daemon_timeout (18000s)
How much time a Postfix daemon process may take to
diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html
index 9c0b5d460..54aef3151 100644
--- a/postfix/html/smtp.8.html
+++ b/postfix/html/smtp.8.html
@@ -105,7 +105,6 @@ SMTP(8) SMTP(8)
RFC 1652 (8bit-MIME transport)
RFC 1870 (Message Size Declaration)
RFC 2033 (LMTP protocol)
- RFC 2034 (Enhanced Status Codes)
RFC 2045 (MIME: Format of Internet Message Bodies)
RFC 2046 (MIME: Media Types)
RFC 2554 (AUTH command)
@@ -220,18 +219,26 @@ SMTP(8) SMTP(8)
locally valid address into a globally valid address
when sending mail across the Internet.
+ Available in Postfix version 2.2.9 and later:
+
+ smtp_cname_overrides_servername (version dependent)
+ Allow DNS CNAME records to override the servername
+ that the Postfix SMTP client uses for logging, SASL
+ password lookup, TLS policy decisions, or TLS cer-
+ tificate verification.
+
Available in Postfix version 2.3 and later:
lmtp_discard_lhlo_keyword_address_maps (empty)
- Lookup tables, indexed by the remote LMTP server
- address, with case insensitive lists of LHLO key-
- words (pipelining, starttls, auth, etc.) that the
+ Lookup tables, indexed by the remote LMTP server
+ address, with case insensitive lists of LHLO key-
+ words (pipelining, starttls, auth, etc.) that the
LMTP client will ignore in the LHLO response from a
remote LMTP server.
lmtp_discard_lhlo_keywords ($myhostname)
- A case insensitive list of LHLO keywords (pipelin-
- ing, starttls, auth, etc.) that the LMTP client
+ A case insensitive list of LHLO keywords (pipelin-
+ ing, starttls, auth, etc.) that the LMTP client
will ignore in the LHLO response from a remote LMTP
server.
@@ -239,7 +246,7 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.0 and later:
disable_mime_output_conversion (no)
- Disable the conversion of 8BITMIME format to 7BIT
+ Disable the conversion of 8BITMIME format to 7BIT
format.
mime_boundary_length_limit (2048)
@@ -254,132 +261,132 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.1 and later:
smtp_send_xforward_command (no)
- Send the non-standard XFORWARD command when the
- Postfix SMTP server EHLO response announces XFOR-
+ Send the non-standard XFORWARD command when the
+ Postfix SMTP server EHLO response announces XFOR-
WARD support.
SASL AUTHENTICATION CONTROLS
smtp_sasl_auth_enable (no)
- Enable SASL authentication in the Postfix SMTP
+ Enable SASL authentication in the Postfix SMTP
client.
smtp_sasl_password_maps (empty)
- Optional SMTP client lookup tables with one user-
- name:password entry per remote hostname or domain,
+ Optional SMTP client lookup tables with one user-
+ name:password entry per remote hostname or domain,
or sender address when sender-dependent authentica-
tion is enabled.
smtp_sasl_security_options (noplaintext, noanonymous)
- SASL security options; as of Postfix 2.3 the list
- of available features depends on the SASL client
- implementation that is selected with
+ SASL security options; as of Postfix 2.3 the list
+ of available features depends on the SASL client
+ implementation that is selected with
smtp_sasl_type.
Available in Postfix version 2.2 and later:
smtp_sasl_mechanism_filter (empty)
- If non-empty, a Postfix SMTP client filter for the
- remote SMTP server's list of offered SASL mecha-
+ If non-empty, a Postfix SMTP client filter for the
+ remote SMTP server's list of offered SASL mecha-
nisms.
Available in Postfix version 2.3 and later:
smtp_sender_dependent_authentication (no)
- Enable sender-dependent authentication in the SMTP
- client; this is available only with SASL authenti-
- cation, and disables SMTP connection caching to
- ensure that mail from different senders will use
+ Enable sender-dependent authentication in the SMTP
+ client; this is available only with SASL authenti-
+ cation, and disables SMTP connection caching to
+ ensure that mail from different senders will use
the appropriate credentials.
smtp_sasl_path (empty)
- Implementation-specific information that is passed
- through to the SASL plug-in implementation that is
+ Implementation-specific information that is passed
+ through to the SASL plug-in implementation that is
selected with smtp_sasl_type.
smtp_sasl_type (cyrus)
- The SASL plug-in type that the Postfix SMTP client
+ The SASL plug-in type that the Postfix SMTP client
should use for authentication.
STARTTLS SUPPORT CONTROLS
- Detailed information about STARTTLS configuration may be
+ Detailed information about STARTTLS configuration may be
found in the TLS_README document.
smtp_use_tls (no)
- Opportunistic mode: use TLS when a remote SMTP
- server announces STARTTLS support, otherwise send
+ Opportunistic mode: use TLS when a remote SMTP
+ server announces STARTTLS support, otherwise send
the mail in the clear.
smtp_enforce_tls (no)
- Enforcement mode: require that remote SMTP servers
- use TLS encryption, and never send mail in the
+ Enforcement mode: require that remote SMTP servers
+ use TLS encryption, and never send mail in the
clear.
smtp_sasl_tls_security_options ($smtp_sasl_secu-
rity_options)
- The SASL authentication security options that the
- Postfix SMTP client uses for TLS encrypted SMTP
+ The SASL authentication security options that the
+ Postfix SMTP client uses for TLS encrypted SMTP
sessions.
smtp_starttls_timeout (300s)
- Time limit for Postfix SMTP client write and read
- operations during TLS startup and shutdown hand-
+ Time limit for Postfix SMTP client write and read
+ operations during TLS startup and shutdown hand-
shake procedures.
smtp_tls_CAfile (empty)
- The file with the certificate of the certification
- authority (CA) that issued the Postfix SMTP client
+ The file with the certificate of the certification
+ authority (CA) that issued the Postfix SMTP client
certificate.
smtp_tls_CApath (empty)
- Directory with PEM format certificate authority
- certificates that the Postfix SMTP client uses to
+ Directory with PEM format certificate authority
+ certificates that the Postfix SMTP client uses to
verify a remote SMTP server certificate.
smtp_tls_cert_file (empty)
- File with the Postfix SMTP client RSA certificate
+ File with the Postfix SMTP client RSA certificate
in PEM format.
smtp_tls_cipherlist (empty)
- Controls the Postfix SMTP client TLS cipher selec-
+ Controls the Postfix SMTP client TLS cipher selec-
tion scheme.
smtp_tls_dcert_file (empty)
- File with the Postfix SMTP client DSA certificate
+ File with the Postfix SMTP client DSA certificate
in PEM format.
smtp_tls_dkey_file ($smtp_tls_dcert_file)
- File with the Postfix SMTP client DSA private key
+ File with the Postfix SMTP client DSA private key
in PEM format.
smtp_tls_enforce_peername (yes)
- When TLS encryption is enforced, require that the
+ When TLS encryption is enforced, require that the
remote SMTP server hostname matches the information
in the remote SMTP server certificate.
smtp_tls_key_file ($smtp_tls_cert_file)
- File with the Postfix SMTP client RSA private key
+ File with the Postfix SMTP client RSA private key
in PEM format.
smtp_tls_loglevel (0)
- Enable additional Postfix SMTP client logging of
+ Enable additional Postfix SMTP client logging of
TLS activity.
smtp_tls_note_starttls_offer (no)
- Log the hostname of a remote SMTP server that
- offers STARTTLS, when TLS is not already enabled
+ Log the hostname of a remote SMTP server that
+ offers STARTTLS, when TLS is not already enabled
for that server.
smtp_tls_per_site (empty)
Optional lookup tables with the Postfix SMTP client
- TLS usage policy by next-hop domain name and by
+ TLS usage policy by next-hop domain name and by
remote SMTP server hostname.
smtp_tls_scert_verifydepth (5)
- The verification depth for remote SMTP server cer-
+ The verification depth for remote SMTP server cer-
tificates.
smtp_tls_session_cache_database (empty)
- Name of the file containing the optional Postfix
+ Name of the file containing the optional Postfix
SMTP client TLS session cache.
smtp_tls_session_cache_timeout (3600s)
@@ -387,35 +394,43 @@ SMTP(8) SMTP(8)
sion cache information.
tls_daemon_random_bytes (32)
- The number of pseudo-random bytes that an smtp(8)
- or smtpd(8) process requests from the tlsmgr(8)
- server in order to seed its internal pseudo random
+ The number of pseudo-random bytes that an smtp(8)
+ or smtpd(8) process requests from the tlsmgr(8)
+ server in order to seed its internal pseudo random
number generator (PRNG).
+ Available in Postfix version 2.3 and later:
+
+ smtp_sasl_tls_verified_security_options
+ ($smtp_sasl_tls_security_options)
+ The SASL authentication security options that the
+ Postfix SMTP client uses for TLS encrypted SMTP
+ sessions with a verified server certificate.
+
RESOURCE AND RATE CONTROLS
smtp_destination_concurrency_limit ($default_destina-
tion_concurrency_limit)
- The maximal number of parallel deliveries to the
- same destination via the smtp message delivery
+ The maximal number of parallel deliveries to the
+ same destination via the smtp message delivery
transport.
smtp_destination_recipient_limit ($default_destina-
tion_recipient_limit)
- The maximal number of recipients per delivery via
+ The maximal number of recipients per delivery via
the smtp message delivery transport.
smtp_connect_timeout (30s)
- The SMTP client time limit for completing a TCP
+ The SMTP client time limit for completing a TCP
connection, or zero (use the operating system
built-in time limit).
smtp_helo_timeout (300s)
- The SMTP client time limit for sending the HELO or
- EHLO command, and for receiving the initial server
+ The SMTP client time limit for sending the HELO or
+ EHLO command, and for receiving the initial server
response.
lmtp_lhlo_timeout (300s)
- The LMTP client time limit for sending the LHLO
+ The LMTP client time limit for sending the LHLO
command, and for receiving the initial server
response.
@@ -424,30 +439,30 @@ SMTP(8) SMTP(8)
command, and for receiving the server response.
smtp_mail_timeout (300s)
- The SMTP client time limit for sending the MAIL
- FROM command, and for receiving the server
+ The SMTP client time limit for sending the MAIL
+ FROM command, and for receiving the server
response.
smtp_rcpt_timeout (300s)
- The SMTP client time limit for sending the SMTP
- RCPT TO command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ RCPT TO command, and for receiving the server
response.
smtp_data_init_timeout (120s)
- The SMTP client time limit for sending the SMTP
- DATA command, and for receiving the server
+ The SMTP client time limit for sending the SMTP
+ DATA command, and for receiving the server
response.
smtp_data_xfer_timeout (180s)
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
message content.
smtp_data_done_timeout (600s)
- The SMTP client time limit for sending the SMTP
+ The SMTP client time limit for sending the SMTP
".", and for receiving the server response.
smtp_quit_timeout (300s)
- The SMTP client time limit for sending the QUIT
+ The SMTP client time limit for sending the QUIT
command, and for receiving the server response.
Available in Postfix version 2.1 and later:
@@ -458,12 +473,12 @@ SMTP(8) SMTP(8)
lookups, or zero (no limit).
smtp_mx_session_limit (2)
- The maximal number of SMTP sessions per delivery
- request before giving up or delivering to a fall-
+ The maximal number of SMTP sessions per delivery
+ request before giving up or delivering to a fall-
back relay host, or zero (no limit).
smtp_rset_timeout (20s)
- The SMTP client time limit for sending the RSET
+ The SMTP client time limit for sending the RSET
command, and for receiving the server response.
Available in Postfix version 2.2 and earlier:
@@ -475,11 +490,11 @@ SMTP(8) SMTP(8)
Available in Postfix version 2.2 and later:
smtp_connection_cache_destinations (empty)
- Permanently enable SMTP connection caching for the
+ Permanently enable SMTP connection caching for the
specified destinations.
smtp_connection_cache_on_demand (yes)
- Temporarily enable SMTP connection caching while a
+ Temporarily enable SMTP connection caching while a
destination has a high volume of mail in the active
queue.
@@ -489,57 +504,57 @@ SMTP(8) SMTP(8)
smtp_connection_cache_time_limit (2s)
When SMTP connection caching is enabled, the amount
- of time that an unused SMTP client socket is kept
+ of time that an unused SMTP client socket is kept
open before it is closed.
Available in Postfix version 2.3 and later:
connection_cache_protocol_timeout (5s)
- Time limit for connection cache connect, send or
+ Time limit for connection cache connect, send or
receive operations.
TROUBLE SHOOTING CONTROLS
debug_peer_level (2)
- The increment in verbose logging level when a
- remote client or server matches a pattern in the
+ 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 address patterns that cause the verbose
- logging level to increase by the amount specified
+ 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.
error_notice_recipient (postmaster)
- The recipient of postmaster notifications about
- mail delivery problems that are caused by policy,
+ The recipient of postmaster notifications about
+ mail delivery problems that are caused by policy,
resource, software or protocol errors.
notify_classes (resource, software)
- The list of error classes that are reported to the
+ The list of error classes that are reported to the
postmaster.
MISCELLANEOUS CONTROLS
best_mx_transport (empty)
- Where the Postfix SMTP client should deliver mail
+ Where the Postfix SMTP client should deliver mail
when it detects a "mail loops back to myself" error
condition.
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
+ The default location of the Postfix main.cf and
master.cf configuration files.
daemon_timeout (18000s)
- How much time a Postfix daemon process may take to
- handle a request before it is terminated by a
+ How much time a Postfix daemon process may take to
+ handle a request before it is terminated by a
built-in watchdog timer.
delay_logging_resolution_limit (2)
- The maximal number of digits after the decimal
+ The maximal number of digits after the decimal
point when logging sub-second delay values.
disable_dns_lookups (no)
- Disable DNS lookups in the Postfix SMTP and LMTP
+ Disable DNS lookups in the Postfix SMTP and LMTP
clients.
inet_interfaces (all)
@@ -547,7 +562,7 @@ SMTP(8) SMTP(8)
tem receives mail on.
inet_protocols (ipv4)
- The Internet protocols Postfix will attempt to use
+ The Internet protocols Postfix will attempt to use
when making or accepting connections.
ipc_timeout (3600s)
@@ -555,74 +570,74 @@ SMTP(8) SMTP(8)
over an internal communication channel.
lmtp_tcp_port (24)
- The default TCP port that the Postfix LMTP client
+ The default TCP port that the Postfix LMTP client
connects to.
max_idle (100s)
- The maximum amount of time that an idle Postfix
- daemon process waits for the next service request
+ The maximum amount of time that an idle Postfix
+ daemon process waits for the next service request
before exiting.
max_use (100)
- The maximal number of connection requests before a
+ The maximal number of connection requests before a
Postfix daemon process terminates.
process_id (read-only)
- The process ID of a Postfix command or daemon
+ The process ID of a Postfix command or daemon
process.
process_name (read-only)
- The process name of a Postfix command or daemon
+ The process name of a Postfix command or daemon
process.
proxy_interfaces (empty)
The network interface addresses that this mail sys-
- tem receives mail on by way of a proxy or network
+ tem receives mail on by way of a proxy or network
address translation unit.
smtp_bind_address (empty)
An optional numerical network address that the SMTP
- client should bind to when making an IPv4 connec-
+ client should bind to when making an IPv4 connec-
tion.
smtp_bind_address6 (empty)
An optional numerical network address that the SMTP
- client should bind to when making an IPv6 connec-
+ client should bind to when making an IPv6 connec-
tion.
smtp_helo_name ($myhostname)
- The hostname to send in the SMTP EHLO or HELO com-
+ The hostname to send in the SMTP EHLO or HELO com-
mand.
lmtp_lhlo_name ($myhostname)
The hostname to send in the LMTP LHLO command.
smtp_host_lookup (dns)
- What mechanisms when the SMTP client uses to look
+ What mechanisms when the SMTP client uses to look
up a host's IP address.
smtp_randomize_addresses (yes)
- Randomize the order of equal-preference MX host
+ Randomize the order of equal-preference MX host
addresses.
syslog_facility (mail)
The syslog facility of Postfix logging.
syslog_name (postfix)
- The mail system name that is prepended to the
- process name in syslog records, so that "smtpd"
+ The mail system name that is prepended to the
+ process name in syslog records, so that "smtpd"
becomes, for example, "postfix/smtpd".
Available with Postfix 2.2 and earlier:
fallback_relay (empty)
- Optional list of relay hosts for SMTP destinations
+ Optional list of relay hosts for SMTP destinations
that can't be found or that are unreachable.
Available with Postfix 2.3 and later:
smtp_fallback_relay ($fallback_relay)
- Optional list of relay hosts for SMTP destinations
+ Optional list of relay hosts for SMTP destinations
that can't be found or that are unreachable.
SEE ALSO
@@ -640,7 +655,7 @@ SMTP(8) SMTP(8)
TLS_README, Postfix STARTTLS howto
LICENSE
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
AUTHOR(S)
diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html
index 4304450d9..371d10f56 100644
--- a/postfix/html/smtpd.8.html
+++ b/postfix/html/smtpd.8.html
@@ -33,7 +33,7 @@ SMTPD(8) SMTPD(8)
The SMTP server implements a variety of policies for con-
nection requests, and for parameters given to HELO, ETRN,
MAIL FROM, VRFY and RCPT TO commands. They are detailed
- below and in the main.cf configuration file.
+ below and in the main.cf configuration file.
SECURITY
The SMTP server is moderately security-sensitive. It talks
@@ -47,7 +47,6 @@ SMTPD(8) SMTPD(8)
RFC 1869 (SMTP service extensions)
RFC 1870 (Message Size Declaration)
RFC 1985 (ETRN command)
- RFC 2034 (Enhanced Status Codes)
RFC 2554 (AUTH command)
RFC 2821 (SMTP protocol)
RFC 2920 (SMTP Pipelining)
@@ -63,7 +62,7 @@ SMTPD(8) SMTPD(8)
policy violations, and of other trouble.
CONFIGURATION PARAMETERS
- Changes to main.cf are picked up automatically, as
+ Changes to main.cf are picked up automatically, as
smtpd(8) processes run for only a limited amount of time.
Use the command "postfix reload" to speed up a change.
@@ -872,8 +871,8 @@ SMTPD(8) SMTPD(8)
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
- master.cf configuration files.
+ The default location of the Postfix main.cf and
+ master.cf configuration files.
daemon_timeout (18000s)
How much time a Postfix daemon process may take to
diff --git a/postfix/html/verify.8.html b/postfix/html/verify.8.html
index 9f12a5d41..23dce7167 100644
--- a/postfix/html/verify.8.html
+++ b/postfix/html/verify.8.html
@@ -70,7 +70,7 @@ VERIFY(8) VERIFY(8)
This violates a basic Postfix principle.
CONFIGURATION PARAMETERS
- Changes to main.cf are not picked up automatically, as
+ Changes to main.cf are not picked up automatically, as
verify(8) processes are persistent. Use the command "post-
fix reload" after a configuration change.
@@ -137,8 +137,8 @@ VERIFY(8) VERIFY(8)
MISCELLANEOUS CONTROLS
config_directory (see 'postconf -d' output)
- The default location of the Postfix main.cf and
- master.cf configuration files.
+ The default location of the Postfix main.cf and
+ master.cf configuration files.
daemon_timeout (18000s)
How much time a Postfix daemon process may take to
diff --git a/postfix/man/man5/bounce.5 b/postfix/man/man5/bounce.5
index 4bbe6463a..4d2d591f0 100644
--- a/postfix/man/man5/bounce.5
+++ b/postfix/man/man5/bounce.5
@@ -75,7 +75,7 @@ only. You can change the word EOF, but you can't enclose
it in quotes as with the shell or with Perl (\fItemplate_name\fB
= <<'EOF'\fR). Here is an example:
-.in +2
+.in +4
.nf
.na
# The failure template is used for undeliverable mail.
@@ -99,16 +99,22 @@ delete your own text from the attached returned message.
.ti +12
The $mail_name program
EOF
-.in -2
+.in -4
.ad
.fi
-
+.PP
+The usage and specification of bounce templates is
+subject to the following restrictions:
+.IP \(bu
No special meaning is given to the backslash character or
to leading whitespace; these are always taken literally.
-
+.IP \(bu
+Inside the << context, the "$" character is special. To
+produce a "$" character as output, specify "$$".
+.IP \(bu
Outside the << context, lines beginning with "#" are ignored,
as are empty lines, and lines consisting of whitespace only.
-
+.PP
Examples of all templates can be found in the file
\fBbounce.cf.default\fR in the Postfix configuration
directory.
diff --git a/postfix/man/man5/postconf.5 b/postfix/man/man5/postconf.5
index 7e1dece6e..ddde62dd4 100644
--- a/postfix/man/man5/postconf.5
+++ b/postfix/man/man5/postconf.5
@@ -1666,6 +1666,11 @@ command.
Most of these limitations will be removed after Postfix implements
a connection cache that is shared among multiple LMTP client
programs.
+.SH lmtp_cname_overrides_servername (default: yes)
+The LMTP-specific version of the smtp_cname_overrides_servername
+configuration parameter. See there for details.
+.PP
+This feature is available in Postfix 2.3 and later.
.SH lmtp_connect_timeout (default: 0s)
The LMTP client time limit for completing a TCP connection, or
zero (use the operating system built-in time limit). When no
@@ -1910,11 +1915,17 @@ lmtp_sasl_security_options = noplaintext
.fi
.ad
.ft R
-.SH lmtp_sasl_tls_security_options (default: $var_lmtp_sasl_opts)
+.SH lmtp_sasl_tls_security_options (default: $lmtp_sasl_security_options)
The LMTP-specific version of the smtp_sasl_tls_security_options
configuration parameter. See there for details.
.PP
This feature is available in Postfix 2.3 and later.
+.SH lmtp_sasl_tls_verified_security_options (default: $lmtp_sasl_tls_security_options)
+The LMTP-specific version of the
+smtp_sasl_tls_verified_security_options configuration parameter.
+See there for details.
+.PP
+This feature is available in Postfix 2.3 and later.
.SH lmtp_sasl_type (default: cyrus)
The SASL plug-in type that the Postfix LMTP client should use
for authentication. The available types are listed with the
@@ -3569,6 +3580,16 @@ inet_interfaces documentation for more detail.
.PP
Note 2: address information may be enclosed inside [],
but this form is not recommended here.
+.SH smtp_cname_overrides_servername (default: version dependent)
+Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification. The value "no"
+hardens Postfix smtp_tls_per_site hostname-based policies against
+false hostname information in DNS CNAME records, and makes SASL
+password file lookups more predictable. This is the default setting
+as of Postfix 2.3.
+.PP
+This feature is available in Postfix 2.2.9 and later.
.SH smtp_connect_timeout (default: 30s)
The SMTP client time limit for completing a TCP connection, or
zero (use the operating system built-in time limit).
@@ -4014,6 +4035,12 @@ smtp_sasl_security_options = noplaintext
.SH smtp_sasl_tls_security_options (default: $smtp_sasl_security_options)
The SASL authentication security options that the Postfix SMTP
client uses for TLS encrypted SMTP sessions.
+.SH smtp_sasl_tls_verified_security_options (default: $smtp_sasl_tls_security_options)
+The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate.
+.PP
+This feature is available in Postfix 2.3 and later.
.SH smtp_sasl_type (default: cyrus)
The SASL plug-in type that the Postfix SMTP client should use
for authentication. The available types are listed with the
@@ -4239,12 +4266,32 @@ not require that the remote SMTP server hostname matches the
information in the remote SMTP server certificate, or that the
server certificate was issued by a trusted CA.
.PP
-Special hint for enforcement mode: since no secure DNS lookup
-mechanism is available, the recommended setup is: specify local
-\fBtransport\fR(5) table entries for sensitive domains with explicit
-smtp:[mailhost] destinations (since you can assure security of this
-table unlike DNS), then specify MUST for these mail hosts in the
-smtp_tls_per_site table.
+Special hints for enforcement mode: since no secure DNS lookup
+mechanism is available, the recommended setup is:
+.IP "Postfix 2.2.9"
+.IP \(bu
+Specify "smtp_cname_overrides_servername = no". This avoids
+false hostname information in DNS CNAME records that could bypass
+a hostname-based TLS usage policy.
+.IP \(bu
+Specify local \fBtransport\fR(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy.
+.IP \(bu
+Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+.IP "Postfix < 2.2.9"
+.IP \(bu
+Specify local \fBtransport\fR(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy, but cannot avoid false hostname
+information in DNS CNAME records.
+.IP \(bu
+Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+.PP
.SH smtp_tls_scert_verifydepth (default: 5)
The verification depth for remote SMTP server certificates. A
depth of 1 is sufficient, if the certificate is directly issued by
diff --git a/postfix/man/man8/pipe.8 b/postfix/man/man8/pipe.8
index 70da797c9..c3f653824 100644
--- a/postfix/man/man8/pipe.8
+++ b/postfix/man/man8/pipe.8
@@ -32,8 +32,8 @@ appropriate.
.ad
.fi
Some external commands cannot handle more than one recipient
-per delivery request. Examples of such transports are pagers,
-fax machines, and so on.
+per delivery request. Examples of such transports are pagers
+or fax machines.
To prevent Postfix from sending multiple recipients per delivery
request, specify
diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8
index 0b3b09396..5c82b4c33 100644
--- a/postfix/man/man8/smtp.8
+++ b/postfix/man/man8/smtp.8
@@ -99,7 +99,6 @@ RFC 1651 (SMTP service extensions)
RFC 1652 (8bit-MIME transport)
RFC 1870 (Message Size Declaration)
RFC 2033 (LMTP protocol)
-RFC 2034 (Enhanced Status Codes)
RFC 2045 (MIME: Format of Internet Message Bodies)
RFC 2046 (MIME: Media Types)
RFC 2554 (AUTH command)
@@ -202,6 +201,12 @@ Optional lookup tables that perform address rewriting in the
SMTP client, typically to transform a locally valid address into
a globally valid address when sending mail across the Internet.
.PP
+Available in Postfix version 2.2.9 and later:
+.IP "\fBsmtp_cname_overrides_servername (version dependent)\fR"
+Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification.
+.PP
Available in Postfix version 2.3 and later:
.IP "\fBlmtp_discard_lhlo_keyword_address_maps (empty)\fR"
Lookup tables, indexed by the remote LMTP server address, with
@@ -327,6 +332,12 @@ information.
The number of pseudo-random bytes that an \fBsmtp\fR(8) or \fBsmtpd\fR(8)
process requests from the \fBtlsmgr\fR(8) server in order to seed its
internal pseudo random number generator (PRNG).
+.PP
+Available in Postfix version 2.3 and later:
+.IP "\fBsmtp_sasl_tls_verified_security_options ($smtp_sasl_tls_security_options)\fR"
+The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate.
.SH "RESOURCE AND RATE CONTROLS"
.na
.nf
diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8
index 2a8762e81..fdc89d215 100644
--- a/postfix/man/man8/smtpd.8
+++ b/postfix/man/man8/smtpd.8
@@ -50,7 +50,6 @@ RFC 1652 (8bit-MIME transport)
RFC 1869 (SMTP service extensions)
RFC 1870 (Message Size Declaration)
RFC 1985 (ETRN command)
-RFC 2034 (Enhanced Status Codes)
RFC 2554 (AUTH command)
RFC 2821 (SMTP protocol)
RFC 2920 (SMTP Pipelining)
@@ -114,9 +113,9 @@ What SMTP clients Postfix will not offer AUTH support to.
Available in Postfix version 2.2 and later:
.IP "\fBsmtpd_discard_ehlo_keyword_address_maps (empty)\fR"
Lookup tables, indexed by the remote SMTP client address, with
-case insensitive lists of EHLO keywords (pipelining, starttls,
-auth, etc.) that the SMTP server will not send in the EHLO response
-to a remote SMTP client.
+case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+etc.) that the SMTP server will not send in the EHLO response to a
+remote SMTP client.
.IP "\fBsmtpd_discard_ehlo_keywords (empty)\fR"
A case insensitive list of EHLO keywords (pipelining, starttls,
auth, etc.) that the SMTP server will not send in the EHLO response
diff --git a/postfix/mantools/postlink b/postfix/mantools/postlink
index c2c674a05..8af68581f 100755
--- a/postfix/mantools/postlink
+++ b/postfix/mantools/postlink
@@ -199,6 +199,7 @@ while (<>) {
s;\blmtp_discard_lhlo_keyword_address_maps\b;$&;g;
s;\blmtp_discard_lhlo_keywords\b;$&;g;
s;\blmtp_sasl_tls_security_options\b;$&;g;
+ s;\blmtp_sasl_tls_verified_security_options\b;$&;g;
s;\blmtp_sasl_mechanism_filter\b;$&;g;
s;\blmtp_host_lookup\b;$&;g;
s;\blmtp_connection_cache_destinations\b;$&;g;
@@ -355,6 +356,7 @@ while (<>) {
s;\bsmtp_always_send_ehlo\b;$&;g;
s;\bsmtp_bind_address\b;$&;g;
s;\bsmtp_bind_address6\b;$&;g;
+ s;\bsmtp_cname_overrides_servername\b;$&;g;
s;\bsmtp_connect_timeout\b;$&;g;
s;\bsmtp_connection_cache_on_demand\b;$&;g;
@@ -499,8 +501,8 @@ while (<>) {
s;\bsmtp_enforce_tls\b;$&;g;
s;\bsmtp_fallback_relay\b;$&;g;
- s;\bsmtp_sasl_tls_security_options\b;$&;g;
- s;\bsmtp_sasl_tls_verified_security_options\b;$&;g;
+ s;\bsmtp_[-]*\n* *[]*sasl_[-]*\n* *[]*tls_[-]*\n* *[]*secu[-]*\n* *[]*rity_options\b;$&;g;
+ s;\bsmtp_sasl_tls_verified_secu[-]*\n* *[]*rity_options\b;$&;g;
s;\bsmtp_sasl_type\b;$&;g;
s;\bsmtp_starttls_timeout\b;$&;g;
s;\bsmtp_tls_CAfile\b;$&;g;
diff --git a/postfix/proto/bounce b/postfix/proto/bounce
index f8ffca51b..aaf5fd43f 100644
--- a/postfix/proto/bounce
+++ b/postfix/proto/bounce
@@ -65,7 +65,7 @@
# it in quotes as with the shell or with Perl (\fItemplate_name\fB
# = <<'EOF'\fR). Here is an example:
#
-# .in +2
+# .in +4
# .nf
# .na
# # The failure template is used for undeliverable mail.
@@ -89,16 +89,22 @@
# .ti +12
# The $mail_name program
# EOF
-# .in -2
+# .in -4
# .ad
# .fi
-#
+# .PP
+# The usage and specification of bounce templates is
+# subject to the following restrictions:
+# .IP \(bu
# No special meaning is given to the backslash character or
# to leading whitespace; these are always taken literally.
-#
+# .IP \(bu
+# Inside the << context, the "$" character is special. To
+# produce a "$" character as output, specify "$$".
+# .IP \(bu
# Outside the << context, lines beginning with "#" are ignored,
# as are empty lines, and lines consisting of whitespace only.
-#
+# .PP
# Examples of all templates can be found in the file
# \fBbounce.cf.default\fR in the Postfix configuration
# directory.
diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto
index 65e620d06..e4ac74bfb 100644
--- a/postfix/proto/postconf.proto
+++ b/postfix/proto/postconf.proto
@@ -8538,12 +8538,47 @@ server certificate was issued by a trusted CA.
- Special hint for enforcement mode: since no secure DNS lookup
-mechanism is available, the recommended setup is: specify local
-transport(5) table entries for sensitive domains with explicit
-smtp:[mailhost] destinations (since you can assure security of this
-table unlike DNS), then specify MUST for these mail hosts in the
-smtp_tls_per_site table.
+ Special hints for enforcement mode: since no secure DNS lookup
+mechanism is available, the recommended setup is:
+
+
+
+- Postfix 2.2.9
+
+-
+
+- Specify "smtp_cname_overrides_servername = no". This avoids
+false hostname information in DNS CNAME records that could bypass
+a hostname-based TLS usage policy.
+
+
- Specify local transport(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy.
+
+
- Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+
+
+
+- Postfix < 2.2.9
+
+-
+
+- Specify local transport(5) table entries for sensitive domains
+with explicit smtp:[mailhost] destinations. This avoids false
+hostname information in DNS MX records that could bypass a
+hostname-based TLS usage policy, but cannot avoid false hostname
+information in DNS CNAME records.
+
+
- Specify MUST for these mail hosts in the smtp_tls_per_site
+table.
+
+
+
+
+
+
%PARAM smtp_tls_scert_verifydepth 5
@@ -8866,7 +8901,7 @@ for receiving the initial server response.
Time units: s (seconds), m (minutes), h (hours), d (days), w
(weeks). The default time unit is s (seconds).
-%PARAM lmtp_sasl_tls_security_options $var_lmtp_sasl_opts
+%PARAM lmtp_sasl_tls_security_options $lmtp_sasl_security_options
The LMTP-specific version of the smtp_sasl_tls_security_options
configuration parameter. See there for details.
@@ -9148,3 +9183,38 @@ mailbox_command_maps, mailbox_command, home_mailbox, mail_spool_directory,
fallback_transport_maps, fallback_transport and luser_relay.
This feature is available in Postfix 2.3 and later.
+
+%PARAM smtp_cname_overrides_servername version dependent
+
+ Allow DNS CNAME records to override the servername that the
+Postfix SMTP client uses for logging, SASL password lookup, TLS
+policy decisions, or TLS certificate verification. The value "no"
+hardens Postfix smtp_tls_per_site hostname-based policies against
+false hostname information in DNS CNAME records, and makes SASL
+password file lookups more predictable. This is the default setting
+as of Postfix 2.3.
+
+ This feature is available in Postfix 2.2.9 and later.
+
+%PARAM lmtp_cname_overrides_servername yes
+
+ The LMTP-specific version of the smtp_cname_overrides_servername
+configuration parameter. See there for details.
+
+ This feature is available in Postfix 2.3 and later.
+
+%PARAM smtp_sasl_tls_verified_security_options $smtp_sasl_tls_security_options
+
+ The SASL authentication security options that the Postfix SMTP
+client uses for TLS encrypted SMTP sessions with a verified server
+certificate.
+
+ This feature is available in Postfix 2.3 and later.
+
+%PARAM lmtp_sasl_tls_verified_security_options $lmtp_sasl_tls_security_options
+
+ The LMTP-specific version of the
+smtp_sasl_tls_verified_security_options configuration parameter.
+See there for details.
+
+ This feature is available in Postfix 2.3 and later.
diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c
index 1a19890c7..c7a824ca5 100644
--- a/postfix/src/bounce/bounce.c
+++ b/postfix/src/bounce/bounce.c
@@ -194,14 +194,14 @@ BOUNCE_TEMPLATES *bounce_templates;
#define STR vstring_str
+#define VS_NEUTER(s) printable(vstring_str(s), '?')
+
/* bounce_append_proto - bounce_append server protocol */
static int bounce_append_proto(char *service_name, VSTREAM *client)
{
char *myname = "bounce_append_proto";
int flags;
- RECIPIENT_VAR rcpt;
- DSN_VAR dsn;
/*
* Read and validate the client request.
@@ -215,17 +215,31 @@ static int bounce_append_proto(char *service_name, VSTREAM *client)
msg_warn("malformed request");
return (-1);
}
+
+ /*
+ * Sanitize input.
+ */
if (mail_queue_id_ok(STR(queue_id)) == 0) {
msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
return (-1);
}
- (void) RECIPIENT_FROM_RCPT_BUF(&rcpt, rcpt_buf);
- (void) DSN_FROM_DSN_BUF(&dsn, dsn_buf);
+ VS_NEUTER(rcpt_buf->address);
+ VS_NEUTER(rcpt_buf->orig_addr);
+ VS_NEUTER(rcpt_buf->dsn_orcpt);
+ VS_NEUTER(dsn_buf->status);
+ VS_NEUTER(dsn_buf->action);
+ VS_NEUTER(dsn_buf->reason);
+ VS_NEUTER(dsn_buf->dtype);
+ VS_NEUTER(dsn_buf->dtext);
+ VS_NEUTER(dsn_buf->mtype);
+ VS_NEUTER(dsn_buf->mname);
+ (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf);
+ (void) DSN_FROM_DSN_BUF(dsn_buf);
/*
- * Beware: some dsn or rcpt fields may be null; access dsn_buf and
- * rcpt_buf instead. See DSN_FROM_DSN_BUF(), RECIPIENT_FROM_RCPT_BUF(),
- * and bounce_log(3).
+ * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and
+ * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and
+ * RECIPIENT_FROM_RCPT_BUF().
*/
if (msg_verbose)
msg_info("%s: flags=0x%x service=%s id=%s org_to=%s to=%s off=%ld dsn_org=%s, notif=0x%x stat=%s act=%s why=%s",
@@ -246,7 +260,7 @@ static int bounce_append_proto(char *service_name, VSTREAM *client)
* Execute the request.
*/
return (bounce_append_service(flags, service_name, STR(queue_id),
- &rcpt, &dsn));
+ &rcpt_buf->rcpt, &dsn_buf->dsn));
}
/* bounce_notify_proto - bounce_notify server protocol */
@@ -275,6 +289,10 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client,
msg_warn("malformed request");
return (-1);
}
+
+ /*
+ * Sanitize input.
+ */
if (mail_queue_name_ok(STR(queue_name)) == 0) {
msg_warn("malformed queue name: %s", printable(STR(queue_name), '?'));
return (-1);
@@ -329,6 +347,10 @@ static int bounce_verp_proto(char *service_name, VSTREAM *client)
msg_warn("malformed request");
return (-1);
}
+
+ /*
+ * Sanitize input.
+ */
if (mail_queue_name_ok(STR(queue_name)) == 0) {
msg_warn("malformed queue name: %s", printable(STR(queue_name), '?'));
return (-1);
@@ -380,8 +402,6 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
char *myname = "bounce_one_proto";
int flags;
int dsn_ret;
- RECIPIENT rcpt;
- DSN dsn;
/*
* Read and validate the client request.
@@ -400,6 +420,10 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
msg_warn("malformed request");
return (-1);
}
+
+ /*
+ * Sanitize input.
+ */
if (strcmp(service_name, MAIL_SERVICE_BOUNCE) != 0) {
msg_warn("wrong service name \"%s\" for one-recipient bouncing",
service_name);
@@ -414,13 +438,23 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
return (-1);
}
printable(STR(dsn_envid), '?');
- (void) RECIPIENT_FROM_RCPT_BUF(&rcpt, rcpt_buf);
- (void) DSN_FROM_DSN_BUF(&dsn, dsn_buf);
+ VS_NEUTER(rcpt_buf->address);
+ VS_NEUTER(rcpt_buf->orig_addr);
+ VS_NEUTER(rcpt_buf->dsn_orcpt);
+ VS_NEUTER(dsn_buf->status);
+ VS_NEUTER(dsn_buf->action);
+ VS_NEUTER(dsn_buf->reason);
+ VS_NEUTER(dsn_buf->dtype);
+ VS_NEUTER(dsn_buf->dtext);
+ VS_NEUTER(dsn_buf->mtype);
+ VS_NEUTER(dsn_buf->mname);
+ (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf);
+ (void) DSN_FROM_DSN_BUF(dsn_buf);
/*
- * Beware: some dsn or rcpt fields may be null; access dsn_buf and
- * rcpt_buf instead. See DSN_FROM_DSN_BUF(), RECIPIENT_FROM_RCPT_BUF(),
- * and bounce_log(3).
+ * Beware: some DSN or RECIPIENT fields may be null; access dsn_buf and
+ * rcpt_buf buffers instead. See DSN_FROM_DSN_BUF() and
+ * 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",
@@ -436,7 +470,7 @@ static int bounce_one_proto(char *service_name, VSTREAM *client)
*/
return (bounce_one_service(flags, STR(queue_name), STR(queue_id),
STR(encoding), STR(sender), STR(dsn_envid),
- dsn_ret, &rcpt, &dsn, bounce_templates));
+ dsn_ret, rcpt_buf, dsn_buf, bounce_templates));
}
/* bounce_service - parse bounce command type and delegate */
@@ -536,7 +570,9 @@ static void post_jail_init(char *service_name, char **unused_argv)
/*
* Special case: dump bounce templates. This is not part of the master(5)
- * public interface.
+ * public interface. This internal interface is used by the postconf
+ * command. It was implemented before bounce templates were isolated
+ * into modules that could have been called directly.
*/
if (strcmp(service_name, "dump_templates") == 0) {
bounce_templates_dump(VSTREAM_OUT, bounce_templates);
diff --git a/postfix/src/bounce/bounce_append_service.c b/postfix/src/bounce/bounce_append_service.c
index 868b03e68..582bb1977 100644
--- a/postfix/src/bounce/bounce_append_service.c
+++ b/postfix/src/bounce/bounce_append_service.c
@@ -10,8 +10,8 @@
/* int flags;
/* char *service;
/* char *queue_id;
-/* RECIPIENT_VAR *rcpt;
-/* DSN_VAR *dsn;
+/* RECIPIENT *rcpt;
+/* DSN *dsn;
/* DESCRIPTION
/* This module implements the server side of the bounce_append()
/* (append bounce log) request. This routine either succeeds or
@@ -67,7 +67,7 @@
/* bounce_append_service - append bounce log */
int bounce_append_service(int unused_flags, char *service, char *queue_id,
- RECIPIENT_VAR *rcpt, DSN_VAR *dsn)
+ RECIPIENT *rcpt, DSN *dsn)
{
VSTRING *in_buf = vstring_alloc(100);
VSTREAM *log;
@@ -113,49 +113,41 @@ int bounce_append_service(int unused_flags, char *service, char *queue_id,
msg_fatal("seek file %s %s: %m", service, queue_id);
#define NOT_NULL_EMPTY(s) ((s) != 0 && *(s) != 0)
-#define ST_NEUTER(s) printable((s), '?')
-#define VS_NEUTER(s) printable(vstring_str(s), '?')
+#define STR(x) vstring_str(x)
vstream_fputs("\n", log);
if (var_oldlog_compat) {
vstream_fprintf(log, "<%s>: %s\n", *rcpt->address == 0 ? "" :
- VS_NEUTER(quote_822_local(in_buf, rcpt->address)),
- ST_NEUTER(dsn->reason));
+ STR(quote_822_local(in_buf, rcpt->address)),
+ dsn->reason);
}
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_RECIP, *rcpt->address ?
- VS_NEUTER(quote_822_local(in_buf, rcpt->address)) : "<>");
+ STR(quote_822_local(in_buf, rcpt->address)) : "<>");
if (NOT_NULL_EMPTY(rcpt->orig_addr)
&& strcasecmp(rcpt->address, rcpt->orig_addr) != 0)
vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_ORCPT,
- VS_NEUTER(quote_822_local(in_buf, rcpt->orig_addr)));
+ STR(quote_822_local(in_buf, rcpt->orig_addr)));
if (rcpt->offset > 0)
vstream_fprintf(log, "%s=%ld\n", MAIL_ATTR_OFFSET, rcpt->offset);
if (NOT_NULL_EMPTY(rcpt->dsn_orcpt))
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ORCPT,
- ST_NEUTER(rcpt->dsn_orcpt));
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt);
if (rcpt->dsn_notify != 0)
vstream_fprintf(log, "%s=%d\n", MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify);
if (NOT_NULL_EMPTY(dsn->status))
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_STATUS,
- ST_NEUTER(dsn->status));
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_STATUS, dsn->status);
if (NOT_NULL_EMPTY(dsn->action))
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ACTION,
- ST_NEUTER(dsn->action));
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_ACTION, dsn->action);
if (NOT_NULL_EMPTY(dsn->dtype) && NOT_NULL_EMPTY(dsn->dtext)) {
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTYPE,
- ST_NEUTER(dsn->dtype));
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTEXT,
- ST_NEUTER(dsn->dtext));
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTYPE, dsn->dtype);
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_DTEXT, dsn->dtext);
}
if (NOT_NULL_EMPTY(dsn->mtype) && NOT_NULL_EMPTY(dsn->mname)) {
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MTYPE,
- ST_NEUTER(dsn->mtype));
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MNAME,
- ST_NEUTER(dsn->mname));
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MTYPE, dsn->mtype);
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_DSN_MNAME, dsn->mname);
}
if (NOT_NULL_EMPTY(dsn->reason))
- vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_WHY, ST_NEUTER(dsn->reason));
+ vstream_fprintf(log, "%s=%s\n", MAIL_ATTR_WHY, dsn->reason);
vstream_fputs("\n", log);
if (vstream_fflush(log) != 0 || fsync(vstream_fileno(log)) < 0) {
diff --git a/postfix/src/bounce/bounce_notify_service.c b/postfix/src/bounce/bounce_notify_service.c
index c02ffb9c3..8c3550594 100644
--- a/postfix/src/bounce/bounce_notify_service.c
+++ b/postfix/src/bounce/bounce_notify_service.c
@@ -92,6 +92,7 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
VSTREAM *bounce;
int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
var_notify_classes);
+ VSTRING *new_id = vstring_alloc(10);
char *postmaster;
int count;
@@ -174,7 +175,8 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
postmaster,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
/*
* Double bounce to Postmaster. This is the last opportunity
@@ -192,6 +194,9 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
DSN_NOTIFY_OVERRIDE) > 0) {
bounce_original(bounce, bounce_info, DSN_RET_FULL);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: postmaster non-delivery notification: %s",
+ queue_id, STR(new_id));
} else {
/* No applicable recipients found - cancel this notice. */
(void) vstream_fclose(bounce);
@@ -209,7 +214,8 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
else {
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
/*
* Send the bounce message header, some boilerplate text that
@@ -228,6 +234,9 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
bounce_original(bounce, bounce_info, dsn_ret ?
dsn_ret : DSN_RET_FULL);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: sender non-delivery notification: %s",
+ queue_id, STR(new_id));
} else {
/* No applicable recipients found - cancel this notice. */
(void) vstream_fclose(bounce);
@@ -259,7 +268,8 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
postmaster,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
count = -1;
if (bounce_header(bounce, bounce_info, postmaster,
POSTMASTER_COPY) == 0
@@ -270,6 +280,9 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
DSN_NOTIFY_OVERRIDE) > 0) {
bounce_original(bounce, bounce_info, DSN_RET_HDRS);
postmaster_status = post_mail_fclose(bounce);
+ if (postmaster_status == 0)
+ msg_info("%s: postmaster non-delivery notification: %s",
+ queue_id, STR(new_id));
} else {
/* No applicable recipients found - cancel this notice. */
(void) vstream_fclose(bounce);
@@ -278,8 +291,8 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
}
}
if (postmaster_status)
- msg_warn("postmaster notice failed while bouncing to %s",
- recipient);
+ msg_warn("%s: postmaster notice failed while bouncing to %s",
+ queue_id, recipient);
}
}
@@ -302,6 +315,7 @@ int bounce_notify_service(int flags, char *service, char *queue_name,
* Cleanup.
*/
bounce_mail_free(bounce_info);
+ vstring_free(new_id);
return (bounce_status);
}
diff --git a/postfix/src/bounce/bounce_notify_util.c b/postfix/src/bounce/bounce_notify_util.c
index 0078b680c..39dc887e7 100644
--- a/postfix/src/bounce/bounce_notify_util.c
+++ b/postfix/src/bounce/bounce_notify_util.c
@@ -22,15 +22,15 @@
/* const BOUNCE_TEMPLATE *template;
/*
/* BOUNCE_INFO *bounce_mail_one_init(queue_name, queue_id, encoding,
-/* dsn_envid, dsn_notify, rcpt, dsn,
-/* template)
+/* dsn_envid, dsn_notify, rcpt_buf,
+/* dsn_buf, template)
/* const char *queue_name;
/* const char *queue_id;
/* const char *encoding;
/* int dsn_notify;
/* const char *dsn_envid;
-/* RECIPIENT *rcpt;
-/* DSN *dsn;
+/* RCPT_BUF *rcpt_buf;
+/* DSN_BUF *dsn_buf;
/* const BOUNCE_TEMPLATE *template;
/*
/* void bounce_mail_free(bounce_info)
@@ -160,6 +160,7 @@
#include
#include
#include
+#include /* sscanf() */
#include
#include
#include
@@ -211,6 +212,8 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
const char *queue_id,
const char *encoding,
const char *dsn_envid,
+ RCPT_BUF *rcpt_buf,
+ DSN_BUF *dsn_buf,
BOUNCE_TEMPLATE *template,
BOUNCE_LOG *log_handle)
{
@@ -218,7 +221,7 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
int rec_type;
/*
- * Bundle up a bunch of parameters and initialize information. that will
+ * Bundle up a bunch of parameters and initialize information that will
* be discovered on the fly.
*/
bounce_info = (BOUNCE_INFO *) mymalloc(sizeof(*bounce_info));
@@ -245,6 +248,8 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
bounce_info->arrival_time = 0;
bounce_info->orig_offs = 0;
bounce_info->message_size = 0;
+ bounce_info->rcpt_buf = rcpt_buf;
+ bounce_info->dsn_buf = dsn_buf;
bounce_info->log_handle = log_handle;
/*
@@ -278,9 +283,9 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
msg_fatal("open %s %s: %m", service, queue_id);
/*
- * Skip over the original message envelope records. If the envelope is
- * corrupted just send whatever we can (remember this is a best effort,
- * it does not have to be perfect).
+ * Get time/size/sender information from the original message envelope
+ * records. If the envelope is corrupted just send whatever we can
+ * (remember this is a best effort, it does not have to be perfect).
*
* Lock the file for shared use, so that queue manager leaves it alone after
* restarting.
@@ -294,20 +299,44 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
VSTREAM_PATH(bounce_info->orig_fp));
while ((rec_type = rec_get(bounce_info->orig_fp,
bounce_info->buf, 0)) > 0) {
+
+ /*
+ * Postfix version dependent: data offset in SIZE record.
+ */
if (rec_type == REC_TYPE_SIZE) {
- if (bounce_info->message_size == 0
- && (bounce_info->message_size = atol(STR(bounce_info->buf))) < 0)
+ if (bounce_info->message_size == 0)
+ sscanf(STR(bounce_info->buf), "%ld %ld",
+ &bounce_info->message_size,
+ &bounce_info->orig_offs);
+ if (bounce_info->message_size < 0)
bounce_info->message_size = 0;
- } else if (rec_type == REC_TYPE_TIME) {
+ if (bounce_info->orig_offs < 0)
+ bounce_info->orig_offs = 0;
+ }
+
+ /*
+ * Information for the Arrival-Date: attribute.
+ */
+ else if (rec_type == REC_TYPE_TIME) {
if (bounce_info->arrival_time == 0
&& (bounce_info->arrival_time = atol(STR(bounce_info->buf))) < 0)
bounce_info->arrival_time = 0;
- } else if (rec_type == REC_TYPE_FROM) {
+ }
+
+ /*
+ * Information for the X-Postfix-Sender: attribute.
+ */
+ else if (rec_type == REC_TYPE_FROM) {
quote_822_local_flags(bounce_info->sender,
VSTRING_LEN(bounce_info->buf) ?
STR(bounce_info->buf) :
mail_addr_mail_daemon(), 0);
- } else if (rec_type == REC_TYPE_MESG) {
+ }
+
+ /*
+ * Backwards compatibility: no data offset in SIZE record.
+ */
+ else if (rec_type == REC_TYPE_MESG) {
/* XXX Future: sender+recipient after message content. */
if (VSTRING_LEN(bounce_info->sender) == 0)
msg_warn("%s: no sender before message content record",
@@ -315,6 +344,10 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
bounce_info->orig_offs = vstream_ftell(bounce_info->orig_fp);
break;
}
+ if (bounce_info->orig_offs > 0
+ && bounce_info->arrival_time > 0
+ && VSTRING_LEN(bounce_info->sender) > 0)
+ break;
}
}
return (bounce_info);
@@ -331,6 +364,8 @@ BOUNCE_INFO *bounce_mail_init(const char *service,
{
BOUNCE_INFO *bounce_info;
BOUNCE_LOG *log_handle;
+ RCPT_BUF *rcpt_buf;
+ DSN_BUF *dsn_buf;
/*
* Initialize the bounce_info structure. If the bounce log cannot be
@@ -340,11 +375,18 @@ BOUNCE_INFO *bounce_mail_init(const char *service,
* job. But if the system IS running out of resources, raise a fatal
* run-time error and force a backoff.
*/
- if ((log_handle = bounce_log_open(service, queue_id, O_RDONLY, 0)) == 0
- && errno != ENOENT)
- msg_fatal("open %s %s: %m", service, queue_id);
+ if ((log_handle = bounce_log_open(service, queue_id, O_RDONLY, 0)) == 0) {
+ if (errno != ENOENT)
+ msg_fatal("open %s %s: %m", service, queue_id);
+ rcpt_buf = 0;
+ dsn_buf = 0;
+ } else {
+ rcpt_buf = rcpb_create();
+ dsn_buf = dsb_create();
+ }
bounce_info = bounce_mail_alloc(service, queue_name, queue_id, encoding,
- dsn_envid, template, log_handle);
+ dsn_envid, rcpt_buf, dsn_buf,
+ template, log_handle);
return (bounce_info);
}
@@ -354,20 +396,18 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name,
const char *queue_id,
const char *encoding,
const char *dsn_envid,
- RECIPIENT *rcpt,
- DSN *dsn,
+ RCPT_BUF *rcpt_buf,
+ DSN_BUF *dsn_buf,
BOUNCE_TEMPLATE *template)
{
BOUNCE_INFO *bounce_info;
- BOUNCE_LOG *log_handle;
/*
- * Initialize the bounce_info structure. Forge a logfile record for just
- * one recipient.
+ * Initialize the bounce_info structure for just one recipient.
*/
- log_handle = bounce_log_forge(rcpt, dsn);
bounce_info = bounce_mail_alloc("none", queue_name, queue_id, encoding,
- dsn_envid, template, log_handle);
+ dsn_envid, rcpt_buf, dsn_buf, template,
+ (BOUNCE_LOG *) 0);
return (bounce_info);
}
@@ -375,9 +415,13 @@ BOUNCE_INFO *bounce_mail_one_init(const char *queue_name,
void bounce_mail_free(BOUNCE_INFO *bounce_info)
{
- if (bounce_info->log_handle && bounce_log_close(bounce_info->log_handle))
- msg_warn("%s: read bounce log %s: %m",
- bounce_info->queue_id, bounce_info->queue_id);
+ if (bounce_info->log_handle) {
+ if (bounce_log_close(bounce_info->log_handle))
+ msg_warn("%s: read bounce log %s: %m",
+ bounce_info->queue_id, bounce_info->queue_id);
+ rcpb_free(bounce_info->rcpt_buf);
+ dsb_free(bounce_info->dsn_buf);
+ }
if (bounce_info->orig_fp && vstream_fclose(bounce_info->orig_fp))
msg_warn("%s: read message file %s %s: %m",
bounce_info->queue_id, bounce_info->queue_name,
@@ -480,6 +524,8 @@ static void bounce_print_wrap(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
int bounce_recipient_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
{
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+ DSN *dsn = &bounce_info->dsn_buf->dsn;
/*
* Mask control and non-ASCII characters (done in bounce_log_read()),
@@ -487,16 +533,15 @@ int bounce_recipient_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
* piped into other programs. Sort of like TCP Wrapper's safe_finger
* program.
*/
+#define NON_NULL_EMPTY(s) ((s) && *(s))
+
post_mail_fputs(bounce, "");
- if (bounce_info->log_handle->rcpt.orig_addr) {
+ if (NON_NULL_EMPTY(rcpt->orig_addr)) {
bounce_print_wrap(bounce, bounce_info, "<%s> (expanded from <%s>): %s",
- bounce_info->log_handle->rcpt.address,
- bounce_info->log_handle->rcpt.orig_addr,
- bounce_info->log_handle->dsn.reason);
+ rcpt->address, rcpt->orig_addr, dsn->reason);
} else {
bounce_print_wrap(bounce, bounce_info, "<%s>: %s",
- bounce_info->log_handle->rcpt.address,
- bounce_info->log_handle->dsn.reason);
+ rcpt->address, dsn->reason);
}
return (vstream_ferror(bounce));
}
@@ -506,6 +551,7 @@ int bounce_recipient_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
int bounce_diagnostic_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
int notify_filter)
{
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
int count = 0;
/*
@@ -520,13 +566,15 @@ int bounce_diagnostic_log(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
if (bounce_info->log_handle == 0
|| bounce_log_rewind(bounce_info->log_handle)) {
if (IS_FAILURE_TEMPLATE(bounce_info->template)) {
+ post_mail_fputs(bounce, "");
post_mail_fputs(bounce, "\t--- Delivery report unavailable ---");
count = 1; /* XXX don't abort */
}
} else {
- while (bounce_log_read(bounce_info->log_handle) != 0) {
- if (bounce_info->log_handle->rcpt.dsn_notify == 0 /* compat */
- || (bounce_info->log_handle->rcpt.dsn_notify & notify_filter)) {
+ while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+ bounce_info->dsn_buf) != 0) {
+ if (rcpt->dsn_notify == 0 /* compat */
+ || (rcpt->dsn_notify & notify_filter)) {
count++;
if (bounce_recipient_log(bounce, bounce_info) != 0)
break;
@@ -561,7 +609,7 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
#if 0
post_mail_fprintf(bounce, "Received-From-MTA: dns; %s", "whatever");
#endif
- if (bounce_info->dsn_envid) {
+ if (NON_NULL_EMPTY(bounce_info->dsn_envid)) {
post_mail_fprintf(bounce, "Original-Envelope-Id: %s",
bounce_info->dsn_envid);
}
@@ -580,9 +628,11 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
{
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+ DSN *dsn = &bounce_info->dsn_buf->dsn;
+
post_mail_fputs(bounce, "");
- post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s",
- bounce_info->log_handle->rcpt.address);
+ post_mail_fprintf(bounce, "Final-Recipient: rfc822; %s", rcpt->address);
/*
* XXX DSN
@@ -603,35 +653,29 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
* Postfix always reports an Original-Recipient field, because it is more
* more useful and more consistent.
*/
- if (bounce_info->log_handle->rcpt.dsn_orcpt) {
- post_mail_fprintf(bounce, "Original-Recipient: %s",
- bounce_info->log_handle->rcpt.dsn_orcpt);
- } else if (bounce_info->log_handle->rcpt.orig_addr) {
+ 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",
- bounce_info->log_handle->rcpt.orig_addr);
+ rcpt->orig_addr);
}
post_mail_fprintf(bounce, "Action: %s",
IS_FAILURE_TEMPLATE(bounce_info->template) ?
- "failed" : bounce_info->log_handle->dsn.action);
- post_mail_fprintf(bounce, "Status: %s",
- bounce_info->log_handle->dsn.status);
- if (bounce_info->log_handle->dsn.mtype
- && bounce_info->log_handle->dsn.mname)
+ "failed" : dsn->action);
+ post_mail_fprintf(bounce, "Status: %s", dsn->status);
+ if (NON_NULL_EMPTY(dsn->mtype) && NON_NULL_EMPTY(dsn->mname))
bounce_print_wrap(bounce, bounce_info, "Remote-MTA: %s; %s",
- bounce_info->log_handle->dsn.mtype,
- bounce_info->log_handle->dsn.mname);
- if (bounce_info->log_handle->dsn.dtype
- && bounce_info->log_handle->dsn.dtext)
+ dsn->mtype, dsn->mname);
+ if (NON_NULL_EMPTY(dsn->dtype) && NON_NULL_EMPTY(dsn->dtext))
bounce_print_wrap(bounce, bounce_info, "Diagnostic-Code: %s; %s",
- bounce_info->log_handle->dsn.dtype,
- bounce_info->log_handle->dsn.dtext);
+ dsn->dtype, dsn->dtext);
else
bounce_print_wrap(bounce, bounce_info, "Diagnostic-Code: X-%s; %s",
- bounce_info->mail_name,
- bounce_info->log_handle->dsn.reason);
+ bounce_info->mail_name, dsn->reason);
#if 0
- post_mail_fprintf(bounce, "Last-Attempt-Date: %s",
- bounce_info->log_handle->log_time);
+ if (dsn->time > 0)
+ post_mail_fprintf(bounce, "Last-Attempt-Date: %s",
+ mail_date(dsn->time));
#endif
if (IS_DELAY_TEMPLATE(bounce_info->template))
post_mail_fprintf(bounce, "Will-Retry-Until: %s",
@@ -644,6 +688,7 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
int bounce_diagnostic_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
int notify_filter)
{
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
int count = 0;
/*
@@ -660,9 +705,10 @@ int bounce_diagnostic_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
if (IS_FAILURE_TEMPLATE(bounce_info->template))
count = 1; /* XXX don't abort */
} else {
- while (bounce_log_read(bounce_info->log_handle) != 0) {
- if (bounce_info->log_handle->rcpt.dsn_notify == 0 /* compat */
- || (bounce_info->log_handle->rcpt.dsn_notify & notify_filter)) {
+ while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+ bounce_info->dsn_buf) != 0) {
+ if (rcpt->dsn_notify == 0 /* compat */
+ || (rcpt->dsn_notify & notify_filter)) {
count++;
if (bounce_recipient_dsn(bounce, bounce_info) != 0)
break;
@@ -752,22 +798,23 @@ int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
void bounce_delrcpt(BOUNCE_INFO *bounce_info)
{
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+
if (bounce_info->orig_fp != 0
&& bounce_info->log_handle != 0
&& bounce_log_rewind(bounce_info->log_handle) == 0)
- while (bounce_log_read(bounce_info->log_handle) != 0)
- if (bounce_info->log_handle->rcpt.offset > 0)
- deliver_completed(bounce_info->orig_fp,
- bounce_info->log_handle->rcpt.offset);
+ while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+ bounce_info->dsn_buf) != 0)
+ if (rcpt->offset > 0)
+ deliver_completed(bounce_info->orig_fp, rcpt->offset);
}
/* bounce_delrcpt_one - delete one recipient from original queue file */
void bounce_delrcpt_one(BOUNCE_INFO *bounce_info)
{
- if (bounce_info->orig_fp != 0
- && bounce_info->log_handle != 0
- && bounce_info->log_handle->rcpt.offset > 0)
- deliver_completed(bounce_info->orig_fp,
- bounce_info->log_handle->rcpt.offset);
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+
+ if (bounce_info->orig_fp != 0 && rcpt->offset > 0)
+ deliver_completed(bounce_info->orig_fp, rcpt->offset);
}
diff --git a/postfix/src/bounce/bounce_notify_verp.c b/postfix/src/bounce/bounce_notify_verp.c
index e1f69dc01..9a1913103 100644
--- a/postfix/src/bounce/bounce_notify_verp.c
+++ b/postfix/src/bounce/bounce_notify_verp.c
@@ -97,7 +97,8 @@ int bounce_notify_verp(int flags, char *service, char *queue_name,
int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
var_notify_classes);
char *postmaster;
- VSTRING *verp_buf = vstring_alloc(100);
+ VSTRING *verp_buf;
+ VSTRING *new_id;
/*
* Sanity checks. We must be called only for undeliverable non-bounce
@@ -114,6 +115,27 @@ int bounce_notify_verp(int flags, char *service, char *queue_name,
bounce_info = bounce_mail_init(service, queue_name, queue_id,
encoding, dsn_envid, ts->failure);
+ /*
+ * If we have no recipient list then we can't send VERP replies. Send
+ * *something* anyway so that the mail is not lost in a black hole.
+ */
+ if (bounce_info->log_handle == 0) {
+ DSN_BUF *dsn_buf = dsb_create();
+ RCPT_BUF *rcpt_buf = rcpb_create();
+
+ dsb_simple(dsn_buf, "5.0.0", "(error report unavailable)");
+ (void) DSN_FROM_DSN_BUF(dsn_buf);
+ 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);
+ rcpb_free(rcpt_buf);
+ dsb_free(dsn_buf);
+ bounce_mail_free(bounce_info);
+ return (bounce_status);
+ }
+
#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
#define NULL_TRACE_FLAGS 0
@@ -121,20 +143,24 @@ int bounce_notify_verp(int flags, char *service, char *queue_name,
* A non-bounce message was returned. Send a single bounce, one per
* recipient.
*/
- while (bounce_log_read(bounce_info->log_handle) != 0) {
+ verp_buf = vstring_alloc(100);
+ new_id = vstring_alloc(10);
+ while (bounce_log_read(bounce_info->log_handle, bounce_info->rcpt_buf,
+ bounce_info->dsn_buf) != 0) {
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
/*
* Notify the originator, subject to DSN NOTIFY restrictions.
*/
- if (bounce_info->log_handle->rcpt.dsn_notify != 0 /* compat */
- && (bounce_info->log_handle->rcpt.dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
+ if (rcpt->dsn_notify != 0 /* compat */
+ && (rcpt->dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
bounce_status = 0;
} else {
- verp_sender(verp_buf, verp_delims, recipient,
- bounce_info->log_handle->rcpt.address);
+ verp_sender(verp_buf, verp_delims, recipient, rcpt->address);
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, STR(verp_buf),
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
/*
* Send the bounce message header, some boilerplate text that
@@ -150,6 +176,9 @@ int bounce_notify_verp(int flags, char *service, char *queue_name,
bounce_original(bounce, bounce_info, dsn_ret ?
dsn_ret : DSN_RET_FULL);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: sender non-delivery notification: %s",
+ queue_id, STR(new_id));
} else
bounce_status = 1;
@@ -189,7 +218,8 @@ int bounce_notify_verp(int flags, char *service, char *queue_name,
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
postmaster,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
if (bounce_header(bounce, bounce_info, postmaster,
POSTMASTER_COPY) == 0
&& bounce_recipient_log(bounce, bounce_info) == 0
@@ -197,12 +227,15 @@ int bounce_notify_verp(int flags, char *service, char *queue_name,
&& bounce_recipient_dsn(bounce, bounce_info) == 0)
bounce_original(bounce, bounce_info, DSN_RET_HDRS);
postmaster_status = post_mail_fclose(bounce);
+ if (postmaster_status == 0)
+ msg_info("%s: postmaster non-delivery notification: %s",
+ queue_id, STR(new_id));
} else
postmaster_status = 1;
if (postmaster_status)
- msg_warn("postmaster notice failed while bouncing to %s",
- recipient);
+ msg_warn("%s: postmaster notice failed while bouncing to %s",
+ queue_id, recipient);
}
}
@@ -220,6 +253,7 @@ int bounce_notify_verp(int flags, char *service, char *queue_name,
*/
bounce_mail_free(bounce_info);
vstring_free(verp_buf);
+ vstring_free(new_id);
return (bounce_status);
}
diff --git a/postfix/src/bounce/bounce_one_service.c b/postfix/src/bounce/bounce_one_service.c
index d6355afba..6d6ca629a 100644
--- a/postfix/src/bounce/bounce_one_service.c
+++ b/postfix/src/bounce/bounce_one_service.c
@@ -8,7 +8,7 @@
/*
/* int bounce_one_service(flags, queue_name, queue_id, encoding,
/* orig_sender, envid, ret,
-/* rcpt, dsn, templates)
+/* rcpt_buf, dsn_buf, templates)
/* int flags;
/* char *queue_name;
/* char *queue_id;
@@ -16,8 +16,8 @@
/* char *orig_sender;
/* char *envid;
/* int ret;
-/* RECIPIENT *rcpt;
-/* DSN *dsn;
+/* RCPT_BUF *rcpt_buf;
+/* DSN_BUF *dsn_buf;
/* BOUNCE_TEMPLATES *templates;
/* DESCRIPTION
/* This module implements the server side of the bounce_one()
@@ -86,7 +86,7 @@
int bounce_one_service(int flags, char *queue_name, char *queue_id,
char *encoding, char *orig_sender,
char *dsn_envid, int dsn_ret,
- RECIPIENT *rcpt, DSN *dsn,
+ RCPT_BUF *rcpt_buf, DSN_BUF *dsn_buf,
BOUNCE_TEMPLATES *ts)
{
BOUNCE_INFO *bounce_info;
@@ -95,12 +95,14 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id,
VSTREAM *bounce;
int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
var_notify_classes);
+ VSTRING *new_id = vstring_alloc(10);
/*
* Initialize. Open queue file, bounce log, etc.
*/
bounce_info = bounce_mail_one_init(queue_name, queue_id, encoding,
- dsn_envid, rcpt, dsn, ts->failure);
+ dsn_envid, rcpt_buf, dsn_buf,
+ ts->failure);
#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
#define NULL_TRACE_FLAGS 0
@@ -146,7 +148,8 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id,
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
var_2bounce_rcpt,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
/*
* Double bounce to Postmaster. This is the last opportunity
@@ -161,6 +164,9 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id,
&& bounce_recipient_dsn(bounce, bounce_info) == 0)
bounce_original(bounce, bounce_info, DSN_RET_FULL);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: postmaster non-delivery notification: %s",
+ queue_id, STR(new_id));
}
}
}
@@ -170,13 +176,16 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id,
* restrictions.
*/
else {
- if (bounce_info->log_handle->rcpt.dsn_notify != 0 /* compat */
- && (bounce_info->log_handle->rcpt.dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
+ RECIPIENT *rcpt = &bounce_info->rcpt_buf->rcpt;
+
+ if (rcpt->dsn_notify != 0 /* compat */
+ && (rcpt->dsn_notify & DSN_NOTIFY_FAILURE) == 0) {
bounce_status = 0;
} else {
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, orig_sender,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
/*
* Send the bounce message header, some boilerplate text that
@@ -192,6 +201,9 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id,
bounce_original(bounce, bounce_info, dsn_ret ?
dsn_ret : DSN_RET_FULL);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: sender non-delivery notification: %s",
+ queue_id, STR(new_id));
}
}
@@ -217,7 +229,8 @@ 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,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
if (bounce_header(bounce, bounce_info, var_bounce_rcpt,
POSTMASTER_COPY) == 0
&& bounce_recipient_log(bounce, bounce_info) == 0
@@ -225,10 +238,13 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id,
&& bounce_recipient_dsn(bounce, bounce_info) == 0)
bounce_original(bounce, bounce_info, DSN_RET_HDRS);
postmaster_status = post_mail_fclose(bounce);
+ if (postmaster_status == 0)
+ msg_info("%s: postmaster non-delivery notification: %s",
+ queue_id, STR(new_id));
}
if (postmaster_status)
- msg_warn("postmaster notice failed while bouncing to %s",
- orig_sender);
+ msg_warn("%s: postmaster notice failed while bouncing to %s",
+ queue_id, orig_sender);
}
}
@@ -242,6 +258,7 @@ int bounce_one_service(int flags, char *queue_name, char *queue_id,
* Cleanup.
*/
bounce_mail_free(bounce_info);
+ vstring_free(new_id);
return (bounce_status);
}
diff --git a/postfix/src/bounce/bounce_service.h b/postfix/src/bounce/bounce_service.h
index fb3af89c7..0a9bc4d02 100644
--- a/postfix/src/bounce/bounce_service.h
+++ b/postfix/src/bounce/bounce_service.h
@@ -26,7 +26,7 @@
/*
* bounce_append_service.c
*/
-extern int bounce_append_service(int, char *, char *, RECIPIENT_VAR *, DSN_VAR *);
+extern int bounce_append_service(int, char *, char *, RECIPIENT *, DSN *);
/*
* bounce_notify_service.c
@@ -51,7 +51,7 @@ extern int bounce_notify_verp(int, char *, char *, char *, char *, char *, char
/*
* bounce_one_service.c
*/
-extern int bounce_one_service(int, char *, char *, char *, char *, char *, int, RECIPIENT *, DSN *, BOUNCE_TEMPLATES *);
+extern int bounce_one_service(int, char *, char *, char *, char *, char *, int, RCPT_BUF *, DSN_BUF *, BOUNCE_TEMPLATES *);
/*
* bounce_cleanup.c
@@ -80,6 +80,8 @@ typedef struct {
long orig_offs; /* start of content */
time_t arrival_time; /* time of arrival */
long message_size; /* size of content */
+ RCPT_BUF *rcpt_buf; /* recipient info */
+ DSN_BUF *dsn_buf; /* delivery status info */
BOUNCE_LOG *log_handle; /* open logfile */
char *mail_name; /* $mail_name, cooked */
} BOUNCE_INFO;
@@ -87,7 +89,7 @@ typedef struct {
/* */
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 *, RECIPIENT *, DSN *, BOUNCE_TEMPLATE *);
+extern BOUNCE_INFO *bounce_mail_one_init(const char *, const char *, const char *, 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_templates.c b/postfix/src/bounce/bounce_templates.c
index 381763429..b01f12686 100644
--- a/postfix/src/bounce/bounce_templates.c
+++ b/postfix/src/bounce/bounce_templates.c
@@ -130,7 +130,7 @@ static const char *def_bounce_delay_body[] = {
"# THIS IS A WARNING ONLY. YOU DO NOT NEED TO RESEND YOUR MESSAGE. #",
"####################################################################",
"",
- "Your message could not be delivered for $delay_warning_time_hours hour(s)."
+ "Your message could not be delivered for more than $delay_warning_time_hours hour(s)."
,
"It will be retried until it is $maximal_queue_lifetime_days day(s) old.",
"",
diff --git a/postfix/src/bounce/bounce_trace_service.c b/postfix/src/bounce/bounce_trace_service.c
index 04cf425ce..747e6f400 100644
--- a/postfix/src/bounce/bounce_trace_service.c
+++ b/postfix/src/bounce/bounce_trace_service.c
@@ -83,6 +83,7 @@ int bounce_trace_service(int flags, char *service, char *queue_name,
BOUNCE_INFO *bounce_info;
int bounce_status = 1;
VSTREAM *bounce;
+ VSTRING *new_id = vstring_alloc(10);
int count;
/*
@@ -140,7 +141,8 @@ int bounce_trace_service(int flags, char *service, char *queue_name,
*/
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
count = -1;
if (bounce_header(bounce, bounce_info, recipient,
NO_POSTMASTER_COPY) == 0
@@ -152,6 +154,9 @@ int bounce_trace_service(int flags, char *service, char *queue_name,
DSN_NOTIFY_OVERRIDE) > 0) {
bounce_original(bounce, bounce_info, DSN_RET_HDRS);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: sender delivery status notification: %s",
+ queue_id, STR(new_id));
} else {
(void) vstream_fclose(bounce);
if (count == 0)
@@ -171,6 +176,7 @@ int bounce_trace_service(int flags, char *service, char *queue_name,
* Cleanup.
*/
bounce_mail_free(bounce_info);
+ vstring_free(new_id);
return (bounce_status);
}
diff --git a/postfix/src/bounce/bounce_warn_service.c b/postfix/src/bounce/bounce_warn_service.c
index f446dd6d5..98db272ea 100644
--- a/postfix/src/bounce/bounce_warn_service.c
+++ b/postfix/src/bounce/bounce_warn_service.c
@@ -92,6 +92,7 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
VSTREAM *bounce;
int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
var_notify_classes);
+ VSTRING *new_id = vstring_alloc(10);
char *postmaster;
int count;
@@ -164,7 +165,8 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
postmaster,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
/*
* Double bounce to Postmaster. This is the last opportunity
@@ -182,6 +184,9 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
DSN_NOTIFY_OVERRIDE) > 0) {
bounce_original(bounce, bounce_info, DSN_RET_FULL);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: postmaster delay notification: %s",
+ queue_id, STR(new_id));
} else {
(void) vstream_fclose(bounce);
if (count == 0)
@@ -198,7 +203,8 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
else {
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
/*
* Send the bounce message header, some boilerplate text that
@@ -216,6 +222,9 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
DSN_NOTIFY_DELAY) > 0) {
bounce_original(bounce, bounce_info, DSN_RET_HDRS);
bounce_status = post_mail_fclose(bounce);
+ if (bounce_status == 0)
+ msg_info("%s: sender delay notification: %s",
+ queue_id, STR(new_id));
} else {
(void) vstream_fclose(bounce);
if (count == 0)
@@ -244,7 +253,8 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
postmaster,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS)) != 0) {
+ NULL_TRACE_FLAGS,
+ new_id)) != 0) {
count = -1;
if (bounce_header(bounce, bounce_info, postmaster,
POSTMASTER_COPY) == 0
@@ -255,6 +265,9 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
DSN_NOTIFY_OVERRIDE) > 0) {
bounce_original(bounce, bounce_info, DSN_RET_HDRS);
postmaster_status = post_mail_fclose(bounce);
+ if (postmaster_status == 0)
+ msg_info("%s: postmaster delay notification: %s",
+ queue_id, STR(new_id));
} else {
(void) vstream_fclose(bounce);
if (count == 0)
@@ -262,8 +275,8 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
}
}
if (postmaster_status)
- msg_warn("postmaster notice failed while bouncing to %s",
- recipient);
+ msg_warn("%s: postmaster notice failed while warning %s",
+ queue_id, recipient);
}
}
@@ -271,6 +284,7 @@ int bounce_warn_service(int unused_flags, char *service, char *queue_name,
* Cleanup.
*/
bounce_mail_free(bounce_info);
+ vstring_free(new_id);
return (bounce_status);
}
diff --git a/postfix/src/dns/dns.h b/postfix/src/dns/dns.h
index 415c4703b..705623831 100644
--- a/postfix/src/dns/dns.h
+++ b/postfix/src/dns/dns.h
@@ -80,7 +80,7 @@ typedef struct DNS_FIXED {
* named after the things one can expect to find in a DNS resource record.
*/
typedef struct DNS_RR {
- char *name; /* name, mystrdup()ed */
+ char *qname; /* query name, mystrdup()ed */
char *rname; /* reply name, mystrdup()ed */
unsigned short type; /* T_A, T_CNAME, etc. */
unsigned short class; /* C_IN, etc. */
diff --git a/postfix/src/dns/dns_rr.c b/postfix/src/dns/dns_rr.c
index e4dc0f85e..e2027ba47 100644
--- a/postfix/src/dns/dns_rr.c
+++ b/postfix/src/dns/dns_rr.c
@@ -6,9 +6,9 @@
/* SYNOPSIS
/* #include
/*
-/* DNS_RR *dns_rr_create(name, rname, type, class, ttl, preference,
+/* DNS_RR *dns_rr_create(qname, rname, type, class, ttl, preference,
/* data, data_len)
-/* const char *name;
+/* const char *qname;
/* const char *rname;
/* unsigned short type;
/* unsigned short class;
@@ -46,7 +46,7 @@
/* information, and maintain lists of DNS resource records.
/*
/* dns_rr_create() creates and initializes one resource record.
-/* The \fIname\fR field specifies the query name.
+/* The \fIqname\fR field specifies the query name.
/* The \fIrname\fR field specifies the reply name.
/* \fIpreference\fR is used for MX records; \fIdata\fR is a null
/* pointer or specifies optional resource-specific data;
@@ -59,6 +59,7 @@
/*
/* dns_rr_append() appends a resource record to a (list of) resource
/* record(s).
+/* A null input list is explicitly allowed.
/*
/* dns_rr_sort() sorts a list of resource records into ascending
/* order according to a user-specified criterion. The result is the
@@ -71,6 +72,7 @@
/*
/* dns_rr_remove() removes the specified record from the specified list.
/* The updated list is the result value.
+/* The record MUST be a list member.
/* LICENSE
/* .ad
/* .fi
@@ -100,7 +102,7 @@
/* dns_rr_create - fill in resource record structure */
-DNS_RR *dns_rr_create(const char *name, const char *rname,
+DNS_RR *dns_rr_create(const char *qname, const char *rname,
ushort type, ushort class,
unsigned int ttl, unsigned pref,
const char *data, size_t data_len)
@@ -108,7 +110,7 @@ DNS_RR *dns_rr_create(const char *name, const char *rname,
DNS_RR *rr;
rr = (DNS_RR *) mymalloc(sizeof(*rr) + data_len - 1);
- rr->name = mystrdup(name);
+ rr->qname = mystrdup(qname);
rr->rname = mystrdup(rname);
rr->type = type;
rr->class = class;
@@ -128,7 +130,7 @@ void dns_rr_free(DNS_RR *rr)
if (rr) {
if (rr->next)
dns_rr_free(rr->next);
- myfree(rr->name);
+ myfree(rr->qname);
myfree(rr->rname);
myfree((char *) rr);
}
@@ -146,7 +148,7 @@ DNS_RR *dns_rr_copy(DNS_RR *src)
*/
dst = (DNS_RR *) mymalloc(len);
memcpy((char *) dst, (char *) src, len);
- dst->name = mystrdup(src->name);
+ dst->qname = mystrdup(src->qname);
dst->rname = mystrdup(src->rname);
dst->next = 0;
return (dst);
diff --git a/postfix/src/error/error.c b/postfix/src/error/error.c
index c7be3d6ec..1a13a7613 100644
--- a/postfix/src/error/error.c
+++ b/postfix/src/error/error.c
@@ -178,8 +178,7 @@ static int deliver_message(DELIVER_REQUEST *request)
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset >= 0) {
status = bounce_append(BOUNCE_FLAGS(request), request->queue_id,
- &request->msg_stats, rcpt, "none",
- &dsn);
+ &request->msg_stats, rcpt, "none", &dsn);
if (status == 0)
deliver_completed(src, rcpt->offset);
result |= status;
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index e46bf79a6..1a6faf282 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -642,6 +642,7 @@ deliver_pass.o: dsn_buf.h
deliver_pass.o: mail_params.h
deliver_pass.o: mail_proto.h
deliver_pass.o: msg_stats.h
+deliver_pass.o: rcpt_print.h
deliver_pass.o: recipient_list.h
deliver_request.o: ../../include/attr.h
deliver_request.o: ../../include/iostuff.h
@@ -655,12 +656,12 @@ deliver_request.o: ../../include/vstring.h
deliver_request.o: deliver_request.c
deliver_request.o: deliver_request.h
deliver_request.o: dsn.h
-deliver_request.o: dsn_buf.h
deliver_request.o: dsn_print.h
deliver_request.o: mail_open_ok.h
deliver_request.o: mail_proto.h
deliver_request.o: mail_queue.h
deliver_request.o: msg_stats.h
+deliver_request.o: rcpt_buf.h
deliver_request.o: recipient_list.h
dict_ldap.o: ../../include/argv.h
dict_ldap.o: ../../include/binhash.h
@@ -763,16 +764,14 @@ dsb_scan.o: ../../include/vstream.h
dsb_scan.o: ../../include/vstring.h
dsb_scan.o: dsb_scan.c
dsb_scan.o: dsb_scan.h
+dsb_scan.o: dsn.h
dsb_scan.o: dsn_buf.h
dsb_scan.o: mail_proto.h
dsn.o: ../../include/msg.h
dsn.o: ../../include/mymalloc.h
dsn.o: ../../include/sys_defs.h
-dsn.o: ../../include/vbuf.h
-dsn.o: ../../include/vstring.h
dsn.o: dsn.c
dsn.o: dsn.h
-dsn.o: dsn_buf.h
dsn_attr_map.o: ../../include/attr.h
dsn_attr_map.o: ../../include/iostuff.h
dsn_attr_map.o: ../../include/sys_defs.h
@@ -787,6 +786,7 @@ dsn_buf.o: ../../include/mymalloc.h
dsn_buf.o: ../../include/sys_defs.h
dsn_buf.o: ../../include/vbuf.h
dsn_buf.o: ../../include/vstring.h
+dsn_buf.o: dsn.h
dsn_buf.o: dsn_buf.c
dsn_buf.o: dsn_buf.h
dsn_mask.o: ../../include/msg.h
@@ -800,9 +800,7 @@ dsn_print.o: ../../include/iostuff.h
dsn_print.o: ../../include/sys_defs.h
dsn_print.o: ../../include/vbuf.h
dsn_print.o: ../../include/vstream.h
-dsn_print.o: ../../include/vstring.h
dsn_print.o: dsn.h
-dsn_print.o: dsn_buf.h
dsn_print.o: dsn_print.c
dsn_print.o: dsn_print.h
dsn_print.o: mail_proto.h
@@ -888,7 +886,6 @@ log_adhoc.o: ../../include/vbuf.h
log_adhoc.o: ../../include/vstream.h
log_adhoc.o: ../../include/vstring.h
log_adhoc.o: dsn.h
-log_adhoc.o: dsn_buf.h
log_adhoc.o: log_adhoc.c
log_adhoc.o: log_adhoc.h
log_adhoc.o: mail_params.h
@@ -1041,6 +1038,7 @@ mail_copy.o: ../../include/vbuf.h
mail_copy.o: ../../include/vstream.h
mail_copy.o: ../../include/vstring.h
mail_copy.o: ../../include/vstring_vstream.h
+mail_copy.o: dsn.h
mail_copy.o: dsn_buf.h
mail_copy.o: mail_addr.h
mail_copy.o: mail_copy.c
@@ -1217,7 +1215,6 @@ mark_corrupt.o: ../../include/vstream.h
mark_corrupt.o: ../../include/vstring.h
mark_corrupt.o: deliver_request.h
mark_corrupt.o: dsn.h
-mark_corrupt.o: dsn_buf.h
mark_corrupt.o: mail_params.h
mark_corrupt.o: mail_queue.h
mark_corrupt.o: mark_corrupt.c
@@ -1249,6 +1246,7 @@ mbox_open.o: ../../include/vstream.h
mbox_open.o: ../../include/vstring.h
mbox_open.o: deliver_flock.h
mbox_open.o: dot_lockfile.h
+mbox_open.o: dsn.h
mbox_open.o: dsn_buf.h
mbox_open.o: mbox_conf.h
mbox_open.o: mbox_open.c
@@ -1266,7 +1264,14 @@ mime_state.o: mail_params.h
mime_state.o: mime_state.c
mime_state.o: mime_state.h
mime_state.o: rec_type.h
+mkmap_cdb.o: ../../include/argv.h
+mkmap_cdb.o: ../../include/dict.h
+mkmap_cdb.o: ../../include/dict_cdb.h
+mkmap_cdb.o: ../../include/mymalloc.h
mkmap_cdb.o: ../../include/sys_defs.h
+mkmap_cdb.o: ../../include/vbuf.h
+mkmap_cdb.o: ../../include/vstream.h
+mkmap_cdb.o: mkmap.h
mkmap_cdb.o: mkmap_cdb.c
mkmap_db.o: ../../include/argv.h
mkmap_db.o: ../../include/dict.h
@@ -1407,6 +1412,7 @@ pipe_command.o: ../../include/timed_wait.h
pipe_command.o: ../../include/vbuf.h
pipe_command.o: ../../include/vstream.h
pipe_command.o: ../../include/vstring.h
+pipe_command.o: dsn.h
pipe_command.o: dsn_buf.h
pipe_command.o: dsn_util.h
pipe_command.o: mail_copy.h
@@ -1453,6 +1459,7 @@ rcpt_buf.o: ../../include/vstring.h
rcpt_buf.o: mail_proto.h
rcpt_buf.o: rcpt_buf.c
rcpt_buf.o: rcpt_buf.h
+rcpt_buf.o: recipient_list.h
rcpt_print.o: ../../include/attr.h
rcpt_print.o: ../../include/iostuff.h
rcpt_print.o: ../../include/sys_defs.h
@@ -1754,7 +1761,6 @@ verify.o: ../../include/vstream.h
verify.o: ../../include/vstring.h
verify.o: deliver_request.h
verify.o: dsn.h
-verify.o: dsn_buf.h
verify.o: log_adhoc.h
verify.o: mail_params.h
verify.o: mail_proto.h
@@ -1773,7 +1779,6 @@ verify_clnt.o: ../../include/vstring.h
verify_clnt.o: clnt_stream.h
verify_clnt.o: deliver_request.h
verify_clnt.o: dsn.h
-verify_clnt.o: dsn_buf.h
verify_clnt.o: mail_params.h
verify_clnt.o: mail_proto.h
verify_clnt.o: msg_stats.h
diff --git a/postfix/src/global/bounce.h b/postfix/src/global/bounce.h
index bde6451c1..31f7398d2 100644
--- a/postfix/src/global/bounce.h
+++ b/postfix/src/global/bounce.h
@@ -20,6 +20,7 @@
* Global library.
*/
#include
+#include
/*
* Client interface.
diff --git a/postfix/src/global/bounce_log.c b/postfix/src/global/bounce_log.c
index 0fac7f986..d93198609 100644
--- a/postfix/src/global/bounce_log.c
+++ b/postfix/src/global/bounce_log.c
@@ -8,9 +8,7 @@
/*
/* typedef struct {
/* .in +4
-/* /* Non-null: rcpt.address, dsn.{status,action,text} */
-/* RECIPIENT rcpt;
-/* DSN dsn;
+/* /* No public members. */
/* .in -4
/* } BOUNCE_LOG;
/*
@@ -20,16 +18,14 @@
/* int flags;
/* mode_t mode;
/*
-/* BOUNCE_LOG *bounce_log_read(bp)
+/* BOUNCE_LOG *bounce_log_read(bp, rcpt, dsn)
/* BOUNCE_LOG *bp;
+/* RCPT_BUF *rcpt;
+/* DSN_BUF *dsn;
/*
/* void bounce_log_rewind(bp)
/* BOUNCE_LOG *bp;
/*
-/* BOUNCE_LOG *bounce_log_forge(rcpt, dsn)
-/* RECIPIENT *rcpt;
-/* DSN *dsn;
-/*
/* void bounce_log_close(bp)
/* BOUNCE_LOG *bp;
/* DESCRIPTION
@@ -55,12 +51,6 @@
/* are marked as done). The result is 0 in case of success, -1 in case
/* of problems.
/*
-/* bounce_log_forge() forges one recipient status record
-/* without actually accessing a logfile. No copy is made
-/* of strings with recipient or status information.
-/* The result cannot be used for any logfile access operation
-/* and must be disposed of by passing it to bounce_log_close().
-/*
/* bounce_log_close() closes an open bounce or defer logfile and
/* releases memory for the specified handle. The result is non-zero
/* in case of I/O errors.
@@ -75,38 +65,10 @@
/* File open flags, as with open(2).
/* .IP mode
/* File permissions, as with open(2).
-/* .PP
-/* Recipient results:
-/* .IP address
-/* The final recipient address in RFC 822 external form, or <>
-/* in case of the null recipient address.
-/* .IP dsn_orcpt
-/* Null pointer or DSN original recipient.
-/* .IP orig_addr
-/* Null pointer or the original recipient address in RFC 822
-/* external form.
-/* .IP dsn_notify
-/* Zero or DSN notify flags.
-/* .IP offset
-/* Zero or queue file offset of recipient record.
-/* .PP
-/* Delivery status results:
-/* .IP dsn_status
-/* RFC 3463-compatible enhanced status code (digit.digits.digits).
-/* .IP dsn_action
-/* "delivered", "failed", "delayed" and so on.
-/* .IP reason
-/* The text that explains why the recipient was undeliverable.
-/* .IP dsn_dtype
-/* Null pointer or RFC 3464-compatible diagnostic type.
-/* .IP dsn_dtext
-/* Null pointer or RFC 3464-compatible diagnostic text.
-/* .IP dsn_mtype
-/* Null pointer or RFC 3464-compatible remote MTA type.
-/* .IP dsn_mname
-/* Null pointer or RFC 3464-compatible remote MTA name.
-/* .PP
-/* Other fields will be added as the code evolves.
+/* .IP rcpt
+/* Recipient buffer. The RECIPIENT member is updated.
+/* .IP dsn
+/* Delivery status information. The DSN member is updated.
/* LICENSE
/* .ad
/* .fi
@@ -141,8 +103,6 @@
#include
#include
#include
-#include
-#include
#include
/* Application-specific. */
@@ -160,10 +120,8 @@ BOUNCE_LOG *bounce_log_open(const char *queue_name, const char *queue_id,
#define STREQ(x,y) (strcmp((x),(y)) == 0)
/*
- * TODO: peek at the first byte to see if this is an old-style log
- * (: text) or a new-style extensible log with multiple
- * attributes per recipient. That would not help during a transition from
- * old to new style, where one can expect to find mixed format files.
+ * Logfiles may contain a mixture of old-style (: text) and
+ * new-style entries with multiple attributes per recipient.
*
* Kluge up default DSN status and action for old-style logfiles.
*/
@@ -173,8 +131,6 @@ BOUNCE_LOG *bounce_log_open(const char *queue_name, const char *queue_id,
bp = (BOUNCE_LOG *) mymalloc(sizeof(*bp));
bp->fp = fp;
bp->buf = vstring_alloc(100);
- bp->rcpt_buf = rcpb_create();
- bp->dsn_buf = dsb_create();
if (STREQ(queue_name, MAIL_QUEUE_DEFER)) {
bp->compat_status = mystrdup("4.0.0");
bp->compat_action = mystrdup("delayed");
@@ -188,7 +144,8 @@ BOUNCE_LOG *bounce_log_open(const char *queue_name, const char *queue_id,
/* bounce_log_read - read one record from bounce log file */
-BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
+BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
+ DSN_BUF *dsn_buf)
{
char *recipient;
char *text;
@@ -202,24 +159,11 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
#define FOUND 1 /* in logfile entry */
/*
- * Initialize. See also DSN_FROM_DSN_BUF() and bounce_log_forge() for
- * null and non-null fields.
+ * Initialize.
*/
state = START;
- bp->rcpt.address = "(recipient address unavailable)";
- bp->dsn.status = bp->compat_status;
- bp->dsn.action = bp->compat_action;
- bp->dsn.reason = "(description unavailable)";
-
- bp->rcpt.orig_addr = 0;
- bp->rcpt.dsn_orcpt = 0;
- bp->rcpt.dsn_notify = 0;
- bp->rcpt.offset = 0;
-
- bp->dsn.dtype = 0;
- bp->dsn.dtext = 0;
- bp->dsn.mtype = 0;
- bp->dsn.mname = 0;
+ rcpb_reset(rcpt_buf);
+ dsb_reset(dsn_buf);
/*
* Support mixed logfile formats to make migration easier. The same file
@@ -227,7 +171,9 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
* backwards compatibility, we even have old format followed by new
* format within the same logfile entry!
*/
- while ((vstring_get_nonl(bp->buf, bp->fp) != VSTREAM_EOF)) {
+ for (;;) {
+ if ((vstring_get_nonl(bp->buf, bp->fp) == VSTREAM_EOF))
+ return (0);
/*
* Logfile entries are separated by blank lines. Even the old ad-hoc
@@ -237,7 +183,7 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
*/
if (STR(bp->buf)[0] == 0) {
if (state == FOUND)
- return (bp);
+ break;
state = START;
continue;
}
@@ -259,7 +205,7 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
char *name;
char *value;
long offset;
- long notify;
+ int notify;
/*
* Split into name and value.
@@ -273,51 +219,33 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
* Save attribute value.
*/
if (STREQ(name, MAIL_ATTR_RECIP)) {
- bp->rcpt.address =
- STR(vstring_strcpy(bp->rcpt_buf->address, *value ?
- value : "(MAILER-DAEMON)"));
+ vstring_strcpy(rcpt_buf->address, *value ?
+ value : "(MAILER-DAEMON)");
} else if (STREQ(name, MAIL_ATTR_ORCPT)) {
- bp->rcpt.orig_addr =
- STR(vstring_strcpy(bp->rcpt_buf->orig_addr, *value ?
- value : "(MAILER-DAEMON)"));
+ vstring_strcpy(rcpt_buf->orig_addr, *value ?
+ value : "(MAILER-DAEMON)");
} else if (STREQ(name, MAIL_ATTR_DSN_ORCPT)) {
- if (*value)
- bp->rcpt.dsn_orcpt =
- STR(vstring_strcpy(bp->rcpt_buf->dsn_orcpt, value));
+ vstring_strcpy(rcpt_buf->dsn_orcpt, value);
} else if (STREQ(name, MAIL_ATTR_DSN_NOTIFY)) {
if ((notify = atoi(value)) > 0 && DSN_NOTIFY_OK(notify))
- bp->rcpt.dsn_notify = notify;
+ rcpt_buf->dsn_notify = notify;
} else if (STREQ(name, MAIL_ATTR_OFFSET)) {
if ((offset = atol(value)) > 0)
- bp->rcpt.offset = offset;
+ rcpt_buf->offset = offset;
} else if (STREQ(name, MAIL_ATTR_DSN_STATUS)) {
- if (*value)
- bp->dsn.status =
- STR(vstring_strcpy(bp->dsn_buf->status, value));
+ vstring_strcpy(dsn_buf->status, value);
} else if (STREQ(name, MAIL_ATTR_DSN_ACTION)) {
- if (*value)
- bp->dsn.action =
- STR(vstring_strcpy(bp->dsn_buf->action, value));
+ vstring_strcpy(dsn_buf->action, value);
} else if (STREQ(name, MAIL_ATTR_DSN_DTYPE)) {
- if (*value)
- bp->dsn.dtype =
- STR(vstring_strcpy(bp->dsn_buf->dtype, value));
+ vstring_strcpy(dsn_buf->dtype, value);
} else if (STREQ(name, MAIL_ATTR_DSN_DTEXT)) {
- if (*value)
- bp->dsn.dtext =
- STR(vstring_strcpy(bp->dsn_buf->dtext, value));
+ vstring_strcpy(dsn_buf->dtext, value);
} else if (STREQ(name, MAIL_ATTR_DSN_MTYPE)) {
- if (*value)
- bp->dsn.mtype =
- STR(vstring_strcpy(bp->dsn_buf->mtype, value));
+ vstring_strcpy(dsn_buf->mtype, value);
} else if (STREQ(name, MAIL_ATTR_DSN_MNAME)) {
- if (*value)
- bp->dsn.mname =
- STR(vstring_strcpy(bp->dsn_buf->mname, value));
+ vstring_strcpy(dsn_buf->mname, value);
} else if (STREQ(name, MAIL_ATTR_WHY)) {
- if (*value)
- bp->dsn.reason =
- STR(vstring_strcpy(bp->dsn_buf->reason, value));
+ vstring_strcpy(dsn_buf->reason, value);
} else {
msg_warn("%s: unknown attribute name: %s, ignored",
VSTREAM_PATH(bp->fp), name);
@@ -340,9 +268,8 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
continue;
}
*cp = 0;
- vstring_strcpy(bp->rcpt_buf->address, *recipient ?
+ vstring_strcpy(rcpt_buf->address, *recipient ?
recipient : "(MAILER-DAEMON)");
- bp->rcpt.address = STR(bp->rcpt_buf->address);
/*
* Find the text that explains why mail was not deliverable.
@@ -350,69 +277,26 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
text = cp + 2;
while (*text && ISSPACE(*text))
text++;
- vstring_strcpy(bp->dsn_buf->reason, text);
- if (*text)
- bp->dsn.reason = STR(bp->dsn_buf->reason);
+ vstring_strcpy(dsn_buf->reason, text);
}
- return (0);
-}
-
-/* bounce_log_forge - forge one recipient status record */
-
-BOUNCE_LOG *bounce_log_forge(RECIPIENT *rcpt, DSN *dsn)
-{
- BOUNCE_LOG *bp;
-
- /*
- * Create a partial record. No point copying information that doesn't
- * need to be.
- */
- bp = (BOUNCE_LOG *) mymalloc(sizeof(*bp));
- bp->fp = 0;
- bp->buf = 0;
- bp->rcpt_buf = 0;
- bp->dsn_buf = 0;
- bp->compat_status = 0;
- bp->compat_action = 0;
-
- bp->rcpt = *rcpt;
- bp->dsn = *dsn;
-
- /*
- * Finalize. See also DSN_FROM_DSN_BUF() and bounce_log_read() for null
- * and non-null fields.
- */
-#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
-#define EMPTY_STRING(s) ((s) != 0 && *(s) == 0)
/*
- * Replace null pointers and empty strings by place holders.
+ * Specify place holders for missing fields. See also DSN_FROM_DSN_BUF()
+ * and RECIPIENT_FROM_RCPT_BUF() for null and non-null fields.
*/
- if (bp->rcpt.address == 0)
- bp->rcpt.address = "(recipient address unavailable)";
- if (NULL_OR_EMPTY(bp->dsn.status))
- bp->dsn.status = "(unavailable)";
- if (NULL_OR_EMPTY(bp->dsn.action))
- bp->dsn.action = "(unavailable)";
- if (NULL_OR_EMPTY(bp->dsn.reason))
- bp->dsn.reason = "(description unavailable)";
-
- /*
- * Replace empty strings by null pointers.
- */
- if (EMPTY_STRING(bp->rcpt.orig_addr))
- bp->rcpt.orig_addr = 0;
- if (EMPTY_STRING(bp->rcpt.dsn_orcpt))
- bp->rcpt.dsn_orcpt = 0;
-
- if (EMPTY_STRING(bp->dsn.dtype))
- bp->dsn.dtype = 0;
- if (EMPTY_STRING(bp->dsn.dtext))
- bp->dsn.dtext = 0;
- if (EMPTY_STRING(bp->dsn.mtype))
- bp->dsn.mtype = 0;
- if (EMPTY_STRING(bp->dsn.mname))
- bp->dsn.mname = 0;
+#define BUF_NODATA(buf) (STR(buf)[0] == 0)
+#define BUF_ASSIGN(buf, text) vstring_strcpy((buf), (text))
+
+ if (BUF_NODATA(rcpt_buf->address))
+ BUF_ASSIGN(rcpt_buf->address, "(recipient address unavailable)");
+ if (BUF_NODATA(dsn_buf->status))
+ BUF_ASSIGN(dsn_buf->status, bp->compat_status);
+ if (BUF_NODATA(dsn_buf->action))
+ BUF_ASSIGN(dsn_buf->action, bp->compat_action);
+ if (BUF_NODATA(dsn_buf->reason))
+ BUF_ASSIGN(dsn_buf->reason, "(description unavailable)");
+ (void) RECIPIENT_FROM_RCPT_BUF(rcpt_buf);
+ (void) DSN_FROM_DSN_BUF(dsn_buf);
return (bp);
}
@@ -422,20 +306,10 @@ int bounce_log_close(BOUNCE_LOG *bp)
{
int ret;
- if (bp->fp)
- ret = vstream_fclose(bp->fp);
- else
- ret = 0;
- if (bp->buf)
- vstring_free(bp->buf);
- if (bp->rcpt_buf)
- rcpb_free(bp->rcpt_buf);
- if (bp->dsn_buf)
- dsb_free(bp->dsn_buf);
- if (bp->compat_status)
- myfree(bp->compat_status);
- if (bp->compat_action)
- myfree(bp->compat_action);
+ ret = vstream_fclose(bp->fp);
+ vstring_free(bp->buf);
+ myfree(bp->compat_status);
+ myfree(bp->compat_action);
myfree((char *) bp);
return (ret);
diff --git a/postfix/src/global/bounce_log.h b/postfix/src/global/bounce_log.h
index 235772ed3..03b78b2c4 100644
--- a/postfix/src/global/bounce_log.h
+++ b/postfix/src/global/bounce_log.h
@@ -23,28 +23,20 @@
#include
#include
#include
-#include
/*
* External interface.
*/
typedef struct {
- /* Private. */
VSTREAM *fp; /* open file */
VSTRING *buf; /* I/O buffer */
- RCPT_BUF *rcpt_buf; /* recipient info */
- DSN_BUF *dsn_buf; /* delivery status */
char *compat_status; /* old logfile compatibility */
char *compat_action; /* old logfile compatibility */
- /* Public. */
- RECIPIENT rcpt; /* recipient info */
- DSN dsn; /* delivery status */
} BOUNCE_LOG;
extern BOUNCE_LOG *bounce_log_open(const char *, const char *, int, mode_t);
-extern BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *);
+extern BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *);
extern BOUNCE_LOG *bounce_log_delrcpt(BOUNCE_LOG *);
-extern BOUNCE_LOG *bounce_log_forge(RECIPIENT *, DSN *);
extern int bounce_log_close(BOUNCE_LOG *);
#define bounce_log_rewind(bp) vstream_fseek((bp)->fp, 0L, SEEK_SET)
diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c
index 91675b495..8938e6a88 100644
--- a/postfix/src/global/deliver_pass.c
+++ b/postfix/src/global/deliver_pass.c
@@ -69,6 +69,7 @@
#include
#include
#include
+#include
#define DELIVER_PASS_DEFER 1
#define DELIVER_PASS_UNKNOWN 2
@@ -116,12 +117,10 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, request->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, request->sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, request->rewrite_context,
- ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, rcpt->offset,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt,
- ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify,
- ATTR_TYPE_STR, MAIL_ATTR_ORCPT, rcpt->orig_addr,
- ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
- ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
+ ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, 1,
+ ATTR_TYPE_END);
+ attr_print(stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_FUNC, rcpt_print, (void *) rcpt,
ATTR_TYPE_END);
if (vstream_fflush(stream)) {
@@ -192,17 +191,13 @@ int deliver_pass(const char *class, const char *service,
*/
if (deliver_pass_initial_reply(stream) != 0
|| deliver_pass_send_request(stream, request, nexthop, rcpt) != 0) {
- DSN_SMTP(&dsn, "4.3.0",
- "451 mail transport unavailable",
- "mail transport unavailable");
+ (void) DSN_SIMPLE(&dsn, "4.3.0", "mail transport unavailable");
status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, &request->msg_stats,
rcpt, "none", &dsn);
} else if ((status = deliver_pass_final_reply(stream, dsb))
== DELIVER_PASS_UNKNOWN) {
- DSN_SMTP(&dsn, "4.3.0",
- "451 unknown mail transport error",
- "unknown mail transport error");
+ (void) DSN_SIMPLE(&dsn, "4.3.0", "unknown mail transport error");
status = defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, &request->msg_stats,
rcpt, "none", &dsn);
@@ -227,6 +222,11 @@ int deliver_pass_all(const char *class, const char *service,
RECIPIENT *rcpt;
int status = 0;
+ /*
+ * XXX We should find out if the target transport can handle
+ * multi-recipient requests. Unfortunately such code is hard to test,
+ * rarely used, and therefore will be buggy.
+ */
list = &request->rcpt_list;
for (rcpt = list->info; rcpt < list->info + list->len; rcpt++)
status |= deliver_pass(class, service, request, rcpt);
diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c
index 1391e5d7c..029d2fdef 100644
--- a/postfix/src/global/deliver_request.c
+++ b/postfix/src/global/deliver_request.c
@@ -112,6 +112,7 @@
#include "dsn.h"
#include "dsn_print.h"
#include "deliver_request.h"
+#include "rcpt_buf.h"
/* deliver_request_initial - send initial status code */
@@ -143,13 +144,12 @@ static int deliver_request_final(VSTREAM *stream, DELIVER_REQUEST *request,
{
DSN *hop_status;
int err;
+ /* XXX This DSN structure initialization bypasses integrity checks. */
static DSN dummy_dsn = {"", "", "", "", "", "", ""};
/*
* Send the status and the optional reason.
*/
-#define STRING_OR_EMPTY(s) ((s) ? (s) : "")
-
if ((hop_status = request->hop_status) == 0)
hop_status = &dummy_dsn;
if (msg_verbose)
@@ -185,8 +185,6 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
static VSTRING *queue_id;
static VSTRING *nexthop;
static VSTRING *encoding;
- static VSTRING *dsn_orcpt;
- static VSTRING *orig_addr;
static VSTRING *address;
static VSTRING *client_name;
static VSTRING *client_addr;
@@ -197,9 +195,9 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
static VSTRING *sasl_sender;
static VSTRING *rewrite_context;
static VSTRING *dsn_envid;
- long offset;
+ static RCPT_BUF *rcpt_buf;
+ int rcpt_count;
int dsn_ret;
- int dsn_notify;
/*
* Initialize. For some reason I wanted to allow for multiple instances
@@ -211,9 +209,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
queue_id = vstring_alloc(10);
nexthop = vstring_alloc(10);
encoding = vstring_alloc(10);
- dsn_orcpt = vstring_alloc(10);
- orig_addr = vstring_alloc(10);
- address = vstring_alloc(10);
+ address = vstring_alloc(10);
client_name = vstring_alloc(10);
client_addr = vstring_alloc(10);
client_proto = vstring_alloc(10);
@@ -223,13 +219,14 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
sasl_sender = vstring_alloc(10);
rewrite_context = vstring_alloc(10);
dsn_envid = vstring_alloc(10);
+ rcpt_buf = rcpb_create();
}
/*
* Extract the queue file name, data offset, and sender address. Abort
* the conversation when they send bad information.
*/
- if (attr_scan(stream, ATTR_FLAG_STRICT | ATTR_FLAG_MORE,
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &request->flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id,
@@ -249,7 +246,8 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, rewrite_context,
- ATTR_TYPE_END) != 19) {
+ ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, &rcpt_count,
+ ATTR_TYPE_END) != 20) {
msg_warn("%s: error receiving common attributes", myname);
return (-1);
}
@@ -281,28 +279,18 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
* Extract the recipient offset and address list. Skip over any
* attributes from the sender that we do not understand.
*/
- for (;;) {
- if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
- ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &offset,
+ while (rcpt_count-- > 0) {
+ if (attr_scan(stream, ATTR_FLAG_STRICT,
+ ATTR_TYPE_FUNC, rcpb_scan, (void *) rcpt_buf,
ATTR_TYPE_END) != 1) {
- msg_warn("%s: error receiving offset attribute", myname);
- return (-1);
- }
- if (offset == 0)
- break;
- if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, dsn_orcpt,
- ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, &dsn_notify,
- ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_addr,
- ATTR_TYPE_STR, MAIL_ATTR_RECIP, address,
- ATTR_TYPE_END) != 4) {
msg_warn("%s: error receiving recipient attributes", myname);
return (-1);
}
- recipient_list_add(&request->rcpt_list, offset,
- vstring_str(dsn_orcpt), dsn_notify,
- vstring_str(orig_addr),
- vstring_str(address));
+ recipient_list_add(&request->rcpt_list, rcpt_buf->offset,
+ vstring_str(rcpt_buf->dsn_orcpt),
+ rcpt_buf->dsn_notify,
+ vstring_str(rcpt_buf->orig_addr),
+ vstring_str(rcpt_buf->address));
}
if (request->rcpt_list.len <= 0) {
msg_warn("%s: no recipients in delivery request for destination %s",
diff --git a/postfix/src/global/dsn.c b/postfix/src/global/dsn.c
index b233f56b0..aa78c3b9c 100644
--- a/postfix/src/global/dsn.c
+++ b/postfix/src/global/dsn.c
@@ -8,17 +8,17 @@
/*
/* typedef struct {
/* .in +4
-/* char *status; /* RFC 3463 status */
-/* char *action; /* null or RFC 3464 action */
-/* char *reason; /* human-readable text */
-/* char *dtype; /* null or diagnostic type */
-/* char *dtext; /* null or diagnostic code */
-/* char *mtype; /* null or MTA type */
-/* char *mname; /* null or remote MTA */
+/* const char *status; /* RFC 3463 status */
+/* const char *action; /* null or RFC 3464 action */
+/* const char *reason; /* human-readable text */
+/* const char *dtype; /* null or diagnostic type */
+/* const char *dtext; /* null or diagnostic code */
+/* const char *mtype; /* null or MTA type */
+/* const char *mname; /* null or remote MTA */
/* .in -4
/* } DSN;
/*
-/* DSN *create(status, action, reason, dtype, dtext, mtype, mname)
+/* DSN *create(status, action, reason, dtype, dtext, mtype, mname)
/* const char *status;
/* const char *action;
/* const char *reason;
@@ -27,11 +27,15 @@
/* const char *mtype;
/* const char *mname;
/*
-/* DSN *copy(dsn)
-/* DSN *dsn;
+/* DSN *DSN_COPY(dsn)
+/* DSN *dsn;
/*
-/* DSN *DSN_ASSIGN(dsn, status, action, reason, dtype, dtext, mtype, mname)
-/* DSN *dsn;
+/* void dsn_free(dsn)
+/* DSN *dsn;
+/*
+/* DSN *DSN_ASSIGN(dsn, status, action, reason, dtype, dtext,
+/* mtype, mname)
+/* DSN *dsn;
/* const char *status;
/* const char *action;
/* const char *reason;
@@ -40,21 +44,11 @@
/* const char *mtype;
/* const char *mname;
/*
-/* DSN *DSN_SIMPLE(dsn, status, action, reason)
-/* DSN *dsn;
+/* DSN *DSN_SIMPLE(dsn, status, action, reason)
+/* DSN *dsn;
/* const char *status;
/* const char *action;
/* const char *reason;
-/*
-/* DSN *DSN_SMTP(dsn, status, action, smtp_dtext, reason)
-/* DSN *dsn;
-/* const char *status;
-/* const char *action;
-/* const char *smtp_dtext;
-/* const char *reason;
-/*
-/* void dsn_free(dsn)
-/* DSN *dsn;
/* DESCRIPTION
/* This module maintains delivery error information. For a
/* description of structure field members see "Arguments"
@@ -75,10 +69,8 @@
/* for stack-based short-lived storage.
/*
/* DSN_SIMPLE() takes the minimally required subset of all the
-/* parameters and resets the rest to zero.
-/*
-/* DSN_SMTP() handles the common case of an SMTP-type
-/* diagnostic code that was generated by the local MTA.
+/* attributes and sets the rest to empty strings.
+/* This is a wrapper around the DSN_ASSIGN() macro.
/*
/* Arguments:
/* .IP reason
@@ -88,8 +80,8 @@
/* .IP status
/* Enhanced status code as specified in RFC 3463.
/* .IP action
-/* Action as defined in RFC 3464. If null, a default action
-/* is chosen.
+/* DSN_NO_ACTION, empty string, or action as defined in RFC 3464.
+/* If no action is specified, a default action is chosen.
/* .IP dtype
/* DSN_NO_DTYPE, empty string, or diagnostic code type as
/* specified in RFC 3464.
@@ -102,7 +94,7 @@
/* DSN_NO_MNAME, empty string, or remote MTA as specified in
/* RFC 3464.
/* DIAGNOSTICS
-/* Panic: null status or reason.
+/* Panic: null or empty status or reason.
/* Fatal: out of memory.
/* LICENSE
/* .ad
@@ -140,8 +132,13 @@ DSN *dsn_create(const char *status, const char *action, const char *reason,
dsn = (DSN *) mymalloc(sizeof(*dsn));
/*
- * Status and reason must not be null. Other members may be null pointers
- * or empty strings. Null/empty members are represented as null pointers.
+ * Status and reason must not be empty. Other members may be empty
+ * strings.
+ *
+ * Early implementations represented unavailable information with null
+ * pointers. This resulted in code that was difficult to maintain. We now
+ * use empty strings instead. For safety sake we keep the null pointer
+ * test for input, but we always convert to empty string on output.
*/
#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
@@ -151,7 +148,7 @@ DSN *dsn_create(const char *status, const char *action, const char *reason,
dsn->status = mystrdup(status);
if (NULL_OR_EMPTY(action))
- dsn->action = 0;
+ dsn->action = mystrdup("");
else
dsn->action = mystrdup(action);
@@ -161,15 +158,15 @@ DSN *dsn_create(const char *status, const char *action, const char *reason,
dsn->reason = mystrdup(reason);
if (NULL_OR_EMPTY(dtype) || NULL_OR_EMPTY(dtext)) {
- dsn->dtype = 0;
- dsn->dtext = 0;
+ dsn->dtype = mystrdup("");
+ dsn->dtext = mystrdup("");
} else {
dsn->dtype = mystrdup(dtype);
dsn->dtext = mystrdup(dtext);
}
if (NULL_OR_EMPTY(mtype) || NULL_OR_EMPTY(mname)) {
- dsn->mtype = 0;
- dsn->mname = 0;
+ dsn->mtype = mystrdup("");
+ dsn->mname = mystrdup("");
} else {
dsn->mtype = mystrdup(mtype);
dsn->mname = mystrdup(mname);
@@ -182,16 +179,11 @@ DSN *dsn_create(const char *status, const char *action, const char *reason,
void dsn_free(DSN *dsn)
{
myfree((char *) dsn->status);
- if (dsn->action)
- myfree((char *) dsn->action);
+ myfree((char *) dsn->action);
myfree((char *) dsn->reason);
- if (dsn->dtype)
- myfree((char *) dsn->dtype);
- if (dsn->dtext)
- myfree((char *) dsn->dtext);
- if (dsn->mtype)
- myfree((char *) dsn->mtype);
- if (dsn->mname)
- myfree((char *) dsn->mname);
+ myfree((char *) dsn->dtype);
+ myfree((char *) dsn->dtext);
+ myfree((char *) dsn->mtype);
+ myfree((char *) dsn->mname);
myfree((char *) dsn);
}
diff --git a/postfix/src/global/dsn.h b/postfix/src/global/dsn.h
index 333545f4b..bf49dcb16 100644
--- a/postfix/src/global/dsn.h
+++ b/postfix/src/global/dsn.h
@@ -11,11 +11,6 @@
/* DESCRIPTION
/* .nf
- /*
- * Global library.
- */
-#include
-
/*
* External interface.
*/
@@ -29,19 +24,6 @@ typedef struct {
const char *mname; /* Null / RFC 3464 remote MTA */
} DSN;
- /*
- * Ditto, without const poisoning.
- */
-typedef struct {
- char *status; /* RFC 3463 status */
- char *action; /* Null / RFC 3464 action */
- char *reason; /* descriptive reason */
- char *dtype; /* Null / RFC 3464 diagnostic type */
- char *dtext; /* Null / RFC 3464 diagnostic code */
- char *mtype; /* Null / RFC 3464 MTA type */
- char *mname; /* Null / RFC 3464 remote MTA */
-} DSN_VAR;
-
extern DSN *dsn_create(const char *, const char *, const char *, const char *,
const char *, const char *, const char *);
extern void dsn_free(DSN *);
@@ -58,55 +40,36 @@ extern void dsn_free(DSN *);
#define DSN_SIMPLE(dsn, _status, _reason) \
(((dsn)->status = (_status)), \
- ((dsn)->action = 0), \
+ ((dsn)->action = DSN_NO_ACTION), \
((dsn)->reason = (_reason)), \
- ((dsn)->dtype = 0), \
- ((dsn)->dtext = 0), \
- ((dsn)->mtype = 0), \
- ((dsn)->mname = 0), \
+ ((dsn)->dtype = DSN_NO_DTYPE), \
+ ((dsn)->dtext = DSN_NO_DTEXT), \
+ ((dsn)->mtype = DSN_NO_MTYPE), \
+ ((dsn)->mname = DSN_NO_MNAME), \
(dsn))
-#define DSN_SMTP(dsn, _status, _dtext, _reason) \
- (((dsn)->status = (_status)), \
- ((dsn)->action = 0), \
- ((dsn)->reason = (_reason)), \
- ((dsn)->dtype = DSB_DTYPE_SMTP), \
- ((dsn)->dtext = _dtext), \
- ((dsn)->mtype = 0), \
- ((dsn)->mname = 0), \
- (dsn))
-
-#define DSN_NO_DTYPE 0
-#define DSN_NO_DTEXT 0
-#define DSN_NO_MTYPE 0
-#define DSN_NO_MNAME 0
+#define DSN_NO_ACTION ""
+#define DSN_NO_DTYPE ""
+#define DSN_NO_DTEXT ""
+#define DSN_NO_MTYPE ""
+#define DSN_NO_MNAME ""
/*
- * In order to save space in the queue manager, some DSN fields may be null
- * pointers so that we don't waste memory making copies of empty strings. In
- * addition, sanity requires that the status and reason are never null or
+ * Early implementations represented unavailable information with null
+ * pointers. This resulted in code that is hard to maintain. We now use
+ * empty strings instead. This does not waste precious memory as long as we
+ * can represent empty strings efficiently by collapsing them.
+ *
+ * The only restriction left is that the status and reason are never null or
* empty; this is enforced by dsn_create() which is invoked by DSN_COPY().
- * This complicates the bounce_log(3) and bounce(8) daemons, as well as the
- * server reply parsing code in the smtp(8) and lmtp(8) clients. They must
- * be able to cope with null pointers, and they must never supply empty
- * strings for the required fields.
+ * This complicates the server reply parsing code in the smtp(8) and lmtp(8)
+ * clients. they must never supply empty strings for these required fields.
*/
#define DSN_COPY(dsn) \
dsn_create((dsn)->status, (dsn)->action, (dsn)->reason, \
(dsn)->dtype, (dsn)->dtext, \
(dsn)->mtype, (dsn)->mname)
-#define DSN_STRING_OR_NULL(s) ((s)[0] ? (s) : 0)
-
-#define DSN_FROM_DSN_BUF(dsn, dsb) \
- DSN_ASSIGN((dsn), vstring_str((dsb)->status), \
- DSN_STRING_OR_NULL(vstring_str((dsb)->action)), \
- vstring_str((dsb)->reason), \
- DSN_STRING_OR_NULL(vstring_str((dsb)->dtype)), \
- DSN_STRING_OR_NULL(vstring_str((dsb)->dtext)), \
- DSN_STRING_OR_NULL(vstring_str((dsb)->mtype)), \
- DSN_STRING_OR_NULL(vstring_str((dsb)->mname)))
-
/* LICENSE
/* .ad
/* .fi
diff --git a/postfix/src/global/dsn_buf.c b/postfix/src/global/dsn_buf.c
index c80bc6250..c3c3a7e30 100644
--- a/postfix/src/global/dsn_buf.c
+++ b/postfix/src/global/dsn_buf.c
@@ -1,6 +1,6 @@
/*++
/* NAME
-/* dsbuf 3
+/* dsn_buf 3
/* SUMMARY
/* delivery status buffer
/* SYNOPSIS
@@ -8,20 +8,23 @@
/*
/* typedef struct {
/* .in +4
+/* /* Convenience member */
+/* DSN dsn; /* light-weight, dsn(3) */
+/* /* Formal members... */
/* VSTRING *status; /* RFC 3463 */
/* VSTRING *action; /* RFC 3464 */
/* VSTRING *mtype; /* dns */
/* VSTRING *mname; /* host or domain */
/* VSTRING *dtype; /* smtp, x-unix */
-/* int dcode; /* RFC 2821, sysexits.h */
/* VSTRING *dtext; /* RFC 2821, sysexits.h */
+/* /* Informal members... */
/* VSTRING *reason; /* informal text */
/* .in -4
/* } DSN_BUF;
/*
/* DSN_BUF *dsb_create(void)
/*
-/* DSN_BUF *dsb_update(dsb, status, action, mtype, mname, dtype, dcode,
+/* DSN_BUF *dsb_update(dsb, status, action, mtype, mname, dtype,
/* dtext, reason_fmt, ...)
/* DSN_BUF *dsb;
/* const char *status;
@@ -29,7 +32,6 @@
/* const char *mtype;
/* const char *mname;
/* const char *dtype;
-/* int dcode;
/* const char *dtext;
/* const char *reason_fmt;
/*
@@ -38,17 +40,12 @@
/* const char *status;
/* const char *reason_fmt;
/*
-/* DSN_BUF *dsb_unix(dsb, status, dcode, dtext, reason_fmt, ...)
+/* DSN_BUF *dsb_unix(dsb, status, dtext, reason_fmt, ...)
/* DSN_BUF *dsb;
/* const char *status;
/* const char *reason_fmt;
/*
-/* DSN_BUF *dsb_smtp(dsb, status, dcode, dtext, reason_fmt, ...)
-/* DSN_BUF *dsb;
-/* const char *status;
-/* const char *reason_fmt;
-/*
-/* DSN_BUF *dsb_formal(dsb, status, action, mtype, mname, dtype, dcode,
+/* DSN_BUF *dsb_formal(dsb, status, action, mtype, mname, dtype,
/* dtext)
/* DSN_BUF *dsb;
/* const char *status;
@@ -56,7 +53,6 @@
/* const char *mtype;
/* const char *mname;
/* const char *dtype;
-/* int dcode;
/* const char *dtext;
/*
/* DSN_BUF *dsb_status(dsb, status)
@@ -64,12 +60,17 @@
/* const char *status;
/*
/* void dsb_reset(dsb)
+/* DSN_BUF *dsb;
/*
/* void dsb_free(dsb)
+/* DSN_BUF *dsb;
+/*
+/* DSN *DSN_FROM_DSN_BUF(dsb)
+/* DSN_BUF *dsb;
/* DESCRIPTION
/* This module implements a simple to update delivery status
-/* buffer for Postfix-internal use. Typically it is populated
-/* in course of delivery attempt, and then formatted into a
+/* buffer for Postfix-internal use. Typically it is filled in
+/* the course of delivery attempt, and then formatted into a
/* DSN structure for external notification.
/*
/* dsb_create() creates initialized storage for formal RFC 3464
@@ -84,8 +85,6 @@
/* text, and informal text, sets the diagnostic type to UNIX,
/* and resets all other fields to defaults.
/*
-/* dsb_smtp() does the same for SMTP style diagnostics.
-/*
/* dsb_formal() updates all fields except the informal text.
/*
/* dsb_status() updates the status field, and resets all
@@ -97,6 +96,11 @@
/* dsb_free() recycles the storage that was allocated by
/* dsb_create(), and so on.
/*
+/* DSN_FROM_DSN_BUF() populates the DSN member with a shallow
+/* copy of the contents of the formal and informal fields, and
+/* returns a pointer to the DSN member. This is typically used
+/* for external reporting.
+/*
/* Arguments:
/* .IP dsb
/* Delivery status buffer.
@@ -108,24 +112,20 @@
/* matter here are "expanded" and "relayed"; all other values
/* are already implied by the context.
/* .IP mtype
+/* The remote MTA type.
/* The only valid type is DSB_MTYPE_DNS. The macro DSB_SKIP_RMTA
/* conveniently expands into a null argument list for the
/* remote MTA type and name.
/* .IP mname
/* Remote MTA name.
/* .IP dtype
+/* The reply type.
/* DSB_DTYPE_SMTP or DSB_DTYPE_UNIX. The macro DSB_SKIP_REPLY
/* conveniently expands into a null argument list for the reply
-/* type, code and text.
-/* .IP dcode
-/* Numerical reply code. The reply code is reset when dtype is
-/* DSB_SKIP_REPLY.
+/* type and text.
/* .IP dtext
/* The reply text. The reply text is reset when dtype is
/* DSB_SKIP_REPLY.
-/* .IP reply_fmt
-/* The reply text format. The reply text is reset when type
-/* is DSB_SKIP_REPLY.
/* .IP reason_fmt
/* The informal reason format.
/* SEE ALSO
@@ -179,7 +179,6 @@ DSN_BUF *dsb_create(void)
dsb->mtype = vstring_alloc(10);
dsb->mname = vstring_alloc(100);
dsb->dtype = vstring_alloc(10);
- dsb->dcode = 0;
dsb->dtext = vstring_alloc(100);
dsb->reason = vstring_alloc(100);
@@ -200,13 +199,22 @@ void dsb_free(DSN_BUF *dsb)
myfree((char *) dsb);
}
+ /*
+ * Initial versions of this code represented unavailable inputs with null
+ * pointers, which produced fragile and hard to maintain code. The current
+ * code uses empty strings instead of null pointers.
+ *
+ * For safety we keep the test for null pointers in input. It's cheap.
+ */
#define DSB_TRUNCATE(s) (STR(s)[0] = 0)
+#define NULL_OR_EMPTY(s) ((s) == 0 || *(s) == 0)
+
#define DSB_ACTION(dsb, stat, act) \
- vstring_strcpy((dsb)->action, (act) && *(act) ? (act) : "")
+ vstring_strcpy((dsb)->action, !NULL_OR_EMPTY(act) ? (act) : "")
#define DSB_MTA(dsb, type, name) do { \
- if ((type) == 0) { \
+ if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(name)) { \
DSB_TRUNCATE((dsb)->mtype); \
DSB_TRUNCATE((dsb)->mname); \
} else { \
@@ -215,11 +223,21 @@ void dsb_free(DSN_BUF *dsb)
} \
} while (0)
+#define DSB_DIAG(dsb, type, text) do { \
+ if (NULL_OR_EMPTY(type) || NULL_OR_EMPTY(text)) { \
+ DSB_TRUNCATE((dsb)->dtype); \
+ DSB_TRUNCATE((dsb)->dtext); \
+ } else { \
+ vstring_strcpy((dsb)->dtype, (type)); \
+ vstring_strcpy((dsb)->dtext, (text)); \
+ } \
+} while (0)
+
/* dsb_update - update formal attributes and informal text */
DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
const char *mtype, const char *mname,
- const char *dtype, int dcode, const char *dtext,
+ const char *dtype, const char *dtext,
const char *format,...)
{
va_list ap;
@@ -227,15 +245,7 @@ DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
vstring_strcpy(dsb->status, status);
DSB_ACTION(dsb, status, action);
DSB_MTA(dsb, mtype, mname);
- if (dtype == 0) {
- DSB_TRUNCATE(dsb->dtype);
- dsb->dcode = 0;
- DSB_TRUNCATE(dsb->dtext);
- } else {
- vstring_strcpy(dsb->dtype, dtype);
- dsb->dcode = dcode;
- vstring_strcpy(dsb->dtext, dtext);
- }
+ DSB_DIAG(dsb, dtype, dtext);
va_start(ap, format);
vstring_vsprintf(dsb->reason, format, ap);
va_end(ap);
@@ -243,7 +253,7 @@ DSN_BUF *dsb_update(DSN_BUF *dsb, const char *status, const char *action,
return (dsb);
}
-/* dsb_simple - update status and text */
+/* dsb_simple - update status and informal text */
DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
{
@@ -254,7 +264,6 @@ DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
DSB_TRUNCATE(dsb->mtype);
DSB_TRUNCATE(dsb->mname);
DSB_TRUNCATE(dsb->dtype);
- dsb->dcode = 0;
DSB_TRUNCATE(dsb->dtext);
va_start(ap, format);
vstring_vsprintf(dsb->reason, format, ap);
@@ -263,9 +272,9 @@ DSN_BUF *dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
return (dsb);
}
-/* dsb_unix - update status, UNIX diagnostic and text */
+/* dsb_unix - update status, UNIX diagnostic and informal text */
-DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status, int dcode,
+DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status,
const char *dtext, const char *format,...)
{
va_list ap;
@@ -275,28 +284,6 @@ DSN_BUF *dsb_unix(DSN_BUF *dsb, const char *status, int dcode,
DSB_TRUNCATE(dsb->mtype);
DSB_TRUNCATE(dsb->mname);
vstring_strcpy(dsb->dtype, DSB_DTYPE_UNIX);
- dsb->dcode = dcode;
- vstring_strcpy(dsb->dtext, dtext);
- va_start(ap, format);
- vstring_vsprintf(dsb->reason, format, ap);
- va_end(ap);
-
- return (dsb);
-}
-
-/* dsb_smtp - update status, SMTP diagnostic and text */
-
-DSN_BUF *dsb_smtp(DSN_BUF *dsb, const char *status, int dcode,
- const char *dtext, const char *format,...)
-{
- va_list ap;
-
- vstring_strcpy(dsb->status, status);
- DSB_TRUNCATE(dsb->action);
- DSB_TRUNCATE(dsb->mtype);
- DSB_TRUNCATE(dsb->mname);
- vstring_strcpy(dsb->dtype, DSB_DTYPE_SMTP);
- dsb->dcode = dcode;
vstring_strcpy(dsb->dtext, dtext);
va_start(ap, format);
vstring_vsprintf(dsb->reason, format, ap);
@@ -309,21 +296,12 @@ DSN_BUF *dsb_smtp(DSN_BUF *dsb, const char *status, int dcode,
DSN_BUF *dsb_formal(DSN_BUF *dsb, const char *status, const char *action,
const char *mtype, const char *mname,
- const char *dtype, int dcode,
- const char *dtext)
+ const char *dtype, const char *dtext)
{
vstring_strcpy(dsb->status, status);
DSB_ACTION(dsb, status, action);
DSB_MTA(dsb, mtype, mname);
- if (dtype == 0) {
- DSB_TRUNCATE(dsb->dtype);
- dsb->dcode = 0;
- DSB_TRUNCATE(dsb->dtext);
- } else {
- vstring_strcpy(dsb->dtype, dtype);
- dsb->dcode = dcode;
- vstring_strcpy(dsb->dtext, dtext);
- }
+ DSB_DIAG(dsb, dtype, dtext);
return (dsb);
}
@@ -336,7 +314,6 @@ DSN_BUF *dsb_status(DSN_BUF *dsb, const char *status)
DSB_TRUNCATE(dsb->mtype);
DSB_TRUNCATE(dsb->mname);
DSB_TRUNCATE(dsb->dtype);
- dsb->dcode = 0;
DSB_TRUNCATE(dsb->dtext);
return (dsb);
}
@@ -350,7 +327,6 @@ void dsb_reset(DSN_BUF *dsb)
DSB_TRUNCATE(dsb->mtype);
DSB_TRUNCATE(dsb->mname);
DSB_TRUNCATE(dsb->dtype);
- dsb->dcode = 0;
DSB_TRUNCATE(dsb->dtext);
DSB_TRUNCATE(dsb->reason);
}
diff --git a/postfix/src/global/dsn_buf.h b/postfix/src/global/dsn_buf.h
index 17dd7fc38..b38f46d0d 100644
--- a/postfix/src/global/dsn_buf.h
+++ b/postfix/src/global/dsn_buf.h
@@ -3,9 +3,9 @@
/*++
/* NAME
-/* dsbuf 3h
+/* dsn_buf 3h
/* SUMMARY
-/* DSN support routines
+/* delivery status buffer
/* SYNOPSIS
/* #include
/* DESCRIPTION
@@ -16,17 +16,24 @@
*/
#include
+ /*
+ * Global library.
+ */
+#include
+
/*
* Delivery status buffer, Postfix-internal form.
*/
typedef struct {
+ DSN dsn; /* convenience */
+ /* Formal members. */
VSTRING *status; /* RFC 3463 */
VSTRING *action; /* RFC 3464 */
VSTRING *mtype; /* null or remote MTA type */
VSTRING *mname; /* null or remote MTA name */
- VSTRING *dtype; /* null, smtp, x-unix-command */
- int dcode; /* null, RFC 2821, sysexits.h */
+ VSTRING *dtype; /* null, smtp, x-unix */
VSTRING *dtext; /* null, RFC 2821, sysexits.h */
+ /* Informal free text. */
VSTRING *reason; /* free text */
} DSN_BUF;
@@ -36,23 +43,38 @@ typedef struct {
#define DSB_MTYPE_NONE ((char *) 0)
#define DSB_MTYPE_DNS "dns" /* RFC 2821 */
-#define DSB_SKIP_REPLY (char *) 0, (int) 0, " " /* XXX Bogus? */
+#define DSB_SKIP_REPLY (char *) 0, " " /* XXX Bogus? */
#define DSB_DTYPE_NONE ((char *) 0)
#define DSB_DTYPE_SMTP "smtp" /* RFC 2821 */
#define DSB_DTYPE_UNIX "x-unix" /* sysexits.h */
#define DSB_DTYPE_SASL "x-sasl" /* libsasl */
extern DSN_BUF *dsb_create(void);
-extern DSN_BUF *PRINTFLIKE(9, 10) dsb_update(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, int, const char *, const char *,...);
+extern DSN_BUF *PRINTFLIKE(8, 9) dsb_update(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, const char *, const char *,...);
extern DSN_BUF *PRINTFLIKE(3, 4) dsb_simple(DSN_BUF *, const char *, const char *,...);
-extern DSN_BUF *PRINTFLIKE(5, 6) dsb_smtp(DSN_BUF *, const char *, int, const char *, const char *,...);
-extern DSN_BUF *PRINTFLIKE(5, 6) dsb_unix(DSN_BUF *, const char *, int, const char *, const char *,...);
-extern DSN_BUF *PRINTFLIKE(5, 6) dsb_smtp(DSN_BUF *, const char *, int, const char *, const char *,...);
-extern DSN_BUF *dsb_formal(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, int, const char *);
+extern DSN_BUF *PRINTFLIKE(4, 5) dsb_unix(DSN_BUF *, const char *, const char *, const char *,...);
+extern DSN_BUF *PRINTFLIKE(4, 5) dsb_smtp(DSN_BUF *, const char *, const char *, const char *,...);
+extern DSN_BUF *dsb_formal(DSN_BUF *, const char *, const char *, const char *, const char *, const char *, const char *);
extern DSN_BUF *dsb_status(DSN_BUF *, const char *);
extern void dsb_reset(DSN_BUF *);
extern void dsb_free(DSN_BUF *);
+ /*
+ * Early implementations of the DSN structure represented unavailable
+ * information with null pointers. This resulted in hard to maintain code.
+ * We now use empty strings instead, so there is no need anymore to convert
+ * empty strings to null pointers in the macro below.
+ */
+#define DSN_FROM_DSN_BUF(dsb) \
+ DSN_ASSIGN(&(dsb)->dsn, \
+ vstring_str((dsb)->status), \
+ vstring_str((dsb)->action), \
+ vstring_str((dsb)->reason), \
+ vstring_str((dsb)->dtype), \
+ vstring_str((dsb)->dtext), \
+ vstring_str((dsb)->mtype), \
+ vstring_str((dsb)->mname))
+
/* LICENSE
/* .ad
/* .fi
diff --git a/postfix/src/global/dsn_print.c b/postfix/src/global/dsn_print.c
index ea1dc4924..9b21a6904 100644
--- a/postfix/src/global/dsn_print.c
+++ b/postfix/src/global/dsn_print.c
@@ -51,19 +51,17 @@ int dsn_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
DSN *dsn = (DSN *) ptr;
int ret;
-#define S(s) ((s) ? (s) : "")
-
/*
* The attribute order is determined by backwards compatibility. It can
* be sanitized after all the ad-hoc DSN read/write code is replaced.
*/
ret = print_fn(fp, flags | ATTR_FLAG_MORE,
ATTR_TYPE_STR, MAIL_ATTR_DSN_STATUS, dsn->status,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, S(dsn->dtype),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, S(dsn->dtext),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, S(dsn->mtype),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, S(dsn->mname),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, S(dsn->action),
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, dsn->dtype,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, dsn->dtext,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, dsn->mtype,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, dsn->mname,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, dsn->action,
ATTR_TYPE_STR, MAIL_ATTR_WHY, dsn->reason,
ATTR_TYPE_END);
return (ret);
diff --git a/postfix/src/global/dsn_util.c b/postfix/src/global/dsn_util.c
index a4d7ceed5..52b997a33 100644
--- a/postfix/src/global/dsn_util.c
+++ b/postfix/src/global/dsn_util.c
@@ -12,7 +12,7 @@
/*
/* typedef struct {
/* .in +4
-/* DSN_BUF dsn; /* RFC 3463 status */
+/* DSN_STAT dsn; /* RFC 3463 status */
/* const char *text; /* Free text */
/* .in -4
/* } DSN_SPLIT;
diff --git a/postfix/src/global/dsn_util.h b/postfix/src/global/dsn_util.h
index fbcbfd231..8657a3e50 100644
--- a/postfix/src/global/dsn_util.h
+++ b/postfix/src/global/dsn_util.h
@@ -33,7 +33,7 @@
*/
typedef struct {
char data[DSN_SIZE]; /* NOT a public interface */
-} DSN_BUFFER;
+} DSN_STAT;
#define DSN_UPDATE(dsn_buf, dsn, len) do { \
if (len >= sizeof((dsn_buf).data)) \
@@ -51,7 +51,7 @@ typedef struct {
* Split flat text into detail code and free text.
*/
typedef struct {
- DSN_BUFFER dsn; /* RFC 3463 status */
+ DSN_STAT dsn; /* RFC 3463 status */
const char *text; /* free text */
} DSN_SPLIT;
diff --git a/postfix/src/global/mail_copy.c b/postfix/src/global/mail_copy.c
index 33d41c491..42753d854 100644
--- a/postfix/src/global/mail_copy.c
+++ b/postfix/src/global/mail_copy.c
@@ -268,11 +268,11 @@ int mail_copy(const char *sender,
if (why && read_error)
dsb_unix(why, TRY_AGAIN_ERROR(errno) ? "4.3.0" : "5.3.0",
- EX_IOERR, sys_exits_detail(EX_IOERR)->text,
+ sys_exits_detail(EX_IOERR)->text,
"error reading message: %m");
if (why && write_error)
dsb_unix(why, mbox_dsn(errno, "5.3.0"),
- EX_IOERR, sys_exits_detail(EX_IOERR)->text,
+ sys_exits_detail(EX_IOERR)->text,
"error writing message: %m");
/*
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index 97f39f26a..9a0c60f0e 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -1329,6 +1329,12 @@ extern char *var_smtp_sasl_type;
#define DEF_LMTP_SASL_TLS_OPTS "$" VAR_LMTP_SASL_OPTS
extern char *var_smtp_sasl_tls_opts;
+#define VAR_SMTP_SASL_TLSV_OPTS "smtp_sasl_tls_verified_security_options"
+#define DEF_SMTP_SASL_TLSV_OPTS "$" VAR_SMTP_SASL_TLS_OPTS
+#define VAR_LMTP_SASL_TLSV_OPTS "lmtp_sasl_tls_verified_security_options"
+#define DEF_LMTP_SASL_TLSV_OPTS "$" VAR_LMTP_SASL_TLS_OPTS
+extern char *var_smtp_sasl_tlsv_opts;
+
/*
* LMTP server. The soft error limit determines how many errors an LMTP
* client may make before we start to slow down; the hard error limit
@@ -2532,6 +2538,15 @@ extern char *var_bounce_tmpl;
#define DEF_LMTP_SENDER_AUTH 0
extern bool var_smtp_sender_auth;
+ /*
+ * Allow CNAME lookup result to override the server hostname.
+ */
+#define VAR_SMTP_CNAME_OVERR "smtp_cname_overrides_servername"
+#define DEF_SMTP_CNAME_OVERR 0
+#define VAR_LMTP_CNAME_OVERR "lmtp_cname_overrides_servername"
+#define DEF_LMTP_CNAME_OVERR 0
+extern bool var_smtp_cname_overr;
+
/* LICENSE
/* .ad
/* .fi
diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h
index 2ffcc128a..6e5855287 100644
--- a/postfix/src/global/mail_proto.h
+++ b/postfix/src/global/mail_proto.h
@@ -98,6 +98,7 @@ extern char *mail_pathname(const char *, const char *);
#define MAIL_ATTR_QUEUE "queue_name"
#define MAIL_ATTR_QUEUEID "queue_id"
#define MAIL_ATTR_SENDER "sender"
+#define MAIL_ATTR_RCPT_COUNT "recipient_count"
#define MAIL_ATTR_ORCPT "original_recipient"
#define MAIL_ATTR_RECIP "recipient"
#define MAIL_ATTR_WHY "reason"
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index ee8ce66aa..f77b11e48 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 "20060103"
+#define MAIL_RELEASE_DATE "20060112"
#define MAIL_VERSION_NUMBER "2.3"
#ifdef SNAPSHOT
diff --git a/postfix/src/global/msg_stats_print.c b/postfix/src/global/msg_stats_print.c
index 5765e3e33..98d468dcd 100644
--- a/postfix/src/global/msg_stats_print.c
+++ b/postfix/src/global/msg_stats_print.c
@@ -47,7 +47,7 @@
/* msg_stats_print - write MSG_STATS to stream */
int msg_stats_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
- int flags, void *ptr)
+ int flags, void *ptr)
{
int ret;
diff --git a/postfix/src/global/pipe_command.c b/postfix/src/global/pipe_command.c
index 245e492dc..b0caa5cba 100644
--- a/postfix/src/global/pipe_command.c
+++ b/postfix/src/global/pipe_command.c
@@ -427,7 +427,7 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
*/
case -1:
msg_warn("fork: %m");
- dsb_unix(why, "4.3.0", EX_OSERR, sys_exits_detail(EX_OSERR)->text,
+ dsb_unix(why, "4.3.0", sys_exits_detail(EX_OSERR)->text,
"Delivery failed: %m");
return (PIPE_STAT_DEFER);
@@ -553,7 +553,7 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
args.uid, args.gid) < 0)
msg_fatal("wait: %m");
if (pipe_command_timeout) {
- dsb_unix(why, "5.3.0", EX_SOFTWARE, log_len ?
+ dsb_unix(why, "5.3.0", log_len ?
log_buf : sys_exits_detail(EX_SOFTWARE)->text,
"Command time limit exceeded: \"%s\"%s%s",
args.command,
@@ -567,7 +567,7 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
*/
if (!NORMAL_EXIT_STATUS(wait_status)) {
if (WIFSIGNALED(wait_status)) {
- dsb_unix(why, "5.3.0", EX_SOFTWARE, log_len ?
+ dsb_unix(why, "5.3.0", log_len ?
log_buf : sys_exits_detail(EX_SOFTWARE)->text,
"Command died with signal %d: \"%s\"%s%s",
WTERMSIG(wait_status), args.command,
@@ -577,15 +577,14 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
/* Use "D.S.N text" command output. XXX What diagnostic code? */
else if (dsn_valid(log_buf) > 0) {
dsn_split(&dp, "5.3.0", log_buf);
- dsb_unix(why, DSN_STATUS(dp.dsn), DSN_CLASS(dp.dsn) == '4' ?
- EX_TEMPFAIL : EX_UNAVAILABLE, dp.text, "%s", dp.text);
+ dsb_unix(why, DSN_STATUS(dp.dsn), dp.text, "%s", dp.text);
return (DSN_CLASS(dp.dsn) == '4' ?
PIPE_STAT_DEFER : PIPE_STAT_BOUNCE);
}
/* Use compatible exit status. */
else if (SYS_EXITS_CODE(WEXITSTATUS(wait_status))) {
sp = sys_exits_detail(WEXITSTATUS(wait_status));
- dsb_unix(why, sp->dsn, WEXITSTATUS(wait_status),
+ dsb_unix(why, sp->dsn,
log_len ? log_buf : sp->text, "%s%s%s", sp->text,
log_len ? ". Command output: " : "", log_buf);
return (sp->dsn[0] == '4' ?
@@ -594,7 +593,7 @@ int pipe_command(VSTREAM *src, DSN_BUF *why,...)
/* No "D.S.N text" or compatible status. Fake it. */
else {
sp = sys_exits_detail(WEXITSTATUS(wait_status));
- dsb_unix(why, sp->dsn, WEXITSTATUS(wait_status),
+ dsb_unix(why, sp->dsn,
log_len ? log_buf : sp->text,
"Command died with status %d: \"%s\"%s%s",
WEXITSTATUS(wait_status), args.command,
diff --git a/postfix/src/global/post_mail.c b/postfix/src/global/post_mail.c
index 0904e6e0c..e1c46796d 100644
--- a/postfix/src/global/post_mail.c
+++ b/postfix/src/global/post_mail.c
@@ -6,26 +6,30 @@
/* SYNOPSIS
/* #include
/*
-/* VSTREAM *post_mail_fopen(sender, recipient, cleanup_flags, trace_flags)
+/* VSTREAM *post_mail_fopen(sender, recipient, cleanup_flags, trace_flags,
+/* queue_id)
/* const char *sender;
/* const char *recipient;
/* int cleanup_flags;
/* int trace_flags;
+/* VSTRING *queue_id;
/*
/* VSTREAM *post_mail_fopen_nowait(sender, recipient,
-/* cleanup_flags, trace_flags)
+/* cleanup_flags, trace_flags, queue_id)
/* const char *sender;
/* const char *recipient;
/* int cleanup_flags;
/* int trace_flags;
+/* VSTRING *queue_id;
/*
/* void post_mail_fopen_async(sender, recipient,
/* cleanup_flags, trace_flags,
-/* notify, context)
+/* queue_id, notify, context)
/* const char *sender;
/* const char *recipient;
/* int cleanup_flags;
/* int trace_flags;
+/* VSTRING *queue_id;
/* void (*notify)(VSTREAM *stream, char *context);
/* char *context;
/*
@@ -96,8 +100,9 @@
/* \fB\fR.
/* .IP trace_flags
/* Message tracing flags as specified in \fB\fR.
-/* .IP via
-/* The name of the service responsible for posting this message.
+/* .IP queue_id
+/* Null pointer, or pointer to buffer that receives the queue
+/* ID of the new message.
/* .IP stream
/* A stream opened by mail_post_fopen().
/* .IP notify
@@ -169,15 +174,17 @@ typedef struct {
POST_MAIL_NOTIFY notify;
void *context;
VSTREAM *stream;
+ VSTRING *queue_id;
} POST_MAIL_STATE;
/* post_mail_init - initial negotiations */
static void post_mail_init(VSTREAM *stream, const char *sender,
const char *recipient,
- int cleanup_flags, int trace_flags)
+ int cleanup_flags, int trace_flags,
+ VSTRING *queue_id)
{
- VSTRING *id = vstring_alloc(100);
+ VSTRING *id = queue_id ? queue_id : vstring_alloc(100);
struct timeval now;
const char *date;
@@ -217,31 +224,36 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
var_myhostname, var_mail_name);
post_mail_fprintf(stream, "\tid %s; %s", vstring_str(id), date);
post_mail_fprintf(stream, "Date: %s", date);
- vstring_free(id);
+ if (queue_id == 0)
+ vstring_free(id);
}
/* post_mail_fopen - prepare for posting a message */
VSTREAM *post_mail_fopen(const char *sender, const char *recipient,
- int cleanup_flags, int trace_flags)
+ int cleanup_flags, int trace_flags,
+ VSTRING *queue_id)
{
VSTREAM *stream;
stream = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
- post_mail_init(stream, sender, recipient, cleanup_flags, trace_flags);
+ post_mail_init(stream, sender, recipient, cleanup_flags, trace_flags,
+ queue_id);
return (stream);
}
/* post_mail_fopen_nowait - prepare for posting a message */
VSTREAM *post_mail_fopen_nowait(const char *sender, const char *recipient,
- int cleanup_flags, int trace_flags)
+ int cleanup_flags, 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, cleanup_flags, trace_flags);
+ post_mail_init(stream, sender, recipient, cleanup_flags, trace_flags,
+ queue_id);
return (stream);
}
@@ -281,7 +293,7 @@ static void post_mail_open_event(int event, char *context)
event_disable_readwrite(vstream_fileno(state->stream));
post_mail_init(state->stream, state->sender,
state->recipient, state->cleanup_flags,
- state->trace_flags);
+ state->trace_flags, state->queue_id);
myfree(state->sender);
myfree(state->recipient);
state->notify(state->stream, state->context);
@@ -332,6 +344,7 @@ static void post_mail_open_event(int event, char *context)
void post_mail_fopen_async(const char *sender, const char *recipient,
int cleanup_flags, int trace_flags,
+ VSTRING *queue_id,
void (*notify) (VSTREAM *, void *),
void *context)
{
@@ -347,6 +360,7 @@ void post_mail_fopen_async(const char *sender, const char *recipient,
state->notify = notify;
state->context = context;
state->stream = stream;
+ state->queue_id = queue_id;
/*
* To keep interfaces as simple as possible we report all errors via the
diff --git a/postfix/src/global/post_mail.h b/postfix/src/global/post_mail.h
index d0a0acecc..e55a8d166 100644
--- a/postfix/src/global/post_mail.h
+++ b/postfix/src/global/post_mail.h
@@ -15,6 +15,7 @@
* Utility library.
*/
#include
+#include
/*
* Global library.
@@ -25,9 +26,9 @@
* External interface.
*/
typedef void (*POST_MAIL_NOTIFY)(VSTREAM *, void *);
-extern VSTREAM *post_mail_fopen(const char *, const char *, int, int);
-extern VSTREAM *post_mail_fopen_nowait(const char *, const char *, int, int);
-extern void post_mail_fopen_async(const char *, const char *, int, int, POST_MAIL_NOTIFY, void *);
+extern VSTREAM *post_mail_fopen(const char *, const char *, int, int, VSTRING *);
+extern VSTREAM *post_mail_fopen_nowait(const char *, const char *, int, int, VSTRING *);
+extern void post_mail_fopen_async(const char *, const char *, int, int, VSTRING *, POST_MAIL_NOTIFY, void *);
extern int PRINTFLIKE(2, 3) post_mail_fprintf(VSTREAM *, const char *,...);
extern int post_mail_fputs(VSTREAM *, const char *);
extern int post_mail_buffer(VSTREAM *, const char *, int);
diff --git a/postfix/src/global/rcpt_buf.c b/postfix/src/global/rcpt_buf.c
index 2417a5cb1..cfb1b4178 100644
--- a/postfix/src/global/rcpt_buf.c
+++ b/postfix/src/global/rcpt_buf.c
@@ -7,6 +7,7 @@
/* #include
/*
/* typedef struct {
+/* RECIPIENT rcpt; /* convenience */
/* .in +4
/* VSTRING *address; /* final recipient */
/* VSTRING *orig_addr; /* original recipient */
@@ -16,10 +17,16 @@
/* .in -4
/* } RCPT_BUF;
/*
+/* RECIPIENT *RECIPIENT_FROM_RCPT_BUF(rcpb)
+/* RCPT_BUF *rcpb;
+/*
/* RCPT_BUF *rcpb_create(void)
/*
-/* void rcpb_free(rcpt)
-/* RCPT_BUF *rcpt;
+/* void rcpb_reset(rcpb)
+/* RCPT_BUF *rcpb;
+/*
+/* void rcpb_free(rcpb)
+/* RCPT_BUF *rcpb;
/*
/* int rcpb_scan(scan_fn, stream, flags, ptr)
/* ATTR_SCAN_MASTER_FN scan_fn;
@@ -27,14 +34,17 @@
/* int flags;
/* void *ptr;
/* DESCRIPTION
+/* RECIPIENT_FROM_RCPT_BUF() populates the rcpt member with
+/* a shallow copy of the contents of the other fields.
+/*
/* rcpb_scan() reads a recipient buffer from the named stream
/* using the specified attribute scan routine. rcpb_scan()
/* is meant to be passed as a call-back to attr_scan(), thusly:
/*
/* ... ATTR_SCAN_FUNC, rcpb_scan, (void *) rcpt_buf, ...
/*
-/* rcpb_create() and rcpb_free() create and destroy
-/* recipient buffer instances.
+/* rcpb_create(), rcpb_reset() and rcpb_free() create, wipe
+/* and destroy recipient buffer instances.
/* DIAGNOSTICS
/* Fatal: out of memory.
/* LICENSE
@@ -80,6 +90,19 @@ RCPT_BUF *rcpb_create(void)
return (rcpt);
}
+/* rcpb_reset - reset recipient buffer */
+
+void rcpb_reset(RCPT_BUF *rcpt)
+{
+#define BUF_TRUNCATE(s) (vstring_str(s)[0] = 0)
+
+ rcpt->offset = 0;
+ BUF_TRUNCATE(rcpt->dsn_orcpt);
+ rcpt->dsn_notify = 0;
+ BUF_TRUNCATE(rcpt->orig_addr);
+ BUF_TRUNCATE(rcpt->address);
+}
+
/* rcpb_free - destroy recipient buffer */
void rcpb_free(RCPT_BUF *rcpt)
diff --git a/postfix/src/global/rcpt_buf.h b/postfix/src/global/rcpt_buf.h
index 0dbee35c8..9b2994c0a 100644
--- a/postfix/src/global/rcpt_buf.h
+++ b/postfix/src/global/rcpt_buf.h
@@ -18,10 +18,16 @@
#include
#include
+ /*
+ * Global library.
+ */
+#include
+
/*
* External interface.
*/
typedef struct {
+ RECIPIENT rcpt; /* convenience */
VSTRING *address; /* final recipient */
VSTRING *orig_addr; /* original recipient */
VSTRING *dsn_orcpt; /* dsn original recipient */
@@ -30,16 +36,17 @@ typedef struct {
} RCPT_BUF;
extern RCPT_BUF *rcpb_create(void);
+extern void rcpb_reset(RCPT_BUF *);
extern void rcpb_free(RCPT_BUF *);
extern int rcpb_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
-#define RECIPIENT_FROM_RCPT_BUF(rcpt, buf) \
- ((rcpt)->address = vstring_str((buf)->address), \
- (rcpt)->orig_addr = vstring_str((buf)->orig_addr), \
- (rcpt)->dsn_orcpt = vstring_str((buf)->dsn_orcpt), \
- (rcpt)->dsn_notify = (buf)->dsn_notify, \
- (rcpt)->offset = (buf)->offset, \
- (rcpt))
+#define RECIPIENT_FROM_RCPT_BUF(buf) \
+ ((buf)->rcpt.address = vstring_str((buf)->address), \
+ (buf)->rcpt.orig_addr = vstring_str((buf)->orig_addr), \
+ (buf)->rcpt.dsn_orcpt = vstring_str((buf)->dsn_orcpt), \
+ (buf)->rcpt.dsn_notify = (buf)->dsn_notify, \
+ (buf)->rcpt.offset = (buf)->offset, \
+ &(buf)->rcpt)
/* LICENSE
/* .ad
diff --git a/postfix/src/global/rcpt_print.c b/postfix/src/global/rcpt_print.c
index 47af47032..1c3b723f8 100644
--- a/postfix/src/global/rcpt_print.c
+++ b/postfix/src/global/rcpt_print.c
@@ -52,8 +52,6 @@ int rcpt_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
RECIPIENT *rcpt = (RECIPIENT *) ptr;
int ret;
-#define S(s) ((s) ? (s) : "")
-
/*
* The attribute order is determined by backwards compatibility. It can
* be sanitized after all the ad-hoc recipient read/write code is
@@ -61,10 +59,10 @@ int rcpt_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
*/
ret =
print_fn(fp, flags | ATTR_FLAG_MORE,
- ATTR_TYPE_STR, MAIL_ATTR_ORCPT, S(rcpt->orig_addr),
+ ATTR_TYPE_STR, MAIL_ATTR_ORCPT, rcpt->orig_addr,
ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, rcpt->offset,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, S(rcpt->dsn_orcpt),
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt,
ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify,
ATTR_TYPE_END);
return (ret);
diff --git a/postfix/src/global/recipient_list.c b/postfix/src/global/recipient_list.c
index 8d2c964f9..a39979241 100644
--- a/postfix/src/global/recipient_list.c
+++ b/postfix/src/global/recipient_list.c
@@ -15,9 +15,9 @@
/* char *address;
/* union {
/* .in +4
-/* int status;
-/* struct QMGR_QUEUE *queue;
-/* char *addr_type;
+/* int status;
+/* struct QMGR_QUEUE *queue;
+/* char *addr_type;
/* .in -4
/* }
/* .in -4
diff --git a/postfix/src/global/recipient_list.h b/postfix/src/global/recipient_list.h
index e617b4212..6e9617218 100644
--- a/postfix/src/global/recipient_list.h
+++ b/postfix/src/global/recipient_list.h
@@ -46,22 +46,6 @@ typedef struct RECIPIENT {
myfree((char *) (ptr)); (ptr) = mystrdup(new); \
} while (0)
- /*
- * Same without const poisning.
- */
-typedef struct RECIPIENT_VAR {
- long offset; /* REC_TYPE_RCPT byte */
- char *dsn_orcpt; /* DSN original recipient */
- int dsn_notify; /* DSN notify flags */
- char *orig_addr; /* null or original recipient */
- char *address; /* complete address */
- union { /* Application specific. */
- int status; /* SMTP client */
- struct QMGR_QUEUE *queue; /* Queue manager */
- char *addr_type; /* DSN */
- } u;
-} RECIPIENT_VAR;
-
typedef struct RECIPIENT_LIST {
RECIPIENT *info;
int len;
diff --git a/postfix/src/global/smtp_stream.c b/postfix/src/global/smtp_stream.c
index 5b3d6e040..24507d5ee 100644
--- a/postfix/src/global/smtp_stream.c
+++ b/postfix/src/global/smtp_stream.c
@@ -95,10 +95,6 @@
/* An I/O error happened, or the peer has disconnected unexpectedly.
/* .IP SMTP_ERR_TIME
/* The time limit specified to smtp_timeout_setup() was exceeded.
-/* .IP SMTP_ERR_PROTO
-/* A protocol error happened.
-/* This error is never generated by the smtp_stream(3) module, but
-/* is defined for application-specific use.
/* .IP SMTP_ERR_QUIET
/* Perform silent cleanup; the error was already reported by
/* the application.
diff --git a/postfix/src/global/smtp_stream.h b/postfix/src/global/smtp_stream.h
index 190baf50d..a09a13f89 100644
--- a/postfix/src/global/smtp_stream.h
+++ b/postfix/src/global/smtp_stream.h
@@ -28,7 +28,6 @@
*/
#define SMTP_ERR_EOF 1 /* unexpected client disconnect */
#define SMTP_ERR_TIME 2 /* time out */
-#define SMTP_ERR_PROTO 3 /* protocol (application) */
#define SMTP_ERR_QUIET 4 /* silent cleanup (application) */
extern void smtp_timeout_setup(VSTREAM *, int);
diff --git a/postfix/src/local/local.h b/postfix/src/local/local.h
index 2e3d79359..67c3a9403 100644
--- a/postfix/src/local/local.h
+++ b/postfix/src/local/local.h
@@ -88,7 +88,6 @@ typedef struct DELIVER_ATTR {
char *exp_from; /* expanded_from */
DELIVER_REQUEST *request; /* the kitchen sink */
DSN_BUF *why; /* delivery status */
- DSN dsn; /* delivery status */
} DELIVER_ATTR;
extern void deliver_attr_init(DELIVER_ATTR *);
@@ -132,15 +131,15 @@ typedef struct LOCAL_STATE {
#define BOUNCE_ATTR(attr) \
attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
- DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+ DSN_FROM_DSN_BUF(attr.why)
#define BOUNCE_ONE_ATTR(attr) \
attr.queue_name, attr.queue_id, attr.encoding, \
attr.sender, attr.dsn_envid, attr.dsn_ret, \
&attr.msg_stats, &attr.rcpt, attr.relay, \
- DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+ DSN_FROM_DSN_BUF(attr.why)
#define SENT_ATTR(attr) \
attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
- DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+ DSN_FROM_DSN_BUF(attr.why)
#define OPENED_ATTR(attr) \
attr.queue_id, attr.sender
#define COPY_ATTR(attr) \
diff --git a/postfix/src/local/unknown.c b/postfix/src/local/unknown.c
index cc0a07458..c6d7ed9f0 100644
--- a/postfix/src/local/unknown.c
+++ b/postfix/src/local/unknown.c
@@ -152,8 +152,8 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr)
/*
* Bounce the message when no luser relay is specified.
*/
- dsb_smtp(state.msg_attr.why, "5.1.1", 550, "550 user unknown",
- "unknown user: \"%s\"", state.msg_attr.local);
+ dsb_simple(state.msg_attr.why, "5.1.1",
+ "unknown user: \"%s\"", state.msg_attr.local);
return (bounce_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr)));
}
diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in
index 36cfa45cd..c7e70f939 100644
--- a/postfix/src/master/Makefile.in
+++ b/postfix/src/master/Makefile.in
@@ -135,6 +135,7 @@ master_ent.o: ../../include/myaddrinfo.h
master_ent.o: ../../include/mymalloc.h
master_ent.o: ../../include/own_inet_addr.h
master_ent.o: ../../include/readlline.h
+master_ent.o: ../../include/sock_addr.h
master_ent.o: ../../include/stringops.h
master_ent.o: ../../include/sys_defs.h
master_ent.o: ../../include/vbuf.h
diff --git a/postfix/src/oqmgr/Makefile.in b/postfix/src/oqmgr/Makefile.in
index 1815ddbcb..accc7a2ed 100644
--- a/postfix/src/oqmgr/Makefile.in
+++ b/postfix/src/oqmgr/Makefile.in
@@ -64,7 +64,6 @@ qmgr.o: ../../include/argv.h
qmgr.o: ../../include/attr.h
qmgr.o: ../../include/dict.h
qmgr.o: ../../include/dsn.h
-qmgr.o: ../../include/dsn_buf.h
qmgr.o: ../../include/events.h
qmgr.o: ../../include/flush_clnt.h
qmgr.o: ../../include/iostuff.h
@@ -74,7 +73,6 @@ qmgr.o: ../../include/mail_params.h
qmgr.o: ../../include/mail_proto.h
qmgr.o: ../../include/mail_queue.h
qmgr.o: ../../include/mail_server.h
-qmgr.o: ../../include/maps.h
qmgr.o: ../../include/master_proto.h
qmgr.o: ../../include/msg.h
qmgr.o: ../../include/recipient_list.h
@@ -86,12 +84,10 @@ qmgr.o: ../../include/vstring.h
qmgr.o: qmgr.c
qmgr.o: qmgr.h
qmgr_active.o: ../../include/abounce.h
-qmgr_active.o: ../../include/argv.h
qmgr_active.o: ../../include/attr.h
qmgr_active.o: ../../include/bounce.h
qmgr_active.o: ../../include/defer.h
qmgr_active.o: ../../include/deliver_request.h
-qmgr_active.o: ../../include/dict.h
qmgr_active.o: ../../include/dsn.h
qmgr_active.o: ../../include/dsn_buf.h
qmgr_active.o: ../../include/dsn_mask.h
@@ -99,7 +95,6 @@ qmgr_active.o: ../../include/events.h
qmgr_active.o: ../../include/mail_open_ok.h
qmgr_active.o: ../../include/mail_params.h
qmgr_active.o: ../../include/mail_queue.h
-qmgr_active.o: ../../include/maps.h
qmgr_active.o: ../../include/msg.h
qmgr_active.o: ../../include/msg_stats.h
qmgr_active.o: ../../include/mymalloc.h
@@ -114,15 +109,12 @@ qmgr_active.o: ../../include/vstream.h
qmgr_active.o: ../../include/vstring.h
qmgr_active.o: qmgr.h
qmgr_active.o: qmgr_active.c
-qmgr_bounce.o: ../../include/argv.h
qmgr_bounce.o: ../../include/attr.h
qmgr_bounce.o: ../../include/bounce.h
qmgr_bounce.o: ../../include/deliver_completed.h
qmgr_bounce.o: ../../include/deliver_request.h
-qmgr_bounce.o: ../../include/dict.h
qmgr_bounce.o: ../../include/dsn.h
qmgr_bounce.o: ../../include/dsn_buf.h
-qmgr_bounce.o: ../../include/maps.h
qmgr_bounce.o: ../../include/msg_stats.h
qmgr_bounce.o: ../../include/recipient_list.h
qmgr_bounce.o: ../../include/scan_dir.h
@@ -132,15 +124,12 @@ qmgr_bounce.o: ../../include/vstream.h
qmgr_bounce.o: ../../include/vstring.h
qmgr_bounce.o: qmgr.h
qmgr_bounce.o: qmgr_bounce.c
-qmgr_defer.o: ../../include/argv.h
qmgr_defer.o: ../../include/attr.h
qmgr_defer.o: ../../include/bounce.h
qmgr_defer.o: ../../include/defer.h
qmgr_defer.o: ../../include/deliver_request.h
-qmgr_defer.o: ../../include/dict.h
qmgr_defer.o: ../../include/dsn.h
qmgr_defer.o: ../../include/dsn_buf.h
-qmgr_defer.o: ../../include/maps.h
qmgr_defer.o: ../../include/msg.h
qmgr_defer.o: ../../include/msg_stats.h
qmgr_defer.o: ../../include/recipient_list.h
@@ -151,10 +140,8 @@ qmgr_defer.o: ../../include/vstream.h
qmgr_defer.o: ../../include/vstring.h
qmgr_defer.o: qmgr.h
qmgr_defer.o: qmgr_defer.c
-qmgr_deliver.o: ../../include/argv.h
qmgr_deliver.o: ../../include/attr.h
qmgr_deliver.o: ../../include/deliver_request.h
-qmgr_deliver.o: ../../include/dict.h
qmgr_deliver.o: ../../include/dsb_scan.h
qmgr_deliver.o: ../../include/dsn.h
qmgr_deliver.o: ../../include/dsn_buf.h
@@ -164,9 +151,9 @@ qmgr_deliver.o: ../../include/iostuff.h
qmgr_deliver.o: ../../include/mail_params.h
qmgr_deliver.o: ../../include/mail_proto.h
qmgr_deliver.o: ../../include/mail_queue.h
-qmgr_deliver.o: ../../include/maps.h
qmgr_deliver.o: ../../include/msg.h
qmgr_deliver.o: ../../include/msg_stats.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/stringops.h
@@ -178,29 +165,20 @@ qmgr_deliver.o: ../../include/vstring.h
qmgr_deliver.o: ../../include/vstring_vstream.h
qmgr_deliver.o: qmgr.h
qmgr_deliver.o: qmgr_deliver.c
-qmgr_enable.o: ../../include/argv.h
-qmgr_enable.o: ../../include/dict.h
qmgr_enable.o: ../../include/dsn.h
-qmgr_enable.o: ../../include/dsn_buf.h
-qmgr_enable.o: ../../include/maps.h
qmgr_enable.o: ../../include/msg.h
qmgr_enable.o: ../../include/recipient_list.h
qmgr_enable.o: ../../include/scan_dir.h
qmgr_enable.o: ../../include/sys_defs.h
qmgr_enable.o: ../../include/vbuf.h
qmgr_enable.o: ../../include/vstream.h
-qmgr_enable.o: ../../include/vstring.h
qmgr_enable.o: qmgr.h
qmgr_enable.o: qmgr_enable.c
-qmgr_entry.o: ../../include/argv.h
qmgr_entry.o: ../../include/attr.h
qmgr_entry.o: ../../include/deliver_request.h
-qmgr_entry.o: ../../include/dict.h
qmgr_entry.o: ../../include/dsn.h
-qmgr_entry.o: ../../include/dsn_buf.h
qmgr_entry.o: ../../include/events.h
qmgr_entry.o: ../../include/mail_params.h
-qmgr_entry.o: ../../include/maps.h
qmgr_entry.o: ../../include/msg.h
qmgr_entry.o: ../../include/msg_stats.h
qmgr_entry.o: ../../include/mymalloc.h
@@ -224,11 +202,9 @@ qmgr_message.o: ../../include/dsn_attr_map.h
qmgr_message.o: ../../include/dsn_buf.h
qmgr_message.o: ../../include/dsn_mask.h
qmgr_message.o: ../../include/iostuff.h
-qmgr_message.o: ../../include/mail_addr_find.h
qmgr_message.o: ../../include/mail_params.h
qmgr_message.o: ../../include/mail_proto.h
qmgr_message.o: ../../include/mail_queue.h
-qmgr_message.o: ../../include/maps.h
qmgr_message.o: ../../include/msg.h
qmgr_message.o: ../../include/msg_stats.h
qmgr_message.o: ../../include/myflock.h
@@ -253,13 +229,9 @@ qmgr_message.o: ../../include/vstream.h
qmgr_message.o: ../../include/vstring.h
qmgr_message.o: qmgr.h
qmgr_message.o: qmgr_message.c
-qmgr_move.o: ../../include/argv.h
-qmgr_move.o: ../../include/dict.h
qmgr_move.o: ../../include/dsn.h
-qmgr_move.o: ../../include/dsn_buf.h
qmgr_move.o: ../../include/mail_queue.h
qmgr_move.o: ../../include/mail_scan_dir.h
-qmgr_move.o: ../../include/maps.h
qmgr_move.o: ../../include/msg.h
qmgr_move.o: ../../include/recipient_list.h
qmgr_move.o: ../../include/scan_dir.h
@@ -269,14 +241,10 @@ qmgr_move.o: ../../include/vstream.h
qmgr_move.o: ../../include/vstring.h
qmgr_move.o: qmgr.h
qmgr_move.o: qmgr_move.c
-qmgr_queue.o: ../../include/argv.h
-qmgr_queue.o: ../../include/dict.h
qmgr_queue.o: ../../include/dsn.h
-qmgr_queue.o: ../../include/dsn_buf.h
qmgr_queue.o: ../../include/events.h
qmgr_queue.o: ../../include/htable.h
qmgr_queue.o: ../../include/mail_params.h
-qmgr_queue.o: ../../include/maps.h
qmgr_queue.o: ../../include/msg.h
qmgr_queue.o: ../../include/mymalloc.h
qmgr_queue.o: ../../include/recipient_list.h
@@ -284,15 +252,10 @@ qmgr_queue.o: ../../include/scan_dir.h
qmgr_queue.o: ../../include/sys_defs.h
qmgr_queue.o: ../../include/vbuf.h
qmgr_queue.o: ../../include/vstream.h
-qmgr_queue.o: ../../include/vstring.h
qmgr_queue.o: qmgr.h
qmgr_queue.o: qmgr_queue.c
-qmgr_scan.o: ../../include/argv.h
-qmgr_scan.o: ../../include/dict.h
qmgr_scan.o: ../../include/dsn.h
-qmgr_scan.o: ../../include/dsn_buf.h
qmgr_scan.o: ../../include/mail_scan_dir.h
-qmgr_scan.o: ../../include/maps.h
qmgr_scan.o: ../../include/msg.h
qmgr_scan.o: ../../include/mymalloc.h
qmgr_scan.o: ../../include/recipient_list.h
@@ -300,21 +263,16 @@ qmgr_scan.o: ../../include/scan_dir.h
qmgr_scan.o: ../../include/sys_defs.h
qmgr_scan.o: ../../include/vbuf.h
qmgr_scan.o: ../../include/vstream.h
-qmgr_scan.o: ../../include/vstring.h
qmgr_scan.o: qmgr.h
qmgr_scan.o: qmgr_scan.c
-qmgr_transport.o: ../../include/argv.h
qmgr_transport.o: ../../include/attr.h
-qmgr_transport.o: ../../include/dict.h
qmgr_transport.o: ../../include/dsn.h
-qmgr_transport.o: ../../include/dsn_buf.h
qmgr_transport.o: ../../include/events.h
qmgr_transport.o: ../../include/htable.h
qmgr_transport.o: ../../include/iostuff.h
qmgr_transport.o: ../../include/mail_conf.h
qmgr_transport.o: ../../include/mail_params.h
qmgr_transport.o: ../../include/mail_proto.h
-qmgr_transport.o: ../../include/maps.h
qmgr_transport.o: ../../include/msg.h
qmgr_transport.o: ../../include/mymalloc.h
qmgr_transport.o: ../../include/recipient_list.h
@@ -322,6 +280,5 @@ qmgr_transport.o: ../../include/scan_dir.h
qmgr_transport.o: ../../include/sys_defs.h
qmgr_transport.o: ../../include/vbuf.h
qmgr_transport.o: ../../include/vstream.h
-qmgr_transport.o: ../../include/vstring.h
qmgr_transport.o: qmgr.h
qmgr_transport.o: qmgr_transport.c
diff --git a/postfix/src/oqmgr/qmgr_deliver.c b/postfix/src/oqmgr/qmgr_deliver.c
index 7f392d319..1f813ce4d 100644
--- a/postfix/src/oqmgr/qmgr_deliver.c
+++ b/postfix/src/oqmgr/qmgr_deliver.c
@@ -68,6 +68,7 @@
#include
#include
#include
+#include
/* Application-specific. */
@@ -150,8 +151,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
flags = message->tflags
| entry->queue->dflags
| (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT);
- QMGR_MSG_STATS(&stats, message);
- attr_print(stream, ATTR_FLAG_MORE,
+ (void) QMGR_MSG_STATS(&stats, message);
+ attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
@@ -171,20 +172,14 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
+ ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, list.len,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);
for (recipient = list.info; recipient < list.info + list.len; recipient++)
- attr_print(stream, ATTR_FLAG_MORE,
- ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, recipient->dsn_orcpt,
- ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, recipient->dsn_notify,
- ATTR_TYPE_STR, MAIL_ATTR_ORCPT, recipient->orig_addr,
- ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address,
+ attr_print(stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_FUNC, rcpt_print, (void *) recipient,
ATTR_TYPE_END);
- attr_print(stream, ATTR_FLAG_NONE,
- ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
- ATTR_TYPE_END);
if (vstream_fflush(stream) != 0) {
msg_warn("write to process (%s): %m", entry->queue->transport->name);
return (-1);
@@ -218,7 +213,6 @@ static void qmgr_deliver_update(int unused_event, char *context)
QMGR_MESSAGE *message = entry->message;
static DSN_BUF *dsb;
int status;
- DSN dsn;
RECIPIENT *recipient;
int nrcpt;
@@ -251,9 +245,8 @@ static void qmgr_deliver_update(int unused_event, char *context)
if (status == DELIVER_STAT_CRASH) {
message->flags |= DELIVER_STAT_DEFER;
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 unknown mail transport error",
- "unknown mail transport error"));
+ DSN_SIMPLE(&dsb->dsn, "4.3.0",
+ "unknown mail transport error"));
msg_warn("transport %s failure -- see a previous warning/fatal/panic logfile record for the problem description",
transport->name);
@@ -269,9 +262,9 @@ static void qmgr_deliver_update(int unused_event, char *context)
*/
for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) {
recipient = entry->rcpt_list.info + nrcpt;
- qmgr_defer_recipient(message, recipient, &dsn);
+ qmgr_defer_recipient(message, recipient, &dsb->dsn);
}
- qmgr_defer_transport(transport, &dsn);
+ qmgr_defer_transport(transport, &dsb->dsn);
}
/*
@@ -282,21 +275,23 @@ static void qmgr_deliver_update(int unused_event, char *context)
* (the todo list); stay away from queue entries that have been selected
* (the busy list), or we would have dangling pointers. The queue itself
* won't go away before we dispose of the current queue entry.
+ *
+ * XXX Caution: DSN_COPY() will panic on empty status or reason.
*/
#define SUSPENDED "delivery temporarily suspended: "
if (status == DELIVER_STAT_DEFER) {
message->flags |= DELIVER_STAT_DEFER;
if (VSTRING_LEN(dsb->status)) {
- /* Sanitize the DSN status from the delivery agent. */
+ /* Sanitize the DSN status/reason from the delivery agent. */
if (!dsn_valid(vstring_str(dsb->status)))
vstring_strcpy(dsb->status, "4.0.0");
if (VSTRING_LEN(dsb->reason) == 0)
vstring_strcpy(dsb->reason, "unknown error");
vstring_prepend(dsb->reason, SUSPENDED, sizeof(SUSPENDED) - 1);
- qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(&dsn, dsb));
+ qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(dsb));
if (queue->window == 0)
- qmgr_defer_todo(queue, &dsn);
+ qmgr_defer_todo(queue, &dsb->dsn);
}
}
@@ -339,9 +334,8 @@ void qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
*/
if (qmgr_deliver_initial_reply(stream) != 0) {
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 mail transport unavailable",
- "mail transport unavailable"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "mail transport unavailable"));
qmgr_defer_transport(transport, &dsn);
(void) vstream_fclose(stream);
return;
@@ -369,9 +363,8 @@ void qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
if (qmgr_deliver_send_request(entry, stream) < 0) {
qmgr_entry_unselect(queue, entry);
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 mail transport unavailable",
- "mail transport unavailable"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "mail transport unavailable"));
qmgr_defer_transport(transport, &dsn);
/* warning: entry and queue may be dangling pointers here */
(void) vstream_fclose(stream);
diff --git a/postfix/src/oqmgr/qmgr_message.c b/postfix/src/oqmgr/qmgr_message.c
index a973ffa65..146c7c678 100644
--- a/postfix/src/oqmgr/qmgr_message.c
+++ b/postfix/src/oqmgr/qmgr_message.c
@@ -854,15 +854,13 @@ static int qmgr_resolve_one(QMGR_MESSAGE *message, RECIPIENT *recipient,
resolve_clnt_verify_from(message->sender, addr, reply);
if (reply->flags & RESOLVE_FLAG_FAIL) {
qmgr_defer_recipient(message, recipient,
- DSN_SMTP(&dsn, "4.3.0",
- "451 address resolver failure",
- "address resolver failure"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "address resolver failure"));
return (-1);
} else if (reply->flags & RESOLVE_FLAG_ERROR) {
qmgr_bounce_recipient(message, recipient,
- DSN_SMTP(&dsn, "5.1.3",
- "553 bad address syntax",
- "bad address syntax"));
+ DSN_SIMPLE(&dsn, "5.1.3",
+ "bad address syntax"));
return (-1);
} else {
return (0);
@@ -948,9 +946,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
*/
if (recipient->address[0] == 0) {
qmgr_bounce_recipient(message, recipient,
- DSN_SMTP(&dsn, "5.1.3",
- "553 null recipient address",
- "null recipient address"));
+ DSN_SIMPLE(&dsn, "5.1.3",
+ "null recipient address"));
continue;
}
@@ -967,9 +964,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
*/
if (var_allow_min_user == 0 && recipient->address[0] == '-') {
qmgr_bounce_recipient(message, recipient,
- DSN_SMTP(&dsn, "5.1.3",
- "553 bad address syntax",
- "bad address syntax"));
+ DSN_SIMPLE(&dsn, "5.1.3",
+ "bad address syntax"));
continue;
}
@@ -1015,9 +1011,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
break;
if (*cpp) {
qmgr_defer_recipient(message, recipient,
- DSN_SMTP(&dsn, "4.3.2",
- "450 delivery suspended",
- "deferred transport"));
+ DSN_SIMPLE(&dsn, "4.3.2",
+ "deferred transport"));
continue;
}
}
diff --git a/postfix/src/oqmgr/qmgr_transport.c b/postfix/src/oqmgr/qmgr_transport.c
index 756dd4809..d31f7bd39 100644
--- a/postfix/src/oqmgr/qmgr_transport.c
+++ b/postfix/src/oqmgr/qmgr_transport.c
@@ -289,9 +289,8 @@ void qmgr_transport_alloc(QMGR_TRANSPORT *transport, QMGR_TRANSPORT_ALLOC_NOT
if ((stream = mail_connect(MAIL_CLASS_PRIVATE, transport->name, BLOCK_MODE)) == 0) {
msg_warn("connect to transport %s: %m", transport->name);
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 mail transport unavailable",
- "mail transport unavailable"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "mail transport unavailable"));
return;
}
alloc = (QMGR_TRANSPORT_ALLOC *) mymalloc(sizeof(*alloc));
diff --git a/postfix/src/pipe/pipe.c b/postfix/src/pipe/pipe.c
index e365a3e9d..967d9fb5a 100644
--- a/postfix/src/pipe/pipe.c
+++ b/postfix/src/pipe/pipe.c
@@ -24,8 +24,8 @@
/* .ad
/* .fi
/* Some external commands cannot handle more than one recipient
-/* per delivery request. Examples of such transports are pagers,
-/* fax machines, and so on.
+/* per delivery request. Examples of such transports are pagers
+/* or fax machines.
/*
/* To prevent Postfix from sending multiple recipients per delivery
/* request, specify
@@ -882,7 +882,6 @@ static int eval_command_status(int command_status, char *service,
int status;
int result = 0;
int n;
- DSN dsn;
/*
* Depending on the result, bounce or defer the message, and mark the
@@ -892,12 +891,12 @@ static int eval_command_status(int command_status, char *service,
case PIPE_STAT_OK:
dsb_update(why, "2.0.0", "relayed", DSB_SKIP_RMTA, DSB_SKIP_REPLY,
"delivered via %s service", service);
- (void) DSN_FROM_DSN_BUF(&dsn, why);
+ (void) DSN_FROM_DSN_BUF(why);
for (n = 0; n < request->rcpt_list.len; n++) {
rcpt = request->rcpt_list.info + n;
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, &request->msg_stats, rcpt,
- service, &dsn);
+ service, &why->dsn);
if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
deliver_completed(src, rcpt->offset);
result |= status;
@@ -905,14 +904,14 @@ static int eval_command_status(int command_status, char *service,
break;
case PIPE_STAT_BOUNCE:
case PIPE_STAT_DEFER:
- (void) DSN_FROM_DSN_BUF(&dsn, why);
+ (void) DSN_FROM_DSN_BUF(why);
if (STR(why->status)[0] != '4') {
for (n = 0; n < request->rcpt_list.len; n++) {
rcpt = request->rcpt_list.info + n;
status = bounce_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id,
&request->msg_stats, rcpt,
- service, &dsn);
+ service, &why->dsn);
if (status == 0)
deliver_completed(src, rcpt->offset);
result |= status;
@@ -923,7 +922,7 @@ static int eval_command_status(int command_status, char *service,
result |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id,
&request->msg_stats, rcpt,
- service, &dsn);
+ service, &why->dsn);
}
}
break;
@@ -948,7 +947,6 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
static PIPE_ATTR attr;
RECIPIENT_LIST *rcpt_list = &request->rcpt_list;
DSN_BUF *why = dsb_create();
- DSN dsn;
VSTRING *buf;
ARGV *expanded_argv = 0;
int deliver_status;
@@ -1029,11 +1027,12 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
deliver_status = 0;
dsb_simple(why, "2.0.0", "delivers to command: %s", attr.command[0]);
+ (void) DSN_FROM_DSN_BUF(why);
for (n = 0; n < request->rcpt_list.len; n++) {
rcpt = request->rcpt_list.info + n;
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, &request->msg_stats,
- rcpt, service, DSN_FROM_DSN_BUF(&dsn, why));
+ rcpt, service, &why->dsn);
if (status == 0 && (request->flags & DEL_REQ_FLAG_SUCCESS))
deliver_completed(request->fp, rcpt->offset);
deliver_status |= status;
diff --git a/postfix/src/postlock/Makefile.in b/postfix/src/postlock/Makefile.in
index dffba604f..284f7c686 100644
--- a/postfix/src/postlock/Makefile.in
+++ b/postfix/src/postlock/Makefile.in
@@ -58,6 +58,7 @@ depend: $(MAKES)
postlock.o: ../../include/argv.h
postlock.o: ../../include/deliver_flock.h
postlock.o: ../../include/dot_lockfile.h
+postlock.o: ../../include/dsn.h
postlock.o: ../../include/dsn_buf.h
postlock.o: ../../include/dsn_util.h
postlock.o: ../../include/iostuff.h
diff --git a/postfix/src/qmgr/Makefile.in b/postfix/src/qmgr/Makefile.in
index dde0e834f..d7d52652c 100644
--- a/postfix/src/qmgr/Makefile.in
+++ b/postfix/src/qmgr/Makefile.in
@@ -66,7 +66,6 @@ qmgr.o: ../../include/argv.h
qmgr.o: ../../include/attr.h
qmgr.o: ../../include/dict.h
qmgr.o: ../../include/dsn.h
-qmgr.o: ../../include/dsn_buf.h
qmgr.o: ../../include/events.h
qmgr.o: ../../include/flush_clnt.h
qmgr.o: ../../include/iostuff.h
@@ -76,7 +75,6 @@ qmgr.o: ../../include/mail_params.h
qmgr.o: ../../include/mail_proto.h
qmgr.o: ../../include/mail_queue.h
qmgr.o: ../../include/mail_server.h
-qmgr.o: ../../include/maps.h
qmgr.o: ../../include/master_proto.h
qmgr.o: ../../include/msg.h
qmgr.o: ../../include/recipient_list.h
@@ -88,12 +86,10 @@ qmgr.o: ../../include/vstring.h
qmgr.o: qmgr.c
qmgr.o: qmgr.h
qmgr_active.o: ../../include/abounce.h
-qmgr_active.o: ../../include/argv.h
qmgr_active.o: ../../include/attr.h
qmgr_active.o: ../../include/bounce.h
qmgr_active.o: ../../include/defer.h
qmgr_active.o: ../../include/deliver_request.h
-qmgr_active.o: ../../include/dict.h
qmgr_active.o: ../../include/dsn.h
qmgr_active.o: ../../include/dsn_buf.h
qmgr_active.o: ../../include/dsn_mask.h
@@ -101,7 +97,6 @@ qmgr_active.o: ../../include/events.h
qmgr_active.o: ../../include/mail_open_ok.h
qmgr_active.o: ../../include/mail_params.h
qmgr_active.o: ../../include/mail_queue.h
-qmgr_active.o: ../../include/maps.h
qmgr_active.o: ../../include/msg.h
qmgr_active.o: ../../include/msg_stats.h
qmgr_active.o: ../../include/mymalloc.h
@@ -116,15 +111,12 @@ qmgr_active.o: ../../include/vstream.h
qmgr_active.o: ../../include/vstring.h
qmgr_active.o: qmgr.h
qmgr_active.o: qmgr_active.c
-qmgr_bounce.o: ../../include/argv.h
qmgr_bounce.o: ../../include/attr.h
qmgr_bounce.o: ../../include/bounce.h
qmgr_bounce.o: ../../include/deliver_completed.h
qmgr_bounce.o: ../../include/deliver_request.h
-qmgr_bounce.o: ../../include/dict.h
qmgr_bounce.o: ../../include/dsn.h
qmgr_bounce.o: ../../include/dsn_buf.h
-qmgr_bounce.o: ../../include/maps.h
qmgr_bounce.o: ../../include/msg_stats.h
qmgr_bounce.o: ../../include/recipient_list.h
qmgr_bounce.o: ../../include/scan_dir.h
@@ -134,15 +126,12 @@ qmgr_bounce.o: ../../include/vstream.h
qmgr_bounce.o: ../../include/vstring.h
qmgr_bounce.o: qmgr.h
qmgr_bounce.o: qmgr_bounce.c
-qmgr_defer.o: ../../include/argv.h
qmgr_defer.o: ../../include/attr.h
qmgr_defer.o: ../../include/bounce.h
qmgr_defer.o: ../../include/defer.h
qmgr_defer.o: ../../include/deliver_request.h
-qmgr_defer.o: ../../include/dict.h
qmgr_defer.o: ../../include/dsn.h
qmgr_defer.o: ../../include/dsn_buf.h
-qmgr_defer.o: ../../include/maps.h
qmgr_defer.o: ../../include/msg.h
qmgr_defer.o: ../../include/msg_stats.h
qmgr_defer.o: ../../include/recipient_list.h
@@ -153,10 +142,8 @@ qmgr_defer.o: ../../include/vstream.h
qmgr_defer.o: ../../include/vstring.h
qmgr_defer.o: qmgr.h
qmgr_defer.o: qmgr_defer.c
-qmgr_deliver.o: ../../include/argv.h
qmgr_deliver.o: ../../include/attr.h
qmgr_deliver.o: ../../include/deliver_request.h
-qmgr_deliver.o: ../../include/dict.h
qmgr_deliver.o: ../../include/dsb_scan.h
qmgr_deliver.o: ../../include/dsn.h
qmgr_deliver.o: ../../include/dsn_buf.h
@@ -166,9 +153,9 @@ qmgr_deliver.o: ../../include/iostuff.h
qmgr_deliver.o: ../../include/mail_params.h
qmgr_deliver.o: ../../include/mail_proto.h
qmgr_deliver.o: ../../include/mail_queue.h
-qmgr_deliver.o: ../../include/maps.h
qmgr_deliver.o: ../../include/msg.h
qmgr_deliver.o: ../../include/msg_stats.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/stringops.h
@@ -180,29 +167,20 @@ qmgr_deliver.o: ../../include/vstring.h
qmgr_deliver.o: ../../include/vstring_vstream.h
qmgr_deliver.o: qmgr.h
qmgr_deliver.o: qmgr_deliver.c
-qmgr_enable.o: ../../include/argv.h
-qmgr_enable.o: ../../include/dict.h
qmgr_enable.o: ../../include/dsn.h
-qmgr_enable.o: ../../include/dsn_buf.h
-qmgr_enable.o: ../../include/maps.h
qmgr_enable.o: ../../include/msg.h
qmgr_enable.o: ../../include/recipient_list.h
qmgr_enable.o: ../../include/scan_dir.h
qmgr_enable.o: ../../include/sys_defs.h
qmgr_enable.o: ../../include/vbuf.h
qmgr_enable.o: ../../include/vstream.h
-qmgr_enable.o: ../../include/vstring.h
qmgr_enable.o: qmgr.h
qmgr_enable.o: qmgr_enable.c
-qmgr_entry.o: ../../include/argv.h
qmgr_entry.o: ../../include/attr.h
qmgr_entry.o: ../../include/deliver_request.h
-qmgr_entry.o: ../../include/dict.h
qmgr_entry.o: ../../include/dsn.h
-qmgr_entry.o: ../../include/dsn_buf.h
qmgr_entry.o: ../../include/events.h
qmgr_entry.o: ../../include/mail_params.h
-qmgr_entry.o: ../../include/maps.h
qmgr_entry.o: ../../include/msg.h
qmgr_entry.o: ../../include/msg_stats.h
qmgr_entry.o: ../../include/mymalloc.h
@@ -214,12 +192,8 @@ qmgr_entry.o: ../../include/vstream.h
qmgr_entry.o: ../../include/vstring.h
qmgr_entry.o: qmgr.h
qmgr_entry.o: qmgr_entry.c
-qmgr_job.o: ../../include/argv.h
-qmgr_job.o: ../../include/dict.h
qmgr_job.o: ../../include/dsn.h
-qmgr_job.o: ../../include/dsn_buf.h
qmgr_job.o: ../../include/htable.h
-qmgr_job.o: ../../include/maps.h
qmgr_job.o: ../../include/msg.h
qmgr_job.o: ../../include/mymalloc.h
qmgr_job.o: ../../include/recipient_list.h
@@ -228,7 +202,6 @@ qmgr_job.o: ../../include/scan_dir.h
qmgr_job.o: ../../include/sys_defs.h
qmgr_job.o: ../../include/vbuf.h
qmgr_job.o: ../../include/vstream.h
-qmgr_job.o: ../../include/vstring.h
qmgr_job.o: qmgr.h
qmgr_job.o: qmgr_job.c
qmgr_message.o: ../../include/argv.h
@@ -243,11 +216,9 @@ qmgr_message.o: ../../include/dsn_attr_map.h
qmgr_message.o: ../../include/dsn_buf.h
qmgr_message.o: ../../include/dsn_mask.h
qmgr_message.o: ../../include/iostuff.h
-qmgr_message.o: ../../include/mail_addr_find.h
qmgr_message.o: ../../include/mail_params.h
qmgr_message.o: ../../include/mail_proto.h
qmgr_message.o: ../../include/mail_queue.h
-qmgr_message.o: ../../include/maps.h
qmgr_message.o: ../../include/msg.h
qmgr_message.o: ../../include/msg_stats.h
qmgr_message.o: ../../include/myflock.h
@@ -273,13 +244,9 @@ qmgr_message.o: ../../include/vstream.h
qmgr_message.o: ../../include/vstring.h
qmgr_message.o: qmgr.h
qmgr_message.o: qmgr_message.c
-qmgr_move.o: ../../include/argv.h
-qmgr_move.o: ../../include/dict.h
qmgr_move.o: ../../include/dsn.h
-qmgr_move.o: ../../include/dsn_buf.h
qmgr_move.o: ../../include/mail_queue.h
qmgr_move.o: ../../include/mail_scan_dir.h
-qmgr_move.o: ../../include/maps.h
qmgr_move.o: ../../include/msg.h
qmgr_move.o: ../../include/recipient_list.h
qmgr_move.o: ../../include/scan_dir.h
@@ -289,12 +256,8 @@ qmgr_move.o: ../../include/vstream.h
qmgr_move.o: ../../include/vstring.h
qmgr_move.o: qmgr.h
qmgr_move.o: qmgr_move.c
-qmgr_peer.o: ../../include/argv.h
-qmgr_peer.o: ../../include/dict.h
qmgr_peer.o: ../../include/dsn.h
-qmgr_peer.o: ../../include/dsn_buf.h
qmgr_peer.o: ../../include/htable.h
-qmgr_peer.o: ../../include/maps.h
qmgr_peer.o: ../../include/msg.h
qmgr_peer.o: ../../include/mymalloc.h
qmgr_peer.o: ../../include/recipient_list.h
@@ -302,17 +265,12 @@ qmgr_peer.o: ../../include/scan_dir.h
qmgr_peer.o: ../../include/sys_defs.h
qmgr_peer.o: ../../include/vbuf.h
qmgr_peer.o: ../../include/vstream.h
-qmgr_peer.o: ../../include/vstring.h
qmgr_peer.o: qmgr.h
qmgr_peer.o: qmgr_peer.c
-qmgr_queue.o: ../../include/argv.h
-qmgr_queue.o: ../../include/dict.h
qmgr_queue.o: ../../include/dsn.h
-qmgr_queue.o: ../../include/dsn_buf.h
qmgr_queue.o: ../../include/events.h
qmgr_queue.o: ../../include/htable.h
qmgr_queue.o: ../../include/mail_params.h
-qmgr_queue.o: ../../include/maps.h
qmgr_queue.o: ../../include/msg.h
qmgr_queue.o: ../../include/mymalloc.h
qmgr_queue.o: ../../include/recipient_list.h
@@ -320,15 +278,10 @@ qmgr_queue.o: ../../include/scan_dir.h
qmgr_queue.o: ../../include/sys_defs.h
qmgr_queue.o: ../../include/vbuf.h
qmgr_queue.o: ../../include/vstream.h
-qmgr_queue.o: ../../include/vstring.h
qmgr_queue.o: qmgr.h
qmgr_queue.o: qmgr_queue.c
-qmgr_scan.o: ../../include/argv.h
-qmgr_scan.o: ../../include/dict.h
qmgr_scan.o: ../../include/dsn.h
-qmgr_scan.o: ../../include/dsn_buf.h
qmgr_scan.o: ../../include/mail_scan_dir.h
-qmgr_scan.o: ../../include/maps.h
qmgr_scan.o: ../../include/msg.h
qmgr_scan.o: ../../include/mymalloc.h
qmgr_scan.o: ../../include/recipient_list.h
@@ -336,21 +289,16 @@ qmgr_scan.o: ../../include/scan_dir.h
qmgr_scan.o: ../../include/sys_defs.h
qmgr_scan.o: ../../include/vbuf.h
qmgr_scan.o: ../../include/vstream.h
-qmgr_scan.o: ../../include/vstring.h
qmgr_scan.o: qmgr.h
qmgr_scan.o: qmgr_scan.c
-qmgr_transport.o: ../../include/argv.h
qmgr_transport.o: ../../include/attr.h
-qmgr_transport.o: ../../include/dict.h
qmgr_transport.o: ../../include/dsn.h
-qmgr_transport.o: ../../include/dsn_buf.h
qmgr_transport.o: ../../include/events.h
qmgr_transport.o: ../../include/htable.h
qmgr_transport.o: ../../include/iostuff.h
qmgr_transport.o: ../../include/mail_conf.h
qmgr_transport.o: ../../include/mail_params.h
qmgr_transport.o: ../../include/mail_proto.h
-qmgr_transport.o: ../../include/maps.h
qmgr_transport.o: ../../include/msg.h
qmgr_transport.o: ../../include/mymalloc.h
qmgr_transport.o: ../../include/recipient_list.h
@@ -358,6 +306,5 @@ qmgr_transport.o: ../../include/scan_dir.h
qmgr_transport.o: ../../include/sys_defs.h
qmgr_transport.o: ../../include/vbuf.h
qmgr_transport.o: ../../include/vstream.h
-qmgr_transport.o: ../../include/vstring.h
qmgr_transport.o: qmgr.h
qmgr_transport.o: qmgr_transport.c
diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c
index a2d96f511..9dc54c2f5 100644
--- a/postfix/src/qmgr/qmgr_deliver.c
+++ b/postfix/src/qmgr/qmgr_deliver.c
@@ -73,6 +73,7 @@
#include
#include
#include
+#include
/* Application-specific. */
@@ -155,8 +156,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
flags = message->tflags
| entry->queue->dflags
| (message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT);
- QMGR_MSG_STATS(&stats, message);
- attr_print(stream, ATTR_FLAG_MORE,
+ (void) QMGR_MSG_STATS(&stats, message);
+ attr_print(stream, ATTR_FLAG_NONE,
ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags,
ATTR_TYPE_STR, MAIL_ATTR_QUEUE, message->queue_name,
ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, message->queue_id,
@@ -176,20 +177,14 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
ATTR_TYPE_STR, MAIL_ATTR_SASL_USERNAME, message->sasl_username,
ATTR_TYPE_STR, MAIL_ATTR_SASL_SENDER, message->sasl_sender,
ATTR_TYPE_STR, MAIL_ATTR_RWR_CONTEXT, message->rewrite_context,
+ ATTR_TYPE_NUM, MAIL_ATTR_RCPT_COUNT, list.len,
ATTR_TYPE_END);
if (sender_buf != 0)
vstring_free(sender_buf);
for (recipient = list.info; recipient < list.info + list.len; recipient++)
- attr_print(stream, ATTR_FLAG_MORE,
- ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, recipient->dsn_orcpt,
- ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, recipient->dsn_notify,
- ATTR_TYPE_STR, MAIL_ATTR_ORCPT, recipient->orig_addr,
- ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address,
+ attr_print(stream, ATTR_FLAG_NONE,
+ ATTR_TYPE_FUNC, rcpt_print, (void *) recipient,
ATTR_TYPE_END);
- attr_print(stream, ATTR_FLAG_NONE,
- ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0,
- ATTR_TYPE_END);
if (vstream_fflush(stream) != 0) {
msg_warn("write to process (%s): %m", entry->queue->transport->name);
return (-1);
@@ -223,7 +218,6 @@ static void qmgr_deliver_update(int unused_event, char *context)
QMGR_MESSAGE *message = entry->message;
static DSN_BUF *dsb;
int status;
- DSN dsn;
RECIPIENT *recipient;
int nrcpt;
@@ -256,9 +250,8 @@ static void qmgr_deliver_update(int unused_event, char *context)
if (status == DELIVER_STAT_CRASH) {
message->flags |= DELIVER_STAT_DEFER;
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 unknown mail transport error",
- "unknown mail transport error"));
+ DSN_SIMPLE(&dsb->dsn, "4.3.0",
+ "unknown mail transport error"));
msg_warn("transport %s failure -- see a previous warning/fatal/panic logfile record for the problem description",
transport->name);
@@ -274,9 +267,9 @@ static void qmgr_deliver_update(int unused_event, char *context)
*/
for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) {
recipient = entry->rcpt_list.info + nrcpt;
- qmgr_defer_recipient(message, recipient, &dsn);
+ qmgr_defer_recipient(message, recipient, &dsb->dsn);
}
- qmgr_defer_transport(transport, &dsn);
+ qmgr_defer_transport(transport, &dsb->dsn);
}
/*
@@ -287,21 +280,23 @@ static void qmgr_deliver_update(int unused_event, char *context)
* (the todo list); stay away from queue entries that have been selected
* (the busy list), or we would have dangling pointers. The queue itself
* won't go away before we dispose of the current queue entry.
+ *
+ * XXX Caution: DSN_COPY() will panic on empty status or reason.
*/
#define SUSPENDED "delivery temporarily suspended: "
if (status == DELIVER_STAT_DEFER) {
message->flags |= DELIVER_STAT_DEFER;
if (VSTRING_LEN(dsb->status)) {
- /* Sanitize the DSN status from the delivery agent. */
+ /* Sanitize the DSN status/reason from the delivery agent. */
if (!dsn_valid(vstring_str(dsb->status)))
vstring_strcpy(dsb->status, "4.0.0");
if (VSTRING_LEN(dsb->reason) == 0)
vstring_strcpy(dsb->reason, "unknown error");
vstring_prepend(dsb->reason, SUSPENDED, sizeof(SUSPENDED) - 1);
- qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(&dsn, dsb));
+ qmgr_queue_throttle(queue, DSN_FROM_DSN_BUF(dsb));
if (queue->window == 0)
- qmgr_defer_todo(queue, &dsn);
+ qmgr_defer_todo(queue, &dsb->dsn);
}
}
@@ -343,9 +338,8 @@ void qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
*/
if (qmgr_deliver_initial_reply(stream) != 0) {
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 mail transport unavailable",
- "mail transport unavailable"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "mail transport unavailable"));
qmgr_defer_transport(transport, &dsn);
(void) vstream_fclose(stream);
return;
@@ -372,9 +366,8 @@ void qmgr_deliver(QMGR_TRANSPORT *transport, VSTREAM *stream)
if (qmgr_deliver_send_request(entry, stream) < 0) {
qmgr_entry_unselect(entry);
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 mail transport unavailable",
- "mail transport unavailable"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "mail transport unavailable"));
qmgr_defer_transport(transport, &dsn);
/* warning: entry may be a dangling pointer here */
(void) vstream_fclose(stream);
diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c
index bd4ab56e2..fdef95bce 100644
--- a/postfix/src/qmgr/qmgr_message.c
+++ b/postfix/src/qmgr/qmgr_message.c
@@ -896,15 +896,13 @@ static int qmgr_resolve_one(QMGR_MESSAGE *message, RECIPIENT *recipient,
resolve_clnt_verify_from(message->sender, addr, reply);
if (reply->flags & RESOLVE_FLAG_FAIL) {
qmgr_defer_recipient(message, recipient,
- DSN_SMTP(&dsn, "4.3.0",
- "451 address resolver failure",
- "address resolver failure"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "address resolver failure"));
return (-1);
} else if (reply->flags & RESOLVE_FLAG_ERROR) {
qmgr_bounce_recipient(message, recipient,
- DSN_SMTP(&dsn, "5.1.3",
- "553 bad address syntax",
- "bad address syntax"));
+ DSN_SIMPLE(&dsn, "5.1.3",
+ "bad address syntax"));
return (-1);
} else {
return (0);
@@ -990,9 +988,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
*/
if (recipient->address[0] == 0) {
qmgr_bounce_recipient(message, recipient,
- DSN_SMTP(&dsn, "5.1.3",
- "553 null recipient address",
- "null recipient address"));
+ DSN_SIMPLE(&dsn, "5.1.3",
+ "null recipient address"));
continue;
}
@@ -1009,9 +1006,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
*/
if (var_allow_min_user == 0 && recipient->address[0] == '-') {
qmgr_bounce_recipient(message, recipient,
- DSN_SMTP(&dsn, "5.1.3",
- "553 bad address syntax",
- "bad address syntax"));
+ DSN_SIMPLE(&dsn, "5.1.3",
+ "bad address syntax"));
continue;
}
@@ -1057,9 +1053,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
break;
if (*cpp) {
qmgr_defer_recipient(message, recipient,
- DSN_SMTP(&dsn, "4.3.2",
- "450 delivery suspended",
- "deferred transport"));
+ DSN_SIMPLE(&dsn, "4.3.2",
+ "deferred transport"));
continue;
}
}
diff --git a/postfix/src/qmgr/qmgr_transport.c b/postfix/src/qmgr/qmgr_transport.c
index 036d15b20..14a4593ac 100644
--- a/postfix/src/qmgr/qmgr_transport.c
+++ b/postfix/src/qmgr/qmgr_transport.c
@@ -294,9 +294,8 @@ void qmgr_transport_alloc(QMGR_TRANSPORT *transport, QMGR_TRANSPORT_ALLOC_NOT
if ((stream = mail_connect(MAIL_CLASS_PRIVATE, transport->name, BLOCK_MODE)) == 0) {
msg_warn("connect to transport %s: %m", transport->name);
qmgr_transport_throttle(transport,
- DSN_SMTP(&dsn, "4.3.0",
- "451 mail transport unavailable",
- "mail transport unavailable"));
+ DSN_SIMPLE(&dsn, "4.3.0",
+ "mail transport unavailable"));
return;
}
alloc = (QMGR_TRANSPORT_ALLOC *) mymalloc(sizeof(*alloc));
diff --git a/postfix/src/qmqpd/Makefile.in b/postfix/src/qmqpd/Makefile.in
index aaf91d5e3..1ba772ef3 100644
--- a/postfix/src/qmqpd/Makefile.in
+++ b/postfix/src/qmqpd/Makefile.in
@@ -91,6 +91,7 @@ qmqpd.o: qmqpd.h
qmqpd_peer.o: ../../include/attr.h
qmqpd_peer.o: ../../include/inet_proto.h
qmqpd_peer.o: ../../include/iostuff.h
+qmqpd_peer.o: ../../include/mail_params.h
qmqpd_peer.o: ../../include/mail_proto.h
qmqpd_peer.o: ../../include/mail_stream.h
qmqpd_peer.o: ../../include/msg.h
diff --git a/postfix/src/sendmail/Makefile.in b/postfix/src/sendmail/Makefile.in
index 45f391281..a2ce8a62e 100644
--- a/postfix/src/sendmail/Makefile.in
+++ b/postfix/src/sendmail/Makefile.in
@@ -62,7 +62,6 @@ sendmail.o: ../../include/connect.h
sendmail.o: ../../include/debug_process.h
sendmail.o: ../../include/deliver_request.h
sendmail.o: ../../include/dsn.h
-sendmail.o: ../../include/dsn_buf.h
sendmail.o: ../../include/dsn_mask.h
sendmail.o: ../../include/fullname.h
sendmail.o: ../../include/header_opts.h
diff --git a/postfix/src/showq/showq.c b/postfix/src/showq/showq.c
index 806f02795..ef7e2a38f 100644
--- a/postfix/src/showq/showq.c
+++ b/postfix/src/showq/showq.c
@@ -143,7 +143,8 @@ char *var_empty_addr;
#define SENDER_FORMAT "%-11s%8ld %20.20s %s\n"
#define DROP_FORMAT "%-10s%c%8ld %20.20s (maildrop queue, sender UID %u)\n"
-static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *);
+static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *,
+HTABLE *);
#define STR(x) vstring_str(x)
@@ -160,6 +161,8 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
long msg_size = 0;
BOUNCE_LOG *logfile;
HTABLE *dup_filter = 0;
+ RCPT_BUF *rcpt_buf = 0;
+ DSN_BUF *dsn_buf = 0;
char status = (strcmp(queue, MAIL_QUEUE_ACTIVE) == 0 ? '*' :
strcmp(queue, MAIL_QUEUE_HOLD) == 0 ? '!' : ' ');
int msg_size_ok = 0;
@@ -236,47 +239,58 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
&& dup_filter == 0
&& (logfile = bounce_log_open(MAIL_QUEUE_DEFER, id, O_RDONLY, 0)) != 0) {
dup_filter = htable_create(var_dup_filter_limit);
- showq_reasons(client, logfile, dup_filter);
+ if (rcpt_buf == 0)
+ rcpt_buf = rcpb_create();
+ if (dsn_buf == 0)
+ dsn_buf = dsb_create();
+ showq_reasons(client, logfile, rcpt_buf, dsn_buf, dup_filter);
if (bounce_log_close(logfile))
msg_warn("close %s %s: %m", MAIL_QUEUE_DEFER, id);
}
}
vstring_free(buf);
vstring_free(printable_quoted_addr);
+ if (rcpt_buf)
+ rcpb_free(rcpt_buf);
+ if (dsn_buf)
+ dsb_free(dsn_buf);
if (dup_filter)
htable_free(dup_filter, (void (*) (char *)) 0);
}
/* showq_reasons - show deferral reasons */
-static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, HTABLE *dup_filter)
+static void showq_reasons(VSTREAM *client, BOUNCE_LOG *bp, RCPT_BUF *rcpt_buf,
+DSN_BUF *dsn_buf, HTABLE *dup_filter)
{
char *saved_reason = 0;
int padding;
+ RECIPIENT *rcpt = &rcpt_buf->rcpt;
+ DSN *dsn = &dsn_buf->dsn;
- while (bounce_log_read(bp) != 0) {
+ while (bounce_log_read(bp, rcpt_buf, dsn_buf) != 0) {
/*
* Update the duplicate filter.
*/
if (var_dup_filter_limit == 0
|| dup_filter->used < var_dup_filter_limit)
- if (htable_locate(dup_filter, bp->rcpt.address) == 0)
- htable_enter(dup_filter, bp->rcpt.address, (char *) 0);
+ if (htable_locate(dup_filter, rcpt->address) == 0)
+ htable_enter(dup_filter, rcpt->address, (char *) 0);
/*
* Don't print the reason when the previous recipient had the same
* problem.
*/
- if (saved_reason == 0 || strcmp(saved_reason, bp->dsn.reason) != 0) {
+ if (saved_reason == 0 || strcmp(saved_reason, dsn->reason) != 0) {
if (saved_reason)
myfree(saved_reason);
- saved_reason = mystrdup(bp->dsn.reason);
+ saved_reason = mystrdup(dsn->reason);
if ((padding = 76 - strlen(saved_reason)) < 0)
padding = 0;
vstream_fprintf(client, "%*s(%s)\n", padding, "", saved_reason);
}
- vstream_fprintf(client, STRING_FORMAT, "", "", "", bp->rcpt.address);
+ vstream_fprintf(client, STRING_FORMAT, "", "", "", rcpt->address);
}
if (saved_reason)
myfree(saved_reason);
diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in
index 00a4ed30b..668daea67 100644
--- a/postfix/src/smtp/Makefile.in
+++ b/postfix/src/smtp/Makefile.in
@@ -1,12 +1,10 @@
SHELL = /bin/sh
SRCS = smtp.c smtp_connect.c smtp_proto.c smtp_chat.c smtp_session.c \
smtp_addr.c smtp_trouble.c smtp_state.c smtp_rcpt.c \
- smtp_sasl_proto.c smtp_sasl_glue.c smtp_reuse.c smtp_map11.c \
- smtp_dsn.c
+ smtp_sasl_proto.c smtp_sasl_glue.c smtp_reuse.c smtp_map11.c
OBJS = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
smtp_addr.o smtp_trouble.o smtp_state.o smtp_rcpt.o \
- smtp_sasl_proto.o smtp_sasl_glue.o smtp_reuse.o smtp_map11.o \
- smtp_dsn.o
+ smtp_sasl_proto.o smtp_sasl_glue.o smtp_reuse.o smtp_map11.o
HDRS = smtp.h smtp_sasl.h smtp_addr.h smtp_reuse.h
TESTSRC =
DEFS = -I. -I$(INC_DIR) -D$(SYSTYPE)
@@ -234,30 +232,6 @@ smtp_connect.o: smtp.h
smtp_connect.o: smtp_addr.h
smtp_connect.o: smtp_connect.c
smtp_connect.o: smtp_reuse.h
-smtp_dsn.o: ../../include/argv.h
-smtp_dsn.o: ../../include/attr.h
-smtp_dsn.o: ../../include/deliver_request.h
-smtp_dsn.o: ../../include/dict.h
-smtp_dsn.o: ../../include/dsn.h
-smtp_dsn.o: ../../include/dsn_buf.h
-smtp_dsn.o: ../../include/htable.h
-smtp_dsn.o: ../../include/mail_params.h
-smtp_dsn.o: ../../include/maps.h
-smtp_dsn.o: ../../include/match_list.h
-smtp_dsn.o: ../../include/match_ops.h
-smtp_dsn.o: ../../include/msg_stats.h
-smtp_dsn.o: ../../include/recipient_list.h
-smtp_dsn.o: ../../include/resolve_clnt.h
-smtp_dsn.o: ../../include/scache.h
-smtp_dsn.o: ../../include/string_list.h
-smtp_dsn.o: ../../include/sys_defs.h
-smtp_dsn.o: ../../include/tls.h
-smtp_dsn.o: ../../include/tok822.h
-smtp_dsn.o: ../../include/vbuf.h
-smtp_dsn.o: ../../include/vstream.h
-smtp_dsn.o: ../../include/vstring.h
-smtp_dsn.o: smtp.h
-smtp_dsn.o: smtp_dsn.c
smtp_map11.o: ../../include/argv.h
smtp_map11.o: ../../include/attr.h
smtp_map11.o: ../../include/deliver_request.h
diff --git a/postfix/src/smtp/lmtp_params.c b/postfix/src/smtp/lmtp_params.c
index efb85e3e6..980b4fd0e 100644
--- a/postfix/src/smtp/lmtp_params.c
+++ b/postfix/src/smtp/lmtp_params.c
@@ -7,6 +7,7 @@
VAR_LMTP_SASL_PATH, DEF_LMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0,
#ifdef USE_TLS
VAR_LMTP_SASL_TLS_OPTS, DEF_LMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0,
+ VAR_LMTP_SASL_TLSV_OPTS, DEF_LMTP_SASL_TLSV_OPTS, &var_smtp_sasl_tlsv_opts, 0, 0,
#endif
VAR_LMTP_SASL_MECHS, DEF_LMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0,
VAR_LMTP_SASL_TYPE, DEF_LMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0,
@@ -70,5 +71,6 @@
VAR_LMTP_TLS_NOTEOFFER, DEF_LMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
#endif
VAR_LMTP_SENDER_AUTH, DEF_LMTP_SENDER_AUTH, &var_smtp_sender_auth,
+ VAR_LMTP_CNAME_OVERR, DEF_LMTP_CNAME_OVERR, &var_smtp_cname_overr,
0,
};
diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c
index cc1199d4a..a05bc8ae2 100644
--- a/postfix/src/smtp/smtp.c
+++ b/postfix/src/smtp/smtp.c
@@ -85,7 +85,6 @@
/* RFC 1652 (8bit-MIME transport)
/* RFC 1870 (Message Size Declaration)
/* RFC 2033 (LMTP protocol)
-/* RFC 2034 (Enhanced Status Codes)
/* RFC 2045 (MIME: Format of Internet Message Bodies)
/* RFC 2046 (MIME: Media Types)
/* RFC 2554 (AUTH command)
@@ -180,6 +179,12 @@
/* SMTP client, typically to transform a locally valid address into
/* a globally valid address when sending mail across the Internet.
/* .PP
+/* Available in Postfix version 2.2.9 and later:
+/* .IP "\fBsmtp_cname_overrides_servername (version dependent)\fR"
+/* Allow DNS CNAME records to override the servername that the
+/* Postfix SMTP client uses for logging, SASL password lookup, TLS
+/* policy decisions, or TLS certificate verification.
+/* .PP
/* Available in Postfix version 2.3 and later:
/* .IP "\fBlmtp_discard_lhlo_keyword_address_maps (empty)\fR"
/* Lookup tables, indexed by the remote LMTP server address, with
@@ -297,6 +302,12 @@
/* The number of pseudo-random bytes that an \fBsmtp\fR(8) or \fBsmtpd\fR(8)
/* process requests from the \fBtlsmgr\fR(8) server in order to seed its
/* internal pseudo random number generator (PRNG).
+/* .PP
+/* Available in Postfix version 2.3 and later:
+/* .IP "\fBsmtp_sasl_tls_verified_security_options ($smtp_sasl_tls_security_options)\fR"
+/* The SASL authentication security options that the Postfix SMTP
+/* client uses for TLS encrypted SMTP sessions with a verified server
+/* certificate.
/* RESOURCE AND RATE CONTROLS
/* .ad
/* .fi
@@ -606,6 +617,7 @@ char *var_smtp_tls_per_site;
#ifdef USE_TLS
int var_smtp_starttls_tmout;
char *var_smtp_sasl_tls_opts;
+char *var_smtp_sasl_tlsv_opts;
bool var_smtp_tls_enforce_peername;
int var_smtp_tls_scert_vd;
bool var_smtp_tls_note_starttls_offer;
@@ -617,12 +629,11 @@ char *var_prop_extension;
bool var_smtp_sender_auth;
char *var_lmtp_tcp_port;
int var_scache_proto_tmout;
+bool var_smtp_cname_overr;
/*
- * Global variables. smtp_errno is set by the address lookup routines and by
- * the connection management routines.
+ * Global variables.
*/
-int smtp_errno;
int smtp_host_lookup_mask;
STRING_LIST *smtp_cache_dest;
SCACHE *smtp_scache;
diff --git a/postfix/src/smtp/smtp.h b/postfix/src/smtp/smtp.h
index 9e4e5c8ed..e79832fb0 100644
--- a/postfix/src/smtp/smtp.h
+++ b/postfix/src/smtp/smtp.h
@@ -8,6 +8,11 @@
/* DESCRIPTION
/* .nf
+ /*
+ * System library.
+ */
+#include
+
/*
* Utility library.
*/
@@ -77,7 +82,7 @@ typedef struct SMTP_STATE {
/*
* DSN Support introduced major bloat in error processing.
*/
- VSTRING *dsn_reason; /* on-the-fly formatting buffer */
+ DSN_BUF *why; /* on-the-fly formatting buffer */
} SMTP_STATE;
#define SET_NEXTHOP_STATE(state, lookup_mx, domain, port) { \
@@ -140,12 +145,14 @@ typedef struct SMTP_STATE {
/*
* smtp.c
*/
-extern int smtp_errno; /* XXX can we get rid of this? */
+#define SMTP_HAS_DSN(why) (STR((why)->status)[0] != 0)
+#define SMTP_HAS_SOFT_DSN(why) (STR((why)->status)[0] == '4')
+#define SMTP_HAS_HARD_DSN(why) (STR((why)->status)[0] == '5')
+#define SMTP_HAS_LOOP_DSN(why) \
+ (SMTP_HAS_DSN(why) && strcmp(STR((why)->status) + 1, ".4.6") == 0)
-#define SMTP_ERR_NONE 0 /* no error */
-#define SMTP_ERR_FAIL 1 /* permanent error */
-#define SMTP_ERR_RETRY 2 /* temporary error */
-#define SMTP_ERR_LOOP 3 /* mailer loop */
+#define SMTP_SET_SOFT_DSN(why) (STR((why)->status)[0] = '4')
+#define SMTP_SET_HARD_DSN(why) (STR((why)->status)[0] = '5')
extern int smtp_host_lookup_mask; /* host lookup methods to use */
@@ -228,6 +235,11 @@ extern void smtp_tls_list_init(void);
#endif
+ /*
+ * What's in a name?
+ */
+#define SMTP_HNAME(rr) (var_smtp_cname_overr ? (rr)->rname : (rr)->qname)
+
/*
* smtp_connect.c
*/
@@ -320,12 +332,14 @@ extern void smtp_chat_init(SMTP_SESSION *);
extern void smtp_chat_reset(SMTP_SESSION *);
extern void smtp_chat_notify(SMTP_SESSION *);
-#define SMTP_RESP_FAKE(resp, _code, _dsn, _str) \
- ((resp)->code = (_code), \
+#define SMTP_RESP_FAKE(resp, _dsn) \
+ ((resp)->code = 0, \
(resp)->dsn = (_dsn), \
- (resp)->str = (_str), \
+ (resp)->str = DSN_BY_LOCAL_MTA, \
(resp))
+#define DSN_BY_LOCAL_MTA ((char *) 0) /* DSN issued by local MTA */
+
/*
* These operations implement a redundant mark-and-sweep algorithm that
* explicitly accounts for the fate of every recipient. The interface is
@@ -370,7 +384,7 @@ extern void smtp_rcpt_done(SMTP_STATE *, SMTP_RESP *, RECIPIENT *);
/*
* smtp_trouble.c
*/
-extern int smtp_sess_fail(SMTP_STATE *, DSN_BUF *);
+extern int smtp_sess_fail(SMTP_STATE *);
extern int PRINTFLIKE(4, 5) smtp_site_fail(SMTP_STATE *, const char *,
SMTP_RESP *, const char *,...);
extern int PRINTFLIKE(4, 5) smtp_mesg_fail(SMTP_STATE *, const char *,
@@ -399,26 +413,6 @@ extern int smtp_map11_external(VSTRING *, MAPS *, int);
extern int smtp_map11_tree(TOK822 *, MAPS *, int);
extern int smtp_map11_internal(VSTRING *, MAPS *, int);
- /*
- * smtp_dsn.c
- */
-extern void PRINTFLIKE(6, 7) smtp_dsn_update(DSN_BUF *, const char *,
- const char *,
- int,
- const char *,
- const char *,...);
-extern void vsmtp_dsn_update(DSN_BUF *, const char *, const char *,
- int, const char *,
- const char *, va_list);
-extern void smtp_dsn_formal(DSN_BUF *, const char *, const char *, int,
- const char *);
-
-#define SMTP_DSN_ASSIGN(dsn, mta, stat, resp, why) \
- DSN_ASSIGN((dsn), (stat), DSB_DEF_ACTION, (why), DSB_DTYPE_SMTP, (resp), \
- (mta) ? DSB_MTYPE_DNS : DSB_MTYPE_NONE, (mta))
-
-#define DSN_BY_LOCAL_MTA ((char *) 0) /* DSN issued by local MTA */
-
/*
* Silly little macros.
*/
diff --git a/postfix/src/smtp/smtp_addr.c b/postfix/src/smtp/smtp_addr.c
index ddc06c87e..bb9f0d147 100644
--- a/postfix/src/smtp/smtp_addr.c
+++ b/postfix/src/smtp/smtp_addr.c
@@ -48,16 +48,7 @@
/* when DNS lookups are explicitly disabled.
/*
/* All routines either return a DNS_RR pointer, or return a null
-/* pointer and set the \fIsmtp_errno\fR global variable accordingly:
-/* .IP SMTP_ERR_RETRY
-/* The request failed due to a soft error, and should be retried later.
-/* .IP SMTP_ERR_FAIL
-/* The request attempt failed due to a hard error.
-/* .IP SMTP_ERR_LOOP
-/* The local machine is the best mail exchanger.
-/* .PP
-/* In addition, a description of the problem is made available
-/* via the \fIwhy\fR argument.
+/* pointer and update the \fIwhy\fR argument accordingly.
/* LICENSE
/* .ad
/* .fi
@@ -120,7 +111,7 @@ static void smtp_print_addr(char *what, DNS_RR *addr_list)
msg_warn("skipping record type %s: %m", dns_strtype(addr->type));
} else {
msg_info("pref %4d host %s/%s",
- addr->pref, addr->name,
+ addr->pref, SMTP_HNAME(addr),
hostaddr.buf);
}
}
@@ -170,22 +161,14 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
addr_list = dns_rr_append(addr_list, addr);
return (addr_list);
default:
- smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
- "4.4.3", 450, "450 Host not found");
- smtp_errno = SMTP_ERR_RETRY;
+ dsb_status(why, "4.4.3");
return (addr_list);
case DNS_FAIL:
- smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
- "5.4.3", 550, "550 Name server failure");
- if (smtp_errno != SMTP_ERR_RETRY)
- smtp_errno = SMTP_ERR_FAIL;
+ dsb_status(why, SMTP_HAS_SOFT_DSN(why) ? "4.4.3" : "5.4.3");
return (addr_list);
case DNS_INVAL:
case DNS_NOTFOUND:
- smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
- "5.4.4", 550, "550 Host not found");
- if (smtp_errno != SMTP_ERR_RETRY)
- smtp_errno = SMTP_ERR_FAIL;
+ dsb_status(why, SMTP_HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4");
/* maybe native naming service will succeed */
break;
}
@@ -206,14 +189,11 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
if (smtp_host_lookup_mask & SMTP_HOST_FLAG_NATIVE) {
if ((aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0)) != 0) {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- DSN_NOHOST(aierr) ? "4.4.4" : "4.3.0",
- 450, "450 Host not found",
- "unable to look up host %s: %s",
- host, MAI_STRERROR(aierr));
- if (smtp_errno != SMTP_ERR_RETRY)
- smtp_errno =
- (RETRY_AI_ERROR(aierr) ? SMTP_ERR_RETRY : SMTP_ERR_FAIL);
+ dsb_simple(why, (SMTP_HAS_SOFT_DSN(why) || RETRY_AI_ERROR(aierr)) ?
+ (DSN_NOHOST(aierr) ? "4.4.4" : "4.3.0") :
+ (DSN_NOHOST(aierr) ? "5.4.4" : "5.3.0"),
+ "unable to look up host %s: %s",
+ host, MAI_STRERROR(aierr));
} else {
for (found = 0, res = res0; res != 0; res = res->ai_next) {
if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
@@ -229,11 +209,8 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
}
freeaddrinfo(res0);
if (found == 0) {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "5.4.4", 550, "550 Host not found",
- "%s: host not found", host);
- if (smtp_errno != SMTP_ERR_RETRY)
- smtp_errno = SMTP_ERR_FAIL;
+ dsb_simple(why, SMTP_HAS_SOFT_DSN(why) ? "4.4.4" : "5.4.4",
+ "%s: host not found", host);
}
return (addr_list);
}
@@ -257,10 +234,11 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, DSN_BUF *why)
* with DNS lookups (except if we're backup MX, and all the better MX
* hosts can't be found).
*
- * XXX 2821: update smtp_errno (0->FAIL upon unrecoverable lookup error,
- * any->RETRY upon temporary lookup error) so that we can correctly
- * handle the case of no resolvable MX host. Currently this is always
- * treated as a soft error. RFC 2821 wants a more precise response.
+ * XXX 2821: update the error status (0->FAIL upon unrecoverable lookup
+ * error, any->RETRY upon temporary lookup error) so that we can
+ * correctly handle the case of no resolvable MX host. Currently this is
+ * always treated as a soft error. RFC 2821 wants a more precise
+ * response.
*/
for (rr = mx_names; rr; rr = rr->next) {
if (rr->type != T_MX)
@@ -349,7 +327,7 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
unsigned best_pref;
unsigned best_found;
- smtp_errno = SMTP_ERR_NONE; /* Paranoia */
+ dsb_reset(why); /* Paranoia */
/*
* Preferences from DNS use 0..32767, fall-backs use 32768+.
@@ -406,16 +384,12 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
*/
switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why->reason)) {
default:
- smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
- "4.4.3", 450, "450 Host not found");
- smtp_errno = SMTP_ERR_RETRY;
+ dsb_status(why, "4.4.3");
if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(name, misc_flags, why);
break;
case DNS_FAIL:
- smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
- "5.4.3", 550, "550 Name server failure");
- smtp_errno = SMTP_ERR_FAIL;
+ dsb_status(why, "5.4.3");
if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(name, misc_flags, why);
break;
@@ -425,9 +399,15 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
addr_list = smtp_addr_list(mx_names, why);
dns_rr_free(mx_names);
if (addr_list == 0) {
- /* DSN and text does not change. */
- if (var_smtp_defer_mxaddr)
- smtp_errno = SMTP_ERR_RETRY;
+ /* Text does not change. */
+ if (var_smtp_defer_mxaddr) {
+ /* Don't clobber the null terminator. */
+ if (SMTP_HAS_HARD_DSN(why))
+ SMTP_SET_SOFT_DSN(why); /* XXX */
+ /* Require some error status. */
+ else if (!SMTP_HAS_SOFT_DSN(why))
+ msg_panic("smtp_domain_addr: bad status");
+ }
msg_warn("no MX host for %s has a valid address record", name);
break;
}
@@ -439,17 +419,11 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
addr_list = smtp_truncate_self(addr_list, self->pref);
if (addr_list == 0) {
if (best_pref != best_found) {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "4.4.4", 450, "450 Host not found",
- "unable to find primary relay for %s",
- name);
- smtp_errno = SMTP_ERR_RETRY;
+ dsb_simple(why, "4.4.4",
+ "unable to find primary relay for %s", name);
} else {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "5.4.6", 550, "550 Mailer loop",
- "mail for %s loops back to myself",
- name);
- smtp_errno = SMTP_ERR_LOOP;
+ dsb_simple(why, "5.4.6", "mail for %s loops back to myself",
+ name);
}
}
}
@@ -459,9 +433,7 @@ DNS_RR *smtp_domain_addr(char *name, int misc_flags, DSN_BUF *why,
}
break;
case DNS_INVAL:
- smtp_dsn_formal(why, DSN_BY_LOCAL_MTA,
- "5.4.4", 550, "550 Host not found");
- smtp_errno = SMTP_ERR_FAIL;
+ dsb_status(why, "5.4.4");
break;
case DNS_NOTFOUND:
addr_list = smtp_host_addr(name, misc_flags, why);
@@ -481,7 +453,7 @@ DNS_RR *smtp_host_addr(char *host, int misc_flags, DSN_BUF *why)
{
DNS_RR *addr_list;
- smtp_errno = SMTP_ERR_NONE; /* Paranoia */
+ dsb_reset(why); /* Paranoia */
/*
* If the host is specified by numerical address, just convert the
@@ -493,10 +465,7 @@ DNS_RR *smtp_host_addr(char *host, int misc_flags, DSN_BUF *why)
&& (misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
&& smtp_find_self(addr_list) != 0) {
dns_rr_free(addr_list);
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "5.4.6", 550, "550 Mailer loop",
- "mail for %s loops back to myself", host);
- smtp_errno = SMTP_ERR_LOOP;
+ dsb_simple(why, "5.4.6", "mail for %s loops back to myself", host);
return (0);
}
if (addr_list && addr_list->next) {
diff --git a/postfix/src/smtp/smtp_chat.c b/postfix/src/smtp/smtp_chat.c
index 0b645dc47..7b68b157c 100644
--- a/postfix/src/smtp/smtp_chat.c
+++ b/postfix/src/smtp/smtp_chat.c
@@ -400,13 +400,14 @@ void smtp_chat_notify(SMTP_SESSION *session)
* generate from untrusted data.
*/
#define NULL_TRACE_FLAGS 0
+#define NO_QUEUE_ID ((VSTRING *) 0)
#define LENGTH 78
#define INDENT 4
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
var_error_rcpt,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS);
+ NULL_TRACE_FLAGS, NO_QUEUE_ID);
if (notice == 0) {
msg_warn("postmaster notify: %m");
return;
diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c
index 6e883116d..8142cc47a 100644
--- a/postfix/src/smtp/smtp_connect.c
+++ b/postfix/src/smtp/smtp_connect.c
@@ -126,17 +126,14 @@ static SMTP_SESSION *smtp_connect_unix(const char *addr,
int len = strlen(addr);
int sock;
- smtp_errno = SMTP_ERR_NONE; /* Paranoia */
+ dsb_reset(why); /* Paranoia */
/*
* Sanity checks.
*/
if (len >= (int) sizeof(sock_un.sun_path)) {
msg_warn("unix-domain name too long: %s", addr);
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA, "4.3.5",
- 450, "450 Mail server configuration error",
- "Server configuration error");
- smtp_errno = SMTP_ERR_RETRY;
+ dsb_simple(why, "4.3.5", "Server configuration error");
return (0);
}
@@ -182,7 +179,7 @@ static SMTP_SESSION *smtp_connect_addr(const char *destination, DNS_RR *addr,
char *bind_addr;
char *bind_var;
- smtp_errno = SMTP_ERR_NONE; /* Paranoia */
+ dsb_reset(why); /* Paranoia */
/*
* Sanity checks.
@@ -190,10 +187,7 @@ static SMTP_SESSION *smtp_connect_addr(const char *destination, DNS_RR *addr,
if (dns_rr_to_sa(addr, port, sa, &salen) != 0) {
msg_warn("%s: skip address type %s: %m",
myname, dns_strtype(addr->type));
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA, "4.4.0",
- 451, "451 network address conversion failed",
- "network address conversion failed: %m");
- smtp_errno = SMTP_ERR_RETRY;
+ dsb_simple(why, "4.4.0", "network address conversion failed: %m");
return (0);
}
@@ -271,9 +265,9 @@ static SMTP_SESSION *smtp_connect_addr(const char *destination, DNS_RR *addr,
SOCKADDR_TO_HOSTADDR(sa, salen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
if (msg_verbose)
msg_info("%s: trying: %s[%s] port %d...",
- myname, addr->name, hostaddr.buf, ntohs(port));
+ myname, SMTP_HNAME(addr), hostaddr.buf, ntohs(port));
- return (smtp_connect_sock(sock, sa, salen, addr->name, hostaddr.buf,
+ return (smtp_connect_sock(sock, sa, salen, SMTP_HNAME(addr), hostaddr.buf,
port, destination, why, sess_flags));
}
@@ -290,7 +284,6 @@ static SMTP_SESSION *smtp_connect_sock(int sock, struct sockaddr * sa,
int conn_stat;
int saved_errno;
VSTREAM *stream;
- int ch;
time_t start_time;
start_time = time((time_t *) 0);
@@ -303,54 +296,12 @@ static SMTP_SESSION *smtp_connect_sock(int sock, struct sockaddr * sa,
} else {
conn_stat = sane_connect(sock, sa, salen);
}
- /* XXX 42X Means connection error, but only 421 is defined. */
if (conn_stat < 0) {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "4.4.1", 420, "420 Unable to connect to server",
- "connect to %s[%s]: %m", name, addr);
- smtp_errno = SMTP_ERR_RETRY;
+ dsb_simple(why, "4.4.1", "connect to %s[%s]: %m", name, addr);
close(sock);
return (0);
}
-
- /*
- * Following code is obsolete now that the SMTP client will connect to
- * alternate hosts when a session fails before "MAIL FROM".
- */
-#if 1
stream = vstream_fdopen(sock, O_RDWR);
-#else
-
- /*
- * Skip this host if it takes no action within some time limit. XXX Some
- * MTAs use 426 to indicate a timeout error.
- */
- if (read_wait(sock, var_smtp_helo_tmout) < 0) {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "4.4.2", 426, "426 No response from server",
- "connect to %s[%s]: read timeout",
- addr->name, hostaddr.buf);
- smtp_errno = SMTP_ERR_RETRY;
- close(sock);
- return (0);
- }
-
- /*
- * Skip this host if it disconnects without talking to us.
- */
- stream = vstream_fdopen(sock, O_RDWR);
- if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "4.4.0", 421, "421 Lost connection",
- "connect to %s[%s]: server dropped connection"
- " without sending the initial greeting",
- addr->name, hostaddr.buf);
- smtp_errno = SMTP_ERR_RETRY;
- vstream_fclose(stream);
- return (0);
- }
- vstream_ungetc(stream, ch);
-#endif
/*
* Bundle up what we have into a nice SMTP_SESSION object.
@@ -473,11 +424,11 @@ static void smtp_cleanup_session(SMTP_STATE *state)
/* smtp_connect_local - connect to local server */
-static void smtp_connect_local(SMTP_STATE *state, const char *path,
- DSN_BUF *why)
+static void smtp_connect_local(SMTP_STATE *state, const char *path)
{
DELIVER_REQUEST *request = state->request;
SMTP_SESSION *session;
+ DSN_BUF *why = state->why;
/*
* It's too painful to weave this code into the SMTP connection
@@ -660,13 +611,14 @@ static int smtp_reuse_session(SMTP_STATE *state, int lookup_mx,
/* smtp_connect_remote - establish remote connection */
static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
- char *def_service, DSN_BUF *why)
+ char *def_service)
{
DELIVER_REQUEST *request = state->request;
ARGV *sites;
char *dest;
char **cpp;
int non_fallback_sites;
+ DSN_BUF *why = state->why;
/*
* First try to deliver to the indicated destination, then try to deliver
@@ -759,7 +711,7 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
* Don't try fall-back hosts if mail loops to myself. That would just
* make the problem worse.
*/
- if (addr_list == 0 && smtp_errno == SMTP_ERR_LOOP)
+ if (addr_list == 0 && SMTP_HAS_LOOP_DSN(why))
state->misc_flags |= SMTP_MISC_FLAG_FINAL_NEXTHOP;
/*
@@ -885,23 +837,22 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
if (SMTP_RCPT_LEFT(state) > 0) {
/*
- * In case of a "no error" indication we make up an excuse; this can
- * happen when the fall-back relay was already tried via a cached
- * connection, so that the address list scrubber left behind an empty
- * list.
+ * In case of a "no error" indication we make up an excuse: we did
+ * find the host address, but we did not attempt to connect to it.
+ * This can happen when the fall-back relay was already tried via a
+ * cached connection, so that the address list scrubber left behind
+ * an empty list.
*/
- if (smtp_errno == SMTP_ERR_NONE) {
- smtp_dsn_update(why, DSN_BY_LOCAL_MTA,
- "4.3.0", 450, "450 Server unavailable",
- "server unavailable or unable to receive mail");
- smtp_errno = SMTP_ERR_RETRY;
+ if (!SMTP_HAS_DSN(why)) {
+ dsb_simple(why, "4.3.0",
+ "server unavailable or unable to receive mail");
}
/*
* Pay attention to what could be configuration problems, and pretend
* that these are recoverable rather than bouncing the mail.
*/
- else if (smtp_errno != SMTP_ERR_RETRY
+ else if (!SMTP_HAS_SOFT_DSN(why)
&& (state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) == 0) {
/*
@@ -912,7 +863,6 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
msg_warn("%s configuration problem", VAR_SMTP_FALLBACK);
vstring_strcpy(why->status, "4.3.5");
/* XXX Keep the diagnostic code and MTA. */
- smtp_errno = SMTP_ERR_RETRY;
}
/*
@@ -923,18 +873,17 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
msg_warn("%s configuration problem", VAR_RELAYHOST);
vstring_strcpy(why->status, "4.3.5");
/* XXX Keep the diagnostic code and MTA. */
- smtp_errno = SMTP_ERR_RETRY;
}
/*
* Mail for the next-hop destination loops back to myself. Pass
* the mail to the best_mx_transport or bounce it.
*/
- else if (smtp_errno == SMTP_ERR_LOOP && *var_bestmx_transp) {
+ else if (SMTP_HAS_LOOP_DSN(why) && *var_bestmx_transp) {
+ dsb_reset(why); /* XXX */
state->status = deliver_pass_all(MAIL_CLASS_PRIVATE,
var_bestmx_transp,
request);
- smtp_errno = 0; /* XXX */
SMTP_RCPT_LEFT(state) = 0; /* XXX */
}
}
@@ -953,7 +902,6 @@ static void smtp_connect_remote(SMTP_STATE *state, const char *nexthop,
int smtp_connect(SMTP_STATE *state)
{
DELIVER_REQUEST *request = state->request;
- DSN_BUF *why = dsb_create();
char *destination = request->nexthop;
/*
@@ -975,11 +923,11 @@ int smtp_connect(SMTP_STATE *state)
*/
if (state->misc_flags & SMTP_MISC_FLAG_USE_LMTP) {
if (strncmp(destination, "unix:", 5) == 0) {
- smtp_connect_local(state, destination + 5, why);
+ smtp_connect_local(state, destination + 5);
} else {
if (strncmp(destination, "inet:", 5) == 0)
destination += 5;
- smtp_connect_remote(state, destination, DEF_LMTP_SERVICE, why);
+ smtp_connect_remote(state, destination, DEF_LMTP_SERVICE);
}
}
@@ -992,7 +940,7 @@ int smtp_connect(SMTP_STATE *state)
* Postfix configurations that have a host with such a name.
*/
else {
- smtp_connect_remote(state, destination, DEF_SMTP_SERVICE, why);
+ smtp_connect_remote(state, destination, DEF_SMTP_SERVICE);
}
/*
@@ -1005,20 +953,10 @@ int smtp_connect(SMTP_STATE *state)
* deferred recipients at the end. We'd probably still want to bounce
* recipients immediately, so we'd end up with another chunk of code for
* defer logging only.
- *
- * XXX Unlike enhanced status codes, changing a 4xx into 5xx SMTP code is
- * not simply a matter of changing the initial digit. What we're doing
- * here is correct only under specific conditions, such as changing 450
- * into 550 or vice versa.
*/
if (SMTP_RCPT_LEFT(state) > 0) {
state->misc_flags |= SMTP_MISC_FLAG_FINAL_SERVER; /* XXX */
- if (smtp_errno == SMTP_ERR_RETRY)
- STR(why->status)[0] = STR(why->dtext)[0] = '4'; /* XXX */
- else
- STR(why->status)[0] = STR(why->dtext)[0] = '5'; /* XXX */
- why->dcode = atoi(STR(why->dtext)); /* XXX */
- smtp_sess_fail(state, why);
+ smtp_sess_fail(state);
/*
* Sanity check. Don't silently lose recipients.
@@ -1027,6 +965,5 @@ int smtp_connect(SMTP_STATE *state)
if (SMTP_RCPT_LEFT(state) > 0)
msg_panic("smtp_connect: left-over recipients");
}
- dsb_free(why);
return (state->status);
}
diff --git a/postfix/src/smtp/smtp_dsn.c b/postfix/src/smtp/smtp_dsn.c
deleted file mode 100644
index a48701ec0..000000000
--- a/postfix/src/smtp/smtp_dsn.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*++
-/* NAME
-/* smtp_dsn 3
-/* SUMMARY
-/* application-specific DSN wrappers
-/* SYNOPSIS
-/* #include
-/*
-/* void smtp_dsn_update(dsb, mta_name, status, code, reply,
-/* reason_fmt, ...)
-/* SMTP_DSN *dsb;
-/* const char *mta_name;
-/* const char *status;
-/* int code;
-/* const char *reply;
-/* const char *reason_fmt;
-/*
-/* void vsmtp_dsn_update(dsb, mta_name, status, code, reply,
-/* reason_fmt, ap)
-/* SMTP_DSN *dsb;
-/* const char *mta_name;
-/* const char *status;
-/* int code;
-/* const char *reply;
-/* const char *reason_fmt;
-/* va_list ap;
-/*
-/* void smtp_dsn_formal(dsb, mta_name, status, code, reply)
-/* DSN_BUF *dsb;
-/* const char *mta_name;
-/* const char *status;
-/* int code;
-/* const char *reply;
-/*
-/* DSN *SMTP_DSN_ASSIGN(dsn, mta_name, status, action, reply, reason)
-/* DSN *dsn;
-/* const char *mta_name;
-/* const char *status;
-/* const char *action;
-/* const char *reply;
-/* const char *reason;
-/* DESCRIPTION
-/* This module implements application-specific wrappers for
-/* the dsbuf(3) delivery status information module. The purpose
-/* of the wrappers is to eliminate clutter from the code.
-/*
-/* smtp_dsn_update() updates the formal and informal delivery
-/* status attributes.
-/*
-/* vsmtp_dsn_update() implements an alternative interface.
-/*
-/* smtp_dsn_formal() updates the formal delivery status
-/* attributes and leaves the informal reason attribute unmodified.
-/*
-/* SMTP_DSN_ASSIGN() is a wrapper around the DSN_ASSIGN macro.
-/*
-/* Arguments:
-/* .IP dsb
-/* Delivery status information. See dsbuf(3).
-/* .IP mta_name
-/* The name of the MTA that issued the response given with the
-/* status and reply arguments. Specify DSN_BY_LOCAL_MTA for
-/* status and "reply" information that was issued by the local
-/* MTA.
-/* .IP status
-/* RFC 3463 status code.
-/* .IP code
-/* SMTP reply code.
-/* .IP reply
-/* SMTP reply code followed by text. The bounce(8) server
-/* replaces non-printable characters by '?', so it is a good
-/* idea to replace embedded newline characters by spaces
-/* before using this module.
-/* .IP reason_fmt
-/* Format string for the informal reason attribute.
-/* .IP DIAGNOSTICS
-/* Fatal: out of memory. Panic: invalid arguments.
-/* BUGS
-/* It seems wasteful to copy mostly-constant information into
-/* VSTRING buffers, but it's unavoidable if one needs to
-/* delegate work to a subordinate routine, and report the error
-/* after the subordinate has terminated.
-/* 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
-#include /* 44BSD stdarg.h uses abort() */
-#include
-
-/* Utility library. */
-
-#include
-
-/* Global library. */
-
-#include
-#include
-
-/* Application-specific. */
-
-#include
-
-/* smtp_dsn_update - update formal and informal DSN attributes */
-
-void smtp_dsn_update(DSN_BUF *why, const char *mta_name,
- const char *status, int code,
- const char *reply,
- const char *format,...)
-{
- va_list ap;
-
- va_start(ap, format);
- vsmtp_dsn_update(why, mta_name, status, code, reply, format, ap);
- va_end(ap);
-}
-
-/* vsmtp_dsn_update - update formal and informal DSN attributes */
-
-void vsmtp_dsn_update(DSN_BUF *why, const char *mta_name,
- const char *status, int code,
- const char *reply,
- const char *format, va_list ap)
-{
- dsb_formal(why, status, DSB_DEF_ACTION,
- mta_name ? DSB_MTYPE_DNS : DSB_MTYPE_NONE,
- mta_name, var_procname, code, reply);
- vstring_vsprintf(why->reason, format, ap);
-}
-
-/* smtp_dsn_formal - update formal DSN attributes only */
-
-void smtp_dsn_formal(DSN_BUF *why, const char *mta_name,
- const char *status, int code,
- const char *reply)
-{
- dsb_formal(why, status, DSB_DEF_ACTION,
- mta_name ? DSB_MTYPE_DNS : DSB_MTYPE_NONE,
- mta_name, var_procname, code, reply);
-}
diff --git a/postfix/src/smtp/smtp_params.c b/postfix/src/smtp/smtp_params.c
index f3a1494b1..2aed9efa1 100644
--- a/postfix/src/smtp/smtp_params.c
+++ b/postfix/src/smtp/smtp_params.c
@@ -8,6 +8,7 @@
VAR_SMTP_SASL_PATH, DEF_SMTP_SASL_PATH, &var_smtp_sasl_path, 0, 0,
#ifdef USE_TLS
VAR_SMTP_SASL_TLS_OPTS, DEF_SMTP_SASL_TLS_OPTS, &var_smtp_sasl_tls_opts, 0, 0,
+ VAR_SMTP_SASL_TLSV_OPTS, DEF_SMTP_SASL_TLSV_OPTS, &var_smtp_sasl_tlsv_opts, 0, 0,
#endif
VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0,
VAR_SMTP_SASL_TYPE, DEF_SMTP_SASL_TYPE, &var_smtp_sasl_type, 1, 0,
@@ -74,5 +75,6 @@
VAR_SMTP_TLS_NOTEOFFER, DEF_SMTP_TLS_NOTEOFFER, &var_smtp_tls_note_starttls_offer,
#endif
VAR_SMTP_SENDER_AUTH, DEF_SMTP_SENDER_AUTH, &var_smtp_sender_auth,
+ VAR_SMTP_CNAME_OVERR, DEF_SMTP_CNAME_OVERR, &var_smtp_cname_overr,
0,
};
diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c
index 337fda0a0..5cee7ff28 100644
--- a/postfix/src/smtp/smtp_proto.c
+++ b/postfix/src/smtp/smtp_proto.c
@@ -405,14 +405,12 @@ int smtp_helo(SMTP_STATE *state)
session->namaddrport, var_myhostname);
if (session->features & SMTP_FEATURE_BEST_MX)
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 554, "5.4.6",
- "554 Mailer loop"),
+ SMTP_RESP_FAKE(&fake, "5.4.6"),
"mail for %s loops back to myself",
request->nexthop));
else
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 450, "4.4.6",
- "450 Mailer loop"),
+ SMTP_RESP_FAKE(&fake, "4.4.6"),
"mail for %s loops back to myself",
request->nexthop));
}
@@ -542,10 +540,8 @@ int smtp_helo(SMTP_STATE *state)
smtp_chat_cmd(session, "STARTTLS");
if ((resp = smtp_chat_resp(session))->code / 100 == 2) {
#ifdef USE_SASL_AUTH
- if (session->sasl_mechanism_list) {
- myfree(session->sasl_mechanism_list);
- session->sasl_mechanism_list = 0;
- }
+ if (session->features & SMTP_FEATURE_AUTH)
+ smtp_sasl_cleanup(session);
#endif
session->features = saved_features;
/* XXX Mix-up of per-session and per-request flags. */
@@ -578,39 +574,26 @@ int smtp_helo(SMTP_STATE *state)
if (session->tls_enforce_tls) {
if (!(session->features & SMTP_FEATURE_STARTTLS)) {
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 421, "4.7.4",
- "421 TLS is required, but unavailable"),
+ SMTP_RESP_FAKE(&fake, "4.7.4"),
"TLS is required, but was not offered by host %s",
session->namaddr));
} else if (smtp_tls_ctx == 0) {
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 421, "4.7.5",
- "421 TLS is required, but unavailable"),
+ SMTP_RESP_FAKE(&fake, "4.7.5"),
"TLS is required, but our TLS engine is unavailable"));
} else {
msg_warn("%s: TLS is required but unavailable, don't know why",
myname);
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 421, "4.7.0",
- "421 TLS is required, but unavailable"),
+ SMTP_RESP_FAKE(&fake, "4.7.0"),
"TLS is required, but unavailable"));
}
}
}
#endif
#ifdef USE_SASL_AUTH
- if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH)) {
- if (session->sasl_mechanism_list != 0)
- return (smtp_sasl_helo_login(state));
- else
- return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 421, "4.7.0",
- "421 SASL authentication failed: "
- "server offered no compatible authentication mechanisms"),
- "SASL authentication failed: "
- "server %s offered no compatible authentication mechanisms",
- session->namaddr));
- }
+ if (var_smtp_sasl_enable && (session->features & SMTP_FEATURE_AUTH))
+ return (smtp_sasl_helo_login(state));
#endif
return (0);
@@ -669,8 +652,7 @@ static int smtp_start_tls(SMTP_STATE *state)
vstring_free(serverid);
if (session->tls_context == 0)
return (smtp_site_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 421, "4.7.5",
- "421 TLS handshake failure"),
+ SMTP_RESP_FAKE(&fake, "4.7.5"),
"Cannot start TLS: handshake failure"));
/*
@@ -860,14 +842,11 @@ static void smtp_mime_fail(SMTP_STATE *state, int mime_errs)
{
MIME_STATE_DETAIL *detail;
SMTP_RESP fake;
- char *text;
detail = mime_state_detail(mime_errs);
- text = concatenate("554 ", detail->text, (char *) 0);
smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 554, detail->dsn, text),
+ SMTP_RESP_FAKE(&fake, detail->dsn),
"%s", detail->text);
- myfree(text);
}
/* smtp_loop - exercise the SMTP protocol engine */
@@ -1638,8 +1617,7 @@ int smtp_xfer(SMTP_STATE *state)
*/
if (session->size_limit > 0 && session->size_limit < request->data_size) {
smtp_mesg_fail(state, DSN_BY_LOCAL_MTA,
- SMTP_RESP_FAKE(&fake, 552, "5.3.4",
- "552 message too large"),
+ SMTP_RESP_FAKE(&fake, "5.3.4"),
"message size %lu exceeds size limit %.0f of server %s",
request->data_size, (double) session->size_limit,
session->namaddr);
diff --git a/postfix/src/smtp/smtp_rcpt.c b/postfix/src/smtp/smtp_rcpt.c
index 1b64f6b06..31599464b 100644
--- a/postfix/src/smtp/smtp_rcpt.c
+++ b/postfix/src/smtp/smtp_rcpt.c
@@ -131,7 +131,7 @@ void smtp_rcpt_done(SMTP_STATE *state, SMTP_RESP *resp, RECIPIENT *rcpt)
{
DELIVER_REQUEST *request = state->request;
SMTP_SESSION *session = state->session;
- DSN dsn;
+ DSN_BUF *why = state->why;
int status;
/*
@@ -144,13 +144,12 @@ void smtp_rcpt_done(SMTP_STATE *state, SMTP_RESP *resp, RECIPIENT *rcpt)
if (session->features & SMTP_FEATURE_DSN)
rcpt->dsn_notify &= ~DSN_NOTIFY_SUCCESS;
- (void) SMTP_DSN_ASSIGN(&dsn, session->host, resp->dsn,
- resp->str, resp->str);
- dsn.action = "relayed";
+ dsb_update(why, resp->dsn, "relayed", DSB_MTYPE_DNS, session->host,
+ DSB_DTYPE_SMTP, resp->str, "%s", resp->str);
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id, &request->msg_stats, rcpt,
- session->namaddrport, &dsn);
+ session->namaddrport, DSN_FROM_DSN_BUF(why));
if (status == 0)
if (request->flags & DEL_REQ_FLAG_SUCCESS)
deliver_completed(state->src, rcpt->offset);
diff --git a/postfix/src/smtp/smtp_sasl_glue.c b/postfix/src/smtp/smtp_sasl_glue.c
index b08ed135c..38e78ddcc 100644
--- a/postfix/src/smtp/smtp_sasl_glue.c
+++ b/postfix/src/smtp/smtp_sasl_glue.c
@@ -283,8 +283,9 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
session->sasl_passwd,
&mechanism, session->sasl_reply);
if (result != XSASL_AUTH_OK) {
- dsb_update(why, "4.7.0", DSB_DEF_ACTION, DSB_SKIP_RMTA, DSB_DTYPE_SASL,
- 421, STR(session->sasl_reply),
+ dsb_update(why, "4.7.0", DSB_DEF_ACTION, DSB_SKIP_RMTA,
+ DSB_DTYPE_SASL, STR(session->sasl_reply),
+ "SASL authentication failed; "
"cannot authenticate to server %s: %s",
session->namaddr, STR(session->sasl_reply));
return (-1);
@@ -317,8 +318,8 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
session->sasl_reply);
if (result != XSASL_AUTH_OK) {
dsb_update(why, "4.7.0", DSB_DEF_ACTION, /* Fix 200512 */
- DSB_SKIP_RMTA, DSB_DTYPE_SASL,
- 421, STR(session->sasl_reply),
+ DSB_SKIP_RMTA, DSB_DTYPE_SASL, STR(session->sasl_reply),
+ "SASL authentication failed; "
"cannot authenticate to server %s: %s",
session->namaddr, STR(session->sasl_reply));
return (-1); /* Fix 200512 */
@@ -334,9 +335,11 @@ int smtp_sasl_authenticate(SMTP_SESSION *session, DSN_BUF *why)
* We completed the authentication protocol.
*/
if (resp->code / 100 != 2) {
- smtp_dsn_update(why, session->host, resp->dsn, resp->code, resp->str,
- "SASL authentication failed; server %s said: %s",
- session->namaddr, resp->str);
+ dsb_update(why, resp->dsn, DSB_DEF_ACTION,
+ DSB_MTYPE_DNS, session->host,
+ var_procname, resp->str,
+ "SASL authentication failed; server %s said: %s",
+ session->namaddr, resp->str);
return (0);
}
return (1);
diff --git a/postfix/src/smtp/smtp_sasl_proto.c b/postfix/src/smtp/smtp_sasl_proto.c
index 699f163d2..0799d2c44 100644
--- a/postfix/src/smtp/smtp_sasl_proto.c
+++ b/postfix/src/smtp/smtp_sasl_proto.c
@@ -149,7 +149,7 @@ void smtp_sasl_helo_auth(SMTP_SESSION *session, const char *words)
int smtp_sasl_helo_login(SMTP_STATE *state)
{
SMTP_SESSION *session = state->session;
- DSN_BUF *why;
+ DSN_BUF *why = state->why;
int ret;
/*
@@ -168,16 +168,28 @@ int smtp_sasl_helo_login(SMTP_STATE *state)
* error is unrecoverable from a session point of view - the session will
* not be reused.
*/
- why = dsb_create();
ret = 0;
- smtp_sasl_start(session, VAR_SMTP_SASL_OPTS, var_smtp_sasl_opts);
- if (smtp_sasl_authenticate(session, why) <= 0) {
- vstring_prepend(why->reason, "Authentication failed: ",
- sizeof("Authentication failed: ") - 1);
- ret = smtp_sess_fail(state, why);
+ if (session->sasl_mechanism_list == 0) {
+ dsb_simple(why, "4.7.0", "SASL authentication failed: "
+ "server %s offered no compatible authentication mechanisms for this type of connection security",
+ session->namaddr);
+ ret = smtp_sess_fail(state);
/* Session reuse is disabled. */
+ } else {
+ if (session->tls_context == 0)
+ smtp_sasl_start(session, VAR_SMTP_SASL_OPTS,
+ var_smtp_sasl_opts);
+ else if (session->tls_context->peer_verified == 0)
+ smtp_sasl_start(session, VAR_SMTP_SASL_TLS_OPTS,
+ var_smtp_sasl_tls_opts);
+ else
+ smtp_sasl_start(session, VAR_SMTP_SASL_TLSV_OPTS,
+ var_smtp_sasl_tlsv_opts);
+ if (smtp_sasl_authenticate(session, why) <= 0) {
+ ret = smtp_sess_fail(state);
+ /* Session reuse is disabled. */
+ }
}
- dsb_free(why);
return (ret);
}
diff --git a/postfix/src/smtp/smtp_state.c b/postfix/src/smtp/smtp_state.c
index 9f364b671..b396397a1 100644
--- a/postfix/src/smtp/smtp_state.c
+++ b/postfix/src/smtp/smtp_state.c
@@ -76,7 +76,7 @@ SMTP_STATE *smtp_state_alloc(void)
state->endp_prop = 0;
state->cache_used = 0;
}
- state->dsn_reason = 0;
+ state->why = dsb_create();
/*
* The process name, "smtp" or "lmtp", is also used as the DSN server
@@ -112,8 +112,8 @@ void smtp_state_free(SMTP_STATE *state)
vstring_free(state->endp_prop);
if (state->cache_used)
htable_free(state->cache_used, (void (*) (char *)) 0);
- if (state->dsn_reason)
- vstring_free(state->dsn_reason);
+ if (state->why)
+ dsb_free(state->why);
myfree((char *) state);
}
diff --git a/postfix/src/smtp/smtp_trouble.c b/postfix/src/smtp/smtp_trouble.c
index 4ddef7dcc..761aee970 100644
--- a/postfix/src/smtp/smtp_trouble.c
+++ b/postfix/src/smtp/smtp_trouble.c
@@ -6,9 +6,8 @@
/* SYNOPSIS
/* #include "smtp.h"
/*
-/* int smtp_sess_fail(state, why)
+/* int smtp_sess_fail(state)
/* SMTP_STATE *state;
-/* DSN_BUF *why;
/*
/* int smtp_site_fail(state, mta_name, resp, format, ...)
/* SMTP_STATE *state;
@@ -183,13 +182,14 @@ static void smtp_check_code(SMTP_SESSION *session, int code)
/* smtp_bulk_fail - skip, defer or bounce recipients, maybe throttle queue */
-static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
+static int smtp_bulk_fail(SMTP_STATE *state, int throttle_queue)
{
DELIVER_REQUEST *request = state->request;
SMTP_SESSION *session = state->session;
+ DSN_BUF *why = state->why;
RECIPIENT *rcpt;
int status;
- int soft_error = (dsn->status[0] == '4');
+ int soft_error = (STR(why->status)[0] == '4');
int nrcpt;
/*
@@ -198,7 +198,7 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
* why we're skipping this host.
*/
if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) {
- msg_info("%s: %s", request->queue_id, dsn->reason);
+ msg_info("%s: %s", request->queue_id, STR(why->reason));
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (SMTP_RCPT_ISMARKED(rcpt))
@@ -230,6 +230,7 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
} else
GETTIMEOFDAY(&request->msg_stats.deliver_done);
+ (void) DSN_FROM_DSN_BUF(why);
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (SMTP_RCPT_ISMARKED(rcpt))
@@ -237,14 +238,14 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
&request->msg_stats, rcpt,
- session ? session->namaddrport : "none", dsn);
+ session ? session->namaddrport : "none", &why->dsn);
if (status == 0)
deliver_completed(state->src, rcpt->offset);
SMTP_RCPT_DROP(state, rcpt);
state->status |= status;
}
if (throttle_queue && soft_error && request->hop_status == 0)
- request->hop_status = DSN_COPY(dsn);
+ request->hop_status = DSN_COPY(&why->dsn);
}
/*
@@ -258,57 +259,42 @@ static int smtp_bulk_fail(SMTP_STATE *state, DSN *dsn, int throttle_queue)
/* smtp_sess_fail - skip site, defer or bounce all recipients */
-int smtp_sess_fail(SMTP_STATE *state, DSN_BUF *why)
+int smtp_sess_fail(SMTP_STATE *state)
{
- DSN dsn;
/*
- * We need to incur the expense of copying lots of strings into VSTRING
- * buffers when the error information is collected by a routine that
- * terminates BEFORE the error is reported. If no copies were made, the
- * information would not be frozen in time.
+ * We can't avoid copying copying lots of strings into VSTRING buffers,
+ * because this error information is collected by a routine that
+ * terminates BEFORE the error is reported.
*/
- return (smtp_bulk_fail(state, DSN_FROM_DSN_BUF(&dsn, why), SMTP_THROTTLE));
+ return (smtp_bulk_fail(state, SMTP_THROTTLE));
}
/* vsmtp_fill_dsn - fill in temporary DSN structure */
-static void vsmtp_fill_dsn(SMTP_STATE *state, DSN *dsn, const char *mta_name,
+static void vsmtp_fill_dsn(SMTP_STATE *state, const char *mta_name,
const char *status, const char *reply,
const char *format, va_list ap)
{
+ DSN_BUF *why = state->why;
/*
- * We can avoid the cost of copying lots of strings into VSTRING buffers
- * when the error information is collected by the routine that terminates
- * AFTER the error is reported. In this case, the information is already
- * frozen in time, so we don't need to make copies.
+ * We could avoid copying lots of strings into VSTRING buffers, because
+ * this error information is given to us by a routine that terminates
+ * AFTER the error is reported. However, this results in ugly kludges
+ * when informal text needs to be formatted. So we maintain consistency
+ * with other error reporting in the SMTP client even if we waste a few
+ * cycles.
*/
- if (state->dsn_reason == 0)
- state->dsn_reason = vstring_alloc(100);
- else
- VSTRING_RESET(state->dsn_reason);
- if (mta_name && reply[0] != '4' && reply[0] != '5') {
- vstring_strcpy(state->dsn_reason, "Protocol error: ");
- mta_name = DSN_BY_LOCAL_MTA;
+ VSTRING_RESET(why->reason);
+ if (mta_name && reply && reply[0] != '4' && reply[0] != '5') {
+ vstring_strcpy(why->reason, "Protocol error: ");
status = "5.5.0";
- reply = "501 Protocol error in server reply";
}
- vstring_vsprintf_append(state->dsn_reason, format, ap);
- SMTP_DSN_ASSIGN(dsn, mta_name, status, reply, STR(state->dsn_reason));
-}
-
-/* smtp_fill_dsn - fill in temporary DSN structure */
-
-static void smtp_fill_dsn(SMTP_STATE *state, DSN *dsn, const char *mta_name,
- const char *status, const char *reply,
- const char *format,...)
-{
- va_list ap;
-
- va_start(ap, format);
- vsmtp_fill_dsn(state, dsn, mta_name, status, reply, format, ap);
- va_end(ap);
+ vstring_vsprintf_append(why->reason, format, ap);
+ dsb_formal(why, status, DSB_DEF_ACTION,
+ mta_name ? DSB_MTYPE_DNS : DSB_MTYPE_NONE, mta_name,
+ reply ? DSB_DTYPE_SMTP : DSB_DTYPE_NONE, reply);
}
/* smtp_site_fail - throttle this queue; skip, defer or bounce all recipients */
@@ -316,14 +302,13 @@ static void smtp_fill_dsn(SMTP_STATE *state, DSN *dsn, const char *mta_name,
int smtp_site_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
const char *format,...)
{
- DSN dsn;
va_list ap;
/*
* Initialize.
*/
va_start(ap, format);
- vsmtp_fill_dsn(state, &dsn, mta_name, resp->dsn, resp->str, format, ap);
+ vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap);
va_end(ap);
if (state->session && mta_name)
@@ -332,7 +317,7 @@ int smtp_site_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
/*
* Skip, defer or bounce recipients, and throttle this queue.
*/
- return (smtp_bulk_fail(state, &dsn, SMTP_THROTTLE));
+ return (smtp_bulk_fail(state, SMTP_THROTTLE));
}
/* smtp_mesg_fail - skip, defer or bounce all recipients; no queue throttle */
@@ -341,13 +326,12 @@ int smtp_mesg_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
const char *format,...)
{
va_list ap;
- DSN dsn;
/*
* Initialize.
*/
va_start(ap, format);
- vsmtp_fill_dsn(state, &dsn, mta_name, resp->dsn, resp->str, format, ap);
+ vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap);
va_end(ap);
if (state->session && mta_name)
@@ -356,7 +340,7 @@ int smtp_mesg_fail(SMTP_STATE *state, const char *mta_name, SMTP_RESP *resp,
/*
* Skip, defer or bounce recipients, but don't throttle this queue.
*/
- return (smtp_bulk_fail(state, &dsn, SMTP_NOTHROTTLE));
+ return (smtp_bulk_fail(state, SMTP_NOTHROTTLE));
}
/* smtp_rcpt_fail - skip, defer, or bounce recipient */
@@ -366,7 +350,7 @@ void smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
{
DELIVER_REQUEST *request = state->request;
SMTP_SESSION *session = state->session;
- DSN dsn;
+ DSN_BUF *why = state->why;
int status;
int soft_error;
va_list ap;
@@ -381,9 +365,9 @@ void smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
* Initialize.
*/
va_start(ap, format);
- vsmtp_fill_dsn(state, &dsn, mta_name, resp->dsn, resp->str, format, ap);
+ vsmtp_fill_dsn(state, mta_name, resp->dsn, resp->str, format, ap);
va_end(ap);
- soft_error = dsn.status[0] == '4';
+ soft_error = STR(why->status)[0] == '4';
if (state->session && mta_name)
smtp_check_code(state->session, resp->code);
@@ -394,7 +378,7 @@ void smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
* why we're skipping this recipient now.
*/
if (soft_error && (state->misc_flags & SMTP_MISC_FLAG_FINAL_SERVER) == 0) {
- msg_info("%s: %s", request->queue_id, dsn.reason);
+ msg_info("%s: %s", request->queue_id, STR(why->reason));
SMTP_RCPT_KEEP(state, rcpt);
}
@@ -407,10 +391,11 @@ void smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
* that did qualify for delivery to a backup server.
*/
else {
+ (void) DSN_FROM_DSN_BUF(state->why);
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
&request->msg_stats, rcpt,
- session ? session->namaddrport : "none", &dsn);
+ session ? session->namaddrport : "none", &why->dsn);
if (status == 0)
deliver_completed(state->src, rcpt->offset);
SMTP_RCPT_DROP(state, rcpt);
@@ -423,7 +408,7 @@ void smtp_rcpt_fail(SMTP_STATE *state, RECIPIENT *rcpt, const char *mta_name,
int smtp_stream_except(SMTP_STATE *state, int code, const char *description)
{
SMTP_SESSION *session = state->session;
- DSN dsn;
+ DSN_BUF *why = state->why;
/*
* Sanity check.
@@ -438,23 +423,13 @@ int smtp_stream_except(SMTP_STATE *state, int code, const char *description)
default:
msg_panic("smtp_stream_except: unknown exception %d", code);
case SMTP_ERR_EOF:
- smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
- "4.4.2", "421 lost connection",
- "lost connection with %s while %s",
- session->namaddr, description);
+ dsb_simple(why, "4.4.2", "lost connection with %s while %s",
+ session->namaddr, description);
break;
case SMTP_ERR_TIME:
- smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
- "4.4.2", "426 conversation timed out",
- "conversation with %s timed out while %s",
- session->namaddr, description);
- break;
- case SMTP_ERR_PROTO:
- smtp_fill_dsn(state, &dsn, DSN_BY_LOCAL_MTA,
- "4.5.0", "403 remote protocol error",
- "remote protocol error in reply from %s while %s",
- session->namaddr, description);
+ dsb_simple(why, "4.4.2", "conversation with %s timed out while %s",
+ session->namaddr, description);
break;
}
- return (smtp_bulk_fail(state, &dsn, SMTP_THROTTLE));
+ return (smtp_bulk_fail(state, SMTP_THROTTLE));
}
diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in
index da78675d0..2776c4c91 100644
--- a/postfix/src/smtpd/Makefile.in
+++ b/postfix/src/smtpd/Makefile.in
@@ -215,7 +215,6 @@ smtpd_check.o: ../../include/dict.h
smtpd_check.o: ../../include/dns.h
smtpd_check.o: ../../include/domain_list.h
smtpd_check.o: ../../include/dsn.h
-smtpd_check.o: ../../include/dsn_buf.h
smtpd_check.o: ../../include/dsn_util.h
smtpd_check.o: ../../include/fsspace.h
smtpd_check.o: ../../include/htable.h
diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c
index 9457a1505..664f3ddd8 100644
--- a/postfix/src/smtpd/smtpd.c
+++ b/postfix/src/smtpd/smtpd.c
@@ -40,7 +40,6 @@
/* RFC 1869 (SMTP service extensions)
/* RFC 1870 (Message Size Declaration)
/* RFC 1985 (ETRN command)
-/* RFC 2034 (Enhanced Status Codes)
/* RFC 2554 (AUTH command)
/* RFC 2821 (SMTP protocol)
/* RFC 2920 (SMTP Pipelining)
@@ -98,9 +97,9 @@
/* Available in Postfix version 2.2 and later:
/* .IP "\fBsmtpd_discard_ehlo_keyword_address_maps (empty)\fR"
/* Lookup tables, indexed by the remote SMTP client address, with
-/* case insensitive lists of EHLO keywords (pipelining, starttls,
-/* auth, etc.) that the SMTP server will not send in the EHLO response
-/* to a remote SMTP client.
+/* case insensitive lists of EHLO keywords (pipelining, starttls, auth,
+/* etc.) that the SMTP server will not send in the EHLO response to a
+/* remote SMTP client.
/* .IP "\fBsmtpd_discard_ehlo_keywords (empty)\fR"
/* A case insensitive list of EHLO keywords (pipelining, starttls,
/* auth, etc.) that the SMTP server will not send in the EHLO response
diff --git a/postfix/src/smtpd/smtpd_chat.c b/postfix/src/smtpd/smtpd_chat.c
index 2962b1efb..d91b8131a 100644
--- a/postfix/src/smtpd/smtpd_chat.c
+++ b/postfix/src/smtpd/smtpd_chat.c
@@ -214,13 +214,14 @@ void smtpd_chat_notify(SMTPD_STATE *state)
* generate from untrusted data.
*/
#define NULL_TRACE_FLAGS 0
+#define NO_QUEUE_ID ((VSTRING *) 0)
#define LENGTH 78
#define INDENT 4
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
var_error_rcpt,
CLEANUP_FLAG_MASK_INTERNAL,
- NULL_TRACE_FLAGS);
+ NULL_TRACE_FLAGS, NO_QUEUE_ID);
if (notice == 0) {
msg_warn("postmaster notify: %m");
return;
diff --git a/postfix/src/util/mymalloc.c b/postfix/src/util/mymalloc.c
index 91b4af281..1c8165da7 100644
--- a/postfix/src/util/mymalloc.c
+++ b/postfix/src/util/mymalloc.c
@@ -31,6 +31,12 @@
/* handling. A call of these functions either succeeds or it does
/* not return at all.
/*
+/* To save memory, zero-length strings are shared and read-only.
+/* The caller must not attempt to modify the null terminator.
+/* This code is enabled unless NO_SHARED_EMPTY_STRINGS is
+/* defined at compile time (for example, you have an sscanf()
+/* routine that pushes characters back into its input).
+/*
/* mymalloc() allocates the requested amount of memory. The memory
/* is not set to zero.
/*
@@ -118,6 +124,22 @@ typedef struct MBLOCK {
#define SPACE_FOR(len) (offsetof(MBLOCK, u.payload[0]) + len)
+ /*
+ * Optimization for short strings. We share one copy with multiple callers.
+ * This differs from normal heap memory in two ways, because the memory is
+ * shared:
+ *
+ * - It must be read-only to avoid horrible bugs. This is OK because there is
+ * no legitimate reason to modify the null terminator.
+ *
+ * - myfree() cannot overwrite the memory with a filler pattern like it can do
+ * with heap memory. Therefore, some dangling pointer bugs will be masked.
+ */
+#ifndef NO_SHARED_EMPTY_STRINGS
+static const char empty_string[] = "";
+
+#endif
+
/* mymalloc - allocate memory or bust */
char *mymalloc(ssize_t len)
@@ -141,6 +163,11 @@ char *myrealloc(char *ptr, ssize_t len)
MBLOCK *real_ptr;
ssize_t old_len;
+#ifndef NO_SHARED_EMPTY_STRINGS
+ if (ptr == empty_string)
+ return (mymalloc(len));
+#endif
+
if (len < 1)
msg_panic("myrealloc: requested length %ld", (long) len);
CHECK_IN_PTR(ptr, real_ptr, old_len, "myrealloc");
@@ -159,9 +186,15 @@ void myfree(char *ptr)
MBLOCK *real_ptr;
ssize_t len;
- CHECK_IN_PTR(ptr, real_ptr, len, "myfree");
- memset((char *) real_ptr, FILLER, SPACE_FOR(len));
- free((char *) real_ptr);
+#ifndef NO_SHARED_EMPTY_STRINGS
+ if (ptr != empty_string) {
+#endif
+ CHECK_IN_PTR(ptr, real_ptr, len, "myfree");
+ memset((char *) real_ptr, FILLER, SPACE_FOR(len));
+ free((char *) real_ptr);
+#ifndef NO_SHARED_EMPTY_STRINGS
+ }
+#endif
}
/* mystrdup - save string to heap */
@@ -170,6 +203,10 @@ char *mystrdup(const char *str)
{
if (str == 0)
msg_panic("mystrdup: null pointer argument");
+#ifndef NO_SHARED_EMPTY_STRINGS
+ if (*str == 0)
+ return ((char *) empty_string);
+#endif
return (strcpy(mymalloc(strlen(str) + 1), str));
}
@@ -184,6 +221,10 @@ char *mystrndup(const char *str, ssize_t len)
msg_panic("mystrndup: null pointer argument");
if (len < 0)
msg_panic("mystrndup: requested length %ld", (long) len);
+#ifndef NO_SHARED_EMPTY_STRINGS
+ if (*str == 0)
+ return ((char *) empty_string);
+#endif
if ((cp = memchr(str, 0, len)) != 0)
len = cp - str;
result = memcpy(mymalloc(len + 1), str, len);
diff --git a/postfix/src/util/netstring.c b/postfix/src/util/netstring.c
index 7dfee0a34..54c793321 100644
--- a/postfix/src/util/netstring.c
+++ b/postfix/src/util/netstring.c
@@ -204,6 +204,9 @@ ssize_t netstring_get_length(VSTREAM *stream)
if (!ISDIGIT(ch))
netstring_except(stream, NETSTRING_ERR_FORMAT);
len = len * 10 + ch - '0';
+ /* vstream_fread() would read zero bytes. Reject input anyway. */
+ if (len < 0)
+ netstring_except(stream, NETSTRING_ERR_SIZE);
break;
}
}
diff --git a/postfix/src/util/vstring.c b/postfix/src/util/vstring.c
index c050f6381..df65a69bc 100644
--- a/postfix/src/util/vstring.c
+++ b/postfix/src/util/vstring.c
@@ -491,7 +491,6 @@ char *vstring_memchr(VSTRING *vp, int ch)
VSTRING *vstring_insert(VSTRING *vp, ssize_t start, const char *buf, ssize_t len)
{
- const char *myname = "vstring_insert";
ssize_t new_len;
/*
diff --git a/postfix/src/verify/Makefile.in b/postfix/src/verify/Makefile.in
index 3592ffaa9..b5a1a2884 100644
--- a/postfix/src/verify/Makefile.in
+++ b/postfix/src/verify/Makefile.in
@@ -62,7 +62,6 @@ verify.o: ../../include/deliver_request.h
verify.o: ../../include/dict.h
verify.o: ../../include/dict_ht.h
verify.o: ../../include/dsn.h
-verify.o: ../../include/dsn_buf.h
verify.o: ../../include/htable.h
verify.o: ../../include/iostuff.h
verify.o: ../../include/mail_conf.h
diff --git a/postfix/src/verify/verify.c b/postfix/src/verify/verify.c
index 0ae579b97..ecc0d5f39 100644
--- a/postfix/src/verify/verify.c
+++ b/postfix/src/verify/verify.c
@@ -454,6 +454,7 @@ static void verify_query_service(VSTREAM *client_stream)
"" : var_verify_sender, STR(addr),
CLEANUP_FLAG_MASK_INTERNAL,
DEL_REQ_FLAG_MTA_VRFY,
+ (VSTRING *) 0,
verify_post_mail_action,
(void *) 0);
if (updated != 0 || var_verify_neg_cache != 0) {
diff --git a/postfix/src/virtual/unknown.c b/postfix/src/virtual/unknown.c
index 54208df14..d789a471e 100644
--- a/postfix/src/virtual/unknown.c
+++ b/postfix/src/virtual/unknown.c
@@ -58,8 +58,8 @@ int deliver_unknown(LOCAL_STATE state)
if (msg_verbose)
MSG_LOG_STATE(myname, state);
- dsb_smtp(state.msg_attr.why, "5.1.1", 550, "550 user unknown",
- "unknown user: \"%s\"", state.msg_attr.user);
+ dsb_simple(state.msg_attr.why, "5.1.1",
+ "unknown user: \"%s\"", state.msg_attr.user);
return (bounce_append(BOUNCE_FLAGS(state.request),
BOUNCE_ATTR(state.msg_attr)));
}
diff --git a/postfix/src/virtual/virtual.h b/postfix/src/virtual/virtual.h
index b74936067..75dd6cd2e 100644
--- a/postfix/src/virtual/virtual.h
+++ b/postfix/src/virtual/virtual.h
@@ -76,7 +76,6 @@ typedef struct DELIVER_ATTR {
char *relay; /* relay host */
MSG_STATS msg_stats; /* time profile */
DSN_BUF *why; /* delivery status */
- DSN dsn; /* delivery status */
} DELIVER_ATTR;
extern void deliver_attr_init(DELIVER_ATTR *);
@@ -103,10 +102,10 @@ typedef struct LOCAL_STATE {
#define BOUNCE_ATTR(attr) \
attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
- DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+ DSN_FROM_DSN_BUF(attr.why)
#define SENT_ATTR(attr) \
attr.queue_id, &attr.msg_stats, &attr.rcpt, attr.relay, \
- DSN_FROM_DSN_BUF(&attr.dsn, attr.why)
+ DSN_FROM_DSN_BUF(attr.why)
#define COPY_ATTR(attr) \
attr.sender, attr.rcpt.orig_addr, attr.delivered, attr.fp