mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-29 13:18:12 +00:00
snapshot-20000625
This commit is contained in:
parent
a8e8c4d123
commit
9f6c81ebcd
@ -1,4 +1,8 @@
|
|||||||
This is a very first implementation of Postfix content filtering.
|
This is a very first implementation of Postfix content filtering.
|
||||||
|
A Postfix content filter re-injects filtered mail back into Postfix.
|
||||||
|
If all you want is content _inspection_, see the INSPECT_README
|
||||||
|
file instead.
|
||||||
|
|
||||||
It involves an incompatible change to queue file formats. Older
|
It involves an incompatible change to queue file formats. Older
|
||||||
Postfix versions will reject mail that needs to be content filtered,
|
Postfix versions will reject mail that needs to be content filtered,
|
||||||
and will move the queue file to the "corrupt" mail queue subdirectory.
|
and will move the queue file to the "corrupt" mail queue subdirectory.
|
||||||
@ -76,18 +80,19 @@ content through run a third-party content filter program. If the
|
|||||||
mail cannot be captured to file, mail delivery is deferred by
|
mail cannot be captured to file, mail delivery is deferred by
|
||||||
terminating with exit status 75 (EX_TEMPFAIL). If the content
|
terminating with exit status 75 (EX_TEMPFAIL). If the content
|
||||||
filter program finds a problem, the mail is bounced by terminating
|
filter program finds a problem, the mail is bounced by terminating
|
||||||
the filter command with exit status 69 (EX_UNAVAILABLE). If the
|
the shell script with exit status 69 (EX_UNAVAILABLE). If the
|
||||||
content is OK, it is given as input to Postfix sendmail, and the
|
content is OK, it is given as input to Postfix sendmail, and the
|
||||||
exit status of the filter command is whatever exit status Postfix
|
exit status of the filter command is whatever exit status Postfix
|
||||||
sendmail produces.
|
sendmail produces.
|
||||||
|
|
||||||
The problem with content filterings like this is that they are not
|
The problem with content filters like this is that they are not
|
||||||
very robust, because they do not talk a well-defined protocol with
|
very robust, because the software does not talk a well-defined
|
||||||
Postfix. If the filter command aborts because of some memory
|
protocol with Postfix. If the filter shell script aborts because
|
||||||
allocation problem, it will not produce a nice exit status as per
|
the shell runs into some memory allocation problem, the script will
|
||||||
/usr/include/sysexits.h and mail will probably bounce. The same
|
not produce a nice exit status as per /usr/include/sysexits.h and
|
||||||
lack of robustness is possible when the content filtering software
|
mail will probably bounce. The same lack of robustness is possible
|
||||||
itself runs into a resource problem.
|
when the content filtering software itself runs into a resource
|
||||||
|
problem.
|
||||||
|
|
||||||
I suggest that you play with this script for a while until you are
|
I suggest that you play with this script for a while until you are
|
||||||
satisfied with the results. Run it as root or as the filter user,
|
satisfied with the results. Run it as root or as the filter user,
|
||||||
@ -159,7 +164,7 @@ When a queue file has content filtering information, the queue
|
|||||||
manager will deliver the mail to the specified content filtering
|
manager will deliver the mail to the specified content filtering
|
||||||
regardless of its final destination.
|
regardless of its final destination.
|
||||||
|
|
||||||
The content filtering can be set up with the Postfix spawn service,
|
The content filter can be set up with the Postfix spawn service,
|
||||||
which is the Postfix equivalent of inetd. For example, to instantiate
|
which is the Postfix equivalent of inetd. For example, to instantiate
|
||||||
up to 10 content filtering processes on demand:
|
up to 10 content filtering processes on demand:
|
||||||
|
|
||||||
@ -184,18 +189,18 @@ For now, it is left up to the Postfix users to come up with a
|
|||||||
PERL/SMTP framework for Postfix content filtering. If done well,
|
PERL/SMTP framework for Postfix content filtering. If done well,
|
||||||
it can be used with other mailers too, which is a nice spin-off.
|
it can be used with other mailers too, which is a nice spin-off.
|
||||||
|
|
||||||
The simplest content filtering just copies SMTP commands and data
|
The simplest content filter just copies SMTP commands and data
|
||||||
between its inputs and outputs. If it has a problem, all it has to
|
between its inputs and outputs. If it has a problem, all it has to
|
||||||
do is to reply to an input of `.' with `550 content rejected', and
|
do is to reply to an input of `.' with `550 content rejected', and
|
||||||
to disconnect its output side instead of sending `.'.
|
to disconnect its output side instead of sending `.'.
|
||||||
|
|
||||||
The job of the content filtering is to either bounce mail with a
|
The job of the content filter is to either bounce mail with a
|
||||||
suitable diagnostic, or to feed the mail back into Postfix through
|
suitable diagnostic, or to feed the mail back into Postfix through
|
||||||
a dedicated listener on port localhost 10026:
|
a dedicated listener on port localhost 10026:
|
||||||
|
|
||||||
/etc/postfix/master.cf:
|
/etc/postfix/master.cf:
|
||||||
localhost:10026 inet n - n - 10 smtpd
|
localhost:10026 inet n - n - 10 smtpd
|
||||||
-o content_filter= myhostname=localhost.domain.name
|
-o content_filter= -o myhostname=localhost.domain.name
|
||||||
|
|
||||||
This is just another SMTP server. It is configured NOT to request
|
This is just another SMTP server. It is configured NOT to request
|
||||||
content filtering for incoming mail, has the same process limit
|
content filtering for incoming mail, has the same process limit
|
||||||
|
@ -4032,3 +4032,66 @@ Apologies for any names omitted.
|
|||||||
Renamed "content inspection" etc. to "content filtering"
|
Renamed "content inspection" etc. to "content filtering"
|
||||||
in anticipation of a new hook for content inspection that
|
in anticipation of a new hook for content inspection that
|
||||||
only inspects mail without re-injecting it into Postfix.
|
only inspects mail without re-injecting it into Postfix.
|
||||||
|
|
||||||
|
20000601
|
||||||
|
|
||||||
|
Feature: limit the size of pipe mailer deliveries with the
|
||||||
|
size=nnn command-line attribute. Patch by Andrew McNamara.
|
||||||
|
|
||||||
|
20000603
|
||||||
|
|
||||||
|
Bugfix: don't try to do SASL authentication when running
|
||||||
|
in stand-alone (sendmail -bs) mode. Fix by Liviu Daia.
|
||||||
|
|
||||||
|
Bug: the unauthorized pipelining test fails with single
|
||||||
|
recipient mail when smtpd_delay_reject = yes.
|
||||||
|
|
||||||
|
20000617
|
||||||
|
|
||||||
|
Bugfix: conf/sample-ldap.cf was no longer up to date with
|
||||||
|
reality. Patch by Lamont Jones, HP.
|
||||||
|
|
||||||
|
Bugfix: the maildir delivery routine left temporary files
|
||||||
|
lying around after unsuccessful delivery (problem reported
|
||||||
|
by Brian Laughton @ Corp.Axxent.Ca).
|
||||||
|
|
||||||
|
20000619
|
||||||
|
|
||||||
|
Workaround: if append_dot_mydomain=no, turn on parent domain
|
||||||
|
search in the Postfix SMTP client, so that mail does not
|
||||||
|
bounce. Files: smtp/smtp.c, smtp/smtp_unalias.c.
|
||||||
|
|
||||||
|
20000621
|
||||||
|
|
||||||
|
AIX 4.x had POSIX regular expression support all the time
|
||||||
|
I was working on Postfix. Beter find out late than never.
|
||||||
|
|
||||||
|
20000623
|
||||||
|
|
||||||
|
Bugfix: the SMTP server did not reset the so-called junk
|
||||||
|
command counter after successfull delivery (Mark Hoffman
|
||||||
|
@ wallst.com). File: smtpd/smtpd.c.
|
||||||
|
|
||||||
|
20000625
|
||||||
|
|
||||||
|
Cleanup: remove Content-Length from incoming mail. The
|
||||||
|
sender has no authority over the format of mail as stored
|
||||||
|
by the receiving system. File: global/header_opts.h.
|
||||||
|
|
||||||
|
Feature: rewrite Mail-Followup-To: as sender. Files:
|
||||||
|
global/header_opts.[hc].
|
||||||
|
|
||||||
|
Cleanup: rewrite Reply-To, Errors-To, Return-Receipt-To as
|
||||||
|
sender, so that address masquerading works as expected.
|
||||||
|
Files: global/header_opts.c.
|
||||||
|
|
||||||
|
Feature: specify "test_home_directory = yes" to prevent
|
||||||
|
mail from being delivered to a user whose home directory
|
||||||
|
is not mounted. File: local/dotforward.c.
|
||||||
|
|
||||||
|
Cleanup: the pipe deliver agent no longer appends a blank
|
||||||
|
line when the F flag (prepend From_ line) is specified.
|
||||||
|
Specify the B flag if you need that blank line. The local
|
||||||
|
delivery agent no longer appends a blank line to mail that
|
||||||
|
is delivered to external command. Files: pipe/pipe.c,
|
||||||
|
global/mail_copy.[hc].
|
||||||
|
181
postfix/INSPECT_README
Normal file
181
postfix/INSPECT_README
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
This is a very first implementation of Postfix content inspection.
|
||||||
|
A Postfix content inspector causes "bad" mail to be bounced. All
|
||||||
|
other mail is delivered normally. If you want content _inspection_,
|
||||||
|
which allows you to modify mail content or destination, see the
|
||||||
|
FILTER_README file instead.
|
||||||
|
|
||||||
|
Content inspection involves an incompatible change to queue file
|
||||||
|
formats. Older Postfix versions will reject mail that needs to be
|
||||||
|
content inspected, and will move the queue file to the "corrupt"
|
||||||
|
mail queue subdirectory.
|
||||||
|
|
||||||
|
This document describes two approaches to content inspection.
|
||||||
|
|
||||||
|
Simple content inspection example
|
||||||
|
=================================
|
||||||
|
|
||||||
|
The example is relatively simple to set up, but is resource intensive
|
||||||
|
because it runs a shell script for each message.
|
||||||
|
|
||||||
|
With the shell script as shown you can lose a factor in Postfix
|
||||||
|
performance for each temporary file that is created and deleted in
|
||||||
|
the process of content inspection. The performance impact is less
|
||||||
|
for mail that is submitted or delivered locally, because such
|
||||||
|
deliveries are not as fast as SMTP transit mail.
|
||||||
|
|
||||||
|
The example assumes that only mail received via SMTP needs to be
|
||||||
|
content inspected.
|
||||||
|
|
||||||
|
..................................
|
||||||
|
. Postfix .
|
||||||
|
------smtpd \ /local-----
|
||||||
|
. -cleanup->queue- .
|
||||||
|
-----pickup / \smtp------
|
||||||
|
. | .
|
||||||
|
. \pipe------>inspector
|
||||||
|
..................................
|
||||||
|
|
||||||
|
Create a dedicated local user account called "inspect". The user
|
||||||
|
will never log in, and can be given a "*" password and non-existent
|
||||||
|
shell and home.
|
||||||
|
|
||||||
|
Create a directory /var/spool/inspect that is accessible only to
|
||||||
|
the "inspect" user. This is where the content inspection software
|
||||||
|
will store any temporary files.
|
||||||
|
|
||||||
|
Define a content inspection entry in the Postfix master file:
|
||||||
|
|
||||||
|
/etc/postfix/master.cf:
|
||||||
|
inspect unix - n n - - pipe
|
||||||
|
user=inspect argv=/some/where/inspect ${sender} ${recipient}
|
||||||
|
|
||||||
|
The filter program can start out as a simple shell script like this:
|
||||||
|
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Localize this
|
||||||
|
INSPECT_DIR=/var/spool/inspect
|
||||||
|
|
||||||
|
# Exit codes from <sysexits.h>
|
||||||
|
EX_TEMPFAIL=75
|
||||||
|
EX_UNAVAILABLE=69
|
||||||
|
|
||||||
|
cd $INSPECT_DIR || { echo $INSPECT_DIR does not exist; exit $EX_TEMPFAIL; }
|
||||||
|
|
||||||
|
# Clean up when done or when aborting.
|
||||||
|
trap "rm -f in.$$; exit" 0 1 2 3 15
|
||||||
|
|
||||||
|
cat >in.$$ || { echo Cannot save mail to file; exit $EX_TEMPFAIL; }
|
||||||
|
|
||||||
|
# inspect <in.$$ || { echo Message content rejected; exit $EX_UNAVAILABLE; }
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
The idea is to first capture the message to file and then run the
|
||||||
|
content through run a third-party content inspection program. If
|
||||||
|
the mail cannot be captured to file, mail delivery is deferred by
|
||||||
|
terminating with exit status 75 (EX_TEMPFAIL). If the content
|
||||||
|
inspection program finds a problem, the mail is bounced by terminating
|
||||||
|
the shell script with exit status 69 (EX_UNAVAILABLE). An exit
|
||||||
|
status of zero means everything is hunky-dory and the mail can
|
||||||
|
be delivered to its recipients.
|
||||||
|
|
||||||
|
If mail is rejected, another possible action is to mail a copy to
|
||||||
|
the local postmaster. If you do that, be sure not to enable content
|
||||||
|
inspection for locally-posted mail or else rejected mail will loop.
|
||||||
|
|
||||||
|
The problem with content inspection sotware like this is that it is
|
||||||
|
not very robust, because the software does not talk a well-defined
|
||||||
|
protocol with Postfix. If the shell scripts aborts because the
|
||||||
|
shell runs into some memory allocation problem, the script will
|
||||||
|
not produce a nice exit status as per /usr/include/sysexits.h and
|
||||||
|
mail will probably bounce. The same lack of robustness is possible
|
||||||
|
when the content inspection software itself runs into a resource
|
||||||
|
problem.
|
||||||
|
|
||||||
|
I suggest that you play with this script for a while until you are
|
||||||
|
satisfied with the results. Run it as root or as the filter user,
|
||||||
|
with a real message (headers+body) as input:
|
||||||
|
|
||||||
|
# /some/where/inspect sender recipient... <message-file
|
||||||
|
|
||||||
|
Turn on content inspection for mail arriving via SMTP only, by
|
||||||
|
appending "-o content_inspector=inspect:dummy" to the master.cf
|
||||||
|
entry that defines the Postfix SMTP server:
|
||||||
|
|
||||||
|
/etc/postfix/master.cf:
|
||||||
|
smtp inet ...stuff... smtpd
|
||||||
|
-o content_inspector=inspect:dummy
|
||||||
|
|
||||||
|
The content_inspector configuration parameter accepts the same
|
||||||
|
syntax as the right-hand side in a Postfix transport table.
|
||||||
|
|
||||||
|
Advanced content inspection example
|
||||||
|
===================================
|
||||||
|
|
||||||
|
The second example is more complex, but can give better performance,
|
||||||
|
and is less likely to bounce mail when the machine runs into a
|
||||||
|
resource problem. This approach uses content inspection software
|
||||||
|
that can receive mail via SMTP, and that can run as a resident
|
||||||
|
server. You can expect to lose about a factor in Postfix performance
|
||||||
|
for every temporary file created.
|
||||||
|
|
||||||
|
We will set up a content inspection program listening on localhost
|
||||||
|
port 10025 that receives mail via the SMTP protocol.
|
||||||
|
|
||||||
|
..................................
|
||||||
|
. Postfix .
|
||||||
|
------smtpd \ /local-----
|
||||||
|
. -cleanup->queue- .
|
||||||
|
-----pickup / | \smtp------
|
||||||
|
. v .
|
||||||
|
. smtp .
|
||||||
|
. | .
|
||||||
|
......................|...........
|
||||||
|
|
|
||||||
|
v
|
||||||
|
.................
|
||||||
|
. 10025 .
|
||||||
|
. inspection .
|
||||||
|
. .
|
||||||
|
.................
|
||||||
|
|
||||||
|
To enable content inspection in this manner, specify in main.cf a
|
||||||
|
new parameter:
|
||||||
|
|
||||||
|
/etc/postfix/main.cf:
|
||||||
|
content_filter = smtp:localhost:10025
|
||||||
|
|
||||||
|
This causes Postfix to add one extra content inspection record to
|
||||||
|
each incoming mail message, with content smtp:localhost:10025.
|
||||||
|
You can use the same syntax as in the right-hand side of a Postfix
|
||||||
|
transport table. The content inspection records are added by the
|
||||||
|
smtpd and pickup servers.
|
||||||
|
|
||||||
|
When a queue file has content inspection information, the queue
|
||||||
|
manager will deliver the mail to the specified content inspector
|
||||||
|
before attempting final delivery.
|
||||||
|
|
||||||
|
The content filter can be set up with the Postfix spawn service,
|
||||||
|
which is the Postfix equivalent of inetd. For example, to instantiate
|
||||||
|
up to 10 content inspection processes on demand:
|
||||||
|
|
||||||
|
/etc/postfix/master.cf:
|
||||||
|
localhost:10025 inet n n n - 10 spawn
|
||||||
|
user=inspect argv=/some/where/inspect
|
||||||
|
|
||||||
|
"inspect" is a dedicated local user account. The user will never
|
||||||
|
log in, and can be given a "*" password and non-existent shell and
|
||||||
|
home.
|
||||||
|
|
||||||
|
The spawn server is part of Postfix but is not installed by default.
|
||||||
|
Edit the top-level Makefile.in file, run "make makefiles", "make",
|
||||||
|
and "make install". The manual page isn't installed by default,
|
||||||
|
either. See the spawn.c source file.
|
||||||
|
|
||||||
|
The /some/where/inspect command is most likely a PERL script. PERL
|
||||||
|
has modules that make talking SMTP easy.
|
||||||
|
|
||||||
|
For now, it is left up to the Postfix users to come up with a
|
||||||
|
PERL/SMTP framework for Postfix content inspection. If done well,
|
||||||
|
it can be used with other mailers too, which is a nice spin-off.
|
@ -1,3 +1,12 @@
|
|||||||
|
Incompatible changes with snapshot-20000625
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
The local delivery agent no longer appends a blank line to mail
|
||||||
|
that is delivered to external command.
|
||||||
|
|
||||||
|
The pipe delivery agent no longer appends a blank line when the F
|
||||||
|
flag is specified. Specify the B flag if you need that blank line.
|
||||||
|
|
||||||
Incompatible changes with snapshot-20000531
|
Incompatible changes with snapshot-20000531
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
|
BIN
postfix/base64/base64decode
Executable file
BIN
postfix/base64/base64decode
Executable file
Binary file not shown.
BIN
postfix/base64/base64encode
Executable file
BIN
postfix/base64/base64encode
Executable file
Binary file not shown.
@ -118,6 +118,8 @@ cleanup_envelope.o: ../include/tok822.h
|
|||||||
cleanup_envelope.o: ../include/resolve_clnt.h
|
cleanup_envelope.o: ../include/resolve_clnt.h
|
||||||
cleanup_envelope.o: ../include/mail_params.h
|
cleanup_envelope.o: ../include/mail_params.h
|
||||||
cleanup_envelope.o: ../include/ext_prop.h
|
cleanup_envelope.o: ../include/ext_prop.h
|
||||||
|
cleanup_envelope.o: ../include/mail_addr.h
|
||||||
|
cleanup_envelope.o: ../include/canon_addr.h
|
||||||
cleanup_envelope.o: cleanup.h
|
cleanup_envelope.o: cleanup.h
|
||||||
cleanup_envelope.o: ../include/argv.h
|
cleanup_envelope.o: ../include/argv.h
|
||||||
cleanup_envelope.o: ../include/maps.h
|
cleanup_envelope.o: ../include/maps.h
|
||||||
|
@ -8,12 +8,62 @@
|
|||||||
# The ldap_lookup_timeout parameter specifies the timeout for LDAP
|
# The ldap_lookup_timeout parameter specifies the timeout for LDAP
|
||||||
# database lookups.
|
# database lookups.
|
||||||
#
|
#
|
||||||
ldap_lookup_timeout = 10
|
#ldap_timeout = 10
|
||||||
|
|
||||||
# The ldap_search_base parameter specifies the LDAP database to search.
|
# The ldap_search_base parameter specifies the LDAP database to search.
|
||||||
#
|
#
|
||||||
ldap_search_base =
|
#ldap_search_base =
|
||||||
|
|
||||||
# The ldap_server_host parameter specifies the LDAP server hostname.
|
# The ldap_server_host parameter specifies the LDAP server hostname.
|
||||||
#
|
#
|
||||||
ldap_server_host =
|
#ldap_server_host = localhost
|
||||||
|
|
||||||
|
# The ldap_server_port parameter specifies the LDAP server port number.
|
||||||
|
#
|
||||||
|
#ldap_server_port = 389
|
||||||
|
|
||||||
|
# The ldap_query_filter parameter specifies the filter used for queries.
|
||||||
|
#
|
||||||
|
#ldap_query_filter = (mailacceptinggeneralid=%s)
|
||||||
|
|
||||||
|
# The ldap_result_attribute parameter specifies the attribute returned by
|
||||||
|
# the search.
|
||||||
|
#
|
||||||
|
#ldap_result_attribute = maildrop
|
||||||
|
|
||||||
|
# The ldap_scope parameter specifies the LDAP search scope: sub, base, or one.
|
||||||
|
#
|
||||||
|
#ldap_scope = sub
|
||||||
|
|
||||||
|
# The ldap_bind parameter specifies whether or not to bind to the server.
|
||||||
|
# LDAP v3 implementations don't require it, which saves some overhead.
|
||||||
|
#
|
||||||
|
#ldap_bind = yes
|
||||||
|
|
||||||
|
# The ldap_bind_dn parameter specifies what distinguished name to use
|
||||||
|
# when binding.
|
||||||
|
#
|
||||||
|
#ldap_bind_dn =
|
||||||
|
|
||||||
|
# The ldap_bind_pw parameter specifies the password to use.
|
||||||
|
#
|
||||||
|
#ldap_bind_pw =
|
||||||
|
|
||||||
|
# The ldap_cache parameter specifies whether or not to turn on client-side
|
||||||
|
# caching.
|
||||||
|
#
|
||||||
|
#ldap_cache = no
|
||||||
|
|
||||||
|
# The ldap_cache_expiry parameter specifies how many seconds to cache results
|
||||||
|
# for (if ldap_cache=yes)
|
||||||
|
#
|
||||||
|
#ldap_cache_expiry = 30
|
||||||
|
|
||||||
|
# The ldap_cache_size parameter specifies the cache size, in bytes.
|
||||||
|
#
|
||||||
|
#ldap_cache_size = 32768
|
||||||
|
|
||||||
|
# The ldap_deference parameter specifies how to handle LDAP aliases. See the
|
||||||
|
# ldap_open(3) man page.
|
||||||
|
#
|
||||||
|
#ldap_dereference = 0
|
||||||
|
@ -87,7 +87,8 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request,
|
|||||||
{
|
{
|
||||||
int stat;
|
int stat;
|
||||||
|
|
||||||
mail_print(stream, "%s %s %ld %ld %s %s %s %s %ld %ld %s %s",
|
mail_print(stream, "%d %s %s %ld %ld %s %s %s %s %ld %ld %s %s",
|
||||||
|
request->flags,
|
||||||
request->queue_name, request->queue_id,
|
request->queue_name, request->queue_id,
|
||||||
request->data_offset, request->data_size,
|
request->data_offset, request->data_size,
|
||||||
request->nexthop, request->sender,
|
request->nexthop, request->sender,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
/* typedef struct DELIVER_REQUEST {
|
/* typedef struct DELIVER_REQUEST {
|
||||||
/* .in +5
|
/* .in +5
|
||||||
/* VSTREAM *fp;
|
/* VSTREAM *fp;
|
||||||
|
/* int flags;
|
||||||
/* char *queue_name;
|
/* char *queue_name;
|
||||||
/* char *queue_id;
|
/* char *queue_id;
|
||||||
/* long data_offset;
|
/* long data_offset;
|
||||||
@ -40,6 +41,17 @@
|
|||||||
/* A null result means that the client sent bad information or that
|
/* A null result means that the client sent bad information or that
|
||||||
/* it went away unexpectedly.
|
/* it went away unexpectedly.
|
||||||
/*
|
/*
|
||||||
|
/* The \fBflags\fR structure member is the bit-wise OR of zero or more
|
||||||
|
/* of the following:
|
||||||
|
/* .IP \fBDEL_REQ_FLAG_SUCCESS\fR
|
||||||
|
/* Delete successful recipients from the queue file.
|
||||||
|
/* .IP \fBDEL_REQ_FLAG_BOUNCE\fR
|
||||||
|
/* Delete bounced recipients from the queue file. Currently,
|
||||||
|
/* this flag is considered to be "always on".
|
||||||
|
/* .PP
|
||||||
|
/* The \fBDEL_REQ_FLAG_DEFLT\fR constant provides a convenient shorthand
|
||||||
|
/* for the most common case: delete successful and bounced recipients.
|
||||||
|
/*
|
||||||
/* The \fIhop_status\fR structure member must be updated
|
/* The \fIhop_status\fR structure member must be updated
|
||||||
/* by the caller when all delivery to the destination in
|
/* by the caller when all delivery to the destination in
|
||||||
/* \fInexthop\fR should be deferred. The value of the
|
/* \fInexthop\fR should be deferred. The value of the
|
||||||
@ -174,7 +186,8 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request)
|
|||||||
* Extract the queue file name, data offset, and sender address. Abort
|
* Extract the queue file name, data offset, and sender address. Abort
|
||||||
* the conversation when they send bad information.
|
* the conversation when they send bad information.
|
||||||
*/
|
*/
|
||||||
if (mail_scan(stream, "%s %s %ld %ld %s %s %s %s %ld",
|
if (mail_scan(stream, "%d %s %s %ld %ld %s %s %s %s %ld",
|
||||||
|
&request->flags,
|
||||||
queue_name, queue_id, &request->data_offset,
|
queue_name, queue_id, &request->data_offset,
|
||||||
&request->data_size, nexthop, address,
|
&request->data_size, nexthop, address,
|
||||||
errors_to, return_receipt, &request->arrival_time) != 9)
|
errors_to, return_receipt, &request->arrival_time) != 9)
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
typedef struct DELIVER_REQUEST {
|
typedef struct DELIVER_REQUEST {
|
||||||
VSTREAM *fp; /* stream, shared lock */
|
VSTREAM *fp; /* stream, shared lock */
|
||||||
|
int flags; /* see below */
|
||||||
char *queue_name; /* message queue name */
|
char *queue_name; /* message queue name */
|
||||||
char *queue_id; /* message queue id */
|
char *queue_id; /* message queue id */
|
||||||
long data_offset; /* offset to message */
|
long data_offset; /* offset to message */
|
||||||
@ -40,6 +41,10 @@ typedef struct DELIVER_REQUEST {
|
|||||||
char *hop_status; /* reason if unavailable */
|
char *hop_status; /* reason if unavailable */
|
||||||
} DELIVER_REQUEST;
|
} DELIVER_REQUEST;
|
||||||
|
|
||||||
|
#define DEL_REQ_FLAG_DEFLT (DEL_REQ_FLAG_SUCCESS | DEL_REQ_FLAG_BOUNCE)
|
||||||
|
#define DEL_REQ_FLAG_SUCCESS (1<<0) /* delete successful recipients */
|
||||||
|
#define DEL_REQ_FLAG_BOUNCE (1<<1) /* unimplemented */
|
||||||
|
|
||||||
typedef struct VSTREAM _deliver_vstream_;
|
typedef struct VSTREAM _deliver_vstream_;
|
||||||
extern DELIVER_REQUEST *deliver_request_read(_deliver_vstream_ *);
|
extern DELIVER_REQUEST *deliver_request_read(_deliver_vstream_ *);
|
||||||
extern int deliver_request_done(_deliver_vstream_ *, DELIVER_REQUEST *, int);
|
extern int deliver_request_done(_deliver_vstream_ *, DELIVER_REQUEST *, int);
|
||||||
|
@ -51,13 +51,15 @@ static HEADER_OPTS header_opts[] = {
|
|||||||
"Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
|
"Apparently-To", HDR_APPARENTLY_TO, HDR_OPT_RECIP,
|
||||||
"Bcc", HDR_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP,
|
"Bcc", HDR_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP,
|
||||||
"Cc", HDR_CC, HDR_OPT_XRECIP,
|
"Cc", HDR_CC, HDR_OPT_XRECIP,
|
||||||
|
"Content-Length", HDR_CONTENT_LENGTH, HDR_OPT_DROP,
|
||||||
"Delivered-To", HDR_DELIVERED_TO, 0,
|
"Delivered-To", HDR_DELIVERED_TO, 0,
|
||||||
"Date", HDR_DATE, 0,
|
"Date", HDR_DATE, 0,
|
||||||
"Errors-To", HDR_ERRORS_TO, HDR_OPT_RECIP,
|
"Errors-To", HDR_ERRORS_TO, HDR_OPT_SENDER,
|
||||||
"From", HDR_FROM, HDR_OPT_SENDER,
|
"From", HDR_FROM, HDR_OPT_SENDER,
|
||||||
|
"Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
|
||||||
"Message-Id", HDR_MESSAGE_ID, 0,
|
"Message-Id", HDR_MESSAGE_ID, 0,
|
||||||
"Received", HDR_RECEIVED, 0,
|
"Received", HDR_RECEIVED, 0,
|
||||||
"Reply-To", HDR_REPLY_TO, HDR_OPT_RECIP,
|
"Reply-To", HDR_REPLY_TO, HDR_OPT_SENDER,
|
||||||
"Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP | HDR_OPT_RR,
|
"Resent-Bcc", HDR_RESENT_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP | HDR_OPT_RR,
|
||||||
"Resent-Cc", HDR_RESENT_CC, HDR_OPT_XRECIP | HDR_OPT_RR,
|
"Resent-Cc", HDR_RESENT_CC, HDR_OPT_XRECIP | HDR_OPT_RR,
|
||||||
"Resent-Date", HDR_RESENT_DATE, HDR_OPT_RR,
|
"Resent-Date", HDR_RESENT_DATE, HDR_OPT_RR,
|
||||||
@ -67,7 +69,7 @@ static HEADER_OPTS header_opts[] = {
|
|||||||
"Resent-Sender", HDR_RESENT_SENDER, HDR_OPT_SENDER | HDR_OPT_RR,
|
"Resent-Sender", HDR_RESENT_SENDER, HDR_OPT_SENDER | HDR_OPT_RR,
|
||||||
"Resent-To", HDR_RESENT_TO, HDR_OPT_XRECIP | HDR_OPT_RR,
|
"Resent-To", HDR_RESENT_TO, HDR_OPT_XRECIP | HDR_OPT_RR,
|
||||||
"Return-Path", HDR_RETURN_PATH, HDR_OPT_DROP | HDR_OPT_SENDER,
|
"Return-Path", HDR_RETURN_PATH, HDR_OPT_DROP | HDR_OPT_SENDER,
|
||||||
"Return-Receipt-To", HDR_RETURN_RECEIPT_TO, HDR_OPT_RECIP,
|
"Return-Receipt-To", HDR_RETURN_RECEIPT_TO, HDR_OPT_SENDER,
|
||||||
"Sender", HDR_SENDER, HDR_OPT_SENDER,
|
"Sender", HDR_SENDER, HDR_OPT_SENDER,
|
||||||
"To", HDR_TO, HDR_OPT_XRECIP,
|
"To", HDR_TO, HDR_OPT_XRECIP,
|
||||||
};
|
};
|
||||||
|
@ -48,6 +48,7 @@ typedef struct {
|
|||||||
#define HDR_RETURN_RECEIPT_TO 23
|
#define HDR_RETURN_RECEIPT_TO 23
|
||||||
#define HDR_SENDER 24
|
#define HDR_SENDER 24
|
||||||
#define HDR_TO 25
|
#define HDR_TO 25
|
||||||
|
#define HDR_MAIL_FOLLOWUP_TO 26
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Header flags.
|
* Header flags.
|
||||||
|
@ -186,7 +186,7 @@ int mail_copy(const char *sender, const char *delivered,
|
|||||||
corrupt_error = mark_corrupt(src);
|
corrupt_error = mark_corrupt(src);
|
||||||
if (prev_type != REC_TYPE_NORM)
|
if (prev_type != REC_TYPE_NORM)
|
||||||
vstream_fputs(eol, dst);
|
vstream_fputs(eol, dst);
|
||||||
if (flags & MAIL_COPY_FROM)
|
if (flags & MAIL_COPY_BLANK)
|
||||||
vstream_fputs(eol, dst);
|
vstream_fputs(eol, dst);
|
||||||
}
|
}
|
||||||
vstring_free(buf);
|
vstring_free(buf);
|
||||||
|
@ -29,9 +29,10 @@ extern int mail_copy(const char *, const char *, VSTREAM *, VSTREAM *,
|
|||||||
#define MAIL_COPY_DELIVERED (1<<3) /* prepend Delivered-To: */
|
#define MAIL_COPY_DELIVERED (1<<3) /* prepend Delivered-To: */
|
||||||
#define MAIL_COPY_RETURN_PATH (1<<4) /* prepend Return-Path: */
|
#define MAIL_COPY_RETURN_PATH (1<<4) /* prepend Return-Path: */
|
||||||
#define MAIL_COPY_DOT (1<<5) /* escape dots - needed for bsmtp */
|
#define MAIL_COPY_DOT (1<<5) /* escape dots - needed for bsmtp */
|
||||||
|
#define MAIL_COPY_BLANK (1<<6) /* append blank line */
|
||||||
#define MAIL_COPY_MBOX (MAIL_COPY_FROM | MAIL_COPY_QUOTE | \
|
#define MAIL_COPY_MBOX (MAIL_COPY_FROM | MAIL_COPY_QUOTE | \
|
||||||
MAIL_COPY_TOFILE | MAIL_COPY_DELIVERED | \
|
MAIL_COPY_TOFILE | MAIL_COPY_DELIVERED | \
|
||||||
MAIL_COPY_RETURN_PATH)
|
MAIL_COPY_RETURN_PATH | MAIL_COPY_BLANK)
|
||||||
#define MAIL_COPY_NONE 0 /* all turned off */
|
#define MAIL_COPY_NONE 0 /* all turned off */
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
|
@ -381,10 +381,14 @@ extern char *var_fwd_exp_filter;
|
|||||||
#define DEF_DELIVER_HDR "command, file, forward"
|
#define DEF_DELIVER_HDR "command, file, forward"
|
||||||
extern char *var_deliver_hdr;
|
extern char *var_deliver_hdr;
|
||||||
|
|
||||||
#define VAR_EXP_OWN_ALIAS "expand_owner_alias"
|
#define VAR_EXP_OWN_ALIAS "expand_owner_alias"
|
||||||
#define DEF_EXP_OWN_ALIAS 0
|
#define DEF_EXP_OWN_ALIAS 0
|
||||||
extern bool var_exp_own_alias;
|
extern bool var_exp_own_alias;
|
||||||
|
|
||||||
|
#define VAR_STAT_HOME_DIR "test_home_directory"
|
||||||
|
#define DEF_STAT_HOME_DIR 0
|
||||||
|
extern bool var_stat_home_dir;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Queue manager: maximal size of the duplicate expansion filter. By
|
* Queue manager: maximal size of the duplicate expansion filter. By
|
||||||
* default, we do graceful degradation with huge mailing lists.
|
* default, we do graceful degradation with huge mailing lists.
|
||||||
|
@ -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-20000531"
|
#define DEF_MAIL_VERSION "Snapshot-20000625"
|
||||||
extern char *var_mail_version;
|
extern char *var_mail_version;
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
|
@ -1020,10 +1020,9 @@ types Postfix supports, use the command <b>postconf -m</b>.
|
|||||||
<p>
|
<p>
|
||||||
|
|
||||||
N.B. Some non-Postfix software such as <a
|
N.B. Some non-Postfix software such as <a
|
||||||
href="http://www.mbnet.mb.ca/howto/dynamic.htm">DRAC</a> uses
|
href="http://mail.cc.umanitoba.ca/drac/">DRAC</a> uses <b>btree</b>
|
||||||
<b>btree</b> files instead of <b>hash</b> files. In that case,
|
files instead of <b>hash</b> files. In that case, you will have
|
||||||
you will have to adjust the above <b>check_client_access</b>
|
to adjust the above <b>check_client_access</b> restriction accordingly.
|
||||||
restriction accordingly.
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ LOCAL(8) LOCAL(8)
|
|||||||
lope header to each message, prepends an optional <b>Deliv-</b>
|
lope header to each message, prepends an optional <b>Deliv-</b>
|
||||||
<b>ered-To:</b> header with the recipient envelope address,
|
<b>ered-To:</b> header with the recipient envelope address,
|
||||||
prepends a <b>Return-Path:</b> header with the sender envelope
|
prepends a <b>Return-Path:</b> header with the sender envelope
|
||||||
address, and appends an empty line.
|
address, and appends no empty line.
|
||||||
|
|
||||||
<b>EXTERNAL</b> <b>FILE</b> <b>DELIVERY</b>
|
<b>EXTERNAL</b> <b>FILE</b> <b>DELIVERY</b>
|
||||||
The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b> configuration parameter restricts
|
The <b>allow</b><i>_</i><b>mail</b><i>_</i><b>to</b><i>_</i><b>files</b> configuration parameter restricts
|
||||||
@ -277,7 +277,7 @@ LOCAL(8) LOCAL(8)
|
|||||||
the <b>default</b><i>_</i><b>privs</b> configuration parameter.
|
the <b>default</b><i>_</i><b>privs</b> configuration parameter.
|
||||||
|
|
||||||
<b>STANDARDS</b>
|
<b>STANDARDS</b>
|
||||||
RFC 822 (ARPA Internet Text Messages)
|
<a href="http://www.faqs.org/rfcs/rfc822.html">RFC 822</a> (ARPA Internet Text Messages)
|
||||||
|
|
||||||
<b>DIAGNOSTICS</b>
|
<b>DIAGNOSTICS</b>
|
||||||
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
|
Problems and transactions are logged to <b>syslogd</b>(8). Cor-
|
||||||
@ -352,6 +352,10 @@ LOCAL(8) LOCAL(8)
|
|||||||
<b>recipient</b><i>_</i><b>delimiter</b>
|
<b>recipient</b><i>_</i><b>delimiter</b>
|
||||||
Separator between username and address extension.
|
Separator between username and address extension.
|
||||||
|
|
||||||
|
<b>test</b><i>_</i><b>home</b><i>_</i><b>directory</b>
|
||||||
|
Require that a recipient's home directory is acces-
|
||||||
|
sible by the recipient before attempting delivery.
|
||||||
|
|
||||||
<b>Mailbox</b> <b>delivery</b>
|
<b>Mailbox</b> <b>delivery</b>
|
||||||
<b>fallback</b><i>_</i><b>transport</b>
|
<b>fallback</b><i>_</i><b>transport</b>
|
||||||
Message transport for recipients that are not found
|
Message transport for recipients that are not found
|
||||||
@ -385,10 +389,6 @@ LOCAL(8) LOCAL(8)
|
|||||||
rides all other configuration parameters that con-
|
rides all other configuration parameters that con-
|
||||||
trol mailbox delivery, including <b>luser</b><i>_</i><b>relay</b>.
|
trol mailbox delivery, including <b>luser</b><i>_</i><b>relay</b>.
|
||||||
|
|
||||||
<b>Locking</b> <b>controls</b>
|
|
||||||
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
|
|
||||||
Limit the number of attempts to acquire an exclu-
|
|
||||||
sive lock on a mailbox or external file.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -401,6 +401,11 @@ LOCAL(8) LOCAL(8)
|
|||||||
LOCAL(8) LOCAL(8)
|
LOCAL(8) LOCAL(8)
|
||||||
|
|
||||||
|
|
||||||
|
<b>Locking</b> <b>controls</b>
|
||||||
|
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>attempts</b>
|
||||||
|
Limit the number of attempts to acquire an exclu-
|
||||||
|
sive lock on a mailbox or external file.
|
||||||
|
|
||||||
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
|
<b>deliver</b><i>_</i><b>lock</b><i>_</i><b>delay</b>
|
||||||
Time in seconds between successive attempts to
|
Time in seconds between successive attempts to
|
||||||
acquire an exclusive lock.
|
acquire an exclusive lock.
|
||||||
@ -449,11 +454,6 @@ LOCAL(8) LOCAL(8)
|
|||||||
Default rights for delivery to external file or
|
Default rights for delivery to external file or
|
||||||
command.
|
command.
|
||||||
|
|
||||||
<b>forward</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
|
|
||||||
What characters are allowed to appear in $name
|
|
||||||
expansions of forward_path. Illegal characters are
|
|
||||||
replaced by underscores.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -467,6 +467,11 @@ LOCAL(8) LOCAL(8)
|
|||||||
LOCAL(8) LOCAL(8)
|
LOCAL(8) LOCAL(8)
|
||||||
|
|
||||||
|
|
||||||
|
<b>forward</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>
|
||||||
|
What characters are allowed to appear in $name
|
||||||
|
expansions of forward_path. Illegal characters are
|
||||||
|
replaced by underscores.
|
||||||
|
|
||||||
<b>HISTORY</b>
|
<b>HISTORY</b>
|
||||||
The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
|
The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
|
||||||
Daniel Bernstein.
|
Daniel Bernstein.
|
||||||
@ -513,11 +518,6 @@ LOCAL(8) LOCAL(8)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,23 +30,28 @@ PIPE(8) PIPE(8)
|
|||||||
file at the end of a service definition. The syntax is as
|
file at the end of a service definition. The syntax is as
|
||||||
follows:
|
follows:
|
||||||
|
|
||||||
<b>flags=FR.</b>> (optional)
|
<b>flags=BFR.</b>> (optional)
|
||||||
Optional message processing flags. By default, a
|
Optional message processing flags. By default, a
|
||||||
message is copied unchanged.
|
message is copied unchanged.
|
||||||
|
|
||||||
<b>F</b> Prepend a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope
|
<b>B</b> Append a blank line at the end of each mes-
|
||||||
header to the message content. This is
|
sage. This is required by some mail user
|
||||||
|
agents that recognize "<b>From</b> " lines only
|
||||||
|
when preceded by a blank line.
|
||||||
|
|
||||||
|
<b>F</b> Prepend a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope
|
||||||
|
header to the message content. This is
|
||||||
expected by, for example, <b>UUCP</b> software. The
|
expected by, for example, <b>UUCP</b> software. The
|
||||||
<b>F</b> flag also causes an empty line to be
|
<b>F</b> flag also causes an empty line to be
|
||||||
appended to the message.
|
appended to the message.
|
||||||
|
|
||||||
<b>R</b> Prepend a <b>Return-Path:</b> message header with
|
<b>R</b> Prepend a <b>Return-Path:</b> message header with
|
||||||
the envelope sender address.
|
the envelope sender address.
|
||||||
|
|
||||||
<b>.</b> Prepend <b>.</b> to lines starting with "<b>.</b>". This
|
<b>.</b> Prepend <b>.</b> to lines starting with "<b>.</b>". This
|
||||||
is needed by, for example, <b>BSMTP</b> software.
|
is needed by, for example, <b>BSMTP</b> software.
|
||||||
|
|
||||||
> Prepend > to lines starting with "<b>From</b> ".
|
> Prepend > to lines starting with "<b>From</b> ".
|
||||||
This is expected by, for example, <b>UUCP</b> soft-
|
This is expected by, for example, <b>UUCP</b> soft-
|
||||||
ware.
|
ware.
|
||||||
|
|
||||||
@ -54,11 +59,6 @@ PIPE(8) PIPE(8)
|
|||||||
|
|
||||||
<b>user</b>=<i>username</i>:<i>groupname</i>
|
<b>user</b>=<i>username</i>:<i>groupname</i>
|
||||||
The external command is executed with the rights of
|
The external command is executed with the rights of
|
||||||
the specified <i>username</i>. The software refuses to
|
|
||||||
execute commands with root privileges, or with the
|
|
||||||
privileges of the mail system owner. If <i>groupname</i>
|
|
||||||
is specified, the corresponding group ID is used
|
|
||||||
instead of the group ID of <i>username</i>.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -71,12 +71,22 @@ PIPE(8) PIPE(8)
|
|||||||
PIPE(8) PIPE(8)
|
PIPE(8) PIPE(8)
|
||||||
|
|
||||||
|
|
||||||
|
the specified <i>username</i>. The software refuses to
|
||||||
|
execute commands with root privileges, or with the
|
||||||
|
privileges of the mail system owner. If <i>groupname</i>
|
||||||
|
is specified, the corresponding group ID is used
|
||||||
|
instead of the group ID of <i>username</i>.
|
||||||
|
|
||||||
<b>eol=string</b> (default: <b>\n</b>)
|
<b>eol=string</b> (default: <b>\n</b>)
|
||||||
The output record delimiter. Typically one would
|
The output record delimiter. Typically one would
|
||||||
use either <b>\r\n</b> or <b>\n</b>. The usual C-style backslash
|
use either <b>\r\n</b> or <b>\n</b>. The usual C-style backslash
|
||||||
escape sequences are recognized: <b>\a</b> <b>\b</b> <b>\f</b> <b>\n</b> <b>\r</b> <b>\t</b>
|
escape sequences are recognized: <b>\a</b> <b>\b</b> <b>\f</b> <b>\n</b> <b>\r</b> <b>\t</b>
|
||||||
<b>\v</b> <b>\</b><i>octal</i> and <b>\\</b>.
|
<b>\v</b> <b>\</b><i>octal</i> and <b>\\</b>.
|
||||||
|
|
||||||
|
<b>size</b>=<i>size_limit</i> (optional)
|
||||||
|
Messages greater in size than this limit (in bytes)
|
||||||
|
will be bounced back to the sender.
|
||||||
|
|
||||||
<b>argv</b>=<i>command</i>... (required)
|
<b>argv</b>=<i>command</i>... (required)
|
||||||
The command to be executed. This must be specified
|
The command to be executed. This must be specified
|
||||||
as the last command attribute. The command is exe-
|
as the last command attribute. The command is exe-
|
||||||
@ -115,16 +125,6 @@ PIPE(8) PIPE(8)
|
|||||||
tains <b>${recipient</b>} expands into as many com-
|
tains <b>${recipient</b>} expands into as many com-
|
||||||
mand-line arguments as there are recipients.
|
mand-line arguments as there are recipients.
|
||||||
|
|
||||||
<b>${sender</b>}
|
|
||||||
This macro expands to the envelope sender
|
|
||||||
address.
|
|
||||||
|
|
||||||
<b>${user</b>}
|
|
||||||
This macro expands to the username part of a
|
|
||||||
recipient address. For example, with an
|
|
||||||
address <i>user+foo@domain</i> the username part is
|
|
||||||
<i>user</i>. A command-line argument that contains
|
|
||||||
<b>${user</b>} expands into as many command-line
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -137,6 +137,16 @@ PIPE(8) PIPE(8)
|
|||||||
PIPE(8) PIPE(8)
|
PIPE(8) PIPE(8)
|
||||||
|
|
||||||
|
|
||||||
|
<b>${sender</b>}
|
||||||
|
This macro expands to the envelope sender
|
||||||
|
address.
|
||||||
|
|
||||||
|
<b>${user</b>}
|
||||||
|
This macro expands to the username part of a
|
||||||
|
recipient address. For example, with an
|
||||||
|
address <i>user+foo@domain</i> the username part is
|
||||||
|
<i>user</i>. A command-line argument that contains
|
||||||
|
<b>${user</b>} expands into as many command-line
|
||||||
arguments as there are recipients.
|
arguments as there are recipients.
|
||||||
|
|
||||||
In addition to the form ${<i>name</i>}, the forms $<i>name</i> and
|
In addition to the form ${<i>name</i>}, the forms $<i>name</i> and
|
||||||
@ -180,17 +190,7 @@ PIPE(8) PIPE(8)
|
|||||||
enforced by the Postfix queue manager.
|
enforced by the Postfix queue manager.
|
||||||
|
|
||||||
<i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
|
<i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
|
||||||
Limit the number of recipients per message deliv-
|
Limit the number of recipients per message
|
||||||
ery, for delivery via the named <i>transport</i>. The
|
|
||||||
default limit is taken from the <b>default</b><i>_</i><b>destina-</b>
|
|
||||||
<b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter. The limit is
|
|
||||||
enforced by the Postfix queue manager.
|
|
||||||
|
|
||||||
<i>transport_</i><b>time</b><i>_</i><b>limit</b>
|
|
||||||
Limit the time for delivery to external command,
|
|
||||||
for delivery via the named <b>transport</b>. The default
|
|
||||||
limit is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> parame-
|
|
||||||
ter. The limit is enforced by the Postfix queue
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -203,6 +203,16 @@ PIPE(8) PIPE(8)
|
|||||||
PIPE(8) PIPE(8)
|
PIPE(8) PIPE(8)
|
||||||
|
|
||||||
|
|
||||||
|
delivery, for delivery via the named <i>transport</i>. The
|
||||||
|
default limit is taken from the <b>default</b><i>_</i><b>destina-</b>
|
||||||
|
<b>tion</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter. The limit is
|
||||||
|
enforced by the Postfix queue manager.
|
||||||
|
|
||||||
|
<i>transport_</i><b>time</b><i>_</i><b>limit</b>
|
||||||
|
Limit the time for delivery to external command,
|
||||||
|
for delivery via the named <b>transport</b>. The default
|
||||||
|
limit is taken from the <b>command</b><i>_</i><b>time</b><i>_</i><b>limit</b> parame-
|
||||||
|
ter. The limit is enforced by the Postfix queue
|
||||||
manager.
|
manager.
|
||||||
|
|
||||||
<b>SEE</b> <b>ALSO</b>
|
<b>SEE</b> <b>ALSO</b>
|
||||||
@ -239,16 +249,6 @@ PIPE(8) PIPE(8)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,6 +75,9 @@ SMTP(8) SMTP(8)
|
|||||||
command after a configuration change.
|
command after a configuration change.
|
||||||
|
|
||||||
<b>Miscellaneous</b>
|
<b>Miscellaneous</b>
|
||||||
|
<b>append</b><i>_</i><b>dot</b><i>_</i><b>mydomain</b>
|
||||||
|
Rewrite <i>user</i>@<i>host</i> to <i>user</i>@<i>host</i>.$<b>mydomain</b>.
|
||||||
|
|
||||||
<b>best</b><i>_</i><b>mx</b><i>_</i><b>transport</b>
|
<b>best</b><i>_</i><b>mx</b><i>_</i><b>transport</b>
|
||||||
Name of the delivery transport to use when the
|
Name of the delivery transport to use when the
|
||||||
local machine is the most-preferred mail exchanger
|
local machine is the most-preferred mail exchanger
|
||||||
@ -123,9 +126,6 @@ SMTP(8) SMTP(8)
|
|||||||
<b>smtp</b><i>_</i><b>always</b><i>_</i><b>send</b><i>_</i><b>ehlo</b>
|
<b>smtp</b><i>_</i><b>always</b><i>_</i><b>send</b><i>_</i><b>ehlo</b>
|
||||||
Always send EHLO at the start of a connection.
|
Always send EHLO at the start of a connection.
|
||||||
|
|
||||||
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
|
|
||||||
Skip servers that greet us with a 4xx status code.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2
|
2
|
||||||
@ -137,6 +137,9 @@ SMTP(8) SMTP(8)
|
|||||||
SMTP(8) SMTP(8)
|
SMTP(8) SMTP(8)
|
||||||
|
|
||||||
|
|
||||||
|
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>4xx</b><i>_</i><b>greeting</b>
|
||||||
|
Skip servers that greet us with a 4xx status code.
|
||||||
|
|
||||||
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>5xx</b><i>_</i><b>greeting</b>
|
<b>smtp</b><i>_</i><b>skip</b><i>_</i><b>5xx</b><i>_</i><b>greeting</b>
|
||||||
Skip servers that greet us with a 5xx status code.
|
Skip servers that greet us with a 5xx status code.
|
||||||
|
|
||||||
@ -188,9 +191,6 @@ SMTP(8) SMTP(8)
|
|||||||
ery. The default limit is taken from the
|
ery. The default limit is taken from the
|
||||||
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
|
<b>default</b><i>_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b> parameter.
|
||||||
|
|
||||||
<b>Timeout</b> <b>controls</b>
|
|
||||||
<b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
|
|
||||||
Timeout in seconds for completing a TCP connection.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -203,6 +203,9 @@ SMTP(8) SMTP(8)
|
|||||||
SMTP(8) SMTP(8)
|
SMTP(8) SMTP(8)
|
||||||
|
|
||||||
|
|
||||||
|
<b>Timeout</b> <b>controls</b>
|
||||||
|
<b>smtp</b><i>_</i><b>connect</b><i>_</i><b>timeout</b>
|
||||||
|
Timeout in seconds for completing a TCP connection.
|
||||||
When no connection can be made within the deadline,
|
When no connection can be made within the deadline,
|
||||||
the SMTP client tries the next address on the mail
|
the SMTP client tries the next address on the mail
|
||||||
exchanger list.
|
exchanger list.
|
||||||
@ -254,9 +257,6 @@ SMTP(8) SMTP(8)
|
|||||||
The Secure Mailer license must be distributed with this
|
The Secure Mailer license must be distributed with this
|
||||||
software.
|
software.
|
||||||
|
|
||||||
<b>AUTHOR(S)</b>
|
|
||||||
Wietse Venema
|
|
||||||
IBM T.J. Watson Research
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -269,6 +269,9 @@ SMTP(8) SMTP(8)
|
|||||||
SMTP(8) SMTP(8)
|
SMTP(8) SMTP(8)
|
||||||
|
|
||||||
|
|
||||||
|
<b>AUTHOR(S)</b>
|
||||||
|
Wietse Venema
|
||||||
|
IBM T.J. Watson Research
|
||||||
P.O. Box 704
|
P.O. Box 704
|
||||||
Yorktown Heights, NY 10598, USA
|
Yorktown Heights, NY 10598, USA
|
||||||
|
|
||||||
@ -319,9 +322,6 @@ SMTP(8) SMTP(8)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -531,7 +531,8 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state)
|
|||||||
sent(request->queue_id, rcpt->address,
|
sent(request->queue_id, rcpt->address,
|
||||||
session->namaddr, request->arrival_time,
|
session->namaddr, request->arrival_time,
|
||||||
"%s", resp->str);
|
"%s", resp->str);
|
||||||
deliver_completed(state->src, rcpt->offset);
|
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||||
|
deliver_completed(state->src, rcpt->offset);
|
||||||
rcpt->offset = 0;
|
rcpt->offset = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -64,6 +64,7 @@
|
|||||||
#include <vstream.h>
|
#include <vstream.h>
|
||||||
#include <htable.h>
|
#include <htable.h>
|
||||||
#include <open_as.h>
|
#include <open_as.h>
|
||||||
|
#include <stat_as.h>
|
||||||
#include <lstat_as.h>
|
#include <lstat_as.h>
|
||||||
#include <iostuff.h>
|
#include <iostuff.h>
|
||||||
#include <stringops.h>
|
#include <stringops.h>
|
||||||
@ -78,6 +79,7 @@
|
|||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <mail_conf.h>
|
#include <mail_conf.h>
|
||||||
#include <ext_prop.h>
|
#include <ext_prop.h>
|
||||||
|
#include <defer.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@ -112,18 +114,36 @@ int deliver_dotforward(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
|
|||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
MSG_LOG_STATE(myname, state);
|
MSG_LOG_STATE(myname, state);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip non-existing users. The mailbox delivery routine will catch the
|
||||||
|
* error.
|
||||||
|
*
|
||||||
|
* Defer delivery to recipients whose home directory is not accessible.
|
||||||
|
*
|
||||||
|
* XXX This code should be one level up. The caller should pass the
|
||||||
|
* recipient's password file info along with the call.
|
||||||
|
*
|
||||||
|
* XXX This code should also be executed for \user deliveries that bypass
|
||||||
|
* aliasing and .forward processing. Said code is currently broken after
|
||||||
|
* a revision of the RFC822 address parser.
|
||||||
|
*/
|
||||||
|
if ((mypwd = mypwnam(state.msg_attr.user)) == 0)
|
||||||
|
return (NO);
|
||||||
|
if (var_stat_home_dir
|
||||||
|
&& stat_as(mypwd->pw_dir, &st, mypwd->pw_uid, mypwd->pw_gid) < 0) {
|
||||||
|
*statusp = defer_append(BOUNCE_FLAG_KEEP,
|
||||||
|
BOUNCE_ATTR(state.msg_attr),
|
||||||
|
"cannot access %s home directory %s: %m",
|
||||||
|
mypwd->pw_name, mypwd->pw_dir);
|
||||||
|
return (YES);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip this module if per-user forwarding is disabled.
|
* Skip this module if per-user forwarding is disabled.
|
||||||
*/
|
*/
|
||||||
if (*var_forward_path == 0)
|
if (*var_forward_path == 0)
|
||||||
return (NO);
|
return (NO);
|
||||||
|
|
||||||
/*
|
|
||||||
* Skip non-existing users. The mailbox delivery routine will catch the
|
|
||||||
* error.
|
|
||||||
*/
|
|
||||||
if ((mypwd = mypwnam(state.msg_attr.user)) == 0)
|
|
||||||
return (NO);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From here on no early returns or we have a memory leak.
|
* From here on no early returns or we have a memory leak.
|
||||||
|
@ -173,7 +173,7 @@
|
|||||||
/* optional \fBDelivered-To:\fR
|
/* optional \fBDelivered-To:\fR
|
||||||
/* header with the recipient envelope address, prepends a
|
/* header with the recipient envelope address, prepends a
|
||||||
/* \fBReturn-Path:\fR header with the sender envelope address,
|
/* \fBReturn-Path:\fR header with the sender envelope address,
|
||||||
/* and appends an empty line.
|
/* and appends no empty line.
|
||||||
/* EXTERNAL FILE DELIVERY
|
/* EXTERNAL FILE DELIVERY
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -278,6 +278,9 @@
|
|||||||
/* forwarding mail is not recommended.
|
/* forwarding mail is not recommended.
|
||||||
/* .IP \fBrecipient_delimiter\fR
|
/* .IP \fBrecipient_delimiter\fR
|
||||||
/* Separator between username and address extension.
|
/* Separator between username and address extension.
|
||||||
|
/* .IP \fBtest_home_directory\fR
|
||||||
|
/* Require that a recipient's home directory is accessible by the
|
||||||
|
/* recipient before attempting delivery.
|
||||||
/* .SH Mailbox delivery
|
/* .SH Mailbox delivery
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
@ -439,6 +442,7 @@ char *var_fwd_exp_filter;
|
|||||||
char *var_prop_extension;
|
char *var_prop_extension;
|
||||||
int var_exp_own_alias;
|
int var_exp_own_alias;
|
||||||
char *var_deliver_hdr;
|
char *var_deliver_hdr;
|
||||||
|
int var_stat_home_dir;
|
||||||
|
|
||||||
int local_cmd_deliver_mask;
|
int local_cmd_deliver_mask;
|
||||||
int local_file_deliver_mask;
|
int local_file_deliver_mask;
|
||||||
@ -500,7 +504,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service)
|
|||||||
state.msg_attr.recipient = rcpt->address;
|
state.msg_attr.recipient = rcpt->address;
|
||||||
rcpt_stat = deliver_recipient(state, usr_attr);
|
rcpt_stat = deliver_recipient(state, usr_attr);
|
||||||
rcpt_stat |= forward_finish(state.msg_attr, rcpt_stat);
|
rcpt_stat |= forward_finish(state.msg_attr, rcpt_stat);
|
||||||
if (rcpt_stat == 0)
|
if (rcpt_stat == 0 && (rqst->flags & DEL_REQ_FLAG_SUCCESS))
|
||||||
deliver_completed(state.msg_attr.fp, rcpt->offset);
|
deliver_completed(state.msg_attr.fp, rcpt->offset);
|
||||||
been_here_free(state.dup_filter);
|
been_here_free(state.dup_filter);
|
||||||
msg_stat |= rcpt_stat;
|
msg_stat |= rcpt_stat;
|
||||||
@ -618,6 +622,7 @@ int main(int argc, char **argv)
|
|||||||
static CONFIG_BOOL_TABLE bool_table[] = {
|
static CONFIG_BOOL_TABLE bool_table[] = {
|
||||||
VAR_BIFF, DEF_BIFF, &var_biff,
|
VAR_BIFF, DEF_BIFF, &var_biff,
|
||||||
VAR_EXP_OWN_ALIAS, DEF_EXP_OWN_ALIAS, &var_exp_own_alias,
|
VAR_EXP_OWN_ALIAS, DEF_EXP_OWN_ALIAS, &var_exp_own_alias,
|
||||||
|
VAR_STAT_HOME_DIR, DEF_STAT_HOME_DIR, &var_stat_home_dir,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -143,11 +143,11 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
|
|||||||
|| sane_link(tmpfile, newfile) < 0)) {
|
|| sane_link(tmpfile, newfile) < 0)) {
|
||||||
vstring_sprintf(why, "link to %s: %m", newfile);
|
vstring_sprintf(why, "link to %s: %m", newfile);
|
||||||
} else {
|
} else {
|
||||||
if (unlink(tmpfile) < 0)
|
|
||||||
msg_warn("remove %s: %m", tmpfile);
|
|
||||||
status = 0;
|
status = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (unlink(tmpfile) < 0)
|
||||||
|
msg_warn("remove %s: %m", tmpfile);
|
||||||
}
|
}
|
||||||
set_eugid(var_owner_uid, var_owner_gid);
|
set_eugid(var_owner_uid, var_owner_gid);
|
||||||
|
|
||||||
|
@ -104,6 +104,10 @@ static int deliver_switch(LOCAL_STATE state, USER_ATTR usr_attr)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* \user is special: it means don't do any alias or forward expansion.
|
* \user is special: it means don't do any alias or forward expansion.
|
||||||
|
*
|
||||||
|
* XXX This code currently does not work due to revision of the RFC822
|
||||||
|
* address parser. \user should be permitted only in locally specified
|
||||||
|
* aliases, includes or forward files.
|
||||||
*/
|
*/
|
||||||
if (state.msg_attr.recipient[0] == '\\') {
|
if (state.msg_attr.recipient[0] == '\\') {
|
||||||
state.msg_attr.recipient++, state.msg_attr.local++, state.msg_attr.user++;
|
state.msg_attr.recipient++, state.msg_attr.local++, state.msg_attr.user++;
|
||||||
|
@ -147,7 +147,7 @@ case "$SYSTEM.$RELEASE" in
|
|||||||
case "$CC" in
|
case "$CC" in
|
||||||
cc|*/cc|xlc|*/xlc) OPT=; CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
|
cc|*/cc|xlc|*/xlc) OPT=; CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
|
||||||
esac
|
esac
|
||||||
CCARGS="$CCARGS -D_ALL_SOURCE"
|
CCARGS="$CCARGS -D_ALL_SOURCE -DHAS_POSIX_REGEXP"
|
||||||
;;
|
;;
|
||||||
3) SYSTYPE=AIX3
|
3) SYSTYPE=AIX3
|
||||||
# How embarrassing...
|
# How embarrassing...
|
||||||
|
@ -187,7 +187,7 @@ envelope header to each message, prepends an
|
|||||||
optional \fBDelivered-To:\fR
|
optional \fBDelivered-To:\fR
|
||||||
header with the recipient envelope address, prepends a
|
header with the recipient envelope address, prepends a
|
||||||
\fBReturn-Path:\fR header with the sender envelope address,
|
\fBReturn-Path:\fR header with the sender envelope address,
|
||||||
and appends an empty line.
|
and appends no empty line.
|
||||||
.SH EXTERNAL FILE DELIVERY
|
.SH EXTERNAL FILE DELIVERY
|
||||||
.na
|
.na
|
||||||
.nf
|
.nf
|
||||||
@ -306,6 +306,9 @@ forwarding, delivery to command or file. Specify zero or more of:
|
|||||||
forwarding mail is not recommended.
|
forwarding mail is not recommended.
|
||||||
.IP \fBrecipient_delimiter\fR
|
.IP \fBrecipient_delimiter\fR
|
||||||
Separator between username and address extension.
|
Separator between username and address extension.
|
||||||
|
.IP \fBtest_home_directory\fR
|
||||||
|
Require that a recipient's home directory is accessible by the
|
||||||
|
recipient before attempting delivery.
|
||||||
.SH Mailbox delivery
|
.SH Mailbox delivery
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
|
@ -30,10 +30,14 @@ to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
|
|||||||
.fi
|
.fi
|
||||||
The external command attributes are given in the \fBmaster.cf\fR
|
The external command attributes are given in the \fBmaster.cf\fR
|
||||||
file at the end of a service definition. The syntax is as follows:
|
file at the end of a service definition. The syntax is as follows:
|
||||||
.IP "\fBflags=FR.>\fR (optional)"
|
.IP "\fBflags=BFR.>\fR (optional)"
|
||||||
Optional message processing flags. By default, a message is
|
Optional message processing flags. By default, a message is
|
||||||
copied unchanged.
|
copied unchanged.
|
||||||
.RS
|
.RS
|
||||||
|
.IP \fBB\fR
|
||||||
|
Append a blank line at the end of each message. This is required
|
||||||
|
by some mail user agents that recognize "\fBFrom \fR" lines only
|
||||||
|
when preceded by a blank line.
|
||||||
.IP \fBF\fR
|
.IP \fBF\fR
|
||||||
Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
|
Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
|
||||||
the message content.
|
the message content.
|
||||||
@ -62,6 +66,9 @@ The output record delimiter. Typically one would use either
|
|||||||
\fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
|
\fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
|
||||||
sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
|
sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
|
||||||
\e\fIoctal\fR and \fB\e\e\fR.
|
\e\fIoctal\fR and \fB\e\e\fR.
|
||||||
|
.IP "\fBsize\fR=\fIsize_limit\fR (optional)"
|
||||||
|
Messages greater in size than this limit (in bytes) will be bounced
|
||||||
|
back to the sender.
|
||||||
.IP "\fBargv\fR=\fIcommand\fR... (required)"
|
.IP "\fBargv\fR=\fIcommand\fR... (required)"
|
||||||
The command to be executed. This must be specified as the
|
The command to be executed. This must be specified as the
|
||||||
last command attribute.
|
last command attribute.
|
||||||
|
@ -72,6 +72,8 @@ a configuration change.
|
|||||||
.SH Miscellaneous
|
.SH Miscellaneous
|
||||||
.ad
|
.ad
|
||||||
.fi
|
.fi
|
||||||
|
.IP \fBappend_dot_mydomain\fR
|
||||||
|
Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
|
||||||
.IP \fBbest_mx_transport\fR
|
.IP \fBbest_mx_transport\fR
|
||||||
Name of the delivery transport to use when the local machine
|
Name of the delivery transport to use when the local machine
|
||||||
is the most-preferred mail exchanger (by default, a mailer
|
is the most-preferred mail exchanger (by default, a mailer
|
||||||
|
@ -22,10 +22,14 @@
|
|||||||
/* .fi
|
/* .fi
|
||||||
/* The external command attributes are given in the \fBmaster.cf\fR
|
/* The external command attributes are given in the \fBmaster.cf\fR
|
||||||
/* file at the end of a service definition. The syntax is as follows:
|
/* file at the end of a service definition. The syntax is as follows:
|
||||||
/* .IP "\fBflags=FR.>\fR (optional)"
|
/* .IP "\fBflags=BFR.>\fR (optional)"
|
||||||
/* Optional message processing flags. By default, a message is
|
/* Optional message processing flags. By default, a message is
|
||||||
/* copied unchanged.
|
/* copied unchanged.
|
||||||
/* .RS
|
/* .RS
|
||||||
|
/* .IP \fBB\fR
|
||||||
|
/* Append a blank line at the end of each message. This is required
|
||||||
|
/* by some mail user agents that recognize "\fBFrom \fR" lines only
|
||||||
|
/* when preceded by a blank line.
|
||||||
/* .IP \fBF\fR
|
/* .IP \fBF\fR
|
||||||
/* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
|
/* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
|
||||||
/* the message content.
|
/* the message content.
|
||||||
@ -54,6 +58,9 @@
|
|||||||
/* \fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
|
/* \fB\er\en\fR or \fB\en\fR. The usual C-style backslash escape
|
||||||
/* sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
|
/* sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
|
||||||
/* \e\fIoctal\fR and \fB\e\e\fR.
|
/* \e\fIoctal\fR and \fB\e\e\fR.
|
||||||
|
/* .IP "\fBsize\fR=\fIsize_limit\fR (optional)"
|
||||||
|
/* Messages greater in size than this limit (in bytes) will be bounced
|
||||||
|
/* back to the sender.
|
||||||
/* .IP "\fBargv\fR=\fIcommand\fR... (required)"
|
/* .IP "\fBargv\fR=\fIcommand\fR... (required)"
|
||||||
/* The command to be executed. This must be specified as the
|
/* The command to be executed. This must be specified as the
|
||||||
/* last command attribute.
|
/* last command attribute.
|
||||||
@ -200,6 +207,7 @@
|
|||||||
#include <mail_addr.h>
|
#include <mail_addr.h>
|
||||||
#include <canon_addr.h>
|
#include <canon_addr.h>
|
||||||
#include <split_addr.h>
|
#include <split_addr.h>
|
||||||
|
#include <off_cvt.h>
|
||||||
|
|
||||||
/* Single server skeleton. */
|
/* Single server skeleton. */
|
||||||
|
|
||||||
@ -255,6 +263,7 @@ typedef struct {
|
|||||||
gid_t gid; /* command privileges */
|
gid_t gid; /* command privileges */
|
||||||
int flags; /* mail_copy() flags */
|
int flags; /* mail_copy() flags */
|
||||||
VSTRING *eol; /* output record delimiter */
|
VSTRING *eol; /* output record delimiter */
|
||||||
|
off_t size_limit; /* max size in bytes we will accept */
|
||||||
} PIPE_ATTR;
|
} PIPE_ATTR;
|
||||||
|
|
||||||
/* parse_callback - callback for mac_parse() */
|
/* parse_callback - callback for mac_parse() */
|
||||||
@ -415,6 +424,7 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
|||||||
struct group *grp;
|
struct group *grp;
|
||||||
char *user; /* user name */
|
char *user; /* user name */
|
||||||
char *group; /* group name */
|
char *group; /* group name */
|
||||||
|
char *size; /* max message size */
|
||||||
char *cp;
|
char *cp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -425,6 +435,7 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
|||||||
attr->command = 0;
|
attr->command = 0;
|
||||||
attr->flags = 0;
|
attr->flags = 0;
|
||||||
attr->eol = vstring_strcpy(vstring_alloc(1), "\n");
|
attr->eol = vstring_strcpy(vstring_alloc(1), "\n");
|
||||||
|
attr->size_limit = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate over the command-line attribute list.
|
* Iterate over the command-line attribute list.
|
||||||
@ -437,6 +448,9 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
|||||||
if (strncasecmp("flags=", *argv, sizeof("flags=") - 1) == 0) {
|
if (strncasecmp("flags=", *argv, sizeof("flags=") - 1) == 0) {
|
||||||
for (cp = *argv + sizeof("flags=") - 1; *cp; cp++) {
|
for (cp = *argv + sizeof("flags=") - 1; *cp; cp++) {
|
||||||
switch (*cp) {
|
switch (*cp) {
|
||||||
|
case 'B':
|
||||||
|
attr->flags |= MAIL_COPY_BLANK;
|
||||||
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
attr->flags |= MAIL_COPY_FROM;
|
attr->flags |= MAIL_COPY_FROM;
|
||||||
break;
|
break;
|
||||||
@ -483,6 +497,15 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
|||||||
unescape(attr->eol, *argv + sizeof("eol=") - 1);
|
unescape(attr->eol, *argv + sizeof("eol=") - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* size=max_message_size (in bytes)
|
||||||
|
*/
|
||||||
|
else if (strncasecmp("size=", *argv, sizeof("size=") - 1) == 0) {
|
||||||
|
size = *argv + sizeof("size=") - 1;
|
||||||
|
if ((attr->size_limit = off_cvt_string(size)) < 0)
|
||||||
|
msg_fatal("%s: bad size= value: %s", myname, size);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* argv=command...
|
* argv=command...
|
||||||
*/
|
*/
|
||||||
@ -519,8 +542,9 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
|||||||
* Give the poor tester a clue of what is going on.
|
* Give the poor tester a clue of what is going on.
|
||||||
*/
|
*/
|
||||||
if (msg_verbose)
|
if (msg_verbose)
|
||||||
msg_info("%s: uid %d, gid %d. flags %d",
|
msg_info("%s: uid %d, gid %d, flags %d, size %ld",
|
||||||
myname, attr->uid, attr->gid, attr->flags);
|
myname, attr->uid, attr->gid, attr->flags,
|
||||||
|
(long) attr->size_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eval_command_status - do something with command completion status */
|
/* eval_command_status - do something with command completion status */
|
||||||
@ -544,7 +568,8 @@ static int eval_command_status(int command_status, char *service,
|
|||||||
rcpt = request->rcpt_list.info + n;
|
rcpt = request->rcpt_list.info + n;
|
||||||
sent(request->queue_id, rcpt->address, service,
|
sent(request->queue_id, rcpt->address, service,
|
||||||
request->arrival_time, "%s", request->nexthop);
|
request->arrival_time, "%s", request->nexthop);
|
||||||
deliver_completed(src, rcpt->offset);
|
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||||
|
deliver_completed(src, rcpt->offset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PIPE_STAT_BOUNCE:
|
case PIPE_STAT_BOUNCE:
|
||||||
@ -621,6 +646,19 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv)
|
|||||||
get_service_attr(&attr, argv);
|
get_service_attr(&attr, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that this agent accepts messages this large.
|
||||||
|
*/
|
||||||
|
if (attr.size_limit != 0 && request->data_size > attr.size_limit) {
|
||||||
|
if (msg_verbose)
|
||||||
|
msg_info("%s: too big: size_limit = %ld, request->data_size = %ld",
|
||||||
|
myname, (long) attr.size_limit, request->data_size);
|
||||||
|
|
||||||
|
deliver_status = eval_command_status(PIPE_STAT_BOUNCE, service,
|
||||||
|
request, request->fp, "message too large");
|
||||||
|
return (deliver_status);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deliver. Set the nexthop and sender variables, and expand the command
|
* Deliver. Set the nexthop and sender variables, and expand the command
|
||||||
* argument vector. Recipients will be expanded on the fly. XXX Rewrite
|
* argument vector. Recipients will be expanded on the fly. XXX Rewrite
|
||||||
|
@ -134,6 +134,7 @@ qmgr_deliver.o: ../include/mail_queue.h
|
|||||||
qmgr_deliver.o: ../include/mail_proto.h
|
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: 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
|
||||||
|
@ -229,7 +229,8 @@ struct QMGR_MESSAGE {
|
|||||||
char *sender; /* complete address */
|
char *sender; /* complete address */
|
||||||
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; /* inspection transport */
|
char *filter_xport; /* filtering transport */
|
||||||
|
char *inspect_xport; /* inspecting transport */
|
||||||
long data_size; /* message content size */
|
long data_size; /* message content size */
|
||||||
long rcpt_offset; /* more recipients here */
|
long rcpt_offset; /* more recipients here */
|
||||||
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
|
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#include <mail_proto.h>
|
#include <mail_proto.h>
|
||||||
#include <recipient_list.h>
|
#include <recipient_list.h>
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
|
#include <deliver_request.h>
|
||||||
|
|
||||||
/* Application-specific. */
|
/* Application-specific. */
|
||||||
|
|
||||||
@ -117,7 +118,8 @@ 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;
|
||||||
|
|
||||||
mail_print(stream, "%s %s %ld %ld %s %s %s %s %ld",
|
mail_print(stream, "%d %s %s %ld %ld %s %s %s %s %ld",
|
||||||
|
message->inspect_xport ? DEL_REQ_FLAG_BOUNCE : DEL_REQ_FLAG_DEFLT,
|
||||||
message->queue_name, message->queue_id,
|
message->queue_name, message->queue_id,
|
||||||
message->data_offset, message->data_size,
|
message->data_offset, message->data_size,
|
||||||
entry->queue->name, message->sender,
|
entry->queue->name, message->sender,
|
||||||
|
@ -145,6 +145,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
|
|||||||
message->errors_to = 0;
|
message->errors_to = 0;
|
||||||
message->return_receipt = 0;
|
message->return_receipt = 0;
|
||||||
message->filter_xport = 0;
|
message->filter_xport = 0;
|
||||||
|
message->inspect_xport = 0;
|
||||||
message->data_size = 0;
|
message->data_size = 0;
|
||||||
message->warn_offset = 0;
|
message->warn_offset = 0;
|
||||||
message->warn_time = 0;
|
message->warn_time = 0;
|
||||||
@ -250,6 +251,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
|||||||
} else if (rec_type == REC_TYPE_FILT) {
|
} else if (rec_type == REC_TYPE_FILT) {
|
||||||
if (message->filter_xport == 0)
|
if (message->filter_xport == 0)
|
||||||
message->filter_xport = mystrdup(start);
|
message->filter_xport = mystrdup(start);
|
||||||
|
} else if (rec_type == REC_TYPE_INSP) {
|
||||||
|
if (message->inspect_xport == 0)
|
||||||
|
message->inspect_xport = mystrdup(start);
|
||||||
} else if (rec_type == REC_TYPE_FROM) {
|
} else if (rec_type == REC_TYPE_FROM) {
|
||||||
if (message->sender == 0) {
|
if (message->sender == 0) {
|
||||||
message->sender = mystrdup(start);
|
message->sender = mystrdup(start);
|
||||||
@ -706,6 +710,8 @@ void qmgr_message_free(QMGR_MESSAGE *message)
|
|||||||
myfree(message->return_receipt);
|
myfree(message->return_receipt);
|
||||||
if (message->filter_xport)
|
if (message->filter_xport)
|
||||||
myfree(message->filter_xport);
|
myfree(message->filter_xport);
|
||||||
|
if (message->inspect_xport)
|
||||||
|
myfree(message->inspect_xport);
|
||||||
qmgr_rcpt_list_free(&message->rcpt_list);
|
qmgr_rcpt_list_free(&message->rcpt_list);
|
||||||
qmgr_message_count--;
|
qmgr_message_count--;
|
||||||
myfree((char *) message);
|
myfree((char *) message);
|
||||||
|
@ -56,6 +56,8 @@
|
|||||||
/* .SH Miscellaneous
|
/* .SH Miscellaneous
|
||||||
/* .ad
|
/* .ad
|
||||||
/* .fi
|
/* .fi
|
||||||
|
/* .IP \fBappend_dot_mydomain\fR
|
||||||
|
/* Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
|
||||||
/* .IP \fBbest_mx_transport\fR
|
/* .IP \fBbest_mx_transport\fR
|
||||||
/* Name of the delivery transport to use when the local machine
|
/* Name of the delivery transport to use when the local machine
|
||||||
/* is the most-preferred mail exchanger (by default, a mailer
|
/* is the most-preferred mail exchanger (by default, a mailer
|
||||||
@ -239,6 +241,7 @@ char *var_smtp_sasl_opts;
|
|||||||
char *var_smtp_sasl_passwd;
|
char *var_smtp_sasl_passwd;
|
||||||
bool var_smtp_sasl_enable;
|
bool var_smtp_sasl_enable;
|
||||||
char *var_smtp_bind_addr;
|
char *var_smtp_bind_addr;
|
||||||
|
bool var_append_dot_mydomain;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Global variables. smtp_errno is set by the address lookup routines and by
|
* Global variables. smtp_errno is set by the address lookup routines and by
|
||||||
@ -408,6 +411,7 @@ int main(int argc, char **argv)
|
|||||||
VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
|
VAR_SKIP_QUIT_RESP, DEF_SKIP_QUIT_RESP, &var_skip_quit_resp,
|
||||||
VAR_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
|
VAR_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
|
||||||
VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
|
VAR_SMTP_SASL_ENABLE, DEF_SMTP_SASL_ENABLE, &var_smtp_sasl_enable,
|
||||||
|
VAR_APP_DOT_MYDOMAIN, DEF_APP_DOT_MYDOMAIN, &var_append_dot_mydomain,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -533,7 +533,8 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
session->namaddr,
|
session->namaddr,
|
||||||
request->arrival_time, "%s",
|
request->arrival_time, "%s",
|
||||||
resp->str);
|
resp->str);
|
||||||
deliver_completed(state->src, rcpt->offset);
|
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||||
|
deliver_completed(state->src, rcpt->offset);
|
||||||
rcpt->offset = 0;
|
rcpt->offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,10 @@
|
|||||||
#include <vstring.h>
|
#include <vstring.h>
|
||||||
#include <msg.h>
|
#include <msg.h>
|
||||||
|
|
||||||
|
/* Global library. */
|
||||||
|
|
||||||
|
#include <mail_params.h>
|
||||||
|
|
||||||
/* DNS library. */
|
/* DNS library. */
|
||||||
|
|
||||||
#include <dns.h>
|
#include <dns.h>
|
||||||
@ -73,8 +77,11 @@ const char *smtp_unalias_name(const char *name)
|
|||||||
* after servicing a limited number of requests, so there is no need to
|
* after servicing a limited number of requests, so there is no need to
|
||||||
* prevent the cache from growing too large, or to expire old entries.
|
* prevent the cache from growing too large, or to expire old entries.
|
||||||
*/
|
*/
|
||||||
if (cache == 0)
|
if (cache == 0) {
|
||||||
cache = htable_create(10);
|
cache = htable_create(10);
|
||||||
|
if (var_append_dot_mydomain == 0)
|
||||||
|
smtp_unalias_flags |= RES_DNSRCH;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look up the fqdn. If none is found use the query name instead, so that
|
* Look up the fqdn. If none is found use the query name instead, so that
|
||||||
|
@ -431,7 +431,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_chat_reply(state, "250-SIZE");
|
smtpd_chat_reply(state, "250-SIZE");
|
||||||
smtpd_chat_reply(state, "250-ETRN");
|
smtpd_chat_reply(state, "250-ETRN");
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
if (SMTPD_STAND_ALONE(state) == 0 && var_smtpd_sasl_enable)
|
if (var_smtpd_sasl_enable)
|
||||||
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 8BITMIME");
|
smtpd_chat_reply(state, "250 8BITMIME");
|
||||||
@ -624,9 +624,7 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
if ((state->msg_size = off_cvt_string(arg + 5)) < 0)
|
if ((state->msg_size = off_cvt_string(arg + 5)) < 0)
|
||||||
state->msg_size = 0;
|
state->msg_size = 0;
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
} else if (SMTPD_STAND_ALONE(state) == 0
|
} else if (var_smtpd_sasl_enable && strncasecmp(arg, "AUTH=", 5) == 0) {
|
||||||
&& var_smtpd_sasl_enable
|
|
||||||
&& strncasecmp(arg, "AUTH=", 5) == 0) {
|
|
||||||
if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) {
|
if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) {
|
||||||
smtpd_chat_reply(state, "%s", err);
|
smtpd_chat_reply(state, "%s", err);
|
||||||
return (-1);
|
return (-1);
|
||||||
@ -913,6 +911,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
if (state->err == CLEANUP_STAT_OK) {
|
if (state->err == CLEANUP_STAT_OK) {
|
||||||
state->error_count = 0;
|
state->error_count = 0;
|
||||||
state->error_mask = 0;
|
state->error_mask = 0;
|
||||||
|
state->junk_cmds = 0;
|
||||||
smtpd_chat_reply(state, "250 Ok: queued as %s", state->queue_id);
|
smtpd_chat_reply(state, "250 Ok: queued as %s", state->queue_id);
|
||||||
} else if ((state->err & CLEANUP_STAT_BAD) != 0) {
|
} else if ((state->err & CLEANUP_STAT_BAD) != 0) {
|
||||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||||
|
@ -92,6 +92,8 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
|||||||
state->junk_cmds = 0;
|
state->junk_cmds = 0;
|
||||||
|
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
|
if (SMTPD_STAND_ALONE(state))
|
||||||
|
var_smtpd_sasl_enable = 0;
|
||||||
if (var_smtpd_sasl_enable)
|
if (var_smtpd_sasl_enable)
|
||||||
smtpd_sasl_connect(state);
|
smtpd_sasl_connect(state);
|
||||||
#endif
|
#endif
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* dict_pcre_open() opens the named file and compiles the contained
|
/* dict_pcre_open() opens the named file and compiles the contained
|
||||||
/* regular expressions.
|
/* regular expressions.
|
||||||
/*
|
|
||||||
/* The lookup interface will match only user@domain form addresses.
|
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* dict(3) generic dictionary manager
|
/* dict(3) generic dictionary manager
|
||||||
/* AUTHOR(S)
|
/* AUTHOR(S)
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
/* dict_regexp_open() opens the named file and compiles the contained
|
/* dict_regexp_open() opens the named file and compiles the contained
|
||||||
/* regular expressions.
|
/* regular expressions.
|
||||||
/*
|
|
||||||
/* The lookup interface will match only user@domain form addresses.
|
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* dict(3) generic dictionary manager
|
/* dict(3) generic dictionary manager
|
||||||
/* AUTHOR(S)
|
/* AUTHOR(S)
|
||||||
|
@ -213,7 +213,7 @@
|
|||||||
/* value arguments.
|
/* value arguments.
|
||||||
/* .IP "VSTREAM_CTL_READ_FN (int (*)(int, void *, unsigned, int, void *))"
|
/* .IP "VSTREAM_CTL_READ_FN (int (*)(int, void *, unsigned, int, void *))"
|
||||||
/* The argument specifies an alternative for the timed_read(3) function,
|
/* The argument specifies an alternative for the timed_read(3) function,
|
||||||
/* for example, a read function that performs encryption.
|
/* for example, a read function that performs decryption.
|
||||||
/* .IP "VSTREAM_CTL_WRITE_FN (int (*)(int, void *, unsigned, int, void *))"
|
/* .IP "VSTREAM_CTL_WRITE_FN (int (*)(int, void *, unsigned, int, void *))"
|
||||||
/* The argument specifies an alternative for the timed_write(3) function,
|
/* The argument specifies an alternative for the timed_write(3) function,
|
||||||
/* for example, a write function that performs encryption.
|
/* for example, a write function that performs encryption.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user