mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-30 21:55:20 +00:00
postfix-2.0.16-20031221
This commit is contained in:
committed by
Viktor Dukhovni
parent
7011a3b3b6
commit
42f6ab4fc3
@@ -8871,13 +8871,18 @@ Apologies for any names omitted.
|
||||
between short queue ID and message status). File:
|
||||
showq/showq.c.
|
||||
|
||||
20031216-7
|
||||
20031216-20
|
||||
|
||||
Cleanup: the SMTP client now moves on to the next MX host
|
||||
or fallback relay when delivery fails in the middle of an
|
||||
SMTP session. This includes not only broken connections
|
||||
(easy) but also includes 4xx SMTP server replies (not easy).
|
||||
Files: smtp/smtp.c, smtp/smtp_connect.c, smtp_trouble.c.
|
||||
SMTP session. This includes both broken connections and
|
||||
4xx SMTP server replies. Files: smtp/smtp.c, smtp_rcpt.c,
|
||||
smtp/smtp_connect.c, smtp_trouble.c.
|
||||
|
||||
Configuration parameters: smtp_mx_address_limit (limit the
|
||||
list of IP addresses from MX lookup), and smtp_mx_session_limit
|
||||
(limit the number of actual SMTP sessions per delivery
|
||||
attempt, ignoring unusable MX IP addresses).
|
||||
|
||||
20031217
|
||||
|
||||
@@ -8949,7 +8954,7 @@ Open problems:
|
||||
|
||||
Low: postconf -e edits parameters that postconf won't list.
|
||||
|
||||
Low: while convering 8bit text to quoted-printable, perhaps
|
||||
Low: while converting 8bit text to quoted-printable, perhaps
|
||||
use =46rom instead of >From.
|
||||
|
||||
virtual_mailbox_path expression like forward_path, so that
|
||||
|
@@ -22,12 +22,13 @@ snapshot release). Patches change the patchlevel and the release
|
||||
date. Snapshots change only the release date, unless they include
|
||||
the same bugfixes as a patch release.
|
||||
|
||||
Major changes with Postfix snapshot 2.0.16-20031217
|
||||
Major changes with Postfix snapshot 2.0.16-20031221
|
||||
===================================================
|
||||
|
||||
The SMTP client now moves on to the next MX host (or fallback relay)
|
||||
when delivery fails in the middle of a session. This includes both
|
||||
broken connections as well as 4XX replies to SMTP commands.
|
||||
broken connections as well as 4XX replies to SMTP commands. Finally,
|
||||
fallback_relay works as expected.
|
||||
|
||||
Incompatible changes with Postfix snapshot 2.0.16-20031215
|
||||
==========================================================
|
||||
|
@@ -76,6 +76,23 @@ smtp_never_send_ehlo = no
|
||||
#
|
||||
smtp_defer_if_no_mx_address_found = no
|
||||
|
||||
# The smtp_mx_address_limit parameter limits the number of MX (mail
|
||||
# exchanger) IP addresses that can result from DNS or host lookups.
|
||||
#
|
||||
# Specify zero to disable the limit. This is also the default.
|
||||
#
|
||||
smtp_mx_address_limit = 0
|
||||
|
||||
# The smtp_mx_session_limit parameter limits the number of SMTP
|
||||
# sessions that the client will engage in, skipping over MX IP
|
||||
# addresses that fail to complete the SMTP initial handshake.
|
||||
#
|
||||
# By default, Postfix SMTP client gives up after two SMTP sessions.
|
||||
#
|
||||
# Specify zero to disable the limit.
|
||||
#
|
||||
smtp_mx_session_limit = 2
|
||||
|
||||
# The smtp_send_xforward_command parameter controls whether the Postfix
|
||||
# SMTP client will send an XFORWARD command to the SMTP server, when
|
||||
# the ESMTP HELO response of the remote host indicates XFORWARD support.
|
||||
|
@@ -244,29 +244,22 @@ SMTP(8) SMTP(8)
|
||||
|
||||
<b>smtp_mx_address_limit</b>
|
||||
An upper bound on the number of MX (mail exchanger)
|
||||
IP addresses that the SMTP client will try to con-
|
||||
nect to, before giving up or sending the mail to a
|
||||
fall-back relay host.
|
||||
IP addresses that that can result from DNS or host
|
||||
lookups.
|
||||
|
||||
Specify zero to disable the limit.
|
||||
|
||||
Note: by default, equal preference MX addresses are
|
||||
sorted into random order.
|
||||
|
||||
<b>smtp_mx_session_limit</b>
|
||||
An upper bound on the number of SMTP sessions that
|
||||
the SMTP client will engage in before giving up or
|
||||
sending the mail to a fall-back relay host.
|
||||
the SMTP client will engage in per message delivery
|
||||
(ignoring MX IP addresses that fail to complete the
|
||||
SMTP initial handshake).
|
||||
|
||||
Specify zero to disable the limit.
|
||||
|
||||
<b>smtp_backup_on_soft_error</b>
|
||||
The types of recoverable error that qualify for
|
||||
sending a recipient to a backup mail server or to a
|
||||
fall-back relay host. Specify zero or more of <b>ses-</b>
|
||||
<b>sion</b> (SMTP handshake failure, connection loss),
|
||||
<b>message</b> (failure of MAIL FROM, DATA or "."), or
|
||||
<b>recipient</b> (failure of RCPT TO).
|
||||
|
||||
Recipients that do not qualify are deferred.
|
||||
|
||||
<b>Timeout controls</b>
|
||||
The default time unit is seconds; an explicit time unit
|
||||
can be specified by appending a one-letter suffix to the
|
||||
|
@@ -205,24 +205,18 @@ The default limit is taken from the
|
||||
\fBdefault_destination_recipient_limit\fR parameter.
|
||||
.IP \fBsmtp_mx_address_limit\fR
|
||||
An upper bound on the number of MX (mail exchanger) IP addresses
|
||||
that the SMTP client will try to connect to, before giving up or
|
||||
sending the mail to a fall-back relay host.
|
||||
that that can result from DNS or host lookups.
|
||||
.sp
|
||||
Specify zero to disable the limit.
|
||||
.sp
|
||||
Note: by default, equal preference MX addresses are sorted into
|
||||
random order.
|
||||
.IP \fBsmtp_mx_session_limit\fR
|
||||
An upper bound on the number of SMTP sessions that the SMTP client
|
||||
will engage in before giving up or sending the mail to a fall-back
|
||||
relay host.
|
||||
An upper bound on the number of SMTP sessions that the SMTP
|
||||
client will engage in per message delivery (ignoring MX IP
|
||||
addresses that fail to complete the SMTP initial handshake).
|
||||
.sp
|
||||
Specify zero to disable the limit.
|
||||
.IP \fBsmtp_backup_on_soft_error\fR
|
||||
The types of recoverable error that qualify for sending a
|
||||
recipient to a backup mail server or to a fall-back relay host.
|
||||
Specify zero or more of \fBsession\fR (SMTP handshake failure,
|
||||
connection loss), \fBmessage\fR (failure of MAIL FROM, DATA or
|
||||
"."), or \fBrecipient\fR (failure of RCPT TO).
|
||||
.sp
|
||||
Recipients that do not qualify are deferred.
|
||||
.SH "Timeout controls"
|
||||
.ad
|
||||
.fi
|
||||
|
@@ -180,15 +180,6 @@ 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
|
||||
|
||||
#define VAR_SMTP_MXADDR_LIMIT "smtp_mx_address_limit"
|
||||
#define DEF_SMTP_MXADDR_LIMIT 0
|
||||
extern int var_smtp_mxaddr_limit;
|
||||
|
@@ -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 "20031220"
|
||||
#define MAIL_RELEASE_DATE "20031221"
|
||||
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE
|
||||
|
@@ -1,113 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* peer_name 3
|
||||
/* SUMMARY
|
||||
/* produce printable peer name and address
|
||||
/* SYNOPSIS
|
||||
/* #include <peer_name.h>
|
||||
/*
|
||||
/* typedef struct {
|
||||
/* .in +4
|
||||
/* int type;
|
||||
/* char name;
|
||||
/* char addr;
|
||||
/* .in -4
|
||||
/* } PEER_NAME;
|
||||
/*
|
||||
/* PEER_NAME *peer_name(sock)
|
||||
/* int sock;
|
||||
/* DESCRIPTION
|
||||
/* The \fIpeer_name\fR() routine attempts to produce a printable
|
||||
/* version of the peer name and address of the specified socket.
|
||||
/* The result is in static memory that will be overwritten.
|
||||
/* Make a copy if the result is to be used for an appreciable
|
||||
/* amount of time.
|
||||
/*
|
||||
/* Where information is unavailable, the name and/or address
|
||||
/* are set to "unknown".
|
||||
/* The \fItype\fR result field specifies how the name and address
|
||||
/* should be interpreted:
|
||||
/* .IP PEER_TYPE_INET
|
||||
/* The socket specifies a TCP/IP endpoint.
|
||||
/* The result is a hostname (from the DNS, a local hosts file or
|
||||
/* other); the address a dotted quad.
|
||||
/* .IP PEER_TYPE_LOCAL
|
||||
/* The socket argument specifies a local transport.
|
||||
/* The result name is "localhost"; the result address is "127.0.0.1".
|
||||
/* .IP PEER_TYPE_UNKNOWN
|
||||
/* The socket argument does not specify a socket.
|
||||
/* The result name is "localhost"; the result address is "127.0.0.1".
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <msg.h>
|
||||
#include <valid_hostname.h>
|
||||
#include <peer_name.h>
|
||||
|
||||
/* peer_name - produce printable peer name and address */
|
||||
|
||||
PEER_NAME *peer_name(int sock)
|
||||
{
|
||||
static PEER_NAME peer;
|
||||
struct sockaddr_in sin;
|
||||
SOCKADDR_SIZE len = sizeof(sin);
|
||||
struct hostent *hp;
|
||||
|
||||
if (getpeername(sock, (struct sockaddr *) & sin, &len) == 0) {
|
||||
switch (sin.sin_family) {
|
||||
case AF_INET:
|
||||
peer.type = PEER_TYPE_INET;
|
||||
hp = gethostbyaddr((char *) &(sin.sin_addr),
|
||||
sizeof(sin.sin_addr), AF_INET);
|
||||
peer.name = (hp && valid_hostname(hp->h_name, DO_GRIPE) ?
|
||||
hp->h_name : "unknown");
|
||||
peer.addr = inet_ntoa(sin.sin_addr);
|
||||
return (&peer);
|
||||
case AF_UNSPEC:
|
||||
case AF_UNIX:
|
||||
peer.type = PEER_TYPE_LOCAL;
|
||||
peer.name = "localhost";
|
||||
peer.addr = "127.0.0.1";
|
||||
return (&peer);
|
||||
}
|
||||
}
|
||||
peer.type = PEER_TYPE_UNKNOWN;
|
||||
peer.name = "localhost";
|
||||
peer.addr = "127.0.0.1";
|
||||
return (&peer);
|
||||
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int unused_argc, char **unused_argv)
|
||||
{
|
||||
PEER_NAME *peer;
|
||||
|
||||
peer = peer_name(STDIN_FILENO);
|
||||
msg_info("name %s addr %s", peer->name, peer->addr);
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,39 +0,0 @@
|
||||
#ifndef _PEER_NAME_H_INCLUDED_
|
||||
#define _PEER_NAME_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* peer_name 3h
|
||||
/* SUMMARY
|
||||
/* produce printable peer name and address
|
||||
/* SYNOPSIS
|
||||
/* #include <peer_name.h>
|
||||
/* DESCRIPTION
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
typedef struct {
|
||||
int type; /* IPC type, see below */
|
||||
char *name; /* peer official name */
|
||||
char *addr; /* peer address */
|
||||
} PEER_NAME;
|
||||
|
||||
#define PEER_TYPE_UNKNOWN 0
|
||||
#define PEER_TYPE_INET 1
|
||||
#define PEER_TYPE_LOCAL 2
|
||||
|
||||
extern PEER_NAME *peer_name(int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
#endif
|
@@ -31,9 +31,6 @@
|
||||
/* const char *orig_rcpt;
|
||||
/* const char *recipient;
|
||||
/*
|
||||
/* void recipient_list_truncate(list)
|
||||
/* RECIPIENT_LIST *list;
|
||||
/*
|
||||
/* void recipient_list_free(list)
|
||||
/* RECIPIENT_LIST *list;
|
||||
/* DESCRIPTION
|
||||
@@ -51,9 +48,6 @@
|
||||
/* 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.
|
||||
/*
|
||||
@@ -82,7 +76,6 @@
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <msg.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
@@ -121,27 +114,15 @@ void recipient_list_add(RECIPIENT_LIST *list, long offset,
|
||||
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)
|
||||
{
|
||||
if (list->len > 0)
|
||||
recipient_list_truncate(list, 0);
|
||||
RECIPIENT *rcpt;
|
||||
|
||||
for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) {
|
||||
myfree(rcpt->orig_addr);
|
||||
myfree(rcpt->address);
|
||||
}
|
||||
myfree((char *) list->info);
|
||||
}
|
||||
|
@@ -32,7 +32,6 @@ 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
|
||||
|
@@ -146,6 +146,7 @@ lmtp_proto.o: ../../include/vstream.h
|
||||
lmtp_proto.o: ../../include/vstring_vstream.h
|
||||
lmtp_proto.o: ../../include/stringops.h
|
||||
lmtp_proto.o: ../../include/mymalloc.h
|
||||
lmtp_proto.o: ../../include/name_code.h
|
||||
lmtp_proto.o: ../../include/mail_params.h
|
||||
lmtp_proto.o: ../../include/smtp_stream.h
|
||||
lmtp_proto.o: ../../include/mail_queue.h
|
||||
|
@@ -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_misc.c \
|
||||
smtp_addr.c smtp_trouble.c smtp_state.c smtp_rcpt.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_misc.o \
|
||||
smtp_addr.o smtp_trouble.o smtp_state.o smtp_rcpt.o \
|
||||
smtp_sasl_proto.o smtp_sasl_glue.o
|
||||
HDRS = smtp.h smtp_sasl.h
|
||||
TESTSRC =
|
||||
@@ -144,18 +144,6 @@ smtp_connect.o: ../../include/dns.h
|
||||
smtp_connect.o: smtp.h
|
||||
smtp_connect.o: ../../include/argv.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
|
||||
@@ -188,6 +176,18 @@ smtp_proto.o: ../../include/header_opts.h
|
||||
smtp_proto.o: smtp.h
|
||||
smtp_proto.o: ../../include/argv.h
|
||||
smtp_proto.o: smtp_sasl.h
|
||||
smtp_rcpt.o: smtp_rcpt.c
|
||||
smtp_rcpt.o: ../../include/sys_defs.h
|
||||
smtp_rcpt.o: ../../include/msg.h
|
||||
smtp_rcpt.o: ../../include/deliver_request.h
|
||||
smtp_rcpt.o: ../../include/vstring.h
|
||||
smtp_rcpt.o: ../../include/vbuf.h
|
||||
smtp_rcpt.o: ../../include/vstream.h
|
||||
smtp_rcpt.o: ../../include/recipient_list.h
|
||||
smtp_rcpt.o: ../../include/deliver_completed.h
|
||||
smtp_rcpt.o: ../../include/sent.h
|
||||
smtp_rcpt.o: smtp.h
|
||||
smtp_rcpt.o: ../../include/argv.h
|
||||
smtp_sasl_glue.o: smtp_sasl_glue.c
|
||||
smtp_sasl_glue.o: ../../include/sys_defs.h
|
||||
smtp_sasl_glue.o: ../../include/msg.h
|
||||
|
@@ -189,24 +189,18 @@
|
||||
/* \fBdefault_destination_recipient_limit\fR parameter.
|
||||
/* .IP \fBsmtp_mx_address_limit\fR
|
||||
/* An upper bound on the number of MX (mail exchanger) IP addresses
|
||||
/* that the SMTP client will try to connect to, before giving up or
|
||||
/* sending the mail to a fall-back relay host.
|
||||
/* that that can result from DNS or host lookups.
|
||||
/* .sp
|
||||
/* Specify zero to disable the limit.
|
||||
/* .sp
|
||||
/* Note: by default, equal preference MX addresses are sorted into
|
||||
/* random order.
|
||||
/* .IP \fBsmtp_mx_session_limit\fR
|
||||
/* An upper bound on the number of SMTP sessions that the SMTP client
|
||||
/* will engage in before giving up or sending the mail to a fall-back
|
||||
/* relay host.
|
||||
/* An upper bound on the number of SMTP sessions that the SMTP
|
||||
/* client will engage in per message delivery (ignoring MX IP
|
||||
/* addresses that fail to complete the SMTP initial handshake).
|
||||
/* .sp
|
||||
/* Specify zero to disable the limit.
|
||||
/* .IP \fBsmtp_backup_on_soft_error\fR
|
||||
/* The types of recoverable error that qualify for sending a
|
||||
/* recipient to a backup mail server or to a fall-back relay host.
|
||||
/* Specify zero or more of \fBsession\fR (SMTP handshake failure,
|
||||
/* connection loss), \fBmessage\fR (failure of MAIL FROM, DATA or
|
||||
/* "."), or \fBrecipient\fR (failure of RCPT TO).
|
||||
/* .sp
|
||||
/* Recipients that do not qualify are deferred.
|
||||
/* .SH "Timeout controls"
|
||||
/* .ad
|
||||
/* .fi
|
||||
@@ -332,7 +326,6 @@ 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;
|
||||
@@ -345,7 +338,6 @@ int var_smtp_mxsess_limit;
|
||||
*/
|
||||
int smtp_errno;
|
||||
int smtp_host_lookup_mask;
|
||||
int smtp_backup_mask;
|
||||
|
||||
/* deliver_message - deliver message with extreme prejudice */
|
||||
|
||||
@@ -375,6 +367,7 @@ static int deliver_message(DELIVER_REQUEST *request)
|
||||
state = smtp_state_alloc();
|
||||
state->request = request;
|
||||
state->src = request->fp;
|
||||
SMTP_RCPT_INIT(state);
|
||||
|
||||
/*
|
||||
* Establish an SMTP session and deliver this message to all requested
|
||||
@@ -420,21 +413,15 @@ static void smtp_service(VSTREAM *client_stream, char *unused_service, char **ar
|
||||
}
|
||||
}
|
||||
|
||||
/* post_init - post-jail initialization */
|
||||
/* pre_init - pre-jail initialization */
|
||||
|
||||
static void post_init(char *unused_name, char **unused_argv)
|
||||
static void pre_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.
|
||||
@@ -454,23 +441,6 @@ static void post_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.
|
||||
*/
|
||||
@@ -519,7 +489,6 @@ 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[] = {
|
||||
@@ -564,7 +533,6 @@ 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);
|
||||
|
@@ -62,8 +62,9 @@ typedef struct SMTP_STATE {
|
||||
* session all recipients should be marked one way or the other.
|
||||
*/
|
||||
int final_server; /* final mail server */
|
||||
int drop_count; /* recipients marked as drop */
|
||||
int keep_count; /* recipients marked as keep */
|
||||
int rcpt_left; /* recipients left over */
|
||||
int rcpt_drop; /* recipients marked as drop */
|
||||
int rcpt_keep; /* recipients marked as keep */
|
||||
} SMTP_STATE;
|
||||
|
||||
/*
|
||||
@@ -81,47 +82,11 @@ typedef struct SMTP_STATE {
|
||||
#define SMTP_FEATURE_XFORWARD_PROTO (1<<9)
|
||||
#define SMTP_FEATURE_XFORWARD_HELO (1<<10)
|
||||
|
||||
/*
|
||||
* Application-specific per-recipient status. At the end of each delivery
|
||||
* attempt each recipient is marked as DROP (remove from recipient list) or
|
||||
* KEEP (deliver to backup mail server). The ones marked DROP are deleted
|
||||
* before trying to deliver the remainder to a backup server. There's a bit
|
||||
* of redundcancy to ensure that all recipients are marked.
|
||||
*
|
||||
* The single recipient list abstraction dates from the time that the SMTP
|
||||
* client would give up after one SMTP session, so that each recipient was
|
||||
* either bounced, delivered or deferred. Implicitly, all recipients were
|
||||
* marked as DROP.
|
||||
*
|
||||
* This abstraction is less convenient when an SMTP client must be able to
|
||||
* deliver left-over recipients to a backup host. It might be more natural
|
||||
* to have an input list with recipients to deliver, and an output list with
|
||||
* the left-over recipients.
|
||||
*/
|
||||
#define SMTP_RCPT_KEEP 1 /* send to backup host */
|
||||
#define SMTP_RCPT_DROP 2 /* remove from request */
|
||||
|
||||
#define SMTP_RCPT_MARK_INIT(state) do { \
|
||||
(state)->drop_count = (state)->keep_count = 0; \
|
||||
} while (0)
|
||||
|
||||
#define SMTP_RCPT_MARK_DROP(state, rcpt) do { \
|
||||
(rcpt)->status = SMTP_RCPT_DROP; (state)->drop_count++; \
|
||||
} while (0)
|
||||
|
||||
#define SMTP_RCPT_MARK_KEEP(state, rcpt) do { \
|
||||
(rcpt)->status = SMTP_RCPT_KEEP; (state)->keep_count++; \
|
||||
} while (0)
|
||||
|
||||
#define SMTP_RCPT_MARK_ISSET(rcpt) ((rcpt)->status != 0)
|
||||
|
||||
extern int smtp_rcpt_mark_finish(SMTP_STATE *);
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
@@ -182,8 +147,29 @@ extern void smtp_chat_reset(SMTP_STATE *);
|
||||
extern void smtp_chat_notify(SMTP_STATE *);
|
||||
|
||||
/*
|
||||
* smtp_misc.c.
|
||||
* These operations are extensively documented in smtp_rcpt.c
|
||||
*/
|
||||
#define SMTP_RCPT_STATE_KEEP 1 /* send to backup host */
|
||||
#define SMTP_RCPT_STATE_DROP 2 /* remove from request */
|
||||
|
||||
#define SMTP_RCPT_INIT(state) do { \
|
||||
(state)->rcpt_drop = (state)->rcpt_keep = 0; \
|
||||
(state)->rcpt_left = state->request->rcpt_list.len; \
|
||||
} while (0)
|
||||
|
||||
#define SMTP_RCPT_DROP(state, rcpt) do { \
|
||||
(rcpt)->status = SMTP_RCPT_STATE_DROP; (state)->rcpt_drop++; \
|
||||
} while (0)
|
||||
|
||||
#define SMTP_RCPT_KEEP(state, rcpt) do { \
|
||||
(rcpt)->status = SMTP_RCPT_STATE_KEEP; (state)->rcpt_keep++; \
|
||||
} while (0)
|
||||
|
||||
#define SMTP_RCPT_ISMARKED(rcpt) ((rcpt)->status != 0)
|
||||
|
||||
#define SMTP_RCPT_LEFT(state) (state)->rcpt_left
|
||||
|
||||
extern void smtp_rcpt_cleanup(SMTP_STATE *);
|
||||
extern void smtp_rcpt_done(SMTP_STATE *, const char *, RECIPIENT *);
|
||||
|
||||
/*
|
||||
|
@@ -316,7 +316,7 @@ int smtp_connect(SMTP_STATE *state)
|
||||
* then is to build this into the pre-existing SMTP client without
|
||||
* getting lost in the complexity.
|
||||
*/
|
||||
for (cpp = sites->argv; (dest = *cpp) != 0; cpp++) {
|
||||
for (cpp = sites->argv; SMTP_RCPT_LEFT(state) > 0 && (dest = *cpp) != 0; cpp++) {
|
||||
state->final_server = (cpp[1] == 0);
|
||||
smtp_errno = SMTP_NONE;
|
||||
|
||||
@@ -359,14 +359,14 @@ int smtp_connect(SMTP_STATE *state)
|
||||
* list. Unmark any left-over recipients and try to deliver them to a
|
||||
* backup mail server.
|
||||
*/
|
||||
for (sess_count = addr_count = 0, addr = addr_list; addr; addr = next) {
|
||||
sess_count = addr_count = 0;
|
||||
for (addr = addr_list; SMTP_RCPT_LEFT(state) > 0 && addr; addr = next) {
|
||||
next = addr->next;
|
||||
if (++addr_count == var_smtp_mxaddr_limit)
|
||||
next = 0;
|
||||
if ((state->session = smtp_connect_addr(addr, port, why)) != 0) {
|
||||
if (++sess_count == var_smtp_mxsess_limit)
|
||||
next = 0;
|
||||
SMTP_RCPT_MARK_INIT(state);
|
||||
state->final_server = (cpp[1] == 0 && next == 0);
|
||||
state->session->best = (addr->pref == addr_list->pref);
|
||||
debug_peer_check(state->session->host, state->session->addr);
|
||||
@@ -379,8 +379,7 @@ 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 (smtp_rcpt_mark_finish(state) == 0)
|
||||
break;
|
||||
smtp_rcpt_cleanup(state);
|
||||
} else {
|
||||
msg_info("%s (port %d)", vstring_str(why), ntohs(port));
|
||||
}
|
||||
@@ -395,7 +394,7 @@ int smtp_connect(SMTP_STATE *state)
|
||||
* 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_RCPT_LEFT(state) > 0) {
|
||||
switch (smtp_errno) {
|
||||
|
||||
default:
|
||||
@@ -430,6 +429,7 @@ int smtp_connect(SMTP_STATE *state)
|
||||
state->status = deliver_pass_all(MAIL_CLASS_PRIVATE,
|
||||
var_bestmx_transp,
|
||||
request);
|
||||
SMTP_RCPT_LEFT(state) = 0; /* XXX */
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
@@ -440,9 +440,16 @@ int smtp_connect(SMTP_STATE *state)
|
||||
* We still need to bounce or defer some left-over recipients:
|
||||
* either mail loops or some backup mail server was unavailable.
|
||||
*/
|
||||
state->final_server = 1;
|
||||
smtp_site_fail(state, smtp_errno == SMTP_RETRY ? 450 : 550,
|
||||
"%s", vstring_str(why));
|
||||
break;
|
||||
|
||||
/*
|
||||
* Sanity check. Don't silently lose recipients.
|
||||
*/
|
||||
smtp_rcpt_cleanup(state);
|
||||
if (SMTP_RCPT_LEFT(state) > 0)
|
||||
msg_panic("smtp_connect: left-over recipients");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,124 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* smtp_misc 3
|
||||
/* SUMMARY
|
||||
/* assorted routines
|
||||
/* SYNOPSIS
|
||||
/* #include <smtp.h>
|
||||
/*
|
||||
/* void smtp_rcpt_done(state, reply, rcpt)
|
||||
/* SMTP_STATE *state;
|
||||
/* const char *reply;
|
||||
/* RECIPIENT *rcpt;
|
||||
/*
|
||||
/* int smtp_rcpt_mark_finish(SMTP_STATE *state)
|
||||
/* SMTP_STATE *state;
|
||||
/* DESCRIPTION
|
||||
/* smtp_rcpt_done() logs that a recipient is completed and upon
|
||||
/* success it marks the recipient as done in the queue file.
|
||||
/* Finally, it marks the in-memory recipient as DROP.
|
||||
/*
|
||||
/* smtp_rcpt_mark_finish() cleans up the in-memory recipient list.
|
||||
/* It deletes recipients marked DROP, and unmarks recipients marked KEEP.
|
||||
/* It enforces the requirement that all recipients are marked one way
|
||||
/* or the other. The result value is the number of left-over recipients.
|
||||
/* DIAGNOSTICS
|
||||
/* Panic: interface violation.
|
||||
/*
|
||||
/* When a recipient can't be logged as completed, the recipient is
|
||||
/* logged as deferred instead.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <stdlib.h> /* smtp_rcpt_mark_finish */
|
||||
|
||||
/* 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);
|
||||
SMTP_RCPT_MARK_DROP(state, rcpt);
|
||||
state->status |= status;
|
||||
}
|
||||
|
||||
/* smtp_rcpt_mark_finish_callback - qsort callback */
|
||||
|
||||
static int smtp_rcpt_mark_finish_callback(const void *a, const void *b)
|
||||
{
|
||||
return (((RECIPIENT *) a)->status - ((RECIPIENT *) b)->status);
|
||||
}
|
||||
|
||||
/* smtp_rcpt_mark_finish - purge completed recipients from request */
|
||||
|
||||
int smtp_rcpt_mark_finish(SMTP_STATE *state)
|
||||
{
|
||||
RECIPIENT_LIST *rcpt_list = &state->request->rcpt_list;
|
||||
RECIPIENT *rcpt;
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (state->drop_count + state->keep_count != rcpt_list->len)
|
||||
msg_panic("smtp_rcpt_mark_finish: recipient count mismatch: %d+%d!=%d",
|
||||
state->drop_count, state->keep_count, rcpt_list->len);
|
||||
|
||||
/*
|
||||
* Recipients marked KEEP sort before recipients marked DROP. Skip the
|
||||
* sorting in the common case that all recipients are marked the same.
|
||||
*/
|
||||
if (state->drop_count > 0 && state->keep_count > 0)
|
||||
qsort((void *) rcpt_list->info, rcpt_list->len,
|
||||
sizeof(rcpt_list->info), smtp_rcpt_mark_finish_callback);
|
||||
|
||||
/*
|
||||
* Truncate the recipient list and unmark the left-over recipients so
|
||||
* that the result looks like a brand-new recipient list.
|
||||
*/
|
||||
if (state->keep_count < rcpt_list->len)
|
||||
recipient_list_truncate(rcpt_list, state->keep_count);
|
||||
for (rcpt = rcpt_list->info; rcpt < rcpt_list->info + rcpt_list->len; rcpt++)
|
||||
rcpt->status = 0;
|
||||
|
||||
return (rcpt_list->len);
|
||||
}
|
@@ -434,10 +434,10 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
/*
|
||||
* Sanity check. Recipients should be unmarked at this point.
|
||||
*/
|
||||
if (request->rcpt_list.len <= 0)
|
||||
if (SMTP_RCPT_LEFT(state) <= 0)
|
||||
msg_panic("smtp_xfer: bad recipient count: %d",
|
||||
request->rcpt_list.len);
|
||||
if (SMTP_RCPT_MARK_ISSET(request->rcpt_list.info))
|
||||
SMTP_RCPT_LEFT(state));
|
||||
if (SMTP_RCPT_ISMARKED(request->rcpt_list.info))
|
||||
msg_panic("smtp_xfer: bad recipient status: %d",
|
||||
request->rcpt_list.info->status);
|
||||
|
||||
@@ -616,7 +616,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
QUOTE_ADDRESS(state->scratch, rcpt->address);
|
||||
vstring_sprintf(next_command, "RCPT TO:<%s>",
|
||||
vstring_str(state->scratch));
|
||||
if ((next_rcpt = send_rcpt + 1) == request->rcpt_list.len)
|
||||
if ((next_rcpt = send_rcpt + 1) == SMTP_RCPT_LEFT(state))
|
||||
next_state = DEL_REQ_TRACE_ONLY(request->flags) ?
|
||||
SMTP_STATE_ABORT : SMTP_STATE_DATA;
|
||||
break;
|
||||
@@ -779,7 +779,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
}
|
||||
}
|
||||
/* If trace-only, send RSET instead of DATA. */
|
||||
if (++recv_rcpt == request->rcpt_list.len)
|
||||
if (++recv_rcpt == SMTP_RCPT_LEFT(state))
|
||||
recv_state = DEL_REQ_TRACE_ONLY(request->flags) ?
|
||||
SMTP_STATE_ABORT : SMTP_STATE_DATA;
|
||||
break;
|
||||
@@ -822,7 +822,7 @@ int smtp_xfer(SMTP_STATE *state)
|
||||
} else {
|
||||
for (nrcpt = 0; nrcpt < recv_rcpt; nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (!SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (!SMTP_RCPT_ISMARKED(rcpt))
|
||||
smtp_rcpt_done(state, resp->str, rcpt);
|
||||
}
|
||||
}
|
||||
|
182
postfix/src/smtp/smtp_rcpt.c
Normal file
182
postfix/src/smtp/smtp_rcpt.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* smtp_rcpt 3
|
||||
/* SUMMARY
|
||||
/* application-specific recipient list operations
|
||||
/* SYNOPSIS
|
||||
/* #include <smtp.h>
|
||||
/*
|
||||
/* SMTP_RCPT_INIT(state)
|
||||
/* SMTP_STATE *state;
|
||||
/*
|
||||
/* SMTP_RCPT_DROP(state, rcpt)
|
||||
/* SMTP_STATE *state;
|
||||
/* RECIPIENT *rcpt;
|
||||
/*
|
||||
/* SMTP_RCPT_KEEP(state, rcpt)
|
||||
/* SMTP_STATE *state;
|
||||
/* RECIPIENT *rcpt;
|
||||
/*
|
||||
/* SMTP_RCPT_ISMARKED(rcpt)
|
||||
/* RECIPIENT *rcpt;
|
||||
/*
|
||||
/* void smtp_rcpt_cleanup(SMTP_STATE *state)
|
||||
/* SMTP_STATE *state;
|
||||
/*
|
||||
/* int SMTP_RCPT_LEFT(state)
|
||||
/* SMTP_STATE *state;
|
||||
/*
|
||||
/* void smtp_rcpt_done(state, reply, rcpt)
|
||||
/* SMTP_STATE *state;
|
||||
/* const char *reply;
|
||||
/* RECIPIENT *rcpt;
|
||||
/* DESCRIPTION
|
||||
/* This module implements application-specific mark and sweep
|
||||
/* operations on recipient lists. Operation is as follows:
|
||||
/* .IP \(bu
|
||||
/* In the course of a delivery attempt each recipient is
|
||||
/* marked either as DROP (remove from recipient list) or KEEP
|
||||
/* (deliver to backup mail server).
|
||||
/* .IP \(bu
|
||||
/* After a delivery attempt any recipients marked DROP are deleted
|
||||
/* from the request, and the left-over recipients are unmarked.
|
||||
/* .PP
|
||||
/* Operations with upper case names are implemented by macros
|
||||
/* whose arguments may be evaluated more than once.
|
||||
/*
|
||||
/* SMTP_RCPT_INIT() initializes application-specific recipient
|
||||
/* information and must be called before the first delivery attempt.
|
||||
/*
|
||||
/* SMTP_RCPT_DROP() marks the specified recipient as DROP (remove
|
||||
/* from recipient list). It is an error to mark an already marked
|
||||
/* recipient.
|
||||
/*
|
||||
/* SMTP_RCPT_KEEP() marks the specified recipient as KEEP (deliver
|
||||
/* to alternate mail server). It is an error to mark an already
|
||||
/* marked recipient.
|
||||
/*
|
||||
/* SMTP_RCPT_ISMARKED() returns non-zero when the specified
|
||||
/* recipient is marked.
|
||||
/*
|
||||
/* SMTP_RCPT_LEFT() returns the number of left_over recipients
|
||||
/* (the total number of marked and non-marked recipients).
|
||||
/*
|
||||
/* smtp_rcpt_cleanup() cleans up the in-memory recipient list.
|
||||
/* It removes the recipients marked DROP from the left-over
|
||||
/* recipients, unmarks the left-over recipients, and enforces
|
||||
/* the requirement that all recipients are marked upon entry.
|
||||
/*
|
||||
/* smtp_rcpt_done() logs that a recipient is completed and upon
|
||||
/* success it marks the recipient as done in the queue file.
|
||||
/* Finally, it marks the in-memory recipient as DROP.
|
||||
/*
|
||||
/* Note: smtp_rcpt_done() may change the order of the recipient
|
||||
/* list.
|
||||
/* DIAGNOSTICS
|
||||
/* Panic: interface violation.
|
||||
/*
|
||||
/* When a recipient can't be logged as completed, the recipient is
|
||||
/* logged as deferred instead.
|
||||
/* BUGS
|
||||
/* The single recipient list abstraction dates from the time
|
||||
/* that the SMTP client would give up after one SMTP session,
|
||||
/* so that each recipient was either bounced, delivered or
|
||||
/* deferred. Implicitly, all recipients were marked as DROP.
|
||||
/*
|
||||
/* This abstraction is less convenient when an SMTP client
|
||||
/* must be able to deliver left-over recipients to a backup
|
||||
/* host. It might be more natural to have an input list with
|
||||
/* recipients to deliver, and an output list with left-over
|
||||
/* recipients.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <stdlib.h> /* smtp_rcpt_cleanup */
|
||||
|
||||
/* 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);
|
||||
SMTP_RCPT_DROP(state, rcpt);
|
||||
state->status |= status;
|
||||
}
|
||||
|
||||
/* smtp_rcpt_cleanup_callback - qsort callback */
|
||||
|
||||
static int smtp_rcpt_cleanup_callback(const void *a, const void *b)
|
||||
{
|
||||
return (((RECIPIENT *) a)->status - ((RECIPIENT *) b)->status);
|
||||
}
|
||||
|
||||
/* smtp_rcpt_cleanup - purge completed recipients from request */
|
||||
|
||||
void smtp_rcpt_cleanup(SMTP_STATE *state)
|
||||
{
|
||||
RECIPIENT_LIST *rcpt_list = &state->request->rcpt_list;
|
||||
RECIPIENT *rcpt;
|
||||
|
||||
/*
|
||||
* Sanity checks.
|
||||
*/
|
||||
if (state->rcpt_drop + state->rcpt_keep != state->rcpt_left)
|
||||
msg_panic("smtp_rcpt_cleanup: recipient count mismatch: %d+%d!=%d",
|
||||
state->rcpt_drop, state->rcpt_keep, state->rcpt_left);
|
||||
|
||||
/*
|
||||
* Recipients marked KEEP sort before recipients marked DROP. Skip the
|
||||
* sorting in the common case that all recipients are marked the same.
|
||||
*/
|
||||
if (state->rcpt_drop > 0 && state->rcpt_keep > 0)
|
||||
qsort((void *) rcpt_list->info, state->rcpt_left,
|
||||
sizeof(rcpt_list->info), smtp_rcpt_cleanup_callback);
|
||||
|
||||
/*
|
||||
* Truncate the recipient list and unmark the left-over recipients.
|
||||
*/
|
||||
state->rcpt_left = state->rcpt_keep;
|
||||
for (rcpt = rcpt_list->info; rcpt < rcpt_list->info + state->rcpt_left; rcpt++)
|
||||
rcpt->status = 0;
|
||||
state->rcpt_drop = state->rcpt_keep = 0;
|
||||
}
|
@@ -34,7 +34,7 @@
|
||||
/* 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. In any case, the recipient is marked as either KEEP
|
||||
/* (try again with a backup host) or DROP (delete recipient from
|
||||
/* (try again with a backup host) or DROP (delete recipient from
|
||||
/* delivery request).
|
||||
/*
|
||||
/* In addition, when an unexpected response code is seen such
|
||||
@@ -47,7 +47,7 @@
|
||||
/*
|
||||
/* 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
|
||||
/* an informational record only and try a backup server) or
|
||||
/* whether this is the final server (log recipient delivery status
|
||||
/* records and delete the recipient from the request).
|
||||
/*
|
||||
@@ -59,7 +59,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 and mark the destination
|
||||
/* a problematic; hard error: bounce all remaining recipients.
|
||||
/* as problematic; hard error: bounce all remaining recipients.
|
||||
/* The result is non-zero.
|
||||
/*
|
||||
/* smtp_mesg_fail() handles the case where the smtp server
|
||||
@@ -180,14 +180,13 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
* delivery to a backup server. Just log something informative to show
|
||||
* why we're skipping this host.
|
||||
*/
|
||||
if (soft_error && state->final_server == 0
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_SESSION_FAILURE)) {
|
||||
if (soft_error && state->final_server == 0) {
|
||||
msg_info("%s: %s", request->queue_id, vstring_str(why));
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (SMTP_RCPT_ISMARKED(rcpt))
|
||||
continue;
|
||||
SMTP_RCPT_MARK_KEEP(state, rcpt);
|
||||
SMTP_RCPT_KEEP(state, rcpt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,9 +196,9 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
* the recipient for delivery to a backup server.
|
||||
*/
|
||||
else {
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (SMTP_RCPT_ISMARKED(rcpt))
|
||||
continue;
|
||||
status = (soft_error ? defer_append : bounce_append)
|
||||
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
||||
@@ -208,7 +207,7 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
request->arrival_time, "%s", vstring_str(why));
|
||||
if (status == 0)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
SMTP_RCPT_MARK_DROP(state, rcpt);
|
||||
SMTP_RCPT_DROP(state, rcpt);
|
||||
state->status |= status;
|
||||
}
|
||||
/* XXX This assumes no fall-back relay. */
|
||||
@@ -249,14 +248,13 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
* delivery to a backup server. Just log something informative to show
|
||||
* why we're skipping this host.
|
||||
*/
|
||||
if (soft_error && state->final_server == 0
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_MESSAGE_FAILURE)) {
|
||||
if (soft_error && state->final_server == 0) {
|
||||
msg_info("%s: %s", request->queue_id, vstring_str(why));
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (SMTP_RCPT_ISMARKED(rcpt))
|
||||
continue;
|
||||
SMTP_RCPT_MARK_KEEP(state, rcpt);
|
||||
SMTP_RCPT_KEEP(state, rcpt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,9 +264,9 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
* the recipient for delivery to a backup server.
|
||||
*/
|
||||
else {
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (SMTP_RCPT_ISMARKED(rcpt))
|
||||
continue;
|
||||
status = (soft_error ? defer_append : bounce_append)
|
||||
(DEL_REQ_TRACE_FLAGS(request->flags), request->queue_id,
|
||||
@@ -277,7 +275,7 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
|
||||
"%s", vstring_str(why));
|
||||
if (status == 0)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
SMTP_RCPT_MARK_DROP(state, rcpt);
|
||||
SMTP_RCPT_DROP(state, rcpt);
|
||||
state->status |= status;
|
||||
}
|
||||
}
|
||||
@@ -304,7 +302,7 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (SMTP_RCPT_ISMARKED(rcpt))
|
||||
msg_panic("smtp_rcpt_fail: recipient <%s> is marked", rcpt->address);
|
||||
|
||||
/*
|
||||
@@ -312,15 +310,14 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
|
||||
* 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
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_RECIPIENT_FAILURE)) {
|
||||
if (soft_error && state->final_server == 0) {
|
||||
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));
|
||||
SMTP_RCPT_MARK_KEEP(state, rcpt);
|
||||
SMTP_RCPT_KEEP(state, rcpt);
|
||||
vstring_free(buf);
|
||||
}
|
||||
|
||||
@@ -341,7 +338,7 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
|
||||
va_end(ap);
|
||||
if (status == 0)
|
||||
deliver_completed(state->src, rcpt->offset);
|
||||
SMTP_RCPT_MARK_DROP(state, rcpt);
|
||||
SMTP_RCPT_DROP(state, rcpt);
|
||||
state->status |= status;
|
||||
}
|
||||
smtp_check_code(state, code);
|
||||
@@ -378,14 +375,13 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
|
||||
* delivery to a backup server. Just log something informative to show
|
||||
* why we're skipping this host.
|
||||
*/
|
||||
if (state->final_server == 0
|
||||
&& (smtp_backup_mask & SMTP_BACKUP_SESSION_FAILURE)) {
|
||||
if (state->final_server == 0) {
|
||||
msg_info("%s: %s", request->queue_id, vstring_str(why));
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (SMTP_RCPT_ISMARKED(rcpt))
|
||||
continue;
|
||||
SMTP_RCPT_MARK_KEEP(state, rcpt);
|
||||
SMTP_RCPT_KEEP(state, rcpt);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,9 +390,9 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
|
||||
* request.
|
||||
*/
|
||||
else {
|
||||
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
|
||||
for (nrcpt = 0; nrcpt < SMTP_RCPT_LEFT(state); nrcpt++) {
|
||||
rcpt = request->rcpt_list.info + nrcpt;
|
||||
if (SMTP_RCPT_MARK_ISSET(rcpt))
|
||||
if (SMTP_RCPT_ISMARKED(rcpt))
|
||||
continue;
|
||||
state->status |= defer_append(DEL_REQ_TRACE_FLAGS(request->flags),
|
||||
request->queue_id,
|
||||
@@ -404,7 +400,7 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
|
||||
rcpt->offset, session->namaddr,
|
||||
request->arrival_time,
|
||||
"%s", vstring_str(why));
|
||||
SMTP_RCPT_MARK_DROP(state, rcpt);
|
||||
SMTP_RCPT_DROP(state, rcpt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,94 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* smtpd_xclient 3
|
||||
/* SUMMARY
|
||||
/* maintain XCLIENT information
|
||||
/* SYNOPSIS
|
||||
/* #include "smtpd.h"
|
||||
/*
|
||||
/* void smtpd_xclient_init(state)
|
||||
/* SMTPD_STATE *state;
|
||||
/*
|
||||
/* void smtpd_xclient_reset(state)
|
||||
/* SMTPD_STATE *state;
|
||||
/* DESCRIPTION
|
||||
/* smtpd_xclient_init() zeroes the attributes for storage of XCLIENT
|
||||
/* FORWARD command parameters.
|
||||
/*
|
||||
/* smtpd_xclient_preset() takes the result from smtpd_xclient_init()
|
||||
/* and sets all fields to the same "unknown" value that regular
|
||||
/* client attributes would have.
|
||||
/*
|
||||
/* smtpd_xclient_reset() restores the state from smtpd_xclient_init().
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include <mymalloc.h>
|
||||
#include <msg.h>
|
||||
|
||||
/* Global library. */
|
||||
|
||||
#include <mail_proto.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include <smtpd.h>
|
||||
|
||||
/* smtpd_xclient_init - initialize XCLIENT attributes */
|
||||
|
||||
void smtpd_xclient_init(SMTPD_STATE *state)
|
||||
{
|
||||
state->xclient.used = 0;
|
||||
state->xclient.name = 0;
|
||||
state->xclient.addr = 0;
|
||||
state->xclient.namaddr = 0;
|
||||
state->xclient.peer_code = 0;
|
||||
state->xclient.protocol = 0;
|
||||
state->xclient.helo_name = 0;
|
||||
}
|
||||
|
||||
/* smtpd_xclient_preset - set xclient attributes to "unknown" */
|
||||
|
||||
void smtpd_xclient_preset(SMTPD_STATE *state)
|
||||
{
|
||||
|
||||
/*
|
||||
* This is a temporary solution. Unknown forwarded attributes get the
|
||||
* same values as unknown normal attributes, so that we don't break
|
||||
* assumptions in pre-existing code.
|
||||
*/
|
||||
state->xclient.used = 1;
|
||||
state->xclient.name = mystrdup(CLIENT_NAME_UNKNOWN);
|
||||
state->xclient.addr = mystrdup(CLIENT_ADDR_UNKNOWN);
|
||||
state->xclient.namaddr = mystrdup(CLIENT_NAMADDR_UNKNOWN);
|
||||
state->xclient.protocol = mystrdup(CLIENT_PROTO_UNKNOWN);
|
||||
}
|
||||
|
||||
/* smtpd_xclient_reset - reset XCLIENT attributes */
|
||||
|
||||
void smtpd_xclient_reset(SMTPD_STATE *state)
|
||||
{
|
||||
#define FREE_AND_WIPE(s) { if (s) myfree(s); s = 0; }
|
||||
|
||||
state->xclient.used = 0;
|
||||
FREE_AND_WIPE(state->xclient.name);
|
||||
FREE_AND_WIPE(state->xclient.addr);
|
||||
FREE_AND_WIPE(state->xclient.namaddr);
|
||||
state->xclient.peer_code = 0;
|
||||
FREE_AND_WIPE(state->xclient.protocol);
|
||||
FREE_AND_WIPE(state->xclient.helo_name);
|
||||
}
|
@@ -1,117 +0,0 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* intv 3
|
||||
/* SUMMARY
|
||||
/* integer array utilities
|
||||
/* SYNOPSIS
|
||||
/* #include <intv.h>
|
||||
/*
|
||||
/* INTV *intv_alloc(len)
|
||||
/* int len;
|
||||
/*
|
||||
/* INTV *intv_free(intvp)
|
||||
/* INTV *intvp;
|
||||
/*
|
||||
/* void intv_add(intvp, count, arg, ...)
|
||||
/* INTV *intvp;
|
||||
/* int count;
|
||||
/* int *arg;
|
||||
/* DESCRIPTION
|
||||
/* The functions in this module manipulate arrays of integers.
|
||||
/* An INTV structure contains the following members:
|
||||
/* .IP len
|
||||
/* The actual length of the \fIintv\fR array.
|
||||
/* .IP intc
|
||||
/* The number of \fIintv\fR elements used.
|
||||
/* .IP intv
|
||||
/* An array of integer values.
|
||||
/* .PP
|
||||
/* intv_alloc() returns an empty integer array of the requested
|
||||
/* length. The result is ready for use by intv_add().
|
||||
/*
|
||||
/* intv_add() copies zero or more integers and adds them to the
|
||||
/* specified integer array.
|
||||
/*
|
||||
/* intv_free() releases storage for an integer array, and conveniently
|
||||
/* returns a null pointer.
|
||||
/* SEE ALSO
|
||||
/* msg(3) diagnostics interface
|
||||
/* DIAGNOSTICS
|
||||
/* Fatal errors: memory allocation problem.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System libraries. */
|
||||
|
||||
#include <sys_defs.h>
|
||||
#include <stdlib.h> /* 44BSD stdarg.h uses abort() */
|
||||
#include <stdarg.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#include "mymalloc.h"
|
||||
#include "msg.h"
|
||||
#include "intv.h"
|
||||
|
||||
/* intv_free - destroy integer array */
|
||||
|
||||
INTV *intv_free(INTV *intvp)
|
||||
{
|
||||
myfree((char *) intvp->intv);
|
||||
myfree((char *) intvp);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* intv_alloc - initialize integer array */
|
||||
|
||||
INTV *intv_alloc(int len)
|
||||
{
|
||||
INTV *intvp;
|
||||
|
||||
/*
|
||||
* Sanity check.
|
||||
*/
|
||||
if (len < 1)
|
||||
msg_panic("intv_alloc: bad array length %d", len);
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
*/
|
||||
intvp = (INTV *) mymalloc(sizeof(*intvp));
|
||||
intvp->len = 0;
|
||||
intvp->intv = (int *) mymalloc(len * sizeof(intvp->intv[0]));
|
||||
intvp->len = len;
|
||||
intvp->intc = 0;
|
||||
return (intvp);
|
||||
}
|
||||
|
||||
/* intv_add - add integer to vector */
|
||||
|
||||
void intv_add(INTV *intvp, int count,...)
|
||||
{
|
||||
va_list ap;
|
||||
int new_len;
|
||||
|
||||
/*
|
||||
* Make sure that always intvp->intc < intvp->len.
|
||||
*/
|
||||
va_start(ap, count);
|
||||
while (count-- > 0) {
|
||||
if (intvp->intc >= intvp->len) {
|
||||
new_len = intvp->len * 2;
|
||||
intvp->intv = (int *) myrealloc((char *) intvp->intv,
|
||||
new_len * sizeof(int));
|
||||
intvp->len = new_len;
|
||||
}
|
||||
intvp->intv[intvp->intc++] = va_arg(ap, int);
|
||||
}
|
||||
va_end(ap);
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
#ifndef _INTV_H_INCLUDED_
|
||||
#define _INTV_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* intv 3h
|
||||
/* SUMMARY
|
||||
/* string array utilities
|
||||
/* SYNOPSIS
|
||||
/* #include "intv.h"
|
||||
DESCRIPTION
|
||||
.nf
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
typedef struct INTV {
|
||||
int len; /* number of array elements */
|
||||
int intc; /* array elements in use */
|
||||
int *intv; /* integer array */
|
||||
} INTV;
|
||||
|
||||
extern INTV *intv_alloc(int);
|
||||
extern void intv_add(INTV *, int,...);
|
||||
extern INTV *intv_free(INTV *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user