-TSMTP_RESP
-TSMTP_SESSION
-TSMTP_STATE
+-TSM_STATE
-TSOCKADDR_SIZE
-TSPAWN_ATTR
-TSTRING_LIST
client sockets. This puts less strain on local system
resources.
-10030415
+20030415
Cleanup: the file system clock drift detection code now
runs only for incoming mail. File: global/mail_stream.c.
+20030416
+
+ Bugfix: missing output flush when message content did not
+ end in newline while converting 8-bit to 7-bit mail. File:
+ smtp/smtp_proto.c.
+
+ Cleanup: auto-bcc recipients are now added in one place
+ (the cleanup server) instead of by individual front-end
+ servers (pickup, smtpd, qmqpd). This makes it easier to
+ add auto-bcc features that trigger on sender or recipient
+ addresses.
+
+ Cleanup: "sendmail -t" (recipients from headers) is now
+ implemented by the sendmail command instead of by the
+ cleanup server. This means that the extract_recipient_limit
+ configuration parameter is no longer needed. Files:
+ sendmail/sendmail.c, cleanup/cleanup_message.c,
+ cleanup/cleanup_extracted.c.
+
+ Compatibility: "sendmail -t" (recipients from headers) now
+ accepts command-line recipients instead of complaining.
+ The extracted header recipients are added to the command-line
+ recipients.
+
+ Feature: sender/recipient_bcc_maps. These are indexed by
+ sender/recipient address and are examined when mail enters
+ from outside of Postfix. Files: cleanup/cleanup_addr.c.
+ cleanup/cleanup_envelope.c cleanup/cleanup_extracted.c.
+
Open problems:
Low: smtp-source may block when sending large test messages.
date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release.
-Incompatible changes with Postfix snapshot 2.0.8-20040414
+Incompatible changes with Postfix snapshot 2.0.8-2004XXXX
+=========================================================
+
+"sendmail -t" no longer complains when recipients are given on the
+command line. Instead, it now adds recipients from headers to the
+command-line recipients.
+
+Major changes with Postfix snapshot 2.0.8-2004XXXX
+==================================================
+
+sender_bcc_maps and recipient_bcc_maps, after a reorganization
+of how auto-bcc recipients are added.
+
+Incompatible changes with Postfix snapshot 2.0.8-20040415
=========================================================
Too many people mess up their net/mask patterns, causing open
168.100.189.2/28), and suggest to specify the proper net/mask
pattern instead (for example, 168.100.189.0/28).
-Major changes with Postfix snapshot 2.0.8-20040414
+Major changes with Postfix snapshot 2.0.8-20040415
==================================================
PostgreSQL table lookups. Specify "pgsql:/file/name" where "/file/name"
#propagate_unmatched_extensions = canonical, virtual, alias, forward, include
#propagate_unmatched_extensions = canonical, virtual
+# The recipient_bcc_maps parameter specifies optional lookup tables
+# with automatic BCC recipients per recipient address. Each table
+# entry should contain exactly one recipient address. The BCC address
+# is added when mail enters from outside of Postfix.
+#
+# By default, this feature is disabled.
+#
+# Specify the types and names of databases to use. After change,
+# run "postmap /etc/postfix/relocated", then "postfix reload".
+#
+#recipient_bcc_maps = hash:/etc/postfix/recipient_bcc
+recipient_bcc_maps =
+
# The relayhost parameter specifies the default host to send mail to
# when no entry is matched in the optional transport(5) table. When
# no relayhost is given, mail is routed directly to the destination.
#
resolve_dequoted_address = no
+# The sender_bcc_maps parameter specifies optional lookup tables with
+# automatic BCC recipients per sender address. Each table entry
+# should contain exactly one recipient address. The BCC address is
+# added when mail enters from outside of Postfix.
+#
+# By default, this feature is disabled.
+#
+# Specify the types and names of databases to use. After change,
+# run "postmap /etc/postfix/relocated", then "postfix reload".
+#
+#sender_bcc_maps = hash:/etc/postfix/sender_bcc
+sender_bcc_maps =
+
# The syslog_facility parameter controls where Postfix logging is
# sent by the syslog daemon. Specify a logging facility as defined
# in syslog.conf(5). The default logging facility is "mail".
Address to send a copy of each message that enters
the system.
+ <b>sender</b><i>_</i><b>bcc</b><i>_</i><b>maps</b>
+ Automatic BCC recipient lookup table, indexed by
+ sender address. The BCC address is added when the
+ message enters the system.
+
+ <b>recipient</b><i>_</i><b>bcc</b><i>_</i><b>maps</b>
+ Automatic BCC recipient lookup table, indexed by
+ recipient address. The BCC address is added when
+ the message enters the system.
+
<b>hopcount</b><i>_</i><b>limit</b>
Limit the number of <b>Received:</b> message headers.
when the message arrival rate exceeds the message
delivery rate.
- <b>extract</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Limit the amount of recipients extracted from mes-
- sage headers.
-
<b>virtual</b><i>_</i><b>alias</b><i>_</i><b>expansion</b><i>_</i><b>limit</b>
- Limit the number of actual recipients produced by
- virtual alias expansion from each original recipi-
+ Limit the number of actual recipients produced by
+ virtual alias expansion from each original recipi-
ent.
<b>virtual</b><i>_</i><b>alias</b><i>_</i><b>recursion</b><i>_</i><b>limit</b>
- Limit the recursion depth of virtual alias expan-
+ Limit the recursion depth of virtual alias expan-
sion.
<b>SEE</b> <b>ALSO</b>
/etc/postfix/virtual*, virtual mapping table
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
transport table.
<b>Miscellaneous</b>
- <b>always</b><i>_</i><b>bcc</b>
- Address to send a copy of each message that enters
- the system.
-
<b>queue</b><i>_</i><b>directory</b>
Top-level directory of the Postfix queue.
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
command after a configuration change.
<b>Miscellaneous</b>
- <b>always</b><i>_</i><b>bcc</b>
- Address to send a copy of each message that enters
- the system.
-
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
- Increment in verbose logging level when a remote
+ Increment in verbose logging level when a remote
host matches a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
parameter.
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
- List of domain or network patterns. When a remote
- host matches a pattern, increase the verbose log-
- ging level by the amount specified in the
+ List of domain or network patterns. When a remote
+ host matches a pattern, increase the verbose log-
+ ging level by the amount specified in the
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
<b>hopcount</b><i>_</i><b>limit</b>
what clients are allowed to use the service.
<b>qmqpd</b><i>_</i><b>timeout</b>
- Limit the time to send a server response and to
+ Limit the time to send a server response and to
receive a client request.
<b>soft</b><i>_</i><b>bounce</b>
- Change hard (D) reject responses into soft (Z)
- reject responses. This can be useful for testing
+ Change hard (D) reject responses into soft (Z)
+ reject responses. This can be useful for testing
purposes.
<b>Content</b> <b>inspection</b> <b>controls</b>
<b>content</b><i>_</i><b>filter</b>
- The name of a mail delivery transport that filters
+ The name of a mail delivery transport that filters
mail and that either bounces mail or re-injects the
- result back into Postfix. This parameter uses the
- same syntax as the right-hand side of a Postfix
+ result back into Postfix. This parameter uses the
+ same syntax as the right-hand side of a Postfix
transport table.
<b>Resource</b> <b>controls</b>
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
- Limit the amount of memory in bytes used for the
- handling of partial input lines, and the length of
- sender and recipient addresses that are received
+ Limit the amount of memory in bytes used for the
+ handling of partial input lines, and the length of
+ sender and recipient addresses that are received
from client.
<b>message</b><i>_</i><b>size</b><i>_</i><b>limit</b>
Limit the total size in bytes of a message, includ-
- ing on-disk storage for sender and recipient
+ ing on-disk storage for sender and recipient
address information.
<b>Tarpitting</b>
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
This command is not implemented. Use the slower
<b>sendmail</b> <b>-q</b> command instead.
- <b>-t</b> Extract recipients from message headers. This
- requires that no recipients be specified on the
- command line.
+ <b>-t</b> Extract recipients from message headers. These are
+ added to any recipients specified on the command
+ line.
<b>-v</b> Send an email report of all delivery attempts (mail
delivery always happens in the background). When
restriction.
<b>Miscellaneous</b>
- <b>always</b><i>_</i><b>bcc</b>
- Address to send a copy of each message that enters
- the system.
-
<b>authorized</b><i>_</i><b>verp</b><i>_</i><b>clients</b>
Hostnames, domain names and/or addresses of clients
that are authorized to use the XVERP extension.
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
- Increment in verbose logging level when a remote
+ Increment in verbose logging level when a remote
host matches a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
parameter.
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
- List of domain or network patterns. When a remote
- host matches a pattern, increase the verbose log-
- ging level by the amount specified in the
+ List of domain or network patterns. When a remote
+ host matches a pattern, increase the verbose log-
+ ging level by the amount specified in the
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
<b>default</b><i>_</i><b>verp</b><i>_</i><b>delimiters</b>
The default VERP delimiter characters that are used
- when the XVERP command is specified without
+ when the XVERP command is specified without
explicit delimiters.
<b>error</b><i>_</i><b>notice</b><i>_</i><b>recipient</b>
- Recipient of protocol/policy/resource/software
+ Recipient of protocol/policy/resource/software
error notices.
<b>hopcount</b><i>_</i><b>limit</b>
<b>notify</b><i>_</i><b>classes</b>
List of error classes. Of special interest are:
- <b>policy</b> When a client violates any policy, mail a
+ <b>policy</b> When a client violates any policy, mail a
transcript of the entire SMTP session to the
postmaster.
<b>protocol</b>
- When a client violates the SMTP protocol or
+ When a client violates the SMTP protocol or
issues an unimplemented command, mail a
transcript of the entire SMTP session to the
postmaster.
<b>smtpd</b><i>_</i><b>banner</b>
- Text that follows the <b>220</b> status code in the SMTP
+ Text that follows the <b>220</b> status code in the SMTP
greeting banner.
<b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
expansion of rbl template responses and other text.
<b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
- Restrict the number of recipients that the SMTP
+ Restrict the number of recipients that the SMTP
server accepts per message delivery.
<b>smtpd</b><i>_</i><b>timeout</b>
- Limit the time to send a server response and to
+ Limit the time to send a server response and to
receive a client request.
<b>soft</b><i>_</i><b>bounce</b>
- Change hard (5xx) reject responses into soft (4xx)
- reject responses. This can be useful for testing
+ Change hard (5xx) reject responses into soft (4xx)
+ reject responses. This can be useful for testing
purposes.
<b>verp</b><i>_</i><b>delimiter</b><i>_</i><b>filter</b>
- The characters that Postfix accepts as VERP delim-
+ The characters that Postfix accepts as VERP delim-
iter characters.
<b>Known</b> <b>versus</b> <b>unknown</b> <b>recipients</b>
<b>show</b><i>_</i><b>user</b><i>_</i><b>unknown</b><i>_</i><b>table</b><i>_</i><b>name</b>
- Whether or not to reveal the table name in the
- "User unknown" responses. The extra detail makes
- trouble shooting easier but also reveals informa-
+ Whether or not to reveal the table name in the
+ "User unknown" responses. The extra detail makes
+ trouble shooting easier but also reveals informa-
tion that is nobody elses business.
<b>unknown</b><i>_</i><b>local</b><i>_</i><b>recipient</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
- ent whose domain matches <b>$mydestination</b> or
+ ent whose domain matches <b>$mydestination</b> or
<b>$inet</b><i>_</i><b>interfaces</b>, while <b>$local</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is
- non-empty and does not list the recipient address
+ non-empty and does not list the recipient address
or address local-part.
<b>unknown</b><i>_</i><b>relay</b><i>_</i><b>recipient</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
ent whose domain matches <b>$relay</b><i>_</i><b>domains</b>, while
- <b>$relay</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is non-empty and does not
+ <b>$relay</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is non-empty and does not
list the recipient address.
<b>unknown</b><i>_</i><b>virtual</b><i>_</i><b>alias</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
- ent whose domain matches <b>$virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b>,
- while the recipient is not listed in <b>$vir-</b>
+ ent whose domain matches <b>$virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b>,
+ while the recipient is not listed in <b>$vir-</b>
<b>tual</b><i>_</i><b>alias</b><i>_</i><b>maps</b>.
<b>unknown</b><i>_</i><b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
- ent whose domain matches <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>,
+ ent whose domain matches <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>,
while the recipient is not listed in <b>$virtual</b><i>_</i><b>mail-</b>
<b>box</b><i>_</i><b>maps</b>.
<b>Resource</b> <b>controls</b>
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
- Limit the amount of memory in bytes used for the
+ Limit the amount of memory in bytes used for the
handling of partial input lines.
<b>message</b><i>_</i><b>size</b><i>_</i><b>limit</b>
ing on-disk storage for envelope information.
<b>queue</b><i>_</i><b>minfree</b>
- Minimal amount of free space in bytes in the queue
- file system for the SMTP server to accept any mail
+ Minimal amount of free space in bytes in the queue
+ file system for the SMTP server to accept any mail
at all.
<b>smtpd</b><i>_</i><b>history</b><i>_</i><b>flush</b><i>_</i><b>threshold</b>
<b>smtpd</b><i>_</i><b>soft</b><i>_</i><b>error</b><i>_</i><b>limit</b>
When an SMTP client has made this number of errors,
- wait <i>error_count</i> seconds before responding to any
+ wait <i>error_count</i> seconds before responding to any
client request.
<b>smtpd</b><i>_</i><b>hard</b><i>_</i><b>error</b><i>_</i><b>limit</b>
- Disconnect after a client has made this number of
+ Disconnect after a client has made this number of
errors.
<b>smtpd</b><i>_</i><b>junk</b><i>_</i><b>command</b><i>_</i><b>limit</b>
Limit the number of times a client can issue a junk
- command such as NOOP, VRFY, ETRN or RSET in one
- SMTP session before it is penalized with tarpit
+ command such as NOOP, VRFY, ETRN or RSET in one
+ SMTP session before it is penalized with tarpit
delays.
<b>UCE</b> <b>control</b> <b>restrictions</b>
<b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b>
- List of Postfix features that use <i>domain.tld</i> pat-
- terns to match <i>sub.domain.tld</i> (as opposed to
+ List of Postfix features that use <i>domain.tld</i> pat-
+ terns to match <i>sub.domain.tld</i> (as opposed to
requiring <i>.domain.tld</i> patterns).
<b>smtpd</b><i>_</i><b>client</b><i>_</i><b>restrictions</b>
tem.
<b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>required</b>
- Require that clients introduce themselves at the
+ Require that clients introduce themselves at the
beginning of an SMTP session.
<b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>restrictions</b>
- Restrict what client hostnames are allowed in <b>HELO</b>
+ Restrict what client hostnames are allowed in <b>HELO</b>
and <b>EHLO</b> commands.
<b>smtpd</b><i>_</i><b>sender</b><i>_</i><b>restrictions</b>
- Restrict what sender addresses are allowed in <b>MAIL</b>
+ Restrict what sender addresses are allowed in <b>MAIL</b>
<b>FROM</b> commands.
<b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>restrictions</b>
- Restrict what recipient addresses are allowed in
+ Restrict what recipient addresses are allowed in
<b>RCPT</b> <b>TO</b> commands.
<b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b>
mands, and what clients may issue <b>ETRN</b> commands.
<b>smtpd</b><i>_</i><b>data</b><i>_</i><b>restrictions</b>
- Restrictions on the <b>DATA</b> command. Currently, the
- only restriction that makes sense here is
+ Restrictions on the <b>DATA</b> command. Currently, the
+ only restriction that makes sense here is
<b>reject</b><i>_</i><b>unauth</b><i>_</i><b>pipelining</b>.
<b>allow</b><i>_</i><b>untrusted</b><i>_</i><b>routing</b>
- Allow untrusted clients to specify addresses with
- sender-specified routing. Enabling this opens up
- nasty relay loopholes involving trusted backup MX
+ Allow untrusted clients to specify addresses with
+ sender-specified routing. Enabling this opens up
+ nasty relay loopholes involving trusted backup MX
hosts.
<b>smtpd</b><i>_</i><b>restriction</b><i>_</i><b>classes</b>
- Declares the name of zero or more parameters that
- contain a list of UCE restrictions. The names of
- these parameters can then be used instead of the
+ Declares the name of zero or more parameters that
+ contain a list of UCE restrictions. The names of
+ these parameters can then be used instead of the
restriction lists that they represent.
<b>smtpd</b><i>_</i><b>null</b><i>_</i><b>access</b><i>_</i><b>lookup</b><i>_</i><b>key</b>
- The lookup key to be used in SMTPD access tables
- instead of the null sender address. A null sender
+ The lookup key to be used in SMTPD access tables
+ instead of the null sender address. A null sender
address cannot be looked up.
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b> (deprecated)
- List of DNS domains that publish the addresses of
+ List of DNS domains that publish the addresses of
blacklisted hosts. This is used with the deprecated
<b>reject</b><i>_</i><b>maps</b><i>_</i><b>rbl</b> restriction.
<b>permit</b><i>_</i><b>mx</b><i>_</i><b>backup</b><i>_</i><b>networks</b>
- Only domains whose primary MX hosts match the
- listed networks are eligible for the <b>per-</b>
+ Only domains whose primary MX hosts match the
+ listed networks are eligible for the <b>per-</b>
<b>mit</b><i>_</i><b>mx</b><i>_</i><b>backup</b> feature.
<b>relay</b><i>_</i><b>domains</b>
- Restrict what domains this mail system will relay
- mail to. The domains are routed to the delivery
+ Restrict what domains this mail system will relay
+ mail to. The domains are routed to the delivery
agent specified with the <b>relay</b><i>_</i><b>transport</b> setting.
<b>UCE</b> <b>control</b> <b>responses</b>
<b>access</b><i>_</i><b>map</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Response code when a client violates an access
+ Response code when a client violates an access
database restriction.
<b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b>
Default template reply when a request is RBL black-
- listed. This template is used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b>
- and <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
+ listed. This template is used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b>
+ and <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
<b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>.
<b>defer</b><i>_</i><b>code</b>
- Response code when a client request is rejected by
+ Response code when a client request is rejected by
the <b>defer</b> restriction.
<b>invalid</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Response code when a client violates the
+ Response code when a client violates the
<b>reject</b><i>_</i><b>invalid</b><i>_</i><b>hostname</b> restriction.
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>reject</b><i>_</i><b>code</b>
Response code when a request is RBL blacklisted.
<b>multi</b><i>_</i><b>recipient</b><i>_</i><b>bounce</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Response code when a multi-recipient bounce is
+ Response code when a multi-recipient bounce is
blocked.
<b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b>
- Table with template responses for RBL blacklisted
- requests, indexed by RBL domain name. These tem-
+ Table with template responses for RBL blacklisted
+ requests, indexed by RBL domain name. These tem-
plates are used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b> and
- <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
+ <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
<b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>.
<b>reject</b><i>_</i><b>code</b>
- Response code when the client matches a <b>reject</b>
+ Response code when the client matches a <b>reject</b>
restriction.
<b>relay</b><i>_</i><b>domains</b><i>_</i><b>reject</b><i>_</i><b>code</b>
mail relay policy.
<b>unknown</b><i>_</i><b>address</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Response code when a client violates the
+ Response code when a client violates the
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>address</b> restriction.
<b>unknown</b><i>_</i><b>client</b><i>_</i><b>reject</b><i>_</i><b>code</b>
tion.
<b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Response code when a client violates the
+ Response code when a client violates the
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
<b>unverified</b><i>_</i><b>sender</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Response code when a sender address is known to be
+ Response code when a sender address is known to be
undeliverable.
<b>unverified</b><i>_</i><b>recipient</b><i>_</i><b>reject</b><i>_</i><b>code</b>
- Response code when a recipient address is known to
+ Response code when a recipient address is known to
be undeliverable.
<b>SEE</b> <b>ALSO</b>
syslogd(8) system logging
<b>LICENSE</b>
- The Secure Mailer license must be distributed with this
+ The Secure Mailer license must be distributed with this
software.
<b>AUTHOR(S)</b>
This command is not implemented. Use the slower \fBsendmail -q\fR
command instead.
.IP \fB-t\fR
-Extract recipients from message headers. This requires that no
-recipients be specified on the command line.
+Extract recipients from message headers. These are added to any
+recipients specified on the command line.
.IP \fB-v\fR
Send an email report of all delivery attempts (mail delivery
always happens in the background). When multiple \fB-v\fR
.fi
.IP \fBalways_bcc\fR
Address to send a copy of each message that enters the system.
+.IP \fBsender_bcc_maps\fR
+Automatic BCC recipient lookup table, indexed by sender address.
+The BCC address is added when the message enters the system.
+.IP \fBrecipient_bcc_maps\fR
+Automatic BCC recipient lookup table, indexed by recipient address.
+The BCC address is added when the message enters the system.
.IP \fBhopcount_limit\fR
Limit the number of \fBReceived:\fR message headers.
.IP \fBundisclosed_recipients_header\fR
.IP \fBin_flow_delay\fR
Amount of time to pause before accepting a message, when the
message arrival rate exceeds the message delivery rate.
-.IP \fBextract_recipient_limit\fR
-Limit the amount of recipients extracted from message headers.
.IP \fBvirtual_alias_expansion_limit\fR
Limit the number of actual recipients produced by virtual alias
expansion from each original recipient.
.SH Miscellaneous
.ad
.fi
-.IP \fBalways_bcc\fR
-Address to send a copy of each message that enters the system.
.IP \fBqueue_directory\fR
Top-level directory of the Postfix queue.
.SH SEE ALSO
.SH Miscellaneous
.ad
.fi
-.IP \fBalways_bcc\fR
-Address to send a copy of each message that enters the system.
.IP \fBdebug_peer_level\fR
Increment in verbose logging level when a remote host matches a
pattern in the \fBdebug_peer_list\fR parameter.
.SH Miscellaneous
.ad
.fi
-.IP \fBalways_bcc\fR
-Address to send a copy of each message that enters the system.
.IP \fBauthorized_verp_clients\fR
Hostnames, domain names and/or addresses of clients that are
authorized to use the XVERP extension.
SRCS = cleanup.c cleanup_out.c cleanup_envelope.c cleanup_message.c \
cleanup_extracted.c cleanup_state.c cleanup_rewrite.c \
cleanup_map11.c cleanup_map1n.c cleanup_masquerade.c \
- cleanup_out_recipient.c cleanup_init.c cleanup_api.c
+ cleanup_out_recipient.c cleanup_init.c cleanup_api.c \
+ cleanup_addr.c
OBJS = cleanup.o cleanup_out.o cleanup_envelope.o cleanup_message.o \
cleanup_extracted.o cleanup_state.o cleanup_rewrite.o \
cleanup_map11.o cleanup_map1n.o cleanup_masquerade.o \
- cleanup_out_recipient.o cleanup_init.o cleanup_api.o
+ cleanup_out_recipient.o cleanup_init.o cleanup_api.o \
+ cleanup_addr.o
HDRS =
TESTSRC =
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
cleanup.o: ../../include/string_list.h
cleanup.o: ../../include/match_list.h
cleanup.o: ../../include/match_ops.h
+cleanup_addr.o: cleanup_addr.c
+cleanup_addr.o: ../../include/sys_defs.h
+cleanup_addr.o: ../../include/msg.h
+cleanup_addr.o: ../../include/vstring.h
+cleanup_addr.o: ../../include/vbuf.h
+cleanup_addr.o: ../../include/vstream.h
+cleanup_addr.o: ../../include/mymalloc.h
+cleanup_addr.o: ../../include/stringops.h
+cleanup_addr.o: ../../include/rec_type.h
+cleanup_addr.o: ../../include/cleanup_user.h
+cleanup_addr.o: ../../include/mail_params.h
+cleanup_addr.o: ../../include/ext_prop.h
+cleanup_addr.o: ../../include/mail_addr.h
+cleanup_addr.o: ../../include/canon_addr.h
+cleanup_addr.o: cleanup.h
+cleanup_addr.o: ../../include/argv.h
+cleanup_addr.o: ../../include/nvtable.h
+cleanup_addr.o: ../../include/htable.h
+cleanup_addr.o: ../../include/maps.h
+cleanup_addr.o: ../../include/dict.h
+cleanup_addr.o: ../../include/tok822.h
+cleanup_addr.o: ../../include/resolve_clnt.h
+cleanup_addr.o: ../../include/been_here.h
+cleanup_addr.o: ../../include/mail_stream.h
+cleanup_addr.o: ../../include/mail_conf.h
+cleanup_addr.o: ../../include/mime_state.h
+cleanup_addr.o: ../../include/header_opts.h
+cleanup_addr.o: ../../include/string_list.h
+cleanup_addr.o: ../../include/match_list.h
+cleanup_addr.o: ../../include/match_ops.h
cleanup_api.o: cleanup_api.c
cleanup_api.o: ../../include/sys_defs.h
cleanup_api.o: ../../include/msg.h
cleanup_map1n.o: ../../include/vbuf.h
cleanup_map1n.o: ../../include/dict.h
cleanup_map1n.o: ../../include/vstream.h
+cleanup_map1n.o: ../../include/mail_params.h
cleanup_map1n.o: ../../include/mail_addr_map.h
cleanup_map1n.o: ../../include/maps.h
cleanup_map1n.o: ../../include/cleanup_user.h
cleanup_state.o: ../../include/mymalloc.h
cleanup_state.o: ../../include/vstring.h
cleanup_state.o: ../../include/vbuf.h
-cleanup_state.o: ../../include/argv.h
cleanup_state.o: ../../include/htable.h
cleanup_state.o: ../../include/been_here.h
cleanup_state.o: ../../include/mail_params.h
cleanup_state.o: ../../include/header_opts.h
cleanup_state.o: cleanup.h
cleanup_state.o: ../../include/vstream.h
+cleanup_state.o: ../../include/argv.h
cleanup_state.o: ../../include/nvtable.h
cleanup_state.o: ../../include/maps.h
cleanup_state.o: ../../include/dict.h
/* .fi
/* .IP \fBalways_bcc\fR
/* Address to send a copy of each message that enters the system.
+/* .IP \fBsender_bcc_maps\fR
+/* Automatic BCC recipient lookup table, indexed by sender address.
+/* The BCC address is added when the message enters the system.
+/* .IP \fBrecipient_bcc_maps\fR
+/* Automatic BCC recipient lookup table, indexed by recipient address.
+/* The BCC address is added when the message enters the system.
/* .IP \fBhopcount_limit\fR
/* Limit the number of \fBReceived:\fR message headers.
/* .IP \fBundisclosed_recipients_header\fR
/* .IP \fBin_flow_delay\fR
/* Amount of time to pause before accepting a message, when the
/* message arrival rate exceeds the message delivery rate.
-/* .IP \fBextract_recipient_limit\fR
-/* Limit the amount of recipients extracted from message headers.
/* .IP \fBvirtual_alias_expansion_limit\fR
/* Limit the number of actual recipients produced by virtual alias
/* expansion from each original recipient.
int err_mask; /* allowed badness */
int headers_seen; /* which headers were seen */
int hop_count; /* count of received: headers */
- ARGV *recipients; /* recipients from regular headers */
- ARGV *resent_recip; /* recipients from resent headers */
char *resent; /* any resent- header seen */
BH_TABLE *dups; /* recipient dup filter */
long warn_time; /* cleanup_envelope.c */
- void (*action) (struct CLEANUP_STATE *, int, char *, int);
+ void (*action) (struct CLEANUP_STATE *, int, const char *, int);
off_t mesg_offset; /* start of message segment */
off_t data_offset; /* start of message content */
off_t xtra_offset; /* start of extra segment */
extern ARGV *cleanup_masq_domains;
extern STRING_LIST *cleanup_masq_exceptions;
extern int cleanup_masq_flags;
+extern MAPS *cleanup_send_bcc_maps;
+extern MAPS *cleanup_rcpt_bcc_maps;
/*
* Address masquerading fine control.
/*
* cleanup_envelope.c
*/
-extern void cleanup_envelope(CLEANUP_STATE *, int, char *, int);
+extern void cleanup_envelope(CLEANUP_STATE *, int, const char *, int);
/*
* cleanup_message.c
*/
-extern void cleanup_message(CLEANUP_STATE *, int, char *, int);
+extern void cleanup_message(CLEANUP_STATE *, int, const char *, int);
/*
* cleanup_extracted.c
*/
-extern void cleanup_extracted(CLEANUP_STATE *, int, char *, int);
+extern void cleanup_extracted(CLEANUP_STATE *, int, const char *, int);
/*
* cleanup_rewrite.c
extern void cleanup_masquerade_tree(TOK822 *, ARGV *);
/*
- * Cleanup_recipient.c
+ * cleanup_recipient.c
*/
extern void cleanup_out_recipient(CLEANUP_STATE *, const char *, const char *);
+ /*
+ * cleanup_addr.c.
+ */
+extern void cleanup_addr_sender(CLEANUP_STATE *, const char *);
+extern void cleanup_addr_recipient(CLEANUP_STATE *, const char *);
+extern void cleanup_addr_bcc(CLEANUP_STATE *, const char *);
+
/* LICENSE
/* .ad
/* .fi
--- /dev/null
+/*++
+/* NAME
+/* cleanup_addr 3
+/* SUMMARY
+/* process envelope addresses
+/* SYNOPSIS
+/* #include <cleanup.h>
+/*
+/* void cleanup_addr_sender(state, addr)
+/* CLEANUP_STATE *state;
+/* const char *addr;
+/*
+/* void cleanup_addr_recipient(state, addr)
+/* CLEANUP_STATE *state;
+/* const char *addr;
+/*
+/* void cleanup_addr_bcc(state, addr)
+/* CLEANUP_STATE *state;
+/* const char *addr;
+/* DESCRIPTION
+/* This module processes envelope address records and writes the result
+/* to the queue file. Processing includes address rewriting and
+/* sender/recipient auto bcc address generation.
+/*
+/* cleanup_addr_sender() process sender envelope information and updates
+/* state->sender.
+/*
+/* cleanup_addr_recipient() processes recipient envelope information
+/* and updates state->recip.
+/*
+/* cleanup_addr_bcc() processes recipient envelope information. This
+/* is a separate function to avoid invoking cleanup_addr_recipient()
+/* recursively.
+/*
+/* Arguments:
+/* .IP state
+/* Queue file and message processing state. This state is updated
+/* as records are processed and as errors happen.
+/* .IP buf
+/* Record content.
+/* 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 <sys_defs.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <vstream.h>
+#include <mymalloc.h>
+#include <stringops.h>
+
+/* Global library. */
+
+#include <rec_type.h>
+#include <cleanup_user.h>
+#include <mail_params.h>
+#include <ext_prop.h>
+#include <mail_addr.h>
+#include <canon_addr.h>
+
+/* Application-specific. */
+
+#include "cleanup.h"
+
+#define STR vstring_str
+
+/* cleanup_addr_sender - process envelope sender record */
+
+void cleanup_addr_sender(CLEANUP_STATE *state, const char *buf)
+{
+ VSTRING *clean_addr = vstring_alloc(100);
+ const char *bcc;
+
+ cleanup_rewrite_internal(clean_addr, buf);
+ if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
+ sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
+ canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
+ if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0)
+ vstring_strcpy(clean_addr, "");
+ }
+ if (cleanup_send_canon_maps)
+ cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_comm_canon_maps)
+ cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_masq_domains
+ && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM))
+ cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
+ CLEANUP_OUT_BUF(state, REC_TYPE_FROM, clean_addr);
+ if (state->sender == 0)
+ state->sender = mystrdup(STR(clean_addr));
+ if ((state->flags & CLEANUP_FLAG_BCC_OK)
+ && *STR(clean_addr)
+ && cleanup_send_bcc_maps
+ && (bcc = maps_find(cleanup_send_bcc_maps, STR(clean_addr), 0)) != 0)
+ cleanup_addr_bcc(state, bcc);
+ vstring_free(clean_addr);
+}
+
+/* cleanup_addr_recipient - process envelope recipient */
+
+void cleanup_addr_recipient(CLEANUP_STATE *state, const char *buf)
+{
+ VSTRING *clean_addr = vstring_alloc(100);
+ const char *bcc;
+
+ cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr);
+ if (cleanup_rcpt_canon_maps)
+ cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_comm_canon_maps)
+ cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_masq_domains
+ && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
+ cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
+ cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr));
+ if (state->recip == 0)
+ state->recip = mystrdup(STR(clean_addr));
+ if ((state->flags & CLEANUP_FLAG_BCC_OK)
+ && *STR(clean_addr)
+ && cleanup_rcpt_bcc_maps
+ && (bcc = maps_find(cleanup_rcpt_bcc_maps, STR(clean_addr), 0)) != 0)
+ cleanup_addr_bcc(state, bcc);
+ vstring_free(clean_addr);
+}
+
+/* cleanup_addr_bcc - process automatic BCC recipient */
+
+void cleanup_addr_bcc(CLEANUP_STATE *state, const char *bcc)
+{
+ VSTRING *clean_addr = vstring_alloc(100);
+
+ cleanup_rewrite_internal(clean_addr, bcc);
+ if (cleanup_rcpt_canon_maps)
+ cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_comm_canon_maps)
+ cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
+ cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
+ if (cleanup_masq_domains
+ && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
+ cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
+ cleanup_out_recipient(state, STR(clean_addr), STR(clean_addr));
+ vstring_free(clean_addr);
+}
/* .IP CLEANUP_FLAG_BOUNCE
/* The cleanup server is responsible for returning undeliverable
/* mail (too many hops, message too large) to the sender.
+/* .IP CLEANUP_FLAG_BCC_OK
+/* It is OK to add automatic BCC recipient addresses.
/* .IP CLEANUP_FLAG_FILTER
/* Enable header/body filtering. This should be enabled only with mail
/* that enters Postfix, not with locally forwarded mail or with bounce
/* messages.
-/* .IP CLEANUP_FLAG_EXTRACT
-/* Extract recipients from message headers when no recipients are
-/* provided in the message envelope records.
/* .PP
/* CLEANUP_RECORD() is a macro that processes one message record,
/* that copies the result to the queue file, and that maintains a
if ((state->flags = flags) & CLEANUP_FLAG_BOUNCE) {
state->err_mask = CLEANUP_STAT_MASK_INCOMPLETE;
} else {
- state->err_mask = ~CLEANUP_STAT_MASK_EXTRACT_RCPT;
+ state->err_mask = ~0;
}
}
int status;
char *encoding;
- /*
- * Ignore recipient extraction alarms if (a) we did (not need to) extract
- * recipients, or (b) we did not examine all queue file records.
- */
- if (state->recip != 0 || CLEANUP_OUT_OK(state) == 0)
- state->errs &= ~CLEANUP_STAT_MASK_EXTRACT_RCPT;
-
/*
* Raise these errors only if we examined all queue file records.
*/
/* void cleanup_envelope(state, type, buf, len)
/* CLEANUP_STATE *state;
/* int type;
-/* char *buf;
-/* int len;
+/* const char *buf;
/* int len;
/* DESCRIPTION
/* This module processes envelope records and writes the result
#define STR vstring_str
-static void cleanup_envelope_process(CLEANUP_STATE *, int, char *, int);
+static void cleanup_envelope_process(CLEANUP_STATE *, int, const char *, int);
/* cleanup_envelope - initialize message envelope */
-void cleanup_envelope(CLEANUP_STATE *state, int type, char *str, int len)
+void cleanup_envelope(CLEANUP_STATE *state, int type,
+ const char *str, int len)
{
/*
/* cleanup_envelope_process - process one envelope record */
-static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, int len)
+static void cleanup_envelope_process(CLEANUP_STATE *state, int type,
+ const char *buf, int len)
{
char *attr_name;
char *attr_value;
const char *error_text;
int extra_flags;
+ /*
+ * On the transition from envelope segment to content segment, do some
+ * sanity checks and add some records.
+ */
if (type == REC_TYPE_MESG) {
if (state->sender == 0 || state->time == 0) {
msg_warn("%s: missing sender or time envelope record",
} else if (type == REC_TYPE_FULL) {
state->fullname = mystrdup(buf);
} else if (type == REC_TYPE_FROM) {
- VSTRING *clean_addr = vstring_alloc(100);
-
- cleanup_rewrite_internal(clean_addr, buf);
- if (strncasecmp(STR(clean_addr), MAIL_ADDR_MAIL_DAEMON "@",
- sizeof(MAIL_ADDR_MAIL_DAEMON)) == 0) {
- canon_addr_internal(state->temp1, MAIL_ADDR_MAIL_DAEMON);
- if (strcasecmp(STR(clean_addr), STR(state->temp1)) == 0)
- vstring_strcpy(clean_addr, "");
+ if (state->sender != 0) {
+ msg_warn("%s: too many envelope sender records", state->queue_id);
+ state->errs |= CLEANUP_STAT_BAD;
+ return;
}
- if (cleanup_send_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_send_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- if (cleanup_comm_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- if (cleanup_masq_domains
- && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_FROM))
- cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
- CLEANUP_OUT_BUF(state, type, clean_addr);
- if (state->sender == 0)
- state->sender = mystrdup(STR(clean_addr));
- vstring_free(clean_addr);
+ cleanup_addr_sender(state, buf);
} else if (type == REC_TYPE_RCPT) {
- VSTRING *clean_addr = vstring_alloc(100);
-
if (state->sender == 0) { /* protect showq */
msg_warn("%s: envelope recipient precedes sender",
state->queue_id);
}
if (state->orig_rcpt == 0)
state->orig_rcpt = mystrdup(buf);
- cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr);
- if (cleanup_rcpt_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- if (cleanup_comm_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- if (cleanup_masq_domains
- && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
- cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
- cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr));
- if (state->recip == 0)
- state->recip = mystrdup(STR(clean_addr));
- vstring_free(clean_addr);
+ cleanup_addr_recipient(state, buf);
myfree(state->orig_rcpt);
state->orig_rcpt = 0;
} else if (type == REC_TYPE_WARN) {
return;
}
} else if (type == REC_TYPE_ATTR) {
+ char *sbuf;
+
if (state->attr->used >= var_qattr_count_limit) {
msg_warn("%s: queue file attribute count exceeds safety limit: %d",
state->queue_id, var_qattr_count_limit);
return;
}
cleanup_out(state, type, buf, len);
- if ((error_text = split_nameval(buf, &attr_name, &attr_value)) != 0) {
+ sbuf = mystrdup(buf);
+ if ((error_text = split_nameval(sbuf, &attr_name, &attr_value)) != 0) {
msg_warn("%s: malformed attribute: %s: %.100s",
state->queue_id, error_text, buf);
state->errs |= CLEANUP_STAT_BAD;
+ myfree(sbuf);
return;
}
nvtable_update(state->attr, attr_name, attr_value);
+ myfree(sbuf);
} else if (type == REC_TYPE_ORCP) {
state->orig_rcpt = mystrdup(buf);
} else {
/* void cleanup_extracted(state, type, buf, len)
/* CLEANUP_STATE *state;
/* int type;
-/* char *buf;
+/* const char *buf;
/* int len;
/* DESCRIPTION
/* This module processes message records with information extracted
#define STR(x) vstring_str(x)
-static void cleanup_extracted_process(CLEANUP_STATE *, int, char *, int);
+static void cleanup_extracted_process(CLEANUP_STATE *, int, const char *, int);
/* cleanup_extracted - initialize extracted segment */
-void cleanup_extracted(CLEANUP_STATE *state, int type, char *buf, int len)
+void cleanup_extracted(CLEANUP_STATE *state, int type,
+ const char *buf, int len)
{
const char *encoding;
/* cleanup_extracted_process - process extracted segment */
-static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, int len)
+static void cleanup_extracted_process(CLEANUP_STATE *state, int type,
+ const char *buf, int len)
{
char *myname = "cleanup_extracted_process";
- VSTRING *clean_addr;
- ARGV *rcpt;
- char **cpp;
/*
* Weird condition for consistency with cleanup_envelope.c
}
}
if (type == REC_TYPE_RCPT) {
- clean_addr = vstring_alloc(100);
if (state->orig_rcpt == 0)
state->orig_rcpt = mystrdup(buf);
- cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr);
- if (cleanup_rcpt_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- if (cleanup_comm_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- if (cleanup_masq_domains
- && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT))
- cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
- cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr));
- if (state->recip == 0)
- state->recip = mystrdup(STR(clean_addr));
- vstring_free(clean_addr);
+ cleanup_addr_recipient(state, buf);
myfree(state->orig_rcpt);
state->orig_rcpt = 0;
return;
}
/*
- * Optionally account for missing recipient envelope records.
- *
- * Don't extract recipients when some header was too long. We have
- * incomplete information.
- *
- * XXX Code duplication from cleanup_envelope.c. This should be in one
- * place.
+ * On the way out, add the optional automatic BCC recipient.
*/
- if (state->recip == 0 && (state->errs & CLEANUP_STAT_HOVFL) == 0) {
- rcpt = (state->resent[0] ? state->resent_recip : state->recipients);
- if (rcpt->argc >= var_extra_rcpt_limit) {
- state->errs |= CLEANUP_STAT_ROVFL;
- } else {
- clean_addr = vstring_alloc(100);
- if (*var_always_bcc && rcpt->argv[0]) {
- cleanup_rewrite_internal(clean_addr, var_always_bcc);
- if (cleanup_rcpt_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- if (cleanup_comm_canon_maps)
- cleanup_map11_internal(state, clean_addr, cleanup_comm_canon_maps,
- cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- argv_add(rcpt, STR(clean_addr), (char *) 0);
- }
- argv_terminate(rcpt);
-
- /*
- * Recipients extracted from message headers already have
- * undergone recipient address rewriting (see cleanup_message.c),
- * but still may need address masquerading.
- */
- for (cpp = rcpt->argv; CLEANUP_OUT_OK(state) && *cpp; cpp++) {
- if (cleanup_masq_domains
- && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) {
- vstring_strcpy(clean_addr, *cpp);
- cleanup_masquerade_internal(clean_addr, cleanup_masq_domains);
- cleanup_out_recipient(state, STR(clean_addr),
- STR(clean_addr)); /* XXX */
- } else
- cleanup_out_recipient(state, *cpp, *cpp); /* XXX */
- }
- if (rcpt->argv[0])
- state->recip = mystrdup(rcpt->argv[0]);
- vstring_free(clean_addr);
- }
- }
+ if ((state->flags & CLEANUP_FLAG_BCC_OK)
+ && state->recip != 0 && *var_always_bcc)
+ cleanup_addr_bcc(state, var_always_bcc);
/*
* Terminate the extracted segment.
int var_delay_warn_time; /* delay that triggers warning */
char *var_prop_extension; /* propagate unmatched extension */
char *var_always_bcc; /* big brother */
-int var_extra_rcpt_limit; /* recipient extract limit */
char *var_rcpt_witheld; /* recipients not disclosed */
char *var_masq_classes; /* what to masquerade */
int var_qattr_count_limit; /* named attribute limit */
int var_virt_recur_limit; /* maximum virtual alias recursion */
int var_virt_expan_limit; /* maximum virtual alias expansion */
int var_body_check_len; /* when to stop body scan */
+char *var_send_bcc_maps; /* sender auto-bcc maps */
+char *var_rcpt_bcc_maps; /* recipient auto-bcc maps */
CONFIG_INT_TABLE cleanup_int_table[] = {
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
VAR_DUP_FILTER_LIMIT, DEF_DUP_FILTER_LIMIT, &var_dup_filter_limit, 0, 0,
- VAR_EXTRA_RCPT_LIMIT, DEF_EXTRA_RCPT_LIMIT, &var_extra_rcpt_limit, 0, 0,
VAR_QATTR_COUNT_LIMIT, DEF_QATTR_COUNT_LIMIT, &var_qattr_count_limit, 1, 0,
VAR_VIRT_RECUR_LIMIT, DEF_VIRT_RECUR_LIMIT, &var_virt_recur_limit, 1, 0,
VAR_VIRT_EXPAN_LIMIT, DEF_VIRT_EXPAN_LIMIT, &var_virt_expan_limit, 1, 0,
VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 1, 0,
VAR_MASQ_CLASSES, DEF_MASQ_CLASSES, &var_masq_classes, 0, 0,
+ VAR_SEND_BCC_MAPS, DEF_SEND_BCC_MAPS, &var_send_bcc_maps, 0, 0,
+ VAR_RCPT_BCC_MAPS, DEF_RCPT_BCC_MAPS, &var_rcpt_bcc_maps, 0, 0,
0,
};
ARGV *cleanup_masq_domains;
STRING_LIST *cleanup_masq_exceptions;
int cleanup_masq_flags;
+MAPS *cleanup_send_bcc_maps;
+MAPS *cleanup_rcpt_bcc_maps;
/*
* Address extension propagation restrictions.
if (*var_masq_classes)
cleanup_masq_flags = name_mask(VAR_MASQ_CLASSES, masq_class_table,
var_masq_classes);
+ if (*var_send_bcc_maps)
+ cleanup_send_bcc_maps =
+ maps_create(VAR_SEND_BCC_MAPS, var_send_bcc_maps,
+ DICT_FLAG_LOCK);
+ if (*var_rcpt_bcc_maps)
+ cleanup_rcpt_bcc_maps =
+ maps_create(VAR_RCPT_BCC_MAPS, var_rcpt_bcc_maps,
+ DICT_FLAG_LOCK);
}
/* cleanup_post_jail - initialize after entering the chroot jail */
/* void cleanup_message(state, type, buf, len)
/* CLEANUP_STATE *state;
/* int type;
-/* char *buf;
+/* const char *buf;
/* int len;
/* DESCRIPTION
/* This module processes message content records and copies the
TOK822 *tree;
TOK822 **addr_list;
TOK822 **tpp;
- ARGV *rcpt;
if (msg_verbose)
msg_info("rewrite_recip: %s", hdr_opts->name);
cleanup_map11_tree(state, *tpp, cleanup_comm_canon_maps,
cleanup_ext_prop_mask & EXT_PROP_CANONICAL);
- /*
- * Extract envelope recipients after recipient address rewriting but
- * before address masquerading.
- */
- if (state->recip == 0 && (hdr_opts->flags & HDR_OPT_EXTRACT) != 0) {
- rcpt = (hdr_opts->flags & HDR_OPT_RR) ?
- state->resent_recip : state->recipients;
- if (rcpt->argc < var_extra_rcpt_limit) {
- tok822_internalize(state->temp1, tpp[0]->head, TOK822_STR_DEFL);
- argv_add(rcpt, vstring_str(state->temp1), (char *) 0);
- }
- }
if (cleanup_masq_domains
&& (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT))
cleanup_masquerade_tree(*tpp, cleanup_masq_domains);
const char *attr;
if ((attr = nvtable_find(state->attr, MAIL_ATTR_ORIGIN)) == 0)
- attr="unknown";
+ attr = "unknown";
vstring_sprintf(state->temp1, "%s: %s: %s %.200s from %s;",
state->queue_id, action, class, content, attr);
if (state->sender)
if ((state->headers_seen & VISIBLE_RCPT) == 0)
cleanup_out_format(state, REC_TYPE_NORM, "%s", var_rcpt_witheld);
-
- /*
- * Header buffer overflow is an unrecoverable error only if we extract
- * recipients from the main message headers.
- */
- if (state->mime_errs & MIME_ERR_TRUNC_HEADER)
- state->errs |= CLEANUP_STAT_HOVFL;
}
/* cleanup_body_callback - output one body record */
/* cleanup_message_headerbody - process message content, header and body */
static void cleanup_message_headerbody(CLEANUP_STATE *state, int type,
- char *buf, int len)
+ const char *buf, int len)
{
char *myname = "cleanup_message_headerbody";
/* cleanup_message - initialize message content segment */
-void cleanup_message(CLEANUP_STATE *state, int type, char *buf, int len)
+void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, int len)
{
char *myname = "cleanup_message";
int mime_options;
* special processing of Content-Type: headers, and thus, causes all text
* after the primary headers to be treated as the message body.
*/
- mime_options = MIME_OPT_REPORT_TRUNC_HEADER;
+ mime_options = 0;
if (var_disable_mime_input) {
mime_options |= MIME_OPT_DISABLE_MIME;
} else {
#include <mymalloc.h>
#include <vstring.h>
-#include <argv.h>
#include <htable.h>
/* Global library. */
state->err_mask = 0;
state->headers_seen = 0;
state->hop_count = 0;
- state->recipients = argv_alloc(2);
- state->resent_recip = argv_alloc(2);
state->resent = "";
state->dups = been_here_init(var_dup_filter_limit, BH_FLAG_FOLD);
state->warn_time = 0;
myfree(state->return_receipt);
if (state->errors_to)
myfree(state->errors_to);
- argv_free(state->recipients);
- argv_free(state->resent_recip);
if (state->queue_name)
myfree(state->queue_name);
if (state->queue_id)
static struct cleanup_stat_map cleanup_stat_map[] = {
CLEANUP_STAT_BAD, "Internal protocol error",
- CLEANUP_STAT_HOVFL, "Message header too long",
- CLEANUP_STAT_ROVFL, "Too many extracted recipients",
CLEANUP_STAT_RCPT, "No recipients specified",
CLEANUP_STAT_HOPS, "Too many hops",
CLEANUP_STAT_SIZE, "Message file too big",
#define CLEANUP_FLAG_FILTER (1<<1) /* Enable content filter */
#define CLEANUP_FLAG_HOLD (1<<2) /* Place message on hold */
#define CLEANUP_FLAG_DISCARD (1<<3) /* Discard message silently */
+#define CLEANUP_FLAG_BCC_OK (1<<4) /* Ok to add auto-BCC addresses */
/*
* These are set on the fly while processing SMTP envelopes or message
#define CLEANUP_STAT_SIZE (1<<2) /* Message file too big */
#define CLEANUP_STAT_CONT (1<<3) /* Message content rejected */
#define CLEANUP_STAT_HOPS (1<<4) /* Too many hops */
-#define CLEANUP_STAT_SYN (1<<5) /* Bad address syntax */
#define CLEANUP_STAT_RCPT (1<<6) /* No recipients found */
-#define CLEANUP_STAT_HOVFL (1<<7) /* Header overflow */
-#define CLEANUP_STAT_ROVFL (1<<8) /* Recipient overflow */
/*
* These are set when we can't bounce even if we were asked to.
#define CLEANUP_STAT_MASK_INCOMPLETE \
(CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE)
- /*
- * These are relevant for extracting recipients from headers.
- */
-#define CLEANUP_STAT_MASK_EXTRACT_RCPT \
- (CLEANUP_STAT_HOVFL | CLEANUP_STAT_ROVFL | CLEANUP_STAT_RCPT)
-
extern const char *cleanup_strerror(unsigned);
/* LICENSE
#define DEF_RCPT_CANON_MAPS ""
extern char *var_rcpt_canon_maps;
+#define VAR_SEND_BCC_MAPS "sender_bcc_maps"
+#define DEF_SEND_BCC_MAPS ""
+extern char *var_send_bcc_maps;
+
+#define VAR_RCPT_BCC_MAPS "recipient_bcc_maps"
+#define DEF_RCPT_BCC_MAPS ""
+extern char *var_rcpt_bcc_maps;
+
#define VAR_TRANSPORT_MAPS "transport_maps"
#define DEF_TRANSPORT_MAPS ""
extern char *var_transport_maps;
#define DEF_TOKEN_LIMIT 10240
extern int var_token_limit;
-#define VAR_EXTRA_RCPT_LIMIT "extract_recipient_limit"
-#define DEF_EXTRA_RCPT_LIMIT 10240
-extern int var_extra_rcpt_limit;
-
#define VAR_VIRT_RECUR_LIMIT "virtual_alias_recursion_limit"
#define DEF_VIRT_RECUR_LIMIT 1000
extern int var_virt_recur_limit;
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
-#define MAIL_RELEASE_DATE "20030415"
+#define MAIL_RELEASE_DATE "20030416"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.8-" MAIL_RELEASE_DATE
defer_append : bounce_append)
(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr),
"maildir delivery failed: %s", vstring_str(why));
+ if (errno == EACCES) {
+ msg_warn("maildir access problem for UID/GID=%lu/%lu: %s",
+ (long) usr_attr.uid, (long) usr_attr.gid, vstring_str(why));
+ msg_warn("perhaps you need to create the maildirs in advance");
+ }
} else {
deliver_status = sent(BOUNCE_FLAGS(state.request),
SENT_ATTR(state.msg_attr),
/* .SH Miscellaneous
/* .ad
/* .fi
-/* .IP \fBalways_bcc\fR
-/* Address to send a copy of each message that enters the system.
/* .IP \fBqueue_directory\fR
/* Top-level directory of the Postfix queue.
/* SEE ALSO
/* Application-specific. */
-char *var_always_bcc;
char *var_filter_xport;
/*
* Copy the message envelope segment. Allow only those records that we
* expect to see in the envelope section. The envelope segment must
* contain an envelope sender address.
- *
- * If the segment contains a recipient address, include the optional
- * always_bcc recipient.
*/
if ((status = copy_segment(qfile, cleanup, info, buf, REC_TYPE_ENVELOPE)) != 0)
return (status);
msg_info("%s: uid=%d from=<%s>", info->id,
(int) info->st.st_uid, info->sender);
- if (info->rcpt) {
- if (*var_always_bcc)
- rec_fputs(cleanup, REC_TYPE_RCPT, var_always_bcc);
- }
-
/*
* Message content segment. Send a dummy message length. Prepend a
* Received: header to the message contents. For tracing purposes,
* easier to implement the many possible error exits without forgetting
* to close files, or to release memory.
*/
-#define PICKUP_CLEANUP_FLAGS (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER)
+#define PICKUP_CLEANUP_FLAGS \
+ (CLEANUP_FLAG_BOUNCE | CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK)
cleanup = mail_connect_wait(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (attr_scan(cleanup, ATTR_FLAG_STRICT,
int main(int argc, char **argv)
{
static CONFIG_STR_TABLE str_table[] = {
- VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0,
0,
};
/* .SH Miscellaneous
/* .ad
/* .fi
-/* .IP \fBalways_bcc\fR
-/* Address to send a copy of each message that enters the system.
/* .IP \fBdebug_peer_level\fR
/* Increment in verbose logging level when a remote host matches a
/* pattern in the \fBdebug_peer_list\fR parameter.
*/
int var_qmqpd_timeout;
int var_qmqpd_err_sleep;
-char *var_always_bcc;
char *var_filter_xport;
char *var_qmqpd_clients;
/*
* Connect to the cleanup server. Log client name/address with queue ID.
*/
+#define QMQPD_CLEANUP_FLAGS (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK)
+
state->dest = mail_stream_service(MAIL_CLASS_PUBLIC, var_cleanup_service);
if (state->dest == 0
|| attr_print(state->dest->stream, ATTR_FLAG_NONE,
- ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, QMQPD_CLEANUP_FLAGS,
ATTR_TYPE_END) != 0)
msg_fatal("unable to connect to the %s %s service",
MAIL_CLASS_PUBLIC, var_cleanup_service);
if (state->recipient == 0)
state->recipient = mystrndup(STR(state->buf), LEN(state->buf));
}
-
- /*
- * Append the optional recipient who is copied on all mail.
- */
- if (state->err == CLEANUP_STAT_OK
- && *var_always_bcc
- && rec_fputs(state->cleanup, REC_TYPE_RCPT, var_always_bcc) < 0)
- state->err = CLEANUP_STAT_WRITE;
}
/* qmqpd_next_line - get line from buffer, return last char, newline, or -1 */
0,
};
static CONFIG_STR_TABLE str_table[] = {
- VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
VAR_FILTER_XPORT, DEF_FILTER_XPORT, &var_filter_xport, 0, 0,
VAR_QMQPD_CLIENTS, DEF_QMQPD_CLIENTS, &var_qmqpd_clients, 0, 0,
0,
/* This command is not implemented. Use the slower \fBsendmail -q\fR
/* command instead.
/* .IP \fB-t\fR
-/* Extract recipients from message headers. This requires that no
-/* recipients be specified on the command line.
+/* Extract recipients from message headers. These are added to any
+/* recipients specified on the command line.
/* .IP \fB-v\fR
/* Send an email report of all delivery attempts (mail delivery
/* always happens in the background). When multiple \fB-v\fR
#include <stringops.h>
#include <set_ugid.h>
#include <connect.h>
+#include <split_at.h>
/* Global library. */
#include <mail_stream.h>
#include <verp_sender.h>
#include <deliver_request.h>
+#include <mime_state.h>
+#include <header_opts.h>
/* Application-specific. */
* Flag parade. Flags 8-15 are reserved for delivery request trace flags.
*/
#define SM_FLAG_AEOF (1<<0) /* archaic EOF */
+#define SM_FLAG_XRCPT (1<<1) /* extract recipients from headers */
#define SM_FLAG_DEFAULT (SM_FLAG_AEOF)
*/
char *verp_delims;
+ /*
+ * Context for extracting recipients.
+ */
+typedef struct SM_STATE {
+ VSTREAM *dst; /* output stream */
+ ARGV *recipients; /* recipients from regular headers */
+ ARGV *resent_recip; /* recipients from resent headers */
+ int resent; /* resent flag */
+ const char *saved_sender; /* for error messages */
+ uid_t uid; /* for error messages */
+ VSTRING *temp; /* scratch buffer */
+} SM_STATE;
+
/*
* Silly little macros (SLMs).
*/
#define STR vstring_str
+/* output_text - output partial or complete text line */
+
+static void output_text(void *context, int rec_type, const char *buf, int len,
+ off_t unused_offset)
+{
+ SM_STATE *state = (SM_STATE *) context;
+
+ if (rec_put(state->dst, rec_type, buf, len) < 0)
+ msg_fatal_status(EX_TEMPFAIL,
+ "%s(%ld): error writing queue file: %m",
+ state->saved_sender, (long) state->uid);
+}
+
+/* output_header - output one message header */
+
+static void output_header(void *context, int header_class,
+ HEADER_OPTS *header_info,
+ VSTRING *buf, off_t offset)
+{
+ SM_STATE *state = (SM_STATE *) context;
+ TOK822 *tree;
+ TOK822 **addr_list;
+ TOK822 **tpp;
+ ARGV *rcpt;
+ char *start;
+ char *line;
+ char *next_line;
+
+ /*
+ * Pipe the unmodified message header through the header line folding
+ * routine.
+ */
+ for (line = start = STR(buf); line; line = next_line) {
+ next_line = split_at(line, '\n');
+ output_text(context, REC_TYPE_NORM, line, next_line ?
+ next_line - line - 1 : strlen(line), offset);
+ }
+
+ /*
+ * Parse the header line, and save copies of recipient addresses in the
+ * appropriate place.
+ */
+ if (header_class == MIME_HDR_PRIMARY
+ && header_info->flags & HDR_OPT_RECIP
+ && header_info->flags & HDR_OPT_EXTRACT
+ && (state->resent == 0 || (header_info->flags & HDR_OPT_RR))) {
+ if (header_info->flags & HDR_OPT_RR) {
+ rcpt = state->resent_recip;
+ if (state->resent == 0)
+ state->resent = 1;
+ } else
+ rcpt = state->recipients;
+ tree = tok822_parse(vstring_str(buf) + strlen(header_info->name) + 1);
+ addr_list = tok822_grep(tree, TOK822_ADDR);
+ for (tpp = addr_list; *tpp; tpp++) {
+ tok822_internalize(state->temp, tpp[0]->head, TOK822_STR_DEFL);
+ argv_add(rcpt, vstring_str(state->temp), (char *) 0);
+ }
+ myfree((char *) addr_list);
+ tok822_free_tree(tree);
+ }
+}
+
/* enqueue - post one message */
static void enqueue(const int flags, const char *encoding, const char *sender,
int status;
int naddr;
int prev_type;
+ MIME_STATE *mime_state = 0;
+ SM_STATE state;
+ int mime_errs;
/*
* Initialize.
}
}
} else {
+
+ /*
+ * Initialize the MIME processor and set up the callback context.
+ */
+ if (flags & SM_FLAG_XRCPT) {
+ state.dst = dst;
+ state.recipients = argv_alloc(2);
+ state.resent_recip = argv_alloc(2);
+ state.resent = 0;
+ state.saved_sender = saved_sender;
+ state.uid = uid;
+ state.temp = vstring_alloc(10);
+ mime_state = mime_state_alloc(MIME_OPT_DISABLE_MIME
+ | MIME_OPT_REPORT_TRUNC_HEADER,
+ output_header,
+ (MIME_STATE_ANY_END) 0,
+ output_text,
+ (MIME_STATE_ANY_END) 0,
+ (MIME_STATE_ERR_PRINT) 0,
+ (void *) &state);
+ }
+
+ /*
+ * Process header/body lines.
+ */
skip_from_ = 1;
strip_cr = STRIP_CR_DUNNO;
for (prev_type = 0; (type = rec_streamlf_get(VSTREAM_IN, buf, var_line_limit))
if ((flags & SM_FLAG_AEOF) && prev_type != REC_TYPE_CONT
&& VSTRING_LEN(buf) == 1 && *STR(buf) == '.')
break;
- if (REC_PUT_BUF(dst, type, buf) < 0)
- msg_fatal_status(EX_TEMPFAIL,
- "%s(%ld): error writing queue file: %m",
- saved_sender, (long) uid);
+ if (mime_state) {
+ mime_errs = mime_state_update(mime_state, type, STR(buf),
+ VSTRING_LEN(buf));
+ if (mime_errs)
+ msg_fatal_status(EX_DATAERR,
+ "%s(%ld): unable to extract recipients: %s",
+ saved_sender, (long) uid,
+ mime_state_error(mime_errs));
+ } else {
+ if (REC_PUT_BUF(dst, type, buf) < 0)
+ msg_fatal_status(EX_TEMPFAIL,
+ "%s(%ld): error writing queue file: %m",
+ saved_sender, (long) uid);
+ }
}
}
/*
- * Append an empty section for information extracted from message
- * headers. Header parsing is done by the cleanup service.
+ * Finish up MIME processing.
+ */
+ if (mime_state) {
+ mime_errs = mime_state_update(mime_state, REC_TYPE_EOF, "", 0);
+ if (mime_errs)
+ msg_fatal_status(EX_DATAERR,
+ "%s(%ld): unable to extract recipients: %s",
+ saved_sender, (long) uid,
+ mime_state_error(mime_errs));
+ mime_state = mime_state_free(mime_state);
+ }
+
+ /*
+ * Append recipient addresses that were extracted from message headers.
*/
rec_fputs(dst, REC_TYPE_XTRA, "");
+ if (flags & SM_FLAG_XRCPT) {
+ for (cpp = state.resent ? state.resent_recip->argv :
+ state.recipients->argv; *cpp; cpp++) {
+ if (rec_put(dst, REC_TYPE_RCPT, *cpp, strlen(*cpp)) < 0)
+ msg_fatal_status(EX_TEMPFAIL,
+ "%s(%ld): error writing queue file: %m",
+ saved_sender, (long) uid);
+ }
+ argv_free(state.recipients);
+ argv_free(state.resent_recip);
+ vstring_free(state.temp);
+ }
/*
* Identify the end of the queue file.
static char *full_name = 0; /* sendmail -F */
struct stat st;
char *slash;
- int extract_recipients = 0; /* sendmail -t, almost */
char *sender = 0; /* sendmail -f */
int c;
int fd;
}
break;
case 't':
- extract_recipients = 1;
+ flags |= SM_FLAG_XRCPT;
break;
case 'v':
msg_verbose++;
/*
* Look for conflicting options and arguments.
*/
- if (extract_recipients && mode != SM_MODE_ENQUEUE)
+ if ((flags & SM_FLAG_XRCPT) && mode != SM_MODE_ENQUEUE)
msg_fatal_status(EX_USAGE, "-t can be used only in delivery mode");
if (site_to_flush && mode != SM_MODE_ENQUEUE)
msg_fatal_status(EX_USAGE, "-qR can be used only in delivery mode");
- if (extract_recipients && argv[OPTIND])
- msg_fatal_status(EX_USAGE,
- "cannot handle command-line recipients with -t");
-
/*
* The -v option plays double duty. One requests verbose delivery, more
* than one requests verbose logging.
* preferred than myself. When no MX resource records exist, look up the
* addresses listed for this name.
*
+ * According to RFC 974: "It is possible that the list of MXs in the
+ * response to the query will be empty. This is a special case. If the
+ * list is empty, mailers should treat it as if it contained one RR, an
+ * MX RR with a preference value of 0, and a host name of REMOTE. (I.e.,
+ * REMOTE is its only MX). In addition, the mailer should do no further
+ * processing on the list, but should attempt to deliver the message to
+ * REMOTE."
+ *
* Normally it is OK if an MX host cannot be found in the DNS; we'll just
* use a backup one, and silently ignore the better MX host. However, if
* the best backup that we can find in the DNS is the local machine, then
request->queue_id, rcpt->orig_addr,
rcpt->address, session->namaddr,
request->arrival_time, "%s",
- translit(resp->str, "\n", " ")) == 0) {
+ translit(resp->str, "\n", " ")) == 0) {
if (request->flags & DEL_REQ_FLAG_SUCCESS)
deliver_completed(state->src, rcpt->offset);
rcpt->offset = 0; /* in case deferred */
vstring_str(state->scratch),
VSTRING_LEN(state->scratch));
if (mime_errs) {
- smtp_mesg_fail(state, 554, "MIME 7-bit conversion failed: %s",
+ smtp_mesg_fail(state, 554,
+ "MIME 7-bit conversion failed: %s",
mime_state_error(mime_errs));
RETURN(0);
}
prev_type = rec_type;
}
- if (prev_type == REC_TYPE_CONT) /* missing newline at end */
+ if (state->mime_state) {
+ mime_errs =
+ mime_state_update(state->mime_state, rec_type, "", 0);
+ if (mime_errs) {
+ smtp_mesg_fail(state, 554,
+ "MIME 7-bit conversion failed: %s",
+ mime_state_error(mime_errs));
+ RETURN(0);
+ }
+ } else if (prev_type == REC_TYPE_CONT) /* missing newline */
smtp_fputs("", 0, session->stream);
if ((state->features & SMTP_FEATURE_MAYBEPIX) != 0
&& request->arrival_time < vstream_ftime(session->stream)
send_state = next_state;
send_rcpt = next_rcpt;
}
-
RETURN(0);
}
/* .SH Miscellaneous
/* .ad
/* .fi
-/* .IP \fBalways_bcc\fR
-/* Address to send a copy of each message that enters the system.
/* .IP \fBauthorized_verp_clients\fR
/* Hostnames, domain names and/or addresses of clients that are
/* authorized to use the XVERP extension.
int var_defer_code;
int var_smtpd_err_sleep;
int var_non_fqdn_code;
-char *var_always_bcc;
char *var_error_rcpt;
int var_smtpd_delay_reject;
char *var_rest_classes;
* If running from the master or from inetd, connect to the cleanup
* service.
*/
+#define SMTPD_CLEANUP_FLAGS (CLEANUP_FLAG_FILTER | CLEANUP_FLAG_BCC_OK)
+
if (SMTPD_STAND_ALONE(state) == 0) {
state->dest = mail_stream_service(MAIL_CLASS_PUBLIC,
var_cleanup_service);
if (state->dest == 0
|| attr_print(state->dest->stream, ATTR_FLAG_NONE,
- ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER,
+ ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, SMTPD_CLEANUP_FLAGS,
ATTR_TYPE_END) != 0)
msg_fatal("unable to connect to the %s %s service",
MAIL_CLASS_PUBLIC, var_cleanup_service);
* segment, and prepend our own Received: header. If there is only one
* recipient, list the recipient address.
*/
- if (*var_always_bcc)
- rec_fputs(state->cleanup, REC_TYPE_RCPT, var_always_bcc);
rec_fputs(state->cleanup, REC_TYPE_MESG, "");
rec_fprintf(state->cleanup, REC_TYPE_NORM,
"Received: from %s (%s [%s])",
VAR_DATA_CHECKS, DEF_DATA_CHECKS, &var_data_checks, 0, 0,
VAR_MAPS_RBL_DOMAINS, DEF_MAPS_RBL_DOMAINS, &var_maps_rbl_domains, 0, 0,
VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps, 0, 0,
- VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes, 0, 0,
VAR_CANONICAL_MAPS, DEF_CANONICAL_MAPS, &var_canonical_maps, 0, 0,
bounce_append : defer_append)
(BOUNCE_FLAGS(state.request), BOUNCE_ATTR(state.msg_attr),
"maildir delivery failed: %s", vstring_str(why));
-
+ if (errno == EACCES) {
+ msg_warn("maildir access problem for UID/GID=%lu/%lu: %s",
+ (long) usr_attr.uid, (long) usr_attr.gid, vstring_str(why));
+ msg_warn("perhaps you need to create the maildirs in advance");
+ }
} else {
deliver_status = sent(BOUNCE_FLAGS(state.request),
SENT_ATTR(state.msg_attr),