From: Wietse Venema Date: Fri, 25 Oct 2002 05:00:00 +0000 (-0500) Subject: postfix-1.1.11-20021025 X-Git-Tag: v2.0.0~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41c3d3216d0d217cd24729c4064eb33fbba24a72;p=thirdparty%2Fpostfix.git postfix-1.1.11-20021025 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index 3192c07e7..ff08a78fb 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -7075,6 +7075,14 @@ Apologies for any names omitted. Files: global/mail_params.[hc] global/own_inet_addr.[hc] global/resolve_local.c smtp/smtp_addr.c smtpd/smtpd_check.c. + Paranoia: defend against a very unlikely false alarm in + safe_open(). + +20020125 + + Feature: X-Original-To: message headers with the raw original + envelope recipient. + Open problems: Low: smtpd should log queue ID with reject/warn/hold/discard diff --git a/postfix/conf/aliases b/postfix/conf/aliases index 9e43ebc24..2b44b3aa1 100644 --- a/postfix/conf/aliases +++ b/postfix/conf/aliases @@ -8,6 +8,9 @@ # >>>>>>>>>> show through to Postfix. # +# Person who should get root's mail. Don't receive mail as root! +#root: you + # Basic system aliases -- these MUST be present MAILER-DAEMON: postmaster postmaster: root @@ -33,9 +36,6 @@ abuse: postmaster # trap decode to catch security attacks decode: root -# Person who should get root's mail -#root: you - # # ALIASES(5) ALIASES(5) # diff --git a/postfix/html/error.8.html b/postfix/html/error.8.html index a96801b32..308870567 100644 --- a/postfix/html/error.8.html +++ b/postfix/html/error.8.html @@ -1,5 +1,4 @@
-
 ERROR(8)                                                 ERROR(8)
 
 NAME
@@ -72,6 +71,5 @@ ERROR(8)                                                 ERROR(8)
        P.O. Box 704
        Yorktown Heights, NY 10598, USA
 
-                                                                1
-
+                                                         ERROR(8)
 
