mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 14:17:41 +00:00
snapshot-19991115
This commit is contained in:
@@ -3170,8 +3170,56 @@ Apologies for any names omitted.
|
||||
Bugfix: LDAP lookup timeout settings were ignored. Patch
|
||||
by John Hensley. File: util/dict_ldap.c.
|
||||
|
||||
19991110
|
||||
19991108
|
||||
|
||||
Bugfix: when doing a fresh install, INSTALL.sh didn't set
|
||||
main.cf:mail_owner properly (Simon J. Mudd).
|
||||
|
||||
19991109
|
||||
|
||||
Bugfix: when doing a fresh install, INSTALL.sh no longer
|
||||
worked (missing main.cf file). Fix: add "-c" argument to
|
||||
the postmap commands (Lars Hecking @ nmrc.ucc.ie).
|
||||
|
||||
Documentation: removed spurious "do not edit" comments from
|
||||
the sample pcre and regexp configuration files.
|
||||
|
||||
19991110-13
|
||||
|
||||
Code cleanup: greatly simplified the SMTPD command parser
|
||||
and somewhat simplified the code that groks RFC 822-style
|
||||
address syntax in MAIL FROM and RCPT TO commands.
|
||||
|
||||
New parameter: strict_rfc821_envelopes (default: no) to
|
||||
reject RFC 822 address forms (with comments etc.) in SMTP
|
||||
envelopes. By default, the Postfix SMTP server only logs
|
||||
a warning.
|
||||
|
||||
19991113
|
||||
|
||||
Oops, also updated the SMTP VRFY code in the light of
|
||||
changes to the SMTPD command parser.
|
||||
|
||||
Cleanup: the local delivery agent now explicitly rejects
|
||||
recipients with an empty username.
|
||||
|
||||
19991114
|
||||
|
||||
Workaround: with some gawk versions, postconf/extract.awk
|
||||
reportedly returns a non-zero exit status upon success.
|
||||
Added an explicit exit(0) statement.
|
||||
|
||||
19991115
|
||||
|
||||
Feature: DNS TXT record lookup support, based on initial
|
||||
code by Simon J Mudd. File: dns/dns_lookup.c.
|
||||
|
||||
Feature: RBL TXT record lookups, based on initial code by
|
||||
Simon J Mudd. File: smtpd/smtpd_check.c.
|
||||
|
||||
Feature: permit_auth_destination restriction based on code
|
||||
by Jesper Skriver @ skriver.dk.
|
||||
|
||||
Code cleanup: the transport table now can override local
|
||||
deliveries. Postfix no longer uses the "empty next-hop
|
||||
hostname hack" to remember that a destination is local.
|
||||
|
@@ -6,6 +6,9 @@
|
||||
PATH=/bin:/usr/bin:/usr/sbin:/usr/etc:/sbin:/etc
|
||||
umask 022
|
||||
|
||||
# Workaround, should edit main.cf in place.
|
||||
trap 'rm -f ./main.cf; exit' 0 1 2 3 15
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Warning: this script replaces existing sendmail or Postfix programs.
|
||||
@@ -138,7 +141,14 @@ do
|
||||
esac
|
||||
done
|
||||
|
||||
bin/postmap -c ./conf -q "$owner" unix:passwd.byname >/dev/null || {
|
||||
# Workaround, should edit main.cf in place.
|
||||
test -f $config_directory/main.cf || {
|
||||
echo "mail_owner = $owner" >./main.cf
|
||||
echo "myhostname = xx.yy" >>./main.cf
|
||||
alt_main="-c ."
|
||||
}
|
||||
|
||||
bin/postmap $alt_main -q "$owner" unix:passwd.byname >/dev/null || {
|
||||
echo "$owner needs an entry in the passwd file" 1>&2
|
||||
echo "Remember, $owner must have a dedicated user id and group id." 1>&2
|
||||
exit 1
|
||||
@@ -146,7 +156,7 @@ bin/postmap -c ./conf -q "$owner" unix:passwd.byname >/dev/null || {
|
||||
|
||||
case $setgid in
|
||||
no) ;;
|
||||
*) bin/postmap -c ./conf -q "$setgid" unix:group.byname >/dev/null || {
|
||||
*) bin/postmap $alt_main -q "$setgid" unix:group.byname >/dev/null || {
|
||||
echo "$setgid needs an entry in the group file" 1>&2
|
||||
echo "Remember, $setgid must have a dedicated group id." 1>&2
|
||||
exit 1
|
||||
@@ -239,6 +249,16 @@ compare_or_replace a+x,go-w $postfix_script $config_directory/postfix-script ||
|
||||
|
||||
case $manpages in
|
||||
no) ;;
|
||||
*) test -d $manpages || mkdir -p $manpages || exit 1
|
||||
(cd man && tar cf - man?) | (cd $manpages && tar xf -)
|
||||
*) (
|
||||
cd man || exit 1
|
||||
for dir in man?
|
||||
do mkdir -p $manpages/$dir || exit 1
|
||||
done
|
||||
for file in man?/*
|
||||
do
|
||||
rm -f $manpages/$file
|
||||
cp $file $manpages/$file || exit 1
|
||||
chmod 644 $manpages/$file || exit 1
|
||||
done
|
||||
)
|
||||
esac
|
||||
|
@@ -22,6 +22,9 @@ update printfck:
|
||||
|
||||
printfck: update
|
||||
|
||||
install: update
|
||||
sh INSTALL.sh
|
||||
|
||||
depend clean:
|
||||
set -e; for i in $(DIRS); do \
|
||||
(set -e; echo "[$$i]"; cd $$i; $(MAKE) $@) || exit 1; \
|
||||
|
@@ -191,8 +191,10 @@ smtpd_sender_restrictions =
|
||||
# reject_invalid_hostname: reject HELO hostname with bad syntax.
|
||||
# reject_unknown_hostname: reject HELO hostname without DNS A or MX record.
|
||||
# reject_unknown_sender_domain: reject sender domain without A or MX record.
|
||||
# check_relay_domains: permit only mail from/to domains in $relay_domains.
|
||||
# reject_unauth_destination: reject mail not to domains in $relay_domains.
|
||||
# check_relay_domains: permit only mail from/to domains in $relay_domains
|
||||
or to the local machine.
|
||||
# permit_auth_destination: permit mail to self or to $relay_domains.
|
||||
# reject_unauth_destination: reject mail not to self or to $relay_domains.
|
||||
# reject_unauth_pipelining: reject mail from improperly pipelining spamware
|
||||
# permit_mx_backup: accept mail for sites that list me as MX host.
|
||||
# reject_unknown_recipient_domain: reject domains without A or MX record.
|
||||
|
@@ -100,6 +100,7 @@
|
||||
#include <stdlib.h> /* BSDI stdarg.h uses abort() */
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
@@ -107,6 +108,7 @@
|
||||
#include <vstring.h>
|
||||
#include <msg.h>
|
||||
#include <valid_hostname.h>
|
||||
#include <stringops.h>
|
||||
|
||||
/* DNS library. */
|
||||
|
||||
@@ -246,8 +248,13 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
|
||||
char *rr_name, DNS_FIXED *fixed)
|
||||
{
|
||||
char temp[DNS_NAME_LEN];
|
||||
int data_len = fixed->length;
|
||||
int data_len;
|
||||
unsigned pref = 0;
|
||||
unsigned char *src;
|
||||
unsigned char *dst;
|
||||
int ch;
|
||||
|
||||
#define MIN2(a, b) ((unsigned)(a) < (unsigned)(b) ? (a) : (b))
|
||||
|
||||
if (pos + fixed->length > reply->end)
|
||||
return (0);
|
||||
@@ -287,6 +294,14 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
|
||||
memcpy(temp, pos, fixed->length);
|
||||
data_len = fixed->length;
|
||||
break;
|
||||
case T_TXT:
|
||||
data_len = MIN2(fixed->length + 1, sizeof(temp));
|
||||
for (src = pos, dst = temp; dst < temp + data_len - 1; /* void */ ) {
|
||||
ch = *src++;
|
||||
*dst++ = (ISPRINT(ch) ? ch : ' ');
|
||||
}
|
||||
*dst = 0;
|
||||
break;
|
||||
}
|
||||
return (dns_rr_create(rr_name, fixed, pref, temp, data_len));
|
||||
}
|
||||
|
@@ -55,6 +55,7 @@ static void print_rr(DNS_RR *rr)
|
||||
case T_MR:
|
||||
case T_NS:
|
||||
case T_PTR:
|
||||
case T_TXT:
|
||||
printf("%s: %s\n", dns_strtype(rr->type), rr->data);
|
||||
break;
|
||||
case T_MX:
|
||||
|
@@ -208,11 +208,11 @@ extern char *var_db_type;
|
||||
extern char *var_always_bcc;
|
||||
|
||||
/*
|
||||
* Standards violation: permit RFC 822-style addresses in SMTP commands.
|
||||
* Standards violation: allow/permit RFC 822-style addresses in SMTP commands.
|
||||
*/
|
||||
#define VAR_ALLOW_RFC822_ENV "allow_rfc822_envelopes"
|
||||
#define DEF_ALLOW_RFC822_ENV 1
|
||||
extern bool var_allow_rfc822_envelopes;
|
||||
#define VAR_STRICT_RFC821_ENV "strict_rfc821_envelopes"
|
||||
#define DEF_STRICT_RFC821_ENV 0
|
||||
extern bool var_strict_rfc821_env;
|
||||
|
||||
/*
|
||||
* trivial rewrite/resolve service: mapping tables.
|
||||
@@ -773,6 +773,7 @@ extern int var_non_fqdn_code;
|
||||
#define DEF_UNK_ADDR_CODE 450
|
||||
extern int var_unk_addr_code;
|
||||
|
||||
#define PERMIT_AUTH_DEST "permit_auth_destination"
|
||||
#define REJECT_UNAUTH_DEST "reject_unauth_destination"
|
||||
#define CHECK_RELAY_DOMAINS "check_relay_domains"
|
||||
#define VAR_RELAY_CODE "relay_domains_reject_code"
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* Version of this program.
|
||||
*/
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "Snapshot-19991110"
|
||||
#define DEF_MAIL_VERSION "Snapshot-19991115"
|
||||
extern char *var_mail_version;
|
||||
|
||||
/* LICENSE
|
||||
|
@@ -537,20 +537,30 @@ reject_unauth_destination</b>
|
||||
|
||||
<dt> <b>check_relay_domains</b> <dd> Permit the request when the
|
||||
client hostname matches <a href="#relay_domains">$relay_domains</a>,
|
||||
or when the resolved destination address matches <a href="#relay_domains">
|
||||
$relay_domains</a>, otherwise reject. The <b>relay_domains_reject_code</b>
|
||||
parameter specifies the response code for rejected requests (default:
|
||||
or when the resolved destination address matches the the local
|
||||
machine or <a href="#relay_domains"> $relay_domains</a>, otherwise
|
||||
reject the request. The <b>relay_domains_reject_code</b> parameter
|
||||
specifies the response code for rejected requests (default:
|
||||
<b>554</b>).
|
||||
|
||||
<p>
|
||||
|
||||
<a name="permit_auth_destination">
|
||||
|
||||
<dt> <b>permit_auth_destination</b> <dd> Ignore the client hostname.
|
||||
Permit the request when the resolved destination address matches
|
||||
the local machine or <a href="#relay_domains"> $relay_domains</a>.
|
||||
|
||||
<p>
|
||||
|
||||
<a name="reject_unauth_destination">
|
||||
|
||||
<dt> <b>reject_unauth_destination</b> <dd> Ignore the client
|
||||
hostname. Reject the request when the resolved destination address
|
||||
does not match <a href="#relay_domains"> $relay_domains</a>. The
|
||||
<b>relay_domains_reject_code</b> parameter specifies the response
|
||||
code for rejected requests (default: <b>554</b>).
|
||||
does not match the local machine or <a href="#relay_domains">
|
||||
$relay_domains</a>. The <b>relay_domains_reject_code</b> parameter
|
||||
specifies the response code for rejected requests (default:
|
||||
<b>554</b>).
|
||||
|
||||
<p>
|
||||
|
||||
|
@@ -221,6 +221,13 @@ int deliver_recipient(LOCAL_STATE state, USER_ATTR usr_attr)
|
||||
state.msg_attr.extension = 0;
|
||||
state.msg_attr.unmatched = state.msg_attr.extension;
|
||||
|
||||
/*
|
||||
* Do not allow null usernames.
|
||||
*/
|
||||
if (state.msg_attr.user[0] == 0)
|
||||
return (bounce_append(BOUNCE_FLAG_KEEP, BOUNCE_ATTR(state.msg_attr),
|
||||
"null username in %s", state.msg_attr.recipient));
|
||||
|
||||
/*
|
||||
* Run the recipient through the delivery switch.
|
||||
*/
|
||||
|
@@ -62,6 +62,7 @@
|
||||
#include <rewrite_clnt.h>
|
||||
#include <tok822.h>
|
||||
#include <mail_params.h>
|
||||
#include <resolve_local.h>
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
@@ -138,7 +139,7 @@ int deliver_resolve_tree(LOCAL_STATE state, USER_ATTR usr_attr, TOK822 *addr
|
||||
* ugly code to force local recursive alias expansions on a host with no
|
||||
* authority over the local domain, but that code was just too unclean.
|
||||
*/
|
||||
if (VSTRING_LEN(reply.nexthop) == 0) {
|
||||
if (resolve_local(STR(reply.nexthop))) {
|
||||
status = deliver_recipient(state, usr_attr);
|
||||
} else {
|
||||
status = deliver_indirect(state);
|
||||
|
@@ -18,3 +18,7 @@
|
||||
print | "sort -u >bool_table.h"
|
||||
}
|
||||
}
|
||||
|
||||
# Workaround for broken gawk versions.
|
||||
|
||||
END { exit(0); }
|
||||
|
@@ -110,6 +110,7 @@
|
||||
#include <deliver_completed.h>
|
||||
#include <mail_addr_find.h>
|
||||
#include <opened.h>
|
||||
#include <resolve_local.h>
|
||||
|
||||
/* Client stubs. */
|
||||
|
||||
@@ -476,7 +477,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
|
||||
/*
|
||||
* Bounce mail to non-existent users in virtual domains.
|
||||
*/
|
||||
if (VSTRING_LEN(reply.nexthop) > 0
|
||||
if (!resolve_local(STR(reply.nexthop))
|
||||
&& qmgr_virtual != 0
|
||||
&& (at = strrchr(recipient->address, '@')) != 0) {
|
||||
domain = lowercase(mystrdup(at + 1));
|
||||
@@ -515,7 +516,7 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
|
||||
* job requires knowledge of local aliases. Yuck! I don't want to
|
||||
* duplicate delivery-agent specific knowledge in the queue manager.
|
||||
*/
|
||||
if (VSTRING_LEN(reply.nexthop) == 0) {
|
||||
if (resolve_local(STR(reply.nexthop))) {
|
||||
vstring_strcpy(reply.nexthop, STR(reply.recipient));
|
||||
(void) split_at_right(STR(reply.nexthop), '@');
|
||||
#if 0
|
||||
|
@@ -52,6 +52,12 @@
|
||||
/* this program. See the Postfix \fBmain.cf\fR file for syntax details
|
||||
/* and for default values. Use the \fBpostfix reload\fR command after
|
||||
/* a configuration change.
|
||||
/* .SH "Compatibility controls"
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* .IP \fBstrict_rfc821_envelopes\fR
|
||||
/* Disallow non-RFC 821 style addresses in envelopes. For example,
|
||||
/* allow RFC822-style address forms with comments, like Sendmail does.
|
||||
/* .SH Miscellaneous
|
||||
/* .ad
|
||||
/* .fi
|
||||
@@ -284,6 +290,7 @@ char *var_always_bcc;
|
||||
char *var_error_rcpt;
|
||||
int var_smtpd_delay_reject;
|
||||
char *var_rest_classes;
|
||||
int var_strict_rfc821_env;
|
||||
|
||||
/*
|
||||
* Global state, for stand-alone mode queue file cleanup. When this is
|
||||
@@ -291,17 +298,23 @@ char *var_rest_classes;
|
||||
*/
|
||||
char *smtpd_path;
|
||||
|
||||
/*
|
||||
* Silly little macros.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* collapse_args - put arguments together again */
|
||||
|
||||
static void collapse_args(int argc, SMTPD_TOKEN *argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 2; i < argc; i++) {
|
||||
vstring_strcat(argv[1].vstrval, " ");
|
||||
vstring_strcat(argv[1].vstrval, argv[i].strval);
|
||||
for (i = 1; i < argc; i++) {
|
||||
vstring_strcat(argv[0].vstrval, " ");
|
||||
vstring_strcat(argv[0].vstrval, argv[i].strval);
|
||||
}
|
||||
argv[1].strval = vstring_str(argv[1].vstrval);
|
||||
argv[0].strval = STR(argv[0].vstrval);
|
||||
}
|
||||
|
||||
/* helo_cmd - process HELO command */
|
||||
@@ -320,7 +333,8 @@ static int helo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "503 Duplicate HELO/EHLO");
|
||||
return (-1);
|
||||
}
|
||||
collapse_args(argc, argv);
|
||||
if (argc > 2)
|
||||
collapse_args(argc - 1, argv + 1);
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& var_smtpd_delay_reject == 0
|
||||
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
|
||||
@@ -349,7 +363,8 @@ static int ehlo_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "503 Error: duplicate HELO/EHLO");
|
||||
return (-1);
|
||||
}
|
||||
collapse_args(argc, argv);
|
||||
if (argc > 2)
|
||||
collapse_args(argc - 1, argv + 1);
|
||||
if (SMTPD_STAND_ALONE(state) == 0
|
||||
&& var_smtpd_delay_reject == 0
|
||||
&& (err = smtpd_check_helo(state, argv[1].strval)) != 0) {
|
||||
@@ -427,46 +442,94 @@ static void mail_open_stream(SMTPD_STATE *state)
|
||||
|
||||
/* extract_addr - extract address from rubble */
|
||||
|
||||
static VSTRING *extract_addr(SMTPD_STATE *state, VSTRING *buf)
|
||||
static char *extract_addr(SMTPD_STATE *state, SMTPD_TOKEN *arg,
|
||||
int allow_empty_addr)
|
||||
{
|
||||
char *myname = "extract_addr";
|
||||
TOK822 *tree;
|
||||
TOK822 *tp;
|
||||
TOK822 *addr = 0;
|
||||
int naddr;
|
||||
int non_addr;
|
||||
char *err = 0;
|
||||
|
||||
/*
|
||||
* Special case.
|
||||
*/
|
||||
#define PERMIT_EMPTY_ADDR 1
|
||||
#define REJECT_EMPTY_ADDR 0
|
||||
|
||||
if (allow_empty_addr && strcmp(STR(arg->vstrval), "<>") == 0) {
|
||||
if (msg_verbose)
|
||||
msg_info("%s: empty address", myname);
|
||||
VSTRING_RESET(arg->vstrval);
|
||||
VSTRING_TERMINATE(arg->vstrval);
|
||||
arg->strval = STR(arg->vstrval);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some mailers send RFC822-style address forms (with comments and such)
|
||||
* in SMTP envelopes. We cannot blame users for this: the blame is with
|
||||
* programmers violating the RFC, and with sendmail for being permissive.
|
||||
*
|
||||
* Extract the address from any surrounding junk. XXX Because of this, the
|
||||
* SMTP command tokenizer must leave the address in externalized (quoted)
|
||||
* form.
|
||||
* XXX The SMTP command tokenizer must leave the address in externalized
|
||||
* (quoted) form, so that the address parser can correctly extract the
|
||||
* address from surrounding junk.
|
||||
*
|
||||
* XXX We have only one address parser, written according to the rules of
|
||||
* RFC 822. That standard differs subtly from RFC 821.
|
||||
*/
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: input: %s", myname, STR(buf));
|
||||
tree = tok822_parse(STR(buf));
|
||||
msg_info("%s: input: %s", myname, STR(arg->vstrval));
|
||||
tree = tok822_parse(STR(arg->vstrval));
|
||||
|
||||
/*
|
||||
* Find trouble.
|
||||
*/
|
||||
for (naddr = non_addr = 0, tp = tree; tp != 0; tp = tp->next) {
|
||||
if (tp->type == TOK822_ADDR) {
|
||||
if (++naddr == 1)
|
||||
tok822_internalize(buf, tp->head, TOK822_STR_DEFL);
|
||||
else if (naddr == 2)
|
||||
msg_warn("Multiple addresses from %s in %s command: %s",
|
||||
state->namaddr, state->where, STR(buf));
|
||||
} else if (tp->type != '<' && tp->type != '>') {
|
||||
if (++non_addr == 1)
|
||||
msg_warn("Non-RFC 821 syntax from %s in %s command: %s",
|
||||
state->namaddr, state->where, STR(buf));
|
||||
addr = tp;
|
||||
naddr += 1; /* count address forms */
|
||||
} else if (tp->type == '<' || tp->type == '>') {
|
||||
/* void */ ; /* ignore brackets */
|
||||
} else {
|
||||
non_addr += 1; /* count non-address forms */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Report trouble.
|
||||
*/
|
||||
if (naddr != 1) { /* sorry, no can do */
|
||||
msg_warn("Illegal address syntax from %s in %s command: %s",
|
||||
state->namaddr, state->where, STR(arg->vstrval));
|
||||
err = "501 Bad address syntax";
|
||||
} else if (non_addr > 0) { /* it works with Sendmail... */
|
||||
msg_warn("Illegal address syntax from %s in %s command: %s",
|
||||
state->namaddr, state->where, STR(arg->vstrval));
|
||||
err = (var_strict_rfc821_env ? "501 Bad address syntax" : 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Overwrite the input with the extracted address. This seems bad design,
|
||||
* but we really are not going to use the original data anymore. What we
|
||||
* start with is quoted (external) form, and what we need is unquoted
|
||||
* (internal form).
|
||||
*/
|
||||
if (addr)
|
||||
tok822_internalize(arg->vstrval, addr->head, TOK822_STR_DEFL);
|
||||
else
|
||||
vstring_strcat(arg->vstrval, "");
|
||||
arg->strval = STR(arg->vstrval);
|
||||
|
||||
/*
|
||||
* Cleanup.
|
||||
*/
|
||||
tok822_free_tree(tree);
|
||||
if (msg_verbose)
|
||||
msg_info("%s: result: %s", myname, STR(buf));
|
||||
return (buf);
|
||||
msg_info("%s: result: %s", myname, STR(arg->vstrval));
|
||||
return (err);
|
||||
}
|
||||
|
||||
/* mail_cmd - process MAIL command */
|
||||
@@ -498,7 +561,16 @@ static int mail_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "501 Syntax: MAIL FROM: <address>");
|
||||
return (-1);
|
||||
}
|
||||
argv[2].strval = STR(extract_addr(state, argv[2].vstrval));
|
||||
if (argv[2].tokval == SMTPD_TOK_ERROR) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad address syntax");
|
||||
return (-1);
|
||||
}
|
||||
if ((err = extract_addr(state, argv + 2, PERMIT_EMPTY_ADDR)) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
for (narg = 3; narg < argc; narg++) {
|
||||
arg = argv[narg].strval;
|
||||
if (strcasecmp(arg, "BODY=8BITMIME") == 0
|
||||
@@ -596,7 +668,16 @@ static int rcpt_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
smtpd_chat_reply(state, "501 Syntax: RCPT TO: <address>");
|
||||
return (-1);
|
||||
}
|
||||
argv[2].strval = STR(extract_addr(state, argv[2].vstrval));
|
||||
if (argv[2].tokval == SMTPD_TOK_ERROR) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Bad address syntax");
|
||||
return (-1);
|
||||
}
|
||||
if ((err = extract_addr(state, argv + 2, REJECT_EMPTY_ADDR)) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
if (var_smtpd_rcpt_limit && state->rcpt_count >= var_smtpd_rcpt_limit) {
|
||||
state->error_mask |= MAIL_ERROR_POLICY;
|
||||
smtpd_chat_reply(state, "452 Error: too many recipients");
|
||||
@@ -845,13 +926,25 @@ static int vrfy_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
|
||||
* The SMTP standard (RFC 821) disallows unquoted special characters in
|
||||
* the VRFY argument. Common practice violates the standard, however.
|
||||
* Postfix accomodates common practice where it violates the standard.
|
||||
*
|
||||
* XXX Impedance mismatch! The SMTP command tokenizer preserves quoting,
|
||||
* whereas the recipient restrictions checks expect unquoted (internal)
|
||||
* address forms. Therefore we must parse out the address, or we must
|
||||
* stop doing recipient restriction checks and lose the opportunity to
|
||||
* say "user unknown" at the SMTP port.
|
||||
*/
|
||||
if (argc < 2) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "501 Syntax: VRFY address");
|
||||
return (-1);
|
||||
}
|
||||
collapse_args(argc, argv);
|
||||
if (argc > 2)
|
||||
collapse_args(argc - 1, argv + 1);
|
||||
if ((err = extract_addr(state, argv + 1, REJECT_EMPTY_ADDR)) != 0) {
|
||||
state->error_mask |= MAIL_ERROR_PROTOCOL;
|
||||
smtpd_chat_reply(state, "%s", err);
|
||||
return (-1);
|
||||
}
|
||||
if (SMTPD_STAND_ALONE(state) == 0)
|
||||
err = smtpd_check_rcpt(state, argv[1].strval);
|
||||
|
||||
@@ -1216,6 +1309,7 @@ int main(int argc, char **argv)
|
||||
static CONFIG_BOOL_TABLE bool_table[] = {
|
||||
VAR_HELO_REQUIRED, DEF_HELO_REQUIRED, &var_helo_required,
|
||||
VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject,
|
||||
VAR_STRICT_RFC821_ENV, DEF_STRICT_RFC821_ENV, &var_strict_rfc821_env,
|
||||
0,
|
||||
};
|
||||
static CONFIG_STR_TABLE str_table[] = {
|
||||
|
@@ -124,10 +124,13 @@
|
||||
/* parameter. Reject the request otherwise.
|
||||
/* The \fIrelay_domains_reject_code\fR configuration parameter specifies
|
||||
/* the reject status code (default: 554).
|
||||
/* .IP permit_auth_destination
|
||||
/* Permit the request when the resolved recipient domain matches
|
||||
/* the local machine or the \fIrelay_domains\fR configuration parameter.
|
||||
/* .IP reject_unauth_destination
|
||||
/* Reject the request when the resolved recipient domain does not match
|
||||
/* the \fIrelay_domains\fR configuration parameter. Same error code as
|
||||
/* check_relay_domains.
|
||||
/* the local machine or the \fIrelay_domains\fR configuration parameter.
|
||||
/* Same error code as check_relay_domains.
|
||||
/* .IP reject_unauth_pipelining
|
||||
/* Reject the request when the client has already sent the next request
|
||||
/* without being told that the server implements SMTP command pipelining.
|
||||
@@ -709,7 +712,7 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
|
||||
* Permit if destination is local. XXX This must be generalized for
|
||||
* per-domain user tables and for non-UNIX local delivery agents.
|
||||
*/
|
||||
if (STR(reply.nexthop)[0] == 0
|
||||
if (resolve_local(STR(reply.nexthop))
|
||||
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
|
||||
return (SMTPD_CHECK_OK);
|
||||
domain += 1;
|
||||
@@ -728,6 +731,43 @@ static int check_relay_domains(SMTPD_STATE *state, char *recipient,
|
||||
var_relay_code, reply_name, reply_class));
|
||||
}
|
||||
|
||||
/* permit_auth_destination - OK for message relaying */
|
||||
|
||||
static int permit_auth_destination(SMTPD_STATE *state, char *recipient)
|
||||
{
|
||||
char *myname = "permit_auth_destination";
|
||||
char *domain;
|
||||
|
||||
if (msg_verbose)
|
||||
msg_info("%s: %s", myname, recipient);
|
||||
|
||||
/*
|
||||
* Resolve the address.
|
||||
*/
|
||||
canon_addr_internal(query, recipient);
|
||||
resolve_clnt_query(STR(query), &reply);
|
||||
|
||||
/*
|
||||
* Permit if destination is local. XXX This must be generalized for
|
||||
* per-domain user tables and for non-UNIX local delivery agents.
|
||||
*/
|
||||
if (resolve_local(STR(reply.nexthop))
|
||||
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
|
||||
return (SMTPD_CHECK_OK);
|
||||
domain += 1;
|
||||
|
||||
/*
|
||||
* Permit if the destination matches the relay_domains list.
|
||||
*/
|
||||
if (domain_list_match(relay_domains, domain))
|
||||
return (SMTPD_CHECK_OK);
|
||||
|
||||
/*
|
||||
* Skip when not matched
|
||||
*/
|
||||
return (SMTPD_CHECK_DUNNO);
|
||||
}
|
||||
|
||||
/* reject_unauth_destination - FAIL for message relaying */
|
||||
|
||||
static int reject_unauth_destination(SMTPD_STATE *state, char *recipient)
|
||||
@@ -748,7 +788,7 @@ static int reject_unauth_destination(SMTPD_STATE *state, char *recipient)
|
||||
* Pass if destination is local. XXX This must be generalized for
|
||||
* per-domain user tables and for non-UNIX local delivery agents.
|
||||
*/
|
||||
if (STR(reply.nexthop)[0] == 0
|
||||
if (resolve_local(STR(reply.nexthop))
|
||||
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
|
||||
return (SMTPD_CHECK_DUNNO);
|
||||
domain += 1;
|
||||
@@ -850,7 +890,7 @@ static int permit_mx_backup(SMTPD_STATE *unused_state, const char *recipient)
|
||||
* If the destination is local, it is acceptable, because we are
|
||||
* supposedly MX for our own address.
|
||||
*/
|
||||
if (STR(reply.nexthop)[0] == 0
|
||||
if (resolve_local(STR(reply.nexthop))
|
||||
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
|
||||
return (SMTPD_CHECK_OK);
|
||||
domain += 1;
|
||||
@@ -984,7 +1024,7 @@ static int reject_unknown_address(SMTPD_STATE *state, char *addr,
|
||||
/*
|
||||
* Skip local destinations and non-DNS forms.
|
||||
*/
|
||||
if (STR(reply.nexthop)[0] == 0
|
||||
if (resolve_local(STR(reply.nexthop))
|
||||
|| (domain = strrchr(STR(reply.recipient), '@')) == 0)
|
||||
return (SMTPD_CHECK_DUNNO);
|
||||
domain += 1;
|
||||
@@ -1024,7 +1064,7 @@ static int permit_rcpt_map(char *table, char *reply_name)
|
||||
return (SMTPD_CHECK_DUNNO);
|
||||
domain += 1;
|
||||
if (domain[0] == '#' || domain[0] == '[')
|
||||
if (STR(reply.nexthop)[0] != 0)
|
||||
if (!resolve_local(STR(reply.nexthop)))
|
||||
return (SMTPD_CHECK_DUNNO);
|
||||
|
||||
/*
|
||||
@@ -1338,6 +1378,9 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
||||
char *saved_domains = mystrdup(var_maps_rbl_domains);
|
||||
char *bp = saved_domains;
|
||||
char *rbl_domain;
|
||||
char *rbl_reason;
|
||||
char *rbl_fodder;
|
||||
DNS_RR *txt_list;
|
||||
int reverse_len;
|
||||
int dns_status = DNS_FAIL;
|
||||
int i;
|
||||
@@ -1371,11 +1414,22 @@ static int reject_maps_rbl(SMTPD_STATE *state)
|
||||
/*
|
||||
* Report the result.
|
||||
*/
|
||||
if (dns_status == DNS_OK)
|
||||
if (dns_status == DNS_OK) {
|
||||
if (dns_lookup(STR(query), T_TXT, 0, &txt_list,
|
||||
(VSTRING *) 0, (VSTRING *) 0) == DNS_OK) {
|
||||
rbl_fodder = ", reason: ";
|
||||
rbl_reason = (char *) txt_list->data;
|
||||
} else {
|
||||
txt_list = 0;
|
||||
rbl_fodder = rbl_reason = "";
|
||||
}
|
||||
result = smtpd_check_reject(state, MAIL_ERROR_POLICY,
|
||||
"%d Service unavailable; [%s] blocked using %s",
|
||||
var_maps_rbl_code, state->addr, rbl_domain);
|
||||
else
|
||||
"%d Service unavailable; [%s] blocked using %s%s%s",
|
||||
var_maps_rbl_code, state->addr, rbl_domain,
|
||||
rbl_fodder, rbl_reason);
|
||||
if (txt_list)
|
||||
dns_rr_free(txt_list);
|
||||
} else
|
||||
result = SMTPD_CHECK_DUNNO;
|
||||
|
||||
/*
|
||||
@@ -1549,6 +1603,9 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
|
||||
} else if (strcasecmp(name, PERMIT_MX_BACKUP) == 0) {
|
||||
if (state->recipient)
|
||||
status = permit_mx_backup(state, state->recipient);
|
||||
} else if (strcasecmp(name, PERMIT_AUTH_DEST) == 0) {
|
||||
if (state->recipient)
|
||||
status = permit_auth_destination(state, state->recipient);
|
||||
} else if (strcasecmp(name, REJECT_UNAUTH_DEST) == 0) {
|
||||
if (state->recipient)
|
||||
status = reject_unauth_destination(state, state->recipient);
|
||||
|
@@ -94,3 +94,14 @@ rcpt wietse@porcupine.org
|
||||
rcpt wietse@no.recipient.domain
|
||||
mail wietse@no.sender.domain
|
||||
rcpt wietse@porcupine.org
|
||||
#
|
||||
# {permit_auth,reject_unauth}_destination
|
||||
#
|
||||
relay_domains foo.com,bar.com
|
||||
mail user@some.where
|
||||
recipient_restrictions permit_auth_destination,reject
|
||||
rcpt user@foo.org
|
||||
rcpt user@foo.com
|
||||
recipient_restrictions reject_unauth_destination,permit
|
||||
rcpt user@foo.org
|
||||
rcpt user@foo.com
|
||||
|
@@ -182,8 +182,8 @@ OK
|
||||
>>> client spike.porcupine.org 168.100.189.2
|
||||
OK
|
||||
>>> client foo 127.0.0.2
|
||||
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com; from=<foo@friend.bad.domain>
|
||||
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
|
||||
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
|
||||
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
|
||||
>>> #
|
||||
>>> # Hybrids
|
||||
>>> #
|
||||
|
@@ -172,8 +172,8 @@ OK
|
||||
>>> client spike.porcupine.org 168.100.189.2
|
||||
OK
|
||||
>>> client foo 127.0.0.2
|
||||
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com; from=<foo@friend.bad.domain>
|
||||
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com
|
||||
./smtpd_check: reject: CONNECT from foo[127.0.0.2]: 554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>; from=<foo@friend.bad.domain>
|
||||
554 Service unavailable; [127.0.0.2] blocked using rbl.maps.vix.com, reason: EBlackholed - see <URL:http://mail-abuse.org/cgi-bin/lookup?127.0.0.2>
|
||||
>>> #
|
||||
>>> # unknown sender/recipient domain
|
||||
>>> #
|
||||
@@ -193,3 +193,24 @@ OK
|
||||
>>> rcpt wietse@porcupine.org
|
||||
./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 <wietse@no.sender.domain>: Sender address rejected: Domain not found; from=<wietse@no.sender.domain> to=<wietse@porcupine.org>
|
||||
554 <wietse@no.sender.domain>: Sender address rejected: Domain not found
|
||||
>>> #
|
||||
>>> # {permit_auth,reject_unauth}_destination
|
||||
>>> #
|
||||
>>> relay_domains foo.com,bar.com
|
||||
OK
|
||||
>>> mail user@some.where
|
||||
OK
|
||||
>>> recipient_restrictions permit_auth_destination,reject
|
||||
OK
|
||||
>>> rcpt user@foo.org
|
||||
./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 <user@foo.org>: Recipient address rejected: Access denied; from=<user@some.where> to=<user@foo.org>
|
||||
554 <user@foo.org>: Recipient address rejected: Access denied
|
||||
>>> rcpt user@foo.com
|
||||
OK
|
||||
>>> recipient_restrictions reject_unauth_destination,permit
|
||||
OK
|
||||
>>> rcpt user@foo.org
|
||||
./smtpd_check: reject: RCPT from foo[127.0.0.2]: 554 <user@foo.org>: Relay access denied; from=<user@some.where> to=<user@foo.org>
|
||||
554 <user@foo.org>: Relay access denied
|
||||
>>> rcpt user@foo.com
|
||||
OK
|
||||
|
@@ -31,7 +31,7 @@
|
||||
/* It understands backslash escapes, white space, quoted strings,
|
||||
/* and addresses (including quoted text) enclosed by < and >.
|
||||
/* The input is broken up into tokens by whitespace, except for
|
||||
/* whitespace that is protected by quites etc.
|
||||
/* whitespace that is protected by quotes etc.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
@@ -64,12 +64,22 @@
|
||||
static char *smtp_quoted(char *cp, SMTPD_TOKEN *arg, int start, int last)
|
||||
{
|
||||
static VSTRING *stack;
|
||||
int wanted;
|
||||
int c;
|
||||
|
||||
/*
|
||||
* Parser stack. `ch' is always the most-recently entered character.
|
||||
*/
|
||||
#define ENTER_CHAR(buf, ch) VSTRING_ADDCH(buf, ch);
|
||||
#define LEAVE_CHAR(buf, ch) { \
|
||||
vstring_truncate(buf, VSTRING_LEN(buf) - 1); \
|
||||
ch = vstring_end(buf)[-1]; \
|
||||
}
|
||||
|
||||
if (stack == 0)
|
||||
stack = vstring_alloc(1);
|
||||
VSTRING_RESET(stack);
|
||||
VSTRING_ADDCH(stack, last);
|
||||
ENTER_CHAR(stack, wanted = last);
|
||||
|
||||
VSTRING_ADDCH(arg->vstrval, start);
|
||||
for (;;) {
|
||||
@@ -77,25 +87,22 @@ static char *smtp_quoted(char *cp, SMTPD_TOKEN *arg, int start, int last)
|
||||
break;
|
||||
cp++;
|
||||
VSTRING_ADDCH(arg->vstrval, c);
|
||||
if (c == vstring_end(stack)[-1]) { /* closing quote etc. */
|
||||
vstring_truncate(stack, VSTRING_LEN(stack) - 1);
|
||||
if (VSTRING_LEN(stack) == 0)
|
||||
if (c == '\\') { /* parse escape sequence */
|
||||
if ((c = *cp) == 0)
|
||||
break;
|
||||
} else {
|
||||
if (c == '\\') { /* parse escape sequence */
|
||||
if ((c = *cp) == 0)
|
||||
break;
|
||||
cp++;
|
||||
VSTRING_ADDCH(arg->vstrval, c);
|
||||
} else if (c == '"') {
|
||||
VSTRING_ADDCH(stack, '"'); /* highest precedence */
|
||||
} else if (c == '(' && vstring_end(stack)[-1] != '"') {
|
||||
VSTRING_ADDCH(stack, ')'); /* medium precedence */
|
||||
} else if (c == '<' && vstring_end(stack)[-1] == '>') {
|
||||
VSTRING_ADDCH(stack, '>'); /* lowest precedence */
|
||||
}
|
||||
cp++;
|
||||
VSTRING_ADDCH(arg->vstrval, c);
|
||||
} else if (c == wanted) { /* closing quote etc. */
|
||||
if (VSTRING_LEN(stack) == 1)
|
||||
return (cp);
|
||||
LEAVE_CHAR(stack, wanted);
|
||||
} else if (c == '"') {
|
||||
ENTER_CHAR(stack, wanted = '"'); /* highest precedence */
|
||||
} else if (c == '<' && wanted == '>') {
|
||||
ENTER_CHAR(stack, wanted = '>'); /* lowest precedence */
|
||||
}
|
||||
}
|
||||
arg->tokval = SMTPD_TOK_ERROR; /* missing end */
|
||||
return (cp);
|
||||
}
|
||||
|
||||
@@ -106,12 +113,15 @@ static char *smtp_next_token(char *cp, SMTPD_TOKEN *arg)
|
||||
int c;
|
||||
|
||||
VSTRING_RESET(arg->vstrval);
|
||||
arg->tokval = SMTPD_TOK_OTHER;
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
#define STREQ(x,y,l) ((x)[0] == (x)[0] && strncasecmp((x), (y), (l)) == 0)
|
||||
#define STREQ(x,y,l) (strncasecmp((x), (y), (l)) == 0)
|
||||
|
||||
while ((c = *cp) != 0) {
|
||||
for (;;) {
|
||||
if ((c = *cp) == 0) /* end of input */
|
||||
break;
|
||||
cp++;
|
||||
if (ISSPACE(c)) { /* whitespace, skip */
|
||||
while (*cp && ISSPACE(*cp))
|
||||
@@ -120,8 +130,6 @@ static char *smtp_next_token(char *cp, SMTPD_TOKEN *arg)
|
||||
break;
|
||||
} else if (c == '<') { /* <stuff> */
|
||||
cp = smtp_quoted(cp, arg, c, '>');
|
||||
} else if (c == '[') { /* [stuff] */
|
||||
cp = smtp_quoted(cp, arg, c, ']');
|
||||
} else if (c == '"') { /* "stuff" */
|
||||
cp = smtp_quoted(cp, arg, c, c);
|
||||
} else if (c == ':') { /* this is gross, but... */
|
||||
@@ -138,7 +146,7 @@ static char *smtp_next_token(char *cp, SMTPD_TOKEN *arg)
|
||||
VSTRING_ADDCH(arg->vstrval, c);
|
||||
}
|
||||
}
|
||||
if (LEN(arg->vstrval) == 0) /* no token found */
|
||||
if (LEN(arg->vstrval) <= 0) /* no token found */
|
||||
return (0);
|
||||
VSTRING_TERMINATE(arg->vstrval);
|
||||
arg->strval = vstring_str(arg->vstrval);
|
||||
@@ -197,15 +205,20 @@ main(int unused_argc, char **unused_argv)
|
||||
if (isatty(STDIN_FILENO))
|
||||
vstream_printf("enter SMTPD command: ");
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
if (vstring_fgets(vp, VSTREAM_IN) == 0)
|
||||
if (vstring_get_nonl(vp, VSTREAM_IN) == VSTREAM_EOF)
|
||||
break;
|
||||
if (*vstring_str(vp) == '#')
|
||||
continue;
|
||||
if (!isatty(STDIN_FILENO))
|
||||
vstream_fputs(vstring_str(vp), VSTREAM_OUT);
|
||||
vstream_printf("%s\n", vstring_str(vp));
|
||||
tok_argc = smtpd_token(vstring_str(vp), &tok_argv);
|
||||
for (i = 0; i < tok_argc; i++)
|
||||
for (i = 0; i < tok_argc; i++) {
|
||||
vstream_printf("Token type: %s\n",
|
||||
tok_argv[i].tokval == SMTPD_TOK_OTHER ? "other" :
|
||||
tok_argv[i].tokval == SMTPD_TOK_ERROR ? "error" :
|
||||
"unknown");
|
||||
vstream_printf("Token value: %s\n", tok_argv[i].strval);
|
||||
}
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
@@ -17,6 +17,7 @@
|
||||
* External interface.
|
||||
*/
|
||||
typedef struct SMTPD_TOKEN {
|
||||
int tokval;
|
||||
char *strval;
|
||||
VSTRING *vstrval;
|
||||
} SMTPD_TOKEN;
|
||||
|
@@ -7,3 +7,6 @@ mail from:<"wietse venema" <wietse@porcupine.org>>
|
||||
mail from:<"wietse venema"@porcupine.org ( ("wietse ) venema") )>
|
||||
mail from:"wietse venema"@porcupine.org
|
||||
mail from:wietse\ venema@porcupine.org
|
||||
mail to:<"wietse venema>
|
||||
mail to:<wietse@[stuff>
|
||||
mail to:<wietse@["stuff]>
|
||||
|
@@ -1,36 +1,84 @@
|
||||
mail from:<wietse@porcupine.org>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: <wietse@porcupine.org>
|
||||
mail from:<"wietse venema"@porcupine.org>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: <"wietse venema"@porcupine.org>
|
||||
mail from:wietse@porcupine.org
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: wietse@porcupine.org
|
||||
mail from:<wietse @ porcupine.org>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: <wietse @ porcupine.org>
|
||||
mail from:<"wietse venema"@porcupine.org ("wietse ) venema")>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: <"wietse venema"@porcupine.org ("wietse ) venema")>
|
||||
mail from:<"wietse venema" <wietse@porcupine.org>>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: <"wietse venema" <wietse@porcupine.org>>
|
||||
mail from:<"wietse venema"@porcupine.org ( ("wietse ) venema") )>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: <"wietse venema"@porcupine.org ( ("wietse ) venema") )>
|
||||
mail from:"wietse venema"@porcupine.org
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: "wietse venema"@porcupine.org
|
||||
mail from:wietse\ venema@porcupine.org
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: from:
|
||||
Token type: other
|
||||
Token value: wietse venema@porcupine.org
|
||||
mail to:<"wietse venema>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: to:
|
||||
Token type: error
|
||||
Token value: <"wietse venema>
|
||||
mail to:<wietse@[stuff>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: to:
|
||||
Token type: other
|
||||
Token value: <wietse@[stuff>
|
||||
mail to:<wietse@["stuff]>
|
||||
Token type: other
|
||||
Token value: mail
|
||||
Token type: other
|
||||
Token value: to:
|
||||
Token type: error
|
||||
Token value: <wietse@["stuff]>
|
||||
|
@@ -151,39 +151,43 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-local delivery: if no transport is specified, assume the transport
|
||||
* specified in var_def_transport. If no mail relay is specified in
|
||||
* var_relayhost, forward to the domain's mail exchanger.
|
||||
* The transport map, if specified, overrides default routing.
|
||||
*/
|
||||
if (domain != 0) {
|
||||
if (*var_transport_maps == 0
|
||||
|| (tok822_internalize(addr_buf, domain->next, TOK822_STR_DEFL),
|
||||
transport_lookup(STR(addr_buf), channel, nexthop) == 0)) {
|
||||
if (*var_transport_maps == 0
|
||||
|| (tok822_internalize(addr_buf, domain->next, TOK822_STR_DEFL),
|
||||
transport_lookup(STR(addr_buf), channel, nexthop)) == 0) {
|
||||
|
||||
/*
|
||||
* Non-local delivery. Use the default transport specified in
|
||||
* var_def_transport. If no default mail relay is specified in
|
||||
* var_relayhost, forward to the domain's mail exchanger.
|
||||
*/
|
||||
if (domain != 0) {
|
||||
vstring_strcpy(channel, var_def_transport);
|
||||
if (*var_relayhost)
|
||||
vstring_strcpy(nexthop, var_relayhost);
|
||||
else
|
||||
tok822_internalize(nexthop, domain->next, TOK822_STR_DEFL);
|
||||
}
|
||||
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local delivery: if no domain was specified, assume the local machine.
|
||||
* See above for what happens with an empty localpart.
|
||||
*/
|
||||
else {
|
||||
vstring_strcpy(channel, MAIL_SERVICE_LOCAL);
|
||||
vstring_strcpy(nexthop, "");
|
||||
if (saved_domain) {
|
||||
tok822_sub_append(tree, saved_domain);
|
||||
saved_domain = 0;
|
||||
} else {
|
||||
tok822_sub_append(tree, tok822_alloc('@', (char *) 0));
|
||||
tok822_sub_append(tree, tok822_scan(var_myhostname, (TOK822 **) 0));
|
||||
/*
|
||||
* Local delivery. Use the default transport and next-hop hostname.
|
||||
* If no domain was specified, assume the local machine. See above
|
||||
* for what happens with an empty localpart.
|
||||
*/
|
||||
else {
|
||||
vstring_strcpy(channel, MAIL_SERVICE_LOCAL);
|
||||
vstring_strcpy(nexthop, var_myhostname);
|
||||
if (saved_domain) {
|
||||
tok822_sub_append(tree, saved_domain);
|
||||
saved_domain = 0;
|
||||
} else {
|
||||
tok822_sub_append(tree, tok822_alloc('@', (char *) 0));
|
||||
tok822_sub_append(tree, tok822_scan(var_myhostname, (TOK822 **) 0));
|
||||
}
|
||||
}
|
||||
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
|
||||
}
|
||||
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
|
||||
|
||||
/*
|
||||
* Clean up.
|
||||
|
Reference in New Issue
Block a user