mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 05:38:06 +00:00
postfix-2.0.16-20031219
This commit is contained in:
parent
92cfbcfea3
commit
4f47f84bdc
@ -72,11 +72,11 @@ smtpd_sasl_security_options = noanonymous
|
||||
# The smtpd_sasl_local_domain parameter specifies the name of the
|
||||
# local authentication realm.
|
||||
#
|
||||
# By default, the local authentication realm name is the name of the
|
||||
# machine.
|
||||
# By default, the local authentication realm name is the null string.
|
||||
#
|
||||
#smtpd_sasl_local_domain = $mydomain
|
||||
smtpd_sasl_local_domain = $myhostname
|
||||
#smtpd_sasl_local_domain = $myhostname
|
||||
smtpd_sasl_local_domain =
|
||||
|
||||
# The smtpd_sasl_exceptions_networks parameter controls what SMTP
|
||||
# clients Postfix will not offer AUTH support.
|
||||
|
@ -180,6 +180,15 @@ extern bool var_disable_dns;
|
||||
#define DEF_SMTP_HOST_LOOKUP SMTP_HOST_LOOKUP_DNS
|
||||
extern int var_smtp_dns_lookup;
|
||||
|
||||
#define SMTP_BACKUP_SESSION "session"
|
||||
#define SMTP_BACKUP_MESSAGE "message"
|
||||
#define SMTP_BACKUP_RECIPIENT "recipient"
|
||||
|
||||
#define VAR_SMTP_BACKUP_MASK "smtp_backup_on_soft_error"
|
||||
#define DEF_SMTP_BACKUP_MASK SMTP_BACKUP_SESSION \
|
||||
" " SMTP_BACKUP_MESSAGE \
|
||||
" " SMTP_BACKUP_RECIPIENT
|
||||
|
||||
/*
|
||||
* Location of the mail queue directory tree.
|
||||
*/
|
||||
|
@ -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 "20031217"
|
||||
#define MAIL_RELEASE_DATE "20031219"
|
||||
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||
|
@ -11,6 +11,7 @@
|
||||
/* long offset;
|
||||
/* char *orig_addr;
|
||||
/* char *address;
|
||||
/* int status;
|
||||
/* .in -4
|
||||
/* } RECIPIENT;
|
||||
/*
|
||||
@ -30,12 +31,18 @@
|
||||
/* const char *orig_rcpt;
|
||||
/* const char *recipient;
|
||||
/*
|
||||
/* void recipient_list_truncate(list)
|
||||
/* RECIPIENT_LIST *list;
|
||||
/*
|
||||
/* void recipient_list_free(list)
|
||||
/* RECIPIENT_LIST *list;
|
||||
/* DESCRIPTION
|
||||
/* This module maintains lists of recipient structures. Each
|
||||
/* recipient is characterized by a destination address and
|
||||
/* by the queue file offset of its delivery status record.
|
||||
/* The per-recipient status is initialized to zero, and exists
|
||||
/* solely for the convenience of the application. It is not used
|
||||
/* by the recipient_list module itself.
|
||||
/*
|
||||
/* recipient_list_init() creates an empty recipient structure list.
|
||||
/* The list argument is initialized such that it can be given to
|
||||
@ -44,6 +51,9 @@
|
||||
/* recipient_list_add() adds a recipient to the specified list.
|
||||
/* The recipient address is copied with mystrdup().
|
||||
/*
|
||||
/* recipient_list_truncate() truncates the specified list to
|
||||
/* the specified length.
|
||||
/*
|
||||
/* recipient_list_free() releases memory for the specified list
|
||||
/* of recipient structures.
|
||||
/*
|
||||
@ -72,6 +82,7 @@
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <msg.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
@ -106,18 +117,30 @@ void recipient_list_add(RECIPIENT_LIST *list, long offset,
|
||||
list->info[list->len].orig_addr = mystrdup(orig_rcpt);
|
||||
list->info[list->len].address = mystrdup(rcpt);
|
||||
list->info[list->len].offset = offset;
|
||||
list->info[list->len].status = 0;
|
||||
list->len++;
|
||||
}
|
||||
|
||||
/* recipient_list_truncate - release memory for unused recipient structures */
|
||||
|
||||
void recipient_list_truncate(RECIPIENT_LIST *list, int new_len)
|
||||
{
|
||||
RECIPIENT *rcpt;
|
||||
|
||||
if (new_len < 0 || new_len > list->len)
|
||||
msg_panic("recipient_list_truncate: bad length %d", new_len);
|
||||
|
||||
for (rcpt = list->info + new_len; rcpt < list->info + list->len; rcpt++) {
|
||||
myfree(rcpt->orig_addr);
|
||||
myfree(rcpt->address);
|
||||
}
|
||||
list->len = new_len;
|
||||
}
|
||||
|
||||
/* recipient_list_free - release memory for in-core recipient structure */
|
||||
|
||||
void recipient_list_free(RECIPIENT_LIST *list)
|
||||
{
|
||||
RECIPIENT *rcpt;
|
||||
|
||||
for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) {
|
||||
myfree(rcpt->orig_addr);
|
||||
myfree(rcpt->address);
|
||||
}
|
||||
recipient_list_truncate(list, 0);
|
||||
myfree((char *) list->info);
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ typedef struct RECIPIENT {
|
||||
long offset; /* REC_TYPE_RCPT byte */
|
||||
char *orig_addr; /* null or original recipient */
|
||||
char *address; /* complete address */
|
||||
int status; /* Application specific. */
|
||||
} RECIPIENT;
|
||||
|
||||
typedef struct RECIPIENT_LIST {
|
||||
@ -31,6 +32,7 @@ typedef struct RECIPIENT_LIST {
|
||||
|
||||
extern void recipient_list_init(RECIPIENT_LIST *);
|
||||
extern void recipient_list_add(RECIPIENT_LIST *, long, const char *, const char *);
|
||||
extern void recipient_list_truncate(RECIPIENT_LIST *, int);
|
||||
extern void recipient_list_free(RECIPIENT_LIST *);
|
||||
|
||||
/* LICENSE
|
||||
|
@ -1,9 +1,9 @@
|
||||
SHELL = /bin/sh
|
||||
SRCS = smtp.c smtp_connect.c smtp_proto.c smtp_chat.c smtp_session.c \
|
||||
smtp_addr.c smtp_trouble.c smtp_state.c \
|
||||
smtp_addr.c smtp_trouble.c smtp_state.c smtp_misc.c \
|
||||
smtp_sasl_proto.c smtp_sasl_glue.c
|
||||
OBJS = smtp.o smtp_connect.o smtp_proto.o smtp_chat.o smtp_session.o \
|
||||
smtp_addr.o smtp_trouble.o smtp_state.o \
|
||||
smtp_addr.o smtp_trouble.o smtp_state.o smtp_misc.o \
|
||||
smtp_sasl_proto.o smtp_sasl_glue.o
|
||||
HDRS = smtp.h smtp_sasl.h
|
||||
TESTSRC =
|
||||
@ -89,16 +89,12 @@ smtp_addr.o: ../../include/stringops.h
|
||||
smtp_addr.o: ../../include/myrand.h
|
||||
smtp_addr.o: ../../include/mail_params.h
|
||||
smtp_addr.o: ../../include/own_inet_addr.h
|
||||
smtp_addr.o: ../../include/deliver_pass.h
|
||||
smtp_addr.o: ../../include/deliver_request.h
|
||||
smtp_addr.o: ../../include/vstream.h
|
||||
smtp_addr.o: ../../include/recipient_list.h
|
||||
smtp_addr.o: ../../include/mail_proto.h
|
||||
smtp_addr.o: ../../include/iostuff.h
|
||||
smtp_addr.o: ../../include/attr.h
|
||||
smtp_addr.o: ../../include/dns.h
|
||||
smtp_addr.o: smtp.h
|
||||
smtp_addr.o: ../../include/vstream.h
|
||||
smtp_addr.o: ../../include/argv.h
|
||||
smtp_addr.o: ../../include/deliver_request.h
|
||||
smtp_addr.o: ../../include/recipient_list.h
|
||||
smtp_addr.o: smtp_addr.h
|
||||
smtp_chat.o: smtp_chat.c
|
||||
smtp_chat.o: ../../include/sys_defs.h
|
||||
@ -137,14 +133,29 @@ smtp_connect.o: ../../include/sane_connect.h
|
||||
smtp_connect.o: ../../include/mail_params.h
|
||||
smtp_connect.o: ../../include/own_inet_addr.h
|
||||
smtp_connect.o: ../../include/debug_peer.h
|
||||
smtp_connect.o: ../../include/deliver_pass.h
|
||||
smtp_connect.o: ../../include/deliver_request.h
|
||||
smtp_connect.o: ../../include/recipient_list.h
|
||||
smtp_connect.o: ../../include/mail_proto.h
|
||||
smtp_connect.o: ../../include/attr.h
|
||||
smtp_connect.o: ../../include/mail_error.h
|
||||
smtp_connect.o: ../../include/name_mask.h
|
||||
smtp_connect.o: ../../include/dns.h
|
||||
smtp_connect.o: smtp.h
|
||||
smtp_connect.o: ../../include/argv.h
|
||||
smtp_connect.o: ../../include/deliver_request.h
|
||||
smtp_connect.o: ../../include/recipient_list.h
|
||||
smtp_connect.o: smtp_addr.h
|
||||
smtp_misc.o: smtp_misc.c
|
||||
smtp_misc.o: ../../include/sys_defs.h
|
||||
smtp_misc.o: ../../include/msg.h
|
||||
smtp_misc.o: ../../include/deliver_request.h
|
||||
smtp_misc.o: ../../include/vstring.h
|
||||
smtp_misc.o: ../../include/vbuf.h
|
||||
smtp_misc.o: ../../include/vstream.h
|
||||
smtp_misc.o: ../../include/recipient_list.h
|
||||
smtp_misc.o: ../../include/deliver_completed.h
|
||||
smtp_misc.o: ../../include/sent.h
|
||||
smtp_misc.o: smtp.h
|
||||
smtp_misc.o: ../../include/argv.h
|
||||
smtp_proto.o: smtp_proto.c
|
||||
smtp_proto.o: ../../include/sys_defs.h
|
||||
smtp_proto.o: ../../include/msg.h
|
||||
@ -162,10 +173,8 @@ smtp_proto.o: ../../include/smtp_stream.h
|
||||
smtp_proto.o: ../../include/mail_queue.h
|
||||
smtp_proto.o: ../../include/recipient_list.h
|
||||
smtp_proto.o: ../../include/deliver_request.h
|
||||
smtp_proto.o: ../../include/deliver_completed.h
|
||||
smtp_proto.o: ../../include/defer.h
|
||||
smtp_proto.o: ../../include/bounce.h
|
||||
smtp_proto.o: ../../include/sent.h
|
||||
smtp_proto.o: ../../include/record.h
|
||||
smtp_proto.o: ../../include/rec_type.h
|
||||
smtp_proto.o: ../../include/off_cvt.h
|
||||
|
@ -310,14 +310,18 @@ int var_smtp_pix_delay;
|
||||
int var_smtp_line_limit;
|
||||
char *var_smtp_helo_name;
|
||||
char *var_smtp_host_lookup;
|
||||
char *var_smtp_backup_mask;
|
||||
bool var_smtp_quote_821_env;
|
||||
bool var_smtp_defer_mxaddr;
|
||||
bool var_smtp_send_xforward;
|
||||
|
||||
/*
|
||||
* Global variables.
|
||||
* Global variables. smtp_errno is set by the address lookup routines and by
|
||||
* the connection management routines.
|
||||
*/
|
||||
int smtp_errno;
|
||||
int smtp_host_lookup_mask;
|
||||
int smtp_backup_mask;
|
||||
|
||||
/* deliver_message - deliver message with extreme prejudice */
|
||||
|
||||
@ -392,15 +396,21 @@ static void smtp_service(VSTREAM *client_stream, char *unused_service, char **ar
|
||||
}
|
||||
}
|
||||
|
||||
/* pre_init - pre-jail initialization */
|
||||
/* post_init - post-jail initialization */
|
||||
|
||||
static void pre_init(char *unused_name, char **unused_argv)
|
||||
static void post_init(char *unused_name, char **unused_argv)
|
||||
{
|
||||
static NAME_MASK lookup_masks[] = {
|
||||
SMTP_HOST_LOOKUP_DNS, SMTP_MASK_DNS,
|
||||
SMTP_HOST_LOOKUP_NATIVE, SMTP_MASK_NATIVE,
|
||||
0,
|
||||
};
|
||||
static NAME_MASK backup_masks[] = {
|
||||
SMTP_BACKUP_SESSION, SMTP_BACKUP_SESSION_FAILURE,
|
||||
SMTP_BACKUP_MESSAGE, SMTP_BACKUP_MESSAGE_FAILURE,
|
||||
SMTP_BACKUP_RECIPIENT, SMTP_BACKUP_RECIPIENT_FAILURE,
|
||||
0,
|
||||
};
|
||||
|
||||
/*
|
||||
* Turn on per-peer debugging.
|
||||
@ -420,6 +430,23 @@ static void pre_init(char *unused_name, char **unused_argv)
|
||||
str_name_mask(VAR_SMTP_HOST_LOOKUP, lookup_masks,
|
||||
smtp_host_lookup_mask));
|
||||
|
||||
/*
|
||||
* When to choose a backup host after a temporary failure.
|
||||
*/
|
||||
smtp_backup_mask = name_mask(VAR_SMTP_BACKUP_MASK, backup_masks,
|
||||
var_smtp_backup_mask);
|
||||
if (msg_verbose)
|
||||
msg_info("when to try backup host: %s",
|
||||
str_name_mask(VAR_SMTP_BACKUP_MASK, backup_masks,
|
||||
smtp_backup_mask));
|
||||
|
||||
}
|
||||
|
||||
/* pre_init - pre-jail initialization */
|
||||
|
||||
static void pre_init(char *unused_name, char **unused_argv)
|
||||
{
|
||||
|
||||
/*
|
||||
* SASL initialization.
|
||||
*/
|
||||
@ -468,6 +495,7 @@ int main(int argc, char **argv)
|
||||
VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
|
||||
VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0,
|
||||
VAR_SMTP_HOST_LOOKUP, DEF_SMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0,
|
||||
VAR_SMTP_BACKUP_MASK, DEF_SMTP_BACKUP_MASK, &var_smtp_backup_mask, 0, 0,
|
||||
0,
|
||||
};
|
||||
static CONFIG_TIME_TABLE time_table[] = {
|
||||
@ -510,6 +538,7 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_STR_TABLE, str_table,
|
||||
MAIL_SERVER_BOOL_TABLE, bool_table,
|
||||
MAIL_SERVER_PRE_INIT, pre_init,
|
||||
MAIL_SERVER_POST_INIT, post_init,
|
||||
MAIL_SERVER_PRE_ACCEPT, pre_accept,
|
||||
MAIL_SERVER_EXIT, pre_exit,
|
||||
0);
|
||||
|
@ -56,29 +56,53 @@ typedef struct SMTP_STATE {
|
||||
int space_left; /* output length control */
|
||||
struct MIME_STATE *mime_state; /* mime state machine */
|
||||
int final_server; /* final mail server */
|
||||
int backup_server; /* relayhost or fallback relay */
|
||||
} SMTP_STATE;
|
||||
|
||||
#define SMTP_FEATURE_ESMTP (1<<0)
|
||||
#define SMTP_FEATURE_8BITMIME (1<<1)
|
||||
#define SMTP_FEATURE_PIPELINING (1<<2)
|
||||
#define SMTP_FEATURE_SIZE (1<<3)
|
||||
#define SMTP_FEATURE_STARTTLS (1<<4)
|
||||
#define SMTP_FEATURE_AUTH (1<<5)
|
||||
#define SMTP_FEATURE_MAYBEPIX (1<<6) /* PIX smtp fixup mode */
|
||||
#define SMTP_FEATURE_XFORWARD_NAME (1<<7)
|
||||
#define SMTP_FEATURE_XFORWARD_ADDR (1<<8)
|
||||
#define SMTP_FEATURE_XFORWARD_PROTO (1<<9)
|
||||
#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
|
||||
/*
|
||||
* Server features.
|
||||
*/
|
||||
#define SMTP_FEATURE_ESMTP (1<<0)
|
||||
#define SMTP_FEATURE_8BITMIME (1<<1)
|
||||
#define SMTP_FEATURE_PIPELINING (1<<2)
|
||||
#define SMTP_FEATURE_SIZE (1<<3)
|
||||
#define SMTP_FEATURE_STARTTLS (1<<4)
|
||||
#define SMTP_FEATURE_AUTH (1<<5)
|
||||
#define SMTP_FEATURE_MAYBEPIX (1<<6) /* PIX smtp fixup mode */
|
||||
#define SMTP_FEATURE_XFORWARD_NAME (1<<7)
|
||||
#define SMTP_FEATURE_XFORWARD_ADDR (1<<8)
|
||||
#define SMTP_FEATURE_XFORWARD_PROTO (1<<9)
|
||||
#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
|
||||
|
||||
/*
|
||||
* Application-specific per-recipient status.
|
||||
*/
|
||||
#define SMTP_RCPT_KEEP 1 /* send to backup host */
|
||||
#define SMTP_RCPT_DROP 2 /* remove from list */
|
||||
|
||||
/*
|
||||
* smtp.c
|
||||
*/
|
||||
extern int smtp_errno; /* XXX can we get rid of this? */
|
||||
|
||||
#define SMTP_NONE 0 /* no error */
|
||||
#define SMTP_FAIL 1 /* permanent error */
|
||||
#define SMTP_RETRY 2 /* temporary error */
|
||||
#define SMTP_LOOP 3 /* MX loop */
|
||||
|
||||
extern int smtp_host_lookup_mask; /* host lookup methods to use */
|
||||
|
||||
#define SMTP_MASK_DNS (1<<0)
|
||||
#define SMTP_MASK_NATIVE (1<<1)
|
||||
|
||||
/*
|
||||
* What soft errors qualify for going to a backup host.
|
||||
*/
|
||||
extern int smtp_backup_mask; /* when to try backup host */
|
||||
|
||||
#define SMTP_BACKUP_SESSION_FAILURE (1<<0)
|
||||
#define SMTP_BACKUP_MESSAGE_FAILURE (1<<1)
|
||||
#define SMTP_BACKUP_RECIPIENT_FAILURE (1<<2)
|
||||
|
||||
/*
|
||||
* smtp_session.c
|
||||
*/
|
||||
@ -119,6 +143,12 @@ extern SMTP_RESP *smtp_chat_resp(SMTP_STATE *);
|
||||
extern void smtp_chat_reset(SMTP_STATE *);
|
||||
extern void smtp_chat_notify(SMTP_STATE *);
|
||||
|
||||
/*
|
||||
* smtp_misc.c.
|
||||
*/
|
||||
extern void smtp_rcpt_done(SMTP_STATE *, const char *, RECIPIENT *);
|
||||
extern int smtp_weed_request(RECIPIENT_LIST *);
|
||||
|
||||
/*
|
||||
* smtp_trouble.c
|
||||
*/
|
||||
@ -140,14 +170,6 @@ extern VSTRING *smtp_unalias_addr(VSTRING *, const char *);
|
||||
extern SMTP_STATE *smtp_state_alloc(void);
|
||||
extern void smtp_state_free(SMTP_STATE *);
|
||||
|
||||
/*
|
||||
* Status codes. Errors must have negative codes so that they do not
|
||||
* interfere with useful counts of work done.
|
||||
*/
|
||||
#define SMTP_OK 0 /* so far, so good */
|
||||
#define SMTP_RETRY (-1) /* transient error */
|
||||
#define SMTP_FAIL (-2) /* hard error */
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
|
@ -6,13 +6,13 @@
|
||||
/* SYNOPSIS
|
||||
/* #include "smtp_addr.h"
|
||||
/*
|
||||
/* DNS_RR *smtp_domain_addr(state, name)
|
||||
/* SMTP_STATE *state;
|
||||
/* DNS_RR *smtp_domain_addr(name, why)
|
||||
/* char *name;
|
||||
/* VSTRING *why;
|
||||
/*
|
||||
/* DNS_RR *smtp_host_addr(state, name)
|
||||
/* SMTP_STATE *state;
|
||||
/* DNS_RR *smtp_host_addr(name, why)
|
||||
/* char *name;
|
||||
/* VSTRING *why;
|
||||
/* DESCRIPTION
|
||||
/* This module implements Internet address lookups. By default,
|
||||
/* lookups are done via the Internet domain name service (DNS).
|
||||
@ -24,10 +24,7 @@
|
||||
/* exchanger hosts listed for the named domain. Addresses are
|
||||
/* returned in most-preferred first order. The result is truncated
|
||||
/* so that it contains only hosts that are more preferred than the
|
||||
/* local mail server itself. When the "best MX is local" feature
|
||||
/* is enabled, the local system is allowed to be the best mail
|
||||
/* exchanger, and mail is delivered accordingly. Otherwise,
|
||||
/* mailer loops are treated as an error.
|
||||
/* local mail server itself.
|
||||
/*
|
||||
/* When no mail exchanger is listed in the DNS for \fIname\fR, the
|
||||
/* request is passed to smtp_host_addr().
|
||||
@ -46,7 +43,16 @@
|
||||
/* when DNS lookups are explicitly disabled.
|
||||
/*
|
||||
/* All routines either return a DNS_RR pointer, or return a null
|
||||
/* pointer and report any problems via the smtp_trouble(3) module.
|
||||
/* pointer and set the \fIsmtp_errno\fR global variable accordingly:
|
||||
/* .IP SMTP_RETRY
|
||||
/* The request failed due to a soft error, and should be retried later.
|
||||
/* .IP SMTP_FAIL
|
||||
/* The request attempt failed due to a hard error.
|
||||
/* .IP SMTP_LOOP
|
||||
/* The local machine is the best mail exchanger.
|
||||
/* .PP
|
||||
/* In addition, a textual description of the problem is made available
|
||||
/* via the \fIwhy\fR argument.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
@ -109,7 +115,6 @@ static int h_errno = TRY_AGAIN;
|
||||
|
||||
#include <mail_params.h>
|
||||
#include <own_inet_addr.h>
|
||||
#include <deliver_pass.h>
|
||||
|
||||
/* DNS library. */
|
||||
|
||||
@ -120,9 +125,6 @@ static int h_errno = TRY_AGAIN;
|
||||
#include "smtp.h"
|
||||
#include "smtp_addr.h"
|
||||
|
||||
#define ERROR_CLASS_RETRY 450
|
||||
#define ERROR_CLASS_FAIL 550
|
||||
|
||||
/* smtp_print_addr - print address list */
|
||||
|
||||
static void smtp_print_addr(char *what, DNS_RR *addr_list)
|
||||
@ -146,8 +148,7 @@ static void smtp_print_addr(char *what, DNS_RR *addr_list)
|
||||
|
||||
/* smtp_addr_one - address lookup for one host name */
|
||||
|
||||
static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
|
||||
VSTRING *why, int *error_class)
|
||||
static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
|
||||
{
|
||||
char *myname = "smtp_addr_one";
|
||||
struct in_addr inaddr;
|
||||
@ -180,13 +181,13 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
|
||||
addr_list = dns_rr_append(addr_list, addr);
|
||||
return (addr_list);
|
||||
default:
|
||||
*error_class = ERROR_CLASS_RETRY;
|
||||
smtp_errno = SMTP_RETRY;
|
||||
return (addr_list);
|
||||
case DNS_FAIL:
|
||||
*error_class = ERROR_CLASS_FAIL;
|
||||
smtp_errno = SMTP_FAIL;
|
||||
return (addr_list);
|
||||
case DNS_NOTFOUND:
|
||||
*error_class = ERROR_CLASS_FAIL;
|
||||
smtp_errno = SMTP_FAIL;
|
||||
/* maybe gethostbyname() will succeed */
|
||||
break;
|
||||
}
|
||||
@ -199,13 +200,12 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
|
||||
memset((char *) &fixed, 0, sizeof(fixed));
|
||||
if ((hp = gethostbyname(host)) == 0) {
|
||||
vstring_sprintf(why, "%s: %s", host, HSTRERROR(h_errno));
|
||||
*error_class = (h_errno == TRY_AGAIN ?
|
||||
ERROR_CLASS_RETRY : ERROR_CLASS_FAIL);
|
||||
smtp_errno = (h_errno == TRY_AGAIN ? SMTP_RETRY : SMTP_FAIL);
|
||||
} else if (hp->h_addrtype != AF_INET) {
|
||||
vstring_sprintf(why, "%s: host not found", host);
|
||||
msg_warn("%s: unknown address family %d for %s",
|
||||
myname, hp->h_addrtype, host);
|
||||
*error_class = ERROR_CLASS_FAIL;
|
||||
smtp_errno = SMTP_FAIL;
|
||||
} else {
|
||||
while (hp->h_addr_list[0]) {
|
||||
addr_list = dns_rr_append(addr_list,
|
||||
@ -226,7 +226,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
|
||||
|
||||
/* smtp_addr_list - address lookup for a list of mail exchangers */
|
||||
|
||||
static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why, int *error_class)
|
||||
static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why)
|
||||
{
|
||||
DNS_RR *addr_list = 0;
|
||||
DNS_RR *rr;
|
||||
@ -236,7 +236,7 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why, int *error_class)
|
||||
* with DNS lookups (except if we're backup MX, and all the better MX
|
||||
* hosts can't be found).
|
||||
*
|
||||
* XXX 2821: update error_class (0->FAIL upon unrecoverable lookup error,
|
||||
* 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.
|
||||
@ -244,8 +244,7 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why, int *error_class)
|
||||
for (rr = mx_names; rr; rr = rr->next) {
|
||||
if (rr->type != T_MX)
|
||||
msg_panic("smtp_addr_list: bad resource type: %d", rr->type);
|
||||
addr_list = smtp_addr_one(addr_list, (char *) rr->data, rr->pref,
|
||||
why, error_class);
|
||||
addr_list = smtp_addr_one(addr_list, (char *) rr->data, rr->pref, why);
|
||||
}
|
||||
return (addr_list);
|
||||
}
|
||||
@ -328,16 +327,13 @@ static int smtp_compare_pref(DNS_RR *a, DNS_RR *b)
|
||||
|
||||
/* smtp_domain_addr - mail exchanger address lookup */
|
||||
|
||||
DNS_RR *smtp_domain_addr(SMTP_STATE *state, char *name)
|
||||
DNS_RR *smtp_domain_addr(char *name, VSTRING *why)
|
||||
{
|
||||
DELIVER_REQUEST *request = state->request;
|
||||
DNS_RR *mx_names;
|
||||
DNS_RR *addr_list = 0;
|
||||
DNS_RR *self = 0;
|
||||
unsigned best_pref;
|
||||
unsigned best_found;
|
||||
int error_class;
|
||||
VSTRING *why = vstring_alloc(1);
|
||||
|
||||
/*
|
||||
* Preferences from DNS use 0..32767, fall-backs use 32768+.
|
||||
@ -391,40 +387,26 @@ DNS_RR *smtp_domain_addr(SMTP_STATE *state, char *name)
|
||||
* 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.
|
||||
*
|
||||
* Defer host lookup errors if a) there are more mail servers or b) we are
|
||||
* looking up a relayhost or fallback relay.
|
||||
*/
|
||||
#define DEFER_HOST_LOOKUP_ERROR(s) \
|
||||
((s)->final_server == 0 || (s)->backup_server)
|
||||
|
||||
switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why)) {
|
||||
default:
|
||||
smtp_errno = SMTP_RETRY;
|
||||
if (var_ign_mx_lookup_err)
|
||||
addr_list = smtp_host_addr(state, name);
|
||||
else
|
||||
smtp_site_fail(state, ERROR_CLASS_RETRY,
|
||||
"%s: %s", request->queue_id, vstring_str(why));
|
||||
addr_list = smtp_host_addr(name, why);
|
||||
break;
|
||||
case DNS_FAIL:
|
||||
smtp_errno = SMTP_FAIL;
|
||||
if (var_ign_mx_lookup_err)
|
||||
addr_list = smtp_host_addr(state, name);
|
||||
else {
|
||||
smtp_site_fail(state, DEFER_HOST_LOOKUP_ERROR(state) ?
|
||||
ERROR_CLASS_RETRY : ERROR_CLASS_FAIL,
|
||||
"%s: %s", request->queue_id, vstring_str(why));
|
||||
}
|
||||
addr_list = smtp_host_addr(name, why);
|
||||
break;
|
||||
case DNS_OK:
|
||||
mx_names = dns_rr_sort(mx_names, smtp_compare_pref);
|
||||
best_pref = (mx_names ? mx_names->pref : IMPOSSIBLE_PREFERENCE);
|
||||
addr_list = smtp_addr_list(mx_names, why, &error_class);
|
||||
addr_list = smtp_addr_list(mx_names, why);
|
||||
dns_rr_free(mx_names);
|
||||
if (addr_list == 0) {
|
||||
if (var_smtp_defer_mxaddr || DEFER_HOST_LOOKUP_ERROR(state))
|
||||
error_class = ERROR_CLASS_RETRY;
|
||||
smtp_site_fail(state, error_class,
|
||||
"%s: %s", request->queue_id, vstring_str(why));
|
||||
if (var_smtp_defer_mxaddr)
|
||||
smtp_errno = SMTP_RETRY;
|
||||
msg_warn("no MX host for %s has a valid A record", name);
|
||||
break;
|
||||
}
|
||||
@ -435,23 +417,14 @@ DNS_RR *smtp_domain_addr(SMTP_STATE *state, char *name)
|
||||
addr_list = smtp_truncate_self(addr_list, self->pref);
|
||||
if (addr_list == 0) {
|
||||
if (best_pref != best_found) {
|
||||
smtp_site_fail(state, ERROR_CLASS_RETRY,
|
||||
"%s: unable to find primary relay for %s",
|
||||
request->queue_id, name);
|
||||
} else if (*var_bestmx_transp != 0) { /* we're best MX */
|
||||
state->status =
|
||||
deliver_pass_all(MAIL_CLASS_PRIVATE, var_bestmx_transp,
|
||||
request);
|
||||
state->final_server = 1;
|
||||
vstring_sprintf(why, "unable to find primary relay for %s",
|
||||
name);
|
||||
smtp_errno = SMTP_RETRY;
|
||||
} else {
|
||||
msg_warn("%s is best MX host for %s but no local, virtual "
|
||||
"or remote delivery is configured for that domain",
|
||||
var_myhostname, request->nexthop);
|
||||
smtp_site_fail(state, ERROR_CLASS_FAIL,
|
||||
"%s: mail for %s loops back to myself",
|
||||
request->queue_id, name);
|
||||
vstring_sprintf(why, "mail for %s loops back to myself",
|
||||
name);
|
||||
smtp_errno = SMTP_LOOP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (addr_list && addr_list->next && var_smtp_rand_addr) {
|
||||
@ -460,43 +433,31 @@ DNS_RR *smtp_domain_addr(SMTP_STATE *state, char *name)
|
||||
}
|
||||
break;
|
||||
case DNS_NOTFOUND:
|
||||
addr_list = smtp_host_addr(state, name);
|
||||
addr_list = smtp_host_addr(name, why);
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
*/
|
||||
vstring_free(why);
|
||||
return (addr_list);
|
||||
}
|
||||
|
||||
/* smtp_host_addr - direct host lookup */
|
||||
|
||||
DNS_RR *smtp_host_addr(SMTP_STATE *state, char *host)
|
||||
DNS_RR *smtp_host_addr(char *host, VSTRING *why)
|
||||
{
|
||||
DELIVER_REQUEST *request = state->request;
|
||||
DNS_RR *addr_list;
|
||||
int error_class;
|
||||
VSTRING *why = vstring_alloc(1);
|
||||
|
||||
/*
|
||||
* If the host is specified by numerical address, just convert the
|
||||
* address to internal form. Otherwise, the host is specified by name.
|
||||
*/
|
||||
#define PREF0 0
|
||||
addr_list = smtp_addr_one((DNS_RR *) 0, host, PREF0, why, &error_class);
|
||||
if (addr_list == 0) {
|
||||
if (DEFER_HOST_LOOKUP_ERROR(state))
|
||||
error_class = ERROR_CLASS_RETRY;
|
||||
smtp_site_fail(state, error_class,
|
||||
"%s: %s", request->queue_id, vstring_str(why));
|
||||
} else {
|
||||
if (addr_list->next && var_smtp_rand_addr)
|
||||
addr_list = dns_rr_shuffle(addr_list);
|
||||
if (msg_verbose)
|
||||
smtp_print_addr(host, addr_list);
|
||||
}
|
||||
vstring_free(why);
|
||||
addr_list = smtp_addr_one((DNS_RR *) 0, host, PREF0, why);
|
||||
if (addr_list && addr_list->next && var_smtp_rand_addr)
|
||||
addr_list = dns_rr_shuffle(addr_list);
|
||||
if (msg_verbose)
|
||||
smtp_print_addr(host, addr_list);
|
||||
return (addr_list);
|
||||
}
|
||||
|
@ -16,8 +16,8 @@
|
||||
/*
|
||||
* Internal interfaces.
|
||||
*/
|
||||
extern DNS_RR *smtp_host_addr(SMTP_STATE *state, char *);
|
||||
extern DNS_RR *smtp_domain_addr(SMTP_STATE *state, char *);
|
||||
extern DNS_RR *smtp_host_addr(char *, VSTRING *);
|
||||
extern DNS_RR *smtp_domain_addr(char *, VSTRING *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
|
@ -82,6 +82,7 @@
|
||||
#include <mail_params.h>
|
||||
#include <own_inet_addr.h>
|
||||
#include <debug_peer.h>
|
||||
#include <deliver_pass.h>
|
||||
#include <mail_error.h>
|
||||
|
||||
/* DNS library. */
|
||||
@ -95,8 +96,8 @@
|
||||
|
||||
/* smtp_connect_addr - connect to explicit address */
|
||||
|
||||
static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
|
||||
unsigned port)
|
||||
static SMTP_SESSION *smtp_connect_addr(DNS_RR *addr, unsigned port,
|
||||
VSTRING *why)
|
||||
{
|
||||
char *myname = "smtp_connect_addr";
|
||||
struct sockaddr_in sin;
|
||||
@ -111,8 +112,11 @@ static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (addr->data_len > sizeof(sin.sin_addr))
|
||||
msg_panic("%s: unexpected address length %d", myname, addr->data_len);
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
@ -174,8 +178,9 @@ static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
|
||||
conn_stat = sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin));
|
||||
}
|
||||
if (conn_stat < 0) {
|
||||
smtp_site_fail(state, 450, "connect to %s[%s] port %u: %m",
|
||||
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
|
||||
vstring_sprintf(why, "connect to %s[%s]: %m",
|
||||
addr->name, inet_ntoa(sin.sin_addr));
|
||||
smtp_errno = SMTP_RETRY;
|
||||
close(sock);
|
||||
return (0);
|
||||
}
|
||||
@ -184,8 +189,9 @@ static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
|
||||
* Skip this host if it takes no action within some time limit.
|
||||
*/
|
||||
if (read_wait(sock, var_smtp_helo_tmout) < 0) {
|
||||
smtp_site_fail(state, 450, "connect to %s[%s] port %u: read timeout",
|
||||
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
|
||||
vstring_sprintf(why, "connect to %s[%s]: read timeout",
|
||||
addr->name, inet_ntoa(sin.sin_addr));
|
||||
smtp_errno = SMTP_RETRY;
|
||||
close(sock);
|
||||
return (0);
|
||||
}
|
||||
@ -195,14 +201,35 @@ static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
|
||||
*/
|
||||
stream = vstream_fdopen(sock, O_RDWR);
|
||||
if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
|
||||
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));
|
||||
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;
|
||||
vstream_fclose(stream);
|
||||
return (0);
|
||||
}
|
||||
vstream_ungetc(stream, ch);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
vstream_fclose(stream);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
vstream_fclose(stream);
|
||||
return (0);
|
||||
}
|
||||
return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
|
||||
}
|
||||
|
||||
@ -246,6 +273,7 @@ static char *smtp_parse_destination(char *destination, char *def_service,
|
||||
int smtp_connect(SMTP_STATE *state)
|
||||
{
|
||||
DELIVER_REQUEST *request = state->request;
|
||||
VSTRING *why = vstring_alloc(10);
|
||||
char *dest_buf;
|
||||
char *host;
|
||||
unsigned port;
|
||||
@ -272,22 +300,21 @@ int smtp_connect(SMTP_STATE *state)
|
||||
argv_split_append(sites, var_fallback_relay, ", \t\r\n");
|
||||
|
||||
/*
|
||||
* Don't give up after any soft error until we have tried all servers.
|
||||
* Don't give up after a qualifying soft error until we have tried all
|
||||
* qualifying mail servers.
|
||||
*
|
||||
* Don't give up after a hard host lookup error until we have tried the
|
||||
* fallback relay servers.
|
||||
*
|
||||
* Don't bounce mail after host lookup problems with a relayhost or with
|
||||
* fallback relays.
|
||||
* Don't bounce mail after a host lookup problem with a relayhost or with a
|
||||
* fallback relay.
|
||||
*
|
||||
* All this means that error handling and error reporting depends on whether
|
||||
* there are more mail servers (state->final_server), or whether we're
|
||||
* looking up a relayhost or fallback relay (state->backup_server).
|
||||
* the error qualifies for trying more mail servers, or whether we're
|
||||
* looking up a relayhost or fallback relay.
|
||||
*/
|
||||
for (cpp = sites->argv; (dest = *cpp) != 0; cpp++) {
|
||||
state->final_server = (cpp[1] == 0);
|
||||
state->backup_server =
|
||||
(cpp > sites->argv || strcmp(request->nexthop, var_relayhost) == 0);
|
||||
|
||||
/*
|
||||
* Parse the destination. Default is to use the SMTP port. Look up
|
||||
@ -295,37 +322,36 @@ int smtp_connect(SMTP_STATE *state)
|
||||
* specified, or when DNS lookups are disabled.
|
||||
*/
|
||||
dest_buf = smtp_parse_destination(dest, def_service, &host, &port);
|
||||
|
||||
/*
|
||||
* Resolve 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 == '[') {
|
||||
addr_list = smtp_host_addr(state, host);
|
||||
addr_list = smtp_host_addr(host, why);
|
||||
} else {
|
||||
addr_list = smtp_domain_addr(state, host);
|
||||
addr_list = smtp_domain_addr(host, why);
|
||||
}
|
||||
myfree(dest_buf);
|
||||
|
||||
/*
|
||||
* No address list. The mail has / has not been delivered. What to do
|
||||
* next (skip remaining hosts / try to deliver) is recorded in the
|
||||
* state->final_server attribute.
|
||||
* Don't try the fall-back relay if mail loops to myself.
|
||||
*/
|
||||
if (addr_list == 0) {
|
||||
if (state->backup_server)
|
||||
msg_warn("%s or %s configuration problem",
|
||||
VAR_RELAYHOST, VAR_FALLBACK_RELAY);
|
||||
}
|
||||
if (addr_list == 0 && smtp_errno == SMTP_LOOP)
|
||||
break;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* After a soft error, weed out the recipient list and if there are any
|
||||
* left, try again.
|
||||
*/
|
||||
for (addr = addr_list; addr; addr = addr->next) {
|
||||
if ((state->session = smtp_connect_addr(state, addr, port)) != 0) {
|
||||
if ((state->session = smtp_connect_addr(addr, port, why)) != 0) {
|
||||
state->final_server = (cpp[1] == 0 && addr->next == 0);
|
||||
state->status = 0;
|
||||
state->session->best = (addr->pref == addr_list->pref);
|
||||
debug_peer_check(state->session->host, state->session->addr);
|
||||
if (smtp_helo(state) == 0)
|
||||
@ -337,23 +363,71 @@ int smtp_connect(SMTP_STATE *state)
|
||||
/* XXX smtp_xfer() may abort in the middle of DATA. */
|
||||
smtp_session_free(state->session);
|
||||
debug_peer_restore();
|
||||
if (state->status == 0 || state->final_server)
|
||||
if (smtp_weed_request(&request->rcpt_list) == 0)
|
||||
break;
|
||||
} else {
|
||||
msg_info("%s (port %d)", vstring_str(why), ntohs(port));
|
||||
}
|
||||
}
|
||||
dns_rr_free(addr_list);
|
||||
}
|
||||
|
||||
/*
|
||||
* We still need to deliver, bounce or defer some recipients.
|
||||
*
|
||||
* Pay attention to what could be configuration problems, and pretend that
|
||||
* these are recoverable rather than bouncing the mail.
|
||||
*/
|
||||
if (request->rcpt_list.len > 0) {
|
||||
if (smtp_errno != SMTP_RETRY) {
|
||||
|
||||
/*
|
||||
* The fall-back destination did not resolve as expected, or it
|
||||
* is refusing to talk to us.
|
||||
*/
|
||||
if (sites->argc > 1 && cpp > sites->argv) {
|
||||
msg_warn("%s configuration problem", VAR_FALLBACK_RELAY);
|
||||
smtp_errno = SMTP_RETRY;
|
||||
}
|
||||
|
||||
/*
|
||||
* The next-hop relayhost did not resolve as expected, or it is
|
||||
* refusing to talk to us.
|
||||
*/
|
||||
else if (strcmp(sites->argv[0], var_relayhost) == 0) {
|
||||
msg_warn("%s configuration problem", VAR_RELAYHOST);
|
||||
smtp_errno = SMTP_RETRY;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mail for the next-hop destination loops back to myself.
|
||||
*/
|
||||
else if (smtp_errno == SMTP_LOOP && *var_bestmx_transp) {
|
||||
state->status = deliver_pass_all(MAIL_CLASS_PRIVATE,
|
||||
var_bestmx_transp,
|
||||
request);
|
||||
smtp_errno = SMTP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In case someone has raised the "final server" flag before we have
|
||||
* tried all fallback servers.
|
||||
* We still need to bounce or defer some recipients. Do it now or
|
||||
* else they would silently disappear due to lack of error
|
||||
* indication.
|
||||
*/
|
||||
if (state->final_server)
|
||||
break;
|
||||
if (smtp_errno != SMTP_NONE) {
|
||||
if (!state->final_server)
|
||||
msg_panic("smtp_connect: we have left-over recipients but "
|
||||
"we did not try to connect to the final server");
|
||||
smtp_site_fail(state, smtp_errno == SMTP_RETRY ? 450 : 550,
|
||||
"%s", vstring_str(why));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Cleanup.
|
||||
*/
|
||||
argv_free(sites);
|
||||
vstring_free(why);
|
||||
return (state->status);
|
||||
}
|
||||
|
81
postfix/src/smtp/smtp_misc.c
Normal file
81
postfix/src/smtp/smtp_misc.c
Normal file
@ -0,0 +1,81 @@
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <stdlib.h> /* smtp_weed_request */
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <deliver_request.h> /* smtp_rcpt_done */
|
||||
#include <deliver_completed.h> /* smtp_rcpt_done */
|
||||
#include <sent.h> /* smtp_rcpt_done */
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include <smtp.h>
|
||||
|
||||
/* smtp_rcpt_done - mark recipient as done or else */
|
||||
|
||||
void smtp_rcpt_done(SMTP_STATE *state, const char *reply, RECIPIENT *rcpt)
|
||||
{
|
||||
DELIVER_REQUEST *request = state->request;
|
||||
SMTP_SESSION *session = state->session;
|
||||
int status;
|
||||
|
||||
/*
|
||||
* Report success and delete the recipient from the delivery request.
|
||||
* Defer if the success can't be reported.
|
||||
*/
|
||||
status = sent(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||
request->queue_id, rcpt->orig_addr,
|
||||
rcpt->address, rcpt->offset,
|
||||
session->namaddr,
|
||||
request->arrival_time,
|
||||
"%s", reply);
|
||||
if (status == 0)
|
||||
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
rcpt->status = SMTP_RCPT_DROP;
|
||||
state->status |= status;
|
||||
}
|
||||
|
||||
/* smtp_weed_request_callback - qsort callback */
|
||||
|
||||
static int smtp_weed_request_callback(const void *a, const void *b)
|
||||
{
|
||||
return (((RECIPIENT *) a)->status - ((RECIPIENT *) b)->status);
|
||||
}
|
||||
|
||||
/* smtp_weed_request - purge completed recipients from request */
|
||||
|
||||
int smtp_weed_request(RECIPIENT_LIST *rcpt_list)
|
||||
{
|
||||
RECIPIENT *rcpt;
|
||||
int nrcpt;
|
||||
|
||||
/*
|
||||
* Status codes one can expect to find: SMTP_RCPT_KEEP (try recipient
|
||||
* another time), SMTP_RCPT_DROP (remove recipient from request) and zero
|
||||
* (error: after delivery attempt, recipient status should be either KEEP
|
||||
* or DROP).
|
||||
*/
|
||||
if (rcpt_list->len > 1)
|
||||
qsort((void *) rcpt_list->info, rcpt_list->len,
|
||||
sizeof(rcpt_list->info), smtp_weed_request_callback);
|
||||
|
||||
for (nrcpt = 0; nrcpt < rcpt_list->len; nrcpt++) {
|
||||
rcpt = rcpt_list->info + nrcpt;
|
||||
if (rcpt->status == SMTP_RCPT_KEEP)
|
||||
rcpt->status = 0;
|
||||
if (rcpt->status == SMTP_RCPT_DROP)
|
||||
break;
|
||||
else
|
||||
msg_panic("smtp_weed_request: bad status: %d for <%s>",
|
||||
rcpt->status, rcpt->address);
|
||||
}
|
||||
recipient_list_truncate(rcpt_list, nrcpt);
|
||||
return (nrcpt);
|
||||
}
|
@ -93,10 +93,8 @@
|
||||
#include <mail_queue.h>
|
||||
#include <recipient_list.h>
|
||||
#include <deliver_request.h>
|
||||
#include <deliver_completed.h>
|
||||
#include <defer.h>
|
||||
#include <bounce.h>
|
||||
#include <sent.h>
|
||||
#include <record.h>
|
||||
#include <rec_type.h>
|
||||
#include <off_cvt.h>
|
||||
@ -197,13 +195,10 @@ int smtp_helo(SMTP_STATE *state)
|
||||
/*
|
||||
* Read and parse the server's SMTP greeting banner.
|
||||
*/
|
||||
if ((resp = smtp_chat_resp(state))->code / 100 != 2) {
|
||||
if (var_smtp_skip_5xx_greeting && resp->code / 100 == '5')
|
||||
resp->code -= 100;
|
||||
if ((resp = smtp_chat_resp(state))->code / 100 != 2)
|
||||
return (smtp_site_fail(state, resp->code,
|
||||
"host %s refused to talk to me: %s",
|
||||
session->namaddr, translit(resp->str, "\n", " ")));
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX Some PIX firewall versions require flush before ".<CR><LF>" so it
|
||||
@ -436,6 +431,16 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
#define SENDING_MAIL \
|
||||
(recv_state <= SMTP_STATE_DOT)
|
||||
|
||||
/*
|
||||
* Sanity check. Recipients should be unmarked at this point.
|
||||
*/
|
||||
if (request->rcpt_list.len <= 0)
|
||||
msg_panic("smtp_xfer: bad recipient count: %d",
|
||||
request->rcpt_list.len);
|
||||
if (request->rcpt_list.info->status != 0)
|
||||
msg_panic("smtp_xfer: bad recipient status: %d",
|
||||
request->rcpt_list.info->status);
|
||||
|
||||
/*
|
||||
* See if we should even try to send this message at all. This code sits
|
||||
* here rather than in the EHLO processing code, because of future SMTP
|
||||
@ -763,24 +768,14 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
if (resp->code / 100 == 2) {
|
||||
++nrcpt;
|
||||
/* If trace-only, mark the recipient done. */
|
||||
if (DEL_REQ_TRACE_ONLY(request->flags)
|
||||
&& sent(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||
request->queue_id, rcpt->orig_addr,
|
||||
rcpt->address, rcpt->offset,
|
||||
session->namaddr, request->arrival_time,
|
||||
"%s",
|
||||
translit(resp->str, "\n", " ")) == 0) {
|
||||
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
rcpt->offset = 0; /* in case deferred */
|
||||
}
|
||||
if (DEL_REQ_TRACE_ONLY(request->flags))
|
||||
smtp_rcpt_done(state, resp->str, rcpt);
|
||||
} else {
|
||||
smtp_rcpt_fail(state, resp->code, rcpt,
|
||||
"host %s said: %s (in reply to %s)",
|
||||
session->namaddr,
|
||||
translit(resp->str, "\n", " "),
|
||||
xfer_request[SMTP_STATE_RCPT]);
|
||||
rcpt->offset = 0; /* in case deferred */
|
||||
}
|
||||
}
|
||||
/* If trace-only, send RSET instead of DATA. */
|
||||
@ -827,18 +822,8 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
} else {
|
||||
for (nrcpt = 0; nrcpt < recv_rcpt; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (rcpt->offset) {
|
||||
if (sent(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||
request->queue_id, rcpt->orig_addr,
|
||||
rcpt->address, rcpt->offset,
|
||||
session->namaddr,
|
||||
request->arrival_time,
|
||||
"%s", resp->str) == 0) {
|
||||
if (request->flags & DEL_REQ_FLAG_SUCCESS)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
rcpt->offset = 0;
|
||||
}
|
||||
}
|
||||
if (rcpt->status == 0)
|
||||
smtp_rcpt_done(state, resp->str, rcpt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +73,6 @@ SMTP_STATE *smtp_state_alloc(void)
|
||||
state->space_left = 0;
|
||||
state->mime_state = 0;
|
||||
state->final_server = 0;
|
||||
state->backup_server = 0;
|
||||
return (state);
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,9 @@
|
||||
/* the problem, delivery of a single message is deferred, delivery
|
||||
/* of all messages to the same domain is deferred, or one or more
|
||||
/* recipients are given up as non-deliverable and a bounce log is
|
||||
/* updated.
|
||||
/* updated. In any case, the recipient status is updated to either
|
||||
/* SMTP_RCPT_KEEP (try again with a backup host) or SMTP_RCPT_DROP
|
||||
/* (delete recipient from delivery request).
|
||||
/*
|
||||
/* In addition, when an unexpected response code is seen such
|
||||
/* as 3xx where only 4xx or 5xx are expected, or any error code
|
||||
@ -43,15 +45,11 @@
|
||||
/* 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 mail servers (log an informational record only and try
|
||||
/* the other servers) or whether this is the final server (log
|
||||
/* recipient delivery status records).
|
||||
/*
|
||||
/* In the case of a hard error that affects all recipients,
|
||||
/* recipient delivery status records are logged, and the
|
||||
/* final server flag is raised so that any remaining mail
|
||||
/* servers are skipped.
|
||||
/* In case of a soft error, action depends on whether the error
|
||||
/* qualifies for trying the request with other mail servers (log
|
||||
/* an informational record only and try the a backup server) or
|
||||
/* whether this is the final server (log recipient delivery status
|
||||
/* records and delete the recipient from the request).
|
||||
/*
|
||||
/* smtp_site_fail() handles the case where the program fails to
|
||||
/* complete the initial SMTP handshake: the server is not reachable,
|
||||
@ -60,9 +58,8 @@
|
||||
/* argument gives a textual description.
|
||||
/* The policy is: soft error, non-final server: log an informational
|
||||
/* record why the host is being skipped; soft error, final server:
|
||||
/* defer delivery of all remaining recipients; hard error: bounce all
|
||||
/* remaining recipients and set the "final server" flag so that any
|
||||
/* remaining mail servers will be skipped.
|
||||
/* defer delivery of all remaining recipients and mark the destination
|
||||
/* a problematic; hard error: bounce all remaining recipients.
|
||||
/* The result is non-zero.
|
||||
/*
|
||||
/* smtp_mesg_fail() handles the case where the smtp server
|
||||
@ -70,8 +67,7 @@
|
||||
/* The policy is: soft error, non-final server: log an informational
|
||||
/* record why the host is being skipped; soft error, final server:
|
||||
/* defer delivery of all remaining recipients; hard error: bounce all
|
||||
/* remaining recipients and set the "final server" flag so that any
|
||||
/* remaining mail servers will be skipped.
|
||||
/* remaining recipients.
|
||||
/* The result is non-zero.
|
||||
/*
|
||||
/* smtp_rcpt_fail() handles the case where a recipient is not
|
||||
@ -80,7 +76,7 @@
|
||||
/* The policy is: soft error, non-final server: log an informational
|
||||
/* record why the recipient is being skipped; soft error, final server:
|
||||
/* defer delivery of this recipient; hard error: bounce this
|
||||
/* recipient. This routine does not change the "final server" flag.
|
||||
/* recipient.
|
||||
/*
|
||||
/* smtp_stream_except() handles the exceptions generated by
|
||||
/* the smtp_stream(3) module (i.e. timeouts and I/O errors).
|
||||
@ -159,7 +155,7 @@ static void smtp_check_code(SMTP_STATE *state, int code)
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
}
|
||||
|
||||
/* smtp_site_fail - skip site, defer all recipients, or bounce all recipients */
|
||||
/* smtp_site_fail - skip site, defer or bounce all recipients */
|
||||
|
||||
int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
{
|
||||
@ -180,38 +176,44 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
va_end(ap);
|
||||
|
||||
/*
|
||||
* Don't defer the recipients just yet when there are still more mail
|
||||
* servers. Just log something informative to show why we're skipping
|
||||
* this host.
|
||||
* Don't defer the recipients just yet when this error qualifies them for
|
||||
* delivery to a backup server. Just log something informative to show
|
||||
* why we're skipping this host.
|
||||
*/
|
||||
if (soft_error && state->final_server == 0) {
|
||||
if (soft_error && state->final_server == 0
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_SESSION_FAILURE)) {
|
||||
msg_info("%s: %s", request->queue_id, vstring_str(why));
|
||||
state->status |= -1;
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (rcpt->status != 0)
|
||||
continue;
|
||||
rcpt->status = SMTP_RCPT_KEEP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Defer or bounce all the remaining recipients and raise the final mail
|
||||
* server flag.
|
||||
* Defer or bounce all the remaining recipients, and delete them from the
|
||||
* delivery request. If a bounce fails, defer instead and do not qualify
|
||||
* the recipient for delivery to a backup server.
|
||||
*/
|
||||
else {
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (rcpt->offset == 0)
|
||||
if (rcpt->status != 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) {
|
||||
if (status == 0)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
rcpt->offset = 0;
|
||||
}
|
||||
rcpt->status = SMTP_RCPT_DROP;
|
||||
state->status |= status;
|
||||
}
|
||||
/* XXX This assumes no fall-back relay. */
|
||||
if (soft_error && request->hop_status == 0)
|
||||
request->hop_status = mystrdup(vstring_str(why));
|
||||
state->final_server = 1;
|
||||
}
|
||||
smtp_check_code(state, code);
|
||||
|
||||
@ -243,36 +245,41 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
va_end(ap);
|
||||
|
||||
/*
|
||||
* Don't defer the recipients just yet when there are still more mail
|
||||
* servers. Just log something informative to show why we're skipping
|
||||
* this host.
|
||||
* Don't defer the recipients just yet when this error qualifies them for
|
||||
* delivery to a backup server. Just log something informative to show
|
||||
* why we're skipping this host.
|
||||
*/
|
||||
if (soft_error && state->final_server == 0) {
|
||||
if (soft_error && state->final_server == 0
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_MESSAGE_FAILURE)) {
|
||||
msg_info("%s: %s", request->queue_id, vstring_str(why));
|
||||
state->status |= -1;
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (rcpt->status != 0)
|
||||
continue;
|
||||
rcpt->status = SMTP_RCPT_KEEP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Defer or bounce all the remaining recipients and raise the final mail
|
||||
* server flag.
|
||||
* Defer or bounce all the remaining recipients, and delete them from the
|
||||
* delivery request. If a bounce fails, defer instead and do not qualify
|
||||
* the recipient for delivery to a backup server.
|
||||
*/
|
||||
else {
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (rcpt->offset == 0)
|
||||
if (rcpt->status != 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) {
|
||||
if (status == 0)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
rcpt->offset = 0;
|
||||
}
|
||||
rcpt->status = SMTP_RCPT_DROP;
|
||||
state->status |= status;
|
||||
}
|
||||
state->final_server = 1;
|
||||
}
|
||||
smtp_check_code(state, code);
|
||||
|
||||
@ -295,31 +302,29 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
|
||||
va_list ap;
|
||||
|
||||
/*
|
||||
* Don't defer this recipient record just yet when there are still more
|
||||
* mail servers. Just log something informative to show why we're
|
||||
* skipping this recipient now.
|
||||
* Don't defer this recipient record just yet when this error qualifies
|
||||
* for trying other mail servers. Just log something informative to show
|
||||
* why we're skipping this recipient now.
|
||||
*/
|
||||
if (soft_error && state->final_server == 0) {
|
||||
VSTRING *buf = vstring_alloc(10);
|
||||
if (soft_error && state->final_server == 0
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_RECIPIENT_FAILURE)) {
|
||||
VSTRING *buf = vstring_alloc(100);
|
||||
|
||||
va_start(ap, format);
|
||||
vstring_vsprintf(buf, format, ap);
|
||||
va_end(ap);
|
||||
msg_info("%s: %s", request->queue_id, vstring_str(buf));
|
||||
rcpt->status = SMTP_RCPT_KEEP;
|
||||
vstring_free(buf);
|
||||
status = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Defer or bounce this specific recipient.
|
||||
* Defer or bounce this recipient, and delete from the delivery request.
|
||||
* If the bounce fails, defer instead and do not qualify the recipient
|
||||
* for delivery to a backup server.
|
||||
*
|
||||
* If this is a hard error, we must not raise the final mail server flag. We
|
||||
* may still make another SMTP connection to deliver deferred recipients.
|
||||
*
|
||||
* If this is a soft error, we got here because the final mail server flag
|
||||
* was already set.
|
||||
*
|
||||
* So don't touch that final mail server flag!
|
||||
* Note: we may still make an SMTP connection to deliver other recipients
|
||||
* that did qualify for delivery to a backup server.
|
||||
*/
|
||||
else {
|
||||
va_start(ap, format);
|
||||
@ -328,13 +333,12 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
|
||||
rcpt->orig_addr, rcpt->address, rcpt->offset,
|
||||
session->namaddr, request->arrival_time, format, ap);
|
||||
va_end(ap);
|
||||
if (status == 0) {
|
||||
if (status == 0)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
rcpt->offset = 0;
|
||||
}
|
||||
rcpt->status = SMTP_RCPT_DROP;
|
||||
state->status |= status;
|
||||
}
|
||||
smtp_check_code(state, code);
|
||||
state->status |= status;
|
||||
}
|
||||
|
||||
/* smtp_stream_except - defer domain after I/O problem */
|
||||
@ -364,21 +368,29 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't defer the recipients just yet when there are still more mail
|
||||
* servers. Just log why we're abandoning this host.
|
||||
* Don't defer the recipients just yet when this error qualifies them for
|
||||
* delivery to a backup server. Just log something informative to show
|
||||
* why we're skipping this host.
|
||||
*/
|
||||
if (state->final_server == 0) {
|
||||
if (state->final_server == 0
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_SESSION_FAILURE)) {
|
||||
msg_info("%s: %s", request->queue_id, vstring_str(why));
|
||||
state->status |= -1;
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (rcpt->status != 0)
|
||||
continue;
|
||||
rcpt->status = SMTP_RCPT_KEEP;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Final server. Defer all the remaining recipients.
|
||||
* Defer all the remaining recipients and drop them from the delivery
|
||||
* request.
|
||||
*/
|
||||
else {
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (rcpt->offset == 0)
|
||||
if (rcpt->status != 0)
|
||||
continue;
|
||||
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||
request->queue_id,
|
||||
@ -386,6 +398,7 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
|
||||
rcpt->offset, session->namaddr,
|
||||
request->arrival_time,
|
||||
"%s", vstring_str(why));
|
||||
rcpt->status = SMTP_RCPT_DROP;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -875,6 +875,7 @@ extern int h_errno;
|
||||
#define STATVFS_IN_SYS_STATVFS_H
|
||||
#define UNIX_DOMAIN_CONNECT_BLOCKS_FOR_ACCEPT
|
||||
#define MISSING_SETENV
|
||||
#define STRCASECMP_IN_STRINGS_H
|
||||
/* SCO5 misses just S_ISSOCK, the others are there
|
||||
* Use C_ISSOCK definition from cpio.h.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user