2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-29 21:27:57 +00:00

postfix-2.0.16-20031216

This commit is contained in:
Wietse Venema 2003-12-16 00:00:00 -05:00 committed by Viktor Dukhovni
parent 7aef2f8c02
commit 49328174e4
12 changed files with 267 additions and 262 deletions

View File

@ -8818,13 +8818,14 @@ Apologies for any names omitted.
of a sender address. Code by Liviu Daia. Files:
smtpd/smtpd_check.c and documentation.
The reject_sender_login_mismatch feature is now implemented
by elementary features reject_unauth_sender_login_mismatch
reject_sender_login_mismatch is now implemented by elementary
features reject_unauthenticated_sender_login_mismatch
(reject if the client is not SASL logged in but the sender
address has an owner in smtpd_sender_login_maps) and
reject_auth_sender_login_mismatch (reject if the client is
SASL logged in but does not own the sender address). Code
by Liviu Daia. Files: smtpd/smtpd_check.c and documentation.
reject_authenticated_sender_login_mismatch (reject if the
client is SASL logged in but does not own the sender
address). Code by Liviu Daia. Files: smtpd/smtpd_check.c
and documentation.
20031207
@ -8864,6 +8865,16 @@ Apologies for any names omitted.
settings before and after DNS lookup, to avoid surprises
in third-party code. File: dns/dns_lookup.c.
20031216
Cleanup: easier to parse mailq output (no more space
between short queue ID and message status). File:
showq/showq.c.
Cleanup: the SMTP client now moves on to the next MX host
when delivery fails in the middle of an SMTP session.
Files: smtp/smtp.c, smtp/smtp_connect.c.
Open problems:
High: when virtual aliasing is turned off after content
@ -8886,9 +8897,8 @@ Open problems:
Low: postmap/postalias should not try to open a bogus file
when given an unsupported dictionary type.
Med: do not postpone rejected "MAIL FROM" size information,
and find a way to log the sender address in the rejected
command.
Med: find a way to log the sender address when MAIL FROM
is rejected due to lack of disk space.
Low: after successful delivery, per-queue window += 1/window,
after failure, queue window -= 1 (Victor).
@ -8929,8 +8939,8 @@ Open problems:
Low: postconf -e edits parameters that postconf won't list.
Low: with quoted-printable, perhaps use =46rom instead of
>From.
Low: while convering 8bit text to quoted-printable, perhaps
use =46rom instead of >From.
virtual_mailbox_path expression like forward_path, so that
people can specify prefix and suffix.

View File

@ -16,7 +16,7 @@ This extension is implemented as a separate command, so that it
can be used to transmit client or message attributes incrementally.
It is not implemented by passing additional parameters via the MAIL
FROM command, because doing so would require extending the MAIL
FROM command length limit by another 600 or more characters beyond.
FROM command length limit by another 600 or more characters.
Command syntax
==============
@ -32,7 +32,7 @@ names are shown in upper case, they are in fact case insensitive.
xforward-command = XFORWARD 1*( SP name"="value )
name = ( NAME | ADDR | PROTO | HELO | IDENT )
name = ( NAME | ADDR | PROTO | HELO )
The XFORWARD command can be sent at any time except in the middle
of a mail delivery transaction (i.e. between MAIL and DOT). The

View File

@ -1,4 +1,4 @@
<html> <head> </head> <body> <pre>
<html> <body> <pre>
SHOWQ(8) SHOWQ(8)
<b>NAME</b>

View File

