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.
|
||||
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
|
||||
Postfix versions will reject mail that needs to be content filtered,
|
||||
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
|
||||
terminating with exit status 75 (EX_TEMPFAIL). If the content
|
||||
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
|
||||
exit status of the filter command is whatever exit status Postfix
|
||||
sendmail produces.
|
||||
|
||||
The problem with content filterings like this is that they are not
|
||||
very robust, because they do not talk a well-defined protocol with
|
||||
Postfix. If the filter command aborts because of some memory
|
||||
allocation problem, it 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 filtering software
|
||||
itself runs into a resource problem.
|
||||
The problem with content filters like this is that they are not
|
||||
very robust, because the software does not talk a well-defined
|
||||
protocol with Postfix. If the filter shell script 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 filtering 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,
|
||||
@ -159,7 +164,7 @@ When a queue file has content filtering information, the queue
|
||||
manager will deliver the mail to the specified content filtering
|
||||
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
|
||||
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,
|
||||
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
|
||||
do is to reply to an input of `.' with `550 content rejected', and
|
||||
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
|
||||
a dedicated listener on port localhost 10026:
|
||||
|
||||
/etc/postfix/master.cf:
|
||||
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
|
||||
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"
|
||||
in anticipation of a new hook for content inspection that
|
||||
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
|
||||
===========================================
|
||||
|
||||
|
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/mail_params.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: ../include/argv.h
|
||||
cleanup_envelope.o: ../include/maps.h
|
||||
|
@ -8,12 +8,62 @@
|
||||
# The ldap_lookup_timeout parameter specifies the timeout for LDAP
|
||||
# database lookups.
|
||||
#
|
||||
ldap_lookup_timeout = 10
|
||||
#ldap_timeout = 10
|
||||
|
||||
# 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.
|
||||
#
|
||||
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;
|
||||
|
||||
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->data_offset, request->data_size,
|
||||
request->nexthop, request->sender,
|
||||
|
@ -9,6 +9,7 @@
|
||||
/* typedef struct DELIVER_REQUEST {
|
||||
/* .in +5
|
||||
/* VSTREAM *fp;
|
||||
/* int flags;
|
||||
/* char *queue_name;
|
||||
/* char *queue_id;
|
||||
/* long data_offset;
|
||||
@ -40,6 +41,17 @@
|
||||
/* A null result means that the client sent bad information or that
|
||||
/* 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
|
||||
/* by the caller when all delivery to the destination in
|
||||
/* \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
|
||||
* 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,
|
||||
&request->data_size, nexthop, address,
|
||||
errors_to, return_receipt, &request->arrival_time) != 9)
|
||||
|
@ -27,6 +27,7 @@
|
||||
*/
|
||||
typedef struct DELIVER_REQUEST {
|
||||
VSTREAM *fp; /* stream, shared lock */
|
||||
int flags; /* see below */
|
||||
char *queue_name; /* message queue name */
|
||||
char *queue_id; /* message queue id */
|
||||
long data_offset; /* offset to message */
|
||||
@ -40,6 +41,10 @@ typedef struct DELIVER_REQUEST {
|
||||
char *hop_status; /* reason if unavailable */
|
||||
} 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_;
|
||||
extern DELIVER_REQUEST *deliver_request_read(_deliver_vstream_ *);
|
||||
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,
|
||||
"Bcc", HDR_BCC, HDR_OPT_DROP | HDR_OPT_XRECIP,
|
||||
"Cc", HDR_CC, HDR_OPT_XRECIP,
|
||||
"Content-Length", HDR_CONTENT_LENGTH, HDR_OPT_DROP,
|
||||
"Delivered-To", HDR_DELIVERED_TO, 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,
|
||||
"Mail-Followup-To", HDR_MAIL_FOLLOWUP_TO, HDR_OPT_SENDER,
|
||||
"Message-Id", HDR_MESSAGE_ID, 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-Cc", HDR_RESENT_CC, HDR_OPT_XRECIP | 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-To", HDR_RESENT_TO, HDR_OPT_XRECIP | HDR_OPT_RR,
|
||||
"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,
|
||||
"To", HDR_TO, HDR_OPT_XRECIP,
|
||||
};
|
||||
|
@ -48,6 +48,7 @@ typedef struct {
|
||||
#define HDR_RETURN_RECEIPT_TO 23
|
||||
#define HDR_SENDER 24
|
||||
#define HDR_TO 25
|
||||
#define HDR_MAIL_FOLLOWUP_TO 26
|
||||
|
||||
/*
|
||||
* Header flags.
|
||||
|
@ -186,7 +186,7 @@ int mail_copy(const char *sender, const char *delivered,
|
||||
corrupt_error = mark_corrupt(src);
|
||||
if (prev_type != REC_TYPE_NORM)
|
||||
vstream_fputs(eol, dst);
|
||||
if (flags & MAIL_COPY_FROM)
|
||||
if (flags & MAIL_COPY_BLANK)
|
||||
vstream_fputs(eol, dst);
|
||||
}
|
||||
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_RETURN_PATH (1<<4) /* prepend Return-Path: */
|
||||
#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 | \
|
||||
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 */
|
||||
|
||||
/* LICENSE
|
||||
|
@ -381,10 +381,14 @@ extern char *var_fwd_exp_filter;
|
||||
#define DEF_DELIVER_HDR "command, file, forward"
|
||||
extern char *var_deliver_hdr;
|
||||
|
||||
#define VAR_EXP_OWN_ALIAS "expand_owner_alias"
|
||||
#define DEF_EXP_OWN_ALIAS 0
|
||||
#define VAR_EXP_OWN_ALIAS "expand_owner_alias"
|
||||
#define DEF_EXP_OWN_ALIAS 0
|
||||
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
|
||||
* default, we do graceful degradation with huge mailing lists.
|
||||
|
@ -15,7 +15,7 @@
|
||||
* Version of this program.
|
||||
*/
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20000531"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20000625"
|
||||
extern char *var_mail_version;
|
||||
|
||||
/* LICENSE
|
||||
|
@ -1020,10 +1020,9 @@ types Postfix supports, use the command <b>postconf -m</b>.
|
||||
<p>
|
||||
|
||||
N.B. Some non-Postfix software such as <a
|
||||
href="http://www.mbnet.mb.ca/howto/dynamic.htm">DRAC</a> uses
|
||||
<b>btree</b> files instead of <b>hash</b> files. In that case,
|
||||
you will have to adjust the above <b>check_client_access</b>
|
||||
restriction accordingly.
|
||||
href="http://mail.cc.umanitoba.ca/drac/">DRAC</a> uses <b>btree</b>
|
||||
files instead of <b>hash</b> files. In that case, you will have
|
||||
to adjust the above <b>check_client_access</b> restriction accordingly.
|
||||
|
||||
<p>
|
||||
|
||||
|
@ -216,7 +216,7 @@ LOCAL(8) LOCAL(8)
|
||||
lope header to each message, prepends an optional <b>Deliv-</b>
|
||||
<b>ered-To:</b> header with the recipient envelope address,
|
||||
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>
|
||||
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.
|
||||
|
||||
<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>
|
||||
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>
|
||||
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>fallback</b><i>_</i><b>transport</b>
|
||||
Message transport for recipients that are not found
|
||||
@ -385,10 +389,6 @@ LOCAL(8) LOCAL(8)
|
||||
rides all other configuration parameters that con-
|
||||
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)
|
||||
|
||||
|
||||
<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>
|
||||
Time in seconds between successive attempts to
|
||||
acquire an exclusive lock.
|
||||
@ -449,11 +454,6 @@ LOCAL(8) LOCAL(8)
|
||||
Default rights for delivery to external file or
|
||||
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)
|
||||
|
||||
|
||||
<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>
|
||||
The <b>Delivered-To:</b> header appears in the <b>qmail</b> system by
|
||||
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
|
||||
follows:
|
||||
|
||||
<b>flags=FR.</b>> (optional)
|
||||
<b>flags=BFR.</b>> (optional)
|
||||
Optional message processing flags. By default, a
|
||||
message is copied unchanged.
|
||||
|
||||
<b>F</b> Prepend a "<b>From</b> <i>sender</i> <i>time_stamp</i>" envelope
|
||||
header to the message content. This is
|
||||
<b>B</b> Append a blank line at the end of each mes-
|
||||
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
|
||||
<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.
|
||||
|
||||
<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.
|
||||
|
||||
<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.
|
||||
|
||||
> 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-
|
||||
ware.
|
||||
|
||||
@ -54,11 +59,6 @@ PIPE(8) PIPE(8)
|
||||
|
||||
<b>user</b>=<i>username</i>:<i>groupname</i>
|
||||
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)
|
||||
|
||||
|
||||
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>)
|
||||
The output record delimiter. Typically one would
|
||||
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>
|
||||
The output record delimiter. Typically one would
|
||||
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>
|
||||
<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)
|
||||
The command to be executed. This must be specified
|
||||
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-
|
||||
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)
|
||||
|
||||
|
||||
<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.
|
||||
|
||||
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.
|
||||
|
||||
<i>transport_</i><b>destination</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
|
||||
Limit the number of recipients per message deliv-
|
||||
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
|
||||
Limit the number of recipients per message
|
||||
|
||||
|
||||
|
||||
@ -203,6 +203,16 @@ 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.
|
||||
|
||||
<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.
|
||||
|
||||
<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>
|
||||
Name of the delivery transport to use when the
|
||||
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>
|
||||
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
|
||||
@ -137,6 +137,9 @@ 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>
|
||||
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
|
||||
<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)
|
||||
|
||||
|
||||
<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,
|
||||
the SMTP client tries the next address on the mail
|
||||
exchanger list.
|
||||
@ -254,9 +257,6 @@ SMTP(8) SMTP(8)
|
||||
The Secure Mailer license must be distributed with this
|
||||
software.
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
|
||||
|
||||
|
||||
@ -269,6 +269,9 @@ SMTP(8) SMTP(8)
|
||||
SMTP(8) SMTP(8)
|
||||
|
||||
|
||||
<b>AUTHOR(S)</b>
|
||||
Wietse Venema
|
||||
IBM T.J. Watson Research
|
||||
P.O. Box 704
|
||||
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,
|
||||
session->namaddr, request->arrival_time,
|
||||
"%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;
|
||||
}
|
||||
} else {
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include <vstream.h>
|
||||
#include <htable.h>
|
||||
#include <open_as.h>
|
||||
#include <stat_as.h>
|
||||
#include <lstat_as.h>
|
||||
#include <iostuff.h>
|
||||
#include <stringops.h>
|
||||
@ -78,6 +79,7 @@
|
||||
#include <mail_params.h>
|
||||
#include <mail_conf.h>
|
||||
#include <ext_prop.h>
|
||||
#include <defer.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -112,18 +114,36 @@ int deliver_dotforward(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp)
|
||||
if (msg_verbose)
|
||||
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.
|
||||
*/
|
||||
if (*var_forward_path == 0)
|
||||
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.
|
||||
|
@ -173,7 +173,7 @@
|
||||
/* optional \fBDelivered-To:\fR
|
||||
/* header with the recipient envelope address, prepends a
|
||||
/* \fBReturn-Path:\fR header with the sender envelope address,
|
||||
/* and appends an empty line.
|
||||
/* and appends no empty line.
|
||||
/* EXTERNAL FILE DELIVERY
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -278,6 +278,9 @@
|
||||
/* forwarding mail is not recommended.
|
||||
/* .IP \fBrecipient_delimiter\fR
|
||||
/* 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
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -439,6 +442,7 @@ char *var_fwd_exp_filter;
|
||||
char *var_prop_extension;
|
||||
int var_exp_own_alias;
|
||||
char *var_deliver_hdr;
|
||||
int var_stat_home_dir;
|
||||
|
||||
int local_cmd_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;
|
||||
rcpt_stat = deliver_recipient(state, usr_attr);
|
||||
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);
|
||||
been_here_free(state.dup_filter);
|
||||
msg_stat |= rcpt_stat;
|
||||
@ -618,6 +622,7 @@ int main(int argc, char **argv)
|
||||
static CONFIG_BOOL_TABLE bool_table[] = {
|
||||
VAR_BIFF, DEF_BIFF, &var_biff,
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -143,11 +143,11 @@ int deliver_maildir(LOCAL_STATE state, USER_ATTR usr_attr, char *path)
|
||||
|| sane_link(tmpfile, newfile) < 0)) {
|
||||
vstring_sprintf(why, "link to %s: %m", newfile);
|
||||
} else {
|
||||
if (unlink(tmpfile) < 0)
|
||||
msg_warn("remove %s: %m", tmpfile);
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
if (unlink(tmpfile) < 0)
|
||||
msg_warn("remove %s: %m", tmpfile);
|
||||
}
|
||||
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.
|
||||
*
|
||||
* 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] == '\\') {
|
||||
state.msg_attr.recipient++, state.msg_attr.local++, state.msg_attr.user++;
|
||||
|
@ -147,7 +147,7 @@ case "$SYSTEM.$RELEASE" in
|
||||
case "$CC" in
|
||||
cc|*/cc|xlc|*/xlc) OPT=; CCARGS="$CCARGS -w -blibpath:/usr/lib:/lib:/usr/local/lib";;
|
||||
esac
|
||||
CCARGS="$CCARGS -D_ALL_SOURCE"
|
||||
CCARGS="$CCARGS -D_ALL_SOURCE -DHAS_POSIX_REGEXP"
|
||||
;;
|
||||
3) SYSTYPE=AIX3
|
||||
# How embarrassing...
|
||||
|
@ -187,7 +187,7 @@ envelope header to each message, prepends an
|
||||
optional \fBDelivered-To:\fR
|
||||
header with the recipient envelope address, prepends a
|
||||
\fBReturn-Path:\fR header with the sender envelope address,
|
||||
and appends an empty line.
|
||||
and appends no empty line.
|
||||
.SH EXTERNAL FILE DELIVERY
|
||||
.na
|
||||
.nf
|
||||
@ -306,6 +306,9 @@ forwarding, delivery to command or file. Specify zero or more of:
|
||||
forwarding mail is not recommended.
|
||||
.IP \fBrecipient_delimiter\fR
|
||||
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
|
||||
.ad
|
||||
.fi
|
||||
|
@ -30,10 +30,14 @@ to the \fBbounce\fR(8) or \fBdefer\fR(8) daemon as appropriate.
|
||||
.fi
|
||||
The external command attributes are given in the \fBmaster.cf\fR
|
||||
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
|
||||
copied unchanged.
|
||||
.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
|
||||
Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
|
||||
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
|
||||
sequences are recognized: \fB\ea \eb \ef \en \er \et \ev
|
||||
\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)"
|
||||
The command to be executed. This must be specified as the
|
||||
last command attribute.
|
||||
|
@ -72,6 +72,8 @@ a configuration change.
|
||||
.SH Miscellaneous
|
||||
.ad
|
||||
.fi
|
||||
.IP \fBappend_dot_mydomain\fR
|
||||
Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
|
||||
.IP \fBbest_mx_transport\fR
|
||||
Name of the delivery transport to use when the local machine
|
||||
is the most-preferred mail exchanger (by default, a mailer
|
||||
|
@ -22,10 +22,14 @@
|
||||
/* .fi
|
||||
/* The external command attributes are given in the \fBmaster.cf\fR
|
||||
/* 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
|
||||
/* copied unchanged.
|
||||
/* .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
|
||||
/* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to
|
||||
/* the message content.
|
||||
@ -54,6 +58,9 @@
|
||||
/* \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
|
||||
/* \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)"
|
||||
/* The command to be executed. This must be specified as the
|
||||
/* last command attribute.
|
||||
@ -200,6 +207,7 @@
|
||||
#include <mail_addr.h>
|
||||
#include <canon_addr.h>
|
||||
#include <split_addr.h>
|
||||
#include <off_cvt.h>
|
||||
|
||||
/* Single server skeleton. */
|
||||
|
||||
@ -255,6 +263,7 @@ typedef struct {
|
||||
gid_t gid; /* command privileges */
|
||||
int flags; /* mail_copy() flags */
|
||||
VSTRING *eol; /* output record delimiter */
|
||||
off_t size_limit; /* max size in bytes we will accept */
|
||||
} PIPE_ATTR;
|
||||
|
||||
/* parse_callback - callback for mac_parse() */
|
||||
@ -415,6 +424,7 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
||||
struct group *grp;
|
||||
char *user; /* user name */
|
||||
char *group; /* group name */
|
||||
char *size; /* max message size */
|
||||
char *cp;
|
||||
|
||||
/*
|
||||
@ -425,6 +435,7 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
||||
attr->command = 0;
|
||||
attr->flags = 0;
|
||||
attr->eol = vstring_strcpy(vstring_alloc(1), "\n");
|
||||
attr->size_limit = 0;
|
||||
|
||||
/*
|
||||
* 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) {
|
||||
for (cp = *argv + sizeof("flags=") - 1; *cp; cp++) {
|
||||
switch (*cp) {
|
||||
case 'B':
|
||||
attr->flags |= MAIL_COPY_BLANK;
|
||||
break;
|
||||
case 'F':
|
||||
attr->flags |= MAIL_COPY_FROM;
|
||||
break;
|
||||
@ -483,6 +497,15 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv)
|
||||
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...
|
||||
*/
|
||||
@ -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.
|
||||
*/
|
||||
if (msg_verbose)
|
||||
msg_info("%s: uid %d, gid %d. flags %d",
|
||||
myname, attr->uid, attr->gid, attr->flags);
|
||||
msg_info("%s: uid %d, gid %d, flags %d, size %ld",
|
||||
myname, attr->uid, attr->gid, attr->flags,
|
||||
(long) attr->size_limit);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
sent(request->queue_id, rcpt->address, service,
|
||||
request->arrival_time, "%s", request->nexthop);
|
||||
deliver_completed(src, rcpt->offset);
|
||||
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||
deliver_completed(src, rcpt->offset);
|
||||
}
|
||||
break;
|
||||
case PIPE_STAT_BOUNCE:
|
||||
@ -621,6 +646,19 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **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
|
||||
* 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/recipient_list.h
|
||||
qmgr_deliver.o: ../include/mail_params.h
|
||||
qmgr_deliver.o: ../include/deliver_request.h
|
||||
qmgr_deliver.o: qmgr.h
|
||||
qmgr_deliver.o: ../include/scan_dir.h
|
||||
qmgr_deliver.o: ../include/maps.h
|
||||
|
@ -229,7 +229,8 @@ struct QMGR_MESSAGE {
|
||||
char *sender; /* complete address */
|
||||
char *errors_to; /* error report 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 rcpt_offset; /* more recipients here */
|
||||
QMGR_RCPT_LIST rcpt_list; /* complete addresses */
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include <mail_proto.h>
|
||||
#include <recipient_list.h>
|
||||
#include <mail_params.h>
|
||||
#include <deliver_request.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@ -117,7 +118,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream)
|
||||
QMGR_RCPT *recipient;
|
||||
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->data_offset, message->data_size,
|
||||
entry->queue->name, message->sender,
|
||||
|
@ -145,6 +145,7 @@ static QMGR_MESSAGE *qmgr_message_create(const char *queue_name,
|
||||
message->errors_to = 0;
|
||||
message->return_receipt = 0;
|
||||
message->filter_xport = 0;
|
||||
message->inspect_xport = 0;
|
||||
message->data_size = 0;
|
||||
message->warn_offset = 0;
|
||||
message->warn_time = 0;
|
||||
@ -250,6 +251,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
|
||||
} else if (rec_type == REC_TYPE_FILT) {
|
||||
if (message->filter_xport == 0)
|
||||
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) {
|
||||
if (message->sender == 0) {
|
||||
message->sender = mystrdup(start);
|
||||
@ -706,6 +710,8 @@ void qmgr_message_free(QMGR_MESSAGE *message)
|
||||
myfree(message->return_receipt);
|
||||
if (message->filter_xport)
|
||||
myfree(message->filter_xport);
|
||||
if (message->inspect_xport)
|
||||
myfree(message->inspect_xport);
|
||||
qmgr_rcpt_list_free(&message->rcpt_list);
|
||||
qmgr_message_count--;
|
||||
myfree((char *) message);
|
||||
|
@ -56,6 +56,8 @@
|
||||
/* .SH Miscellaneous
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* .IP \fBappend_dot_mydomain\fR
|
||||
/* Rewrite \fIuser\fR@\fIhost\fR to \fIuser\fR@\fIhost\fR.$\fBmydomain\fR.
|
||||
/* .IP \fBbest_mx_transport\fR
|
||||
/* Name of the delivery transport to use when the local machine
|
||||
/* is the most-preferred mail exchanger (by default, a mailer
|
||||
@ -239,6 +241,7 @@ char *var_smtp_sasl_opts;
|
||||
char *var_smtp_sasl_passwd;
|
||||
bool var_smtp_sasl_enable;
|
||||
char *var_smtp_bind_addr;
|
||||
bool var_append_dot_mydomain;
|
||||
|
||||
/*
|
||||
* 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_SMTP_ALWAYS_EHLO, DEF_SMTP_ALWAYS_EHLO, &var_smtp_always_ehlo,
|
||||
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,
|
||||
};
|
||||
|
||||
|
@ -533,7 +533,8 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
session->namaddr,
|
||||
request->arrival_time, "%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;
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,10 @@
|
||||
#include <vstring.h>
|
||||
#include <msg.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_params.h>
|
||||
|
||||
/* DNS library. */
|
||||
|
||||
#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
|
||||
* prevent the cache from growing too large, or to expire old entries.
|
||||
*/
|
||||
if (cache == 0)
|
||||
if (cache == 0) {
|
||||
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
|
||||
|
@ -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-ETRN");
|
||||
#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);
|
||||
#endif
|
||||
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)
|
||||
state->msg_size = 0;
|
||||
#ifdef USE_SASL_AUTH
|
||||
} else if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& var_smtpd_sasl_enable
|
||||
&& strncasecmp(arg, "AUTH=", 5) == 0) {
|
||||
} else if (var_smtpd_sasl_enable && strncasecmp(arg, "AUTH=", 5) == 0) {
|
||||
if ((err = smtpd_sasl_mail_opt(state, arg + 5)) != 0) {
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
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) {
|
||||
state->error_count = 0;
|
||||
state->error_mask = 0;
|
||||
state->junk_cmds = 0;
|
||||
smtpd_chat_reply(state, "250 Ok: queued as %s", state->queue_id);
|
||||
} else if ((state->err & CLEANUP_STAT_BAD) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_SOFTWARE;
|
||||
|
@ -92,6 +92,8 @@ void smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
|
||||
state->junk_cmds = 0;
|
||||
|
||||
#ifdef USE_SASL_AUTH
|
||||
if (SMTPD_STAND_ALONE(state))
|
||||
var_smtpd_sasl_enable = 0;
|
||||
if (var_smtpd_sasl_enable)
|
||||
smtpd_sasl_connect(state);
|
||||
#endif
|
||||
|
@ -13,8 +13,6 @@
|
||||
/* DESCRIPTION
|
||||
/* dict_pcre_open() opens the named file and compiles the contained
|
||||
/* regular expressions.
|
||||
/*
|
||||
/* The lookup interface will match only user@domain form addresses.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* AUTHOR(S)
|
||||
|
@ -13,8 +13,6 @@
|
||||
/* DESCRIPTION
|
||||
/* dict_regexp_open() opens the named file and compiles the contained
|
||||
/* regular expressions.
|
||||
/*
|
||||
/* The lookup interface will match only user@domain form addresses.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* AUTHOR(S)
|
||||
|
@ -213,7 +213,7 @@
|
||||
/* value arguments.
|
||||
/* .IP "VSTREAM_CTL_READ_FN (int (*)(int, void *, unsigned, int, void *))"
|
||||
/* 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 *))"
|
||||
/* The argument specifies an alternative for the timed_write(3) function,
|
||||
/* for example, a write function that performs encryption.
|
||||
|
Loading…
x
Reference in New Issue
Block a user