]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.10-20250205
authorWietse Z Venema <wietse@porcupine.org>
Wed, 5 Feb 2025 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <ietf-dane@dukhovni.org>
Mon, 10 Feb 2025 04:50:13 +0000 (15:50 +1100)
18 files changed:
postfix/HISTORY
postfix/README_FILES/TLSRPT_README
postfix/conf/master.cf
postfix/html/TLSRPT_README.html
postfix/html/postconf.5.html
postfix/html/smtpd.8.html
postfix/man/man5/postconf.5
postfix/man/man8/smtpd.8
postfix/mantools/postlink
postfix/proto/TLSRPT_README.html
postfix/proto/postconf.proto
postfix/proto/stop
postfix/proto/stop.double-history
postfix/proto/stop.spell-history
postfix/proto/stop.spell-proto-html
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/smtpd/smtpd.c

index 277752d3532fd423712557a8b338bcf364945959..e30ce59ccec1b21cf8bfc47f76ae653a94d13889 100644 (file)
@@ -28918,4 +28918,19 @@ Apologies for any names omitted.
        Debug logging: cleanup/cleanup_api.c. tls/tlsrpt_wrapper.c.
        proto/TLSRPT_README.html.
 
-       Postfix 3.10 code freeze.
+20250204
+
+       Feature: with "smtpd_hide_client_session = yes", the Postfix
+       SMTP server generates a Received: header without client
+       session info (EHLO, hostname, IP address, TLS session
+       details, SASL login details, SMTP protocol details). Files:
+       conf/master.cf, mantools/postlink, proto/postconf.proto,
+       global/mail_params.h, smtpd/smtpd.c.
+
+20250205
+
+       Documentation: updated TLSRPT_README, added postfix-tlspol
+       policy plugin, deprecated the policy_ttl attribute. File:
+       proto/TLSRPT_README.html.
+
+       Postfix 3.10 code freeze.
index 94f011ebea962f403afa6e00e8d18205ef1d4444..fe26e3b04ea71448ec01dbcc37d7b3f890f178d3 100644 (file)
@@ -48,11 +48,12 @@ are collected and processed into daily summary reports.
     TLSRPT report generator produces daily summary reports.
 
 The TLSRPT client library, and the infrastructure to collect, fetch, and report
-TLSRPT information are maintained by sys4 at https://github.com/sys4/libtlsrpt
-and https://github.com/sys4/tlsrpt-reporter, respectively.
+TLSRPT information, are implemented and maintained by sys4 at https://
+github.com/sys4/libtlsrpt and https://github.com/sys4/tlsrpt-reporter,
+respectively.
 
-The Postfix implementation supports both DANE (Postfix built-in) and MTA-STS
-(through an smtp_tls_policy_maps plug-in).
+The Postfix implementation supports domains with DANE (Postfix built-in) and
+MTA-STS (through an smtp_tls_policy_maps plug-in).
 
 The Postfix smtp(8) client process implements the SMTP client engine. With
 "smtp_tls_connection_reuse = no", the smtp(8) client process also implements
@@ -228,19 +229,25 @@ Options:
 M\bMT\bTA\bA-\b-S\bST\bTS\bS S\bSu\bup\bpp\bpo\bor\brt\bt v\bvi\bia\ba s\bsm\bmt\btp\bp_\b_t\btl\bls\bs_\b_p\bpo\bol\bli\bic\bcy\by_\b_m\bma\bap\bps\bs
 
 Postfix supports MTA-STS though an smtp_tls_policy_maps policy plugin, which
-replies with a TLS security level and optional matching requirements. Postfix
-3.10 and later optionally also accept the name=value attributes described
-below. Specify { name = value } when a value may contain whitespace.
+replies with a TLS security level and name=value attributes with certificate
+matching requirements. Postfix 3.10 and later accept additional name=value
+attributes that are needed for TLSRPT.
 
-    Note 1: Postfix 3.10 and later will accept these attributes in an MTA-STS
-    response even if TLSRPT support is disabled (at build time or run time).
-    With TLSRPT support turned off, Postfix will use the ttl and policy_failure
-    attributes, and will ignore the attributes that are used only for TLSRPT.
+Examples of smtp_tls_policy_maps plugins with MTA-STS support are:
 
-    Note 2: It is an error to specify these attributes for a non-STS policy.
+  * postfix-tlspol, supports domains with DANE (using Postfix built-in DANE),
+    and domains with MTA-STS.
 
-The examples in the table apply to the MTA-STS policy example given in RFC 8461
-Section 3.2:
+  * postfix-mta-sts-resolver, supports domains with MTA-STS.
+
+Both plugins can generate the additional name=value attributes that Postfix
+needs for TLSRPT support (as of February 2025). This is enabled by setting a
+tlsrpt boolean in a plugin configuration file. This setting is safe with
+Postfix 3.10 and later, even if Postfix TLSRPT support is disabled (at build
+time or at run time).
+
+The examples in the text below apply to this MTA-STS policy example given in
+RFC 8461 Section 3.2:
 
     version: STSv1
     mode: enforce
@@ -249,7 +256,9 @@ Section 3.2:
     mx: backupmx.example.com
     max_age: 604800
 
-A policy response may contain line breaks.
+The list of supported attributes is given below. Instead of name=value, specify
+{ name = value } when a value may contain whitespace. A policy response may
+contain line breaks.
 
   * policy_type=type
 
@@ -259,45 +268,49 @@ A policy response may contain line breaks.
 
     The domain that the MTA-STS policy applies to.
 
-  * policy_ttl=time
-
-    How long (in seconds) a Postfix SMTP client process will cache the MTA-STS
-    plugin response.
+    Example: policy_domain=example.com
 
   * { policy_string = value }
 
     Specify one policy_string instance for each MTA-STS policy feature,
     enclosed inside "{" and "}" to protect whitespace in attribute values.
 
-    Example:
-
-        { policy_string = version: STSv1 } { policy_string = mode: enforce }
-        ...
+    Example: { policy_string = version: STSv1 } { policy_string = mode: enforce
+    } ...
 
-    This form ignores whitespace after the opening "{", around the "=", and
-    before the closing "}".
+    The above form ignores whitespace after the opening "{", around the "=",
+    and before the closing "}".
 
   * mx_host_pattern=pattern
 
     Specify one mx_host_pattern instance for each "mx:" feature in the MTA-STS
     policy.
 
-    Example:
-
-        mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
+    Example: mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
 
   * policy_failure=type
 
     If specified, forces MTA-STS policy enforcement to fail with the indicated
     error, even if a server certificate would satisfy conventional PKI
