mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 13:48:06 +00:00
postfix-2.0.16-20031216
This commit is contained in:
committed by
Viktor Dukhovni
parent
7aef2f8c02
commit
49328174e4
@@ -8818,13 +8818,14 @@ Apologies for any names omitted.
|
|||||||
of a sender address. Code by Liviu Daia. Files:
|
of a sender address. Code by Liviu Daia. Files:
|
||||||
smtpd/smtpd_check.c and documentation.
|
smtpd/smtpd_check.c and documentation.
|
||||||
|
|
||||||
The reject_sender_login_mismatch feature is now implemented
|
reject_sender_login_mismatch is now implemented by elementary
|
||||||
by elementary features reject_unauth_sender_login_mismatch
|
features reject_unauthenticated_sender_login_mismatch
|
||||||
(reject if the client is not SASL logged in but the sender
|
(reject if the client is not SASL logged in but the sender
|
||||||
address has an owner in smtpd_sender_login_maps) and
|
address has an owner in smtpd_sender_login_maps) and
|
||||||
reject_auth_sender_login_mismatch (reject if the client is
|
reject_authenticated_sender_login_mismatch (reject if the
|
||||||
SASL logged in but does not own the sender address). Code
|
client is SASL logged in but does not own the sender
|
||||||
by Liviu Daia. Files: smtpd/smtpd_check.c and documentation.
|
address). Code by Liviu Daia. Files: smtpd/smtpd_check.c
|
||||||
|
and documentation.
|
||||||
|
|
||||||
20031207
|
20031207
|
||||||
|
|
||||||
@@ -8864,6 +8865,16 @@ Apologies for any names omitted.
|
|||||||
settings before and after DNS lookup, to avoid surprises
|
settings before and after DNS lookup, to avoid surprises
|
||||||
in third-party code. File: dns/dns_lookup.c.
|
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:
|
Open problems:
|
||||||
|
|
||||||
High: when virtual aliasing is turned off after content
|
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
|
Low: postmap/postalias should not try to open a bogus file
|
||||||
when given an unsupported dictionary type.
|
when given an unsupported dictionary type.
|
||||||
|
|
||||||
Med: do not postpone rejected "MAIL FROM" size information,
|
Med: find a way to log the sender address when MAIL FROM
|
||||||
and find a way to log the sender address in the rejected
|
is rejected due to lack of disk space.
|
||||||
command.
|
|
||||||
|
|
||||||
Low: after successful delivery, per-queue window += 1/window,
|
Low: after successful delivery, per-queue window += 1/window,
|
||||||
after failure, queue window -= 1 (Victor).
|
after failure, queue window -= 1 (Victor).
|
||||||
@@ -8929,8 +8939,8 @@ Open problems:
|
|||||||
|
|
||||||
Low: postconf -e edits parameters that postconf won't list.
|
Low: postconf -e edits parameters that postconf won't list.
|
||||||
|
|
||||||
Low: with quoted-printable, perhaps use =46rom instead of
|
Low: while convering 8bit text to quoted-printable, perhaps
|
||||||
>From.
|
use =46rom instead of >From.
|
||||||
|
|
||||||
virtual_mailbox_path expression like forward_path, so that
|
virtual_mailbox_path expression like forward_path, so that
|
||||||
people can specify prefix and suffix.
|
people can specify prefix and suffix.
|
||||||
|
@@ -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.
|
can be used to transmit client or message attributes incrementally.
|
||||||
It is not implemented by passing additional parameters via the MAIL
|
It is not implemented by passing additional parameters via the MAIL
|
||||||
FROM command, because doing so would require extending 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
|
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 )
|
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
|
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
|
of a mail delivery transaction (i.e. between MAIL and DOT). The
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<html> <head> </head> <body> <pre>
|
<html> <body> <pre>
|
||||||
SHOWQ(8) SHOWQ(8)
|
SHOWQ(8) SHOWQ(8)
|
||||||
|
|
||||||
<b>NAME</b>
|
<b>NAME</b>
|
||||||
|
@@ -141,7 +141,7 @@ static int dns_query(const char *name, int type, int flags,
|
|||||||
{
|
{
|
||||||
HEADER *reply_header;
|
HEADER *reply_header;
|
||||||
int len;
|
int len;
|
||||||
int saved_options = _res.options;
|
unsigned long saved_options = _res.options;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the name service.
|
* Initialize the name service.
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
* Patches change the patchlevel and the release date. Snapshots change the
|
* Patches change the patchlevel and the release date. Snapshots change the
|
||||||
* release date only, unless they include the same bugfix as a patch release.
|
* 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 VAR_MAIL_VERSION "mail_version"
|
||||||
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||||
|
@@ -94,7 +94,7 @@ int var_dup_filter_limit;
|
|||||||
char *var_empty_addr;
|
char *var_empty_addr;
|
||||||
|
|
||||||
#define STRING_FORMAT "%-10s %8s %-20s %s\n"
|
#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"
|
#define DROP_FORMAT "%-10s%c%8ld %20.20s (maildrop queue, sender UID %u)\n"
|
||||||
|
|
||||||
static void showq_reasons(VSTREAM *, BOUNCE_LOG *, HTABLE *);
|
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;
|
start = var_empty_addr;
|
||||||
quote_822_local(printable_quoted_addr, start);
|
quote_822_local(printable_quoted_addr, start);
|
||||||
printable(STR(printable_quoted_addr), '?');
|
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 ?
|
msg_size > 0 ? msg_size : size, arrival_time > 0 ?
|
||||||
asctime(localtime(&arrival_time)) :
|
asctime(localtime(&arrival_time)) :
|
||||||
asctime(localtime(&mtime)),
|
asctime(localtime(&mtime)),
|
||||||
|
@@ -265,8 +265,6 @@
|
|||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <mail_conf.h>
|
#include <mail_conf.h>
|
||||||
#include <debug_peer.h>
|
#include <debug_peer.h>
|
||||||
#include <mail_error.h>
|
|
||||||
#include <deliver_pass.h>
|
|
||||||
|
|
||||||
/* Single server skeleton. */
|
/* Single server skeleton. */
|
||||||
|
|
||||||
@@ -327,7 +325,6 @@ int smtp_host_lookup_mask;
|
|||||||
|
|
||||||
static int deliver_message(DELIVER_REQUEST *request)
|
static int deliver_message(DELIVER_REQUEST *request)
|
||||||
{
|
{
|
||||||
VSTRING *why;
|
|
||||||
SMTP_STATE *state;
|
SMTP_STATE *state;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
@@ -349,7 +346,6 @@ static int deliver_message(DELIVER_REQUEST *request)
|
|||||||
* we can produce understandable diagnostics when something goes wrong
|
* we can produce understandable diagnostics when something goes wrong
|
||||||
* many levels below. The alternative would be to make everything global.
|
* many levels below. The alternative would be to make everything global.
|
||||||
*/
|
*/
|
||||||
why = vstring_alloc(100);
|
|
||||||
state = smtp_state_alloc();
|
state = smtp_state_alloc();
|
||||||
state->request = request;
|
state->request = request;
|
||||||
state->src = request->fp;
|
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
|
* Optionally deliver mail locally when this machine is the best mail
|
||||||
* exchanger.
|
* exchanger.
|
||||||
*/
|
*/
|
||||||
if ((state->session = smtp_connect(request->nexthop, why)) == 0) {
|
result = smtp_connect(state);
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean up.
|
* Clean up.
|
||||||
*/
|
*/
|
||||||
vstring_free(why);
|
|
||||||
smtp_chat_reset(state);
|
smtp_chat_reset(state);
|
||||||
result = state->status;
|
|
||||||
smtp_state_free(state);
|
smtp_state_free(state);
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
|
@@ -55,6 +55,7 @@ typedef struct SMTP_STATE {
|
|||||||
off_t size_limit; /* server limit or unknown */
|
off_t size_limit; /* server limit or unknown */
|
||||||
int space_left; /* output length control */
|
int space_left; /* output length control */
|
||||||
struct MIME_STATE *mime_state; /* mime state machine */
|
struct MIME_STATE *mime_state; /* mime state machine */
|
||||||
|
int final; /* last possibility to deliver */
|
||||||
} SMTP_STATE;
|
} SMTP_STATE;
|
||||||
|
|
||||||
#define SMTP_FEATURE_ESMTP (1<<0)
|
#define SMTP_FEATURE_ESMTP (1<<0)
|
||||||
@@ -95,9 +96,7 @@ extern void smtp_session_free(SMTP_SESSION *);
|
|||||||
/*
|
/*
|
||||||
* smtp_connect.c
|
* smtp_connect.c
|
||||||
*/
|
*/
|
||||||
extern SMTP_SESSION *smtp_connect(char *, VSTRING *);
|
extern int smtp_connect(SMTP_STATE *);
|
||||||
extern SMTP_SESSION *smtp_connect_host(char *, unsigned, VSTRING *);
|
|
||||||
extern SMTP_SESSION *smtp_connect_domain(char *, unsigned, VSTRING *, int *);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* smtp_proto.c
|
* smtp_proto.c
|
||||||
|
@@ -6,29 +6,16 @@
|
|||||||
/* SYNOPSIS
|
/* SYNOPSIS
|
||||||
/* #include "smtp.h"
|
/* #include "smtp.h"
|
||||||
/*
|
/*
|
||||||
/* SMTP_SESSION *smtp_connect(destination, why)
|
/* int smtp_connect(state)
|
||||||
/* char *destination;
|
/* SMTP_STATE *state;
|
||||||
/* 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;
|
|
||||||
/* DESCRIPTION
|
/* 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
|
/* smtp_connect() attempts to establish an SMTP session with a host
|
||||||
/* that represents the named domain.
|
/* that represents the destination domain, or with an optional fallback
|
||||||
/*
|
/* relay when the destination cannot be found, or when all the
|
||||||
/* No session and an smtp_errno of SMTP_OK means that the local
|
/* destination servers are unavailable.
|
||||||
/* 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.
|
|
||||||
/*
|
/*
|
||||||
/* The destination is either a host (or domain) name or a numeric
|
/* The destination is either a host (or domain) name or a numeric
|
||||||
/* address. Symbolic or numeric service port information may be
|
/* address. Symbolic or numeric service port information may be
|
||||||
@@ -39,32 +26,8 @@
|
|||||||
/* suppress mail exchanger lookups.
|
/* suppress mail exchanger lookups.
|
||||||
/*
|
/*
|
||||||
/* Numerical address information should always be quoted with `[]'.
|
/* 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
|
/* DIAGNOSTICS
|
||||||
/* All routines either return an SMTP_SESSION pointer, or
|
/* The delivery status is the result value.
|
||||||
/* 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.
|
|
||||||
/* SEE ALSO
|
/* SEE ALSO
|
||||||
/* smtp_proto(3) SMTP client protocol
|
/* smtp_proto(3) SMTP client protocol
|
||||||
/* LICENSE
|
/* LICENSE
|
||||||
@@ -118,6 +81,9 @@
|
|||||||
|
|
||||||
#include <mail_params.h>
|
#include <mail_params.h>
|
||||||
#include <own_inet_addr.h>
|
#include <own_inet_addr.h>
|
||||||
|
#include <deliver_pass.h>
|
||||||
|
#include <debug_peer.h>
|
||||||
|
#include <mail_error.h>
|
||||||
|
|
||||||
/* DNS library. */
|
/* DNS library. */
|
||||||
|
|
||||||
@@ -130,8 +96,8 @@
|
|||||||
|
|
||||||
/* smtp_connect_addr - connect to explicit address */
|
/* smtp_connect_addr - connect to explicit address */
|
||||||
|
|
||||||
static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
|
static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
|
||||||
VSTRING *why)
|
unsigned port)
|
||||||
{
|
{
|
||||||
char *myname = "smtp_connect_addr";
|
char *myname = "smtp_connect_addr";
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
@@ -146,11 +112,8 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
|
|||||||
/*
|
/*
|
||||||
* Sanity checks.
|
* Sanity checks.
|
||||||
*/
|
*/
|
||||||
if (addr->data_len > sizeof(sin.sin_addr)) {
|
if (addr->data_len > sizeof(sin.sin_addr))
|
||||||
msg_warn("%s: skip address with length %d", myname, addr->data_len);
|
msg_panic("%s: unexpected address length %d", myname, addr->data_len);
|
||||||
smtp_errno = SMTP_RETRY;
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize.
|
* 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));
|
conn_stat = sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin));
|
||||||
}
|
}
|
||||||
if (conn_stat < 0) {
|
if (conn_stat < 0) {
|
||||||
vstring_sprintf(why, "connect to %s[%s]: %m",
|
smtp_site_fail(state, 450, "connect to %s[%s] port %u: %m",
|
||||||
addr->name, inet_ntoa(sin.sin_addr));
|
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
|
||||||
smtp_errno = SMTP_RETRY;
|
|
||||||
close(sock);
|
close(sock);
|
||||||
return (0);
|
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.
|
* Skip this host if it takes no action within some time limit.
|
||||||
*/
|
*/
|
||||||
if (read_wait(sock, var_smtp_helo_tmout) < 0) {
|
if (read_wait(sock, var_smtp_helo_tmout) < 0) {
|
||||||
vstring_sprintf(why, "connect to %s[%s]: read timeout",
|
smtp_site_fail(state, 450, "connect to %s[%s] port %u: read timeout",
|
||||||
addr->name, inet_ntoa(sin.sin_addr));
|
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
|
||||||
smtp_errno = SMTP_RETRY;
|
|
||||||
close(sock);
|
close(sock);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
@@ -235,9 +196,9 @@ static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
|
|||||||
*/
|
*/
|
||||||
stream = vstream_fdopen(sock, O_RDWR);
|
stream = vstream_fdopen(sock, O_RDWR);
|
||||||
if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
|
if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
|
||||||
vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial SMTP greeting",
|
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
|
||||||
addr->name, inet_ntoa(sin.sin_addr));
|
"server dropped connection without sending the initial SMTP greeting",
|
||||||
smtp_errno = SMTP_RETRY;
|
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
|
||||||
vstream_fclose(stream);
|
vstream_fclose(stream);
|
||||||
return (0);
|
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.
|
* Skip this host if it sends a 4xx greeting.
|
||||||
*/
|
*/
|
||||||
if (ch == '4' && var_smtp_skip_4xx_greeting) {
|
if (ch == '4' && var_smtp_skip_4xx_greeting) {
|
||||||
vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
|
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
|
||||||
addr->name, inet_ntoa(sin.sin_addr));
|
"server refused mail service",
|
||||||
smtp_errno = SMTP_RETRY;
|
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
|
||||||
vstream_fclose(stream);
|
vstream_fclose(stream);
|
||||||
return (0);
|
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.
|
* Skip this host if it sends a 5xx greeting.
|
||||||
*/
|
*/
|
||||||
if (ch == '5' && var_smtp_skip_5xx_greeting) {
|
if (ch == '5' && var_smtp_skip_5xx_greeting) {
|
||||||
vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
|
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
|
||||||
addr->name, inet_ntoa(sin.sin_addr));
|
"server refused mail service",
|
||||||
smtp_errno = SMTP_RETRY;
|
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
|
||||||
vstream_fclose(stream);
|
vstream_fclose(stream);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
|
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 */
|
/* smtp_parse_destination - parse destination */
|
||||||
|
|
||||||
static char *smtp_parse_destination(char *destination, char *def_service,
|
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_connect - establish SMTP connection */
|
||||||
|
|
||||||
SMTP_SESSION *smtp_connect(char *destination, VSTRING *why)
|
int smtp_connect(SMTP_STATE *state)
|
||||||
{
|
{
|
||||||
SMTP_SESSION *session = 0;
|
VSTRING *why = vstring_alloc(100);
|
||||||
char *dest_buf = 0;
|
DELIVER_REQUEST *request = state->request;
|
||||||
|
char *dest_buf;
|
||||||
char *host;
|
char *host;
|
||||||
unsigned port;
|
unsigned port;
|
||||||
char *def_service = "smtp"; /* XXX configurable? */
|
char *def_service = "smtp"; /* XXX configurable? */
|
||||||
ARGV *sites;
|
ARGV *sites;
|
||||||
char *dest;
|
char *dest;
|
||||||
char **cpp;
|
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
|
* 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);
|
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");
|
argv_split_append(sites, var_fallback_relay, ", \t\r\n");
|
||||||
|
|
||||||
for (cpp = sites->argv; (dest = *cpp) != 0; cpp++) {
|
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);
|
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)
|
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 == '[') {
|
if (var_disable_dns || *dest == '[') {
|
||||||
session = smtp_connect_host(host, port, why);
|
addr_list = smtp_host_addr(host, why);
|
||||||
} else {
|
} else {
|
||||||
session = smtp_connect_domain(host, port, why, &found_myself);
|
addr_list = smtp_domain_addr(host, why, &found_myself);
|
||||||
}
|
}
|
||||||
myfree(dest_buf);
|
myfree(dest_buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Done if we have a session, or if we have no session and this host
|
* Handle host lookup problems. XXX It would be nice if the address
|
||||||
* is the best MX relay for the destination. Agreed, an errno of OK
|
* lookup routines could do their own smtp_site_fail() calls instead
|
||||||
* after failure is a weird way to reporting progress.
|
* 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)
|
if (addr_list == 0) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sanity check. The destination must not be empty or all blanks.
|
* 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
|
||||||
if (session == 0 && dest_buf == 0)
|
* should not happen with fallback relays.
|
||||||
msg_panic("null destination: \"%s\"", destination);
|
*/
|
||||||
|
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
|
* Pay attention to what could be configuration problems, and
|
||||||
* that these are recoverable rather than bouncing the mail.
|
* pretend that these are recoverable rather than bouncing the
|
||||||
*/
|
* mail.
|
||||||
if (session == 0 && smtp_errno == SMTP_FAIL) {
|
*/
|
||||||
if (strcmp(destination, var_relayhost) == 0) {
|
if (strcmp(request->nexthop, var_relayhost) == 0) {
|
||||||
msg_warn("%s configuration problem: %s",
|
msg_warn("%s configuration problem: %s",
|
||||||
VAR_RELAYHOST, var_relayhost);
|
VAR_RELAYHOST, var_relayhost);
|
||||||
smtp_errno = SMTP_RETRY;
|
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);
|
* Connect to an SMTP server. XXX Limit the number of addresses that
|
||||||
smtp_errno = SMTP_RETRY;
|
* 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.
|
* Cleanup.
|
||||||
*/
|
*/
|
||||||
|
vstring_free(why);
|
||||||
argv_free(sites);
|
argv_free(sites);
|
||||||
return (session);
|
return (state->status);
|
||||||
}
|
}
|
||||||
|
@@ -72,6 +72,7 @@ SMTP_STATE *smtp_state_alloc(void)
|
|||||||
state->size_limit = 0;
|
state->size_limit = 0;
|
||||||
state->space_left = 0;
|
state->space_left = 0;
|
||||||
state->mime_state = 0;
|
state->mime_state = 0;
|
||||||
|
state->final = 0;
|
||||||
return (state);
|
return (state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -43,6 +43,10 @@
|
|||||||
/* what appear to be configuration errors - very likely, they
|
/* what appear to be configuration errors - very likely, they
|
||||||
/* would suffer the same problem and just cause more trouble.
|
/* 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
|
/* smtp_site_fail() handles the case where the program fails to
|
||||||
/* complete the initial SMTP handshake: the server is not reachable,
|
/* complete the initial SMTP handshake: the server is not reachable,
|
||||||
/* is not running, does not want talk to us, or we talk to ourselves.
|
/* 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);
|
vstring_vsprintf(why, format, ap);
|
||||||
va_end(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.
|
* If this is a soft error, postpone further deliveries to this domain.
|
||||||
* Otherwise, generate a bounce record for each recipient.
|
* Otherwise, generate a bounce record for each recipient.
|
||||||
*/
|
*/
|
||||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
else {
|
||||||
rcpt = request->rcpt_list.info + nrcpt;
|
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||||
if (rcpt->offset == 0)
|
rcpt = request->rcpt_list.info + nrcpt;
|
||||||
continue;
|
if (rcpt->offset == 0)
|
||||||
status = (soft_error ? defer_append : bounce_append)
|
continue;
|
||||||
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
status = (soft_error ? defer_append : bounce_append)
|
||||||
rcpt->orig_addr, rcpt->address, rcpt->offset,
|
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
||||||
session ? session->namaddr : "none",
|
rcpt->orig_addr, rcpt->address, rcpt->offset,
|
||||||
request->arrival_time, "%s", vstring_str(why));
|
session ? session->namaddr : "none",
|
||||||
if (status == 0) {
|
request->arrival_time, "%s", vstring_str(why));
|
||||||
deliver_completed(state->src, rcpt->offset);
|
if (status == 0) {
|
||||||
rcpt->offset = 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.
|
* Cleanup.
|
||||||
@@ -195,6 +210,7 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
|
|||||||
RECIPIENT *rcpt;
|
RECIPIENT *rcpt;
|
||||||
int status;
|
int status;
|
||||||
int nrcpt;
|
int nrcpt;
|
||||||
|
int soft_error = SMTP_SOFT(code);
|
||||||
va_list ap;
|
va_list ap;
|
||||||
VSTRING *why = vstring_alloc(100);
|
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);
|
vstring_vsprintf(why, format, ap);
|
||||||
va_end(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,
|
* If this is a soft error, postpone delivery of this message. Otherwise,
|
||||||
* generate a bounce record for each recipient.
|
* generate a bounce record for each recipient.
|
||||||
*/
|
*/
|
||||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
else {
|
||||||
rcpt = request->rcpt_list.info + nrcpt;
|
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||||
if (rcpt->offset == 0)
|
rcpt = request->rcpt_list.info + nrcpt;
|
||||||
continue;
|
if (rcpt->offset == 0)
|
||||||
status = (SMTP_SOFT(code) ? defer_append : bounce_append)
|
continue;
|
||||||
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
status = (soft_error ? defer_append : bounce_append)
|
||||||
rcpt->orig_addr, rcpt->address, rcpt->offset,
|
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
||||||
session->namaddr, request->arrival_time,
|
rcpt->orig_addr, rcpt->address, rcpt->offset,
|
||||||
"%s", vstring_str(why));
|
session->namaddr, request->arrival_time,
|
||||||
if (status == 0) {
|
"%s", vstring_str(why));
|
||||||
deliver_completed(state->src, rcpt->offset);
|
if (status == 0) {
|
||||||
rcpt->offset = 0;
|
deliver_completed(state->src, rcpt->offset);
|
||||||
|
rcpt->offset = 0;
|
||||||
|
}
|
||||||
|
state->status |= status;
|
||||||
}
|
}
|
||||||
state->status |= status;
|
|
||||||
}
|
}
|
||||||
smtp_check_code(state, code);
|
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;
|
DELIVER_REQUEST *request = state->request;
|
||||||
SMTP_SESSION *session = state->session;
|
SMTP_SESSION *session = state->session;
|
||||||
int status;
|
int status;
|
||||||
|
int soft_error = SMTP_SOFT(code);
|
||||||
va_list ap;
|
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.
|
* If this is a soft error, postpone delivery to this recipient.
|
||||||
* Otherwise, generate a bounce record for this recipient.
|
* Otherwise, generate a bounce record for this recipient.
|
||||||
*/
|
*/
|
||||||
va_start(ap, format);
|
else {
|
||||||
status = (SMTP_SOFT(code) ? vdefer_append : vbounce_append)
|
va_start(ap, format);
|
||||||
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
status = (soft_error ? vdefer_append : vbounce_append)
|
||||||
rcpt->orig_addr, rcpt->address, rcpt->offset,
|
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
||||||
session->namaddr, request->arrival_time, format, ap);
|
rcpt->orig_addr, rcpt->address, rcpt->offset,
|
||||||
va_end(ap);
|
session->namaddr, request->arrival_time, format, ap);
|
||||||
if (status == 0) {
|
va_end(ap);
|
||||||
deliver_completed(state->src, rcpt->offset);
|
if (status == 0) {
|
||||||
rcpt->offset = 0;
|
deliver_completed(state->src, rcpt->offset);
|
||||||
|
rcpt->offset = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
smtp_check_code(state, code);
|
smtp_check_code(state, code);
|
||||||
state->status |= status;
|
state->status |= status;
|
||||||
@@ -287,20 +332,31 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
|
|||||||
break;
|
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.
|
* 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.
|
* All we know is that we should stay away from this host for a while.
|
||||||
*/
|
*/
|
||||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
else {
|
||||||
rcpt = request->rcpt_list.info + nrcpt;
|
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||||
if (rcpt->offset == 0)
|
rcpt = request->rcpt_list.info + nrcpt;
|
||||||
continue;
|
if (rcpt->offset == 0)
|
||||||
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
|
continue;
|
||||||
request->queue_id,
|
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||||
rcpt->orig_addr, rcpt->address,
|
request->queue_id,
|
||||||
rcpt->offset, session->namaddr,
|
rcpt->orig_addr, rcpt->address,
|
||||||
request->arrival_time,
|
rcpt->offset, session->namaddr,
|
||||||
"%s", vstring_str(why));
|
request->arrival_time,
|
||||||
|
"%s", vstring_str(why));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -347,6 +347,8 @@
|
|||||||
#include "smtpd_sasl_glue.h"
|
#include "smtpd_sasl_glue.h"
|
||||||
#include "smtpd_check.h"
|
#include "smtpd_check.h"
|
||||||
|
|
||||||
|
#define RESTRICTION_SEPARATORS ", \t\r\n"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Eject seat in case of parsing problems.
|
* 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
|
* encounter. Dictionaries must be opened before entering the chroot
|
||||||
* jail.
|
* jail.
|
||||||
*/
|
*/
|
||||||
while ((name = mystrtok(&bp, " \t\r\n,")) != 0) {
|
while ((name = mystrtok(&bp, RESTRICTION_SEPARATORS)) != 0) {
|
||||||
argv_add(argv, name, (char *) 0);
|
argv_add(argv, name, (char *) 0);
|
||||||
if (last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0)
|
if (last && strcasecmp(last, CHECK_POLICY_SERVICE) == 0)
|
||||||
policy_client_register(name);
|
policy_client_register(name);
|
||||||
@@ -767,7 +769,7 @@ void smtpd_check_init(void)
|
|||||||
smtpd_rest_classes = htable_create(1);
|
smtpd_rest_classes = htable_create(1);
|
||||||
if (*var_rest_classes) {
|
if (*var_rest_classes) {
|
||||||
cp = saved_classes = mystrdup(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)
|
if ((value = mail_conf_lookup_eval(name)) == 0 || *value == 0)
|
||||||
msg_fatal("restriction class `%s' needs a definition", name);
|
msg_fatal("restriction class `%s' needs a definition", name);
|
||||||
htable_enter(smtpd_rest_classes, 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))
|
#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));
|
memcpy(ADDROF(savebuf), ADDROF(smtpd_check_buf), sizeof(savebuf));
|
||||||
status = setjmp(smtpd_check_buf);
|
status = setjmp(smtpd_check_buf);
|
||||||
if (status != 0) {
|
if (status != 0) {
|
||||||
@@ -2837,7 +2839,7 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
|||||||
"use \"%s domain-name\" instead",
|
"use \"%s domain-name\" instead",
|
||||||
REJECT_MAPS_RBL, var_mail_name, REJECT_RBL_CLIENT);
|
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,
|
result = reject_rbl_addr(state, rbl_domain, state->addr,
|
||||||
SMTPD_NAME_CLIENT);
|
SMTPD_NAME_CLIENT);
|
||||||
if (result != SMTPD_CHECK_DUNNO)
|
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,
|
if ((owners = check_mail_addr_find(state, sender, smtpd_sender_login_maps,
|
||||||
STR(reply->recipient), (char **) 0)) != 0) {
|
STR(reply->recipient), (char **) 0)) != 0) {
|
||||||
cp = saved_owners = mystrdup(owners);
|
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) {
|
if (strcasecmp(state->sasl_username, name) == 0) {
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
@@ -4179,7 +4181,7 @@ static void rest_class(char *class)
|
|||||||
if (smtpd_rest_classes == 0)
|
if (smtpd_rest_classes == 0)
|
||||||
smtpd_rest_classes = htable_create(1);
|
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");
|
msg_panic("rest_class: null class name");
|
||||||
if ((entry = htable_locate(smtpd_rest_classes, name)) != 0)
|
if ((entry = htable_locate(smtpd_rest_classes, name)) != 0)
|
||||||
argv_free((ARGV *) entry->value);
|
argv_free((ARGV *) entry->value);
|
||||||
|
Reference in New Issue
Block a user