mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 13:48:06 +00:00
snapshot-20010709
This commit is contained in:
committed by
Viktor Dukhovni
parent
7e8044da83
commit
a94bf41134
1
postfix/.indent.pro
vendored
1
postfix/.indent.pro
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
-TABOUNCE
|
||||||
-TALIAS_TOKEN
|
-TALIAS_TOKEN
|
||||||
-TARGV
|
-TARGV
|
||||||
-TBH_TABLE
|
-TBH_TABLE
|
||||||
|
@@ -25,7 +25,7 @@ lmtp support yes (client)
|
|||||||
m4 config no
|
m4 config no
|
||||||
mail to command yes (configurable for .forward, aliases, :include:)
|
mail to command yes (configurable for .forward, aliases, :include:)
|
||||||
mail to file yes (configurable for .forward, aliases, :include:)
|
mail to file yes (configurable for .forward, aliases, :include:)
|
||||||
maildir yes (with procmail)
|
maildir yes
|
||||||
mailertable yes (it's called transport)
|
mailertable yes (it's called transport)
|
||||||
mailq yes
|
mailq yes
|
||||||
majordomo yes (edit approve script to delete /delivered-to/i)
|
majordomo yes (edit approve script to delete /delivered-to/i)
|
||||||
@@ -38,6 +38,7 @@ nis tables yes
|
|||||||
nis+ tables not yet
|
nis+ tables not yet
|
||||||
pipeline option yes (server and client)
|
pipeline option yes (server and client)
|
||||||
pop/imap yes (with third-party daemons that use /var[/spool]/mail)
|
pop/imap yes (with third-party daemons that use /var[/spool]/mail)
|
||||||
|
qmqp server yes (with verp support)
|
||||||
rbl support yes
|
rbl support yes
|
||||||
return-receipt: not yet
|
return-receipt: not yet
|
||||||
sasl support yes (compile time option)
|
sasl support yes (compile time option)
|
||||||
@@ -55,5 +56,6 @@ user+extension yes (also: .forward+extension)
|
|||||||
user-extension yes (also: .forward-extension)
|
user-extension yes (also: .forward-extension)
|
||||||
user.lock yes (runtime configurable)
|
user.lock yes (runtime configurable)
|
||||||
uucp support yes (sends user@domain recipients)
|
uucp support yes (sends user@domain recipients)
|
||||||
|
verp support yes (delimiters are configurable)
|
||||||
virtual domains yes
|
virtual domains yes
|
||||||
year 2000 safe yes
|
year 2000 safe yes
|
||||||
|
@@ -5292,13 +5292,12 @@ Apologies for any names omitted.
|
|||||||
|
|
||||||
Cleanup: the virtual delivery agent was poorly integrated
|
Cleanup: the virtual delivery agent was poorly integrated
|
||||||
so that the SMTP server and queue manager did not reject
|
so that the SMTP server and queue manager did not reject
|
||||||
mail for unknown users. Files: smtpd/smtpd_check.c,
|
mail for unknown users. Files: smtpd/smtpd_check.c.
|
||||||
*qmgr/qmgr_message.c.
|
|
||||||
|
|
||||||
20010705
|
20010705
|
||||||
|
|
||||||
Feature: QMQP server for compatibility with the ezmlm list
|
Feature: QMQP server, compatible with qmail and the ezmlm
|
||||||
manager. Files: util/netstring.[hc], qmqpd/qmqpd*.c.
|
list manager. Files: util/netstring.[hc], qmqpd/qmqpd*.c.
|
||||||
|
|
||||||
20010706
|
20010706
|
||||||
|
|
||||||
@@ -5309,3 +5308,17 @@ Apologies for any names omitted.
|
|||||||
|
|
||||||
Bugfix: with disable_dns=yes, the SMTP client treated all
|
Bugfix: with disable_dns=yes, the SMTP client treated all
|
||||||
host lookup errors as permanent. File: smtp/smtp_addr.c.
|
host lookup errors as permanent. File: smtp/smtp_addr.c.
|
||||||
|
|
||||||
|
20010709
|
||||||
|
|
||||||
|
Feature: VERP support, based on a patch by Peng Yong, and
|
||||||
|
with the missing parts filled in so that the Postfix bounce
|
||||||
|
daemon can send one VERP bounce per undeliverable recipient.
|
||||||
|
Files: , sendmail/sendmail.c, smtpd/smtpd.c, qmgr/qmgr_deliver.c,
|
||||||
|
bounce/bounce_notify_verp.c, qmqpd/qmqpd.c, plus a couple
|
||||||
|
support routines in the global library.
|
||||||
|
|
||||||
|
Cleanup: with recipient_delimiter=+ (or any character other
|
||||||
|
than -) Postfix will now recognize address extensions even
|
||||||
|
with owner-foo+extension addresses. This is necessary to
|
||||||
|
make VERP work for mailing lists.
|
||||||
|
@@ -145,7 +145,7 @@ expect to run more than 1000 delivery processes, you may need to
|
|||||||
override the definition of the FD_SETSIZE macro to make select()
|
override the definition of the FD_SETSIZE macro to make select()
|
||||||
work correctly:
|
work correctly:
|
||||||
|
|
||||||
% make makefiles CCARGS=-FD_SETSIZE=2048
|
% make makefiles CCARGS=-DFD_SETSIZE=2048
|
||||||
|
|
||||||
In any case, if the command
|
In any case, if the command
|
||||||
|
|
||||||
|
@@ -6,8 +6,8 @@ that Postfix can be used as a backend for the Ezmlm-idx mailing
|
|||||||
list manager. This support includes qmqp-source and qmqp-sink
|
list manager. This support includes qmqp-source and qmqp-sink
|
||||||
programs for protocol stress testing.
|
programs for protocol stress testing.
|
||||||
|
|
||||||
Turning on the QMQP service
|
Turning on the Postfix QMQP service
|
||||||
===========================
|
===================================
|
||||||
|
|
||||||
To enable QMQP server support on an existing Postfix system you
|
To enable QMQP server support on an existing Postfix system you
|
||||||
have to add the following line to /etc/postfix/master.cf:
|
have to add the following line to /etc/postfix/master.cf:
|
||||||
@@ -15,8 +15,8 @@ have to add the following line to /etc/postfix/master.cf:
|
|||||||
628 inet n - n - - qmqpd
|
628 inet n - n - - qmqpd
|
||||||
|
|
||||||
|
|
||||||
QMQP server access control
|
Postfix QMQP server access control
|
||||||
==========================
|
==================================
|
||||||
|
|
||||||
By default, the QMQP server does not accept mail from any client.
|
By default, the QMQP server does not accept mail from any client.
|
||||||
This is because the QMQP server relays mail to any destination
|
This is because the QMQP server relays mail to any destination
|
||||||
@@ -37,3 +37,9 @@ instead.
|
|||||||
Patterns are separated by whitespace and/or commas. In order to
|
Patterns are separated by whitespace and/or commas. In order to
|
||||||
reverse the result, precede a non-file name pattern with an
|
reverse the result, precede a non-file name pattern with an
|
||||||
exclamation point (!).
|
exclamation point (!).
|
||||||
|
|
||||||
|
Setting up Ezmlm-idx to use Postfix QMQP support
|
||||||
|
================================================
|
||||||
|
|
||||||
|
You need to list the Postfix IP address in a suitable configuration
|
||||||
|
file. See the ezmlm-idx documentation for details.
|
@@ -1,17 +1,33 @@
|
|||||||
Incompatible changes with snapshot-20010707
|
Incompatible changes with snapshot-20010709
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
The SMTP client by default breaks lines > 2048 characters, in order
|
This release introduces a new queue file record type that is used
|
||||||
to avoid problems with mail delivery to fragile SMTP server software.
|
only for messages that actually use VERP (variable envelope return
|
||||||
To get the old behavior, specify "smtp_break_lines = no" in the
|
path) support. With this sole exception, the queue file format is
|
||||||
Postfix main.cf file.
|
entirely backwards compatible with previous Postfix releases.
|
||||||
|
|
||||||
Major changes with snapshot-20010707
|
The SMTP client now by default breaks lines > 2048 characters, to
|
||||||
|
avoid mail delivery problems with fragile SMTP server software.
|
||||||
|
To get the old behavior back, specify "smtp_break_lines = no" in
|
||||||
|
the Postfix main.cf file.
|
||||||
|
|
||||||
|
With recipient_delimiter=+ (or any character other than -) Postfix
|
||||||
|
will now recognize address extensions even with owner-foo+extension
|
||||||
|
addresses. This change was necessary to make VERP useful for mailing
|
||||||
|
list bounce processing.
|
||||||
|
|
||||||
|
Major changes with snapshot-20010709
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
QMQP server support, so that Postfix can be used as a backend mailer
|
QMQP server support, so that Postfix can be used as a backend mailer
|
||||||
for the Ezmlm-idx mailing list manager. The service is disabled by
|
for the ezmlm-idx mailing list manager. You still need qmail to
|
||||||
default. To enable, follow instructions in the README_QMQP file.
|
drive ezmlm and to process mailing list bounces. The QMQP service
|
||||||
|
is disabled by default. To enable, follow the instructions in the
|
||||||
|
QMQP_README file.
|
||||||
|
|
||||||
|
VERP (variable envelope return path) support. This is enabled by
|
||||||
|
default. See the VERP_README file for instructions. These instructions
|
||||||
|
need more examples for how to process bounces automatically.
|
||||||
|
|
||||||
You can now reject unknown virtual(8) recipients at the SMTP port
|
You can now reject unknown virtual(8) recipients at the SMTP port
|
||||||
by specifying a "domain.name whatever" entry in the tables specified
|
by specifying a "domain.name whatever" entry in the tables specified
|
||||||
|
96
postfix/VERP_README
Normal file
96
postfix/VERP_README
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
Postfix VERP support
|
||||||
|
====================
|
||||||
|
|
||||||
|
Postfix supports variable envelope return path addresses, which
|
||||||
|
means that each recipient receives a customized copy of the message,
|
||||||
|
with the recipient address encoded in the envelope sender address.
|
||||||
|
This concept was popularized by the qmail MTA and by the ezmlm
|
||||||
|
mailing list manager.
|
||||||
|
|
||||||
|
When VERP style delivery is requested, Postfix delivers mail with
|
||||||
|
sender address prefix@origin for a recipient user@domain, with a
|
||||||
|
sender address that encodes the recipient as follows:
|
||||||
|
|
||||||
|
prefix+user=domain@origin
|
||||||
|
|
||||||
|
so that undeliverable mail reveals what address was undeliverable.
|
||||||
|
|
||||||
|
The + and = are the default VERP delimiters. You can specify non-
|
||||||
|
default delimiters in main.cf with the default_verp_delimiters
|
||||||
|
configuration parameter (default value: +=). Specify two characters;
|
||||||
|
the first delimiter should match the $recipient_delimiter setting.
|
||||||
|
|
||||||
|
Using VERP with majordomo etc. mailing lists
|
||||||
|
============================================
|
||||||
|
|
||||||
|
In order to make VERP useful with majordomo etc. mailing lists,
|
||||||
|
you would configure the list manager to submit mail as:
|
||||||
|
|
||||||
|
sendmail -V -f owner-listname other-arguments...
|
||||||
|
|
||||||
|
This text assumes that you have set up an owner-listname alias that
|
||||||
|
routes undeliverable mail to a real person:
|
||||||
|
|
||||||
|
/etc/aliases:
|
||||||
|
owner-listname: yourname+listname
|
||||||
|
|
||||||
|
In order to process bounces we are going to make extensive use of
|
||||||
|
address extension tricks.
|
||||||
|
|
||||||
|
You need to tell Postfix that + is the separator between an address
|
||||||
|
and its optional address extension, that address extensions are
|
||||||
|
appended to .forward file names, and that address extensions are
|
||||||
|
to be discarded when doing alias expansions:
|
||||||
|
|
||||||
|
/etc/postfix/main.cf:
|
||||||
|
recipient_delimiter = +
|
||||||
|
forward_path = $home/.forward${recipient_delimiter}${extension},$home/.forward
|
||||||
|
propagate_unmatched_extensions = canonical, virtual
|
||||||
|
|
||||||
|
(the last two parameter settings are default settings).
|
||||||
|
|
||||||
|
You need to set up a file named .forward+listname with the commands
|
||||||
|
that process all the mail that is sent to the owner-listname address:
|
||||||
|
|
||||||
|
~/.forward+listname:
|
||||||
|
"|/some/where/command ..."
|
||||||
|
|
||||||
|
With this set up, undeliverable mail for user@domain will be returned
|
||||||
|
to the following address:
|
||||||
|
|
||||||
|
owner-listname+user=domain@your.domain
|
||||||
|
|
||||||
|
which is processed by the command in your .forward+listname file.
|
||||||
|
|
||||||
|
It is left as an exercise for the reader to parse the To: header
|
||||||
|
line and to pull out the user=domain part from the recipient address.
|
||||||
|
|
||||||
|
VERP support in the Postfix SMTP server
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
The Postfix SMTP server has a new command XVERP to enable VERP
|
||||||
|
style delivery. The syntax allows two forms:
|
||||||
|
|
||||||
|
MAIL FROM:<sender@domain> XVERP
|
||||||
|
MAIL FROM:<sender@domain> XVERP=xy
|
||||||
|
|
||||||
|
where x and y are the VERP delimiters. When no VERP delimiters
|
||||||
|
are specified, Postfix uses the two characters specified with the
|
||||||
|
default_verp_delimiters configuration parameter.
|
||||||
|
|
||||||
|
VERP support in the Postfix sendmail command
|
||||||
|
============================================
|
||||||
|
|
||||||
|
The Postfix sendmail command has a -V flag to request VERP style
|
||||||
|
delivery. It is not possible to override the default VERP delimiters.
|
||||||
|
|
||||||
|
VERP support in the Postfix QMQP server
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
When the Postfix QMQP server receives mail with a an envelope sender
|
||||||
|
address of the form:
|
||||||
|
|
||||||
|
prefix-@origin-@[]
|
||||||
|
|
||||||
|
Postfix generates VERP sender addresses using prefix@domain as the
|
||||||
|
original sender address, and using "-=" as the VERP delimiters.
|
@@ -94,33 +94,38 @@ SENDMAIL(1) SENDMAIL(1)
|
|||||||
<b>-U</b> (ignored)
|
<b>-U</b> (ignored)
|
||||||
Initial user submission.
|
Initial user submission.
|
||||||
|
|
||||||
<b>-bd</b> Go into daemon mode. This mode of operation is
|
<b>-V</b> Variable Envelope Return Path. Given an envelope
|
||||||
|
sender address <i>prefix</i>-@<i>origin</i>, each recipient
|
||||||
|
<i>user@domain</i> receives mail with a personalized enve-
|
||||||
|
lope sender address <i>prefix</i><b>-</b><i>user=domain</i>@<i>origin</i>.
|
||||||
|
|
||||||
|
<b>-bd</b> Go into daemon mode. This mode of operation is
|
||||||
implemented by executing the <b>postfix</b> <b>start</b> command.
|
implemented by executing the <b>postfix</b> <b>start</b> command.
|
||||||
|
|
||||||
<b>-bi</b> Initialize alias database. See the <b>newaliases</b> com-
|
<b>-bi</b> Initialize alias database. See the <b>newaliases</b> com-
|
||||||
mand above.
|
mand above.
|
||||||
|
|
||||||
<b>-bm</b> Read mail from standard input and arrange for
|
<b>-bm</b> Read mail from standard input and arrange for
|
||||||
delivery. This is the default mode of operation.
|
delivery. This is the default mode of operation.
|
||||||
|
|
||||||
<b>-bp</b> List the mail queue. See the <b>mailq</b> command above.
|
<b>-bp</b> List the mail queue. See the <b>mailq</b> command above.
|
||||||
|
|
||||||
<b>-bs</b> Stand-alone SMTP server mode. Read SMTP commands
|
<b>-bs</b> Stand-alone SMTP server mode. Read SMTP commands
|
||||||
from standard input, and write responses to stan-
|
from standard input, and write responses to stan-
|
||||||
dard output. This mode of operation is implemented
|
dard output. This mode of operation is implemented
|
||||||
by running the <a href="smtpd.8.html"><b>smtpd</b>(8)</a> daemon.
|
by running the <a href="smtpd.8.html"><b>smtpd</b>(8)</a> daemon.
|
||||||
|
|
||||||
<b>-f</b> <i>sender</i>
|
<b>-f</b> <i>sender</i>
|
||||||
Set the envelope sender address. This is the
|
Set the envelope sender address. This is the
|
||||||
address where delivery problems are sent to, unless
|
address where delivery problems are sent to, unless
|
||||||
the message contains an <b>Errors-To:</b> message header.
|
the message contains an <b>Errors-To:</b> message header.
|
||||||
|
|
||||||
<b>-h</b> <i>hop_count</i> (ignored)
|
<b>-h</b> <i>hop_count</i> (ignored)
|
||||||
Hop count limit. Use the <b>hopcount</b><i>_</i><b>limit</b> configura-
|
Hop count limit. Use the <b>hopcount</b><i>_</i><b>limit</b> configura-
|
||||||
tion parameter instead.
|
tion parameter instead.
|
||||||
|
|
||||||
<b>-i</b> When reading a message from standard input, don't
|
<b>-i</b> When reading a message from standard input, don't
|
||||||
treat a line with only a <b>.</b> character as the end of
|
treat a line with only a <b>.</b> character as the end of
|
||||||
input.
|
input.
|
||||||
|
|
||||||
<b>-m</b> (ignored)
|
<b>-m</b> (ignored)
|
||||||
@@ -130,68 +135,68 @@ SENDMAIL(1) SENDMAIL(1)
|
|||||||
Backwards compatibility.
|
Backwards compatibility.
|
||||||
|
|
||||||
<b>-oA</b><i>alias_database</i>
|
<b>-oA</b><i>alias_database</i>
|
||||||
Non-default alias database. Specify <i>pathname</i> or
|
Non-default alias database. Specify <i>pathname</i> or
|
||||||
<i>type</i>:<i>pathname</i>. See <a href="postalias.1.html"><b>postalias</b>(1)</a> for details.
|
<i>type</i>:<i>pathname</i>. See <a href="postalias.1.html"><b>postalias</b>(1)</a> for details.
|
||||||
|
|
||||||
<b>-o7</b> (ignored)
|
<b>-o7</b> (ignored)
|
||||||
|
|
||||||
<b>-o8</b> (ignored)
|
<b>-o8</b> (ignored)
|
||||||
The message body type. Currently, Postfix imple-
|
The message body type. Currently, Postfix imple-
|
||||||
ments <b>just-send-eight</b>.
|
ments <b>just-send-eight</b>.
|
||||||
|
|
||||||
<b>-oi</b> When reading a message from standard input, don't
|
<b>-oi</b> When reading a message from standard input, don't
|
||||||
treat a line with only a <b>.</b> character as the end of
|
treat a line with only a <b>.</b> character as the end of
|
||||||
input.
|
input.
|
||||||
|
|
||||||
<b>-om</b> (ignored)
|
<b>-om</b> (ignored)
|
||||||
The sender is never eliminated from alias etc.
|
The sender is never eliminated from alias etc.
|
||||||
expansions.
|
expansions.
|
||||||
|
|
||||||
<b>-o</b> <i>x</i> <i>value</i> (ignored)
|
<b>-o</b> <i>x</i> <i>value</i> (ignored)
|
||||||
Set option <i>x</i> to <i>value</i>. Use the equivalent configu-
|
Set option <i>x</i> to <i>value</i>. Use the equivalent configu-
|
||||||
ration parameter in <b>main.cf</b> instead.
|
ration parameter in <b>main.cf</b> instead.
|
||||||
|
|
||||||
<b>-r</b> <i>sender</i>
|
<b>-r</b> <i>sender</i>
|
||||||
Set the envelope sender address. This is the
|
Set the envelope sender address. This is the
|
||||||
address where delivery problems are sent to, unless
|
address where delivery problems are sent to, unless
|
||||||
the message contains an <b>Errors-To:</b> message header.
|
the message contains an <b>Errors-To:</b> message header.
|
||||||
|
|
||||||
<b>-q</b> Attempt to deliver all queued mail. This is imple-
|
<b>-q</b> Attempt to deliver all queued mail. This is imple-
|
||||||
mented by kicking the <a href="qmgr.8.html"><b>qmgr</b>(8)</a> daemon.
|
mented by kicking the <a href="qmgr.8.html"><b>qmgr</b>(8)</a> daemon.
|
||||||
|
|
||||||
<b>-q</b><i>interval</i> (ignored)
|
<b>-q</b><i>interval</i> (ignored)
|
||||||
The interval between queue runs. Use the
|
The interval between queue runs. Use the
|
||||||
<b>queue</b><i>_</i><b>run</b><i>_</i><b>delay</b> configuration parameter instead.
|
<b>queue</b><i>_</i><b>run</b><i>_</i><b>delay</b> configuration parameter instead.
|
||||||
|
|
||||||
<b>-qR</b><i>site</i>
|
<b>-qR</b><i>site</i>
|
||||||
Schedule immediate delivery of all mail that is
|
Schedule immediate delivery of all mail that is
|
||||||
queued for the named <i>site</i>. Depending on the desti-
|
queued for the named <i>site</i>. Depending on the desti-
|
||||||
nation, this uses "fast flush" service, or it has
|
nation, this uses "fast flush" service, or it has
|
||||||
the same effect as <b>sendmail</b> <b>-q</b>. This is imple-
|
the same effect as <b>sendmail</b> <b>-q</b>. This is imple-
|
||||||
mented by connecting to the local SMTP server. See
|
mented by connecting to the local SMTP server. See
|
||||||
<a href="smtpd.8.html"><b>smtpd</b>(8)</a> for more information about the "fast
|
<a href="smtpd.8.html"><b>smtpd</b>(8)</a> for more information about the "fast
|
||||||
flush" service.
|
flush" service.
|
||||||
|
|
||||||
<b>-qS</b><i>site</i>
|
<b>-qS</b><i>site</i>
|
||||||
This command is not implemented. Use the slower
|
This command is not implemented. Use the slower
|
||||||
<b>sendmail</b> <b>-q</b> command instead.
|
<b>sendmail</b> <b>-q</b> command instead.
|
||||||
|
|
||||||
<b>-t</b> Extract recipients from message headers. This
|
<b>-t</b> Extract recipients from message headers. This
|
||||||
requires that no recipients be specified on the
|
requires that no recipients be specified on the
|
||||||
command line.
|
command line.
|
||||||
|
|
||||||
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
|
<b>-v</b> Enable verbose logging for debugging purposes. Mul-
|
||||||
tiple <b>-v</b> options make the software increasingly
|
tiple <b>-v</b> options make the software increasingly
|
||||||
verbose.
|
verbose.
|
||||||
|
|
||||||
<b>SECURITY</b>
|
<b>SECURITY</b>
|
||||||
By design, this program is not set-user (or group) id.
|
By design, this program is not set-user (or group) id.
|
||||||
However, it must handle data from untrusted users or
|
However, it must handle data from untrusted users or
|
||||||
untrusted machines. Thus, the usual precautions need to
|
untrusted machines. Thus, the usual precautions need to
|
||||||
be taken against malicious inputs.
|
be taken against malicious inputs.
|
||||||
|
|
||||||
<b>DIAGNOSTICS</b>
|
<b>DIAGNOSTICS</b>
|
||||||
Problems are logged to <b>syslogd</b>(8) and to the standard
|
Problems are logged to <b>syslogd</b>(8) and to the standard
|
||||||
error stream.
|
error stream.
|
||||||
|
|
||||||
<b>ENVIRONMENT</b>
|
<b>ENVIRONMENT</b>
|
||||||
@@ -203,7 +208,7 @@ SENDMAIL(1) SENDMAIL(1)
|
|||||||
|
|
||||||
<b>MAIL</b><i>_</i><b>DEBUG</b>
|
<b>MAIL</b><i>_</i><b>DEBUG</b>
|
||||||
Enable debugging with an external command, as spec-
|
Enable debugging with an external command, as spec-
|
||||||
ified with the <b>debugger</b><i>_</i><b>command</b> configuration
|
ified with the <b>debugger</b><i>_</i><b>command</b> configuration
|
||||||
parameter.
|
parameter.
|
||||||
|
|
||||||
<b>FILES</b>
|
<b>FILES</b>
|
||||||
@@ -211,13 +216,13 @@ SENDMAIL(1) SENDMAIL(1)
|
|||||||
/etc/postfix, configuration files
|
/etc/postfix, configuration files
|
||||||
|
|
||||||
<b>CONFIGURATION</b> <b>PARAMETERS</b>
|
<b>CONFIGURATION</b> <b>PARAMETERS</b>
|
||||||
See the Postfix <b>main.cf</b> file for syntax details and for
|
See the Postfix <b>main.cf</b> file for syntax details and for
|
||||||
default values. Use the <b>postfix</b> <b>reload</b> command after a
|
default values. Use the <b>postfix</b> <b>reload</b> command after a
|
||||||
configuration change.
|
configuration change.
|
||||||
|
|
||||||
<b>alias</b><i>_</i><b>database</b>
|
<b>alias</b><i>_</i><b>database</b>
|
||||||
Default alias database(s) for <b>newaliases</b>. The
|
Default alias database(s) for <b>newaliases</b>. The
|
||||||
default value for this parameter is system-spe-
|
default value for this parameter is system-spe-
|
||||||
cific.
|
cific.
|
||||||
|
|
||||||
<b>bounce</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
<b>bounce</b><i>_</i><b>size</b><i>_</i><b>limit</b>
|
||||||
@@ -233,55 +238,55 @@ SENDMAIL(1) SENDMAIL(1)
|
|||||||
initialized.
|
initialized.
|
||||||
|
|
||||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b>
|
<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>
|
host matches a pattern in the <b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||||
parameter.
|
parameter.
|
||||||
|
|
||||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>list</b>
|
||||||
List of domain or network patterns. When a remote
|
List of domain or network patterns. When a remote
|
||||||
host matches a pattern, increase the verbose log-
|
host matches a pattern, increase the verbose log-
|
||||||
ging level by the amount specified in the
|
ging level by the amount specified in the
|
||||||
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
|
<b>debug</b><i>_</i><b>peer</b><i>_</i><b>level</b> parameter.
|
||||||
|
|
||||||
<b>fast</b><i>_</i><b>flush</b><i>_</i><b>domains</b>
|
<b>fast</b><i>_</i><b>flush</b><i>_</i><b>domains</b>
|
||||||
List of domains that will receive "fast flush" ser-
|
List of domains that will receive "fast flush" ser-
|
||||||
vice (default: all domains that this system is
|
vice (default: all domains that this system is
|
||||||
willing to relay mail to). This greatly improves
|
willing to relay mail to). This greatly improves
|
||||||
the performance of the SMTP <b>ETRN</b> request, and of
|
the performance of the SMTP <b>ETRN</b> request, and of
|
||||||
the <b>sendmail</b> <b>-qR</b> command. For domains not in the
|
the <b>sendmail</b> <b>-qR</b> command. For domains not in the
|
||||||
list, Postfix simply attempts to deliver all queued
|
list, Postfix simply attempts to deliver all queued
|
||||||
mail.
|
mail.
|
||||||
|
|
||||||
<b>fork</b><i>_</i><b>attempts</b>
|
<b>fork</b><i>_</i><b>attempts</b>
|
||||||
Number of attempts to <b>fork</b>() a process before giv-
|
Number of attempts to <b>fork</b>() a process before giv-
|
||||||
ing up.
|
ing up.
|
||||||
|
|
||||||
<b>fork</b><i>_</i><b>delay</b>
|
<b>fork</b><i>_</i><b>delay</b>
|
||||||
Delay in seconds between successive <b>fork</b>()
|
Delay in seconds between successive <b>fork</b>()
|
||||||
attempts.
|
attempts.
|
||||||
|
|
||||||
<b>hopcount</b><i>_</i><b>limit</b>
|
<b>hopcount</b><i>_</i><b>limit</b>
|
||||||
Limit the number of <b>Received:</b> message headers.
|
Limit the number of <b>Received:</b> message headers.
|
||||||
|
|
||||||
<b>mail</b><i>_</i><b>owner</b>
|
<b>mail</b><i>_</i><b>owner</b>
|
||||||
The owner of the mail queue and of most Postfix
|
The owner of the mail queue and of most Postfix
|
||||||
processes.
|
processes.
|
||||||
|
|
||||||
<b>command</b><i>_</i><b>directory</b>
|
<b>command</b><i>_</i><b>directory</b>
|
||||||
Directory with Postfix support commands (default:
|
Directory with Postfix support commands (default:
|
||||||
<b>$program</b><i>_</i><b>directory</b>).
|
<b>$program</b><i>_</i><b>directory</b>).
|
||||||
|
|
||||||
<b>daemon</b><i>_</i><b>directory</b>
|
<b>daemon</b><i>_</i><b>directory</b>
|
||||||
Directory with Postfix daemon programs (default:
|
Directory with Postfix daemon programs (default:
|
||||||
<b>$program</b><i>_</i><b>directory</b>).
|
<b>$program</b><i>_</i><b>directory</b>).
|
||||||
|
|
||||||
<b>queue</b><i>_</i><b>directory</b>
|
<b>queue</b><i>_</i><b>directory</b>
|
||||||
Top-level directory of the Postfix queue. This is
|
Top-level directory of the Postfix queue. This is
|
||||||
also the root directory of Postfix daemons that run
|
also the root directory of Postfix daemons that run
|
||||||
chrooted.
|
chrooted.
|
||||||
|
|
||||||
<b>queue</b><i>_</i><b>run</b><i>_</i><b>delay</b>
|
<b>queue</b><i>_</i><b>run</b><i>_</i><b>delay</b>
|
||||||
The time between successive scans of the deferred
|
The time between successive scans of the deferred
|
||||||
queue.
|
queue.
|
||||||
|
|
||||||
<b>SEE</b> <b>ALSO</b>
|
<b>SEE</b> <b>ALSO</b>
|
||||||
@@ -297,7 +302,7 @@ SENDMAIL(1) SENDMAIL(1)
|
|||||||
syslogd(8) system logging
|
syslogd(8) system logging
|
||||||
|
|
||||||
<b>LICENSE</b>
|
<b>LICENSE</b>
|
||||||
The Secure Mailer license must be distributed with this
|
The Secure Mailer license must be distributed with this
|
||||||
software.
|
software.
|
||||||
|
|
||||||
<b>AUTHOR(S)</b>
|
<b>AUTHOR(S)</b>
|
||||||
|
@@ -35,8 +35,8 @@ SMTPD(8) SMTPD(8)
|
|||||||
<b>STANDARDS</b>
|
<b>STANDARDS</b>
|
||||||
<a href="http://www.faqs.org/rfcs/rfc821.html">RFC 821</a> (SMTP protocol)
|
<a href="http://www.faqs.org/rfcs/rfc821.html">RFC 821</a> (SMTP protocol)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1123.html">RFC 1123</a> (Host requirements)
|
<a href="http://www.faqs.org/rfcs/rfc1123.html">RFC 1123</a> (Host requirements)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1651.html">RFC 1651</a> (SMTP service extensions)
|
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1652.html">RFC 1652</a> (8bit-MIME transport)
|
<a href="http://www.faqs.org/rfcs/rfc1652.html">RFC 1652</a> (8bit-MIME transport)
|
||||||
|
<a href="http://www.faqs.org/rfcs/rfc1869.html">RFC 1869</a> (SMTP service extensions)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1854.html">RFC 1854</a> (SMTP Pipelining)
|
<a href="http://www.faqs.org/rfcs/rfc1854.html">RFC 1854</a> (SMTP Pipelining)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1870.html">RFC 1870</a> (Message Size Declaration)
|
<a href="http://www.faqs.org/rfcs/rfc1870.html">RFC 1870</a> (Message Size Declaration)
|
||||||
<a href="http://www.faqs.org/rfcs/rfc1985.html">RFC 1985</a> (ETRN command)
|
<a href="http://www.faqs.org/rfcs/rfc1985.html">RFC 1985</a> (ETRN command)
|
||||||
|
@@ -82,6 +82,11 @@ Log mailer traffic. Use the \fBdebug_peer_list\fR and
|
|||||||
\fBdebug_peer_level\fR configuration parameters instead.
|
\fBdebug_peer_level\fR configuration parameters instead.
|
||||||
.IP "\fB-U\fR (ignored)"
|
.IP "\fB-U\fR (ignored)"
|
||||||
Initial user submission.
|
Initial user submission.
|
||||||
|
.IP \fB-V\fR
|
||||||
|
Variable Envelope Return Path. Given an envelope sender address
|
||||||
|
\fIprefix\fR-@\fIorigin\fR, each recipient \fIuser@domain\fR
|
||||||
|
receives mail with a personalized envelope sender address
|
||||||
|
\fIprefix\fB-\fIuser=domain\fR@\fIorigin\fR.
|
||||||
.IP \fB-bd\fR
|
.IP \fB-bd\fR
|
||||||
Go into daemon mode. This mode of operation is implemented by
|
Go into daemon mode. This mode of operation is implemented by
|
||||||
executing the \fBpostfix start\fR command.
|
executing the \fBpostfix start\fR command.
|
||||||
|
@@ -42,8 +42,8 @@ run chrooted at fixed low privilege.
|
|||||||
.nf
|
.nf
|
||||||
RFC 821 (SMTP protocol)
|
RFC 821 (SMTP protocol)
|
||||||
RFC 1123 (Host requirements)
|
RFC 1123 (Host requirements)
|
||||||
RFC 1651 (SMTP service extensions)
|
|
||||||
RFC 1652 (8bit-MIME transport)
|
RFC 1652 (8bit-MIME transport)
|
||||||
|
RFC 1869 (SMTP service extensions)
|
||||||
RFC 1854 (SMTP Pipelining)
|
RFC 1854 (SMTP Pipelining)
|
||||||
RFC 1870 (Message Size Declaration)
|
RFC 1870 (Message Size Declaration)
|
||||||
RFC 1985 (ETRN command)
|
RFC 1985 (ETRN command)
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
SRCS = bounce.c bounce_append_service.c bounce_notify_service.c \
|
SRCS = bounce.c bounce_append_service.c bounce_notify_service.c \
|
||||||
bounce_cleanup.c bounce_notify_util.c
|
bounce_cleanup.c bounce_notify_util.c bounce_notify_verp.c
|
||||||
OBJS = bounce.o bounce_append_service.o bounce_notify_service.o \
|
OBJS = bounce.o bounce_append_service.o bounce_notify_service.o \
|
||||||
bounce_cleanup.o bounce_notify_util.o
|
bounce_cleanup.o bounce_notify_util.o bounce_notify_verp.o
|
||||||
HDRS =
|
HDRS =
|
||||||
TESTSRC =
|
TESTSRC =
|
||||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||||
@@ -69,6 +69,7 @@ bounce.o: ../../include/mail_queue.h
|
|||||||
bounce.o: ../../include/mail_params.h
|
bounce.o: ../../include/mail_params.h
|
||||||
bounce.o: ../../include/mail_conf.h
|
bounce.o: ../../include/mail_conf.h
|
||||||
bounce.o: ../../include/bounce.h
|
bounce.o: ../../include/bounce.h
|
||||||
|
bounce.o: ../../include/mail_addr.h
|
||||||
bounce.o: ../../include/mail_server.h
|
bounce.o: ../../include/mail_server.h
|
||||||
bounce.o: bounce_service.h
|
bounce.o: bounce_service.h
|
||||||
bounce.o: ../../include/bounce_log.h
|
bounce.o: ../../include/bounce_log.h
|
||||||
@@ -133,3 +134,18 @@ bounce_notify_util.o: ../../include/name_mask.h
|
|||||||
bounce_notify_util.o: ../../include/bounce_log.h
|
bounce_notify_util.o: ../../include/bounce_log.h
|
||||||
bounce_notify_util.o: ../../include/mail_date.h
|
bounce_notify_util.o: ../../include/mail_date.h
|
||||||
bounce_notify_util.o: bounce_service.h
|
bounce_notify_util.o: bounce_service.h
|
||||||
|
bounce_notify_verp.o: bounce_notify_verp.c
|
||||||
|
bounce_notify_verp.o: ../../include/sys_defs.h
|
||||||
|
bounce_notify_verp.o: ../../include/msg.h
|
||||||
|
bounce_notify_verp.o: ../../include/vstream.h
|
||||||
|
bounce_notify_verp.o: ../../include/vbuf.h
|
||||||
|
bounce_notify_verp.o: ../../include/name_mask.h
|
||||||
|
bounce_notify_verp.o: ../../include/mail_params.h
|
||||||
|
bounce_notify_verp.o: ../../include/mail_queue.h
|
||||||
|
bounce_notify_verp.o: ../../include/vstring.h
|
||||||
|
bounce_notify_verp.o: ../../include/post_mail.h
|
||||||
|
bounce_notify_verp.o: ../../include/cleanup_user.h
|
||||||
|
bounce_notify_verp.o: ../../include/mail_addr.h
|
||||||
|
bounce_notify_verp.o: ../../include/mail_error.h
|
||||||
|
bounce_notify_verp.o: bounce_service.h
|
||||||
|
bounce_notify_verp.o: ../../include/bounce_log.h
|
||||||
|
@@ -80,6 +80,11 @@
|
|||||||
/* System library. */
|
/* System library. */
|
||||||
|
|
||||||
#include <sys_defs.h>
|
#include <sys_defs.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef STRCASECMP_IN_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
@@ -95,6 +100,7 @@
|
|||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <mail_conf.h>
|
#include <mail_conf.h>
|
||||||
#include <bounce.h>
|
#include <bounce.h>
|
||||||
|
#include <mail_addr.h>
|
||||||
|
|
||||||
/* Single-threaded server skeleton. */
|
/* Single-threaded server skeleton. */
|
||||||
|
|
||||||
@@ -122,6 +128,7 @@ static VSTRING *queue_id;
|
|||||||
static VSTRING *queue_name;
|
static VSTRING *queue_name;
|
||||||
static VSTRING *recipient;
|
static VSTRING *recipient;
|
||||||
static VSTRING *sender;
|
static VSTRING *sender;
|
||||||
|
static VSTRING *verp_delims;
|
||||||
static VSTRING *why;
|
static VSTRING *why;
|
||||||
|
|
||||||
#define STR vstring_str
|
#define STR vstring_str
|
||||||
@@ -199,7 +206,62 @@ static int bounce_notify_proto(char *service_name, VSTREAM *client, int flush)
|
|||||||
* Execute the request.
|
* Execute the request.
|
||||||
*/
|
*/
|
||||||
return (bounce_notify_service(service_name, STR(queue_name),
|
return (bounce_notify_service(service_name, STR(queue_name),
|
||||||
STR(queue_id), STR(sender), flush));
|
STR(queue_id), STR(sender), flush));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bounce_verp_proto - bounce_notify server protocol, VERP style */
|
||||||
|
|
||||||
|
static int bounce_verp_proto(char *service_name, VSTREAM *client, int flush)
|
||||||
|
{
|
||||||
|
char *myname="bounce_verp_proto";
|
||||||
|
int flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read and validate the client request.
|
||||||
|
*/
|
||||||
|
if (mail_command_read(client, "%d %s %s %s %s",
|
||||||
|
&flags, queue_name, queue_id,
|
||||||
|
sender, verp_delims) != 5) {
|
||||||
|
msg_warn("malformed request");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (mail_queue_name_ok(STR(queue_name)) == 0) {
|
||||||
|
msg_warn("malformed queue name: %s", printable(STR(queue_name), '?'));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (mail_queue_id_ok(STR(queue_id)) == 0) {
|
||||||
|
msg_warn("malformed queue id: %s", printable(STR(queue_id), '?'));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (strlen(STR(verp_delims)) != 2) {
|
||||||
|
msg_warn("malformed verp delimiter string: %s",
|
||||||
|
printable(STR(verp_delims), '?'));
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: service=%s queue=%s id=%s sender=%s delim=%s",
|
||||||
|
myname, service_name, STR(queue_name), STR(queue_id),
|
||||||
|
STR(sender), STR(verp_delims));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On request by the client, set up a trap to delete the log file in case
|
||||||
|
* of errors.
|
||||||
|
*/
|
||||||
|
if (flags & BOUNCE_FLAG_CLEAN)
|
||||||
|
bounce_cleanup_register(service_name, STR(queue_id));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Execute the request. Fall back to traditional notification if a bounce
|
||||||
|
* was returned as undeliverable, because we don't want to VERPify those.
|
||||||
|
*/
|
||||||
|
if (!*STR(sender) || !strcasecmp(STR(sender), mail_addr_double_bounce())) {
|
||||||
|
msg_warn("request to send VERP-style notification of bounced mail");
|
||||||
|
return (bounce_notify_service(service_name, STR(queue_name),
|
||||||
|
STR(queue_id), STR(sender), flush));
|
||||||
|
} else
|
||||||
|
return (bounce_notify_verp(service_name, STR(queue_name),
|
||||||
|
STR(queue_id), STR(sender),
|
||||||
|
STR(verp_delims), flush));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* bounce_service - parse bounce command type and delegate */
|
/* bounce_service - parse bounce command type and delegate */
|
||||||
@@ -228,6 +290,8 @@ static void bounce_service(VSTREAM *client, char *service_name, char **argv)
|
|||||||
if (mail_scan(client, "%d", &command) != 1) {
|
if (mail_scan(client, "%d", &command) != 1) {
|
||||||
msg_warn("malformed request");
|
msg_warn("malformed request");
|
||||||
status = -1;
|
status = -1;
|
||||||
|
} else if (command == BOUNCE_CMD_VERP) {
|
||||||
|
status = bounce_verp_proto(service_name, client, REALLY_BOUNCE);
|
||||||
} else if (command == BOUNCE_CMD_FLUSH) {
|
} else if (command == BOUNCE_CMD_FLUSH) {
|
||||||
status = bounce_notify_proto(service_name, client, REALLY_BOUNCE);
|
status = bounce_notify_proto(service_name, client, REALLY_BOUNCE);
|
||||||
} else if (command == BOUNCE_CMD_WARN) {
|
} else if (command == BOUNCE_CMD_WARN) {
|
||||||
@@ -271,6 +335,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
|
|||||||
queue_name = vstring_alloc(10);
|
queue_name = vstring_alloc(10);
|
||||||
recipient = vstring_alloc(10);
|
recipient = vstring_alloc(10);
|
||||||
sender = vstring_alloc(10);
|
sender = vstring_alloc(10);
|
||||||
|
verp_delims = vstring_alloc(10);
|
||||||
why = vstring_alloc(10);
|
why = vstring_alloc(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -199,7 +199,7 @@ BOUNCE_INFO *bounce_mail_init(const char *service, const char *queue_name,
|
|||||||
*/
|
*/
|
||||||
if ((bounce_info->log_handle = bounce_log_open(bounce_info->service,
|
if ((bounce_info->log_handle = bounce_log_open(bounce_info->service,
|
||||||
bounce_info->queue_id,
|
bounce_info->queue_id,
|
||||||
O_RDONLY, 0)) == 0
|
O_RDWR, 0)) == 0
|
||||||
&& errno != ENOENT)
|
&& errno != ENOENT)
|
||||||
msg_fatal("open %s %s: %m", bounce_info->service,
|
msg_fatal("open %s %s: %m", bounce_info->service,
|
||||||
bounce_info->queue_id);
|
bounce_info->queue_id);
|
||||||
|
210
postfix/src/bounce/bounce_notify_verp.c
Normal file
210
postfix/src/bounce/bounce_notify_verp.c
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* bounce_notify_verp 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* send non-delivery report to sender, server side
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include "bounce_service.h"
|
||||||
|
/*
|
||||||
|
/* int bounce_notify_verp(service, queue_name, queue_id, sender,
|
||||||
|
/* verp_delims, flush)
|
||||||
|
/* char *queue_name;
|
||||||
|
/* char *queue_id;
|
||||||
|
/* char *sender;
|
||||||
|
/* char *verp_delims;
|
||||||
|
/* int flush;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* This module implements the server side of the bounce_notify()
|
||||||
|
/* (send bounce message) request. If flush is zero, the logfile
|
||||||
|
/* is not removed, and a warning is sent instead of a bounce.
|
||||||
|
/* The bounce recipient address is encoded in VERP format.
|
||||||
|
/* This routine must be used for single bounces only.
|
||||||
|
/*
|
||||||
|
/* When a message bounces, a full copy is sent to the originator,
|
||||||
|
/* and an optional copy of the diagnostics with message headers is
|
||||||
|
/* sent to the postmaster. The result is non-zero when the operation
|
||||||
|
/* should be tried again.
|
||||||
|
/*
|
||||||
|
/* When a bounce is sent, the sender address is the empty
|
||||||
|
/* address.
|
||||||
|
/* DIAGNOSTICS
|
||||||
|
/* Fatal error: error opening existing file. Warnings: corrupt
|
||||||
|
/* message file. A corrupt message is saved to the "corrupt"
|
||||||
|
/* queue for further inspection.
|
||||||
|
/* SEE ALSO
|
||||||
|
/* bounce(3) basic bounce service client interface
|
||||||
|
/* 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 <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#ifdef STRCASECMP_IN_STRINGS_H
|
||||||
|
#include <strings.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <msg.h>
|
||||||
|
#include <vstream.h>
|
||||||
|
#include <name_mask.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <mail_params.h>
|
||||||
|
#include <mail_queue.h>
|
||||||
|
#include <post_mail.h>
|
||||||
|
#include <mail_addr.h>
|
||||||
|
#include <mail_error.h>
|
||||||
|
#include <verp_sender.h>
|
||||||
|
|
||||||
|
/* Application-specific. */
|
||||||
|
|
||||||
|
#include "bounce_service.h"
|
||||||
|
|
||||||
|
#define STR vstring_str
|
||||||
|
|
||||||
|
/* bounce_notify_verp - send a bounce */
|
||||||
|
|
||||||
|
int bounce_notify_verp(char *service, char *queue_name,
|
||||||
|
char *queue_id, char *recipient,
|
||||||
|
char *verp_delims, int flush)
|
||||||
|
{
|
||||||
|
char *myname = "bounce_notify_verp";
|
||||||
|
BOUNCE_INFO *bounce_info;
|
||||||
|
int bounce_status = 0;
|
||||||
|
int postmaster_status;
|
||||||
|
VSTREAM *bounce;
|
||||||
|
int notify_mask = name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
|
||||||
|
var_notify_classes);
|
||||||
|
char *postmaster;
|
||||||
|
VSTRING *verp_buf = vstring_alloc(100);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sanity checks. We must be called only for undeliverable non-bounce
|
||||||
|
* messages.
|
||||||
|
*/
|
||||||
|
if (*recipient == 0)
|
||||||
|
msg_panic("%s: attempt to bounce a single bounce", myname);
|
||||||
|
if (strcasecmp(recipient, mail_addr_double_bounce()) == 0)
|
||||||
|
msg_panic("%s: attempt to bounce a double bounce", myname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize. Open queue file, bounce log, etc.
|
||||||
|
*/
|
||||||
|
bounce_info = bounce_mail_init(service, queue_name, queue_id, flush);
|
||||||
|
|
||||||
|
#define NULL_SENDER MAIL_ADDR_EMPTY /* special address */
|
||||||
|
#define NULL_CLEANUP_FLAGS 0
|
||||||
|
#define BOUNCE_HEADERS 1
|
||||||
|
#define BOUNCE_ALL 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A non-bounce message was returned. Send a single bounce, one per
|
||||||
|
* recipient.
|
||||||
|
*/
|
||||||
|
while (bounce_log_read(bounce_info->log_handle) != 0) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Notify the originator.
|
||||||
|
*/
|
||||||
|
verp_sender(verp_buf, verp_delims, recipient,
|
||||||
|
bounce_info->log_handle->recipient);
|
||||||
|
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, STR(verp_buf),
|
||||||
|
NULL_CLEANUP_FLAGS)) != 0) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send the bounce message header, some boilerplate text that
|
||||||
|
* pretends that we are a polite mail system, the text with
|
||||||
|
* reason for the bounce, and a copy of the original message.
|
||||||
|
*/
|
||||||
|
if (bounce_header(bounce, bounce_info, STR(verp_buf)) == 0
|
||||||
|
&& bounce_boilerplate(bounce, bounce_info) == 0
|
||||||
|
&& bounce_recipient_log(bounce, bounce_info) == 0
|
||||||
|
&& bounce_header_dsn(bounce, bounce_info) == 0
|
||||||
|
&& bounce_recipient_dsn(bounce, bounce_info) == 0)
|
||||||
|
bounce_original(bounce, bounce_info, flush ?
|
||||||
|
BOUNCE_ALL : BOUNCE_HEADERS);
|
||||||
|
bounce_status = post_mail_fclose(bounce);
|
||||||
|
} else
|
||||||
|
bounce_status = 1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stop at the first sign of trouble, instead of making the problem
|
||||||
|
* worse.
|
||||||
|
*/
|
||||||
|
if (bounce_status != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark this recipient as done.
|
||||||
|
*/
|
||||||
|
bounce_log_delrcpt(bounce_info->log_handle);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Optionally, send a postmaster notice.
|
||||||
|
*
|
||||||
|
* This postmaster notice is not critical, so if it fails don't
|
||||||
|
* retransmit the bounce that we just generated, just log a warning.
|
||||||
|
*/
|
||||||
|
#define WANT_IF_BOUNCE (flush == 1 && (notify_mask & MAIL_ERROR_BOUNCE))
|
||||||
|
#define WANT_IF_DELAY (flush == 0 && (notify_mask & MAIL_ERROR_DELAY))
|
||||||
|
|
||||||
|
if (WANT_IF_BOUNCE || WANT_IF_DELAY) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send the text with reason for the bounce, and the headers of
|
||||||
|
* the original message. Don't bother sending the boiler-plate
|
||||||
|
* text. This postmaster notice is not critical, so if it fails
|
||||||
|
* don't retransmit the bounce that we just generated, just log a
|
||||||
|
* warning.
|
||||||
|
*/
|
||||||
|
postmaster = flush ? var_bounce_rcpt : var_delay_rcpt;
|
||||||
|
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
||||||
|
postmaster,
|
||||||
|
NULL_CLEANUP_FLAGS)) != 0) {
|
||||||
|
if (bounce_header(bounce, bounce_info, postmaster) == 0
|
||||||
|
&& bounce_recipient_log(bounce, bounce_info) == 0
|
||||||
|
&& bounce_header_dsn(bounce, bounce_info) == 0
|
||||||
|
&& bounce_recipient_dsn(bounce, bounce_info) == 0)
|
||||||
|
bounce_original(bounce, bounce_info, BOUNCE_HEADERS);
|
||||||
|
postmaster_status = post_mail_fclose(bounce);
|
||||||
|
} else
|
||||||
|
postmaster_status = 1;
|
||||||
|
|
||||||
|
if (postmaster_status)
|
||||||
|
msg_warn("postmaster notice failed while bouncing to %s",
|
||||||
|
recipient);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Examine the completion status. Delete the bounce log file only when
|
||||||
|
* the bounce was posted successfully, and only if we are bouncing for
|
||||||
|
* real, not just warning.
|
||||||
|
*/
|
||||||
|
if (flush != 0 && bounce_status == 0 && mail_queue_remove(service, queue_id)
|
||||||
|
&& errno != ENOENT)
|
||||||
|
msg_fatal("remove %s %s: %m", service, queue_id);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cleanup.
|
||||||
|
*/
|
||||||
|
bounce_mail_free(bounce_info);
|
||||||
|
vstring_free(verp_buf);
|
||||||
|
|
||||||
|
return (bounce_status);
|
||||||
|
}
|
@@ -28,6 +28,11 @@ extern int bounce_append_service(char *, char *, char *, char *);
|
|||||||
*/
|
*/
|
||||||
extern int bounce_notify_service(char *, char *, char *, char *, int);
|
extern int bounce_notify_service(char *, char *, char *, char *, int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bounce_notify_verp.c
|
||||||
|
*/
|
||||||
|
extern int bounce_notify_verp(char *, char *, char *, char *, char *, int);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bounce_cleanup.c
|
* bounce_cleanup.c
|
||||||
*/
|
*/
|
||||||
@@ -51,7 +56,7 @@ typedef struct {
|
|||||||
VSTREAM *orig_fp; /* open queue file */
|
VSTREAM *orig_fp; /* open queue file */
|
||||||
long orig_offs; /* start of content */
|
long orig_offs; /* start of content */
|
||||||
time_t arrival_time; /* time of arrival */
|
time_t arrival_time; /* time of arrival */
|
||||||
BOUNCE_LOG *log_handle; /* open logfile */
|
BOUNCE_LOG *log_handle; /* open logfile */
|
||||||
} BOUNCE_INFO;
|
} BOUNCE_INFO;
|
||||||
|
|
||||||
extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, int);
|
extern BOUNCE_INFO *bounce_mail_init(const char *, const char *, const char *, int);
|
||||||
|
@@ -179,6 +179,20 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf,
|
|||||||
state->errs |= CLEANUP_STAT_BAD;
|
state->errs |= CLEANUP_STAT_BAD;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (type == REC_TYPE_VERP) {
|
||||||
|
if (state->sender == 0 || *state->sender == 0) {
|
||||||
|
state->errs |= CLEANUP_STAT_BAD;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (len == 0) {
|
||||||
|
buf = var_verp_delim;
|
||||||
|
len = strlen(buf);
|
||||||
|
}
|
||||||
|
if (len == 2) {
|
||||||
|
cleanup_out(state, type, buf, len);
|
||||||
|
} else {
|
||||||
|
state->errs |= CLEANUP_STAT_BAD;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cleanup_out(state, type, buf, len);
|
cleanup_out(state, type, buf, len);
|
||||||
}
|
}
|
||||||
|
@@ -106,6 +106,7 @@ char *var_prop_extension; /* propagate unmatched extension */
|
|||||||
char *var_always_bcc; /* big brother */
|
char *var_always_bcc; /* big brother */
|
||||||
int var_extra_rcpt_limit; /* recipient extract limit */
|
int var_extra_rcpt_limit; /* recipient extract limit */
|
||||||
char *var_rcpt_witheld; /* recipients not disclosed */
|
char *var_rcpt_witheld; /* recipients not disclosed */
|
||||||
|
char *var_verp_delim; /* default VERP delimiters */
|
||||||
|
|
||||||
CONFIG_INT_TABLE cleanup_int_table[] = {
|
CONFIG_INT_TABLE cleanup_int_table[] = {
|
||||||
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
|
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
|
||||||
@@ -133,6 +134,7 @@ CONFIG_STR_TABLE cleanup_str_table[] = {
|
|||||||
VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
|
VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0,
|
||||||
VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
|
VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0,
|
||||||
VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 1, 0,
|
VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 1, 0,
|
||||||
|
VAR_VERP_DELIM, DEF_VERP_DELIM, &var_verp_delim, 2, 2,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -18,7 +18,8 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
|
|||||||
sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
|
sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
|
||||||
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
|
timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
|
||||||
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
|
tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
|
||||||
flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c
|
flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
|
||||||
|
verp_sender.c
|
||||||
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
||||||
debug_peer.o debug_process.o defer.o deliver_completed.o \
|
debug_peer.o debug_process.o defer.o deliver_completed.o \
|
||||||
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
|
deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
|
||||||
@@ -38,7 +39,8 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
|||||||
sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
|
sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
|
||||||
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
|
timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
|
||||||
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
|
tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
|
||||||
flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o
|
flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
|
||||||
|
verp_sender.o
|
||||||
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
||||||
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
|
config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
|
||||||
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
|
deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
|
||||||
@@ -54,7 +56,7 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
|||||||
recipient_list.h record.h resolve_clnt.h resolve_local.h \
|
recipient_list.h record.h resolve_clnt.h resolve_local.h \
|
||||||
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
|
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
|
||||||
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
|
sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
|
||||||
mbox_conf.h mbox_open.h abounce.h qmqp_proto.h
|
mbox_conf.h mbox_open.h abounce.h qmqp_proto.h verp_sender.h
|
||||||
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
TESTSRC = rec2stream.c stream2rec.c recdump.c
|
||||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||||
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
-Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
|
||||||
@@ -1036,6 +1038,11 @@ tok822_tree.o: ../../include/vstring.h
|
|||||||
tok822_tree.o: ../../include/vbuf.h
|
tok822_tree.o: ../../include/vbuf.h
|
||||||
tok822_tree.o: tok822.h
|
tok822_tree.o: tok822.h
|
||||||
tok822_tree.o: resolve_clnt.h
|
tok822_tree.o: resolve_clnt.h
|
||||||
|
verp_sender.o: verp_sender.c
|
||||||
|
verp_sender.o: ../../include/sys_defs.h
|
||||||
|
verp_sender.o: ../../include/vstring.h
|
||||||
|
verp_sender.o: ../../include/vbuf.h
|
||||||
|
verp_sender.o: verp_sender.h
|
||||||
xtext.o: xtext.c
|
xtext.o: xtext.c
|
||||||
xtext.o: ../../include/sys_defs.h
|
xtext.o: ../../include/sys_defs.h
|
||||||
xtext.o: ../../include/vstream.h
|
xtext.o: ../../include/vstream.h
|
||||||
|
@@ -14,6 +14,15 @@
|
|||||||
/* void (*callback)(int status, char *context);
|
/* void (*callback)(int status, char *context);
|
||||||
/* char *context;
|
/* char *context;
|
||||||
/*
|
/*
|
||||||
|
/* void abounce_flush_verp(flags, queue, id, sender, verp, callback, context)
|
||||||
|
/* int flags;
|
||||||
|
/* const char *queue;
|
||||||
|
/* const char *id;
|
||||||
|
/* const char *sender;
|
||||||
|
/* const char *verp;
|
||||||
|
/* void (*callback)(int status, char *context);
|
||||||
|
/* char *context;
|
||||||
|
/*
|
||||||
/* void adefer_flush(flags, queue, id, sender, callback, context)
|
/* void adefer_flush(flags, queue, id, sender, callback, context)
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* const char *queue;
|
/* const char *queue;
|
||||||
@@ -22,6 +31,15 @@
|
|||||||
/* void (*callback)(int status, char *context);
|
/* void (*callback)(int status, char *context);
|
||||||
/* char *context;
|
/* char *context;
|
||||||
/*
|
/*
|
||||||
|
/* void adefer_flush_verp(flags, queue, id, sender, verp, callback, context)
|
||||||
|
/* int flags;
|
||||||
|
/* const char *queue;
|
||||||
|
/* const char *id;
|
||||||
|
/* const char *sender;
|
||||||
|
/* const char *verp;
|
||||||
|
/* void (*callback)(int status, char *context);
|
||||||
|
/* char *context;
|
||||||
|
/*
|
||||||
/* void adefer_warn(flags, queue, id, sender, callback, context)
|
/* void adefer_warn(flags, queue, id, sender, callback, context)
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* const char *queue;
|
/* const char *queue;
|
||||||
@@ -38,10 +56,16 @@
|
|||||||
/* the specified sender, including the bounce log that was
|
/* the specified sender, including the bounce log that was
|
||||||
/* built with bounce_append().
|
/* built with bounce_append().
|
||||||
/*
|
/*
|
||||||
|
/* abounce_flush_verp() is like abounce_flush() but sends
|
||||||
|
/* one VERP style notification per undeliverable recipient.
|
||||||
|
/*
|
||||||
/* adefer_flush() bounces the specified message to
|
/* adefer_flush() bounces the specified message to
|
||||||
/* the specified sender, including the defer log that was
|
/* the specified sender, including the defer log that was
|
||||||
/* built with defer_append().
|
/* built with defer_append().
|
||||||
/*
|
/*
|
||||||
|
/* adefer_flush_verp() is like adefer_flush() but sends
|
||||||
|
/* one VERP style notification per undeliverable recipient.
|
||||||
|
/*
|
||||||
/* adefer_warn() sends a "mail is delayed" notification to
|
/* adefer_warn() sends a "mail is delayed" notification to
|
||||||
/* the specified sender, including the defer log that was
|
/* the specified sender, including the defer log that was
|
||||||
/* built with defer_append().
|
/* built with defer_append().
|
||||||
@@ -64,6 +88,8 @@
|
|||||||
/* file has the same name as the original message file.
|
/* file has the same name as the original message file.
|
||||||
/* .IP sender
|
/* .IP sender
|
||||||
/* The sender envelope address.
|
/* The sender envelope address.
|
||||||
|
/* .IP verp
|
||||||
|
/* VERP delimiter characters.
|
||||||
/* .IP callback
|
/* .IP callback
|
||||||
/* Name of a routine that receives the notification status as
|
/* Name of a routine that receives the notification status as
|
||||||
/* documented for bounce_flush() or defer_flush().
|
/* documented for bounce_flush() or defer_flush().
|
||||||
@@ -148,6 +174,60 @@ static void abounce_event(int unused_event, char *context)
|
|||||||
abounce_done(ap, mail_scan(ap->fp, "%d", &status) == 1 ? status : -1);
|
abounce_done(ap, mail_scan(ap->fp, "%d", &status) == 1 ? status : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* abounce_request_verp - suspend pseudo thread until server reply event */
|
||||||
|
|
||||||
|
static void abounce_request_verp(const char *class, const char *service,
|
||||||
|
int command, int flags,
|
||||||
|
const char *queue, const char *id,
|
||||||
|
const char *sender, const char *verp,
|
||||||
|
ABOUNCE_FN callback,
|
||||||
|
char *context)
|
||||||
|
{
|
||||||
|
ABOUNCE *ap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Save pseudo thread state. Connect to the server. Send the request and
|
||||||
|
* suspend the pseudo thread until the server replies (or dies).
|
||||||
|
*/
|
||||||
|
ap = (ABOUNCE *) mymalloc(sizeof(*ap));
|
||||||
|
ap->command = command;
|
||||||
|
ap->flags = flags;
|
||||||
|
ap->id = mystrdup(id);
|
||||||
|
ap->callback = callback;
|
||||||
|
ap->context = context;
|
||||||
|
ap->fp = mail_connect_wait(class, service);
|
||||||
|
|
||||||
|
if (mail_print(ap->fp, "%d %d %s %s %s %s %s", command,
|
||||||
|
flags, queue, id, sender, verp, MAIL_EOF) == 0
|
||||||
|
&& vstream_fflush(ap->fp) == 0) {
|
||||||
|
event_enable_read(vstream_fileno(ap->fp), abounce_event, (char *) ap);
|
||||||
|
} else {
|
||||||
|
abounce_done(ap, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* abounce_flush_verp - asynchronous bounce flush */
|
||||||
|
|
||||||
|
void abounce_flush_verp(int flags, const char *queue, const char *id,
|
||||||
|
const char *sender, const char *verp,
|
||||||
|
ABOUNCE_FN callback, char *context)
|
||||||
|
{
|
||||||
|
abounce_request_verp(MAIL_CLASS_PRIVATE, MAIL_SERVICE_BOUNCE,
|
||||||
|
BOUNCE_CMD_VERP, flags, queue, id, sender, verp,
|
||||||
|
callback, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adefer_flush_verp - asynchronous defer flush */
|
||||||
|
|
||||||
|
void adefer_flush_verp(int flags, const char *queue, const char *id,
|
||||||
|
const char *sender, const char *verp,
|
||||||
|
ABOUNCE_FN callback, char *context)
|
||||||
|
{
|
||||||
|
abounce_request_verp(MAIL_CLASS_PRIVATE, MAIL_SERVICE_DEFER,
|
||||||
|
BOUNCE_CMD_VERP, flags, queue, id, sender, verp,
|
||||||
|
callback, context);
|
||||||
|
}
|
||||||
|
|
||||||
/* abounce_request - suspend pseudo thread until server reply event */
|
/* abounce_request - suspend pseudo thread until server reply event */
|
||||||
|
|
||||||
static void abounce_request(const char *class, const char *service,
|
static void abounce_request(const char *class, const char *service,
|
||||||
|
@@ -25,6 +25,9 @@ extern void abounce_flush(int, const char *, const char *, const char *, ABOUNCE
|
|||||||
extern void adefer_flush(int, const char *, const char *, const char *, ABOUNCE_FN, char *);
|
extern void adefer_flush(int, const char *, const char *, const char *, ABOUNCE_FN, char *);
|
||||||
extern void adefer_warn(int, const char *, const char *, const char *, ABOUNCE_FN, char *);
|
extern void adefer_warn(int, const char *, const char *, const char *, ABOUNCE_FN, char *);
|
||||||
|
|
||||||
|
extern void abounce_flush_verp(int, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *);
|
||||||
|
extern void adefer_flush_verp(int, const char *, const char *, const char *, const char *, ABOUNCE_FN, char *);
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@@ -40,8 +40,8 @@ extern int vbounce_recip(int, const char *, const char *, const char *,
|
|||||||
*/
|
*/
|
||||||
#define BOUNCE_CMD_APPEND 0 /* append log */
|
#define BOUNCE_CMD_APPEND 0 /* append log */
|
||||||
#define BOUNCE_CMD_FLUSH 1 /* send log */
|
#define BOUNCE_CMD_FLUSH 1 /* send log */
|
||||||
#define BOUNCE_CMD_WARN 2 /* send warning bounce, don't delete
|
#define BOUNCE_CMD_WARN 2 /* send warning, don't delete log */
|
||||||
* log */
|
#define BOUNCE_CMD_VERP 3 /* send log, verp style */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flags.
|
* Flags.
|
||||||
|
@@ -24,6 +24,9 @@
|
|||||||
/* BOUNCE_LOG *bounce_log_read(bp)
|
/* BOUNCE_LOG *bounce_log_read(bp)
|
||||||
/* BOUNCE_LOG *bp;
|
/* BOUNCE_LOG *bp;
|
||||||
/*
|
/*
|
||||||
|
/* BOUNCE_LOG *bounce_log_delrcpt(bp)
|
||||||
|
/* BOUNCE_LOG *bp;
|
||||||
|
/*
|
||||||
/* void bounce_log_rewind(bp)
|
/* void bounce_log_rewind(bp)
|
||||||
/* BOUNCE_LOG *bp;
|
/* BOUNCE_LOG *bp;
|
||||||
/*
|
/*
|
||||||
@@ -31,8 +34,7 @@
|
|||||||
/* BOUNCE_LOG *bp;
|
/* BOUNCE_LOG *bp;
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* This module implements a bounce/defer logfile API. Information
|
/* This module implements a bounce/defer logfile API. Information
|
||||||
/* is sanitized for control and non-ASCII characters. Currently,
|
/* is sanitized for control and non-ASCII characters.
|
||||||
/* only the reading end is implemented.
|
|
||||||
/*
|
/*
|
||||||
/* bounce_log_open() opens the named bounce or defer logfile
|
/* bounce_log_open() opens the named bounce or defer logfile
|
||||||
/* and returns a handle that must be used for further access.
|
/* and returns a handle that must be used for further access.
|
||||||
@@ -47,6 +49,9 @@
|
|||||||
/* bounce_log_read() returns a null pointer when no recipient was read,
|
/* bounce_log_read() returns a null pointer when no recipient was read,
|
||||||
/* otherwise it returns its argument.
|
/* otherwise it returns its argument.
|
||||||
/*
|
/*
|
||||||
|
/* bounce_log_delrcpt() marks the last accessed recipient record as
|
||||||
|
/* "deleted". This requires that the logfile is opened for update.
|
||||||
|
/*
|
||||||
/* bounce_log_rewind() is a helper that seeks to the first recipient
|
/* bounce_log_rewind() is a helper that seeks to the first recipient
|
||||||
/* in an open bounce or defer logfile (skipping over recipients that
|
/* in an open bounce or defer logfile (skipping over recipients that
|
||||||
/* are marked as done). The result is 0 in case of success, -1 in case
|
/* are marked as done). The result is 0 in case of success, -1 in case
|
||||||
@@ -92,6 +97,7 @@
|
|||||||
#include <sys_defs.h>
|
#include <sys_defs.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
/* Utility library. */
|
/* Utility library. */
|
||||||
|
|
||||||
@@ -133,6 +139,7 @@ BOUNCE_LOG *bounce_log_open(const char *queue_name, const char *queue_id,
|
|||||||
bp->fp = fp;
|
bp->fp = fp;
|
||||||
bp->buf = vstring_alloc(100);
|
bp->buf = vstring_alloc(100);
|
||||||
bp->status = STREQ(queue_name, MAIL_QUEUE_DEFER) ? "4.0.0" : "5.0.0";
|
bp->status = STREQ(queue_name, MAIL_QUEUE_DEFER) ? "4.0.0" : "5.0.0";
|
||||||
|
bp->offset = 0;
|
||||||
return (bp);
|
return (bp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,7 +152,8 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
|
|||||||
char *text;
|
char *text;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
while (vstring_get_nonl(bp->buf, bp->fp) != VSTREAM_EOF) {
|
while ((bp->offset = vstream_ftell(bp->fp)),
|
||||||
|
(vstring_get_nonl(bp->buf, bp->fp) != VSTREAM_EOF)) {
|
||||||
|
|
||||||
if (STR(bp->buf)[0] == 0)
|
if (STR(bp->buf)[0] == 0)
|
||||||
continue;
|
continue;
|
||||||
@@ -155,6 +163,12 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
|
|||||||
*/
|
*/
|
||||||
cp = printable(STR(bp->buf), '?');
|
cp = printable(STR(bp->buf), '?');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip over deleted recipients.
|
||||||
|
*/
|
||||||
|
if (*cp == BOUNCE_LOG_STAT_DELETED)
|
||||||
|
continue;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the recipient address.
|
* Find the recipient address.
|
||||||
*/
|
*/
|
||||||
@@ -185,6 +199,21 @@ BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *bp)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bounce_log_delrcpt - mark recipient record as deleted */
|
||||||
|
|
||||||
|
BOUNCE_LOG *bounce_log_delrcpt(BOUNCE_LOG *bp)
|
||||||
|
{
|
||||||
|
long current_offset;
|
||||||
|
|
||||||
|
current_offset = vstream_ftell(bp->fp);
|
||||||
|
if (vstream_fseek(bp->fp, bp->offset, SEEK_SET) < 0)
|
||||||
|
msg_fatal("bounce logfile %s seek error: %m", VSTREAM_PATH(bp->fp));
|
||||||
|
VSTREAM_PUTC(BOUNCE_LOG_STAT_DELETED, bp->fp);
|
||||||
|
if (vstream_fseek(bp->fp, current_offset, SEEK_SET) < 0)
|
||||||
|
msg_fatal("bounce logfile %s seek error: %m", VSTREAM_PATH(bp->fp));
|
||||||
|
return (bp);
|
||||||
|
}
|
||||||
|
|
||||||
/* bounce_log_close - close bounce reader stream */
|
/* bounce_log_close - close bounce reader stream */
|
||||||
|
|
||||||
int bounce_log_close(BOUNCE_LOG *bp)
|
int bounce_log_close(BOUNCE_LOG *bp)
|
||||||
|
@@ -28,14 +28,18 @@ typedef struct {
|
|||||||
const char *recipient; /* final recipient */
|
const char *recipient; /* final recipient */
|
||||||
const char *status; /* recipient status */
|
const char *status; /* recipient status */
|
||||||
const char *text; /* why undeliverable */
|
const char *text; /* why undeliverable */
|
||||||
|
long offset; /* start of current record */
|
||||||
} BOUNCE_LOG;
|
} BOUNCE_LOG;
|
||||||
|
|
||||||
extern BOUNCE_LOG *bounce_log_open(const char *, const char *, int, int);
|
extern BOUNCE_LOG *bounce_log_open(const char *, const char *, int, int);
|
||||||
extern BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *);
|
extern BOUNCE_LOG *bounce_log_read(BOUNCE_LOG *);
|
||||||
|
extern BOUNCE_LOG *bounce_log_delrcpt(BOUNCE_LOG *);
|
||||||
extern int bounce_log_close(BOUNCE_LOG *);
|
extern int bounce_log_close(BOUNCE_LOG *);
|
||||||
|
|
||||||
#define bounce_log_rewind(bp) vstream_fseek((bp)->fp, 0L, SEEK_SET)
|
#define bounce_log_rewind(bp) vstream_fseek((bp)->fp, 0L, SEEK_SET)
|
||||||
|
|
||||||
|
#define BOUNCE_LOG_STAT_DELETED 'D' /* deleted record */
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@@ -1271,6 +1271,14 @@ extern int var_qmqpd_timeout;
|
|||||||
#define DEF_QMTPD_ERR_SLEEP "5s"
|
#define DEF_QMTPD_ERR_SLEEP "5s"
|
||||||
extern int var_qmqpd_err_sleep;
|
extern int var_qmqpd_err_sleep;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VERP, more DJB intellectual cross-pollination. However, we prefer + as
|
||||||
|
* the default recipient delimiter.
|
||||||
|
*/
|
||||||
|
#define VAR_VERP_DELIM "default_verp_delimiters"
|
||||||
|
#define DEF_VERP_DELIM "+="
|
||||||
|
extern char *var_verp_delim;
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
@@ -15,7 +15,7 @@
|
|||||||
* Version of this program.
|
* Version of this program.
|
||||||
*/
|
*/
|
||||||
#define VAR_MAIL_VERSION "mail_version"
|
#define VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "Snapshot-20010707"
|
#define DEF_MAIL_VERSION "Snapshot-20010709"
|
||||||
extern char *var_mail_version;
|
extern char *var_mail_version;
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
|
@@ -56,6 +56,7 @@ REC_TYPE_NAME rec_type_names[] = {
|
|||||||
REC_TYPE_RRTO, "return_receipt",
|
REC_TYPE_RRTO, "return_receipt",
|
||||||
REC_TYPE_ERTO, "errors_to",
|
REC_TYPE_ERTO, "errors_to",
|
||||||
REC_TYPE_PRIO, "priority",
|
REC_TYPE_PRIO, "priority",
|
||||||
|
REC_TYPE_VERP, "verp_delimiters",
|
||||||
REC_TYPE_END, "message_end",
|
REC_TYPE_END, "message_end",
|
||||||
0, 0,
|
0, 0,
|
||||||
};
|
};
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#define REC_TYPE_RRTO 'r' /* return-receipt, from headers */
|
#define REC_TYPE_RRTO 'r' /* return-receipt, from headers */
|
||||||
#define REC_TYPE_ERTO 'e' /* errors-to, from headers */
|
#define REC_TYPE_ERTO 'e' /* errors-to, from headers */
|
||||||
#define REC_TYPE_PRIO 'P' /* priority */
|
#define REC_TYPE_PRIO 'P' /* priority */
|
||||||
|
#define REC_TYPE_VERP 'V' /* VERP delimiters */
|
||||||
|
|
||||||
#define REC_TYPE_END 'E' /* terminator, required */
|
#define REC_TYPE_END 'E' /* terminator, required */
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@
|
|||||||
* record groups. The first member in each set is the record type that
|
* record groups. The first member in each set is the record type that
|
||||||
* indicates the end of that record group.
|
* indicates the end of that record group.
|
||||||
*/
|
*/
|
||||||
#define REC_TYPE_ENVELOPE "MCTFILSDRW"
|
#define REC_TYPE_ENVELOPE "MCTFILSDRWV"
|
||||||
#define REC_TYPE_CONTENT "XLN"
|
#define REC_TYPE_CONTENT "XLN"
|
||||||
#define REC_TYPE_EXTRACT "EDRPre"
|
#define REC_TYPE_EXTRACT "EDRPre"
|
||||||
#define REC_TYPE_NOEXTRACT "E"
|
#define REC_TYPE_NOEXTRACT "E"
|
||||||
|
@@ -67,7 +67,7 @@ char *split_addr(char *localpart, int delimiter)
|
|||||||
/*
|
/*
|
||||||
* Backwards compatibility: don't split owner-foo or foo-request.
|
* Backwards compatibility: don't split owner-foo or foo-request.
|
||||||
*/
|
*/
|
||||||
if (var_ownreq_special != 0) {
|
if (delimiter == '-' && var_ownreq_special != 0) {
|
||||||
if (strncasecmp(localpart, "owner-", 6) == 0)
|
if (strncasecmp(localpart, "owner-", 6) == 0)
|
||||||
return (0);
|
return (0);
|
||||||
if ((len = strlen(localpart) - 8) > 0
|
if ((len = strlen(localpart) - 8) > 0
|
||||||
|
83
postfix/src/global/verp_sender.c
Normal file
83
postfix/src/global/verp_sender.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* verp_sender 3
|
||||||
|
/* SUMMARY
|
||||||
|
/* quote local part of mailbox
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include <verp_sender.h>
|
||||||
|
/*
|
||||||
|
/* VSTRING *verp_sender(dst, delims, sender, recipient)
|
||||||
|
/* VSTRING *dst;
|
||||||
|
/* const char *delims;
|
||||||
|
/* const char *sender;
|
||||||
|
/* const char *recipient;
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* verp_sender() encodes the recipient address in the sender
|
||||||
|
/* address, using the specified delimiters. For example,
|
||||||
|
/* with delims +=, sender \fIprefix@origin\fR, and
|
||||||
|
/* recipient \fIuser@domain\fR the result is
|
||||||
|
/* \fIprefix+user=domain@origin\fR.
|
||||||
|
/*
|
||||||
|
/* Arguments:
|
||||||
|
/* .IP dst
|
||||||
|
/* The result. The buffer is null terminated.
|
||||||
|
/* .IP delims
|
||||||
|
/* VERP formatting characters.
|
||||||
|
/* .IP sender
|
||||||
|
/* Sender envelope address.
|
||||||
|
/* .IP recipient
|
||||||
|
/* Recipient envelope address.
|
||||||
|
/* 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>
|
||||||
|
|
||||||
|
/* Utility library. */
|
||||||
|
|
||||||
|
#include <vstring.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <verp_sender.h>
|
||||||
|
|
||||||
|
/* verp_sender - encode recipient into envelope sender address */
|
||||||
|
|
||||||
|
VSTRING *verp_sender(VSTRING *buf, const char *delimiters,
|
||||||
|
const char *sender, const char *recipient)
|
||||||
|
{
|
||||||
|
int send_local_len;
|
||||||
|
int rcpt_local_len;
|
||||||
|
const char *cp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change prefix@origin into prefix+user=domain@origin.
|
||||||
|
*/
|
||||||
|
send_local_len = ((cp = strrchr(sender, '@')) ?
|
||||||
|
cp - sender : strlen(sender));
|
||||||
|
rcpt_local_len = ((cp = strrchr(recipient, '@')) ?
|
||||||
|
cp - recipient : strlen(recipient));
|
||||||
|
vstring_strncpy(buf, sender, send_local_len);
|
||||||
|
VSTRING_ADDCH(buf, delimiters[0] & 0xff);
|
||||||
|
vstring_strncat(buf, recipient, rcpt_local_len);
|
||||||
|
if (recipient[rcpt_local_len] && recipient[rcpt_local_len + 1]) {
|
||||||
|
VSTRING_ADDCH(buf, delimiters[1] & 0xff);
|
||||||
|
vstring_strcat(buf, recipient + rcpt_local_len + 1);
|
||||||
|
}
|
||||||
|
if (sender[send_local_len] && sender[send_local_len + 1]) {
|
||||||
|
VSTRING_ADDCH(buf, '@');
|
||||||
|
vstring_strcat(buf, sender + send_local_len + 1);
|
||||||
|
}
|
||||||
|
VSTRING_TERMINATE(buf);
|
||||||
|
return (buf);
|
||||||
|
}
|
35
postfix/src/global/verp_sender.h
Normal file
35
postfix/src/global/verp_sender.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef _VERP_SENDER_H_INCLUDED_
|
||||||
|
#define _VERP_SENDER_H_INCLUDED_
|
||||||
|
|
||||||
|
/*++
|
||||||
|
/* NAME
|
||||||
|
/* verp_sender 3h
|
||||||
|
/* SUMMARY
|
||||||
|
/* encode recipient into sender, VERP style
|
||||||
|
/* SYNOPSIS
|
||||||
|
/* #include "verp_sender.h"
|
||||||
|
/* DESCRIPTION
|
||||||
|
/* .nf
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Utility library.
|
||||||
|
*/
|
||||||
|
#include <vstring.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* External interface.
|
||||||
|
*/
|
||||||
|
extern VSTRING *verp_sender(VSTRING *, const char *, const char *, const char *);
|
||||||
|
|
||||||
|
/* LICENSE
|
||||||
|
/* .ad
|
||||||
|
/* .fi
|
||||||
|
/* The Secure Mailer license must be distributed with this software.
|
||||||
|
/* AUTHOR(S)
|
||||||
|
/* Wietse Venema
|
||||||
|
/* IBM T.J. Watson Research
|
||||||
|
/* P.O. Box 704
|
||||||
|
/* Yorktown Heights, NY 10598, USA
|
||||||
|
/*--*/
|
||||||
|
|
||||||
|
#endif
|
@@ -267,6 +267,7 @@ struct QMGR_MESSAGE {
|
|||||||
char *queue_name; /* queue name */
|
char *queue_name; /* queue name */
|
||||||
char *queue_id; /* queue file */
|
char *queue_id; /* queue file */
|
||||||
char *sender; /* complete address */
|
char *sender; /* complete address */
|
||||||
|
char *verp_delims; /* VERP delimiters */
|
||||||
char *errors_to; /* error report address */
|
char *errors_to; /* error report address */
|
||||||
char *return_receipt; /* confirm receipt address */
|
char *return_receipt; /* confirm receipt address */
|
||||||
char *filter_xport; /* filtering transport */
|
char *filter_xport; /* filtering transport */
|
||||||
|
@@ -275,12 +275,21 @@ void qmgr_active_done(QMGR_MESSAGE *message)
|
|||||||
} else {
|
} else {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: bounce %s", myname, message->queue_id);
|
msg_info("%s: bounce %s", myname, message->queue_id);
|
||||||
abounce_flush(BOUNCE_FLAG_KEEP,
|
if (message->verp_delims == 0)
|
||||||
message->queue_name,
|
abounce_flush(BOUNCE_FLAG_KEEP,
|
||||||
message->queue_id,
|
message->queue_name,
|
||||||
message->errors_to,
|
message->queue_id,
|
||||||
qmgr_active_done_2_bounce_flush,
|
message->errors_to,
|
||||||
(char *) message);
|
qmgr_active_done_2_bounce_flush,
|
||||||
|
(char *) message);
|
||||||
|
else
|
||||||
|
abounce_flush_verp(BOUNCE_FLAG_KEEP,
|
||||||
|
message->queue_name,
|
||||||
|
message->queue_id,
|
||||||
|
message->errors_to,
|
||||||
|
message->verp_delims,
|
||||||
|
qmgr_active_done_2_bounce_flush,
|
||||||
|
(char *) message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,12 +362,21 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
|
|||||||
if (event_time() > message->arrival_time + var_max_queue_time) {
|
if (event_time() > message->arrival_time + var_max_queue_time) {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: too old, bouncing %s", myname, message->queue_id);
|
msg_info("%s: too old, bouncing %s", myname, message->queue_id);
|
||||||
adefer_flush(BOUNCE_FLAG_KEEP,
|
if (message->verp_delims == 0)
|
||||||
message->queue_name,
|
adefer_flush(BOUNCE_FLAG_KEEP,
|
||||||
message->queue_id,
|
message->queue_name,
|
||||||
message->errors_to,
|
message->queue_id,
|
||||||
qmgr_active_done_3_defer_flush,
|
message->errors_to,
|
||||||
(char *) message);
|
qmgr_active_done_3_defer_flush,
|
||||||
|
(char *) message);
|
||||||
|
else
|
||||||
|
adefer_flush_verp(BOUNCE_FLAG_KEEP,
|
||||||
|
message->queue_name,
|
||||||
|
message->queue_id,
|
||||||
|
message->errors_to,
|
||||||
|
message->verp_delims,
|
||||||
|
qmgr_active_done_3_defer_flush,
|
||||||
|
(char *) message);
|
||||||
return;
|
return;
|
||||||
} else if (message->warn_time > 0
|
} else if (message->warn_time > 0
|
||||||
&& event_time() > message->warn_time) {
|
&& event_time() > message->warn_time) {
|
||||||
|
@@ -68,6 +68,7 @@
|
|||||||
#include <recipient_list.h>
|
#include <recipient_list.h>
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <deliver_request.h>
|
#include <deliver_request.h>
|
||||||
|
#include <verp_sender.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@@ -124,6 +125,22 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
QMGR_RCPT *recipient;
|
QMGR_RCPT *recipient;
|
||||||
QMGR_MESSAGE *message = entry->message;
|
QMGR_MESSAGE *message = entry->message;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
VSTRING *sender_buf = 0;
|
||||||
|
char *sender;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If variable envelope return path is requested, change prefix+@origin
|
||||||
|
* into prefix+user=domain@origin. Note that with VERP there is only one
|
||||||
|
* recipient per delivery.
|
||||||
|
*/
|
||||||
|
if (message->verp_delims == 0) {
|
||||||
|
sender = message->sender;
|
||||||
|
} else {
|
||||||
|
sender_buf = vstring_alloc(100);
|
||||||
|
verp_sender(sender_buf, message->verp_delims,
|
||||||
|
message->sender, list.info->address);
|
||||||
|
sender = vstring_str(sender_buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* With mail transports that accept only one recipient per delivery, the
|
* With mail transports that accept only one recipient per delivery, the
|
||||||
@@ -136,9 +153,11 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
message->queue_name, message->queue_id,
|
message->queue_name, message->queue_id,
|
||||||
message->data_offset, message->data_size,
|
message->data_offset, message->data_size,
|
||||||
(cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 :
|
(cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 :
|
||||||
entry->queue->name, message->sender,
|
entry->queue->name, sender,
|
||||||
message->errors_to, message->return_receipt,
|
message->errors_to, message->return_receipt,
|
||||||
message->arrival_time);
|
message->arrival_time);
|
||||||
|
if (sender_buf != 0)
|
||||||
|
vstring_free(sender_buf);
|
||||||
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
||||||
mail_print(stream, "%ld %s", recipient->offset, recipient->address);
|
mail_print(stream, "%ld %s", recipient->offset, recipient->address);
|
||||||
mail_print(stream, "%s", "0");
|
mail_print(stream, "%s", "0");
|
||||||
|
@@ -161,6 +161,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
|
|||||||
message->warn_offset = 0;
|
message->warn_offset = 0;
|
||||||
message->warn_time = 0;
|
message->warn_time = 0;
|
||||||
message->rcpt_offset = 0;
|
message->rcpt_offset = 0;
|
||||||
|
message->verp_delims = 0;
|
||||||
message->unread_offset = 0;
|
message->unread_offset = 0;
|
||||||
qmgr_rcpt_list_init(&message->rcpt_list);
|
qmgr_rcpt_list_init(&message->rcpt_list);
|
||||||
message->rcpt_count = 0;
|
message->rcpt_count = 0;
|
||||||
@@ -423,6 +424,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
|||||||
message->warn_offset = curr_offset;
|
message->warn_offset = curr_offset;
|
||||||
message->warn_time = atol(start);
|
message->warn_time = atol(start);
|
||||||
}
|
}
|
||||||
|
} else if (rec_type == REC_TYPE_VERP) {
|
||||||
|
if (strlen(start) != 2) {
|
||||||
|
msg_warn("%s: bad VERP record length: \"%s\"",
|
||||||
|
message->queue_id, start);
|
||||||
|
} else {
|
||||||
|
message->single_rcpt = 1;
|
||||||
|
message->verp_delims = mystrdup(start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (rec_type > 0 && rec_type != REC_TYPE_END);
|
} while (rec_type > 0 && rec_type != REC_TYPE_END);
|
||||||
|
|
||||||
@@ -902,6 +911,8 @@ void qmgr_message_free(QMGR_MESSAGE *message)
|
|||||||
myfree(message->queue_name);
|
myfree(message->queue_name);
|
||||||
if (message->sender)
|
if (message->sender)
|
||||||
myfree(message->sender);
|
myfree(message->sender);
|
||||||
|
if (message->verp_delims)
|
||||||
|
myfree(message->verp_delims);
|
||||||
if (message->errors_to)
|
if (message->errors_to)
|
||||||
myfree(message->errors_to);
|
myfree(message->errors_to);
|
||||||
if (message->return_receipt)
|
if (message->return_receipt)
|
||||||
|
@@ -136,6 +136,7 @@ qmgr_deliver.o: ../../include/mail_proto.h
|
|||||||
qmgr_deliver.o: ../../include/recipient_list.h
|
qmgr_deliver.o: ../../include/recipient_list.h
|
||||||
qmgr_deliver.o: ../../include/mail_params.h
|
qmgr_deliver.o: ../../include/mail_params.h
|
||||||
qmgr_deliver.o: ../../include/deliver_request.h
|
qmgr_deliver.o: ../../include/deliver_request.h
|
||||||
|
qmgr_deliver.o: ../../include/verp_sender.h
|
||||||
qmgr_deliver.o: qmgr.h
|
qmgr_deliver.o: qmgr.h
|
||||||
qmgr_deliver.o: ../../include/scan_dir.h
|
qmgr_deliver.o: ../../include/scan_dir.h
|
||||||
qmgr_deliver.o: ../../include/maps.h
|
qmgr_deliver.o: ../../include/maps.h
|
||||||
|
@@ -227,6 +227,7 @@ struct QMGR_MESSAGE {
|
|||||||
char *queue_name; /* queue name */
|
char *queue_name; /* queue name */
|
||||||
char *queue_id; /* queue file */
|
char *queue_id; /* queue file */
|
||||||
char *sender; /* complete address */
|
char *sender; /* complete address */
|
||||||
|
char *verp_delims; /* VERP delimiters */
|
||||||
char *errors_to; /* error report address */
|
char *errors_to; /* error report address */
|
||||||
char *return_receipt; /* confirm receipt address */
|
char *return_receipt; /* confirm receipt address */
|
||||||
char *filter_xport; /* filtering transport */
|
char *filter_xport; /* filtering transport */
|
||||||
|
@@ -275,12 +275,21 @@ void qmgr_active_done(QMGR_MESSAGE *message)
|
|||||||
} else {
|
} else {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: bounce %s", myname, message->queue_id);
|
msg_info("%s: bounce %s", myname, message->queue_id);
|
||||||
abounce_flush(BOUNCE_FLAG_KEEP,
|
if (message->verp_delims == 0)
|
||||||
message->queue_name,
|
abounce_flush(BOUNCE_FLAG_KEEP,
|
||||||
message->queue_id,
|
message->queue_name,
|
||||||
message->errors_to,
|
message->queue_id,
|
||||||
qmgr_active_done_2_bounce_flush,
|
message->errors_to,
|
||||||
(char *) message);
|
qmgr_active_done_2_bounce_flush,
|
||||||
|
(char *) message);
|
||||||
|
else
|
||||||
|
abounce_flush_verp(BOUNCE_FLAG_KEEP,
|
||||||
|
message->queue_name,
|
||||||
|
message->queue_id,
|
||||||
|
message->errors_to,
|
||||||
|
message->verp_delims,
|
||||||
|
qmgr_active_done_2_bounce_flush,
|
||||||
|
(char *) message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -353,12 +362,21 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
|
|||||||
if (event_time() > message->arrival_time + var_max_queue_time) {
|
if (event_time() > message->arrival_time + var_max_queue_time) {
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: too old, bouncing %s", myname, message->queue_id);
|
msg_info("%s: too old, bouncing %s", myname, message->queue_id);
|
||||||
adefer_flush(BOUNCE_FLAG_KEEP,
|
if (message->verp_delims == 0)
|
||||||
message->queue_name,
|
adefer_flush(BOUNCE_FLAG_KEEP,
|
||||||
message->queue_id,
|
message->queue_name,
|
||||||
message->errors_to,
|
message->queue_id,
|
||||||
qmgr_active_done_3_defer_flush,
|
message->errors_to,
|
||||||
(char *) message);
|
qmgr_active_done_3_defer_flush,
|
||||||
|
(char *) message);
|
||||||
|
else
|
||||||
|
adefer_flush_verp(BOUNCE_FLAG_KEEP,
|
||||||
|
message->queue_name,
|
||||||
|
message->queue_id,
|
||||||
|
message->errors_to,
|
||||||
|
message->verp_delims,
|
||||||
|
qmgr_active_done_3_defer_flush,
|
||||||
|
(char *) message);
|
||||||
return;
|
return;
|
||||||
} else if (message->warn_time > 0
|
} else if (message->warn_time > 0
|
||||||
&& event_time() > message->warn_time) {
|
&& event_time() > message->warn_time) {
|
||||||
|
@@ -63,6 +63,7 @@
|
|||||||
#include <recipient_list.h>
|
#include <recipient_list.h>
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <deliver_request.h>
|
#include <deliver_request.h>
|
||||||
|
#include <verp_sender.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@@ -119,6 +120,22 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
QMGR_RCPT *recipient;
|
QMGR_RCPT *recipient;
|
||||||
QMGR_MESSAGE *message = entry->message;
|
QMGR_MESSAGE *message = entry->message;
|
||||||
char *cp;
|
char *cp;
|
||||||
|
VSTRING *sender_buf = 0;
|
||||||
|
char *sender;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If variable envelope return path is requested, change prefix+@origin
|
||||||
|
* into prefix+user=domain@origin. Note that with VERP there is only one
|
||||||
|
* recipient per delivery.
|
||||||
|
*/
|
||||||
|
if (message->verp_delims == 0) {
|
||||||
|
sender = message->sender;
|
||||||
|
} else {
|
||||||
|
sender_buf = vstring_alloc(100);
|
||||||
|
verp_sender(sender_buf, message->verp_delims,
|
||||||
|
message->sender, list.info->address);
|
||||||
|
sender = vstring_str(sender_buf);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* With mail transports that accept only one recipient per delivery, the
|
* With mail transports that accept only one recipient per delivery, the
|
||||||
@@ -131,9 +148,11 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
|||||||
message->queue_name, message->queue_id,
|
message->queue_name, message->queue_id,
|
||||||
message->data_offset, message->data_size,
|
message->data_offset, message->data_size,
|
||||||
(cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 :
|
(cp = strrchr(entry->queue->name, '@')) != 0 && cp[1] ? cp + 1 :
|
||||||
entry->queue->name, message->sender,
|
entry->queue->name, sender,
|
||||||
message->errors_to, message->return_receipt,
|
message->errors_to, message->return_receipt,
|
||||||
message->arrival_time);
|
message->arrival_time);
|
||||||
|
if (sender_buf != 0)
|
||||||
|
vstring_free(sender_buf);
|
||||||
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
for (recipient = list.info; recipient < list.info + list.len; recipient++)
|
||||||
mail_print(stream, "%ld %s", recipient->offset, recipient->address);
|
mail_print(stream, "%ld %s", recipient->offset, recipient->address);
|
||||||
mail_print(stream, "%s", "0");
|
mail_print(stream, "%s", "0");
|
||||||
|
@@ -151,6 +151,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
|
|||||||
message->warn_offset = 0;
|
message->warn_offset = 0;
|
||||||
message->warn_time = 0;
|
message->warn_time = 0;
|
||||||
message->rcpt_offset = 0;
|
message->rcpt_offset = 0;
|
||||||
|
message->verp_delims = 0;
|
||||||
qmgr_rcpt_list_init(&message->rcpt_list);
|
qmgr_rcpt_list_init(&message->rcpt_list);
|
||||||
return (message);
|
return (message);
|
||||||
}
|
}
|
||||||
@@ -303,6 +304,14 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
|||||||
message->warn_offset = curr_offset;
|
message->warn_offset = curr_offset;
|
||||||
message->warn_time = atol(start);
|
message->warn_time = atol(start);
|
||||||
}
|
}
|
||||||
|
} else if (rec_type == REC_TYPE_VERP) {
|
||||||
|
if (strlen(start) != 2) {
|
||||||
|
msg_warn("%s: bad VERP record length: \"%s\"",
|
||||||
|
message->queue_id, start);
|
||||||
|
} else {
|
||||||
|
message->single_rcpt = 1;
|
||||||
|
message->verp_delims = mystrdup(start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} while (rec_type > 0 && rec_type != REC_TYPE_END);
|
} while (rec_type > 0 && rec_type != REC_TYPE_END);
|
||||||
|
|
||||||
@@ -737,6 +746,8 @@ void qmgr_message_free(QMGR_MESSAGE *message)
|
|||||||
myfree(message->queue_name);
|
myfree(message->queue_name);
|
||||||
if (message->sender)
|
if (message->sender)
|
||||||
myfree(message->sender);
|
myfree(message->sender);
|
||||||
|
if (message->verp_delims)
|
||||||
|
myfree(message->verp_delims);
|
||||||
if (message->errors_to)
|
if (message->errors_to)
|
||||||
myfree(message->errors_to);
|
myfree(message->errors_to);
|
||||||
if (message->return_receipt)
|
if (message->return_receipt)
|
||||||
|
@@ -210,11 +210,34 @@ static void qmqpd_read_content(QMQPD_STATE *state)
|
|||||||
|
|
||||||
static void qmqpd_copy_sender(QMQPD_STATE *state)
|
static void qmqpd_copy_sender(QMQPD_STATE *state)
|
||||||
{
|
{
|
||||||
|
char *end_prefix;
|
||||||
|
char *end_origin;
|
||||||
|
int verp_requested;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the sender address looks like prefix-@origin-@[], then request
|
||||||
|
* variable envelope return path delivery, with an envelope sender
|
||||||
|
* address of prefix@origin, and with VERP delimiters of - and =. This
|
||||||
|
* way, the recipients will see envelope sender addresses that look like:
|
||||||
|
* prefix-user=domain@origin.
|
||||||
|
*/
|
||||||
state->where = "receiving sender address";
|
state->where = "receiving sender address";
|
||||||
netstring_get(state->client, state->buf, var_line_limit);
|
netstring_get(state->client, state->buf, var_line_limit);
|
||||||
|
verp_requested = ((end_prefix = strstr(STR(state->buf), "-@")) != 0
|
||||||
|
&& (end_origin = strstr(end_prefix + 2, "-@")) != 0
|
||||||
|
&& strncmp(end_origin + 2, "[]", 2) == 0
|
||||||
|
&& vstring_end(state->buf) == end_origin + 4);
|
||||||
|
if (verp_requested) {
|
||||||
|
memcpy(end_prefix, end_prefix + 1, end_origin - end_prefix - 1);
|
||||||
|
vstring_truncate(state->buf, end_origin - STR(state->buf) - 1);
|
||||||
|
}
|
||||||
if (state->err == CLEANUP_STAT_OK
|
if (state->err == CLEANUP_STAT_OK
|
||||||
&& REC_PUT_BUF(state->cleanup, REC_TYPE_FROM, state->buf) < 0)
|
&& REC_PUT_BUF(state->cleanup, REC_TYPE_FROM, state->buf) < 0)
|
||||||
state->err = CLEANUP_STAT_WRITE;
|
state->err = CLEANUP_STAT_WRITE;
|
||||||
|
if (verp_requested)
|
||||||
|
if (state->err == CLEANUP_STAT_OK
|
||||||
|
&& rec_put(state->cleanup, REC_TYPE_VERP, "-=", 2) < 0)
|
||||||
|
state->err = CLEANUP_STAT_WRITE;
|
||||||
state->sender = mystrndup(STR(state->buf), LEN(state->buf));
|
state->sender = mystrndup(STR(state->buf), LEN(state->buf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -76,6 +76,11 @@
|
|||||||
/* \fBdebug_peer_level\fR configuration parameters instead.
|
/* \fBdebug_peer_level\fR configuration parameters instead.
|
||||||
/* .IP "\fB-U\fR (ignored)"
|
/* .IP "\fB-U\fR (ignored)"
|
||||||
/* Initial user submission.
|
/* Initial user submission.
|
||||||
|
/* .IP \fB-V\fR
|
||||||
|
/* Variable Envelope Return Path. Given an envelope sender address
|
||||||
|
/* \fIprefix\fR-@\fIorigin\fR, each recipient \fIuser@domain\fR
|
||||||
|
/* receives mail with a personalized envelope sender address
|
||||||
|
/* \fIprefix\fB-\fIuser=domain\fR@\fIorigin\fR.
|
||||||
/* .IP \fB-bd\fR
|
/* .IP \fB-bd\fR
|
||||||
/* Go into daemon mode. This mode of operation is implemented by
|
/* Go into daemon mode. This mode of operation is implemented by
|
||||||
/* executing the \fBpostfix start\fR command.
|
/* executing the \fBpostfix start\fR command.
|
||||||
@@ -319,6 +324,11 @@ static void sendmail_cleanup(void);
|
|||||||
|
|
||||||
#define SM_FLAG_DEFAULT (SM_FLAG_AEOF)
|
#define SM_FLAG_DEFAULT (SM_FLAG_AEOF)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VERP support.
|
||||||
|
*/
|
||||||
|
char *verp_delims;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Silly little macros (SLMs).
|
* Silly little macros (SLMs).
|
||||||
*/
|
*/
|
||||||
@@ -414,6 +424,10 @@ static void enqueue(const int flags, const char *sender, const char *full_name,
|
|||||||
if (full_name || (full_name = fullname()) != 0)
|
if (full_name || (full_name = fullname()) != 0)
|
||||||
rec_fputs(dst, REC_TYPE_FULL, full_name);
|
rec_fputs(dst, REC_TYPE_FULL, full_name);
|
||||||
rec_fputs(dst, REC_TYPE_FROM, saved_sender);
|
rec_fputs(dst, REC_TYPE_FROM, saved_sender);
|
||||||
|
if (verp_delims && *saved_sender == 0)
|
||||||
|
msg_fatal("-V option requires non-null sender address");
|
||||||
|
if (verp_delims)
|
||||||
|
rec_fputs(dst, REC_TYPE_VERP, verp_delims);
|
||||||
if (recipients) {
|
if (recipients) {
|
||||||
for (cpp = recipients; *cpp != 0; cpp++) {
|
for (cpp = recipients; *cpp != 0; cpp++) {
|
||||||
tree = tok822_parse(*cpp);
|
tree = tok822_parse(*cpp);
|
||||||
@@ -794,7 +808,7 @@ int main(int argc, char **argv)
|
|||||||
optind++;
|
optind++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((c = GETOPT(argc, argv, "B:C:F:GIN:R:UX:b:ce:f:h:imno:p:r:q:tvx")) <= 0)
|
if ((c = GETOPT(argc, argv, "B:C:F:GIN:R:UVX:b:ce:f:h:imno:p:r:q:tvx")) <= 0)
|
||||||
break;
|
break;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
default:
|
default:
|
||||||
@@ -817,6 +831,9 @@ int main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
case 'R': /* DSN */
|
case 'R': /* DSN */
|
||||||
break;
|
break;
|
||||||
|
case 'V': /* VERP */
|
||||||
|
verp_delims = "";
|
||||||
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
switch (*optarg) {
|
switch (*optarg) {
|
||||||
default:
|
default:
|
||||||
|
@@ -32,8 +32,8 @@
|
|||||||
/* STANDARDS
|
/* STANDARDS
|
||||||
/* RFC 821 (SMTP protocol)
|
/* RFC 821 (SMTP protocol)
|
||||||
/* RFC 1123 (Host requirements)
|
/* RFC 1123 (Host requirements)
|
||||||
/* RFC 1651 (SMTP service extensions)
|
|
||||||
/* RFC 1652 (8bit-MIME transport)
|
/* RFC 1652 (8bit-MIME transport)
|
||||||
|
/* RFC 1869 (SMTP service extensions)
|
||||||
/* RFC 1854 (SMTP Pipelining)
|
/* RFC 1854 (SMTP Pipelining)
|
||||||
/* RFC 1870 (Message Size Declaration)
|
/* RFC 1870 (Message Size Declaration)
|
||||||
/* RFC 1985 (ETRN command)
|
/* RFC 1985 (ETRN command)
|
||||||
@@ -363,6 +363,12 @@ char *smtpd_path;
|
|||||||
#define STR(x) vstring_str(x)
|
#define STR(x) vstring_str(x)
|
||||||
#define LEN(x) VSTRING_LEN(x)
|
#define LEN(x) VSTRING_LEN(x)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* VERP command name.
|
||||||
|
*/
|
||||||
|
#define VERP_CMD "XVERP"
|
||||||
|
#define VERP_CMD_LEN 5
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Forward declarations.
|
* Forward declarations.
|
||||||
*/
|
*/
|
||||||
@@ -459,6 +465,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
|
smtpd_chat_reply(state, "250-AUTH=%s", state->sasl_mechanism_list);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
smtpd_chat_reply(state, "250-%s", VERP_CMD);
|
||||||
smtpd_chat_reply(state, "250 8BITMIME");
|
smtpd_chat_reply(state, "250 8BITMIME");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -626,6 +633,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
char *err;
|
char *err;
|
||||||
int narg;
|
int narg;
|
||||||
char *arg;
|
char *arg;
|
||||||
|
char *verp_delims = 0;
|
||||||
|
|
||||||
state->msg_size = 0;
|
state->msg_size = 0;
|
||||||
|
|
||||||
@@ -680,12 +688,27 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
} else if (strcasecmp(arg, VERP_CMD) == 0) {
|
||||||
|
verp_delims = "";
|
||||||
|
} else if (strncasecmp(arg, VERP_CMD, VERP_CMD_LEN) == 0
|
||||||
|
&& arg[VERP_CMD_LEN] == '=') {
|
||||||
|
verp_delims = arg + VERP_CMD_LEN + 1;
|
||||||
|
if (strlen(verp_delims) != 2) {
|
||||||
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
|
smtpd_chat_reply(state, "501 Bad %s parameter: %s",
|
||||||
|
VERP_CMD, arg);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "555 Unsupported option: %s", arg);
|
smtpd_chat_reply(state, "555 Unsupported option: %s", arg);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (verp_delims && argv[2].strval[0] == 0) {
|
||||||
|
smtpd_chat_reply(state, "503 Error: XVERP requires non-null sender");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
state->time = time((time_t *) 0);
|
state->time = time((time_t *) 0);
|
||||||
if (SMTPD_STAND_ALONE(state) == 0
|
if (SMTPD_STAND_ALONE(state) == 0
|
||||||
&& var_smtpd_delay_reject == 0
|
&& var_smtpd_delay_reject == 0
|
||||||
@@ -718,6 +741,8 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
if (*var_filter_xport)
|
if (*var_filter_xport)
|
||||||
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
|
rec_fprintf(state->cleanup, REC_TYPE_FILT, "%s", var_filter_xport);
|
||||||
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
|
rec_fputs(state->cleanup, REC_TYPE_FROM, argv[2].strval);
|
||||||
|
if (verp_delims)
|
||||||
|
rec_fputs(state->cleanup, REC_TYPE_VERP, verp_delims);
|
||||||
state->sender = mystrdup(argv[2].strval);
|
state->sender = mystrdup(argv[2].strval);
|
||||||
smtpd_chat_reply(state, "250 Ok");
|
smtpd_chat_reply(state, "250 Ok");
|
||||||
return (0);
|
return (0);
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
/* \fBqmqp-sink\fR [\fB-cv\fR] [\fB-x \fItime\fR]
|
/* \fBqmqp-sink\fR [\fB-cv\fR] [\fB-x \fItime\fR]
|
||||||
/* [\fBinet:\fR][\fIhost\fR]:\fIport\fR \fIbacklog\fR
|
/* [\fBinet:\fR][\fIhost\fR]:\fIport\fR \fIbacklog\fR
|
||||||
/*
|
/*
|
||||||
/* \fBqmqp-sink\fR [\fB-cv\fR]
|
/* \fBqmqp-sink\fR [\fB-cv\fR] [\fB-x \fItime\fR]
|
||||||
/* \fBunix:\fR\fIpathname\fR \fIbacklog\fR
|
/* \fBunix:\fR\fIpathname\fR \fIbacklog\fR
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* \fIqmqp-sink\fR listens on the named host (or address) and port.
|
/* \fIqmqp-sink\fR listens on the named host (or address) and port.
|
||||||
|
Reference in New Issue
Block a user