-    constraints.
+    constraints. Valid errors are sts-policy-fetch-error, sts-policy-invalid,
+    sts-webpki-invalid, or the less informative validation-failure.
 
-    Valid errors are sts-policy-fetch-error, sts-policy-invalid, sts-webpki-
-    invalid, or the less informative validation-failure.
+    Example: policy_failure=sts-webpki-invalid
+
+  * policy_ttl=time
+
+    This attribute is deprecated. The time value is not used, and support for
+    this attribute will eventually be removed from the code.
+
+Notes:
 
-    Example:
+  * Postfix 3.10 and later will accept these additional attributes in an MTA-
+    STS response even if TLSRPT support is disabled (at build time or at run
+    time). With TLSRPT support turned off, Postfix may still use the
+    policy_failure attribute, and will ignore the attributes that are used only
+    for TLSRPT.
 
-        policy_failure=sts-webpki-invalid
+  * It is an error to specify these attributes for a non-STS policy.
 
 L\bLi\bim\bmi\bit\bta\bat\bti\bio\bon\bns\bs
 
@@ -314,7 +327,7 @@ SMTP protocol engine. It just is not how Postfix works internally.
 
 C\bCr\bre\bed\bdi\bit\bts\bs
 
-  * The TLSRPT client library and report generator are implemented and
-    maintained by sys4.
+  * The TLSRPT client library, and the infrastructure to collect, fetch, and
+    report TLSRPT information, are implemented and maintained by sys4.
   * Wietse Venema implemented the integration with Postfix.
 
index dc038d0d1529f5f3241119f50188af5d3c68ad03..5abe06cbdc0ecf20a182ab185570788c8615e483 100644 (file)
@@ -23,6 +23,7 @@ smtp      inet  n       -       n       -       -       smtpd
 #  -o smtpd_sasl_auth_enable=yes
 #  -o smtpd_tls_auth_only=yes
 #  -o local_header_rewrite_clients=static:all
+#  -o smtpd_hide_client_session=yes
 #  -o smtpd_reject_unlisted_recipient=no
 #     Instead of specifying complex smtpd_<xxx>_restrictions here,
 #     specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
@@ -42,6 +43,7 @@ smtp      inet  n       -       n       -       -       smtpd
 #  -o smtpd_tls_wrappermode=yes
 #  -o smtpd_sasl_auth_enable=yes
 #  -o local_header_rewrite_clients=static:all
+#  -o smtpd_hide_client_session=yes
 #  -o smtpd_reject_unlisted_recipient=no
 #     Instead of specifying complex smtpd_<xxx>_restrictions here,
 #     specify "smtpd_<xxx>_restrictions=$mua_<xxx>_restrictions"
index 95acfb7b770044a4a5920bc05e65827d358cf975..cef622abda045388f78dff61368b30d99aee640d 100644 (file)
@@ -98,12 +98,13 @@ and a central TLSRPT report generator produces daily summary reports.
 </ul>
 
 <p> The TLSRPT client library, and the infrastructure to collect,
-fetch, and report TLSRPT information are maintained by sys4 at
-<a href="https://github.com/sys4/libtlsrpt">https://github.com/sys4/libtlsrpt</a> and
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4 at <a href="https://github.com/sys4/libtlsrpt">https://github.com/sys4/libtlsrpt</a> and
 <a href="https://github.com/sys4/tlsrpt-reporter">https://github.com/sys4/tlsrpt-reporter</a>, respectively. </p>
 
-<p> The Postfix implementation supports both DANE (Postfix built-in)
-and MTA-STS (through an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> plug-in). </p>
+<p> The Postfix implementation supports domains with DANE (Postfix
+built-in) and MTA-STS (through an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> plug-in).
+</p>
 
 <p> The Postfix <a href="smtp.8.html">smtp(8)</a> client process implements the SMTP client
 engine. With "<a href="postconf.5.html#smtp_tls_connection_reuse">smtp_tls_connection_reuse</a> = no", the <a href="smtp.8.html">smtp(8)</a> client
@@ -215,7 +216,7 @@ queue, but it will also log a visible record to the mail logfile.
 <p> Below are a few examples of logging from a Postfix SMTP client
 or tlsproxy daemon: </p>
 
-<blockquote> 
+<blockquote>
 <pre>
 TLSRPT: status=success, domain=example.com, receiving_mx=mail.example.com[ipaddr]
 &nbsp;
