mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
snapshot-20010520
This commit is contained in:
committed by
Viktor Dukhovni
parent
6b85132d41
commit
6ac89aab2c
@@ -5125,3 +5125,45 @@ Apologies for any names omitted.
|
|||||||
Code cleanup: in order to make postsuper -d more usable,
|
Code cleanup: in order to make postsuper -d more usable,
|
||||||
the showq command was extended to safely list the possibly
|
the showq command was extended to safely list the possibly
|
||||||
world-writable maildrop directory. File: showq/showq.c.
|
world-writable maildrop directory. File: showq/showq.c.
|
||||||
|
|
||||||
|
20010505
|
||||||
|
|
||||||
|
RFC 2821 feature: an SMTP server must accept a recipient
|
||||||
|
address of "postmaster" without domain name. File:
|
||||||
|
smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
RFC 2821 recommendation: reply with 503 to commands sent
|
||||||
|
after 554 greeting. File: smtpd/smtpd.c.
|
||||||
|
|
||||||
|
RFC 2821 recommendation: if VRFY is enabled, list it in
|
||||||
|
the EHLO response.
|
||||||
|
|
||||||
|
20010507
|
||||||
|
|
||||||
|
Bugfix: with soft_bounce=yes, the SMTP server would log
|
||||||
|
5xx replies even though it would send 4xx replies to the
|
||||||
|
client (Phil Howard, ipal.net). File: smtpd/smtpd_check.c.
|
||||||
|
|
||||||
|
20010515
|
||||||
|
|
||||||
|
Compatibility: Microsoft sends "AUTH=MBS_BASIC LOGIN".
|
||||||
|
Updated the parsing code in smtp/smtp_proto.c. Problem
|
||||||
|
reported by Ralf Tessmann, Godot GmbH.
|
||||||
|
|
||||||
|
20010520
|
||||||
|
|
||||||
|
Standard: deleted the "via" portion from Received: headers
|
||||||
|
generated by Postfix bounce or other notification processes.
|
||||||
|
File: global/post_mail.c.
|
||||||
|
|
||||||
|
Robustness: eliminated stack-based recursion from the RFC
|
||||||
|
822 address parser. File: global/tok822_parse.c.
|
||||||
|
|
||||||
|
Standard: annotated the source code with comments based on
|
||||||
|
RFC 2821 and 2822. Not all the changes make sense.
|
||||||
|
|
||||||
|
Cleanup: moved ownership of the debug_peer parameters from
|
||||||
|
the applications to the library, so that a Postfix shared
|
||||||
|
library does not suffer from undefined references. Files:
|
||||||
|
smtp/smtp.c, lmtp/lmtp.c, smtpd/smtpd.c, global/mail_params.c.
|
||||||
|
LaMont Jones, for Debian.
|
||||||
|
@@ -98,8 +98,10 @@ mail_owner = postfix
|
|||||||
#inet_interfaces = $myhostname, localhost
|
#inet_interfaces = $myhostname, localhost
|
||||||
|
|
||||||
# The mydestination parameter specifies the list of domains that this
|
# The mydestination parameter specifies the list of domains that this
|
||||||
# machine considers itself the final destination for. That does not
|
# machine considers itself the final destination for. That includes
|
||||||
# include domains that are hosted on this machine. Those domains are
|
# Sendmail-style virtual domains hosted on this machine.
|
||||||
|
#
|
||||||
|
# Do not include Postfix-style virtual domains - those domains are
|
||||||
# specified elsewhere (see sample-virtual.cf, and sample-transport.cf).
|
# specified elsewhere (see sample-virtual.cf, and sample-transport.cf).
|
||||||
#
|
#
|
||||||
# The default is $myhostname + localhost.$mydomain. On a mail domain
|
# The default is $myhostname + localhost.$mydomain. On a mail domain
|
||||||
|
@@ -165,7 +165,11 @@ max_idle = 100s
|
|||||||
max_use = 100
|
max_use = 100
|
||||||
|
|
||||||
# The mydestination parameter specifies the list of domains that this
|
# The mydestination parameter specifies the list of domains that this
|
||||||
# machine considers itself the final destination for.
|
# machine considers itself the final destination for. That includes
|
||||||
|
# Sendmail-style virtual domains hosted on this machine.
|
||||||
|
#
|
||||||
|
# Do not include Postfix-style virtual domains - those domains are
|
||||||
|
# specified elsewhere (see sample-virtual.cf, and sample-transport.cf).
|
||||||
#
|
#
|
||||||
# The default is $myhostname + localhost.$mydomain. On a mail domain
|
# The default is $myhostname + localhost.$mydomain. On a mail domain
|
||||||
# gateway, you should also include $mydomain. Do not specify the
|
# gateway, you should also include $mydomain. Do not specify the
|
||||||
|
@@ -1366,8 +1366,9 @@ record, and that this one PTR record needs a matching A record.
|
|||||||
Some people read the RFCs such that one IP address can have multiple
|
Some people read the RFCs such that one IP address can have multiple
|
||||||
PTR records, but that makes PTR records even less useful than they
|
PTR records, but that makes PTR records even less useful than they
|
||||||
already are. And in any case, having multiple names per IP address
|
already are. And in any case, having multiple names per IP address
|
||||||
would only worsen the problem of finding out the "official name"
|
only worsens the problem of finding out the SMTP client hostname.
|
||||||
of a machine's IP address.
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
<a name="open_relay"><h3>Help! Postfix is an open relay</h3>
|
<a name="open_relay"><h3>Help! Postfix is an open relay</h3>
|
||||||
|
|
||||||
|
@@ -43,14 +43,14 @@ SENDMAIL(1) SENDMAIL(1)
|
|||||||
daemon.
|
daemon.
|
||||||
|
|
||||||
<b>newaliases</b>
|
<b>newaliases</b>
|
||||||
Initialize the alias database. If no alias database
|
Initialize the alias database. If no input file is
|
||||||
type is specified, the program uses the type speci-
|
specified (with the <b>-oA</b> option, see below), the
|
||||||
fied in the <b>database</b><i>_</i><b>type</b> configuration parameter;
|
program processes the file(s) specified with the
|
||||||
if no input file is specified, the program pro-
|
<b>alias</b><i>_</i><b>database</b> configuration parameter. If no
|
||||||
cesses the file(s) specified with the
|
alias database type is specified, the program uses
|
||||||
<b>alias</b><i>_</i><b>database</b> configuration parameter. This mode
|
the type specified with the <b>database</b><i>_</i><b>type</b> configu-
|
||||||
of operation is implemented by running the <b>postal-</b>
|
ration parameter. This mode of operation is imple-
|
||||||
<b>ias</b>(1) command.
|
mented by running the <a href="postalias.1.html"><b>postalias</b>(1)</a> command.
|
||||||
|
|
||||||
Note: it may take a minute or so before an alias
|
Note: it may take a minute or so before an alias
|
||||||
database update becomes visible. Use the <b>postfix</b>
|
database update becomes visible. Use the <b>postfix</b>
|
||||||
|
@@ -40,12 +40,13 @@ be delivered. If mail could not be delivered upon the last attempt,
|
|||||||
the reason for failure is shown. This mode of operation is implemented
|
the reason for failure is shown. This mode of operation is implemented
|
||||||
by connecting to the \fBshowq\fR(8) daemon.
|
by connecting to the \fBshowq\fR(8) daemon.
|
||||||
.IP \fBnewaliases\fR
|
.IP \fBnewaliases\fR
|
||||||
Initialize the alias database. If no alias database type is
|
Initialize the alias database. If no input file is specified (with
|
||||||
specified, the program uses the type specified in the
|
the \fB-oA\fR option, see below), the program processes the file(s)
|
||||||
\fBdatabase_type\fR configuration parameter; if no input file
|
specified with the \fBalias_database\fR configuration parameter.
|
||||||
is specified, the program processes the file(s) specified with the
|
If no alias database type is specified, the program uses the type
|
||||||
\fBalias_database\fR configuration parameter. This mode of operation
|
specified with the \fBdatabase_type\fR configuration parameter.
|
||||||
is implemented by running the \fBpostalias\fR(1) command.
|
This mode of operation is implemented by running the \fBpostalias\fR(1)
|
||||||
|
command.
|
||||||
.sp
|
.sp
|
||||||
Note: it may take a minute or so before an alias database update
|
Note: it may take a minute or so before an alias database update
|
||||||
becomes visible. Use the \fBpostfix reload\fR command to eliminate
|
becomes visible. Use the \fBpostfix reload\fR command to eliminate
|
||||||
|
@@ -138,8 +138,7 @@ int bounce_notify_service(char *service, char *queue_name,
|
|||||||
postmaster = flush ? var_2bounce_rcpt : var_delay_rcpt;
|
postmaster = flush ? var_2bounce_rcpt : var_delay_rcpt;
|
||||||
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
||||||
postmaster,
|
postmaster,
|
||||||
NULL_CLEANUP_FLAGS,
|
NULL_CLEANUP_FLAGS)) != 0) {
|
||||||
"BOUNCE")) != 0) {
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Double bounce to Postmaster. This is the last opportunity
|
* Double bounce to Postmaster. This is the last opportunity
|
||||||
@@ -163,8 +162,7 @@ int bounce_notify_service(char *service, char *queue_name,
|
|||||||
*/
|
*/
|
||||||
else {
|
else {
|
||||||
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
|
if ((bounce = post_mail_fopen_nowait(NULL_SENDER, recipient,
|
||||||
NULL_CLEANUP_FLAGS,
|
NULL_CLEANUP_FLAGS)) != 0) {
|
||||||
"BOUNCE")) != 0) {
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Send the bounce message header, some boilerplate text that
|
* Send the bounce message header, some boilerplate text that
|
||||||
@@ -203,8 +201,7 @@ int bounce_notify_service(char *service, char *queue_name,
|
|||||||
postmaster = flush ? var_bounce_rcpt : var_delay_rcpt;
|
postmaster = flush ? var_bounce_rcpt : var_delay_rcpt;
|
||||||
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
if ((bounce = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
||||||
postmaster,
|
postmaster,
|
||||||
NULL_CLEANUP_FLAGS,
|
NULL_CLEANUP_FLAGS)) != 0) {
|
||||||
"BOUNCE")) != 0) {
|
|
||||||
if (bounce_header(bounce, bounce_info, postmaster) == 0
|
if (bounce_header(bounce, bounce_info, postmaster) == 0
|
||||||
&& bounce_diagnostic_log(bounce, bounce_info) == 0
|
&& bounce_diagnostic_log(bounce, bounce_info) == 0
|
||||||
&& bounce_header_dsn(bounce, bounce_info) == 0
|
&& bounce_header_dsn(bounce, bounce_info) == 0
|
||||||
|
@@ -287,6 +287,29 @@ static void cleanup_header(CLEANUP_STATE *state)
|
|||||||
* we should do with this header: delete, count, rewrite. Note that we
|
* we should do with this header: delete, count, rewrite. Note that we
|
||||||
* should examine headers even when they will be deleted from the output,
|
* should examine headers even when they will be deleted from the output,
|
||||||
* because the addresses in those headers might be needed elsewhere.
|
* because the addresses in those headers might be needed elsewhere.
|
||||||
|
*
|
||||||
|
* XXX 2821: Return-path breakage.
|
||||||
|
*
|
||||||
|
* RFC 821 specifies: When the receiver-SMTP makes the "final delivery" of a
|
||||||
|
* message it inserts at the beginning of the mail data a return path
|
||||||
|
* line. The return path line preserves the information in the
|
||||||
|
* <reverse-path> from the MAIL command. Here, final delivery means the
|
||||||
|
* message leaves the SMTP world. Normally, this would mean it has been
|
||||||
|
* delivered to the destination user, but in some cases it may be further
|
||||||
|
* processed and transmitted by another mail system.
|
||||||
|
*
|
||||||
|
* And that is what Postfix implements. Delivery agents prepend
|
||||||
|
* Return-Path:. In order to avoid cluttering up the message with
|
||||||
|
* possibly inconsistent Return-Path: information (the sender can change
|
||||||
|
* as the result of mail forwarding or mailing list delivery), Postfix
|
||||||
|
* removes any existing Return-Path: headers.
|
||||||
|
*
|
||||||
|
* RFC 2821 Section 4.4 specifies: A message-originating SMTP system
|
||||||
|
* SHOULD NOT send a message that already contains a Return-path header.
|
||||||
|
* SMTP servers performing a relay function MUST NOT inspect the message
|
||||||
|
* data, and especially not to the extent needed to determine if
|
||||||
|
* Return-path headers are present. SMTP servers making final delivery
|
||||||
|
* MAY remove Return-path headers before adding their own.
|
||||||
*/
|
*/
|
||||||
else {
|
else {
|
||||||
state->headers_seen |= (1 << hdr_opts->type);
|
state->headers_seen |= (1 << hdr_opts->type);
|
||||||
@@ -324,6 +347,11 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
|
|||||||
/*
|
/*
|
||||||
* Add a missing (Resent-)Message-Id: header. The message ID gives the
|
* Add a missing (Resent-)Message-Id: header. The message ID gives the
|
||||||
* time in GMT units, plus the local queue ID.
|
* time in GMT units, plus the local queue ID.
|
||||||
|
*
|
||||||
|
* XXX Message-Id is not a required message header (RFC 822 and RFC 2822).
|
||||||
|
*
|
||||||
|
* XXX It is the queue ID non-inode bits that prevent messages from getting
|
||||||
|
* the same Message-Id within the same second.
|
||||||
*/
|
*/
|
||||||
if ((state->headers_seen & (1 << (state->resent[0] ?
|
if ((state->headers_seen & (1 << (state->resent[0] ?
|
||||||
HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
|
HDR_RESENT_MESSAGE_ID : HDR_MESSAGE_ID))) == 0) {
|
||||||
@@ -365,6 +393,29 @@ static void cleanup_missing_headers(CLEANUP_STATE *state)
|
|||||||
CLEANUP_OUT_BUF(state, REC_TYPE_NORM, state->temp2);
|
CLEANUP_OUT_BUF(state, REC_TYPE_NORM, state->temp2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX 2821: Appendix B: The return address in the MAIL command SHOULD,
|
||||||
|
* if possible, be derived from the system's identity for the submitting
|
||||||
|
* (local) user, and the "From:" header field otherwise. If there is a
|
||||||
|
* system identity available, it SHOULD also be copied to the Sender
|
||||||
|
* header field if it is different from the address in the From header
|
||||||
|
* field. (Any Sender field that was already there SHOULD be removed.)
|
||||||
|
* Similar wording appears in RFC 2822 section 3.6.2.
|
||||||
|
*
|
||||||
|
* Postfix presently does not insert a Sender: header if envelope and From:
|
||||||
|
* address differ. Older Postfix versions assumed that the envelope
|
||||||
|
* sender address specifies the system identity and inserted Sender:
|
||||||
|
* whenever envelope and From: differed. This was wrong with relayed
|
||||||
|
* mail, and was often not even desirable with original submissions.
|
||||||
|
*
|
||||||
|
* XXX 2822 Section 3.6.2, as well as RFC 822 Section 4.1: FROM headers can
|
||||||
|
* contain multiple addresses. If this is the case, then a Sender: header
|
||||||
|
* must be provided with a single address.
|
||||||
|
*
|
||||||
|
* Postfix does not count the number of addresses in a From: header
|
||||||
|
* (although doing so is trivial, once the address is parsed).
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a missing destination header.
|
* Add a missing destination header.
|
||||||
*/
|
*/
|
||||||
|
@@ -12,7 +12,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \
|
|||||||
mail_scan_dir.c mail_stream.c mail_task.c mail_trigger.c maps.c \
|
mail_scan_dir.c mail_stream.c mail_task.c mail_trigger.c maps.c \
|
||||||
mark_corrupt.c mkmap_db.c mkmap_dbm.c mkmap_open.c mynetworks.c \
|
mark_corrupt.c mkmap_db.c mkmap_dbm.c mkmap_open.c mynetworks.c \
|
||||||
mypwd.c namadr_list.c off_cvt.c opened.c own_inet_addr.c \
|
mypwd.c namadr_list.c off_cvt.c opened.c own_inet_addr.c \
|
||||||
peer_name.c pipe_command.c post_mail.c quote_821_local.c \
|
pipe_command.c post_mail.c quote_821_local.c \
|
||||||
quote_822_local.c rec_streamlf.c rec_type.c recipient_list.c \
|
quote_822_local.c rec_streamlf.c rec_type.c recipient_list.c \
|
||||||
record.c remove.c resolve_clnt.c resolve_local.c rewrite_clnt.c \
|
record.c remove.c resolve_clnt.c resolve_local.c rewrite_clnt.c \
|
||||||
sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
|
sent.c smtp_stream.c split_addr.c string_list.c sys_exits.c \
|
||||||
@@ -32,7 +32,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
|
|||||||
mail_scan_dir.o mail_stream.o mail_task.o mail_trigger.o maps.o \
|
mail_scan_dir.o mail_stream.o mail_task.o mail_trigger.o maps.o \
|
||||||
mark_corrupt.o mkmap_db.o mkmap_dbm.o mkmap_open.o mynetworks.o \
|
mark_corrupt.o mkmap_db.o mkmap_dbm.o mkmap_open.o mynetworks.o \
|
||||||
mypwd.o namadr_list.o off_cvt.o opened.o own_inet_addr.o \
|
mypwd.o namadr_list.o off_cvt.o opened.o own_inet_addr.o \
|
||||||
peer_name.o pipe_command.o post_mail.o quote_821_local.o \
|
pipe_command.o post_mail.o quote_821_local.o \
|
||||||
quote_822_local.o rec_streamlf.o rec_type.o recipient_list.o \
|
quote_822_local.o rec_streamlf.o rec_type.o recipient_list.o \
|
||||||
record.o remove.o resolve_clnt.o resolve_local.o rewrite_clnt.o \
|
record.o remove.o resolve_clnt.o resolve_local.o rewrite_clnt.o \
|
||||||
sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
|
sent.o smtp_stream.o split_addr.o string_list.o sys_exits.o \
|
||||||
@@ -49,7 +49,7 @@ HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
|
|||||||
mail_proto.h mail_queue.h mail_run.h mail_scan_dir.h mail_stream.h \
|
mail_proto.h mail_queue.h mail_run.h mail_scan_dir.h mail_stream.h \
|
||||||
mail_task.h mail_version.h maps.h mark_corrupt.h mkmap.h \
|
mail_task.h mail_version.h maps.h mark_corrupt.h mkmap.h \
|
||||||
mynetworks.h mypwd.h namadr_list.h off_cvt.h opened.h \
|
mynetworks.h mypwd.h namadr_list.h off_cvt.h opened.h \
|
||||||
own_inet_addr.h peer_name.h pipe_command.h post_mail.h \
|
own_inet_addr.h pipe_command.h post_mail.h \
|
||||||
quote_821_local.h quote_822_local.h rec_streamlf.h rec_type.h \
|
quote_821_local.h quote_822_local.h rec_streamlf.h rec_type.h \
|
||||||
recipient_list.h record.h resolve_clnt.h resolve_local.h \
|
recipient_list.h record.h resolve_clnt.h resolve_local.h \
|
||||||
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
|
rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
|
||||||
@@ -65,7 +65,7 @@ INCL =
|
|||||||
LIB = libglobal.a
|
LIB = libglobal.a
|
||||||
TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
|
TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
|
||||||
mail_addr_map mail_date maps mynetworks mypwd namadr_list \
|
mail_addr_map mail_date maps mynetworks mypwd namadr_list \
|
||||||
off_cvt peer_name quote_822_local rec2stream recdump resolve_clnt \
|
off_cvt quote_822_local rec2stream recdump resolve_clnt \
|
||||||
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
|
resolve_local rewrite_clnt stream2rec string_list tok822_parse \
|
||||||
quote_821_local mail_conf_time
|
quote_821_local mail_conf_time
|
||||||
|
|
||||||
|
@@ -41,6 +41,13 @@ int is_header(const char *str)
|
|||||||
const char *cp;
|
const char *cp;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX RFC 2822 Section 4.5.2, Obsolete header fields: whitespace may
|
||||||
|
* appear between header label and ":" (see: RFC 822, Section 3.4.2.).
|
||||||
|
*
|
||||||
|
* The code below allows no such whitespace. This has never been a problem,
|
||||||
|
* and therefore we're not inclined to add code for it.
|
||||||
|
*/
|
||||||
for (cp = str; (c = *(unsigned char *) cp) != 0; cp++) {
|
for (cp = str; (c = *(unsigned char *) cp) != 0; cp++) {
|
||||||
if (c == ':')
|
if (c == ':')
|
||||||
return (cp > str);
|
return (cp > str);
|
||||||
|
@@ -65,6 +65,8 @@
|
|||||||
/*
|
/*
|
||||||
/* char *var_import_environ;
|
/* char *var_import_environ;
|
||||||
/* char *var_export_environ;
|
/* char *var_export_environ;
|
||||||
|
/* char *var_debug_peer_list;
|
||||||
|
/* int var_debug_peer_level;
|
||||||
/*
|
/*
|
||||||
/* void mail_params_init()
|
/* void mail_params_init()
|
||||||
/* DESCRIPTION
|
/* DESCRIPTION
|
||||||
@@ -181,6 +183,8 @@ char *var_mynetworks_style;
|
|||||||
|
|
||||||
char *var_import_environ;
|
char *var_import_environ;
|
||||||
char *var_export_environ;
|
char *var_export_environ;
|
||||||
|
char *var_debug_peer_list;
|
||||||
|
int var_debug_peer_level;
|
||||||
|
|
||||||
/* check_myhostname - lookup hostname and validate */
|
/* check_myhostname - lookup hostname and validate */
|
||||||
|
|
||||||
@@ -298,6 +302,7 @@ void mail_params_init()
|
|||||||
VAR_IMPORT_ENVIRON, DEF_IMPORT_ENVIRON, &var_import_environ, 0, 0,
|
VAR_IMPORT_ENVIRON, DEF_IMPORT_ENVIRON, &var_import_environ, 0, 0,
|
||||||
VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport, 0, 0,
|
VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport, 0, 0,
|
||||||
VAR_MYNETWORKS_STYLE, DEF_MYNETWORKS_STYLE, &var_mynetworks_style, 1, 0,
|
VAR_MYNETWORKS_STYLE, DEF_MYNETWORKS_STYLE, &var_mynetworks_style, 1, 0,
|
||||||
|
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
|
static CONFIG_STR_FN_TABLE function_str_defaults_2[] = {
|
||||||
@@ -312,6 +317,7 @@ void mail_params_init()
|
|||||||
VAR_HASH_QUEUE_DEPTH, DEF_HASH_QUEUE_DEPTH, &var_hash_queue_depth, 1, 0,
|
VAR_HASH_QUEUE_DEPTH, DEF_HASH_QUEUE_DEPTH, &var_hash_queue_depth, 1, 0,
|
||||||
VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0,
|
VAR_FORK_TRIES, DEF_FORK_TRIES, &var_fork_tries, 1, 0,
|
||||||
VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0,
|
VAR_FLOCK_TRIES, DEF_FLOCK_TRIES, &var_flock_tries, 1, 0,
|
||||||
|
VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_TIME_TABLE time_defaults[] = {
|
static CONFIG_TIME_TABLE time_defaults[] = {
|
||||||
|
@@ -224,6 +224,10 @@ extern char *var_always_bcc;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* What to put in the To: header when no recipients were disclosed.
|
* What to put in the To: header when no recipients were disclosed.
|
||||||
|
*
|
||||||
|
* XXX 2822: When no recipient headers remain, a system should insert a Bcc:
|
||||||
|
* header without additional information. That is not so great given that
|
||||||
|
* MTAs routinely strip Bcc: headers from message headers.
|
||||||
*/
|
*/
|
||||||
#define VAR_RCPT_WITHELD "undisclosed_recipients_header"
|
#define VAR_RCPT_WITHELD "undisclosed_recipients_header"
|
||||||
#define DEF_RCPT_WITHELD "To: undisclosed-recipients:;"
|
#define DEF_RCPT_WITHELD "To: undisclosed-recipients:;"
|
||||||
@@ -634,6 +638,9 @@ extern int var_hash_queue_depth;
|
|||||||
* determines how many recipient addresses the SMTP client sends along with
|
* determines how many recipient addresses the SMTP client sends along with
|
||||||
* each message. Unfortunately, some mailers misbehave and disconnect (smap)
|
* each message. Unfortunately, some mailers misbehave and disconnect (smap)
|
||||||
* when given more recipients than they are willing to handle.
|
* when given more recipients than they are willing to handle.
|
||||||
|
*
|
||||||
|
* XXX 2821: A mail system is supposed to use EHLO instead of HELO, and to fall
|
||||||
|
* back to HELO if EHLO is not supported.
|
||||||
*/
|
*/
|
||||||
#define VAR_BESTMX_TRANSP "best_mx_transport"
|
#define VAR_BESTMX_TRANSP "best_mx_transport"
|
||||||
#define DEF_BESTMX_TRANSP ""
|
#define DEF_BESTMX_TRANSP ""
|
||||||
@@ -688,7 +695,11 @@ extern bool var_ign_mx_lookup_err;
|
|||||||
extern bool var_skip_quit_resp;
|
extern bool var_skip_quit_resp;
|
||||||
|
|
||||||
#define VAR_SMTP_ALWAYS_EHLO "smtp_always_send_ehlo"
|
#define VAR_SMTP_ALWAYS_EHLO "smtp_always_send_ehlo"
|
||||||
|
#ifdef RFC821_SYNTAX
|
||||||
#define DEF_SMTP_ALWAYS_EHLO 0
|
#define DEF_SMTP_ALWAYS_EHLO 0
|
||||||
|
#else
|
||||||
|
#define DEF_SMTP_ALWAYS_EHLO 1
|
||||||
|
#endif
|
||||||
extern bool var_smtp_always_ehlo;
|
extern bool var_smtp_always_ehlo;
|
||||||
|
|
||||||
#define VAR_SMTP_NEVER_EHLO "smtp_never_send_ehlo"
|
#define VAR_SMTP_NEVER_EHLO "smtp_never_send_ehlo"
|
||||||
|
@@ -378,6 +378,13 @@ VSTREAM *mail_queue_enter(const char *queue_name, int mode)
|
|||||||
file_id = get_file_id(fd);
|
file_id = get_file_id(fd);
|
||||||
GETTIMEOFDAY(&tv);
|
GETTIMEOFDAY(&tv);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Some systems seem to have clocks that correlate with process
|
||||||
|
* scheduling or something. Unfortunately, we cannot add random
|
||||||
|
* quantities to the time, because the non-inode part of a queue ID must
|
||||||
|
* not repeat within the same second. The queue ID is the sole thing that
|
||||||
|
* prevents multiple messages from getting the same Message-ID value.
|
||||||
|
*/
|
||||||
for (count = 0;; count++) {
|
for (count = 0;; count++) {
|
||||||
vstring_sprintf(id_buf, "%05X%s", (int) tv.tv_usec, file_id);
|
vstring_sprintf(id_buf, "%05X%s", (int) tv.tv_usec, file_id);
|
||||||
mail_queue_path(path_buf, queue_name, STR(id_buf));
|
mail_queue_path(path_buf, queue_name, STR(id_buf));
|
||||||
|
@@ -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-20010502"
|
#define DEF_MAIL_VERSION "Snapshot-20010520"
|
||||||
extern char *var_mail_version;
|
extern char *var_mail_version;
|
||||||
|
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
|
@@ -6,17 +6,15 @@
|
|||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include <post_mail.h>
|
/* #include <post_mail.h>
|
||||||
/*
|
/*
|
||||||
/* VSTREAM *post_mail_fopen(sender, recipient, flags, via)
|
/* VSTREAM *post_mail_fopen(sender, recipient, flags)
|
||||||
/* const char *sender;
|
/* const char *sender;
|
||||||
/* const char *recipient;
|
/* const char *recipient;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* const char *via;
|
|
||||||
/*
|
/*
|
||||||
/* VSTREAM *post_mail_fopen_nowait(sender, recipient, flags, via)
|
/* VSTREAM *post_mail_fopen_nowait(sender, recipient, flags)
|
||||||
/* const char *sender;
|
/* const char *sender;
|
||||||
/* const char *recipient;
|
/* const char *recipient;
|
||||||
/* int flags;
|
/* int flags;
|
||||||
/* const char *via;
|
|
||||||
/*
|
/*
|
||||||
/* int post_mail_fprintf(stream, format, ...)
|
/* int post_mail_fprintf(stream, format, ...)
|
||||||
/* VSTREAM *stream;
|
/* VSTREAM *stream;
|
||||||
@@ -132,7 +130,7 @@
|
|||||||
/* post_mail_init - initial negotiations */
|
/* post_mail_init - initial negotiations */
|
||||||
|
|
||||||
static void post_mail_init(VSTREAM *stream, const char *sender,
|
static void post_mail_init(VSTREAM *stream, const char *sender,
|
||||||
const char *recipient, int flags, const char *via)
|
const char *recipient, int flags)
|
||||||
{
|
{
|
||||||
VSTRING *id = vstring_alloc(100);
|
VSTRING *id = vstring_alloc(100);
|
||||||
long now = time((time_t *) 0);
|
long now = time((time_t *) 0);
|
||||||
@@ -158,8 +156,8 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
|
|||||||
* Do the Received: and Date: header lines. This allows us to shave a few
|
* Do the Received: and Date: header lines. This allows us to shave a few
|
||||||
* cycles by using the expensive date conversion result for both.
|
* cycles by using the expensive date conversion result for both.
|
||||||
*/
|
*/
|
||||||
post_mail_fprintf(stream, "Received: by %s (%s) via %s",
|
post_mail_fprintf(stream, "Received: by %s (%s)",
|
||||||
var_myhostname, var_mail_name, via);
|
var_myhostname, var_mail_name);
|
||||||
post_mail_fprintf(stream, "\tid %s; %s", vstring_str(id), date);
|
post_mail_fprintf(stream, "\tid %s; %s", vstring_str(id), date);
|
||||||
post_mail_fprintf(stream, "Date: %s", date);
|
post_mail_fprintf(stream, "Date: %s", date);
|
||||||
vstring_free(id);
|
vstring_free(id);
|
||||||
@@ -167,26 +165,25 @@ static void post_mail_init(VSTREAM *stream, const char *sender,
|
|||||||
|
|
||||||
/* post_mail_fopen - prepare for posting a message */
|
/* post_mail_fopen - prepare for posting a message */
|
||||||
|
|
||||||
VSTREAM *post_mail_fopen(const char *sender, const char *recipient,
|
VSTREAM *post_mail_fopen(const char *sender, const char *recipient, int flags)
|
||||||
int flags, const char *via)
|
|
||||||
{
|
{
|
||||||
VSTREAM *stream;
|
VSTREAM *stream;
|
||||||
|
|
||||||
stream = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
stream = mail_connect_wait(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP);
|
||||||
post_mail_init(stream, sender, recipient, flags, via);
|
post_mail_init(stream, sender, recipient, flags);
|
||||||
return (stream);
|
return (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* post_mail_fopen_nowait - prepare for posting a message */
|
/* post_mail_fopen_nowait - prepare for posting a message */
|
||||||
|
|
||||||
VSTREAM *post_mail_fopen_nowait(const char *sender, const char *recipient,
|
VSTREAM *post_mail_fopen_nowait(const char *sender, const char *recipient,
|
||||||
int flags, const char *via)
|
int flags)
|
||||||
{
|
{
|
||||||
VSTREAM *stream;
|
VSTREAM *stream;
|
||||||
|
|
||||||
if ((stream = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP,
|
if ((stream = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP,
|
||||||
BLOCKING)) != 0)
|
BLOCKING)) != 0)
|
||||||
post_mail_init(stream, sender, recipient, flags, via);
|
post_mail_init(stream, sender, recipient, flags);
|
||||||
return (stream);
|
return (stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,9 +24,8 @@
|
|||||||
/*
|
/*
|
||||||
* External interface.
|
* External interface.
|
||||||
*/
|
*/
|
||||||
extern VSTREAM *post_mail_fopen(const char *, const char *, int, const char *);
|
extern VSTREAM *post_mail_fopen(const char *, const char *, int);
|
||||||
extern VSTREAM *post_mail_fopen_nowait(const char *, const char *,
|
extern VSTREAM *post_mail_fopen_nowait(const char *, const char *, int);
|
||||||
int, const char *);
|
|
||||||
extern int PRINTFLIKE(2, 3) post_mail_fprintf(VSTREAM *, const char *,...);
|
extern int PRINTFLIKE(2, 3) post_mail_fprintf(VSTREAM *, const char *,...);
|
||||||
extern int post_mail_fputs(VSTREAM *, const char *);
|
extern int post_mail_fputs(VSTREAM *, const char *);
|
||||||
extern int post_mail_buffer(VSTREAM *, const char *, int);
|
extern int post_mail_buffer(VSTREAM *, const char *, int);
|
||||||
|
@@ -200,6 +200,9 @@ int smtp_get(VSTRING *vp, VSTREAM *stream, int bound)
|
|||||||
* Allow for partial long lines (we will read the remainder later) and
|
* Allow for partial long lines (we will read the remainder later) and
|
||||||
* allow for lines ending in bare LF. The idea is to be liberal in what
|
* allow for lines ending in bare LF. The idea is to be liberal in what
|
||||||
* we accept, strict in what we send.
|
* we accept, strict in what we send.
|
||||||
|
*
|
||||||
|
* XXX 2821: Section 4.1.1.4 says that an SMTP server must not recognize
|
||||||
|
* bare LF as record terminator.
|
||||||
*/
|
*/
|
||||||
smtp_timeout_reset(stream);
|
smtp_timeout_reset(stream);
|
||||||
last_char = (bound == 0 ? vstring_get(vp, stream) :
|
last_char = (bound == 0 ? vstring_get(vp, stream) :
|
||||||
|
@@ -45,8 +45,7 @@ typedef struct TOK822 {
|
|||||||
#define TOK822_DOMLIT 259 /* stuff between [] not nesting */
|
#define TOK822_DOMLIT 259 /* stuff between [] not nesting */
|
||||||
#define TOK822_ADDR 260 /* actually a token group */
|
#define TOK822_ADDR 260 /* actually a token group */
|
||||||
#define TOK822_STARTGRP 261 /* start of named group */
|
#define TOK822_STARTGRP 261 /* start of named group */
|
||||||
#define TOK822_COMMENT_TEXT 262 /* comment text */
|
#define TOK822_MAXTOK 261
|
||||||
#define TOK822_MAXTOK 262
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tok822_node.c
|
* tok822_node.c
|
||||||
|
@@ -57,7 +57,7 @@ TOK822 *tok822_alloc(int type, const char *strval)
|
|||||||
TOK822 *tp;
|
TOK822 *tp;
|
||||||
|
|
||||||
#define CONTAINER_TOKEN(x) \
|
#define CONTAINER_TOKEN(x) \
|
||||||
((x) == TOK822_ADDR || (x) == TOK822_COMMENT || (x) == TOK822_STARTGRP)
|
((x) == TOK822_ADDR || (x) == TOK822_STARTGRP)
|
||||||
|
|
||||||
tp = (TOK822 *) mymalloc(sizeof(*tp));
|
tp = (TOK822 *) mymalloc(sizeof(*tp));
|
||||||
tp->type = type;
|
tp->type = type;
|
||||||
|
@@ -192,12 +192,7 @@ VSTRING *tok822_internalize(VSTRING *vp, TOK822 *tree, int flags)
|
|||||||
tok822_internalize(vp, tp->head, TOK822_STR_NONE);
|
tok822_internalize(vp, tp->head, TOK822_STR_NONE);
|
||||||
break;
|
break;
|
||||||
case TOK822_COMMENT:
|
case TOK822_COMMENT:
|
||||||
VSTRING_ADDCH(vp, '(');
|
|
||||||
tok822_internalize(vp, tp->head, TOK822_STR_NONE);
|
|
||||||
VSTRING_ADDCH(vp, ')');
|
|
||||||
break;
|
|
||||||
case TOK822_ATOM:
|
case TOK822_ATOM:
|
||||||
case TOK822_COMMENT_TEXT:
|
|
||||||
case TOK822_QSTRING:
|
case TOK822_QSTRING:
|
||||||
vstring_strcat(vp, vstring_str(tp->vstr));
|
vstring_strcat(vp, vstring_str(tp->vstr));
|
||||||
break;
|
break;
|
||||||
@@ -244,15 +239,8 @@ VSTRING *tok822_externalize(VSTRING *vp, TOK822 *tree, int flags)
|
|||||||
tok822_externalize(vp, tp->head, TOK822_STR_NONE);
|
tok822_externalize(vp, tp->head, TOK822_STR_NONE);
|
||||||
break;
|
break;
|
||||||
case TOK822_ATOM:
|
case TOK822_ATOM:
|
||||||
vstring_strcat(vp, vstring_str(tp->vstr));
|
|
||||||
break;
|
|
||||||
case TOK822_COMMENT:
|
case TOK822_COMMENT:
|
||||||
VSTRING_ADDCH(vp, '(');
|
vstring_strcat(vp, vstring_str(tp->vstr));
|
||||||
tok822_externalize(vp, tp->head, TOK822_STR_NONE);
|
|
||||||
VSTRING_ADDCH(vp, ')');
|
|
||||||
break;
|
|
||||||
case TOK822_COMMENT_TEXT:
|
|
||||||
tok822_copy_quoted(vp, vstring_str(tp->vstr), "()\\");
|
|
||||||
break;
|
break;
|
||||||
case TOK822_QSTRING:
|
case TOK822_QSTRING:
|
||||||
VSTRING_ADDCH(vp, '"');
|
VSTRING_ADDCH(vp, '"');
|
||||||
@@ -321,6 +309,13 @@ TOK822 *tok822_scan(const char *str, TOK822 **tailp)
|
|||||||
TOK822 *tp;
|
TOK822 *tp;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX 2822 new feature: Section 4.1 allows "." to appear in a phrase (to
|
||||||
|
* allow for forms such as: Johnny B. Goode <johhny@domain.org>. I cannot
|
||||||
|
* handle that at the tokenizer level - it is not context sensitive. And
|
||||||
|
* to fix this at the parser level requires radical changes to preserve
|
||||||
|
* white space as part of the token stream. Thanks a lot, people.
|
||||||
|
*/
|
||||||
while ((ch = *(unsigned char *) str++) != 0) {
|
while ((ch = *(unsigned char *) str++) != 0) {
|
||||||
if (ISSPACE(ch))
|
if (ISSPACE(ch))
|
||||||
continue;
|
continue;
|
||||||
@@ -466,36 +461,32 @@ static void tok822_quote_atom(TOK822 *tp)
|
|||||||
|
|
||||||
static const char *tok822_comment(TOK822 *tp, const char *str)
|
static const char *tok822_comment(TOK822 *tp, const char *str)
|
||||||
{
|
{
|
||||||
TOK822 *tc = 0;
|
int level = 1;
|
||||||
int ch;
|
int ch;
|
||||||
|
|
||||||
#define COMMENT_TEXT_TOKEN(t) ((t) && (t)->type == TOK822_COMMENT_TEXT)
|
/*
|
||||||
|
* XXX We cheat by storing comments in their external form. Otherwise it
|
||||||
#define APPEND_NEW_TOKEN(tp, type, strval) \
|
* would be a royal pain to preserve \ before (. That would require a
|
||||||
tok822_sub_append(tp, tok822_alloc(type, strval))
|
* recursive parser, which could consume unreasonable amounts of memory.
|
||||||
|
*/
|
||||||
|
VSTRING_ADDCH(tp->vstr, '(');
|
||||||
|
|
||||||
while ((ch = *(unsigned char *) str) != 0) {
|
while ((ch = *(unsigned char *) str) != 0) {
|
||||||
|
VSTRING_ADDCH(tp->vstr, ch);
|
||||||
str++;
|
str++;
|
||||||
if (ch == '(') { /* comments can nest! */
|
if (ch == '(') { /* comments can nest! */
|
||||||
if (COMMENT_TEXT_TOKEN(tc))
|
level++;
|
||||||
VSTRING_TERMINATE(tc->vstr);
|
|
||||||
tc = APPEND_NEW_TOKEN(tp, TOK822_COMMENT, (char *) 0);
|
|
||||||
str = tok822_comment(tc, str);
|
|
||||||
} else if (ch == ')') {
|
} else if (ch == ')') {
|
||||||
|
if (--level == 0)
|
||||||
break;
|
break;
|
||||||
} else {
|
} else if (ch == '\\') {
|
||||||
if (ch == '\\') {
|
|
||||||
if ((ch = *(unsigned char *) str) == 0)
|
if ((ch = *(unsigned char *) str) == 0)
|
||||||
break;
|
break;
|
||||||
|
VSTRING_ADDCH(tp->vstr, ch);
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
if (!COMMENT_TEXT_TOKEN(tc))
|
|
||||||
tc = APPEND_NEW_TOKEN(tp, TOK822_COMMENT_TEXT, (char *) 0);
|
|
||||||
VSTRING_ADDCH(tc->vstr, ch);
|
|
||||||
}
|
}
|
||||||
}
|
VSTRING_TERMINATE(tp->vstr);
|
||||||
if (COMMENT_TEXT_TOKEN(tc))
|
|
||||||
VSTRING_TERMINATE(tc->vstr);
|
|
||||||
return (str);
|
return (str);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,14 +545,11 @@ static void tok822_print(TOK822 *list, int indent)
|
|||||||
} else if (tp->type == TOK822_ADDR) {
|
} else if (tp->type == TOK822_ADDR) {
|
||||||
vstream_printf("%*s %s\n", indent, "", "address");
|
vstream_printf("%*s %s\n", indent, "", "address");
|
||||||
tok822_print(tp->head, indent + 2);
|
tok822_print(tp->head, indent + 2);
|
||||||
} else if (tp->type == TOK822_COMMENT) {
|
|
||||||
vstream_printf("%*s %s\n", indent, "", "comment");
|
|
||||||
tok822_print(tp->head, indent + 2);
|
|
||||||
} else if (tp->type == TOK822_STARTGRP) {
|
} else if (tp->type == TOK822_STARTGRP) {
|
||||||
vstream_printf("%*s %s\n", indent, "", "group \":\"");
|
vstream_printf("%*s %s\n", indent, "", "group \":\"");
|
||||||
} else {
|
} else {
|
||||||
vstream_printf("%*s %s \"%s\"\n", indent, "",
|
vstream_printf("%*s %s \"%s\"\n", indent, "",
|
||||||
tp->type == TOK822_COMMENT_TEXT ? "text" :
|
tp->type == TOK822_COMMENT ? "comment" :
|
||||||
tp->type == TOK822_ATOM ? "atom" :
|
tp->type == TOK822_ATOM ? "atom" :
|
||||||
tp->type == TOK822_QSTRING ? "quoted string" :
|
tp->type == TOK822_QSTRING ? "quoted string" :
|
||||||
tp->type == TOK822_DOMLIT ? "domain literal" :
|
tp->type == TOK822_DOMLIT ? "domain literal" :
|
||||||
|
@@ -86,8 +86,7 @@ Parse tree:
|
|||||||
OP ","
|
OP ","
|
||||||
address
|
address
|
||||||
atom "venema"
|
atom "venema"
|
||||||
comment
|
comment "("wietse )"
|
||||||
text ""wietse "
|
|
||||||
OP ","
|
OP ","
|
||||||
address
|
address
|
||||||
quoted string ")"
|
quoted string ")"
|
||||||
@@ -135,11 +134,7 @@ Parse tree:
|
|||||||
OP "."
|
OP "."
|
||||||
atom "org"
|
atom "org"
|
||||||
OP ")"
|
OP ")"
|
||||||
comment
|
comment "( ("wietse ) venema")"
|
||||||
text " "
|
|
||||||
comment
|
|
||||||
text ""wietse "
|
|
||||||
text " venema""
|
|
||||||
|
|
||||||
Internalized:
|
Internalized:
|
||||||
wietse venema@porcupine.org) ( ("wietse ) venema")
|
wietse venema@porcupine.org) ( ("wietse ) venema")
|
||||||
@@ -272,9 +267,8 @@ Parse tree:
|
|||||||
atom "wietse"
|
atom "wietse"
|
||||||
OP "@"
|
OP "@"
|
||||||
atom "foo"
|
atom "foo"
|
||||||
comment
|
comment "(wietse
|
||||||
text "wietse
|
venema)"
|
||||||
venema"
|
|
||||||
|
|
||||||
Internalized:
|
Internalized:
|
||||||
wietse@foo (wietse
|
wietse@foo (wietse
|
||||||
|
@@ -269,8 +269,6 @@ int var_lmtp_data0_tmout;
|
|||||||
int var_lmtp_data1_tmout;
|
int var_lmtp_data1_tmout;
|
||||||
int var_lmtp_data2_tmout;
|
int var_lmtp_data2_tmout;
|
||||||
int var_lmtp_quit_tmout;
|
int var_lmtp_quit_tmout;
|
||||||
char *var_debug_peer_list;
|
|
||||||
int var_debug_peer_level;
|
|
||||||
int var_lmtp_cache_conn;
|
int var_lmtp_cache_conn;
|
||||||
int var_lmtp_skip_quit_resp;
|
int var_lmtp_skip_quit_resp;
|
||||||
char *var_notify_classes;
|
char *var_notify_classes;
|
||||||
@@ -505,7 +503,6 @@ static void pre_accept(char *unused_name, char **unused_argv)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
static CONFIG_STR_TABLE str_table[] = {
|
static CONFIG_STR_TABLE str_table[] = {
|
||||||
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
|
|
||||||
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
|
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
|
||||||
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
|
VAR_ERROR_RCPT, DEF_ERROR_RCPT, &var_error_rcpt, 1, 0,
|
||||||
VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_lmtp_sasl_passwd, 0, 0,
|
VAR_LMTP_SASL_PASSWD, DEF_LMTP_SASL_PASSWD, &var_lmtp_sasl_passwd, 0, 0,
|
||||||
@@ -514,7 +511,6 @@ int main(int argc, char **argv)
|
|||||||
};
|
};
|
||||||
static CONFIG_INT_TABLE int_table[] = {
|
static CONFIG_INT_TABLE int_table[] = {
|
||||||
VAR_LMTP_TCP_PORT, DEF_LMTP_TCP_PORT, &var_lmtp_tcp_port, 0, 0,
|
VAR_LMTP_TCP_PORT, DEF_LMTP_TCP_PORT, &var_lmtp_tcp_port, 0, 0,
|
||||||
VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
|
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_TIME_TABLE time_table[] = {
|
static CONFIG_TIME_TABLE time_table[] = {
|
||||||
|
@@ -268,7 +268,7 @@ void lmtp_chat_notify(LMTP_STATE *state)
|
|||||||
|
|
||||||
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
||||||
var_error_rcpt,
|
var_error_rcpt,
|
||||||
NULL_CLEANUP_FLAGS, "NOTICE");
|
NULL_CLEANUP_FLAGS);
|
||||||
if (notice == 0) {
|
if (notice == 0) {
|
||||||
msg_warn("postmaster notify: %m");
|
msg_warn("postmaster notify: %m");
|
||||||
return;
|
return;
|
||||||
|
@@ -66,7 +66,9 @@ postsuper.o: ../../include/vstring.h
|
|||||||
postsuper.o: ../../include/safe.h
|
postsuper.o: ../../include/safe.h
|
||||||
postsuper.o: ../../include/set_ugid.h
|
postsuper.o: ../../include/set_ugid.h
|
||||||
postsuper.o: ../../include/argv.h
|
postsuper.o: ../../include/argv.h
|
||||||
|
postsuper.o: ../../include/vstring_vstream.h
|
||||||
postsuper.o: ../../include/mail_task.h
|
postsuper.o: ../../include/mail_task.h
|
||||||
postsuper.o: ../../include/mail_conf.h
|
postsuper.o: ../../include/mail_conf.h
|
||||||
postsuper.o: ../../include/mail_params.h
|
postsuper.o: ../../include/mail_params.h
|
||||||
postsuper.o: ../../include/mail_queue.h
|
postsuper.o: ../../include/mail_queue.h
|
||||||
|
postsuper.o: ../../include/mail_open_ok.h
|
||||||
|
@@ -170,29 +170,43 @@ static int delete_one(const char *queue_id)
|
|||||||
MAIL_QUEUE_ACTIVE, /* foolproof but adequate */
|
MAIL_QUEUE_ACTIVE, /* foolproof but adequate */
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
|
const char *log_queue_names[] = {
|
||||||
|
MAIL_QUEUE_BOUNCE,
|
||||||
|
MAIL_QUEUE_DEFER,
|
||||||
|
0,
|
||||||
|
};
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char **cpp;
|
const char **msg_qpp;
|
||||||
const char *path;
|
const char **log_qpp;
|
||||||
|
const char *msg_path;
|
||||||
|
VSTRING *log_path_buf = vstring_alloc(100);
|
||||||
int found = 0;
|
int found = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do not delete defer or bounce logfiles, because we could lose a race
|
* Delete defer or bounce logfiles before deleting the corresponding
|
||||||
* and delete a defer/bounce logfile from a message that reuses the queue
|
* message file, and only if the message file exists. This minimizes but
|
||||||
* ID.
|
* does not eliminate a race condition with queue ID reuse which results
|
||||||
|
* in deleting the wrong files.
|
||||||
*/
|
*/
|
||||||
for (cpp = msg_queue_names; *cpp != 0; cpp++) {
|
for (msg_qpp = msg_queue_names; *msg_qpp != 0; msg_qpp++) {
|
||||||
if (!mail_open_ok(*cpp, queue_id, &st, &path)) {
|
if (!mail_open_ok(*msg_qpp, queue_id, &st, &msg_path))
|
||||||
continue;
|
continue;
|
||||||
} else if (unlink(path) == 0) {
|
for (log_qpp = log_queue_names; *log_qpp != 0; log_qpp++)
|
||||||
|
(void) mail_queue_path(log_path_buf, *log_qpp, queue_id);
|
||||||
|
if (unlink(STR(log_path_buf)) < 0 && errno != ENOENT)
|
||||||
|
msg_warn("remove file %s: %m", STR(log_path_buf));
|
||||||
|
if (unlink(msg_path) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
msg_info("removed file %s", path);
|
msg_info("removed file %s", msg_path);
|
||||||
break;
|
break;
|
||||||
} else if (errno != ENOENT) {
|
}
|
||||||
msg_warn("remove file %s: %m", path);
|
if (errno != ENOENT) {
|
||||||
|
msg_warn("remove file %s: %m", msg_path);
|
||||||
} else if (msg_verbose) {
|
} else if (msg_verbose) {
|
||||||
msg_info("remove file %s: %m", path);
|
msg_info("remove file %s: %m", msg_path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
vstring_free(log_path_buf);
|
||||||
return (found);
|
return (found);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,12 +34,13 @@
|
|||||||
/* the reason for failure is shown. This mode of operation is implemented
|
/* the reason for failure is shown. This mode of operation is implemented
|
||||||
/* by connecting to the \fBshowq\fR(8) daemon.
|
/* by connecting to the \fBshowq\fR(8) daemon.
|
||||||
/* .IP \fBnewaliases\fR
|
/* .IP \fBnewaliases\fR
|
||||||
/* Initialize the alias database. If no alias database type is
|
/* Initialize the alias database. If no input file is specified (with
|
||||||
/* specified, the program uses the type specified in the
|
/* the \fB-oA\fR option, see below), the program processes the file(s)
|
||||||
/* \fBdatabase_type\fR configuration parameter; if no input file
|
/* specified with the \fBalias_database\fR configuration parameter.
|
||||||
/* is specified, the program processes the file(s) specified with the
|
/* If no alias database type is specified, the program uses the type
|
||||||
/* \fBalias_database\fR configuration parameter. This mode of operation
|
/* specified with the \fBdatabase_type\fR configuration parameter.
|
||||||
/* is implemented by running the \fBpostalias\fR(1) command.
|
/* This mode of operation is implemented by running the \fBpostalias\fR(1)
|
||||||
|
/* command.
|
||||||
/* .sp
|
/* .sp
|
||||||
/* Note: it may take a minute or so before an alias database update
|
/* Note: it may take a minute or so before an alias database update
|
||||||
/* becomes visible. Use the \fBpostfix reload\fR command to eliminate
|
/* becomes visible. Use the \fBpostfix reload\fR command to eliminate
|
||||||
|
@@ -234,8 +234,6 @@ int var_smtp_data1_tmout;
|
|||||||
int var_smtp_data2_tmout;
|
int var_smtp_data2_tmout;
|
||||||
int var_smtp_quit_tmout;
|
int var_smtp_quit_tmout;
|
||||||
char *var_inet_interfaces;
|
char *var_inet_interfaces;
|
||||||
char *var_debug_peer_list;
|
|
||||||
int var_debug_peer_level;
|
|
||||||
char *var_notify_classes;
|
char *var_notify_classes;
|
||||||
int var_smtp_skip_4xx_greeting;
|
int var_smtp_skip_4xx_greeting;
|
||||||
int var_smtp_skip_5xx_greeting;
|
int var_smtp_skip_5xx_greeting;
|
||||||
@@ -395,7 +393,6 @@ static void pre_exit(void)
|
|||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
static CONFIG_STR_TABLE str_table[] = {
|
static CONFIG_STR_TABLE str_table[] = {
|
||||||
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
|
|
||||||
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
|
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
|
||||||
VAR_FALLBACK_RELAY, DEF_FALLBACK_RELAY, &var_fallback_relay, 0, 0,
|
VAR_FALLBACK_RELAY, DEF_FALLBACK_RELAY, &var_fallback_relay, 0, 0,
|
||||||
VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0,
|
VAR_BESTMX_TRANSP, DEF_BESTMX_TRANSP, &var_bestmx_transp, 0, 0,
|
||||||
@@ -417,7 +414,6 @@ int main(int argc, char **argv)
|
|||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_INT_TABLE int_table[] = {
|
static CONFIG_INT_TABLE int_table[] = {
|
||||||
VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
|
|
||||||
0,
|
0,
|
||||||
};
|
};
|
||||||
static CONFIG_BOOL_TABLE bool_table[] = {
|
static CONFIG_BOOL_TABLE bool_table[] = {
|
||||||
|
@@ -207,6 +207,11 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why)
|
|||||||
/*
|
/*
|
||||||
* As long as we are able to look up any host address, we ignore problems
|
* As long as we are able to look up any host address, we ignore problems
|
||||||
* with DNS lookups.
|
* with DNS lookups.
|
||||||
|
*
|
||||||
|
* XXX 2821: update smtp_errno (0->FAIL upon unrecoverable lookup error,
|
||||||
|
* any->RETRY upon temporary lookup error) so that we can correctly
|
||||||
|
* handle the case of no resolvable MX host. Currently this is always
|
||||||
|
* treated as a soft error. RFC 2821 wants a more precise response.
|
||||||
*/
|
*/
|
||||||
for (rr = mx_names; rr; rr = rr->next) {
|
for (rr = mx_names; rr; rr = rr->next) {
|
||||||
if (rr->type != T_MX)
|
if (rr->type != T_MX)
|
||||||
@@ -320,6 +325,19 @@ DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself)
|
|||||||
* as we're looking up all the hosts, it would be better to look up the
|
* as we're looking up all the hosts, it would be better to look up the
|
||||||
* least preferred host first, so that DNS lookup error messages make
|
* least preferred host first, so that DNS lookup error messages make
|
||||||
* more sense.
|
* more sense.
|
||||||
|
*
|
||||||
|
* XXX 2821: RFC 2821 says that the sender must shuffle equal-preference MX
|
||||||
|
* hosts, whereas multiple A records per hostname must be used in the
|
||||||
|
* order as received. They make the bogus assumption that a hostname with
|
||||||
|
* multiple A records corresponds to one machine with multiple network
|
||||||
|
* interfaces.
|
||||||
|
*
|
||||||
|
* XXX 2821: Postfix recognizes the local machine by looking for its own IP
|
||||||
|
* address in the list of mail exchangers. RFC 2821 says one has to look
|
||||||
|
* at the mail exchanger hostname as well, making the bogus assumption
|
||||||
|
* that an IP address is listed only under one hostname. However, looking
|
||||||
|
* at hostnames provides a partial solution for MX hosts behind a NAT
|
||||||
|
* gateway.
|
||||||
*/
|
*/
|
||||||
switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why)) {
|
switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why)) {
|
||||||
default:
|
default:
|
||||||
|
@@ -252,7 +252,7 @@ void smtp_chat_notify(SMTP_STATE *state)
|
|||||||
|
|
||||||
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
||||||
var_error_rcpt,
|
var_error_rcpt,
|
||||||
NULL_CLEANUP_FLAGS, "NOTICE");
|
NULL_CLEANUP_FLAGS);
|
||||||
if (notice == 0) {
|
if (notice == 0) {
|
||||||
msg_warn("postmaster notify: %m");
|
msg_warn("postmaster notify: %m");
|
||||||
return;
|
return;
|
||||||
|
@@ -213,10 +213,13 @@ int smtp_helo(SMTP_STATE *state)
|
|||||||
* overflow detection, ignore the message size limit advertised by the
|
* overflow detection, ignore the message size limit advertised by the
|
||||||
* SMTP server. Otherwise, we might do the wrong thing when the server
|
* SMTP server. Otherwise, we might do the wrong thing when the server
|
||||||
* advertises a really huge message size limit.
|
* advertises a really huge message size limit.
|
||||||
|
*
|
||||||
|
* XXX Allow for "code (SP|-) ehlo-keyword (SP|=) ehlo-param...", because
|
||||||
|
* MicroSoft implemented AUTH based on an old draft.
|
||||||
*/
|
*/
|
||||||
lines = resp->str;
|
lines = resp->str;
|
||||||
while ((words = mystrtok(&lines, "\n")) != 0) {
|
while ((words = mystrtok(&lines, "\n")) != 0) {
|
||||||
if (mystrtok(&words, "- ") && (word = mystrtok(&words, " \t")) != 0) {
|
if (mystrtok(&words, "- =") && (word = mystrtok(&words, " \t")) != 0) {
|
||||||
if (strcasecmp(word, "8BITMIME") == 0)
|
if (strcasecmp(word, "8BITMIME") == 0)
|
||||||
state->features |= SMTP_FEATURE_8BITMIME;
|
state->features |= SMTP_FEATURE_8BITMIME;
|
||||||
else if (strcasecmp(word, "PIPELINING") == 0)
|
else if (strcasecmp(word, "PIPELINING") == 0)
|
||||||
@@ -226,8 +229,6 @@ int smtp_helo(SMTP_STATE *state)
|
|||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
|
else if (var_smtp_sasl_enable && strcasecmp(word, "AUTH") == 0)
|
||||||
smtp_sasl_helo_auth(state, words);
|
smtp_sasl_helo_auth(state, words);
|
||||||
else if (var_smtp_sasl_enable && strncasecmp(word, "AUTH=", 5) == 0)
|
|
||||||
smtp_sasl_helo_auth(state, word + 5);
|
|
||||||
#endif
|
#endif
|
||||||
else if (strcasecmp(word, var_myhostname) == 0) {
|
else if (strcasecmp(word, var_myhostname) == 0) {
|
||||||
msg_warn("host %s replied to HELO/EHLO with my own hostname %s",
|
msg_warn("host %s replied to HELO/EHLO with my own hostname %s",
|
||||||
@@ -480,9 +481,16 @@ int smtp_xfer(SMTP_STATE *state)
|
|||||||
* rejected, ignore RCPT TO responses: all recipients are
|
* rejected, ignore RCPT TO responses: all recipients are
|
||||||
* dead already. When all recipients are rejected the
|
* dead already. When all recipients are rejected the
|
||||||
* receiver may apply a course correction.
|
* receiver may apply a course correction.
|
||||||
|
*
|
||||||
|
* XXX 2821: Section 4.5.3.1 says that a 552 RCPT TO reply
|
||||||
|
* must be treated as if the server replied with 452.
|
||||||
*/
|
*/
|
||||||
case SMTP_STATE_RCPT:
|
case SMTP_STATE_RCPT:
|
||||||
if (!mail_from_rejected) {
|
if (!mail_from_rejected) {
|
||||||
|
#ifndef RFC821_SYNTAX
|
||||||
|
if (resp->code == 552)
|
||||||
|
resp->code = 452;
|
||||||
|
#endif
|
||||||
if (resp->code / 100 == 2) {
|
if (resp->code / 100 == 2) {
|
||||||
++nrcpt;
|
++nrcpt;
|
||||||
} else {
|
} else {
|
||||||
|
@@ -311,8 +311,6 @@ int var_smtpd_soft_erlim;
|
|||||||
int var_smtpd_hard_erlim;
|
int var_smtpd_hard_erlim;
|
||||||
int var_queue_minfree; /* XXX use off_t */
|
int var_queue_minfree; /* XXX use off_t */
|
||||||
char *var_smtpd_banner;
|
char *var_smtpd_banner;
|
||||||
char *var_debug_peer_list;
|
|
||||||
int var_debug_peer_level;
|
|
||||||
char *var_notify_classes;
|
char *var_notify_classes;
|
||||||
char *var_client_checks;
|
char *var_client_checks;
|
||||||
char *var_helo_checks;
|
char *var_helo_checks;
|
||||||
@@ -416,6 +414,11 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
{
|
{
|
||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX 2821 new feature: Section 4.1.4 specifies that a server must clear
|
||||||
|
* all buffers and reset the state exactly as if a RSET command had been
|
||||||
|
* issued.
|
||||||
|
*/
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
smtpd_chat_reply(state, "501 Syntax: EHLO hostname");
|
smtpd_chat_reply(state, "501 Syntax: EHLO hostname");
|
||||||
@@ -423,7 +426,7 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
}
|
}
|
||||||
if (state->helo_name != 0)
|
if (state->helo_name != 0)
|
||||||
helo_reset(state);
|
helo_reset(state);
|
||||||
#if 0
|
#ifndef RFC821_SYNTAX
|
||||||
mail_reset(state);
|
mail_reset(state);
|
||||||
rcpt_reset(state);
|
rcpt_reset(state);
|
||||||
#endif
|
#endif
|
||||||
@@ -444,6 +447,8 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
(unsigned long) var_message_limit); /* XXX */
|
(unsigned long) var_message_limit); /* XXX */
|
||||||
else
|
else
|
||||||
smtpd_chat_reply(state, "250-SIZE");
|
smtpd_chat_reply(state, "250-SIZE");
|
||||||
|
if (var_disable_vrfy_cmd == 0)
|
||||||
|
smtpd_chat_reply(state, "250-VRFY");
|
||||||
smtpd_chat_reply(state, "250-ETRN");
|
smtpd_chat_reply(state, "250-ETRN");
|
||||||
#ifdef USE_SASL_AUTH
|
#ifdef USE_SASL_AUTH
|
||||||
if (var_smtpd_sasl_enable) {
|
if (var_smtpd_sasl_enable) {
|
||||||
@@ -471,6 +476,18 @@ static void mail_open_stream(SMTPD_STATE *state)
|
|||||||
{
|
{
|
||||||
char *postdrop_command;
|
char *postdrop_command;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX 2821: An SMTP server is not allowed to "clean up" mail except in
|
||||||
|
* the case of original submissions. Presently, Postfix always runs all
|
||||||
|
* mail through the cleanup server.
|
||||||
|
*
|
||||||
|
* We could approximate the RFC as follows: Postfix rewrites mail if it
|
||||||
|
* comes from a source that we are willing to relay for. This way, we
|
||||||
|
* avoid rewriting most mail that comes from elsewhere. However, that
|
||||||
|
* requires moving functionality away from the cleanup daemon elsewhere,
|
||||||
|
* such as virtual address expansion, and header/body pattern matching.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If running from the master or from inetd, connect to the cleanup
|
* If running from the master or from inetd, connect to the cleanup
|
||||||
* service.
|
* service.
|
||||||
@@ -613,6 +630,12 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
/*
|
/*
|
||||||
* Sanity checks. XXX Ignore bad SIZE= values until we can reliably and
|
* Sanity checks. XXX Ignore bad SIZE= values until we can reliably and
|
||||||
* portably detect overflows while converting from string to off_t.
|
* portably detect overflows while converting from string to off_t.
|
||||||
|
*
|
||||||
|
* XXX 2821 pedantism: Section 4.1.2 says that SMTP servers that receive a
|
||||||
|
* command in which invalid character codes have been employed, and for
|
||||||
|
* which there are no other reasons for rejection, MUST reject that
|
||||||
|
* command with a 501 response. So much for the principle of "be liberal
|
||||||
|
* in what you accept, be strict in what you send".
|
||||||
*/
|
*/
|
||||||
if (var_helo_required && state->helo_name == 0) {
|
if (var_helo_required && state->helo_name == 0) {
|
||||||
state->error_mask |= MAIL_ERROR_POLICY;
|
state->error_mask |= MAIL_ERROR_POLICY;
|
||||||
@@ -746,6 +769,12 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity checks.
|
* Sanity checks.
|
||||||
|
*
|
||||||
|
* XXX 2821 pedantism: Section 4.1.2 says that SMTP servers that receive a
|
||||||
|
* command in which invalid character codes have been employed, and for
|
||||||
|
* which there are no other reasons for rejection, MUST reject that
|
||||||
|
* command with a 501 response. So much for the principle of "be liberal
|
||||||
|
* in what you accept, be strict in what you send".
|
||||||
*/
|
*/
|
||||||
if (state->cleanup == 0) {
|
if (state->cleanup == 0) {
|
||||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||||
@@ -1023,6 +1052,15 @@ static int rset_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
static int noop_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
static int noop_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX 2821 incompatibility: Section 4.1.1.9 says that NOOP can have a
|
||||||
|
* parameter string which is to be ignored. NOOP instructions with
|
||||||
|
* parameters? Go figure.
|
||||||
|
*
|
||||||
|
* RFC 2821 violates RFC 821, which says that NOOP takes no parameters.
|
||||||
|
*/
|
||||||
|
#ifdef RFC821_SYNTAX
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity checks.
|
* Sanity checks.
|
||||||
*/
|
*/
|
||||||
@@ -1031,6 +1069,7 @@ static int noop_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
|
|||||||
smtpd_chat_reply(state, "501 Syntax: NOOP");
|
smtpd_chat_reply(state, "501 Syntax: NOOP");
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
smtpd_chat_reply(state, "250 Ok");
|
smtpd_chat_reply(state, "250 Ok");
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -1051,6 +1090,17 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
* address forms. Therefore we must parse out the address, or we must
|
* address forms. Therefore we must parse out the address, or we must
|
||||||
* stop doing recipient restriction checks and lose the opportunity to
|
* stop doing recipient restriction checks and lose the opportunity to
|
||||||
* say "user unknown" at the SMTP port.
|
* say "user unknown" at the SMTP port.
|
||||||
|
*
|
||||||
|
* XXX 2821 incompatibility and brain damage: Section 4.5.1 requires that
|
||||||
|
* VRFY is implemented. RFC 821 specifies that VRFY is optional. It gets
|
||||||
|
* even worse: section 3.5.3 says that a 502 (command recognized but not
|
||||||
|
* implemented) reply is not fully compliant.
|
||||||
|
*
|
||||||
|
* Thus, an RFC 2821 compliant implementation cannot refuse to supply
|
||||||
|
* information in reply to VRFY queries. That is simply bogus. The only
|
||||||
|
* reply we could supply is a generic 252 reply. This causes spammers to
|
||||||
|
* add tons of bogus addresses to their mailing lists (spam harvesting by
|
||||||
|
* trying out large lists of potential recipient names with VRFY).
|
||||||
*/
|
*/
|
||||||
#define SLOPPY 0
|
#define SLOPPY 0
|
||||||
|
|
||||||
@@ -1076,7 +1126,17 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
|||||||
smtpd_chat_reply(state, "%s", err);
|
smtpd_chat_reply(state, "%s", err);
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
smtpd_chat_reply(state, "252 <%s>", argv[1].strval);
|
|
||||||
|
/*
|
||||||
|
* XXX 2821 new feature: Section 3.5.1 requires that the VRFY response is
|
||||||
|
* either "full name <user@domain>" or "user@domain". Postfix replies
|
||||||
|
* with the address that was provided by the client, whether or not it is
|
||||||
|
* in fully qualified domain form or not.
|
||||||
|
*
|
||||||
|
* Reply code 250 is reserved for the case where the address is verified;
|
||||||
|
* reply code 252 should be used when no definitive certainty exists.
|
||||||
|
*/
|
||||||
|
smtpd_chat_reply(state, "252 %s", argv[1].strval);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1256,7 +1316,8 @@ static void smtpd_proto(SMTPD_STATE *state)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (state->access_denied && cmdp->action != quit_cmd) {
|
if (state->access_denied && cmdp->action != quit_cmd) {
|
||||||
smtpd_chat_reply(state, "%s", state->access_denied);
|
smtpd_chat_reply(state, "503 Error: access denied for %s",
|
||||||
|
state->namaddr); /* RFC 2821 Sec 3.1 */
|
||||||
state->error_count++;
|
state->error_count++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1445,7 +1506,6 @@ int main(int argc, char **argv)
|
|||||||
VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim, 1, 0,
|
VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim, 1, 0,
|
||||||
VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim, 1, 0,
|
VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim, 1, 0,
|
||||||
VAR_QUEUE_MINFREE, DEF_QUEUE_MINFREE, &var_queue_minfree, 0, 0,
|
VAR_QUEUE_MINFREE, DEF_QUEUE_MINFREE, &var_queue_minfree, 0, 0,
|
||||||
VAR_DEBUG_PEER_LEVEL, DEF_DEBUG_PEER_LEVEL, &var_debug_peer_level, 1, 0,
|
|
||||||
VAR_UNK_CLIENT_CODE, DEF_UNK_CLIENT_CODE, &var_unk_client_code, 0, 0,
|
VAR_UNK_CLIENT_CODE, DEF_UNK_CLIENT_CODE, &var_unk_client_code, 0, 0,
|
||||||
VAR_BAD_NAME_CODE, DEF_BAD_NAME_CODE, &var_bad_name_code, 0, 0,
|
VAR_BAD_NAME_CODE, DEF_BAD_NAME_CODE, &var_bad_name_code, 0, 0,
|
||||||
VAR_UNK_NAME_CODE, DEF_UNK_NAME_CODE, &var_unk_name_code, 0, 0,
|
VAR_UNK_NAME_CODE, DEF_UNK_NAME_CODE, &var_unk_name_code, 0, 0,
|
||||||
@@ -1475,7 +1535,6 @@ int main(int argc, char **argv)
|
|||||||
};
|
};
|
||||||
static CONFIG_STR_TABLE str_table[] = {
|
static CONFIG_STR_TABLE str_table[] = {
|
||||||
VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0,
|
VAR_SMTPD_BANNER, DEF_SMTPD_BANNER, &var_smtpd_banner, 1, 0,
|
||||||
VAR_DEBUG_PEER_LIST, DEF_DEBUG_PEER_LIST, &var_debug_peer_list, 0, 0,
|
|
||||||
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
|
VAR_NOTIFY_CLASSES, DEF_NOTIFY_CLASSES, &var_notify_classes, 0, 0,
|
||||||
VAR_CLIENT_CHECKS, DEF_CLIENT_CHECKS, &var_client_checks, 0, 0,
|
VAR_CLIENT_CHECKS, DEF_CLIENT_CHECKS, &var_client_checks, 0, 0,
|
||||||
VAR_HELO_CHECKS, DEF_HELO_CHECKS, &var_helo_checks, 0, 0,
|
VAR_HELO_CHECKS, DEF_HELO_CHECKS, &var_helo_checks, 0, 0,
|
||||||
|
@@ -207,7 +207,7 @@ void smtpd_chat_notify(SMTPD_STATE *state)
|
|||||||
|
|
||||||
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
notice = post_mail_fopen_nowait(mail_addr_double_bounce(),
|
||||||
var_error_rcpt,
|
var_error_rcpt,
|
||||||
NULL_CLEANUP_FLAGS, "NOTICE");
|
NULL_CLEANUP_FLAGS);
|
||||||
if (notice == 0) {
|
if (notice == 0) {
|
||||||
msg_warn("postmaster notify: %m");
|
msg_warn("postmaster notify: %m");
|
||||||
return;
|
return;
|
||||||
|
@@ -551,6 +551,26 @@ static int smtpd_check_reject(SMTPD_STATE *state, int error_class,
|
|||||||
}
|
}
|
||||||
printable(STR(error_text), ' ');
|
printable(STR(error_text), ' ');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX The code below also appears in the SMTP server reply output
|
||||||
|
* routine. It is duplicated here in order to avoid discrepancies between
|
||||||
|
* the reply codes that are shown in "reject" logging and the reply codes
|
||||||
|
* that are actually sent to the SMTP client.
|
||||||
|
*
|
||||||
|
* Implementing the soft_bounce safety net in the SMTP server reply output
|
||||||
|
* routine has the advantage that it covers all 5xx replies, including
|
||||||
|
* SMTP protocol or syntax errors, which makes soft_bounce great for
|
||||||
|
* non-destructive tests (especially by people who are paranoid about
|
||||||
|
* losing mail).
|
||||||
|
*
|
||||||
|
* We could eliminate the code duplication and implement the soft_bounce
|
||||||
|
* safety net only in the code below. But then the safety net would cover
|
||||||
|
* the UCE restrictions only. This would be at odds with the documentation
|
||||||
|
* which says soft_bounce changes all 5xx replies into 4xx ones.
|
||||||
|
*/
|
||||||
|
if (var_soft_bounce && STR(error_text)[0] == '5')
|
||||||
|
STR(error_text)[0] = '4';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Log what is happening. When the sysadmin discards policy violation
|
* Log what is happening. When the sysadmin discards policy violation
|
||||||
* postmaster notices, this may be the only trace left that service was
|
* postmaster notices, this may be the only trace left that service was
|
||||||
@@ -1898,6 +1918,13 @@ char *smtpd_check_rcpt(SMTPD_STATE *state, char *recipient)
|
|||||||
if (recipient == 0)
|
if (recipient == 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX 2821: Section 3.6 requires that "postmaster" be accepted even when
|
||||||
|
* specified without a fully qualified domain name.
|
||||||
|
*/
|
||||||
|
if (strcasecmp(recipient, "postmaster") == 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Minor kluge so that we can delegate work to the generic routine and so
|
* Minor kluge so that we can delegate work to the generic routine and so
|
||||||
* that we can syslog the recipient with the reject messages.
|
* that we can syslog the recipient with the reject messages.
|
||||||
|
Reference in New Issue
Block a user