diff --git a/postfix/html/lmtp.8.html b/postfix/html/lmtp.8.html index 08e194752..1f9342a08 100644 --- a/postfix/html/lmtp.8.html +++ b/postfix/html/lmtp.8.html @@ -58,9 +58,9 @@ LMTP(8) LMTP(8) RFC 1652 (8bit-MIME transport) RFC 1870 (Message Size Declaration) RFC 2033 (LMTP protocol) - RFC 2197 (Pipelining) RFC 2554 (AUTH command) RFC 2821 (SMTP protocol) + RFC 2920 (SMTP Pipelining) DIAGNOSTICS Problems and transactions are logged to syslogd(8). Cor- diff --git a/postfix/html/pipe.8.html b/postfix/html/pipe.8.html index d74f25b3e..bb6a6561c 100644 --- a/postfix/html/pipe.8.html +++ b/postfix/html/pipe.8.html @@ -43,7 +43,7 @@ PIPE(8) PIPE(8) file at the end of a service definition. The syntax is as follows: - flags=BDFRhqu.> (optional) + flags=BDFORhqu.> (optional) Optional message processing flags. By default, a message is copied unchanged. @@ -61,6 +61,12 @@ PIPE(8) PIPE(8) header to the message content. This is expected by, for example, UUCP software. + O Prepend an "X-Original-To: recipient" mes- + sage header with the original envelope + recipient address. Note: for this to work, + the transport_destination_recipient_limit + must be 1. + R Prepend a Return-Path: message header with the envelope sender address. diff --git a/postfix/html/smtp.8.html b/postfix/html/smtp.8.html index d6f733457..7e6267be3 100644 --- a/postfix/html/smtp.8.html +++ b/postfix/html/smtp.8.html @@ -48,9 +48,9 @@ SMTP(8) SMTP(8) RFC 1870 (Message Size Declaration) RFC 2045 (MIME: Format of Internet Message Bodies) RFC 2046 (MIME: Media Types) - RFC 2197 (Pipelining) RFC 2554 (AUTH command) RFC 2821 (SMTP protocol) + RFC 2920 (SMTP Pipelining) DIAGNOSTICS Problems and transactions are logged to syslogd(8). Cor- diff --git a/postfix/html/smtpd.8.html b/postfix/html/smtpd.8.html index a040d0ae3..77245cdc7 100644 --- a/postfix/html/smtpd.8.html +++ b/postfix/html/smtpd.8.html @@ -36,11 +36,11 @@ SMTPD(8) SMTPD(8) RFC 1123 (Host requirements) RFC 1652 (8bit-MIME transport) RFC 1869 (SMTP service extensions) - RFC 1854 (SMTP Pipelining) RFC 1870 (Message Size Declaration) RFC 1985 (ETRN command) RFC 2554 (AUTH command) RFC 2821 (SMTP protocol) + RFC 2920 (SMTP Pipelining) DIAGNOSTICS Problems and transactions are logged to syslogd(8). diff --git a/postfix/man/man8/lmtp.8 b/postfix/man/man8/lmtp.8 index c53e0033c..75e42c57a 100644 --- a/postfix/man/man8/lmtp.8 +++ b/postfix/man/man8/lmtp.8 @@ -59,9 +59,9 @@ RFC 1651 (SMTP service extensions) RFC 1652 (8bit-MIME transport) RFC 1870 (Message Size Declaration) RFC 2033 (LMTP protocol) -RFC 2197 (Pipelining) RFC 2554 (AUTH command) RFC 2821 (SMTP protocol) +RFC 2920 (SMTP Pipelining) .SH DIAGNOSTICS .ad .fi diff --git a/postfix/man/man8/pipe.8 b/postfix/man/man8/pipe.8 index 233e7df3e..c93705999 100644 --- a/postfix/man/man8/pipe.8 +++ b/postfix/man/man8/pipe.8 @@ -50,7 +50,7 @@ entry for the pipe-based delivery transport. .fi The external command attributes are given in the \fBmaster.cf\fR file at the end of a service definition. The syntax is as follows: -.IP "\fBflags=BDFRhqu.>\fR (optional)" +.IP "\fBflags=BDFORhqu.>\fR (optional)" Optional message processing flags. By default, a message is copied unchanged. .RS @@ -66,6 +66,10 @@ envelope recipient address. Note: for this to work, the Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to the message content. This is expected by, for example, \fBUUCP\fR software. +.IP \fBO\fR +Prepend an "\fBX-Original-To: \fIrecipient\fR" message header +with the original envelope recipient address. Note: for this to work, +the \fItransport\fB_destination_recipient_limit\fR must be 1. .IP \fBR\fR Prepend a \fBReturn-Path:\fR message header with the envelope sender address. diff --git a/postfix/man/man8/smtp.8 b/postfix/man/man8/smtp.8 index 018a6f6b7..15bee3add 100644 --- a/postfix/man/man8/smtp.8 +++ b/postfix/man/man8/smtp.8 @@ -53,9 +53,9 @@ RFC 1652 (8bit-MIME transport) RFC 1870 (Message Size Declaration) RFC 2045 (MIME: Format of Internet Message Bodies) RFC 2046 (MIME: Media Types) -RFC 2197 (Pipelining) RFC 2554 (AUTH command) RFC 2821 (SMTP protocol) +RFC 2920 (SMTP Pipelining) .SH DIAGNOSTICS .ad .fi diff --git a/postfix/man/man8/smtpd.8 b/postfix/man/man8/smtpd.8 index 393e85b5c..fe5ab654a 100644 --- a/postfix/man/man8/smtpd.8 +++ b/postfix/man/man8/smtpd.8 @@ -44,11 +44,11 @@ RFC 821 (SMTP protocol) RFC 1123 (Host requirements) RFC 1652 (8bit-MIME transport) RFC 1869 (SMTP service extensions) -RFC 1854 (SMTP Pipelining) RFC 1870 (Message Size Declaration) RFC 1985 (ETRN command) RFC 2554 (AUTH command) RFC 2821 (SMTP protocol) +RFC 2920 (SMTP Pipelining) .SH DIAGNOSTICS .ad .fi diff --git a/postfix/src/bounce/bounce.c b/postfix/src/bounce/bounce.c index dd92ec8f5..0e33b3d2b 100644 --- a/postfix/src/bounce/bounce.c +++ b/postfix/src/bounce/bounce.c @@ -127,6 +127,7 @@ char *var_delay_rcpt; */ static VSTRING *queue_id; static VSTRING *queue_name; +static VSTRING *orig_rcpt; static VSTRING *recipient; static VSTRING *encoding; static VSTRING *sender; @@ -147,9 +148,10 @@ static int bounce_append_proto(char *service_name, VSTREAM *client) if (mail_command_server(client, ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, &flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, why, - ATTR_TYPE_END) != 4) { + ATTR_TYPE_END) != 5) { msg_warn("malformed request"); return (-1); } @@ -298,9 +300,10 @@ static int bounce_one_proto(char *service_name, VSTREAM *client) ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, queue_id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, why, - ATTR_TYPE_END) != 7) { + ATTR_TYPE_END) != 8) { msg_warn("malformed request"); return (-1); } @@ -403,6 +406,7 @@ static void post_jail_init(char *unused_name, char **unused_argv) */ queue_id = vstring_alloc(10); queue_name = vstring_alloc(10); + orig_rcpt = vstring_alloc(10); recipient = vstring_alloc(10); encoding = vstring_alloc(10); sender = vstring_alloc(10); diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index 94ca492bb..92fb6bb62 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -43,6 +43,7 @@ typedef struct CLEANUP_STATE { char *from; /* From: address */ char *resent_from; /* Resent-From: address */ char *recip; /* envelope recipient address */ + char *orig_rcpt; /* original recipient address */ char *return_receipt; /* return-receipt address */ char *errors_to; /* errors-to address */ int flags; /* processing options */ @@ -168,7 +169,7 @@ extern void cleanup_map11_tree(CLEANUP_STATE *, TOK822 *, MAPS *, int); /* * cleanup_map1n.c */ -ARGV *cleanup_map1n_internal(CLEANUP_STATE *, char *, MAPS *, int); +ARGV *cleanup_map1n_internal(CLEANUP_STATE *, const char *, MAPS *, int); /* * cleanup_masquerade.c @@ -180,7 +181,7 @@ extern void cleanup_masquerade_tree(TOK822 *, ARGV *); /* * Cleanup_recipient.c */ -extern void cleanup_out_recipient(CLEANUP_STATE *, char *); +extern void cleanup_out_recipient(CLEANUP_STATE *, const char *, const char *); /* LICENSE /* .ad diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index a4261c0fa..6464b4827 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -253,6 +253,7 @@ int cleanup_flush(CLEANUP_STATE *state) if (state->errs != 0) { if (CAN_BOUNCE()) { if (bounce_append(BOUNCE_FLAG_CLEAN, state->queue_id, + state->recip ? state->recip : "unknown", state->recip ? state->recip : "unknown", "cleanup", state->time, "%s", state->reason ? state->reason : diff --git a/postfix/src/cleanup/cleanup_envelope.c b/postfix/src/cleanup/cleanup_envelope.c index 3d0c2019e..64b56e6ff 100644 --- a/postfix/src/cleanup/cleanup_envelope.c +++ b/postfix/src/cleanup/cleanup_envelope.c @@ -180,6 +180,8 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, state->errs |= CLEANUP_STAT_BAD; return; } + if (state->orig_rcpt == 0) + state->orig_rcpt = mystrdup(buf); cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr); if (cleanup_rcpt_canon_maps) cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, @@ -190,10 +192,12 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, if (cleanup_masq_domains && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); - cleanup_out_recipient(state, STR(clean_addr)); + cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr)); if (state->recip == 0) state->recip = mystrdup(STR(clean_addr)); vstring_free(clean_addr); + myfree(state->orig_rcpt); + state->orig_rcpt = 0; } else if (type == REC_TYPE_WARN) { if ((state->warn_time = atol(buf)) < 0) { state->errs |= CLEANUP_STAT_BAD; @@ -227,6 +231,14 @@ static void cleanup_envelope_process(CLEANUP_STATE *state, int type, char *buf, } nvtable_update(state->attr, attr_name, attr_value); } else { + if (state->orig_rcpt != 0) { + msg_warn("%s: out-of-order original recipient <%.200s>", + state->queue_id, buf); + myfree(state->orig_rcpt); + state->orig_rcpt = 0; + } + if (type == REC_TYPE_ORCP) + state->orig_rcpt = mystrdup(buf); cleanup_out(state, type, buf, len); } } diff --git a/postfix/src/cleanup/cleanup_extracted.c b/postfix/src/cleanup/cleanup_extracted.c index a1c9d6b07..f964380f7 100644 --- a/postfix/src/cleanup/cleanup_extracted.c +++ b/postfix/src/cleanup/cleanup_extracted.c @@ -129,6 +129,8 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, if (type == REC_TYPE_RCPT) { clean_addr = vstring_alloc(100); + if (state->orig_rcpt == 0) + state->orig_rcpt = mystrdup(buf); cleanup_rewrite_internal(clean_addr, *buf ? buf : var_empty_addr); if (cleanup_rcpt_canon_maps) cleanup_map11_internal(state, clean_addr, cleanup_rcpt_canon_maps, @@ -139,11 +141,22 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, if (cleanup_masq_domains && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); - cleanup_out_recipient(state, STR(clean_addr)); + cleanup_out_recipient(state, state->orig_rcpt, STR(clean_addr)); if (state->recip == 0) state->recip = mystrdup(STR(clean_addr)); vstring_free(clean_addr); + myfree(state->orig_rcpt); + state->orig_rcpt = 0; return; + } else { + if (state->orig_rcpt != 0) { + msg_warn("%s: out-of-order original recipient <%.200s>", + state->queue_id, buf); + myfree(state->orig_rcpt); + state->orig_rcpt = 0; + } + if (type == REC_TYPE_ORCP) + state->orig_rcpt = mystrdup(buf); } if (type != REC_TYPE_END) { cleanup_out(state, type, buf, len); @@ -187,9 +200,10 @@ static void cleanup_extracted_process(CLEANUP_STATE *state, int type, char *buf, && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_ENV_RCPT)) { vstring_strcpy(clean_addr, *cpp); cleanup_masquerade_internal(clean_addr, cleanup_masq_domains); - cleanup_out_recipient(state, STR(clean_addr)); + cleanup_out_recipient(state, STR(clean_addr), + STR(clean_addr)); /* XXX */ } else - cleanup_out_recipient(state, *cpp); + cleanup_out_recipient(state, *cpp, *cpp); /* XXX */ } if (rcpt->argv[0]) state->recip = mystrdup(rcpt->argv[0]); diff --git a/postfix/src/cleanup/cleanup_map1n.c b/postfix/src/cleanup/cleanup_map1n.c index 4e6e6f290..e83f4fb62 100644 --- a/postfix/src/cleanup/cleanup_map1n.c +++ b/postfix/src/cleanup/cleanup_map1n.c @@ -6,8 +6,11 @@ /* SYNOPSIS /* #include /* -/* ARGV *cleanup_map1n_internal(addr) -/* char *addr; +/* ARGV *cleanup_map1n_internal(state, addr, maps, propagate) +/* CLEANUP_STATE *state; +/* const char *addr; +/* MAPS *maps; +/* int propagate; /* DESCRIPTION /* This module implements one-to-many table mapping via table lookup. /* Table lookups are done with quoted (externalized) address forms. @@ -63,7 +66,7 @@ /* cleanup_map1n_internal - one-to-many table lookups */ -ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, char *addr, +ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, const char *addr, MAPS *maps, int propagate) { ARGV *argv; diff --git a/postfix/src/cleanup/cleanup_out_recipient.c b/postfix/src/cleanup/cleanup_out_recipient.c index bb283aa3c..a45bba88b 100644 --- a/postfix/src/cleanup/cleanup_out_recipient.c +++ b/postfix/src/cleanup/cleanup_out_recipient.c @@ -6,9 +6,10 @@ /* SYNOPSIS /* #include "cleanup.h" /* -/* void cleanup_out_recipient(state, recipient) +/* void cleanup_out_recipient(state, orig_recipient, recipient) /* CLEANUP_STATE *state; -/* char *recipient; +/* const char *orig_recipient; +/* const char *recipient; /* DESCRIPTION /* This module implements an envelope recipient output filter. /* @@ -38,6 +39,11 @@ /* System library. */ #include +#include + +#ifdef STRCASECMP_IN_STRINGS_H +#include +#endif /* Utility library. */ @@ -56,20 +62,29 @@ /* cleanup_out_recipient - envelope recipient output filter */ -void cleanup_out_recipient(CLEANUP_STATE *state, char *recip) +void cleanup_out_recipient(CLEANUP_STATE *state, const char *orcpt, + const char *recip) { ARGV *argv; char **cpp; if (cleanup_virtual_maps == 0) { - if (been_here_fixed(state->dups, recip) == 0) - cleanup_out_string(state, REC_TYPE_RCPT, recip), state->rcpt_count++; + if (been_here_fixed(state->dups, orcpt) == 0) { + if (strcasecmp(orcpt, recip) != 0) + cleanup_out_string(state, REC_TYPE_ORCP, orcpt); + cleanup_out_string(state, REC_TYPE_RCPT, recip); + state->rcpt_count++; + } } else { argv = cleanup_map1n_internal(state, recip, cleanup_virtual_maps, cleanup_ext_prop_mask & EXT_PROP_VIRTUAL); - for (cpp = argv->argv; *cpp; cpp++) - if (been_here_fixed(state->dups, *cpp) == 0) - cleanup_out_string(state, REC_TYPE_RCPT, *cpp), state->rcpt_count++; + if (been_here_fixed(state->dups, orcpt) == 0) { + for (cpp = argv->argv; *cpp; cpp++) { + cleanup_out_string(state, REC_TYPE_ORCP, orcpt); + cleanup_out_string(state, REC_TYPE_RCPT, *cpp); + state->rcpt_count++; + } + } argv_free(argv); } } diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index 1e7bb8890..522db49c2 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -68,6 +68,7 @@ CLEANUP_STATE *cleanup_state_alloc(void) state->from = 0; state->resent_from = 0; state->recip = 0; + state->orig_rcpt = 0; state->return_receipt = 0; state->errors_to = 0; state->flags = 0; @@ -110,6 +111,8 @@ void cleanup_state_free(CLEANUP_STATE *state) myfree(state->resent_from); if (state->recip) myfree(state->recip); + if (state->orig_rcpt) + myfree(state->orig_rcpt); if (state->return_receipt) myfree(state->return_receipt); if (state->errors_to) diff --git a/postfix/src/error/error.c b/postfix/src/error/error.c index 3b43f519b..7129f3129 100644 --- a/postfix/src/error/error.c +++ b/postfix/src/error/error.c @@ -129,7 +129,7 @@ static int deliver_message(DELIVER_REQUEST *request) rcpt = request->rcpt_list.info + nrcpt; if (rcpt->offset >= 0) { status = bounce_append(BOUNCE_FLAG_KEEP, request->queue_id, - rcpt->address, "error", + rcpt->orig_addr, rcpt->address, "error", request->arrival_time, "%s", request->nexthop); if (status == 0) diff --git a/postfix/src/global/bounce.c b/postfix/src/global/bounce.c index 14b74f84b..13d5fc20f 100644 --- a/postfix/src/global/bounce.c +++ b/postfix/src/global/bounce.c @@ -6,17 +6,21 @@ /* SYNOPSIS /* #include /* -/* int bounce_append(flags, id, recipient, relay, entry, format, ...) +/* int bounce_append(flags, id, orig_rcpt, recipient, relay, +/* entry, format, ...) /* int flags; /* const char *id; +/* const char *orig_rcpt; /* const char *recipient; /* const char *relay; /* time_t entry; /* const char *format; /* -/* int vbounce_append(flags, id, recipient, relay, entry, format, ap) +/* int vbounce_append(flags, id, orig_rcpt, recipient, relay, +/* entry, format, ap) /* int flags; /* const char *id; +/* const char *orig_rcpt; /* const char *recipient; /* const char *relay; /* time_t entry; @@ -42,13 +46,14 @@ /* time_t entry; /* const char *format; /* -/* int vbounce_one(flags, queue, id, encoding, sender, +/* int vbounce_one(flags, queue, id, encoding, sender, orig_rcpt, /* recipient, relay, entry, format, ap) /* int flags; /* const char *queue; /* const char *id; /* const char *encoding; /* const char *sender; +/* const char *orig_rcpt; /* const char *recipient; /* const char *relay; /* time_t entry; @@ -68,10 +73,10 @@ /* the specified sender, including the bounce log that was /* built with bounce_append(). /* -/* bounce_one() bounces one recipient and immediately sends a -/* notification to the sender. This procedure does not append -/* the recipient and reason to the per-message bounce log, and -/* should be used when a delivery agent changes the error +/* bounce_one() bounces one recipient and immediately sends a +/* notification to the sender. This procedure does not append +/* the recipient and reason to the per-message bounce log, and +/* should be used when a delivery agent changes the error /* return address in a manner that depends on the recipient /* address. /* @@ -100,6 +105,8 @@ /* This information is used for syslogging only. /* .IP entry /* Message arrival time. +/* .IP orig_rcpt +/* The original envelope recipient address. /* .IP recipient /* Recipient address that the message could not be delivered to. /* This information is used for syslogging only. @@ -147,22 +154,25 @@ /* bounce_append - append reason to per-message bounce log */ -int bounce_append(int flags, const char *id, const char *recipient, - const char *relay, time_t entry, const char *fmt,...) +int bounce_append(int flags, const char *id, const char *orig_rcpt, + const char *recipient, const char *relay, + time_t entry, const char *fmt,...) { va_list ap; int status; va_start(ap, fmt); - status = vbounce_append(flags, id, recipient, relay, entry, fmt, ap); + status = vbounce_append(flags, id, orig_rcpt, recipient, + relay, entry, fmt, ap); va_end(ap); return (status); } /* vbounce_append - append bounce reason to per-message log */ -int vbounce_append(int flags, const char *id, const char *recipient, - const char *relay, time_t entry, const char *fmt, va_list ap) +int vbounce_append(int flags, const char *id, const char *orig_rcpt, + const char *recipient, const char *relay, + time_t entry, const char *fmt, va_list ap) { VSTRING *why; int status; @@ -184,16 +194,18 @@ int vbounce_append(int flags, const char *id, const char *recipient, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why), ATTR_TYPE_END) == 0) { - msg_info("%s: to=<%s>, relay=%s, delay=%d, status=%s (%s%s)", - id, recipient, relay, delay, var_soft_bounce ? "deferred" : - "bounced", var_soft_bounce ? "SOFT BOUNCE - " : "", + msg_info("%s: orig_to=<%s>, to=<%s>, relay=%s, delay=%d, status=%s (%s%s)", + id, orig_rcpt, recipient, relay, delay, + var_soft_bounce ? "deferred" : "bounced", + var_soft_bounce ? "SOFT BOUNCE - " : "", vstring_str(why)); status = (var_soft_bounce ? -1 : 0); } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { - status = defer_append(flags, id, recipient, "bounce", entry, + status = defer_append(flags, id, orig_rcpt, recipient, "bounce", entry, "bounce failed"); } else { status = -1; @@ -235,14 +247,15 @@ int bounce_flush(int flags, const char *queue, const char *id, int bounce_one(int flags, const char *queue, const char *id, const char *encoding, const char *sender, - const char *recipient, const char *relay, - time_t entry, const char *fmt,...) + const char *orig_rcpt, const char *recipient, + const char *relay, time_t entry, + const char *fmt,...) { va_list ap; int status; va_start(ap, fmt); - status = vbounce_one(flags, queue, id, encoding, sender, + status = vbounce_one(flags, queue, id, encoding, sender, orig_rcpt, recipient, relay, entry, fmt, ap); va_end(ap); return (status); @@ -252,8 +265,9 @@ int bounce_one(int flags, const char *queue, const char *id, int vbounce_one(int flags, const char *queue, const char *id, const char *encoding, const char *sender, - const char *recipient, const char *relay, - time_t entry, const char *fmt, va_list ap) + const char *orig_rcpt, const char *recipient, + const char *relay, time_t entry, + const char *fmt, va_list ap) { VSTRING *why; int status; @@ -264,7 +278,8 @@ int vbounce_one(int flags, const char *queue, const char *id, * procedure. */ if (var_soft_bounce) - return (vbounce_append(flags, id, recipient, relay, entry, fmt, ap)); + return (vbounce_append(flags, id, orig_rcpt, recipient, + relay, entry, fmt, ap)); why = vstring_alloc(100); delay = time((time_t *) 0) - entry; @@ -276,6 +291,7 @@ int vbounce_one(int flags, const char *queue, const char *id, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, ATTR_TYPE_STR, MAIL_ATTR_ENCODING, encoding, ATTR_TYPE_STR, MAIL_ATTR_SENDER, sender, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why), ATTR_TYPE_END) == 0) { @@ -283,7 +299,7 @@ int vbounce_one(int flags, const char *queue, const char *id, id, recipient, relay, delay, vstring_str(why)); status = 0; } else if ((flags & BOUNCE_FLAG_CLEAN) == 0) { - status = defer_append(flags, id, recipient, "bounce", entry, + status = defer_append(flags, id, orig_rcpt, recipient, "bounce", entry, "bounce failed"); } else { status = -1; diff --git a/postfix/src/global/bounce.h b/postfix/src/global/bounce.h index 301ba72d1..caaccbfb7 100644 --- a/postfix/src/global/bounce.h +++ b/postfix/src/global/bounce.h @@ -20,19 +20,21 @@ /* * Client interface. */ -extern int PRINTFLIKE(6, 7) bounce_append(int, const char *, const char *, +extern int PRINTFLIKE(7, 8) bounce_append(int, const char *, + const char *, const char *, const char *, time_t, const char *,...); extern int vbounce_append(int, const char *, const char *, const char *, - time_t, const char *, va_list); + const char *, time_t, const char *, va_list); extern int bounce_flush(int, const char *, const char *, const char *, const char *); -extern int PRINTFLIKE(9, 10) bounce_one(int, const char *, const char *, +extern int PRINTFLIKE(10, 11) bounce_one(int, const char *, const char *, const char *, const char *, const char *, const char *, - time_t, const char *,...); + const char *, time_t, + const char *,...); extern int vbounce_one(int, const char *, const char *, const char *, const char *, const char *, const char *, - time_t, const char *, va_list); + const char *, time_t, const char *, va_list); /* * Bounce/defer protocol commands. diff --git a/postfix/src/global/defer.c b/postfix/src/global/defer.c index 862f3a6fd..beb8b04a5 100644 --- a/postfix/src/global/defer.c +++ b/postfix/src/global/defer.c @@ -6,17 +6,21 @@ /* SYNOPSIS /* #include /* -/* int defer_append(flags, id, recipient, relay, entry, format, ...) +/* int defer_append(flags, id, orig_rcpt, recipient, relay, +/* entry, format, ...) /* int flags; /* const char *id; +/* const char *orig_rcpt; /* const char *recipient; /* const char *relay; /* time_t entry; /* const char *format; /* -/* int vdefer_append(flags, id, recipient, relay, entry, format, ap) +/* int vdefer_append(flags, id, orig_rcpt, recipient, relay, +/* entry, format, ap) /* int flags; /* const char *id; +/* const char *orig_rcpt; /* const char *recipient; /* const char *relay; /* time_t entry; @@ -68,6 +72,8 @@ /* The message queue name of the original message file. /* .IP id /* The queue id of the original message file. +/* .IP orig_rcpt +/* The original envelope recipient address. /* .IP recipient /* A recipient address that is being deferred. The domain part /* of the address is marked dead (for a limited amount of time). @@ -127,22 +133,25 @@ /* defer_append - defer message delivery */ -int defer_append(int flags, const char *id, const char *recipient, - const char *relay, time_t entry, const char *fmt,...) +int defer_append(int flags, const char *id, const char *orig_rcpt, + const char *recipient, const char *relay, + time_t entry, const char *fmt,...) { va_list ap; int status; va_start(ap, fmt); - status = vdefer_append(flags, id, recipient, relay, entry, fmt, ap); + status = vdefer_append(flags, id, orig_rcpt, recipient, + relay, entry, fmt, ap); va_end(ap); return (status); } /* vdefer_append - defer delivery of queue file */ -int vdefer_append(int flags, const char *id, const char *recipient, - const char *relay, time_t entry, const char *fmt, va_list ap) +int vdefer_append(int flags, const char *id, const char *orig_rcpt, + const char *recipient, const char *relay, + time_t entry, const char *fmt, va_list ap) { VSTRING *why = vstring_alloc(100); int delay = time((time_t *) 0) - entry; @@ -153,12 +162,13 @@ int vdefer_append(int flags, const char *id, const char *recipient, ATTR_TYPE_NUM, MAIL_ATTR_NREQ, BOUNCE_CMD_APPEND, ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, flags, ATTR_TYPE_STR, MAIL_ATTR_QUEUEID, id, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_rcpt, ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient, ATTR_TYPE_STR, MAIL_ATTR_WHY, vstring_str(why), ATTR_TYPE_END) != 0) msg_warn("%s: defer service failure", id); - msg_info("%s: to=<%s>, relay=%s, delay=%d, status=deferred (%s)", - id, recipient, relay, delay, vstring_str(why)); + msg_info("%s: orig_to=<%s>, to=<%s>, relay=%s, delay=%d, status=deferred (%s)", + id, orig_rcpt, recipient, relay, delay, vstring_str(why)); vstring_free(why); /* diff --git a/postfix/src/global/defer.h b/postfix/src/global/defer.h index 18bbbddd9..acc7bfb91 100644 --- a/postfix/src/global/defer.h +++ b/postfix/src/global/defer.h @@ -25,10 +25,11 @@ /* * External interface. */ -extern int PRINTFLIKE(6, 7) defer_append(int, const char *, const char *, - const char *, time_t, const char *,...); +extern int PRINTFLIKE(7, 8) defer_append(int, const char *, const char *, + const char *, const char *, time_t, + const char *,...); extern int vdefer_append(int, const char *, const char *, const char *, - time_t, const char *, va_list); + const char *, time_t, const char *, va_list); extern int defer_flush(int, const char *, const char *, const char *, const char *); extern int defer_warn(int, const char *, const char *, const char *); diff --git a/postfix/src/global/deliver_pass.c b/postfix/src/global/deliver_pass.c index d2492292f..91ecb467a 100644 --- a/postfix/src/global/deliver_pass.c +++ b/postfix/src/global/deliver_pass.c @@ -6,10 +6,11 @@ /* SYNOPSIS /* #include /* -/* int deliver_pass(class, service, request, address, offset) +/* int deliver_pass(class, service, request, orig_addr, address, offset) /* const char *class; /* const char *service; /* DELIVER_REQUEST *request; +/* const char *orig_addr; /* const char *address; /* long offset; /* @@ -89,7 +90,8 @@ static int deliver_pass_initial_reply(VSTREAM *stream) /* deliver_pass_send_request - send delivery request to delivery process */ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, - const char *nexthop, const char *addr, long offs) + const char *nexthop, const char *orcpt, + const char *addr, long offs) { int stat; @@ -106,6 +108,7 @@ static int deliver_pass_send_request(VSTREAM *stream, DELIVER_REQUEST *request, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, request->return_receipt, ATTR_TYPE_LONG, MAIL_ATTR_TIME, request->arrival_time, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, offs, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orcpt ? orcpt : "", ATTR_TYPE_STR, MAIL_ATTR_RECIP, addr, ATTR_TYPE_NUM, MAIL_ATTR_OFFSET, 0, ATTR_TYPE_END); @@ -138,7 +141,8 @@ static int deliver_pass_final_reply(VSTREAM *stream, VSTRING *reason) /* deliver_pass - deliver one per-site queue entry */ int deliver_pass(const char *class, const char *service, - DELIVER_REQUEST *request, const char *addr, long offs) + DELIVER_REQUEST *request, const char *orig_addr, + const char *addr, long offs) { VSTREAM *stream; VSTRING *reason; @@ -175,7 +179,7 @@ int deliver_pass(const char *class, const char *service, */ if ((status = deliver_pass_initial_reply(stream)) == 0 && (status = deliver_pass_send_request(stream, request, nexthop, - addr, offs)) == 0) + orig_addr, addr, offs)) == 0) status = deliver_pass_final_reply(stream, reason); /* @@ -200,6 +204,7 @@ int deliver_pass_all(const char *class, const char *service, list = &request->rcpt_list; for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) status |= deliver_pass(class, service, request, - rcpt->address, rcpt->offset); + rcpt->orig_addr, rcpt->address, + rcpt->offset); return (status); } diff --git a/postfix/src/global/deliver_pass.h b/postfix/src/global/deliver_pass.h index 39e3e0f06..1854cda03 100644 --- a/postfix/src/global/deliver_pass.h +++ b/postfix/src/global/deliver_pass.h @@ -20,7 +20,7 @@ /* * External interface. */ -extern int deliver_pass(const char *, const char *, DELIVER_REQUEST *, const char *, long); +extern int deliver_pass(const char *, const char *, DELIVER_REQUEST *, const char *, const char *, long); extern int deliver_pass_all(const char *, const char *, DELIVER_REQUEST *); /* LICENSE diff --git a/postfix/src/global/deliver_request.c b/postfix/src/global/deliver_request.c index 75dd3c61b..b855d13a2 100644 --- a/postfix/src/global/deliver_request.c +++ b/postfix/src/global/deliver_request.c @@ -171,6 +171,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) static VSTRING *queue_id; static VSTRING *nexthop; static VSTRING *encoding; + static VSTRING *orig_addr; static VSTRING *address; static VSTRING *errors_to; static VSTRING *return_receipt; @@ -186,6 +187,7 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) queue_id = vstring_alloc(10); nexthop = vstring_alloc(10); encoding = vstring_alloc(10); + orig_addr = vstring_alloc(10); address = vstring_alloc(10); errors_to = vstring_alloc(10); return_receipt = vstring_alloc(10); @@ -207,8 +209,10 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) ATTR_TYPE_STR, MAIL_ATTR_ERRTO, errors_to, ATTR_TYPE_STR, MAIL_ATTR_RRCPT, return_receipt, ATTR_TYPE_LONG, MAIL_ATTR_TIME, &request->arrival_time, - ATTR_TYPE_END) != 11) + ATTR_TYPE_END) != 11) { + msg_warn("%s: error receiving common attributes", myname); return (-1); + } if (mail_open_ok(vstring_str(queue_name), vstring_str(queue_id), &st, &path) == 0) return (-1); @@ -228,15 +232,22 @@ static int deliver_request_get(VSTREAM *stream, DELIVER_REQUEST *request) for (;;) { if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &offset, - ATTR_TYPE_END) != 1) + ATTR_TYPE_END) != 1) { + msg_warn("%s: error receiving offset attribute", myname); return (-1); + } if (offset == 0) break; if (attr_scan(stream, ATTR_FLAG_MORE | ATTR_FLAG_STRICT, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, orig_addr, ATTR_TYPE_STR, MAIL_ATTR_RECIP, address, - ATTR_TYPE_END) != 1) + ATTR_TYPE_END) != 2) { + msg_warn("%s: error receiving recipient attributes", myname); return (-1); - recipient_list_add(&request->rcpt_list, offset, vstring_str(address)); + } + recipient_list_add(&request->rcpt_list, offset, + *vstring_str(orig_addr) ? vstring_str(orig_addr) : 0, + vstring_str(address)); } /* diff --git a/postfix/src/global/deliver_request.h b/postfix/src/global/deliver_request.h index bf4f135b5..c7435afa7 100644 --- a/postfix/src/global/deliver_request.h +++ b/postfix/src/global/deliver_request.h @@ -61,7 +61,7 @@ typedef struct VSTREAM _deliver_vstream_; extern DELIVER_REQUEST *deliver_request_read(_deliver_vstream_ *); extern int deliver_request_done(_deliver_vstream_ *, DELIVER_REQUEST *, int); -extern int deliver_pass(const char *, const char *, DELIVER_REQUEST *, const char *, long); +extern int deliver_pass(const char *, const char *, DELIVER_REQUEST *, const char *, const char *, long); /* LICENSE /* .ad diff --git a/postfix/src/global/mail_copy.c b/postfix/src/global/mail_copy.c index c2d328981..596bd8c4b 100644 --- a/postfix/src/global/mail_copy.c +++ b/postfix/src/global/mail_copy.c @@ -6,8 +6,9 @@ /* SYNOPSIS /* #include /* -/* int mail_copy(sender, delivered, src, dst, flags, eol, why) +/* int mail_copy(sender, envrcpt, delivered, src, dst, flags, eol, why) /* const char *sender; +/* const char *envrcpt; /* const char *delivered; /* VSTREAM *src; /* VSTREAM *dst; @@ -48,6 +49,9 @@ /* .IP MAIL_COPY_DELIVERED /* Prepend a Delivered-To: header with the name of the /* \fIdelivered\fR attribute. +/* .IP MAIL_COPY_ORIG_RCPT +/* Prepend an X-Original-To: header with the original +/* envelope recipient address. /* .IP MAIL_COPY_RETURN_PATH /* Prepend a Return-Path: header with the value of the /* \fIsender\fR attribute. @@ -113,7 +117,9 @@ /* mail_copy - copy message with extreme prejudice */ -int mail_copy(const char *sender, const char *delivered, +int mail_copy(const char *sender, + const char *orig_rcpt, + const char *delivered, VSTREAM *src, VSTREAM *dst, int flags, const char *eol, VSTRING *why) { @@ -156,6 +162,13 @@ int mail_copy(const char *sender, const char *delivered, *sender ? vstring_str(buf) : "", eol); } } + if (flags & MAIL_COPY_ORIG_RCPT) { + if (orig_rcpt == 0) + msg_panic("%s: null orig_rcpt", myname); + quote_822_local(buf, orig_rcpt); + vstream_fprintf(dst, "X-Original-To: %s%s", + lowercase(vstring_str(buf)), eol); + } if (flags & MAIL_COPY_DELIVERED) { if (delivered == 0) msg_panic("%s: null delivered", myname); diff --git a/postfix/src/global/mail_copy.h b/postfix/src/global/mail_copy.h index efa1957c5..e7d650ff8 100644 --- a/postfix/src/global/mail_copy.h +++ b/postfix/src/global/mail_copy.h @@ -20,7 +20,8 @@ /* * External interface. */ -extern int mail_copy(const char *, const char *, VSTREAM *, VSTREAM *, +extern int mail_copy(const char *, const char *, const char *, + VSTREAM *, VSTREAM *, int, const char *, VSTRING *); #define MAIL_COPY_QUOTE (1<<0) /* prepend > to From_ */ @@ -30,9 +31,12 @@ extern int mail_copy(const char *, const char *, VSTREAM *, VSTREAM *, #define MAIL_COPY_RETURN_PATH (1<<4) /* prepend Return-Path: */ #define MAIL_COPY_DOT (1<<5) /* escape dots - needed for bsmtp */ #define MAIL_COPY_BLANK (1<<6) /* append blank line */ +#define MAIL_COPY_ORIG_RCPT (1<<7) /* prepend Delivered-To: */ #define MAIL_COPY_MBOX (MAIL_COPY_FROM | MAIL_COPY_QUOTE | \ MAIL_COPY_TOFILE | MAIL_COPY_DELIVERED | \ - MAIL_COPY_RETURN_PATH | MAIL_COPY_BLANK) + MAIL_COPY_RETURN_PATH | MAIL_COPY_BLANK | \ + MAIL_COPY_ORIG_RCPT) + #define MAIL_COPY_NONE 0 /* all turned off */ #define MAIL_COPY_STAT_OK 0 diff --git a/postfix/src/global/mail_proto.h b/postfix/src/global/mail_proto.h index 89b005b0c..4168d7ead 100644 --- a/postfix/src/global/mail_proto.h +++ b/postfix/src/global/mail_proto.h @@ -84,6 +84,7 @@ extern char *mail_pathname(const char *, const char *); #define MAIL_ATTR_QUEUE "queue_name" #define MAIL_ATTR_QUEUEID "queue_id" #define MAIL_ATTR_SENDER "sender" +#define MAIL_ATTR_ORCPT "original_recipient" #define MAIL_ATTR_RECIP "recipient" #define MAIL_ATTR_WHY "reason" #define MAIL_ATTR_VERPDL "verp_delimiters" diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 476dbc4fb..e4b133be5 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 "20021024" +#define MAIL_RELEASE_DATE "20021025" #define VAR_MAIL_VERSION "mail_version" #define DEF_MAIL_VERSION "1.1.11-" MAIL_RELEASE_DATE diff --git a/postfix/src/global/pipe_command.c b/postfix/src/global/pipe_command.c index 7cee11d7f..b8f07823b 100644 --- a/postfix/src/global/pipe_command.c +++ b/postfix/src/global/pipe_command.c @@ -51,6 +51,9 @@ /* .IP "PIPE_CMD_SENDER (char *)" /* The envelope sender address, which is passed on to the /* \fImail_copy\fR() routine. +/* .IP "PIPE_CMD_ORIG_RCPT (char *)" +/* The original recipient envelope address, which is passed on +/* to the \fImail_copy\fR() routine. /* .IP "PIPE_CMD_DELIVERED (char *)" /* The recipient envelope address, which is passed on to the /* \fImail_copy\fR() routine. @@ -145,6 +148,7 @@ struct pipe_args { int flags; /* see mail_copy.h */ char *sender; /* envelope sender */ + char *orig_rcpt; /* original recipient */ char *delivered; /* envelope recipient */ char *eol; /* carriagecontrol */ char **argv; /* either an array */ @@ -171,6 +175,7 @@ static void get_pipe_args(struct pipe_args * args, va_list ap) */ args->flags = 0; args->sender = 0; + args->orig_rcpt = 0; args->delivered = 0; args->eol = "\n"; args->argv = 0; @@ -194,6 +199,9 @@ static void get_pipe_args(struct pipe_args * args, va_list ap) case PIPE_CMD_SENDER: args->sender = va_arg(ap, char *); break; + case PIPE_CMD_ORIG_RCPT: + args->orig_rcpt = va_arg(ap, char *); + break; case PIPE_CMD_DELIVERED: args->delivered = va_arg(ap, char *); break; @@ -453,7 +461,8 @@ int pipe_command(VSTREAM *src, VSTRING *why,...) */ #define DONT_CARE_WHY ((VSTRING *) 0) - write_status = mail_copy(args.sender, args.delivered, src, + write_status = mail_copy(args.sender, args.orig_rcpt, + args.delivered, src, cmd_in_stream, args.flags, args.eol, DONT_CARE_WHY); diff --git a/postfix/src/global/pipe_command.h b/postfix/src/global/pipe_command.h index 1750ccc7b..9a36832cb 100644 --- a/postfix/src/global/pipe_command.h +++ b/postfix/src/global/pipe_command.h @@ -38,6 +38,7 @@ #define PIPE_CMD_SHELL 10 /* alternative shell */ #define PIPE_CMD_EOL 11 /* record delimiter */ #define PIPE_CMD_EXPORT 12 /* exportable environment */ +#define PIPE_CMD_ORIG_RCPT 13 /* mail_copy() original recipient */ /* * Command completion status. diff --git a/postfix/src/global/recipient_list.c b/postfix/src/global/recipient_list.c index 158338c5e..1153b7c6a 100644 --- a/postfix/src/global/recipient_list.c +++ b/postfix/src/global/recipient_list.c @@ -9,6 +9,7 @@ /* typedef struct { /* .in +4 /* long offset; +/* char *orig_addr; /* char *address; /* .in -4 /* } RECIPIENT; @@ -23,9 +24,10 @@ /* void recipient_list_init(list) /* RECIPIENT_LIST *list; /* -/* void recipient_list_add(list, offset, recipient) +/* void recipient_list_add(list, offset, orig_rcpt, recipient) /* RECIPIENT_LIST *list; /* long offset; +/* const char *orig_rcpt; /* const char *recipient; /* /* void recipient_list_free(list) @@ -90,13 +92,15 @@ void recipient_list_init(RECIPIENT_LIST *list) /* recipient_list_add - add rcpt to list */ -void recipient_list_add(RECIPIENT_LIST *list, long offset, const char *rcpt) +void recipient_list_add(RECIPIENT_LIST *list, long offset, + const char *orig_rcpt, const char *rcpt) { if (list->len >= list->avail) { list->avail *= 2; list->info = (RECIPIENT *) myrealloc((char *) list->info, list->avail * sizeof(RECIPIENT)); } + list->info[list->len].orig_addr = orig_rcpt ? mystrdup(orig_rcpt) : 0; list->info[list->len].address = mystrdup(rcpt); list->info[list->len].offset = offset; list->len++; @@ -108,7 +112,10 @@ void recipient_list_free(RECIPIENT_LIST *list) { RECIPIENT *rcpt; - for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) + for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) { + if (rcpt->orig_addr) + myfree(rcpt->orig_addr); myfree(rcpt->address); + } myfree((char *) list->info); } diff --git a/postfix/src/global/recipient_list.h b/postfix/src/global/recipient_list.h index e7e09d236..0059b71ce 100644 --- a/postfix/src/global/recipient_list.h +++ b/postfix/src/global/recipient_list.h @@ -19,6 +19,7 @@ */ typedef struct RECIPIENT { long offset; /* REC_TYPE_RCPT byte */ + char *orig_addr; /* null or original recipient */ char *address; /* complete address */ } RECIPIENT; @@ -29,7 +30,7 @@ typedef struct RECIPIENT_LIST { } RECIPIENT_LIST; extern void recipient_list_init(RECIPIENT_LIST *); -extern void recipient_list_add(RECIPIENT_LIST *, long, const char *); +extern void recipient_list_add(RECIPIENT_LIST *, long, const char *, const char *); extern void recipient_list_free(RECIPIENT_LIST *); /* LICENSE diff --git a/postfix/src/global/sent.c b/postfix/src/global/sent.c index 3b0c11f89..25e60059d 100644 --- a/postfix/src/global/sent.c +++ b/postfix/src/global/sent.c @@ -6,15 +6,17 @@ /* SYNOPSIS /* #include /* -/* int sent(queue_id, recipient, relay, entry, format, ...) +/* int sent(queue_id, orig_rcpt, recipient, relay, entry, format, ...) /* const char *queue_id; +/* const char *orig_rcpt; /* const char *recipient; /* const char *relay; /* time_t entry; /* const char *format; /* -/* int vsent(queue_id, recipient, relay, entry, format, ap) +/* int vsent(queue_id, orig_rcpt, recipient, relay, entry, format, ap) /* const char *queue_id; +/* const char *orig_rcpt; /* const char *recipient; /* const char *relay; /* time_t entry; @@ -28,6 +30,8 @@ /* Arguments: /* .IP queue_id /* The message queue id. +/* .IP orig_rcpt +/* The original envelope recipient address /* .IP recipient /* The recipient address. /* .IP relay @@ -72,20 +76,22 @@ /* sent - log that a message was sent */ -int sent(const char *queue_id, const char *recipient, const char *relay, +int sent(const char *queue_id, const char *orig_rcpt, + const char *recipient, const char *relay, time_t entry, const char *fmt,...) { va_list ap; va_start(ap, fmt); - vsent(queue_id, recipient, relay, entry, fmt, ap); + vsent(queue_id, orig_rcpt, recipient, relay, entry, fmt, ap); va_end(ap); return (0); } /* vsent - log that a message was sent */ -int vsent(const char *queue_id, const char *recipient, const char *relay, +int vsent(const char *queue_id, const char *orig_rcpt, + const char *recipient, const char *relay, time_t entry, const char *fmt, va_list ap) { #define TEXT (vstring_str(text)) @@ -93,8 +99,8 @@ int vsent(const char *queue_id, const char *recipient, const char *relay, int delay = time((time_t *) 0) - entry; vstring_vsprintf(text, fmt, ap); - msg_info("%s: to=<%s>, relay=%s, delay=%d, status=sent%s%s%s", - queue_id, recipient, relay, delay, + msg_info("%s: orig_to=<%s>, to=<%s>, relay=%s, delay=%d, status=sent%s%s%s", + queue_id, orig_rcpt, recipient, relay, delay, *TEXT ? " (" : "", TEXT, *TEXT ? ")" : ""); vstring_free(text); return (0); diff --git a/postfix/src/global/sent.h b/postfix/src/global/sent.h index cc5178fd0..92c441427 100644 --- a/postfix/src/global/sent.h +++ b/postfix/src/global/sent.h @@ -20,9 +20,9 @@ /* * External interface. */ -extern int PRINTFLIKE(5, 6) sent(const char *, const char *, const char *, - time_t, const char *,...); -extern int vsent(const char *, const char *, const char *, +extern int PRINTFLIKE(6, 7) sent(const char *, const char *, const char *, + const char *, time_t, const char *,...); +extern int vsent(const char *, const char *, const char *, const char *, time_t, const char *, va_list); /* LICENSE diff --git a/postfix/src/lmtp/lmtp.c b/postfix/src/lmtp/lmtp.c index aa9aaf350..c17cc2123 100644 --- a/postfix/src/lmtp/lmtp.c +++ b/postfix/src/lmtp/lmtp.c @@ -49,9 +49,9 @@ /* RFC 1652 (8bit-MIME transport) /* RFC 1870 (Message Size Declaration) /* RFC 2033 (LMTP protocol) -/* RFC 2197 (Pipelining) /* RFC 2554 (AUTH command) /* RFC 2821 (SMTP protocol) +/* RFC 2920 (SMTP Pipelining) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* Corrupted message files are marked so that the queue manager can diff --git a/postfix/src/lmtp/lmtp_proto.c b/postfix/src/lmtp/lmtp_proto.c index de41ac15f..ee990474b 100644 --- a/postfix/src/lmtp/lmtp_proto.c +++ b/postfix/src/lmtp/lmtp_proto.c @@ -575,16 +575,16 @@ static int lmtp_loop(LMTP_STATE *state, int send_state, int recv_state) rcpt = request->rcpt_list.info + survivors[recv_dot]; if (resp->code / 100 == 2) { if (rcpt->offset) { - sent(request->queue_id, rcpt->address, - session->namaddr, request->arrival_time, - "%s", resp->str); + sent(request->queue_id, rcpt->orig_addr, + rcpt->address, session->namaddr, + request->arrival_time, "%s", resp->str); if (request->flags & DEL_REQ_FLAG_SUCCESS) deliver_completed(state->src, rcpt->offset); rcpt->offset = 0; } } else { lmtp_rcpt_fail(state, resp->code, rcpt, - "host %s said: %s (in reply to %s)", + "host %s said: %s (in reply to %s)", session->namaddr, translit(resp->str, "\n", " "), xfer_request[LMTP_STATE_DOT]); diff --git a/postfix/src/lmtp/lmtp_trouble.c b/postfix/src/lmtp/lmtp_trouble.c index 713e4d89b..9a15d4d8e 100644 --- a/postfix/src/lmtp/lmtp_trouble.c +++ b/postfix/src/lmtp/lmtp_trouble.c @@ -178,7 +178,7 @@ int lmtp_site_fail(LMTP_STATE *state, int code, char *format,...) if (rcpt->offset == 0) continue; status = (soft_error ? defer_append : bounce_append) - (KEEP, request->queue_id, rcpt->address, + (KEEP, request->queue_id, rcpt->orig_addr, rcpt->address, session ? session->namaddr : "none", request->arrival_time, "%s", vstring_str(why)); if (status == 0) { @@ -225,7 +225,7 @@ int lmtp_mesg_fail(LMTP_STATE *state, int code, char *format,...) if (rcpt->offset == 0) continue; status = (LMTP_SOFT(code) ? defer_append : bounce_append) - (KEEP, request->queue_id, rcpt->address, + (KEEP, request->queue_id, rcpt->orig_addr, rcpt->address, session->namaddr, request->arrival_time, "%s", vstring_str(why)); if (status == 0) { @@ -259,8 +259,8 @@ void lmtp_rcpt_fail(LMTP_STATE *state, int code, RECIPIENT *rcpt, */ va_start(ap, format); status = (LMTP_SOFT(code) ? vdefer_append : vbounce_append) - (KEEP, request->queue_id, rcpt->address, session->namaddr, - request->arrival_time, format, ap); + (KEEP, request->queue_id, rcpt->orig_addr, rcpt->address, + session->namaddr, request->arrival_time, format, ap); va_end(ap); if (status == 0) { deliver_completed(state->src, rcpt->offset); @@ -305,7 +305,8 @@ int lmtp_stream_except(LMTP_STATE *state, int code, char *description) if (rcpt->offset == 0) continue; state->status |= defer_append(KEEP, request->queue_id, - rcpt->address, session->namaddr, + rcpt->orig_addr, rcpt->address, + session->namaddr, request->arrival_time, "%s", vstring_str(why)); } diff --git a/postfix/src/local/local.c b/postfix/src/local/local.c index 8394a542c..e9d5db6bd 100644 --- a/postfix/src/local/local.c +++ b/postfix/src/local/local.c @@ -534,6 +534,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service) for (msg_stat = 0, rcpt = rqst->rcpt_list.info; rcpt < rcpt_end; rcpt++) { state.dup_filter = been_here_init(var_dup_filter_limit, BH_FLAG_FOLD); forward_init(); + state.msg_attr.orig_rcpt = rcpt->orig_addr; state.msg_attr.recipient = rcpt->address; rcpt_stat = deliver_recipient(state, usr_attr); rcpt_stat |= forward_finish(state.msg_attr, rcpt_stat); diff --git a/postfix/src/local/local.h b/postfix/src/local/local.h index e5ab862f8..764affd77 100644 --- a/postfix/src/local/local.h +++ b/postfix/src/local/local.h @@ -70,6 +70,7 @@ typedef struct DELIVER_ATTR { long offset; /* data offset */ char *encoding; /* MIME encoding */ char *sender; /* taken from envelope */ + char *orig_rcpt; /* from submission */ char *recipient; /* taken from resolver */ char *domain; /* recipient domain */ char *local; /* recipient full localpart */ @@ -120,15 +121,17 @@ typedef struct LOCAL_STATE { /* * Bundle up some often-user attributes. */ -#define BOUNCE_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \ - attr.arrival_time -#define BOUNCE_ONE_ATTR(attr) attr.queue_name, attr.queue_id, attr.encoding, \ - attr.sender, attr.recipient, \ +#define BOUNCE_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \ attr.relay, attr.arrival_time -#define SENT_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \ +#define BOUNCE_ONE_ATTR(attr) attr.queue_name, attr.queue_id, attr.encoding, \ + attr.sender, attr.orig_rcpt, \ + attr.recipient, attr.relay, \ attr.arrival_time +#define SENT_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \ + attr.relay, attr.arrival_time #define OPENED_ATTR(attr) attr.queue_id, attr.sender -#define COPY_ATTR(attr) attr.sender, attr.delivered, attr.fp +#define COPY_ATTR(attr) attr.sender, attr.orig_rcpt, attr.delivered, \ + attr.fp #define MSG_LOG_STATE(m, p) \ msg_info("%s[%d]: local %s recip %s exten %s deliver %s exp_from %s", \ diff --git a/postfix/src/local/mailbox.c b/postfix/src/local/mailbox.c index 49ac57b25..e867988fa 100644 --- a/postfix/src/local/mailbox.c +++ b/postfix/src/local/mailbox.c @@ -260,7 +260,8 @@ int deliver_mailbox(LOCAL_STATE state, USER_ATTR usr_attr, int *statusp) */ if (*var_mailbox_transport) { *statusp = deliver_pass(MAIL_CLASS_PRIVATE, var_mailbox_transport, - state.request, state.msg_attr.recipient, -1L); + state.request, state.msg_attr.orig_rcpt, + state.msg_attr.recipient, -1L); return (YES); } diff --git a/postfix/src/local/unknown.c b/postfix/src/local/unknown.c index 8904159a3..18774e44f 100644 --- a/postfix/src/local/unknown.c +++ b/postfix/src/local/unknown.c @@ -105,7 +105,8 @@ int deliver_unknown(LOCAL_STATE state, USER_ATTR usr_attr) */ if (*var_fallback_transport) return (deliver_pass(MAIL_CLASS_PRIVATE, var_fallback_transport, - state.request, state.msg_attr.recipient, -1L)); + state.request, state.msg_attr.orig_rcpt, + state.msg_attr.recipient, -1L)); /* * Subject the luser_relay address to $name expansion, disable diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in index 13026b82c..cf646935e 100644 --- a/postfix/src/master/Makefile.in +++ b/postfix/src/master/Makefile.in @@ -104,6 +104,7 @@ master.o: ../../include/clean_env.h master.o: ../../include/argv.h master.o: ../../include/safe.h master.o: ../../include/mail_params.h +master.o: ../../include/mail_version.h master.o: ../../include/debug_process.h master.o: ../../include/mail_task.h master.o: ../../include/mail_conf.h diff --git a/postfix/src/nqmgr/qmgr.h b/postfix/src/nqmgr/qmgr.h index 16505f6e4..748501aed 100644 --- a/postfix/src/nqmgr/qmgr.h +++ b/postfix/src/nqmgr/qmgr.h @@ -214,6 +214,7 @@ extern QMGR_QUEUE *qmgr_queue_find(QMGR_TRANSPORT *, const char *); */ struct QMGR_RCPT { long offset; /* REC_TYPE_RCPT byte */ + char *orig_rcpt; /* null or original recipient */ char *address; /* complete address */ QMGR_QUEUE *queue; /* resolved queue */ }; @@ -225,7 +226,7 @@ struct QMGR_RCPT_LIST { }; extern void qmgr_rcpt_list_init(QMGR_RCPT_LIST *); -extern void qmgr_rcpt_list_add(QMGR_RCPT_LIST *, long, const char *); +extern void qmgr_rcpt_list_add(QMGR_RCPT_LIST *, long, const char *, const char *); extern void qmgr_rcpt_list_free(QMGR_RCPT_LIST *); /* @@ -359,7 +360,7 @@ extern void qmgr_peer_free(QMGR_PEER *); */ extern void qmgr_defer_transport(QMGR_TRANSPORT *, const char *); extern void qmgr_defer_todo(QMGR_QUEUE *, const char *); -extern void qmgr_defer_recipient(QMGR_MESSAGE *, const char *, const char *); +extern void qmgr_defer_recipient(QMGR_MESSAGE *, const char *, const char *, const char *); /* * qmgr_bounce.c diff --git a/postfix/src/nqmgr/qmgr_bounce.c b/postfix/src/nqmgr/qmgr_bounce.c index e8f01405f..0f9d50bee 100644 --- a/postfix/src/nqmgr/qmgr_bounce.c +++ b/postfix/src/nqmgr/qmgr_bounce.c @@ -68,7 +68,7 @@ void qmgr_bounce_recipient(QMGR_MESSAGE *message, QMGR_RCPT *recipient, va_start(ap, format); status = vbounce_append(BOUNCE_FLAG_KEEP, message->queue_id, - recipient->address, "none", + recipient->orig_rcpt, recipient->address, "none", message->arrival_time, format, ap); va_end(ap); diff --git a/postfix/src/nqmgr/qmgr_defer.c b/postfix/src/nqmgr/qmgr_defer.c index 72d30aac9..f0dd7c63b 100644 --- a/postfix/src/nqmgr/qmgr_defer.c +++ b/postfix/src/nqmgr/qmgr_defer.c @@ -136,7 +136,8 @@ void qmgr_defer_todo(QMGR_QUEUE *queue, const char *reason) message = entry->message; for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) { recipient = entry->rcpt_list.info + nrcpt; - qmgr_defer_recipient(message, recipient->address, reason); + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, reason); } qmgr_entry_done(entry, QMGR_QUEUE_TODO); } @@ -144,8 +145,8 @@ void qmgr_defer_todo(QMGR_QUEUE *queue, const char *reason) /* qmgr_defer_recipient - defer delivery of specific recipient */ -void qmgr_defer_recipient(QMGR_MESSAGE *message, const char *address, - const char *reason) +void qmgr_defer_recipient(QMGR_MESSAGE *message, const char *orig_addr, + const char *address, const char *reason) { char *myname = "qmgr_defer_recipient"; @@ -159,6 +160,6 @@ void qmgr_defer_recipient(QMGR_MESSAGE *message, const char *address, * Update the message structure and log the message disposition. */ message->flags |= defer_append(BOUNCE_FLAG_KEEP, message->queue_id, - address, "none", message->arrival_time, - "%s", reason); + orig_addr, address, "none", + message->arrival_time, "%s", reason); } diff --git a/postfix/src/nqmgr/qmgr_deliver.c b/postfix/src/nqmgr/qmgr_deliver.c index d8de110c9..38be3d2b6 100644 --- a/postfix/src/nqmgr/qmgr_deliver.c +++ b/postfix/src/nqmgr/qmgr_deliver.c @@ -177,6 +177,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) for (recipient = list.info; recipient < list.info + list.len; recipient++) attr_print(stream, ATTR_FLAG_MORE, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, + recipient->orig_rcpt ? recipient->orig_rcpt : "", ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address, ATTR_TYPE_END); attr_print(stream, ATTR_FLAG_NONE, diff --git a/postfix/src/nqmgr/qmgr_message.c b/postfix/src/nqmgr/qmgr_message.c index 63c6326dd..f1f5fdbf2 100644 --- a/postfix/src/nqmgr/qmgr_message.c +++ b/postfix/src/nqmgr/qmgr_message.c @@ -288,6 +288,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message) const char *error_text; char *name; char *value; + char *orig_rcpt = 0; /* * Initialize. No early returns or we have a memory leak. @@ -400,7 +401,8 @@ static int qmgr_message_read(QMGR_MESSAGE *message) } else if (rec_type == REC_TYPE_RCPT) { if (message->rcpt_list.len < recipient_limit) { message->rcpt_unread--; - qmgr_rcpt_list_add(&message->rcpt_list, curr_offset, start); + qmgr_rcpt_list_add(&message->rcpt_list, curr_offset, + orig_rcpt, start); if (message->rcpt_list.len >= recipient_limit) { if ((message->rcpt_offset = vstream_ftell(message->fp)) < 0) msg_fatal("vstream_ftell %s: %m", @@ -455,8 +457,25 @@ static int qmgr_message_read(QMGR_MESSAGE *message) } } } + if (orig_rcpt != 0) { + msg_warn("%s: out-of-order original recipient <%.200s>", + message->queue_id, start); + myfree(orig_rcpt); + orig_rcpt = 0; + } + if (rec_type == REC_TYPE_ORCP) + orig_rcpt = mystrdup(start); } while (rec_type > 0 && rec_type != REC_TYPE_END); + /* + * Grr. + */ + if (orig_rcpt != 0) { + msg_warn("%s: out-of-order original recipient <%.200s>", + message->queue_id, start); + myfree(orig_rcpt); + } + /* * Avoid clumsiness elsewhere in the program. When sending data across an * IPC channel, sending an empty string is more convenient than sending a @@ -685,7 +704,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) "user has moved to %s", newloc); continue; } else if (dict_errno != 0) { - qmgr_defer_recipient(message, recipient->address, + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, "relocated map lookup failure"); continue; } @@ -771,8 +791,9 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) if (strncasecmp(STR(reply.recipient), var_double_bounce_sender, len) == 0 && !var_double_bounce_sender[len]) { - sent(message->queue_id, recipient->address, - "none", message->arrival_time, "discarded"); + sent(message->queue_id, recipient->orig_rcpt, + recipient->address, "none", message->arrival_time, + "discarded"); deliver_completed(message->fp, recipient->offset); msg_warn("%s: undeliverable postmaster notification discarded", message->queue_id); @@ -791,7 +812,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) if (strcmp(*cpp, STR(reply.transport)) == 0) break; if (*cpp) { - qmgr_defer_recipient(message, recipient->address, + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, "deferred transport"); continue; } @@ -821,7 +843,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * This transport is dead. Defer delivery to this recipient. */ if ((transport->flags & QMGR_TRANSPORT_STAT_DEAD) != 0) { - qmgr_defer_recipient(message, recipient->address, transport->reason); + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, transport->reason); continue; } @@ -838,7 +861,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * This queue is dead. Defer delivery to this recipient. */ if (queue->window == 0) { - qmgr_defer_recipient(message, recipient->address, queue->reason); + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, queue->reason); continue; } @@ -905,7 +929,8 @@ static void qmgr_message_assign(QMGR_MESSAGE *message) * Add the recipient to the current entry and increase all those * recipient counters accordingly. */ - qmgr_rcpt_list_add(&entry->rcpt_list, recipient->offset, recipient->address); + qmgr_rcpt_list_add(&entry->rcpt_list, recipient->offset, + recipient->orig_rcpt, recipient->address); job->rcpt_count++; message->rcpt_count++; qmgr_recipient_count++; diff --git a/postfix/src/nqmgr/qmgr_rcpt_list.c b/postfix/src/nqmgr/qmgr_rcpt_list.c index 2bb292e01..94287fade 100644 --- a/postfix/src/nqmgr/qmgr_rcpt_list.c +++ b/postfix/src/nqmgr/qmgr_rcpt_list.c @@ -9,9 +9,10 @@ /* void qmgr_rcpt_list_init(list) /* QMGR_RCPT_LIST *list; /* -/* void qmgr_rcpt_list_add(list, offset, recipient) +/* void qmgr_rcpt_list_add(list, offset, orig_rcpt, recipient) /* QMGR_RCPT_LIST *list; /* long offset; +/* const char *orig_rcpt; /* const char *recipient; /* /* void qmgr_rcpt_list_free(list) @@ -71,13 +72,15 @@ void qmgr_rcpt_list_init(QMGR_RCPT_LIST *list) /* qmgr_rcpt_list_add - add rcpt to list */ -void qmgr_rcpt_list_add(QMGR_RCPT_LIST *list, long offset, const char *rcpt) +void qmgr_rcpt_list_add(QMGR_RCPT_LIST *list, long offset, + const char *orcpt, const char *rcpt) { if (list->len >= list->avail) { list->avail *= 2; list->info = (QMGR_RCPT *) myrealloc((char *) list->info, list->avail * sizeof(QMGR_RCPT)); } + list->info[list->len].orig_rcpt = (orcpt ? mystrdup(orcpt) : 0); list->info[list->len].address = mystrdup(rcpt); list->info[list->len].offset = offset; list->info[list->len].queue = 0; @@ -90,7 +93,10 @@ void qmgr_rcpt_list_free(QMGR_RCPT_LIST *list) { QMGR_RCPT *rcpt; - for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) + for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) { + if (rcpt->orig_rcpt) + myfree(rcpt->orig_rcpt); myfree(rcpt->address); + } myfree((char *) list->info); } diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 0e865de29..e798de07c 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -186,6 +186,12 @@ static int copy_segment(VSTREAM *qfile, VSTREAM *cleanup, PICKUP_INFO *info, if (type == REC_TYPE_FROM) if (info->sender == 0) info->sender = mystrdup(vstring_str(buf)); + if (type == REC_TYPE_ORCP) + if (info->st.st_uid != var_owner_uid) { + msg_warn("uid=%ld: ignoring original recipient record: %.200s", + (long) info->st.st_uid, vstring_str(buf)); + continue; + } if (type == REC_TYPE_RCPT) if (info->rcpt == 0) info->rcpt = mystrdup(vstring_str(buf)); diff --git a/postfix/src/pipe/pipe.c b/postfix/src/pipe/pipe.c index c838969a4..6332ee4f4 100644 --- a/postfix/src/pipe/pipe.c +++ b/postfix/src/pipe/pipe.c @@ -40,7 +40,7 @@ /* .fi /* The external command attributes are given in the \fBmaster.cf\fR /* file at the end of a service definition. The syntax is as follows: -/* .IP "\fBflags=BDFRhqu.>\fR (optional)" +/* .IP "\fBflags=BDFORhqu.>\fR (optional)" /* Optional message processing flags. By default, a message is /* copied unchanged. /* .RS @@ -56,6 +56,10 @@ /* Prepend a "\fBFrom \fIsender time_stamp\fR" envelope header to /* the message content. /* This is expected by, for example, \fBUUCP\fR software. +/* .IP \fBO\fR +/* Prepend an "\fBX-Original-To: \fIrecipient\fR" message header +/* with the original envelope recipient address. Note: for this to work, +/* the \fItransport\fB_destination_recipient_limit\fR must be 1. /* .IP \fBR\fR /* Prepend a \fBReturn-Path:\fR message header with the envelope sender /* address. @@ -578,6 +582,9 @@ static void get_service_attr(PIPE_ATTR *attr, char **argv) case 'F': attr->flags |= MAIL_COPY_FROM; break; + case 'O': + attr->flags |= MAIL_COPY_ORIG_RCPT; + break; case 'R': attr->flags |= MAIL_COPY_RETURN_PATH; break; @@ -699,7 +706,7 @@ static int eval_command_status(int command_status, char *service, case PIPE_STAT_OK: for (n = 0; n < request->rcpt_list.len; n++) { rcpt = request->rcpt_list.info + n; - sent(request->queue_id, rcpt->address, service, + sent(request->queue_id, rcpt->orig_addr, rcpt->address, service, request->arrival_time, "%s", request->nexthop); if (request->flags & DEL_REQ_FLAG_SUCCESS) deliver_completed(src, rcpt->offset); @@ -709,8 +716,9 @@ static int eval_command_status(int command_status, char *service, for (n = 0; n < request->rcpt_list.len; n++) { rcpt = request->rcpt_list.info + n; status = bounce_append(BOUNCE_FLAG_KEEP, - request->queue_id, rcpt->address, - service, request->arrival_time, "%s", why); + request->queue_id, rcpt->orig_addr, + rcpt->address, service, + request->arrival_time, "%s", why); if (status == 0) deliver_completed(src, rcpt->offset); result |= status; @@ -720,8 +728,9 @@ static int eval_command_status(int command_status, char *service, for (n = 0; n < request->rcpt_list.len; n++) { rcpt = request->rcpt_list.info + n; result |= defer_append(BOUNCE_FLAG_KEEP, - request->queue_id, rcpt->address, - service, request->arrival_time, "%s", why); + request->queue_id, rcpt->orig_addr, + rcpt->address, service, + request->arrival_time, "%s", why); } break; case PIPE_STAT_CORRUPT: @@ -801,6 +810,19 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv) return (deliver_status); } + /* + * The O flag cannot be specified for multi-recipient deliveries. + */ + if ((attr.flags & MAIL_COPY_ORIG_RCPT) && (rcpt_list->len > 1)) { + deliver_status = eval_command_status(PIPE_STAT_DEFER, service, + request, request->fp, + "mailer configuration error"); + msg_warn("pipe flag `O' requires %s_destination_recipient_limit = 1", + service); + DELIVER_MSG_CLEANUP(); + return (deliver_status); + } + /* * Check that this agent accepts messages this large. */ @@ -851,6 +873,7 @@ static int deliver_message(DELIVER_REQUEST *request, char *service, char **argv) PIPE_CMD_TIME_LIMIT, conf.time_limit, PIPE_CMD_EOL, STR(attr.eol), PIPE_CMD_EXPORT, export_env->argv, + PIPE_CMD_ORIG_RCPT, rcpt_list->info[0].orig_addr, PIPE_CMD_DELIVERED, rcpt_list->info[0].address, PIPE_CMD_END); argv_free(export_env); diff --git a/postfix/src/qmgr/qmgr.h b/postfix/src/qmgr/qmgr.h index 6f01c4f32..a7685451e 100644 --- a/postfix/src/qmgr/qmgr.h +++ b/postfix/src/qmgr/qmgr.h @@ -178,6 +178,7 @@ extern QMGR_QUEUE *qmgr_queue_find(QMGR_TRANSPORT *, const char *); */ struct QMGR_RCPT { long offset; /* REC_TYPE_RCPT byte */ + char *orig_rcpt; /* null or original recipient */ char *address; /* complete address */ QMGR_QUEUE *queue; /* resolved queue */ }; @@ -189,7 +190,7 @@ struct QMGR_RCPT_LIST { }; extern void qmgr_rcpt_list_init(QMGR_RCPT_LIST *); -extern void qmgr_rcpt_list_add(QMGR_RCPT_LIST *, long, const char *); +extern void qmgr_rcpt_list_add(QMGR_RCPT_LIST *, long, const char *, const char *); extern void qmgr_rcpt_list_free(QMGR_RCPT_LIST *); /* @@ -256,7 +257,7 @@ extern QMGR_MESSAGE *qmgr_message_realloc(QMGR_MESSAGE *); */ extern void qmgr_defer_transport(QMGR_TRANSPORT *, const char *); extern void qmgr_defer_todo(QMGR_QUEUE *, const char *); -extern void qmgr_defer_recipient(QMGR_MESSAGE *, const char *, const char *); +extern void qmgr_defer_recipient(QMGR_MESSAGE *, const char *, const char *, const char *); /* * qmgr_bounce.c diff --git a/postfix/src/qmgr/qmgr_bounce.c b/postfix/src/qmgr/qmgr_bounce.c index d6631c0ad..23b92447b 100644 --- a/postfix/src/qmgr/qmgr_bounce.c +++ b/postfix/src/qmgr/qmgr_bounce.c @@ -63,7 +63,7 @@ void qmgr_bounce_recipient(QMGR_MESSAGE *message, QMGR_RCPT *recipient, va_start(ap, format); status = vbounce_append(BOUNCE_FLAG_KEEP, message->queue_id, - recipient->address, "none", + recipient->orig_rcpt, recipient->address, "none", message->arrival_time, format, ap); va_end(ap); diff --git a/postfix/src/qmgr/qmgr_defer.c b/postfix/src/qmgr/qmgr_defer.c index 8be8e7247..8c0b5e7ce 100644 --- a/postfix/src/qmgr/qmgr_defer.c +++ b/postfix/src/qmgr/qmgr_defer.c @@ -131,7 +131,8 @@ void qmgr_defer_todo(QMGR_QUEUE *queue, const char *reason) message = entry->message; for (nrcpt = 0; nrcpt < entry->rcpt_list.len; nrcpt++) { recipient = entry->rcpt_list.info + nrcpt; - qmgr_defer_recipient(message, recipient->address, reason); + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, reason); } qmgr_entry_done(entry, QMGR_QUEUE_TODO); } @@ -139,8 +140,8 @@ void qmgr_defer_todo(QMGR_QUEUE *queue, const char *reason) /* qmgr_defer_recipient - defer delivery of specific recipient */ -void qmgr_defer_recipient(QMGR_MESSAGE *message, const char *address, - const char *reason) +void qmgr_defer_recipient(QMGR_MESSAGE *message, const char *orig_addr, + const char *address, const char *reason) { char *myname = "qmgr_defer_recipient"; @@ -154,6 +155,6 @@ void qmgr_defer_recipient(QMGR_MESSAGE *message, const char *address, * Update the message structure and log the message disposition. */ message->flags |= defer_append(BOUNCE_FLAG_KEEP, message->queue_id, - address, "none", message->arrival_time, - "%s", reason); + orig_addr, address, "none", + message->arrival_time, "%s", reason); } diff --git a/postfix/src/qmgr/qmgr_deliver.c b/postfix/src/qmgr/qmgr_deliver.c index 64b170c26..136b3dcb7 100644 --- a/postfix/src/qmgr/qmgr_deliver.c +++ b/postfix/src/qmgr/qmgr_deliver.c @@ -172,6 +172,8 @@ static int qmgr_deliver_send_request(QMGR_ENTRY *entry, VSTREAM *stream) for (recipient = list.info; recipient < list.info + list.len; recipient++) attr_print(stream, ATTR_FLAG_MORE, ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, recipient->offset, + ATTR_TYPE_STR, MAIL_ATTR_ORCPT, + recipient->orig_rcpt ? recipient->orig_rcpt : "", ATTR_TYPE_STR, MAIL_ATTR_RECIP, recipient->address, ATTR_TYPE_END); attr_print(stream, ATTR_FLAG_NONE, diff --git a/postfix/src/qmgr/qmgr_message.c b/postfix/src/qmgr/qmgr_message.c index 9eb702376..fd92d7d52 100644 --- a/postfix/src/qmgr/qmgr_message.c +++ b/postfix/src/qmgr/qmgr_message.c @@ -208,6 +208,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message) const char *error_text; char *name; char *value; + char *orig_rcpt = 0; /* * Initialize. No early returns or we have a memory leak. @@ -276,7 +277,12 @@ static int qmgr_message_read(QMGR_MESSAGE *message) } else if (rec_type == REC_TYPE_RCPT) { #define FUDGE(x) ((x) * (var_qmgr_fudge / 100.0)) if (message->rcpt_list.len < FUDGE(var_qmgr_rcpt_limit)) { - qmgr_rcpt_list_add(&message->rcpt_list, curr_offset, start); + qmgr_rcpt_list_add(&message->rcpt_list, curr_offset, + orig_rcpt, start); + if (orig_rcpt) { + myfree(orig_rcpt); + orig_rcpt = 0; + } if (message->rcpt_list.len >= FUDGE(var_qmgr_rcpt_limit)) { if ((message->rcpt_offset = vstream_ftell(message->fp)) < 0) msg_fatal("vstream_ftell %s: %m", @@ -335,8 +341,25 @@ static int qmgr_message_read(QMGR_MESSAGE *message) } } } + if (orig_rcpt != 0) { + msg_warn("%s: out-of-order original recipient <%.200s>", + message->queue_id, start); + myfree(orig_rcpt); + orig_rcpt = 0; + } + if (rec_type == REC_TYPE_ORCP) + orig_rcpt = mystrdup(start); } while (rec_type > 0 && rec_type != REC_TYPE_END); + /* + * Grr. + */ + if (orig_rcpt != 0) { + msg_warn("%s: out-of-order original recipient <%.200s>", + message->queue_id, start); + myfree(orig_rcpt); + } + /* * If there is no size record, use the queue file size instead. */ @@ -565,7 +588,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) "user has moved to %s", newloc); continue; } else if (dict_errno != 0) { - qmgr_defer_recipient(message, recipient->address, + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, "relocated map lookup failure"); continue; } @@ -651,8 +675,9 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) if (strncasecmp(STR(reply.recipient), var_double_bounce_sender, len) == 0 && !var_double_bounce_sender[len]) { - sent(message->queue_id, recipient->address, - "none", message->arrival_time, "discarded"); + sent(message->queue_id, recipient->orig_rcpt, + recipient->address, "none", message->arrival_time, + "discarded"); deliver_completed(message->fp, recipient->offset); msg_warn("%s: undeliverable postmaster notification discarded", message->queue_id); @@ -671,7 +696,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) if (strcasecmp(*cpp, STR(reply.transport)) == 0) break; if (*cpp) { - qmgr_defer_recipient(message, recipient->address, + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, "deferred transport"); continue; } @@ -701,7 +727,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * This transport is dead. Defer delivery to this recipient. */ if ((transport->flags & QMGR_TRANSPORT_STAT_DEAD) != 0) { - qmgr_defer_recipient(message, recipient->address, transport->reason); + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, transport->reason); continue; } @@ -718,7 +745,8 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message) * This queue is dead. Defer delivery to this recipient. */ if (queue->window == 0) { - qmgr_defer_recipient(message, recipient->address, queue->reason); + qmgr_defer_recipient(message, recipient->orig_rcpt, + recipient->address, queue->reason); continue; } @@ -757,7 +785,8 @@ static void qmgr_message_assign(QMGR_MESSAGE *message) entry->rcpt_list.len)) { entry = qmgr_entry_create(queue, message); } - qmgr_rcpt_list_add(&entry->rcpt_list, recipient->offset, recipient->address); + qmgr_rcpt_list_add(&entry->rcpt_list, recipient->offset, + recipient->orig_rcpt, recipient->address); qmgr_recipient_count++; } } diff --git a/postfix/src/qmgr/qmgr_rcpt_list.c b/postfix/src/qmgr/qmgr_rcpt_list.c index 2bb292e01..94287fade 100644 --- a/postfix/src/qmgr/qmgr_rcpt_list.c +++ b/postfix/src/qmgr/qmgr_rcpt_list.c @@ -9,9 +9,10 @@ /* void qmgr_rcpt_list_init(list) /* QMGR_RCPT_LIST *list; /* -/* void qmgr_rcpt_list_add(list, offset, recipient) +/* void qmgr_rcpt_list_add(list, offset, orig_rcpt, recipient) /* QMGR_RCPT_LIST *list; /* long offset; +/* const char *orig_rcpt; /* const char *recipient; /* /* void qmgr_rcpt_list_free(list) @@ -71,13 +72,15 @@ void qmgr_rcpt_list_init(QMGR_RCPT_LIST *list) /* qmgr_rcpt_list_add - add rcpt to list */ -void qmgr_rcpt_list_add(QMGR_RCPT_LIST *list, long offset, const char *rcpt) +void qmgr_rcpt_list_add(QMGR_RCPT_LIST *list, long offset, + const char *orcpt, const char *rcpt) { if (list->len >= list->avail) { list->avail *= 2; list->info = (QMGR_RCPT *) myrealloc((char *) list->info, list->avail * sizeof(QMGR_RCPT)); } + list->info[list->len].orig_rcpt = (orcpt ? mystrdup(orcpt) : 0); list->info[list->len].address = mystrdup(rcpt); list->info[list->len].offset = offset; list->info[list->len].queue = 0; @@ -90,7 +93,10 @@ void qmgr_rcpt_list_free(QMGR_RCPT_LIST *list) { QMGR_RCPT *rcpt; - for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) + for (rcpt = list->info; rcpt < list->info + list->len; rcpt++) { + if (rcpt->orig_rcpt) + myfree(rcpt->orig_rcpt); myfree(rcpt->address); + } myfree((char *) list->info); } diff --git a/postfix/src/qmqpd/Makefile.in b/postfix/src/qmqpd/Makefile.in index cc878e4fc..6b76ae51c 100644 --- a/postfix/src/qmqpd/Makefile.in +++ b/postfix/src/qmqpd/Makefile.in @@ -95,6 +95,7 @@ qmqpd.o: ../../include/quote_822_local.h qmqpd.o: ../../include/quote_flags.h qmqpd.o: ../../include/match_parent_style.h qmqpd.o: ../../include/lex_822.h +qmqpd.o: ../../include/verp_sender.h qmqpd.o: ../../include/mail_server.h qmqpd.o: qmqpd.h qmqpd_peer.o: qmqpd_peer.c diff --git a/postfix/src/smtp/smtp.c b/postfix/src/smtp/smtp.c index a251e9774..86b825ebe 100644 --- a/postfix/src/smtp/smtp.c +++ b/postfix/src/smtp/smtp.c @@ -43,9 +43,9 @@ /* RFC 1870 (Message Size Declaration) /* RFC 2045 (MIME: Format of Internet Message Bodies) /* RFC 2046 (MIME: Media Types) -/* RFC 2197 (Pipelining) /* RFC 2554 (AUTH command) /* RFC 2821 (SMTP protocol) +/* RFC 2920 (SMTP Pipelining) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* Corrupted message files are marked so that the queue manager can diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index d13fe66cf..4dad14c02 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -700,7 +700,8 @@ int smtp_xfer(SMTP_STATE *state) for (nrcpt = 0; nrcpt < recv_rcpt; nrcpt++) { rcpt = request->rcpt_list.info + nrcpt; if (rcpt->offset) { - sent(request->queue_id, rcpt->address, + sent(request->queue_id, rcpt->orig_addr, + rcpt->address, session->namaddr, request->arrival_time, "%s", resp->str); diff --git a/postfix/src/smtp/smtp_trouble.c b/postfix/src/smtp/smtp_trouble.c index d9128f1f5..ef78e51f3 100644 --- a/postfix/src/smtp/smtp_trouble.c +++ b/postfix/src/smtp/smtp_trouble.c @@ -167,7 +167,7 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...) if (rcpt->offset == 0) continue; status = (soft_error ? defer_append : bounce_append) - (KEEP, request->queue_id, rcpt->address, + (KEEP, request->queue_id, rcpt->orig_addr, rcpt->address, session ? session->namaddr : "none", request->arrival_time, "%s", vstring_str(why)); if (status == 0) { @@ -214,7 +214,7 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...) if (rcpt->offset == 0) continue; status = (SMTP_SOFT(code) ? defer_append : bounce_append) - (KEEP, request->queue_id, rcpt->address, + (KEEP, request->queue_id, rcpt->orig_addr, rcpt->address, session->namaddr, request->arrival_time, "%s", vstring_str(why)); if (status == 0) { @@ -248,8 +248,8 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt, */ va_start(ap, format); status = (SMTP_SOFT(code) ? vdefer_append : vbounce_append) - (KEEP, request->queue_id, rcpt->address, session->namaddr, - request->arrival_time, format, ap); + (KEEP, request->queue_id, rcpt->orig_addr, rcpt->address, + session->namaddr, request->arrival_time, format, ap); va_end(ap); if (status == 0) { deliver_completed(state->src, rcpt->offset); @@ -294,7 +294,8 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description) if (rcpt->offset == 0) continue; state->status |= defer_append(KEEP, request->queue_id, - rcpt->address, session->namaddr, + rcpt->orig_addr, rcpt->address, + session->namaddr, request->arrival_time, "%s", vstring_str(why)); } diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index b88803c9a..7e9a1152c 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -34,11 +34,11 @@ /* RFC 1123 (Host requirements) /* RFC 1652 (8bit-MIME transport) /* RFC 1869 (SMTP service extensions) -/* RFC 1854 (SMTP Pipelining) /* RFC 1870 (Message Size Declaration) /* RFC 1985 (ETRN command) /* RFC 2554 (AUTH command) /* RFC 2821 (SMTP protocol) +/* RFC 2920 (SMTP Pipelining) /* DIAGNOSTICS /* Problems and transactions are logged to \fBsyslogd\fR(8). /* @@ -233,7 +233,7 @@ /* .IP \fBdefault_rbl_reply\fR /* Default template reply when a request is RBL blacklisted. /* This template is used by the \fBreject_rbl_*\fR and -/* \fBreject_rhsbl_*\fR restrictions. See also: +/* \fBreject_rhsbl_*\fR restrictions. See also: /* \fBrbl_reply_maps\fR and \fBsmtpd_expansion_filter\fR. /* .IP \fBdefer_code\fR /* Response code when a client request is rejected by the \fBdefer\fR @@ -244,9 +244,9 @@ /* .IP \fBmaps_rbl_reject_code\fR /* Response code when a request is RBL blacklisted. /* .IP \fBrbl_reply_maps\fR -/* Table with template responses for RBL blacklisted requests, indexed by -/* RBL domain name. These templates are used by the \fBreject_rbl_*\fR -/* and \fBreject_rhsbl_*\fR restrictions. See also: +/* Table with template responses for RBL blacklisted requests, indexed by +/* RBL domain name. These templates are used by the \fBreject_rbl_*\fR +/* and \fBreject_rhsbl_*\fR restrictions. See also: /* \fBdefault_rbl_reply\fR and \fBsmtpd_expansion_filter\fR. /* .IP \fBreject_code\fR /* Response code when the client matches a \fBreject\fR restriction. diff --git a/postfix/src/util/safe_open.c b/postfix/src/util/safe_open.c index d20c9404c..657f9a32a 100644 --- a/postfix/src/util/safe_open.c +++ b/postfix/src/util/safe_open.c @@ -92,13 +92,16 @@ static VSTREAM *safe_open_exist(const char *path, int flags, { struct stat local_statbuf; struct stat lstat_st; + int saved_errno; VSTREAM *fp; /* * Open an existing file. */ if ((fp = vstream_fopen(path, flags & ~(O_CREAT | O_EXCL), 0)) == 0) { + saved_errno = errno; vstring_sprintf(why, "cannot open file: %m"); + errno = saved_errno; return (0); } diff --git a/postfix/src/virtual/virtual.c b/postfix/src/virtual/virtual.c index 9635f7efb..cd8c32319 100644 --- a/postfix/src/virtual/virtual.c +++ b/postfix/src/virtual/virtual.c @@ -118,7 +118,7 @@ /* While searching a lookup table, an address extension /* (\fIuser+foo@domain.tld\fR) is ignored. /* -/* In a lookup table, specify a left-hand side of \fI@domain.tld\fR +/* In a lookup table, specify a left-hand side of \fI@domain.tld\fR /* to match any user in the specified domain that does not have a /* specific \fIuser@domain.tld\fR entry. /* @@ -136,7 +136,7 @@ /* While searching a lookup table, an address extension /* (\fIuser+foo@domain.tld\fR) is ignored. /* -/* In a lookup table, specify a left-hand side of \fI@domain.tld\fR +/* In a lookup table, specify a left-hand side of \fI@domain.tld\fR /* to match any user in the specified domain that does not have a /* specific \fIuser@domain.tld\fR entry. /* .IP "\fBvirtual_gid_maps\fR (regexp maps disallowed)" @@ -146,7 +146,7 @@ /* While searching a lookup table, an address extension /* (\fIuser+foo@domain.tld\fR) is ignored. /* -/* In a lookup table, specify a left-hand side of \fI@domain.tld\fR +/* In a lookup table, specify a left-hand side of \fI@domain.tld\fR /* to match any user in the specified domain that does not have a /* specific \fIuser@domain.tld\fR entry. /* .SH "Locking controls" @@ -317,6 +317,7 @@ static int local_deliver(DELIVER_REQUEST *rqst, char *service) * recipient. Update the per-message delivery status. */ for (msg_stat = 0, rcpt = rqst->rcpt_list.info; rcpt < rcpt_end; rcpt++) { + state.msg_attr.orig_rcpt = rcpt->orig_addr; state.msg_attr.recipient = rcpt->address; rcpt_stat = deliver_recipient(state, usr_attr); if (rcpt_stat == 0) diff --git a/postfix/src/virtual/virtual.h b/postfix/src/virtual/virtual.h index 1443bc8d0..844441d5a 100644 --- a/postfix/src/virtual/virtual.h +++ b/postfix/src/virtual/virtual.h @@ -66,6 +66,7 @@ typedef struct DELIVER_ATTR { char *queue_id; /* mail queue id */ long offset; /* data offset */ char *sender; /* taken from envelope */ + char *orig_rcpt; /* taken from sender */ char *recipient; /* taken from resolver */ char *user; /* recipient lookup handle */ char *delivered; /* for loop detection */ @@ -92,11 +93,12 @@ typedef struct LOCAL_STATE { /* * Bundle up some often-user attributes. */ -#define BOUNCE_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \ - attr.arrival_time -#define SENT_ATTR(attr) attr.queue_id, attr.recipient, attr.relay, \ - attr.arrival_time -#define COPY_ATTR(attr) attr.sender, attr.delivered, attr.fp +#define BOUNCE_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \ + attr.relay, attr.arrival_time +#define SENT_ATTR(attr) attr.queue_id, attr.orig_rcpt, attr.recipient, \ + attr.relay, attr.arrival_time +#define COPY_ATTR(attr) attr.sender, attr.orig_rcpt, attr.delivered, \ + attr.fp #define MSG_LOG_STATE(m, p) \ msg_info("%s[%d]: recip %s deliver %s", m, \