@@ -229,7 +230,7 @@ TLSRPT: status=failure, domain=example.net, receiving_mx=mail.example.net[ipaddr
 
 <p> Notes: </p>
 
-<ul> 
+<ul>
 
 <li> <p> Postfix logs and reports the TLSRPT status only for TLS
 handshakes on a new SMTP connection. There is no TLS handshake, and
@@ -332,25 +333,33 @@ generator's sender address): </p>
 </a></h2>
 
 <p> Postfix supports MTA-STS though an <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> policy
-plugin, which replies with a TLS security level and optional matching
-requirements. Postfix 3.10 and later optionally also accept the
-name=value attributes described below. Specify <tt>{ name = value
-}</tt> when a value may contain whitespace. </p>
+plugin, which replies with a TLS security level and name=value
+attributes with certificate matching requirements. Postfix 3.10 and
+later accept additional name=value attributes that are needed for
+TLSRPT. </p>
 
-<blockquote>
+<p> Examples of <a href="postconf.5.html#smtp_tls_policy_maps">smtp_tls_policy_maps</a> plugins with MTA-STS support
+are: </p>
+
+<ul>
 
-<p> Note 1: Postfix 3.10 and later will accept these attributes in
-an MTA-STS response even if TLSRPT support is disabled (at build
-time or run time). With TLSRPT support turned off, Postfix
-will use the <tt>ttl</tt> and <tt>policy_failure</tt> attributes,
-and will ignore the attributes that are used only for TLSRPT. </p>
+<li> <p> <a href="https://github.com/Zuplu/postfix-tlspol">
+postfix-tlspol</a>, supports domains with DANE (using Postfix
+built-in DANE), and domains with MTA-STS. </p>
 
-<p> Note 2: It is an error to specify these attributes for a non-STS
-policy. </p>
+<li> <p> <a href="https://github.com/Snawoot/postfix-mta-sts-resolver">
+postfix-mta-sts-resolver</a>, supports domains with MTA-STS. </p>
 
-</blockquote>
+</ul>
+
+<p> Both plugins can generate the additional name=value attributes
+that Postfix needs for TLSRPT support (as of February 2025). This
+is enabled by setting a <tt>tlsrpt</tt> boolean in a plugin
+configuration file.  This setting is safe with Postfix 3.10 and
+later, even if Postfix TLSRPT support is disabled (at build time
+or at run time). </p>
 
-<p> The examples in the table apply to the MTA-STS policy example
+<p> The examples in the text below apply to this MTA-STS policy example
 given in <a
 href="https://datatracker.ietf.org/doc/html/rfc8461#section-3.2">
 RFC 8461 Section 3.2</a>: </p>
@@ -366,72 +375,77 @@ max_age: 604800
 </pre>
 </blockquote>
 
-<p> A policy response may contain line breaks. </p>
+<p> The list of supported attributes is given below. Instead of
+<tt>name=value</tt>, specify <tt>{ name = value }</tt> when a value
+may contain whitespace. A policy response may contain line breaks.
+</p>
 
 <ul>
 
-<li> <p> <tt> policy_type=<i>type</i> </tt>
+<li> <p> <tt> policy_type=<i>type</i> </tt> </p>
 
 <p> Specify <tt>sts</tt> or <tt>no-policy-found</tt>. </p> </li>
 
 <li> <p> <tt> policy_domain=<i>name</i> </tt> </p>
 
-<p> The domain that the MTA-STS policy applies to. </p> </li>
+<p> The domain that the MTA-STS policy applies to. </p>
 
-<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
 
-<p> How long (in seconds) a Postfix SMTP client process will cache
-the MTA-STS plugin response. </p> </li>
+<p> Example: <tt>policy_domain=example.com</tt> </p>
+
+</li>
 
 <li> <p> <tt> { policy_string = <i>value</i> } </tt> </p>
 
 <p> Specify one <tt>policy_string</tt> instance for each MTA-STS
 policy feature, enclosed inside "{" and "}" to protect whitespace
-in attribute values. </p>
+in attribute values. <p>
 
-<p> Example: </p>
+<p> Example: <tt> { policy_string = version: STSv1 } { policy_string
+= mode: enforce } ...</tt> </p>
 
-<blockquote>
-<pre>
-{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
-</pre> 
-</blockquote> 
-
-<p> This form ignores whitespace after the opening "{", around the "=",
-and before the closing "}".</p> </li>
+<p> The above form ignores whitespace after the opening "{", around
+the "=", and before the closing "}".</p> </li>
 
 <li> <p> <tt> mx_host_pattern=<i>pattern</i> </tt> </p>
 
 <p> Specify one <tt>mx_host_pattern</tt> instance for each "mx:" feature
 in the MTA-STS policy. </p>
 
-<p> Example: </p>
-
-<blockquote>
-<pre>
-mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
-</pre>
-</blockquote>
-</li>
+<p> Example: <tt>mx_host_pattern=mail.example.com
+mx_host_pattern=*.example.net ...</tt> </p> </li>
 
 <li> <p> <tt> policy_failure=<i>type</i> </tt> </p>
 
 <p> If specified, forces MTA-STS policy enforcement to fail with
 the indicated error, even if a server certificate would satisfy
-conventional PKI constraints. </p>
+conventional PKI constraints. Valid errors are <tt>sts-policy-fetch-error,
+sts-policy-invalid</tt>, <tt>sts-webpki-invalid</tt>, or the less
+informative <tt>validation-failure</tt>. </p>
 
-<p> Valid errors are <tt>sts-policy-fetch-error, sts-policy-invalid</tt>,
-<tt>sts-webpki-invalid</tt>, or the less informative
-<tt>validation-failure</tt>. </p>
+<p> Example: <tt>policy_failure=sts-webpki-invalid</tt> </p> </li>
 
-<p> Example: </p>
+<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
 
-<blockquote>
-<pre>
-policy_failure=sts-webpki-invalid
-</pre>
-</blockquote>
-</li>
+<p> This attribute is deprecated. The <i>time</i> value is not used,
+and support for this attribute will eventually be removed from the
+code. </p> </li>
+
+</ul>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> Postfix 3.10 and later will accept these additional
+attributes in an MTA-STS response even if TLSRPT support is disabled
+(at build time or at run time). With TLSRPT support turned off,
+Postfix may still use the <tt>policy_failure</tt>
+attribute, and will ignore the attributes that are used only for
+TLSRPT. </p>
+
+<li> <p> It is an error to specify these attributes for a non-STS
+policy. </p>
 
 </ul>
 
@@ -453,8 +467,9 @@ engine. It just is not how Postfix works internally. </p>
 
 <ul>
 
-<li> The TLSRPT client library and report generator are implemented
-and maintained by sys4. </li>
+<li> The TLSRPT client library, and the infrastructure to collect,
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4. </li>
 
 <li> Wietse Venema implemented the integration with Postfix.
 </li>
index e67cfb18ed0a237a2943a5be0d68bfbcf11dd944..f61e58ed4922a2c0c967325950aa82774b8ccbaa 100644 (file)
@@ -16550,6 +16550,47 @@ Examples:
 </pre>
 
 
+</DD>
+
+<DT><b><a name="smtpd_hide_client_session">smtpd_hide_client_session</a>
+(default: no)</b></DT><DD>
+
+<p> Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header. </p>
+
+<ul>
+
+<li> <p> The default setting, "<a href="postconf.5.html#smtpd_hide_client_session">smtpd_hide_client_session</a> = no",
+must be used for the port 25 MTA service. It provides information
+that is required by <a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a>. </p>
+
+<li> <p> The setting "<a href="postconf.5.html#smtpd_hide_client_session">smtpd_hide_client_session</a> = yes" may be used
+for the port 587 and 465 MUA services. This hides the SMTP client
+hostname and IP address, TLS session details, SASL login details,
+and SMTP protocol details. </p>
+
+</ul>
+
+<p> Depending on the number of recipients, a redacted Received:
+header has one of the following forms: </p>
+
+<blockquote>
+<pre>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+        for &lt;user@example.com&gt;; Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+<br>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+        Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+</pre>
+</blockquote>
+
+<p> The redacted form hides that a message was received with SMTP,
+and therefore it does not need to provide the information required by
+<a href="https://tools.ietf.org/html/rfc5321">RFC 5321</a>. The form does still meet <a href="https://tools.ietf.org/html/rfc5322">RFC 5322</a> requirements. </p>
+
+<p> This feature is available in Postfix &ge; 3.10. </p>
+
+
 </DD>
 
 <DT><b><a name="smtpd_history_flush_threshold">smtpd_history_flush_threshold</a>
index 83776ac55aab0e682b0186a92f9cd42f2d23f79a..47be68d078ac04398cf3bd0fcec6dd2162c58ab1 100644 (file)
@@ -1431,6 +1431,12 @@ SMTPD(8)                                                              SMTPD(8)
               Lookup tables, indexed by the complete Postfix SMTP  server  4xx
               or 5xx response, with reject footer templates.
 
+       Available in Postfix 3.10 and later:
+
+       <b><a href="postconf.5.html#smtpd_hide_client_session">smtpd_hide_client_session</a> (no)</b>
+              Do  not  include  SMTP client session information in the Postfix
+              SMTP server's Received: message header.
+
 <b><a name="see_also">SEE ALSO</a></b>
        <a href="anvil.8.html">anvil(8)</a>, connection/rate limiting
        <a href="cleanup.8.html">cleanup(8)</a>, message canonicalization
index 060983545423e5733d07d2074869b82c00f3a5bf..14cbf01552ad168554ae745f6619996dc5623019 100644 (file)
@@ -11187,6 +11187,40 @@ smtpd_helo_restrictions = permit_mynetworks, reject_invalid_helo_hostname
 smtpd_helo_restrictions = permit_mynetworks, reject_unknown_helo_hostname
 .fi
 .ad
+.SH smtpd_hide_client_session (default: no)
+Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header.
+.IP \(bu
+The default setting, "smtpd_hide_client_session = no",
+must be used for the port 25 MTA service. It provides information
+that is required by RFC 5321.
+.IP \(bu
+The setting "smtpd_hide_client_session = yes" may be used
+for the port 587 and 465 MUA services. This hides the SMTP client
+hostname and IP address, TLS session details, SASL login details,
+and SMTP protocol details.
+.br
+.PP
+Depending on the number of recipients, a redacted Received:
+header has one of the following forms:
+.sp
+.in +4
+.nf
+.na
+Received: by mail.example.com (Postfix) id postfix\-queue\-id
+        for <user@example.com>; Day, dd Mon yyyy hh:mm:ss tz\-offset (zone)
+.br
+Received: by mail.example.com (Postfix) id postfix\-queue\-id
+        Day, dd Mon yyyy hh:mm:ss tz\-offset (zone)
+.fi
+.ad
+.in -4
+.PP
+The redacted form hides that a message was received with SMTP,
+and therefore it does not need to provide the information required by
+RFC 5321. The form does still meet RFC 5322 requirements.
+.PP
+This feature is available in Postfix >= 3.10.
 .SH smtpd_history_flush_threshold (default: 100)
 The maximal number of lines in the Postfix SMTP server command history
 before it is flushed upon receipt of EHLO, RSET, or end of DATA.
index c68e32598da86628e117a3bbe9d3598c33b58bf1..a671d476bbeb97bce3fb30034a2684e37e9e2ee6 100644 (file)
@@ -1232,6 +1232,11 @@ Available in Postfix 3.4 and later:
 .IP "\fBsmtpd_reject_footer_maps (empty)\fR"
 Lookup tables, indexed by the complete Postfix SMTP server 4xx or
 5xx response, with reject footer templates.
+.PP
+Available in Postfix 3.10 and later:
+.IP "\fBsmtpd_hide_client_session (no)\fR"
+Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header.
 .SH "SEE ALSO"
 .na
 .nf
index 2a6558538dc804929b7e7a71191f986f6f10fac3..b06c2d00fc4b17eb2eed6baceee9d794fa4d1f3e 100755 (executable)
@@ -1188,6 +1188,7 @@ while (<>) {
 
     s;\btls_required_enable\b;<a href="postconf.5.html#tls_required_enable">$&</a>;g;
     s;\bfull_name_encoding_charset\b;<a href="postconf.5.html#full_name_encoding_charset">$&</a>;g;
+    s;\bsmtpd_hide_client_session\b;<a href="postconf.5.html#smtpd_hide_client_session">$&</a>;g;
 
     # Service-defined parameters...
 
index 11bdc5510bfb6f3005c8aee750649458fe7e4a41..7468b6fb1aaeac01695c6575b5bca7d50c25078d 100644 (file)
@@ -98,12 +98,13 @@ and a central TLSRPT report generator produces daily summary reports.
 </ul>
 
 <p> The TLSRPT client library, and the infrastructure to collect,
-fetch, and report TLSRPT information are maintained by sys4 at
-https://github.com/sys4/libtlsrpt and
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4 at https://github.com/sys4/libtlsrpt and
 https://github.com/sys4/tlsrpt-reporter, respectively. </p>
 
-<p> The Postfix implementation supports both DANE (Postfix built-in)
-and MTA-STS (through an smtp_tls_policy_maps plug-in). </p>
+<p> The Postfix implementation supports domains with DANE (Postfix
+built-in) and MTA-STS (through an smtp_tls_policy_maps plug-in).
+</p>
 
 <p> The Postfix smtp(8) client process implements the SMTP client
 engine. With "smtp_tls_connection_reuse = no", the smtp(8) client
@@ -215,7 +216,7 @@ queue, but it will also log a visible record to the mail logfile.
 <p> Below are a few examples of logging from a Postfix SMTP client
 or tlsproxy daemon: </p>
 
-<blockquote> 
+<blockquote>
 <pre>
 TLSRPT: status=success, domain=example.com, receiving_mx=mail.example.com[ipaddr]
 &nbsp;
@@ -229,7 +230,7 @@ TLSRPT: status=failure, domain=example.net, receiving_mx=mail.example.net[ipaddr
 
 <p> Notes: </p>
 
-<ul> 
+<ul>
 
 <li> <p> Postfix logs and reports the TLSRPT status only for TLS
 handshakes on a new SMTP connection. There is no TLS handshake, and
@@ -332,25 +333,33 @@ generator's sender address): </p>
 </a></h2>
 
 <p> Postfix supports MTA-STS though an smtp_tls_policy_maps policy
-plugin, which replies with a TLS security level and optional matching
-requirements. Postfix 3.10 and later optionally also accept the
-name=value attributes described below. Specify <tt>{ name = value
-}</tt> when a value may contain whitespace. </p>
+plugin, which replies with a TLS security level and name=value
+attributes with certificate matching requirements. Postfix 3.10 and
+later accept additional name=value attributes that are needed for
+TLSRPT. </p>
 
-<blockquote>
+<p> Examples of smtp_tls_policy_maps plugins with MTA-STS support
+are: </p>
+
+<ul>
 
-<p> Note 1: Postfix 3.10 and later will accept these attributes in
-an MTA-STS response even if TLSRPT support is disabled (at build
-time or run time). With TLSRPT support turned off, Postfix
-will use the <tt>ttl</tt> and <tt>policy_failure</tt> attributes,
-and will ignore the attributes that are used only for TLSRPT. </p>
+<li> <p> <a href="https://github.com/Zuplu/postfix-tlspol">
+postfix-tlspol</a>, supports domains with DANE (using Postfix
+built-in DANE), and domains with MTA-STS. </p>
 
-<p> Note 2: It is an error to specify these attributes for a non-STS
-policy. </p>
+<li> <p> <a href="https://github.com/Snawoot/postfix-mta-sts-resolver">
+postfix-mta-sts-resolver</a>, supports domains with MTA-STS. </p>
 
-</blockquote>
+</ul>
+
+<p> Both plugins can generate the additional name=value attributes
+that Postfix needs for TLSRPT support (as of February 2025). This
+is enabled by setting a <tt>tlsrpt</tt> boolean in a plugin
+configuration file.  This setting is safe with Postfix 3.10 and
+later, even if Postfix TLSRPT support is disabled (at build time
+or at run time). </p>
 
-<p> The examples in the table apply to the MTA-STS policy example
+<p> The examples in the text below apply to this MTA-STS policy example
 given in <a
 href="https://datatracker.ietf.org/doc/html/rfc8461#section-3.2">
 RFC 8461 Section 3.2</a>: </p>
@@ -366,72 +375,77 @@ max_age: 604800
 </pre>
 </blockquote>
 
-<p> A policy response may contain line breaks. </p>
+<p> The list of supported attributes is given below. Instead of
+<tt>name=value</tt>, specify <tt>{ name = value }</tt> when a value
+may contain whitespace. A policy response may contain line breaks.
+</p>
 
 <ul>
 
-<li> <p> <tt> policy_type=<i>type</i> </tt>
+<li> <p> <tt> policy_type=<i>type</i> </tt> </p>
 
 <p> Specify <tt>sts</tt> or <tt>no-policy-found</tt>. </p> </li>
 
 <li> <p> <tt> policy_domain=<i>name</i> </tt> </p>
 
-<p> The domain that the MTA-STS policy applies to. </p> </li>
+<p> The domain that the MTA-STS policy applies to. </p>
 
-<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
 
-<p> How long (in seconds) a Postfix SMTP client process will cache
-the MTA-STS plugin response. </p> </li>
+<p> Example: <tt>policy_domain=example.com</tt> </p>
+
+</li>
 
 <li> <p> <tt> { policy_string = <i>value</i> } </tt> </p>
 
 <p> Specify one <tt>policy_string</tt> instance for each MTA-STS
 policy feature, enclosed inside "{" and "}" to protect whitespace
-in attribute values. </p>
+in attribute values. <p>
 
-<p> Example: </p>
+<p> Example: <tt> { policy_string = version: STSv1 } { policy_string
+= mode: enforce } ...</tt> </p>
 
-<blockquote>
-<pre>
-{ policy_string = version: STSv1 } { policy_string = mode: enforce } ...
-</pre> 
-</blockquote> 
-
-<p> This form ignores whitespace after the opening "{", around the "=",
-and before the closing "}".</p> </li>
+<p> The above form ignores whitespace after the opening "{", around
+the "=", and before the closing "}".</p> </li>
 
 <li> <p> <tt> mx_host_pattern=<i>pattern</i> </tt> </p>
 
 <p> Specify one <tt>mx_host_pattern</tt> instance for each "mx:" feature
 in the MTA-STS policy. </p>
 
-<p> Example: </p>
-
-<blockquote>
-<pre>
-mx_host_pattern=mail.example.com mx_host_pattern=*.example.net ...
-</pre>
-</blockquote>
-</li>
+<p> Example: <tt>mx_host_pattern=mail.example.com
+mx_host_pattern=*.example.net ...</tt> </p> </li>
 
 <li> <p> <tt> policy_failure=<i>type</i> </tt> </p>
 
 <p> If specified, forces MTA-STS policy enforcement to fail with
 the indicated error, even if a server certificate would satisfy
-conventional PKI constraints. </p>
+conventional PKI constraints. Valid errors are <tt>sts-policy-fetch-error,
+sts-policy-invalid</tt>, <tt>sts-webpki-invalid</tt>, or the less
+informative <tt>validation-failure</tt>. </p>
 
-<p> Valid errors are <tt>sts-policy-fetch-error, sts-policy-invalid</tt>,
-<tt>sts-webpki-invalid</tt>, or the less informative
-<tt>validation-failure</tt>. </p>
+<p> Example: <tt>policy_failure=sts-webpki-invalid</tt> </p> </li>
 
-<p> Example: </p>
+<li> <p> <tt> policy_ttl=<i>time</i> </tt> </p>
 
-<blockquote>
-<pre>
-policy_failure=sts-webpki-invalid
-</pre>
-</blockquote>
-</li>
+<p> This attribute is deprecated. The <i>time</i> value is not used,
+and support for this attribute will eventually be removed from the
+code. </p> </li>
+
+</ul>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> Postfix 3.10 and later will accept these additional
+attributes in an MTA-STS response even if TLSRPT support is disabled
+(at build time or at run time). With TLSRPT support turned off,
+Postfix may still use the <tt>policy_failure</tt>
+attribute, and will ignore the attributes that are used only for
+TLSRPT. </p>
+
+<li> <p> It is an error to specify these attributes for a non-STS
+policy. </p>
 
 </ul>
 
@@ -453,8 +467,9 @@ engine. It just is not how Postfix works internally. </p>
 
 <ul>
 
-<li> The TLSRPT client library and report generator are implemented
-and maintained by sys4. </li>
+<li> The TLSRPT client library, and the infrastructure to collect,
+fetch, and report TLSRPT information, are implemented and maintained
+by sys4. </li>
 
 <li> Wietse Venema implemented the integration with Postfix.
 </li>
index abb6063683e2c27388bb790639c30f4b4c96464d..25eef4da90ae29a5c13604811f807face3e4d971 100644 (file)
@@ -19486,3 +19486,40 @@ will add that header to a delivery status notification for that
 message. </p>
 
 <p> This feature is available in Postfix &ge; 3.10. </p>
+
+%PARAM smtpd_hide_client_session no
+
+<p> Do not include SMTP client session information in the Postfix
+SMTP server's Received: message header. </p>
+
+<ul>
+
+<li> <p> The default setting, "smtpd_hide_client_session = no",
+must be used for the port 25 MTA service. It provides information
+that is required by RFC 5321. </p>
+
+<li> <p> The setting "smtpd_hide_client_session = yes" may be used
+for the port 587 and 465 MUA services. This hides the SMTP client
+hostname and IP address, TLS session details, SASL login details,
+and SMTP protocol details. </p>
+
+</ul>
+
+<p> Depending on the number of recipients, a redacted Received:
+header has one of the following forms: </p>
+
+<blockquote>
+<pre>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+        for &lt;user@example.com&gt;; Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+<br>
+Received: by mail.example.com (Postfix) id postfix-queue-id
+        Day, dd Mon yyyy hh:mm:ss tz-offset (zone)
+</pre>
+</blockquote>
+
+<p> The redacted form hides that a message was received with SMTP,
+and therefore it does not need to provide the information required by
+RFC 5321. The form does still meet RFC 5322 requirements. </p>
+
+<p> This feature is available in Postfix &ge; 3.10. </p>
index c1a080d876e95d338e3bfab7a1863c5c95dea05f..a8b5522a5bfab7c446e6f5a85b2356627d371d06 100644 (file)
@@ -1664,3 +1664,4 @@ REQUIRETLS
 RequireTLS
 requiretls
 sendopts
+tz
index 15d98a3c366c3145018d5cd2aebadbc7572f652c..870135f2b7a97f701c42703945e093da53b5365e 100644 (file)
@@ -160,3 +160,7 @@ proto  proto socketmap_table
  smtp smtp_proto c smtpd smtpd c verify verify c 
  operations Files cleanup cleanup h cleanup cleanup_message c 
  proto postconf proto pipe pipe c 
+ bounce bounce c bounce bounce_notify_util c cleanup cleanup c 
+ cleanup cleanup_message c smtp smtp c smtp smtp_connect c 
+ Documentation edited for clarity Files pipe pipe c 
+ global mail_params h smtpd smtpd c 
index 74e0858b7c4920bcb3758d4da1da5417c6169a35..d358e3614aa822cd97bede0df8e43b1329096d36 100644 (file)
@@ -99,3 +99,4 @@ CLOSEFROM
 Roessner
 bitflags
 Schulze
+tlspol
index 1a487be5fe24ec5a332cdda2b11c1e936347e9fa..b5bd4adf344f902fd53feed6f0718d17a4df86bf 100644 (file)
@@ -397,3 +397,6 @@ dtd
 marc
 LP
 collectd
+Snawoot
+Zuplu
+tlspol
index 8b54490f52c63075e5e41e63ba7f8457db110169..aa2f294bf2354d098c84ad99dd6a36bd15a9e1ff 100644 (file)
@@ -4502,6 +4502,13 @@ extern char *var_full_name_encoding_charset;
 #define DEF_SOCKMAP_MAX_REPLY  100000  /* reply size limit */
 extern int var_sockmap_max_reply;
 
+ /*
+  * Client privacy.
+  */
+#define VAR_SMTPD_HIDE_CLIENT_SESSION  "smtpd_hide_client_session"
+#define DEF_SMTPD_HIDE_CLIENT_SESSION  "no"
+extern int var_smtpd_hide_client_session;
+
 /* LICENSE
 /* .ad
 /* .fi
index 825bcae3d2439b2238f3ccd53110da9396a089cd..27e83993c12529d0659fd48f4823bfc07ccf8079 100644 (file)
@@ -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      "20250202"
+#define MAIL_RELEASE_DATE      "20250205"
 #define MAIL_VERSION_NUMBER    "3.10"
 
 #ifdef SNAPSHOT
index 962b361c7b2838a0feab53366e67242ef5921781..9c11b18ca0b7fc529d7c35005449ef7a4dfb87df 100644 (file)
 /* .IP "\fBsmtpd_reject_footer_maps (empty)\fR"
 /*     Lookup tables, indexed by the complete Postfix SMTP server 4xx or
 /*     5xx response, with reject footer templates.
+/* .PP
+/*     Available in Postfix 3.10 and later:
+/* .IP "\fBsmtpd_hide_client_session (no)\fR"
+/*     Do not include SMTP client session information in the Postfix
+/*     SMTP server's Received: message header.
 /* SEE ALSO
 /*     anvil(8), connection/rate limiting
 /*     cleanup(8), message canonicalization
@@ -1558,6 +1563,7 @@ char   *var_smtpd_forbid_bare_lf_excl;
 int     var_smtpd_forbid_bare_lf_code;
 static int bare_lf_mask;
 static NAMADR_LIST *bare_lf_excl;
+bool    var_smtpd_hide_client_session;
 
  /*
   * Silly little macros.
@@ -3434,10 +3440,13 @@ static void common_pre_message_handling(SMTPD_STATE *state,
 {
     SMTPD_PROXY *proxy = state->proxy;
     char  **cpp;
-    const char *rfc3848_sess;
-    const char *rfc3848_auth;
+    const char *rfc3848_sess = "";
+    const char *rfc3848_auth = "";
+    const char *with_verb = " with ";
     const char *with_protocol = (state->flags & SMTPD_FLAG_SMTPUTF8) ?
     "UTF8SMTP" : state->protocol;
+    const char *id_verb = state->cleanup ? " id " : "";
+    const char *id_value = state->cleanup ? state->queue_id : "";
 
 #ifdef USE_TLS
     VSTRING *peer_CN;
@@ -3483,152 +3492,153 @@ static void common_pre_message_handling(SMTPD_STATE *state,
      * intermediate proxy.
      */
     if (!proxy || state->xforward.flags == 0) {
-       out_fprintf(out_stream, REC_TYPE_NORM,
-                   "Received: from %s (%s [%s])",
-                   state->helo_name ? state->helo_name : state->name,
-                   state->name, state->rfc_addr);
+       if (!var_smtpd_hide_client_session) {
+           out_fprintf(out_stream, REC_TYPE_NORM,
+                       "Received: from %s (%s [%s])",
+                       state->helo_name ? state->helo_name : state->name,
+                       state->name, state->rfc_addr);
 
 #define VSTRING_STRDUP(s) vstring_strcpy(vstring_alloc(strlen(s) + 1), (s))
 
 #ifdef USE_TLS
-       if (var_smtpd_tls_received_header && state->tls_context) {
-           int     cont = 0;
-
-           vstring_sprintf(state->buffer,
-                           "\t(using %s with cipher %s (%d/%d bits)",
-                           state->tls_context->protocol,
-                           state->tls_context->cipher_name,
-                           state->tls_context->cipher_usebits,
-                           state->tls_context->cipher_algbits);
-           if (state->tls_context->kex_name && *state->tls_context->kex_name) {
-               out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
-                          LEN(state->buffer));
-               vstring_sprintf(state->buffer, "\t key-exchange %s",
-                               state->tls_context->kex_name);
-               if (state->tls_context->kex_curve
-                   && *state->tls_context->kex_curve)
-                   vstring_sprintf_append(state->buffer, " (%s)",
-                                          state->tls_context->kex_curve);
-               else if (state->tls_context->kex_bits > 0)
-                   vstring_sprintf_append(state->buffer, " (%d bits)",
-                                          state->tls_context->kex_bits);
-               cont = 1;
-           }
-           if (state->tls_context->srvr_sig_name
-               && *state->tls_context->srvr_sig_name) {
-               if (cont) {
-                   vstring_sprintf_append(state->buffer, " server-signature %s",
-                                        state->tls_context->srvr_sig_name);
-               } else {
+           if (var_smtpd_tls_received_header && state->tls_context) {
+               int     cont = 0;
+
+               vstring_sprintf(state->buffer,
+                               "\t(using %s with cipher %s (%d/%d bits)",
+                               state->tls_context->protocol,
+                               state->tls_context->cipher_name,
+                               state->tls_context->cipher_usebits,
+                               state->tls_context->cipher_algbits);
+               if (state->tls_context->kex_name && *state->tls_context->kex_name) {
                    out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
                               LEN(state->buffer));
-                   vstring_sprintf(state->buffer, "\t server-signature %s",
-                                   state->tls_context->srvr_sig_name);
+                   vstring_sprintf(state->buffer, "\t key-exchange %s",
+                                   state->tls_context->kex_name);
+                   if (state->tls_context->kex_curve
+                       && *state->tls_context->kex_curve)
+                       vstring_sprintf_append(state->buffer, " (%s)",
+                                            state->tls_context->kex_curve);
+                   else if (state->tls_context->kex_bits > 0)
+                       vstring_sprintf_append(state->buffer, " (%d bits)",
+                                              state->tls_context->kex_bits);
+                   cont = 1;
                }
-               if (state->tls_context->srvr_sig_curve
-                   && *state->tls_context->srvr_sig_curve)
-                   vstring_sprintf_append(state->buffer, " (%s%s)",
+               if (state->tls_context->srvr_sig_name
+                   && *state->tls_context->srvr_sig_name) {
+                   if (cont) {
+                       vstring_sprintf_append(state->buffer, " server-signature %s",
+                                        state->tls_context->srvr_sig_name);
+                   } else {
+                       out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
+                                  LEN(state->buffer));
+                       vstring_sprintf(state->buffer, "\t server-signature %s",
+                                       state->tls_context->srvr_sig_name);
+                   }
+                   if (state->tls_context->srvr_sig_curve
+                       && *state->tls_context->srvr_sig_curve)
+                       vstring_sprintf_append(state->buffer, " (%s%s)",
                                         state->tls_context->srvr_sig_curve,
-                                          state->tls_context->stoc_rpk ?
-                                          " raw public key" : "");
-               else if (state->tls_context->srvr_sig_bits > 0)
-                   vstring_sprintf_append(state->buffer, " (%d bit%s)",
-                                          state->tls_context->srvr_sig_bits,
-                                          state->tls_context->stoc_rpk ?
-                                          " raw public key" : "s");
-               if (state->tls_context->srvr_sig_dgst
-                   && *state->tls_context->srvr_sig_dgst)
-                   vstring_sprintf_append(state->buffer, " server-digest %s",
+                                              state->tls_context->stoc_rpk ?
+                                              " raw public key" : "");
+                   else if (state->tls_context->srvr_sig_bits > 0)
+                       vstring_sprintf_append(state->buffer, " (%d bit%s)",
+                                         state->tls_context->srvr_sig_bits,
+                                              state->tls_context->stoc_rpk ?
+                                              " raw public key" : "s");
+                   if (state->tls_context->srvr_sig_dgst
+                       && *state->tls_context->srvr_sig_dgst)
+                       vstring_sprintf_append(state->buffer, " server-digest %s",
                                         state->tls_context->srvr_sig_dgst);
-           }
-           if (state->tls_context->clnt_sig_name
-               && *state->tls_context->clnt_sig_name) {
-               out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
-                          LEN(state->buffer));
-               vstring_sprintf(state->buffer, "\t client-signature %s",
-                               state->tls_context->clnt_sig_name);
-               if (state->tls_context->clnt_sig_curve
-                   && *state->tls_context->clnt_sig_curve)
-                   vstring_sprintf_append(state->buffer, " (%s%s)",
+               }
+               if (state->tls_context->clnt_sig_name
+                   && *state->tls_context->clnt_sig_name) {
+                   out_record(out_stream, REC_TYPE_NORM, STR(state->buffer),
+                              LEN(state->buffer));
+                   vstring_sprintf(state->buffer, "\t client-signature %s",
+                                   state->tls_context->clnt_sig_name);
+                   if (state->tls_context->clnt_sig_curve
+                       && *state->tls_context->clnt_sig_curve)
+                       vstring_sprintf_append(state->buffer, " (%s%s)",
                                         state->tls_context->clnt_sig_curve,
-                                          state->tls_context->ctos_rpk ?
-                                          " raw public key" : "");
-               else if (state->tls_context->clnt_sig_bits > 0)
-                   vstring_sprintf_append(state->buffer, " (%d bit%s)",
-                                          state->tls_context->clnt_sig_bits,
-                                          state->tls_context->ctos_rpk ?
-                                          " raw public key" : "s");
-               if (state->tls_context->clnt_sig_dgst
-                   && *state->tls_context->clnt_sig_dgst)
-                   vstring_sprintf_append(state->buffer, " client-digest %s",
+                                              state->tls_context->ctos_rpk ?
+                                              " raw public key" : "");
+                   else if (state->tls_context->clnt_sig_bits > 0)
+                       vstring_sprintf_append(state->buffer, " (%d bit%s)",
+                                         state->tls_context->clnt_sig_bits,
+                                              state->tls_context->ctos_rpk ?
+                                              " raw public key" : "s");
+                   if (state->tls_context->clnt_sig_dgst
+                       && *state->tls_context->clnt_sig_dgst)
+                       vstring_sprintf_append(state->buffer, " client-digest %s",
                                         state->tls_context->clnt_sig_dgst);
-           }
-           out_fprintf(out_stream, REC_TYPE_NORM, "%s)", STR(state->buffer));
-           if (TLS_CERT_IS_PRESENT(state->tls_context)) {
-               peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN);
-               comment_sanitize(peer_CN);
-               issuer_CN = VSTRING_STRDUP(state->tls_context->issuer_CN ?
+               }
+               out_fprintf(out_stream, REC_TYPE_NORM, "%s)", STR(state->buffer));
+               if (TLS_CERT_IS_PRESENT(state->tls_context)) {
+                   peer_CN = VSTRING_STRDUP(state->tls_context->peer_CN);
+                   comment_sanitize(peer_CN);
+                   issuer_CN = VSTRING_STRDUP(state->tls_context->issuer_CN ?
                                        state->tls_context->issuer_CN : "");
-               comment_sanitize(issuer_CN);
-               out_fprintf(out_stream, REC_TYPE_NORM,
-                           "\t(Client CN \"%s\", Issuer \"%s\" (%s))",
-                           STR(peer_CN), STR(issuer_CN),
-                           TLS_CERT_IS_TRUSTED(state->tls_context) ?
-                           "verified OK" : "not verified");
-               vstring_free(issuer_CN);
-               vstring_free(peer_CN);
-           } else if (TLS_RPK_IS_PRESENT(state->tls_context)) {
-               out_fprintf(out_stream, REC_TYPE_NORM,
-                           "\t(Client RPK %s digest %s)",
-                           var_smtpd_tls_fpt_dgst,
-                           state->tls_context->peer_pkey_fprint);
-           } else if (var_smtpd_tls_ask_ccert)
-               out_fprintf(out_stream, REC_TYPE_NORM,
-                           "\t(Client did not present a certificate)");
-           else
-               out_fprintf(out_stream, REC_TYPE_NORM,
-                           "\t(No client certificate requested)");
-       }
-       /* RFC 3848 is defined for ESMTP only. */
-       if (state->tls_context != 0
-           && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
-           rfc3848_sess = "S";
-       else
+                   comment_sanitize(issuer_CN);
+                   out_fprintf(out_stream, REC_TYPE_NORM,
+                               "\t(Client CN \"%s\", Issuer \"%s\" (%s))",
+                               STR(peer_CN), STR(issuer_CN),
+                               TLS_CERT_IS_TRUSTED(state->tls_context) ?
+                               "verified OK" : "not verified");
+                   vstring_free(issuer_CN);
+                   vstring_free(peer_CN);
+               } else if (TLS_RPK_IS_PRESENT(state->tls_context)) {
+                   out_fprintf(out_stream, REC_TYPE_NORM,
+                               "\t(Client RPK %s digest %s)",
+                               var_smtpd_tls_fpt_dgst,
+                               state->tls_context->peer_pkey_fprint);
+               } else if (var_smtpd_tls_ask_ccert)
+                   out_fprintf(out_stream, REC_TYPE_NORM,
+                               "\t(Client did not present a certificate)");
+               else
+                   out_fprintf(out_stream, REC_TYPE_NORM,
+                               "\t(No client certificate requested)");
+           }
+           /* RFC 3848 is defined for ESMTP only. */
+           if (state->tls_context != 0
+               && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
+               rfc3848_sess = "S";
 #endif
-           rfc3848_sess = "";
 #ifdef USE_SASL_AUTH
-       if (var_smtpd_sasl_auth_hdr && state->sasl_username) {
-           username = VSTRING_STRDUP(state->sasl_username);
-           comment_sanitize(username);
-           out_fprintf(out_stream, REC_TYPE_NORM,
-                       "\t(Authenticated sender: %s)", STR(username));
-           vstring_free(username);
-       }
-       /* RFC 3848 is defined for ESMTP only. */
-       if (state->sasl_username
-           && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
-           rfc3848_auth = "A";
-       else
+           if (var_smtpd_sasl_auth_hdr && state->sasl_username) {
+               username = VSTRING_STRDUP(state->sasl_username);
+               comment_sanitize(username);
+               out_fprintf(out_stream, REC_TYPE_NORM,
+                           "\t(Authenticated sender: %s)", STR(username));
+               vstring_free(username);
+           }
+           /* RFC 3848 is defined for ESMTP only. */
+           if (state->sasl_username
+               && strcmp(state->protocol, MAIL_PROTO_ESMTP) == 0)
+               rfc3848_auth = "A";
 #endif
-           rfc3848_auth = "";
+       } else {
+           with_verb = "";
+           with_protocol = "";
+       }
        if (state->rcpt_count == 1 && state->recipient) {
            out_fprintf(out_stream, REC_TYPE_NORM,
-                       state->cleanup ? "\tby %s (%s) with %s%s%s id %s" :
-                       "\tby %s (%s) with %s%s%s",
+                       "%sby %s (%s)%s%s%s%s%s%s",
+                       var_smtpd_hide_client_session ? "Received: " : "\t",
                        var_myhostname, var_mail_name,
-                       with_protocol, rfc3848_sess,
-                       rfc3848_auth, state->queue_id);
+                       with_verb, with_protocol, rfc3848_sess,
+                       rfc3848_auth, id_verb, id_value);
            quote_822_local(state->buffer, state->recipient);
            out_fprintf(out_stream, REC_TYPE_NORM,
                        "\tfor <%s>; %s", STR(state->buffer),
                        mail_date(state->arrival_time.tv_sec));
        } else {
            out_fprintf(out_stream, REC_TYPE_NORM,
-                       state->cleanup ? "\tby %s (%s) with %s%s%s id %s;" :
-                       "\tby %s (%s) with %s%s%s;",
+                       "%sby %s (%s)%s%s%s%s%s%s;",
+                       var_smtpd_hide_client_session ? "Received: " : "\t",
                        var_myhostname, var_mail_name,
-                       with_protocol, rfc3848_sess,
-                       rfc3848_auth, state->queue_id);
+                       with_verb, with_protocol, rfc3848_sess,
+                       rfc3848_auth, id_verb, id_value);
            out_fprintf(out_stream, REC_TYPE_NORM,
                        "\t%s", mail_date(state->arrival_time.tv_sec));
        }
@@ -6790,6 +6800,7 @@ int     main(int argc, char **argv)
     static const CONFIG_NBOOL_TABLE nbool_table[] = {
        VAR_RELAY_BEFORE_RCPT_CHECKS, DEF_RELAY_BEFORE_RCPT_CHECKS, &var_relay_before_rcpt_checks,
        VAR_SMTPD_REQ_DEADLINE, DEF_SMTPD_REQ_DEADLINE, &var_smtpd_req_deadline,
+       VAR_SMTPD_HIDE_CLIENT_SESSION, DEF_SMTPD_HIDE_CLIENT_SESSION, &var_smtpd_hide_client_session,
        0,
     };
     static const CONFIG_STR_TABLE str_table[] = {