Cleanup: incorrect mailbox seek-to-end error message in the
virtual(8) delivery agent. File: virtual/mailbox.c.
+
+20180107
+
+ Cleanup: Postfix-generated From: headers with 'full name'
+ information are now formatted as "From: name <address>" by
+ default. Specify "header_from_format = obsolete" for the
+ earlier form "From: address (name)". Files: proto/postconf.proto,
+ cleanup/cleanup.h, cleanup_init.c, cleanup_message.c,
+ mail_params.h.
If you upgrade from Postfix 3.1 or earlier, read RELEASE_NOTES-3.2
before proceeding.
+
+Incompatible changes with snapshot 201800107
+--------------------------------------------
+
+This release changes the format of 'full name' information in
+Postfix-generated From: headers, when a local program such as
+/bin/mail submits a message without From: header.
+
+Postfix-generated From: headers with 'full name' information are
+now formatted as "From: name <address>" by default. Specify
+"header_from_format = obsolete" to get the earlier form "From:
+address (name)". See the postconf(5) manpage for more details.
</p>
+</DD>
+
+<DT><b><a name="header_from_format">header_from_format</a>
+(default: standard)</b></DT><DD>
+
+<p> The format of the Postfix-generated <b>From:</b> header. This
+setting affects the appearance of 'full name' information when a
+local program such as /bin/mail submits a message without From:
+header through the Postfix <a href="sendmail.1.html">sendmail(1)</a> command. </p>
+
+<p> Specify one of the following: </p>
+
+<dl>
+
+<dt><b>standard</b> (default)</dt> <dd> Produce a header formatted
+as "<b>From:</b> <i>name</i><b> <</b><i>address</i><b>></b>".
+This is the default as of Postfix 3.3.</dd>
+
+<dt><b>obsolete</b></dt> <dd>Produce a header formatted as "<b>From:</b>
+<i>address</i> <b>(</b><i>name</i><b>)</b>". This is the behavior
+prior to Postfix 3.3. </dd>
+
+</dl>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> Postfix generates the format "<b>From:</b> <i>address</i>"
+when <i>name</i> information is unavailable or the envelope sender
+address is empty. This is the same behavior as prior to Postfix
+3.3. </p>
+
+<li> <p> In the <b>standard</b> form, the <i>name</i> will be quoted
+if it contains <b>specials</b> as defined in <a href="http://tools.ietf.org/html/rfc5322">RFC 5322</a>, or the "!%"
+address operators. </p>
+
+<li> <p> The Postfix <a href="sendmail.1.html">sendmail(1)</a> command gets <i>name</i> information
+from the <b>-F</b> command-line option, from the <b>NAME</b>
+environment variable, or from the UNIX password file. </p>
+
+</ul>
+
+<p> This feature is available in Postfix 3.3 and later. </p>
+
+
</DD>
<DT><b><a name="header_size_limit">header_size_limit</a>
.SH header_checks (default: empty)
Optional lookup tables for content inspection of primary non\-MIME
message headers, as specified in the \fBheader_checks\fR(5) manual page.
+.SH header_from_format (default: standard)
+The format of the Postfix\-generated \fBFrom:\fR header. This
+setting affects the appearance of 'full name' information when a
+local program such as /bin/mail submits a message without From:
+header through the Postfix \fBsendmail\fR(1) command.
+.PP
+Specify one of the following:
+.IP "\fBstandard\fR (default)"
+Produce a header formatted
+as "\fBFrom:\fR \fIname\fR\fB <\fR\fIaddress\fR\fB>\fR".
+This is the default as of Postfix 3.3.
+.br
+.IP "\fBobsolete\fR"
+Produce a header formatted as "\fBFrom:\fR
+\fIaddress\fR \fB(\fR\fIname\fR\fB)\fR". This is the behavior
+prior to Postfix 3.3.
+.br
+.br
+.PP
+Notes:
+.IP \(bu
+Postfix generates the format "\fBFrom:\fR \fIaddress\fR"
+when \fIname\fR information is unavailable or the envelope sender
+address is empty. This is the same behavior as prior to Postfix
+3.3.
+.IP \(bu
+In the \fBstandard\fR form, the \fIname\fR will be quoted
+if it contains \fBspecials\fR as defined in RFC 5322, or the "!%"
+address operators.
+.IP \(bu
+The Postfix \fBsendmail\fR(1) command gets \fIname\fR information
+from the \fB\-F\fR command\-line option, from the \fBNAME\fR
+environment variable, or from the UNIX password file.
+.br
+.PP
+This feature is available in Postfix 3.3 and later.
.SH header_size_limit (default: 102400)
The maximal amount of memory in bytes for storing a message header.
If a header is larger, the excess is discarded. The limit is
configuration parameter. See there for details. </p>
<p> This feature is available in Postfix 3.3 and later. </p>
+
+%PARAM header_from_format standard
+
+<p> The format of the Postfix-generated <b>From:</b> header. This
+setting affects the appearance of 'full name' information when a
+local program such as /bin/mail submits a message without From:
+header through the Postfix sendmail(1) command. </p>
+
+<p> Specify one of the following: </p>
+
+<dl>
+
+<dt><b>standard</b> (default)</dt> <dd> Produce a header formatted
+as "<b>From:</b> <i>name</i><b> <</b><i>address</i><b>></b>".
+This is the default as of Postfix 3.3.</dd>
+
+<dt><b>obsolete</b></dt> <dd>Produce a header formatted as "<b>From:</b>
+<i>address</i> <b>(</b><i>name</i><b>)</b>". This is the behavior
+prior to Postfix 3.3. </dd>
+
+</dl>
+
+<p> Notes: </p>
+
+<ul>
+
+<li> <p> Postfix generates the format "<b>From:</b> <i>address</i>"
+when <i>name</i> information is unavailable or the envelope sender
+address is empty. This is the same behavior as prior to Postfix
+3.3. </p>
+
+<li> <p> In the <b>standard</b> form, the <i>name</i> will be quoted
+if it contains <b>specials</b> as defined in RFC 5322, or the "!%"
+address operators. </p>
+
+<li> <p> The Postfix sendmail(1) command gets <i>name</i> information
+from the <b>-F</b> command-line option, from the <b>NAME</b>
+environment variable, or from the UNIX password file. </p>
+
+</ul>
+
+<p> This feature is available in Postfix 3.3 and later. </p>
cleanup_init.o: ../../include/msg.h
cleanup_init.o: ../../include/myflock.h
cleanup_init.o: ../../include/mymalloc.h
+cleanup_init.o: ../../include/name_code.h
cleanup_init.o: ../../include/name_mask.h
cleanup_init.o: ../../include/nvtable.h
cleanup_init.o: ../../include/resolve_clnt.h
extern int cleanup_body_edit_finish(CLEANUP_STATE *);
extern void cleanup_body_edit_free(CLEANUP_STATE *);
+ /*
+ * From: header formatting.
+ */
+#define HFROM_FORMAT_CODE_STD 0
+#define HFROM_FORMAT_CODE_OBS 1
+extern int hfrom_format_code;
+
/* LICENSE
/* .ad
/* .fi
#include <msg.h>
#include <iostuff.h>
+#include <name_code.h>
#include <name_mask.h>
#include <stringops.h>
int var_auto_8bit_enc_hdr; /* auto-detect 8bit encoding header */
int var_always_add_hdrs; /* always add missing headers */
int var_virt_addrlen_limit; /* stop exponential growth */
+char *var_hfrom_format; /* header_from_format */
const CONFIG_INT_TABLE cleanup_int_table[] = {
VAR_HOPCOUNT_LIMIT, DEF_HOPCOUNT_LIMIT, &var_hopcount_limit, 1, 0,
VAR_CLEANUP_MILTERS, DEF_CLEANUP_MILTERS, &var_cleanup_milters, 0, 0,
VAR_MILT_HEAD_CHECKS, DEF_MILT_HEAD_CHECKS, &var_milt_head_checks, 0, 0,
VAR_MILT_MACRO_DEFLTS, DEF_MILT_MACRO_DEFLTS, &var_milt_macro_deflts, 0, 0,
+ VAR_HFROM_FORMAT, DEF_HFROM_FORMAT, &var_hfrom_format, 1, 0,
0,
};
*/
MILTERS *cleanup_milters;
+ /*
+ * From: header format.
+ */
+int hfrom_format_code;
+
/* cleanup_all - callback for the runtime error handler */
void cleanup_all(void)
void cleanup_post_jail(char *unused_name, char **unused_argv)
{
+ static const NAME_CODE hfrom_format_table[] = {
+ HFROM_FORMAT_NAME_STD, HFROM_FORMAT_CODE_STD,
+ HFROM_FORMAT_NAME_OBS, HFROM_FORMAT_CODE_OBS,
+ 0, -1,
+ };
/*
* Optionally set the file size resource limit. XXX This limits the
cleanup_strip_chars = vstring_alloc(strlen(var_msg_strip_chars));
unescape(cleanup_strip_chars, var_msg_strip_chars);
}
+
+ /*
+ * From: header formatting.
+ */
+ if ((hfrom_format_code = name_code(hfrom_format_table,
+ NAME_CODE_FLAG_NONE, var_hfrom_format)) < 0)
+ msg_fatal("invalid setting: %s = %s",
+ VAR_HFROM_FORMAT, var_hfrom_format);
}
#include <rec_type.h>
#include <cleanup_user.h>
#include <tok822.h>
+#include <lex_822.h>
#include <header_opts.h>
#include <quote_822_local.h>
#include <mail_params.h>
return (buf);
}
if (STREQUAL(value, "PASS", command_len)) {
- cleanup_act_log(state, "pass", context, buf, optional_text);
- state->flags &= ~CLEANUP_FLAG_FILTER_ALL;
- return (buf);
+ cleanup_act_log(state, "pass", context, buf, optional_text);
+ state->flags &= ~CLEANUP_FLAG_FILTER_ALL;
+ return (buf);
}
if (STREQUAL(value, "DISCARD", command_len)) {
cleanup_act_log(state, "discard", context, buf, optional_text);
cleanup_act_log(state, "prepend", context, buf, optional_text);
temp = vstring_strcpy(vstring_alloc(strlen(optional_text)),
- optional_text);
+ optional_text);
cleanup_out_header(state, temp);
vstring_free(temp);
}
char time_stamp[1024]; /* XXX locale dependent? */
struct tm *tp;
TOK822 *token;
+ TOK822 *dummy_token;
time_t tv;
/*
HDR_RESENT_FROM : HDR_FROM))) == 0) {
quote_822_local(state->temp1, *state->sender ?
state->sender : MAIL_ADDR_MAIL_DAEMON);
- vstring_sprintf(state->temp2, "%sFrom: %s",
- state->resent, vstring_str(state->temp1));
if (*state->sender && state->fullname && *state->fullname) {
- vstring_sprintf(state->temp1, "(%s)", state->fullname);
- token = tok822_parse(vstring_str(state->temp1));
- vstring_strcat(state->temp2, " ");
- tok822_externalize(state->temp2, token, TOK822_STR_NONE);
- tok822_free_tree(token);
+ char *cp;
+
+ /* Enforce some sanity on full name content. */
+ while ((cp = strchr(state->fullname, '\r')) != 0
+ || (cp = strchr(state->fullname, '\n')) != 0)
+ *cp = ' ';
+
+ switch (hfrom_format_code) {
+
+ /*
+ * "From: phrase <route-addr>". Quote the phrase if it
+ * contains specials or the "%!" legacy address operators.
+ */
+ case HFROM_FORMAT_CODE_STD:
+ vstring_sprintf(state->temp2, "%sFrom: ", state->resent);
+ if (state->fullname[strcspn(state->fullname,
+ "%!" LEX_822_SPECIALS)] == 0) {
+ /* Normalize whitespace. */
+ token = tok822_scan_limit(state->fullname, &dummy_token,
+ var_token_limit);
+ } else {
+ token = tok822_alloc(TOK822_QSTRING, state->fullname);
+ }
+ tok822_externalize(state->temp2, token, TOK822_STR_NONE);
+ tok822_free(token);
+ vstring_sprintf_append(state->temp2, " <%s>",
+ vstring_str(state->temp1));
+ break;
+
+ /*
+ * "From: addr-spec (ctext)". This is the obsolete form.
+ */
+ case HFROM_FORMAT_CODE_OBS:
+ vstring_sprintf(state->temp2, "%sFrom: %s ",
+ state->resent, vstring_str(state->temp1));
+ vstring_sprintf(state->temp1, "(%s)", state->fullname);
+ token = tok822_parse(vstring_str(state->temp1));
+ tok822_externalize(state->temp2, token, TOK822_STR_NONE);
+ tok822_free_tree(token);
+ break;
+ default:
+ msg_panic("%s: unknown header format %d",
+ myname, hfrom_format_code);
+ }
+ }
+
+ /*
+ * "From: addr-spec". This is the form in the absence of full name
+ * information, also used for mail from mailer-daemon.
+ */
+ else {
+ vstring_sprintf(state->temp2, "%sFrom: %s",
+ state->resent, vstring_str(state->temp1));
}
CLEANUP_OUT_BUF(state, REC_TYPE_NORM, state->temp2);
}
#define DEF_DROP_HDRS "bcc, content-length, resent-bcc, return-path"
extern char *var_drop_hdrs;
+ /*
+ * From: header format: we provide canned versions only, no Sendmail-style
+ * macro expansions.
+ */
+#define HFROM_FORMAT_NAME_STD "standard" /* From: name <address> */
+#define HFROM_FORMAT_NAME_OBS "obsolete" /* From: address (name) */
+#define VAR_HFROM_FORMAT "header_from_format"
+#define DEF_HFROM_FORMAT HFROM_FORMAT_NAME_STD
+extern char *var_hfrom_format;
+
/*
* Standards violation: allow/permit RFC 822-style addresses in SMTP
* commands.
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20180106"
+#define MAIL_RELEASE_DATE "20180107"
#define MAIL_VERSION_NUMBER "3.3"
#ifdef SNAPSHOT