@ -141,7 +141,7 @@ static int dns_query(const char *name, int type, int flags,
{
HEADER *reply_header;
int len;
int saved_options = _res.options;
unsigned long saved_options = _res.options;
/*
* Initialize the name service.

View File

@ -20,7 +20,7 @@
* Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release.
*/
#define MAIL_RELEASE_DATE "20031215"
#define MAIL_RELEASE_DATE "20031216"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE

View File

@ -94,7 +94,7 @@ int var_dup_filter_limit;
char *var_empty_addr;
#define STRING_FORMAT "%-10s %8s %-20s %s\n"
#define DATA_FORMAT "%-10s%c%8ld %20.20s %s\n"
#define SENDER_FORMAT "%-11s%8ld %20.20s %s\n"
#define DROP_FORMAT "%-10s%c%8ld %20.20s (maildrop queue, sender UID %u)\n"
static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *);
@ -150,7 +150,9 @@ static void showq_report(VSTREAM *client, char *queue, char *id,
start = var_empty_addr;
quote_822_local(printable_quoted_addr, start);
printable(STR(printable_quoted_addr), '?');
vstream_fprintf(client, DATA_FORMAT, id, status,
/* quote_822_local() saves buf, so we can reuse its space. */
vstring_sprintf(buf, "%s%c", id, status);
vstream_fprintf(client, SENDER_FORMAT, STR(buf),
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
asctime(localtime(&arrival_time)) :
asctime(localtime(&mtime)),

View File

@ -265,8 +265,6 @@
#include <mail_params.h>
#include <mail_conf.h>
#include <debug_peer.h>
#include <mail_error.h>
#include <deliver_pass.h>
/* Single server skeleton. */
@ -327,7 +325,6 @@ int smtp_host_lookup_mask;
static int deliver_message(DELIVER_REQUEST *request)
{
VSTRING *why;
SMTP_STATE *state;
int result;
@ -349,7 +346,6 @@ static int deliver_message(DELIVER_REQUEST *request)
* we can produce understandable diagnostics when something goes wrong
* many levels below. The alternative would be to make everything global.
*/
why = vstring_alloc(100);
state = smtp_state_alloc();
state->request = request;
state->src = request->fp;
@ -360,35 +356,12 @@ static int deliver_message(DELIVER_REQUEST *request)
* Optionally deliver mail locally when this machine is the best mail
* exchanger.
*/
if ((state->session = smtp_connect(request->nexthop, why)) == 0) {
if (smtp_errno == SMTP_OK) {
if (*var_bestmx_transp == 0)
msg_panic("smtp_errno botch");
state->status = deliver_pass_all(MAIL_CLASS_PRIVATE,
var_bestmx_transp,
request);
} else
smtp_site_fail(state, smtp_errno == SMTP_RETRY ? 450 : 550,
"%s", vstring_str(why));
} else {
debug_peer_check(state->session->host, state->session->addr);
if (smtp_helo(state) == 0)
smtp_xfer(state);
if (state->history != 0
&& (state->error_mask & name_mask(VAR_NOTIFY_CLASSES,
mail_error_masks, var_notify_classes)))
smtp_chat_notify(state);
/* XXX smtp_xfer() may abort in the middle of DATA. */
smtp_session_free(state->session);
debug_peer_restore();
}
result = smtp_connect(state);
/*
* Clean up.
*/
vstring_free(why);
smtp_chat_reset(state);
result = state->status;
smtp_state_free(state);
return (result);

View File

@ -55,6 +55,7 @@ typedef struct SMTP_STATE {
off_t size_limit; /* server limit or unknown */
int space_left; /* output length control */
struct MIME_STATE *mime_state; /* mime state machine */
int final; /* last possibility to deliver */
} SMTP_STATE;
#define SMTP_FEATURE_ESMTP (1<<0)
@ -95,9 +96,7 @@ extern void smtp_session_free(SMTP_SESSION *);
/*
* smtp_connect.c
*/
extern SMTP_SESSION *smtp_connect(char *, VSTRING *);
extern SMTP_SESSION *smtp_connect_host(char *, unsigned, VSTRING *);
extern SMTP_SESSION *smtp_connect_domain(char *, unsigned, VSTRING *, int *);
extern int smtp_connect(SMTP_STATE *);
/*
* smtp_proto.c

View File

@ -6,29 +6,16 @@
/* SYNOPSIS
/* #include "smtp.h"
/*
/* SMTP_SESSION *smtp_connect(destination, why)
/* char *destination;
/* VSTRING *why;
/* AUXILIARY FUNCTIONS
/* SMTP_SESSION *smtp_connect_domain(name, port, why)
/* char *name;
/* unsigned port;
/* VSTRING *why;
/*
/* SMTP_SESSION *smtp_connect_host(name, port, why)
/* char *name;
/* unsigned port;
/* VSTRING *why;
/* int smtp_connect(state)
/* SMTP_STATE *state;
/* DESCRIPTION
/* This module implements SMTP connection management.
/* This module implements SMTP connection management and mail
/* delivery.
/*
/* smtp_connect() attempts to establish an SMTP session with a host
/* that represents the named domain.
/*
/* No session and an smtp_errno of SMTP_OK means that the local
/* machine is the best mail exchanger for the specified destination.
/* It is left up to the caller to decide if this is a mailer loop
/* or if this is a "do what I mean" request.
/* that represents the destination domain, or with an optional fallback
/* relay when the destination cannot be found, or when all the
/* destination servers are unavailable.
/*
/* The destination is either a host (or domain) name or a numeric
/* address. Symbolic or numeric service port information may be
@ -39,32 +26,8 @@
/* suppress mail exchanger lookups.
/*
/* Numerical address information should always be quoted with `[]'.
/*
/* smtp_connect_domain() attempts to make an SMTP connection to
/* the named host or domain and network port (network byte order).
/* \fIname\fR is used to look up mail exchanger information via
/* the Internet domain name system (DNS).
/* When no mail exchanger is listed for \fIname\fR, the request
/* is passed to smtp_connect_host().
/* Otherwise, mail exchanger hosts are tried in order of preference,
/* until one is found that responds. In order to avoid mailer loops,
/* the search for mail exchanger hosts stops when a host is found
/* that has the same preference as the sending machine.
/*
/* smtp_connect_host() makes an SMTP connection without looking up
/* mail exchanger information. The host can be specified as an
/* Internet network address or as a symbolic host name.
/* DIAGNOSTICS
/* All routines either return an SMTP_SESSION pointer, or
/* return a null pointer and set the \fIsmtp_errno\fR
/* global variable accordingly:
/* .IP SMTP_RETRY
/* The connection attempt failed, but should be retried later.
/* .IP SMTP_FAIL
/* The connection attempt failed.
/* .PP
/* In addition, a textual description of the error is made available
/* via the \fIwhy\fR argument.
/* The delivery status is the result value.
/* SEE ALSO
/* smtp_proto(3) SMTP client protocol
/* LICENSE
@ -118,6 +81,9 @@
#include <mail_params.h>
#include <own_inet_addr.h>
#include <deliver_pass.h>
#include <debug_peer.h>
#include <mail_error.h>
/* DNS library. */
@ -130,8 +96,8 @@
/* smtp_connect_addr - connect to explicit address */
static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
VSTRING *why)
static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
unsigned port)
{
char *myname = "smtp_connect_addr";
struct sockaddr_in sin;
@ -146,11 +112,8 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
/*
* Sanity checks.
*/
if (addr->data_len > sizeof(sin.sin_addr)) {
msg_warn("%s: skip address with length %d", myname, addr->data_len);
smtp_errno = SMTP_RETRY;
return (0);
}
if (addr->data_len > sizeof(sin.sin_addr))
msg_panic("%s: unexpected address length %d", myname, addr->data_len);
/*
* Initialize.
@ -212,9 +175,8 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
conn_stat = sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin));
}
if (conn_stat < 0) {
vstring_sprintf(why, "connect to %s[%s]: %m",
addr->name, inet_ntoa(sin.sin_addr));
smtp_errno = SMTP_RETRY;
smtp_site_fail(state, 450, "connect to %s[%s] port %u: %m",
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
close(sock);
return (0);
}
@ -223,9 +185,8 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
* Skip this host if it takes no action within some time limit.
*/
if (read_wait(sock, var_smtp_helo_tmout) < 0) {
vstring_sprintf(why, "connect to %s[%s]: read timeout",
addr->name, inet_ntoa(sin.sin_addr));
smtp_errno = SMTP_RETRY;
smtp_site_fail(state, 450, "connect to %s[%s] port %u: read timeout",
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
close(sock);
return (0);
}
@ -235,9 +196,9 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
*/
stream = vstream_fdopen(sock, O_RDWR);
if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial SMTP greeting",
addr->name, inet_ntoa(sin.sin_addr));
smtp_errno = SMTP_RETRY;
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
"server dropped connection without sending the initial SMTP greeting",
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
vstream_fclose(stream);
return (0);
}
@ -247,9 +208,9 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
* Skip this host if it sends a 4xx greeting.
*/
if (ch == '4' && var_smtp_skip_4xx_greeting) {
vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
addr->name, inet_ntoa(sin.sin_addr));
smtp_errno = SMTP_RETRY;
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
"server refused mail service",
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
vstream_fclose(stream);
return (0);
}
@ -258,69 +219,15 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
* Skip this host if it sends a 5xx greeting.
*/
if (ch == '5' && var_smtp_skip_5xx_greeting) {
vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
addr->name, inet_ntoa(sin.sin_addr));
smtp_errno = SMTP_RETRY;
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
"server refused mail service",
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
vstream_fclose(stream);
return (0);
}
return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
}
/* smtp_connect_host - direct connection to host */
SMTP_SESSION *smtp_connect_host(char *host, unsigned port, VSTRING *why)
{
SMTP_SESSION *session = 0;
DNS_RR *addr_list;
DNS_RR *addr;
/*
* Try each address in the specified order until we find one that works.
* The addresses belong to the same A record, so we have no information
* on what address is "best".
*/
addr_list = smtp_host_addr(host, why);
for (addr = addr_list; addr; addr = addr->next) {
if ((session = smtp_connect_addr(addr, port, why)) != 0) {
session->best = 1;
break;
}
msg_info("%s (port %d)", vstring_str(why), ntohs(port));
}
dns_rr_free(addr_list);
return (session);
}
/* smtp_connect_domain - connect to smtp server for domain */
SMTP_SESSION *smtp_connect_domain(char *name, unsigned port, VSTRING *why,
int *found_myself)
{
SMTP_SESSION *session = 0;
DNS_RR *addr_list;
DNS_RR *addr;
/*
* Try each mail exchanger in order of preference until we find one that
* responds. Once we find a server that responds we never try
* alternative mail exchangers. The benefit of this is that we will use
* backup hosts only when we are unable to reach the primary MX host. If
* the primary MX host is reachable but does not want to receive our
* mail, there is no point in trying the backup hosts.
*/
addr_list = smtp_domain_addr(name, why, found_myself);
for (addr = addr_list; addr; addr = addr->next) {
if ((session = smtp_connect_addr(addr, port, why)) != 0) {
session->best = (addr->pref == addr_list->pref);
break;
}
msg_info("%s (port %d)", vstring_str(why), ntohs(port));
}
dns_rr_free(addr_list);
return (session);
}
/* smtp_parse_destination - parse destination */
static char *smtp_parse_destination(char *destination, char *def_service,
@ -358,81 +265,136 @@ static char *smtp_parse_destination(char *destination, char *def_service,
/* smtp_connect - establish SMTP connection */
SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
int smtp_connect(SMTP_STATE *state)
{
SMTP_SESSION *session = 0;
char *dest_buf = 0;
VSTRING *why = vstring_alloc(100);
DELIVER_REQUEST *request = state->request;
char *dest_buf;
char *host;
unsigned port;
char *def_service = "smtp"; /* XXX configurable? */
ARGV *sites;
char *dest;
char **cpp;
int found_myself = 0;
int found_myself;
DNS_RR *addr_list;
DNS_RR *addr;
/*
* First try to deliver to the indicated destination, then try to deliver
* to the optional fall-back relays.
* to the optional fall-back relays. Sanity check in case we allow the
* primary destination to be a list (we did for some time in the past).
*
* After a soft error, log recipient deferrals only when there are no
* further possibilities to deliver.
*/
sites = argv_alloc(1);
argv_add(sites, destination, (char *) 0);
argv_add(sites, request->nexthop, (char *) 0);
if (sites->argc == 0)
msg_panic("null destination: \"%s\"", request->nexthop);
argv_split_append(sites, var_fallback_relay, ", \t\r\n");
for (cpp = sites->argv; (dest = *cpp) != 0; cpp++) {
found_myself = 0;
state->final = (cpp[1] == 0);
/*
* Parse the destination. Default is to use the SMTP port.
* Parse the destination. Default is to use the SMTP port. Look up
* the address instead of the mail exchanger when a quoted host is
* specified, or when DNS lookups are disabled.
*/
dest_buf = smtp_parse_destination(dest, def_service, &host, &port);
/*
* Connect to an SMTP server. Skip mail exchanger lookups when a
* quoted host is specified, or when DNS lookups are disabled.
*/
if (msg_verbose)
msg_info("connecting to %s port %d", host, ntohs(port));
msg_info("connecting to \"%s\" port \"%d\"", host, ntohs(port));
if (var_disable_dns || *dest == '[') {
session = smtp_connect_host(host, port, why);
addr_list = smtp_host_addr(host, why);
} else {
session = smtp_connect_domain(host, port, why, &found_myself);
addr_list = smtp_domain_addr(host, why, &found_myself);
}
myfree(dest_buf);
/*
* Done if we have a session, or if we have no session and this host
* is the best MX relay for the destination. Agreed, an errno of OK
* after failure is a weird way to reporting progress.
* Handle host lookup problems. XXX It would be nice if the address
* lookup routines could do their own smtp_site_fail() calls instead
* of having us make sense of things from a distance. The
* complication is that an unrecoverable host lookup error may still
* be followed by an attempt to deliver via a fallback relay.
*/
if (session != 0 || smtp_errno == SMTP_OK || found_myself)
break;
}
if (addr_list == 0) {
/*
* Sanity check. The destination must not be empty or all blanks.
*/
if (session == 0 && dest_buf == 0)
msg_panic("null destination: \"%s\"", destination);
/*
* Mail loops back to myself. An smtp_errno of OK means that we
* should hand off the mail to a local transport. This hand-off
* should not happen with fallback relays.
*/
if (smtp_errno == SMTP_OK && cpp == sites->argv) {
state->status =
deliver_pass_all(MAIL_CLASS_PRIVATE, var_bestmx_transp,
request);
break;
}
if (found_myself) {
smtp_site_fail(state, 450,
"%s: %s", request->queue_id, vstring_str(why));
break;
}
/*
* Pay attention to what could be configuration problems, and pretend
* that these are recoverable rather than bouncing the mail.
*/
if (session == 0 && smtp_errno == SMTP_FAIL) {
if (strcmp(destination, var_relayhost) == 0) {
msg_warn("%s configuration problem: %s",
VAR_RELAYHOST, var_relayhost);
smtp_errno = SMTP_RETRY;
/*
* Pay attention to what could be configuration problems, and
* pretend that these are recoverable rather than bouncing the
* mail.
*/
if (strcmp(request->nexthop, var_relayhost) == 0) {
msg_warn("%s configuration problem: %s",
VAR_RELAYHOST, var_relayhost);
smtp_site_fail(state, 450,
"%s: %s", request->queue_id, vstring_str(why));
continue;
}
if (cpp > sites->argv && sites->argc > 1) {
msg_warn("%s problem: %s",
VAR_FALLBACK_RELAY, var_fallback_relay);
smtp_site_fail(state, 450,
"%s: %s", request->queue_id, vstring_str(why));
continue;
}
smtp_site_fail(state, cpp[1] || smtp_errno == SMTP_RETRY ? 450 : 550,
"%s: %s", request->queue_id, vstring_str(why));
}
if (cpp > sites->argv && sites->argc > 1) {
msg_warn("%s problem: %s",
VAR_FALLBACK_RELAY, var_fallback_relay);
smtp_errno = SMTP_RETRY;
/*
* Connect to an SMTP server. XXX Limit the number of addresses that
* we're willing to try for a non-fallback destination.
*
* After a soft error, log deferrals and update delivery status values
* only when there are no further attempts.
*/
for (addr = addr_list; addr; addr = addr->next) {
if ((state->session = smtp_connect_addr(state, addr, port)) != 0) {
state->status = 0;
state->session->best = (addr->pref == addr_list->pref);
debug_peer_check(state->session->host, state->session->addr);
state->final = (cpp[1] == 0 && addr->next == 0);
if (smtp_helo(state) == 0)
smtp_xfer(state);
if (state->history != 0
&& (state->error_mask & name_mask(VAR_NOTIFY_CLASSES,
mail_error_masks, var_notify_classes)))
smtp_chat_notify(state);
/* XXX smtp_xfer() may abort in the middle of DATA. */
smtp_session_free(state->session);
debug_peer_restore();
if (state->status == 0)
break;
}
}
dns_rr_free(addr_list);
}
/*
* Cleanup.
*/
vstring_free(why);
argv_free(sites);
return (session);
return (state->status);
}

View File

@ -72,6 +72,7 @@ SMTP_STATE *smtp_state_alloc(void)
state->size_limit = 0;
state->space_left = 0;
state->mime_state = 0;
state->final = 0;
return (state);
}

View File

@ -43,6 +43,10 @@
/* what appear to be configuration errors - very likely, they
/* would suffer the same problem and just cause more trouble.
/*
/* In case of a soft error, action depends on whether there are
/* more possibilities to deliver (log one generic record) or whether
/* the error happens with the last possibility (log each recipient).
/*
/* smtp_site_fail() handles the case where the program fails to
/* complete the initial SMTP handshake: the server is not reachable,
/* is not running, does not want talk to us, or we talk to ourselves.
@ -157,27 +161,38 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
vstring_vsprintf(why, format, ap);
va_end(ap);
/*
* Don't log deferred recipients yet when there are still untried
* possibilities to deliver. Just log why we're abandoning this host.
*/
if (soft_error && state->final == 0) {
msg_info("%s: %s", request->queue_id, vstring_str(why));
state->status |= -1;
}
/*
* If this is a soft error, postpone further deliveries to this domain.
* Otherwise, generate a bounce record for each recipient.
*/
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset == 0)
continue;
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session ? session->namaddr : "none",
request->arrival_time, "%s", vstring_str(why));
if (status == 0) {
deliver_completed(state->src, rcpt->offset);
rcpt->offset = 0;
else {
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset == 0)
continue;
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session ? session->namaddr : "none",
request->arrival_time, "%s", vstring_str(why));
if (status == 0) {
deliver_completed(state->src, rcpt->offset);
rcpt->offset = 0;
}
state->status |= status;
}
state->status |= status;
if (soft_error && request->hop_status == 0)
request->hop_status = mystrdup(vstring_str(why));
}
if (soft_error && request->hop_status == 0)
request->hop_status = mystrdup(vstring_str(why));
/*
* Cleanup.
@ -195,6 +210,7 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
RECIPIENT *rcpt;
int status;
int nrcpt;
int soft_error = SMTP_SOFT(code);
va_list ap;
VSTRING *why = vstring_alloc(100);
@ -205,24 +221,35 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
vstring_vsprintf(why, format, ap);
va_end(ap);
/*
* Don't log deferred recipients yet when there are still untried
* possibilities to deliver. Just log why we're abandoning this host.
*/
if (soft_error && state->final == 0) {
msg_info("%s: %s", request->queue_id, vstring_str(why));
state->status |= -1;
}
/*
* If this is a soft error, postpone delivery of this message. Otherwise,
* generate a bounce record for each recipient.
*/
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset == 0)
continue;
status = (SMTP_SOFT(code) ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time,
"%s", vstring_str(why));
if (status == 0) {
deliver_completed(state->src, rcpt->offset);
rcpt->offset = 0;
else {
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset == 0)
continue;
status = (soft_error ? defer_append : bounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time,
"%s", vstring_str(why));
if (status == 0) {
deliver_completed(state->src, rcpt->offset);
rcpt->offset = 0;
}
state->status |= status;
}
state->status |= status;
}
smtp_check_code(state, code);
@ -241,21 +268,39 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
DELIVER_REQUEST *request = state->request;
SMTP_SESSION *session = state->session;
int status;
int soft_error = SMTP_SOFT(code);
va_list ap;
/*
* Don't log deferred recipients yet when there are still untried
* possibilities to deliver.
*/
if (soft_error && state->final == 0) {
VSTRING *buf = vstring_alloc(10);
va_start(ap, format);
vstring_vsprintf(buf, format, ap);
va_end(ap);
msg_info("%s: %s", request->queue_id, vstring_str(buf));
vstring_free(buf);
status = -1;
}
/*
* If this is a soft error, postpone delivery to this recipient.
* Otherwise, generate a bounce record for this recipient.
*/
va_start(ap, format);
status = (SMTP_SOFT(code) ? vdefer_append : vbounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time, format, ap);
va_end(ap);
if (status == 0) {
deliver_completed(state->src, rcpt->offset);
rcpt->offset = 0;
else {
va_start(ap, format);
status = (soft_error ? vdefer_append : vbounce_append)
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
rcpt->orig_addr, rcpt->address, rcpt->offset,
session->namaddr, request->arrival_time, format, ap);
va_end(ap);
if (status == 0) {
deliver_completed(state->src, rcpt->offset);
rcpt->offset = 0;
}
}
smtp_check_code(state, code);
state->status |= status;
@ -287,20 +332,31 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
break;
}
/*
* Don't log deferred recipients yet when there are still untried
* possibilities to deliver. Just log why we're abandoning this host.
*/
if (state->final == 0) {
msg_info("%s: %s", request->queue_id, vstring_str(why));
state->status |= -1;
}
/*
* At this point, the status of individual recipients remains unresolved.
* All we know is that we should stay away from this host for a while.
*/
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset == 0)
continue;
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id,
rcpt->orig_addr, rcpt->address,
rcpt->offset, session->namaddr,
request->arrival_time,
"%s", vstring_str(why));
else {
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
rcpt = request->rcpt_list.info + nrcpt;
if (rcpt->offset == 0)
continue;
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
request->queue_id,
rcpt->orig_addr, rcpt->address,
rcpt->offset, session->namaddr,
request->arrival_time,
"%s", vstring_str(why));
}
}
/*

View File

@ -347,6 +347,8 @@
#include "smtpd_sasl_glue.h"
#include "smtpd_check.h"
#define RESTRICTION_SEPARATORS ", \t\r\n"
/*
* Eject seat in case of parsing problems.
*/
@ -596,7 +598,7 @@ static ARGV *smtpd_check_parse(const char *checks)
* encounter. Dictionaries must be opened before entering the chroot
* jail.
*/
while ((name = mystrtok(&bp, " \t\r\n,")) != 0) {
while ((name = mystrtok(&bp, RESTRICTION_SEPARATORS)) != 0) {
argv_add(argv, name, (char *) 0);
if (last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0)
policy_client_register(name);
@ -767,7 +769,7 @@ void smtpd_check_init(void)
smtpd_rest_classes = htable_create(1);
if (*var_rest_classes) {
cp = saved_classes = mystrdup(var_rest_classes);
while ((name = mystrtok(&cp, " \t\r\n,")) != 0) {
while ((name = mystrtok(&cp, RESTRICTION_SEPARATORS)) != 0) {
if ((value = mail_conf_lookup_eval(name)) == 0 || *value == 0)
msg_fatal("restriction class `%s' needs a definition", name);
htable_enter(smtpd_rest_classes, name,
@ -2001,7 +2003,7 @@ static int check_table_result(SMTPD_STATE *state, const char *table,
*/
#define ADDROF(x) ((char *) &(x))
restrictions = argv_split(value, " \t\r\n,");
restrictions = argv_split(value, RESTRICTION_SEPARATORS);
memcpy(ADDROF(savebuf), ADDROF(smtpd_check_buf), sizeof(savebuf));
status = setjmp(smtpd_check_buf);
if (status != 0) {
@ -2837,7 +2839,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
"use \"%s domain-name\" instead",
REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
}
while ((rbl_domain = mystrtok(&bp, " \t\r\n,")) != 0) {
while ((rbl_domain = mystrtok(&bp, RESTRICTION_SEPARATORS)) != 0) {
result = reject_rbl_addr(state, rbl_domain, state->addr,
SMTPD_NAME_CLIENT);
if (result != SMTPD_CHECK_DUNNO)
@ -2875,7 +2877,7 @@ static int reject_auth_sender_login_mismatch(SMTPD_STATE *state, const char *sen
if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps,
STR(reply->recipient), (char **) 0)) != 0) {
cp = saved_owners = mystrdup(owners);
while ((name = mystrtok(&cp, ", \t\r\n")) != 0) {
while ((name = mystrtok(&cp, RESTRICTION_SEPARATORS)) != 0) {
if (strcasecmp(state->sasl_username, name) == 0) {
found = 1;
break;
@ -4179,7 +4181,7 @@ static void rest_class(char *class)
if (smtpd_rest_classes == 0)
smtpd_rest_classes = htable_create(1);
if ((name = mystrtok(&cp, " \t\r\n,")) == 0)
if ((name = mystrtok(&cp, RESTRICTION_SEPARATORS)) == 0)
msg_panic("rest_class: null class name");
if ((entry = htable_locate(smtpd_rest_classes, name)) != 0)
argv_free((ARGV *) entry->value);