Compatibility: Sendmail now invokes the Milter connect
action with the verified hostname instead of the name
obtained with PTR lookup. File: smtpd/smtpd.c.
+
+20061004
+
+ Cleanup: force space between mailq queueid+status and file
+ size items. File: showq/showq.c.
+
+20061015
+
+ Cleanup: convert the Milter {mail_addr} and {rcpt_addr}
+ macro values to external form. File: smtpd/smtpd_milter.c.
+
+ Cleanup: the Milter {mail_addr} and {rcpt_addr} macros are
+ now available with non-SMTP mail. File: cleanup/cleanup_milter.c.
+
+ Cleanup: convert addresses in Milter recipient add/delete
+ requests to internal form. File: cleanup/cleanup_milter.c.
+
+ Cleanup: with non-SMTP mail, convert addresses in simulated
+ MAIL FROM and RCPT TO events to external form. File:
+ cleanup/cleanup_milter.c.
+
+20061017
+
+ Cleanup: removed spurious warning when the cleanup server
+ attempts to bounce mail with soft_bounce=yes. Problem
+ reported by Ralf Hildebrandt. File: cleanup/cleanup_bounce.c.
+
+ Bugfix: null pointer bug when receiving a non-protocol
+ response on a cached SMTP/LMTP connection. Report by Brian
+ Kantor. Fix by Victor Duchovni. File: smtp/smtp_reuse.c.
local delivery agent tries each pathname in the list until
a file is found.
- Delivery via ~/.<b>.forward</b> files is done with the privileges
+ Delivery via ~/.<b>forward</b> files is done with the privileges
of the recipient. Thus, ~/.<b>forward</b> like files must be
readable by the recipient, and their parent directory
needs to have "execute" permission for the recipient.
configuration parameter. Upon delivery, the local delivery agent
tries each pathname in the list until a file is found.
-Delivery via ~/.\fB.forward\fR files is done with the privileges
+Delivery via ~/.\fBforward\fR files is done with the privileges
of the recipient.
Thus, ~/.\fBforward\fR like files must be readable by the
recipient, and their parent directory needs to have "execute"
cleanup_milter.o: ../../include/mymalloc.h
cleanup_milter.o: ../../include/nvtable.h
cleanup_milter.o: ../../include/off_cvt.h
+cleanup_milter.o: ../../include/quote_821_local.h
+cleanup_milter.o: ../../include/quote_flags.h
cleanup_milter.o: ../../include/rec_attr_map.h
cleanup_milter.o: ../../include/rec_type.h
cleanup_milter.o: ../../include/record.h
const char *client_addr; /* real or ersatz client */
int client_af; /* real or ersatz client */
const char *client_port; /* real or ersatz client */
+ VSTRING *milter_ext_from; /* externalized sender */
+ VSTRING *milter_ext_rcpt; /* externalized recipient */
} CLEANUP_STATE;
/*
{
MSG_STATS stats;
+ /*
+ * Don't log a spurious warning (for example, when soft_bounce is turned
+ * on). bounce_append() already logs a record when the logfile can't be
+ * updated. Set the write error flag, so that a maildrop queue file won't
+ * be destroyed.
+ */
if (bounce_append(BOUNCE_FLAG_CLEAN, state->queue_id,
CLEANUP_MSG_STATS(&stats, state),
rcpt, "none", dsn) != 0) {
- msg_warn("%s: bounce logfile update error", state->queue_id);
state->errs |= CLEANUP_STAT_WRITE;
}
}
#include <mail_params.h>
#include <lex_822.h>
#include <is_header.h>
+#include <quote_821_local.h>
/* Application-specific. */
/* cleanup_add_rcpt - append recipient address */
-static const char *cleanup_add_rcpt(void *context, char *rcpt)
+static const char *cleanup_add_rcpt(void *context, char *ext_rcpt)
{
const char *myname = "cleanup_add_rcpt";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
off_t new_rcpt_offset;
off_t reverse_ptr_offset;
+ int addr_count;
+ TOK822 *tree;
+ TOK822 *tp;
+ VSTRING *int_rcpt_buf;
if (msg_verbose)
- msg_info("%s: \"%s\"", myname, rcpt);
+ msg_info("%s: \"%s\"", myname, ext_rcpt);
/*
* To simplify implementation, the cleanup server writes a dummy
msg_warn("%s: seek file %s: %m", myname, cleanup_path);
return (cleanup_milter_error(state, errno));
}
- cleanup_addr_bcc(state, rcpt);
+
+ /*
+ * Transform recipient from external form to internal form. This also
+ * removes the enclosing <>, if present.
+ *
+ * XXX vstring_alloc() rejects zero-length requests.
+ */
+ int_rcpt_buf = vstring_alloc(strlen(ext_rcpt) + 1);
+ tree = tok822_parse(ext_rcpt);
+ for (addr_count = 0, tp = tree; tp != 0; tp = tp->next) {
+ if (tp->type == TOK822_ADDR) {
+ if (addr_count == 0) {
+ tok822_internalize(int_rcpt_buf, tp->head, TOK822_STR_DEFL);
+ addr_count += 1;
+ } else {
+ msg_warn("%s: Milter request to add multi-recipient: \"%s\"",
+ state->queue_id, ext_rcpt);
+ break;
+ }
+ }
+ }
+ tok822_free_tree(tree);
+ cleanup_addr_bcc(state, STR(int_rcpt_buf));
+ vstring_free(int_rcpt_buf);
+ if (addr_count == 0) {
+ msg_warn("%s: ignoring attempt from Milter to add null recipient",
+ state->queue_id);
+ return (CLEANUP_OUT_OK(state) ? 0 : cleanup_milter_error(state, 0));
+ }
if ((reverse_ptr_offset = vstream_ftell(state->dst)) < 0) {
msg_warn("%s: vstream_ftell file %s: %m", myname, cleanup_path);
return (cleanup_milter_error(state, errno));
/* cleanup_del_rcpt - remove recipient and all its expansions */
-static const char *cleanup_del_rcpt(void *context, char *rcpt)
+static const char *cleanup_del_rcpt(void *context, char *ext_rcpt)
{
const char *myname = "cleanup_del_rcpt";
CLEANUP_STATE *state = (CLEANUP_STATE *) context;
int rec_type;
int junk;
int count = 0;
+ TOK822 *tree;
+ TOK822 *tp;
+ VSTRING *int_rcpt_buf;
+ int addr_count;
if (msg_verbose)
- msg_info("%s: \"%s\"", myname, rcpt);
+ msg_info("%s: \"%s\"", myname, ext_rcpt);
/*
* Virtual aliasing and other address rewriting happens after the mail
if (dsn_orcpt != 0) \
myfree(dsn_orcpt); \
vstring_free(buf); \
+ vstring_free(int_rcpt_buf); \
return (ret); \
} while (0)
+ /*
+ * Transform recipient from external form to internal form. This also
+ * removes the enclosing <>, if present.
+ *
+ * XXX vstring_alloc() rejects zero-length requests.
+ */
+ int_rcpt_buf = vstring_alloc(strlen(ext_rcpt) + 1);
+ tree = tok822_parse(ext_rcpt);
+ for (addr_count = 0, tp = tree; tp != 0; tp = tp->next) {
+ if (tp->type == TOK822_ADDR) {
+ if (addr_count == 0) {
+ tok822_internalize(int_rcpt_buf, tp->head, TOK822_STR_DEFL);
+ addr_count += 1;
+ } else {
+ msg_warn("%s: Milter request to drop multi-recipient: \"%s\"",
+ state->queue_id, ext_rcpt);
+ break;
+ }
+ }
+ }
+ tok822_free_tree(tree);
+
buf = vstring_alloc(100);
for (;;) {
if (CLEANUP_OUT_OK(state) == 0)
orig_rcpt = mystrdup(start);
break;
case REC_TYPE_RCPT: /* rewritten RCPT TO address */
- if (strcmp(orig_rcpt ? orig_rcpt : start, rcpt) == 0) {
+ if (strcmp(orig_rcpt ? orig_rcpt : start, STR(int_rcpt_buf)) == 0) {
if (vstream_fseek(state->dst, curr_offset, SEEK_SET) < 0) {
msg_warn("%s: seek file %s: %m", myname, cleanup_path);
CLEANUP_DEL_RCPT_RETURN(cleanup_milter_error(state, errno));
if (msg_verbose)
msg_info("%s: deleted %d records for recipient \"%s\"",
- myname, count, rcpt);
+ myname, count, ext_rcpt);
CLEANUP_DEL_RCPT_RETURN(0);
}
if (strcmp(name, S8_MAC_AUTH_AUTHOR) == 0)
return (nvtable_find(state->attr, MAIL_ATTR_SASL_SENDER));
#endif
-#if 0
if (strcmp(name, S8_MAC_MAIL_ADDR) == 0)
- return (state->sender);
-#endif
+ return (state->milter_ext_from ? STR(state->milter_ext_from) : 0);
/*
* RCPT TO macros.
*/
-#if 0
if (strcmp(name, S8_MAC_RCPT_ADDR) == 0)
- return (state->recipient);
-#endif
+ return (state->milter_ext_rcpt ? STR(state->milter_ext_rcpt) : 0);
return (0);
}
}
}
if (CLEANUP_MILTER_OK(state)) {
- argv[0] = addr;
+ if (state->milter_ext_from == 0)
+ state->milter_ext_from = vstring_alloc(100);
+ /* Sendmail 8.13 does not externalize the null address. */
+ if (*addr)
+ quote_821_local(state->milter_ext_from, addr);
+ else
+ vstring_strcpy(state->milter_ext_from, addr);
+ argv[0] = STR(state->milter_ext_from);
argv[1] = 0;
if ((resp = milter_mail_event(milters, argv)) != 0) {
cleanup_milter_apply(state, "MAIL", resp);
* attribute, but CLEANUP_STAT_DEFER takes precedence. It terminates
* queue record processing, and prevents bounces from being sent.
*/
- argv[0] = addr;
+ if (state->milter_ext_rcpt == 0)
+ state->milter_ext_rcpt = vstring_alloc(100);
+ /* Sendmail 8.13 does not externalize the null address. */
+ if (*addr)
+ quote_821_local(state->milter_ext_rcpt, addr);
+ else
+ vstring_strcpy(state->milter_ext_rcpt, addr);
+ argv[0] = STR(state->milter_ext_rcpt);
argv[1] = 0;
if ((resp = milter_rcpt_event(milters, argv)) != 0
&& cleanup_milter_apply(state, "RCPT", resp) != 0) {
state->client_addr = 0;
state->client_af = 0;
state->client_port = 0;
+ state->milter_ext_from = 0;
+ state->milter_ext_rcpt = 0;
return (state);
}
myfree(state->verp_delims);
if (state->milters)
milter_free(state->milters);
+ if (state->milter_ext_from)
+ vstring_free(state->milter_ext_from);
+ if (state->milter_ext_rcpt)
+ vstring_free(state->milter_ext_rcpt);
myfree((char *) state);
}
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20061002"
-#define MAIL_VERSION_NUMBER "2.3.4-RC1"
+#define MAIL_RELEASE_DATE "20061019"
+#define MAIL_VERSION_NUMBER "2.3.4-RC2"
#ifdef SNAPSHOT
# define MAIL_VERSION_DATE "-" MAIL_RELEASE_DATE
/* configuration parameter. Upon delivery, the local delivery agent
/* tries each pathname in the list until a file is found.
/*
-/* Delivery via ~/.\fB.forward\fR files is done with the privileges
+/* Delivery via ~/.\fBforward\fR files is done with the privileges
/* of the recipient.
/* Thus, ~/.\fBforward\fR like files must be readable by the
/* recipient, and their parent directory needs to have "execute"
char *var_empty_addr;
#define STRING_FORMAT "%-10s %8s %-20s %s\n"
-#define SENDER_FORMAT "%-11s%8ld %20.20s %s\n"
-#define DROP_FORMAT "%-10s%c%8ld %20.20s (maildrop queue, sender UID %u)\n"
+#define SENDER_FORMAT "%-11s %7ld %20.20s %s\n"
+#define DROP_FORMAT "%-10s%c %7ld %20.20s (maildrop queue, sender UID %u)\n"
static void showq_reasons(VSTREAM *, BOUNCE_LOG *, RCPT_BUF *, DSN_BUF *,
HTABLE *);
* EHLO keyword filter.
*/
if (*var_smtp_ehlo_dis_maps)
- smtp_ehlo_dis_maps = maps_create(VAR_SMTPD_EHLO_DIS_MAPS,
+ smtp_ehlo_dis_maps = maps_create(VAR_SMTP_EHLO_DIS_MAPS,
var_smtp_ehlo_dis_maps,
DICT_FLAG_LOCK);
return (0);
}
state->session = session;
+ session->state = state;
/*
* XXX Temporary fix.
smtpd_chat.o: ../../include/argv.h
smtpd_chat.o: ../../include/attr.h
smtpd_chat.o: ../../include/cleanup_user.h
+smtpd_chat.o: ../../include/int_filt.h
smtpd_chat.o: ../../include/iostuff.h
smtpd_chat.o: ../../include/line_wrap.h
smtpd_chat.o: ../../include/mail_addr.h
smtpd_milter.o: ../../include/myaddrinfo.h
smtpd_milter.o: ../../include/name_code.h
smtpd_milter.o: ../../include/name_mask.h
+smtpd_milter.o: ../../include/quote_821_local.h
+smtpd_milter.o: ../../include/quote_flags.h
smtpd_milter.o: ../../include/sys_defs.h
smtpd_milter.o: ../../include/tls.h
smtpd_milter.o: ../../include/vbuf.h
/* Global library. */
#include <mail_params.h>
+#include <quote_821_local.h>
/* Milter library. */
if (strcmp(name, S8_MAC_AUTH_AUTHOR) == 0)
return (IF_SASL_ENABLED(state->sasl_sender));
#endif
- if (strcmp(name, S8_MAC_MAIL_ADDR) == 0)
- return (state->sender);
+ if (strcmp(name, S8_MAC_MAIL_ADDR) == 0) {
+ if (state->sender == 0)
+ return (0);
+ if (state->expand_buf == 0)
+ state->expand_buf = vstring_alloc(10);
+ /* Sendmail 8.13 does not externalize the null string. */
+ if (state->sender[0])
+ quote_821_local(state->expand_buf, state->sender);
+ else
+ vstring_strcpy(state->expand_buf, state->sender);
+ return (STR(state->expand_buf));
+ }
/*
* RCPT TO macros.
*/
- if (strcmp(name, S8_MAC_RCPT_ADDR) == 0)
- return (state->recipient);
-
+ if (strcmp(name, S8_MAC_RCPT_ADDR) == 0) {
+ if (state->recipient == 0)
+ return (0);
+ if (state->expand_buf == 0)
+ state->expand_buf = vstring_alloc(10);
+ /* Sendmail 8.13 does not externalize the null string. */
+ if (state->recipient[0])
+ quote_821_local(state->expand_buf, state->recipient);
+ else
+ vstring_strcpy(state->expand_buf, state->recipient);
+ return (STR(state->expand_buf));
+ }
return (0);
}