2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 13:48:06 +00:00

postfix-2.12-20140720

This commit is contained in:
Wietse Venema
2014-07-20 00:00:00 -05:00
committed by Viktor Dukhovni
parent 14d1b2133a
commit 73a6977944
21 changed files with 283 additions and 77 deletions

1
postfix/.indent.pro vendored
View File

@@ -26,6 +26,7 @@
-TBOUNCE_LOG_FORGE -TBOUNCE_LOG_FORGE
-TBOUNCE_LOG_RCPT_BUF -TBOUNCE_LOG_RCPT_BUF
-TBOUNCE_STAT -TBOUNCE_STAT
-TBOUNCE_STR_PARAMETER
-TBOUNCE_TEMPLATE -TBOUNCE_TEMPLATE
-TBOUNCE_TEMPLATES -TBOUNCE_TEMPLATES
-TBOUNCE_TIME_DIVISOR -TBOUNCE_TIME_DIVISOR

View File

@@ -20261,3 +20261,18 @@ Apologies for any names omitted.
Cleanup: hard-coded GCC dependencies. Eray Aslan. File: Cleanup: hard-coded GCC dependencies. Eray Aslan. File:
makedefs. makedefs.
20140717
Safety: manipulate unsigned characters while decoding.
Files: global/xtext.c, global/uxtext.c.
Infrastructure: ACE label to UTF-8 conversion. Files:
util/midna.[hc].
Infrastructure: macro expansion with printable() filter.
Files: util/mac_expand.[hc].
Feature: when expanding myhostname or mydomain in bounce
template messages, and smtputf8_enable=yes, convert ACE
(xn--mumble) labels into UTF-8. bounce/bounce_template.c.

View File

@@ -8,6 +8,11 @@ Wish list:
Things to do after the stable release: Things to do after the stable release:
up-convert myhostname in MIME boundary strings?
Table-driven case folding and case-insensitive string
comparison specifically for UTF-8.
When downgrading message/global to 7bit, is quoted-printable When downgrading message/global to 7bit, is quoted-printable
the appropriate encoding? Should it be base64? the appropriate encoding? Should it be base64?

View File

@@ -16,16 +16,16 @@ BOUNCE(5) BOUNCE(5)
<b>DESCRIPTION</b> <b>DESCRIPTION</b>
The Postfix <a href="bounce.8.html"><b>bounce</b>(8)</a> server produces delivery status notification The Postfix <a href="bounce.8.html"><b>bounce</b>(8)</a> server produces delivery status notification
(DSN) messages for undeliverable mail, delayed mail, successful deliv- (DSN) messages for undeliverable mail, delayed mail, successful deliv
ery or address verification requests. ery or address verification requests.
By default, these notifications are generated from built-in templates By default, these notifications are generated from built-in templates
with message headers and message text. Sites can override the built-in with message headers and message text. Sites can override the built-in
information by specifying a bounce template file with the <b><a href="postconf.5.html#bounce_template_file">bounce_tem</a>-</b> information by specifying a bounce template file with the <b>bounce_tem</b>
<b><a href="postconf.5.html#bounce_template_file">plate_file</a></b> configuration parameter. <b>plate_file</b> configuration parameter.
This document describes the general procedure to create a bounce tem- This document describes the general procedure to create a bounce tem
plate file, followed by the specific details of bounce template for- plate file, followed by the specific details of bounce template for
mats. mats.
<b>GENERAL PROCEDURE</b> <b>GENERAL PROCEDURE</b>
@@ -44,7 +44,7 @@ BOUNCE(5) BOUNCE(5)
expansion of time value parameters that appear in the delayed mail expansion of time value parameters that appear in the delayed mail
notification text. notification text.
Once the result is satisfactory, copy the template to the Postfix con- Once the result is satisfactory, copy the template to the Postfix con
figuration directory and specify in <a href="postconf.5.html">main.cf</a> something like: figuration directory and specify in <a href="postconf.5.html">main.cf</a> something like:
/etc/postfix/<a href="postconf.5.html">main.cf</a>: /etc/postfix/<a href="postconf.5.html">main.cf</a>:
@@ -53,13 +53,13 @@ BOUNCE(5) BOUNCE(5)
<b>TEMPLATE FILE FORMAT</b> <b>TEMPLATE FILE FORMAT</b>
The template file can specify templates for failed mail, delayed mail, The template file can specify templates for failed mail, delayed mail,
successful delivery or for address verification. These templates are successful delivery or for address verification. These templates are
named <b>failure_template</b>, <b>delay_template</b>, <b>success_template</b> and <b>ver-</b> named <b>failure_template</b>, <b>delay_template</b>, <b>success_template</b> and <b>ver</b>
<b>ify_template</b>, respectively. You can but do not have to specify all <b>ify_template</b>, respectively. You can but do not have to specify all
four templates in a bounce template file. four templates in a bounce template file.
Each template starts with "<i>template</i><b>_</b><i>name</i> <b>=</b> &lt;&lt;<b>EOF</b>" and ends with a line Each template starts with "<i>template</i><b>_</b><i>name</i> <b>=</b> &lt;&lt;<b>EOF</b>" and ends with a line
that contains the word "<b>EOF</b>" only. You can change the word EOF, but you that contains the word "<b>EOF</b>" only. You can change the word EOF, but you
can't enclose it in quotes as with the shell or with Perl (<i>tem-</i> can't enclose it in quotes as with the shell or with Perl (<i>tem</i>
<i>plate</i><b>_</b><i>name</i> <b>=</b> &lt;&lt;<b>'EOF'</b>). Here is an example: <i>plate</i><b>_</b><i>name</i> <b>=</b> &lt;&lt;<b>'EOF'</b>). Here is an example:
# The failure template is used for undeliverable mail. # The failure template is used for undeliverable mail.
@@ -83,16 +83,16 @@ BOUNCE(5) BOUNCE(5)
The mail system The mail system
EOF EOF
The usage and specification of bounce templates is subject to the fol- The usage and specification of bounce templates is subject to the fol
lowing restrictions: lowing restrictions:
<b>o</b> No special meaning is given to the backslash character or to · No special meaning is given to the backslash character or to
leading whitespace; these are always taken literally. leading whitespace; these are always taken literally.
<b>o</b> Inside the &lt;&lt; context, the "$" character is special. To produce · Inside the &lt;&lt; context, the "$" character is special. To produce
a "$" character as output, specify "$$". a "$" character as output, specify "$$".
<b>o</b> Outside the &lt;&lt; context, lines beginning with "#" are ignored, as · Outside the &lt;&lt; context, lines beginning with "#" are ignored, as
are empty lines, and lines consisting of whitespace only. are empty lines, and lines consisting of whitespace only.
Examples of all templates can be found in the file <b>bounce.cf.default</b> in Examples of all templates can be found in the file <b>bounce.cf.default</b> in
@@ -100,7 +100,7 @@ BOUNCE(5) BOUNCE(5)
<b>TEMPLATE HEADER FORMAT</b> <b>TEMPLATE HEADER FORMAT</b>
The first portion of a bounce template consists of optional template The first portion of a bounce template consists of optional template
headers. Some become message headers in the delivery status notifica- headers. Some become message headers in the delivery status notifica
tion; some control the formatting of that notification. Headers not tion; some control the formatting of that notification. Headers not
specified in a template will be left at their default value. specified in a template will be left at their default value.
@@ -114,26 +114,26 @@ BOUNCE(5) BOUNCE(5)
notification. notification.
<b>Subject:</b> <b>Subject:</b>
The subject in the message header of the delivery status notifi- The subject in the message header of the delivery status notifi
cation that is returned to the sender. cation that is returned to the sender.
<b>Postmaster-Subject:</b> <b>Postmaster-Subject:</b>
The subject that will be used in Postmaster copies of undeliver- The subject that will be used in Postmaster copies of undeliver
able or delayed mail notifications. These copies are sent under able or delayed mail notifications. These copies are sent under
control of the <a href="postconf.5.html#notify_classes">notify_classes</a> configuration parameter. control of the <a href="postconf.5.html#notify_classes">notify_classes</a> configuration parameter.
The usage and specification of template message headers is subject to The usage and specification of template message headers is subject to
the following restrictions: the following restrictions:
<b>o</b> Template message header names can be specified in upper case, · Template message header names can be specified in upper case,
lower case or mixed case. Postfix always produces bounce message lower case or mixed case. Postfix always produces bounce message
header labels of the form "<b>From:</b>" and "<b>Subject:</b>". header labels of the form "<b>From:</b>" and "<b>Subject:</b>".
<b>o</b> Template message headers must not span multiple lines. · Template message headers must not span multiple lines.
<b>o</b> Template message headers do not support $parameter expansions. · Template message headers do not support $parameter expansions.
<b>o</b> Template message headers must contain ASCII characters only, and · Template message headers must contain ASCII characters only, and
must not contain ASCII null characters. must not contain ASCII null characters.
<b>TEMPLATE MESSAGE TEXT FORMAT</b> <b>TEMPLATE MESSAGE TEXT FORMAT</b>
@@ -153,16 +153,30 @@ BOUNCE(5) BOUNCE(5)
expressed in the time unit specified by <i>suffix</i>. See above under expressed in the time unit specified by <i>suffix</i>. See above under
<b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a></b> for possible <i>suffix</i> values. <b><a href="postconf.5.html#delay_warning_time">delay_warning_time</a></b> for possible <i>suffix</i> values.
<b><a href="postconf.5.html#mydomain">mydomain</a></b>
Expands into the value of the <b><a href="postconf.5.html#mydomain">mydomain</a></b> parameter. With "smt
putf8_enable = yes", this replaces ACE labels (xn--mumble) with
their UTF-8 equivalent.
This feature is available in Postfix 2.12.
<b><a href="postconf.5.html#myhostname">myhostname</a></b>
Expands into the value of the <b><a href="postconf.5.html#myhostname">myhostname</a></b> parameter. With "smt
putf8_enable = yes", this replaces ACE labels (xn--mumble) with
their UTF-8 equivalent.
This feature is available in Postfix 2.12.
The usage and specification of template message text is subject to the The usage and specification of template message text is subject to the
following restrictions: following restrictions:
<b>o</b> The template message text is not sent in Postmaster copies of · The template message text is not sent in Postmaster copies of
delivery status notifications. delivery status notifications.
<b>o</b> If the template message text contains non-ASCII characters, · If the template message text contains non-ASCII characters,
Postfix requires that the <b>Charset:</b> template header is updated. Postfix requires that the <b>Charset:</b> template header is updated.
Specify an appropriate superset of US-ASCII. A superset is Specify an appropriate superset of US-ASCII. A superset is
needed because Postfix appends ASCII text after the message tem- needed because Postfix appends ASCII text after the message tem
plate when it sends a delivery status notification. plate when it sends a delivery status notification.
<b>SEE ALSO</b> <b>SEE ALSO</b>

View File

@@ -16413,13 +16413,12 @@ daemon. </dd>
daemon. </dd> daemon. </dd>
<dt> <b> forward </b> </dt> <dd> Local forwarding or aliasing. When <dt> <b> forward </b> </dt> <dd> Local forwarding or aliasing. When
a message is received with "SMTPUTF8 requested", then the forwarded a message is received with "SMTPUTF8 required", then the forwarded
(aliased) message automatically has "SMTPUTF8 requested". </dd> (aliased) message always has "SMTPUTF8 required". </dd>
<dt> <b> bounce </b> </dt> <dd> Submission by the <a href="bounce.8.html">bounce(8)</a> daemon. <dt> <b> bounce </b> </dt> <dd> Submission by the <a href="bounce.8.html">bounce(8)</a> daemon.
When a message is received with "SMTPUTF8 requested", then the When a message is received with "SMTPUTF8 required", then the
delivery status notification automatically has "SMTPUTF8 requested". delivery status notification always has "SMTPUTF8 required". </dd>
</dd>
<dt> <b> notify </b> </dt> <dd> Postmaster notification from the <dt> <b> notify </b> </dt> <dd> Postmaster notification from the
<a href="smtp.8.html">smtp(8)</a> or <a href="smtpd.8.html">smtpd(8)</a> daemon. </dd> <a href="smtp.8.html">smtp(8)</a> or <a href="smtpd.8.html">smtpd(8)</a> daemon. </dd>

View File

@@ -178,6 +178,18 @@ Expands into the value of the \fBmaximal_queue_lifetime\fR
parameter, expressed in the time unit specified by parameter, expressed in the time unit specified by
\fIsuffix\fR. See above under \fBdelay_warning_time\fR for \fIsuffix\fR. See above under \fBdelay_warning_time\fR for
possible \fIsuffix\fR values. possible \fIsuffix\fR values.
.IP \fBmydomain\fR
Expands into the value of the \fBmydomain\fR parameter.
With "smtputf8_enable = yes", this replaces ACE labels
(xn--mumble) with their UTF-8 equivalent.
.sp
This feature is available in Postfix 2.12.
.IP \fBmyhostname\fR
Expands into the value of the \fBmyhostname\fR parameter.
With "smtputf8_enable = yes", this replaces ACE labels
(xn--mumble) with their UTF-8 equivalent.
.sp
This feature is available in Postfix 2.12.
.PP .PP
The usage and specification of template message text is The usage and specification of template message text is
subject to the following restrictions: subject to the following restrictions:

View File

@@ -11229,13 +11229,13 @@ daemon.
.br .br
.IP "\fB forward \fR" .IP "\fB forward \fR"
Local forwarding or aliasing. When Local forwarding or aliasing. When
a message is received with "SMTPUTF8 requested", then the forwarded a message is received with "SMTPUTF8 required", then the forwarded
(aliased) message automatically has "SMTPUTF8 requested". (aliased) message always has "SMTPUTF8 required".
.br .br
.IP "\fB bounce \fR" .IP "\fB bounce \fR"
Submission by the \fBbounce\fR(8) daemon. Submission by the \fBbounce\fR(8) daemon.
When a message is received with "SMTPUTF8 requested", then the When a message is received with "SMTPUTF8 required", then the
delivery status notification automatically has "SMTPUTF8 requested". delivery status notification always has "SMTPUTF8 required".
.br .br
.IP "\fB notify \fR" .IP "\fB notify \fR"
Postmaster notification from the Postmaster notification from the

View File

@@ -164,6 +164,18 @@
# parameter, expressed in the time unit specified by # parameter, expressed in the time unit specified by
# \fIsuffix\fR. See above under \fBdelay_warning_time\fR for # \fIsuffix\fR. See above under \fBdelay_warning_time\fR for
# possible \fIsuffix\fR values. # possible \fIsuffix\fR values.
# .IP \fBmydomain\fR
# Expands into the value of the \fBmydomain\fR parameter.
# With "smtputf8_enable = yes", this replaces ACE labels
# (xn--mumble) with their UTF-8 equivalent.
# .sp
# This feature is available in Postfix 2.12.
# .IP \fBmyhostname\fR
# Expands into the value of the \fBmyhostname\fR parameter.
# With "smtputf8_enable = yes", this replaces ACE labels
# (xn--mumble) with their UTF-8 equivalent.
# .sp
# This feature is available in Postfix 2.12.
# .PP # .PP
# The usage and specification of template message text is # The usage and specification of template message text is
# subject to the following restrictions: # subject to the following restrictions:

View File

@@ -16097,13 +16097,12 @@ daemon. </dd>
daemon. </dd> daemon. </dd>
<dt> <b> forward </b> </dt> <dd> Local forwarding or aliasing. When <dt> <b> forward </b> </dt> <dd> Local forwarding or aliasing. When
a message is received with "SMTPUTF8 requested", then the forwarded a message is received with "SMTPUTF8 required", then the forwarded
(aliased) message automatically has "SMTPUTF8 requested". </dd> (aliased) message always has "SMTPUTF8 required". </dd>
<dt> <b> bounce </b> </dt> <dd> Submission by the bounce(8) daemon. <dt> <b> bounce </b> </dt> <dd> Submission by the bounce(8) daemon.
When a message is received with "SMTPUTF8 requested", then the When a message is received with "SMTPUTF8 required", then the
delivery status notification automatically has "SMTPUTF8 requested". delivery status notification always has "SMTPUTF8 required". </dd>
</dd>
<dt> <b> notify </b> </dt> <dd> Postmaster notification from the <dt> <b> notify </b> </dt> <dd> Postmaster notification from the
smtp(8) or smtpd(8) daemon. </dd> smtp(8) or smtpd(8) daemon. </dd>

View File

@@ -298,6 +298,7 @@ bounce_template.o: ../../include/mac_parse.h
bounce_template.o: ../../include/mail_conf.h bounce_template.o: ../../include/mail_conf.h
bounce_template.o: ../../include/mail_params.h bounce_template.o: ../../include/mail_params.h
bounce_template.o: ../../include/mail_proto.h bounce_template.o: ../../include/mail_proto.h
bounce_template.o: ../../include/midna.h
bounce_template.o: ../../include/msg.h bounce_template.o: ../../include/msg.h
bounce_template.o: ../../include/mymalloc.h bounce_template.o: ../../include/mymalloc.h
bounce_template.o: ../../include/split_at.h bounce_template.o: ../../include/split_at.h

View File

@@ -227,18 +227,19 @@ static BOUNCE_INFO *bounce_mail_alloc(const char *service,
/* /*
* Bundle up a bunch of parameters and initialize information that will * Bundle up a bunch of parameters and initialize information that will
* be discovered on the fly. * be discovered on the fly.
*
* XXX Instead of overriding the returned-message MIME encoding, separate
* the returned-message MIME encoding from the (boiler plate, delivery
* status) MIME encoding.
*/ */
bounce_info = (BOUNCE_INFO *) mymalloc(sizeof(*bounce_info)); bounce_info = (BOUNCE_INFO *) mymalloc(sizeof(*bounce_info));
bounce_info->service = service; bounce_info->service = service;
bounce_info->queue_name = queue_name; bounce_info->queue_name = queue_name;
bounce_info->queue_id = queue_id; bounce_info->queue_id = queue_id;
bounce_info->smtputf8 = smtputf8; bounce_info->smtputf8 = smtputf8;
/* Fix 20140708: propagate smtputf8 attribute to bounce message. */
bounce_info->smtputf8_attr =
vstring_export(vstring_sprintf(vstring_alloc(20), "%s=%d",
MAIL_ATTR_SMTPUTF8, smtputf8));
/* Fix 20140708: override MIME encoding: addresses may be 8bit. */ /* Fix 20140708: override MIME encoding: addresses may be 8bit. */
if (bounce_info->smtputf8) { /* Fix 20140718: override MIME encoding: 8bit $myhostname expansion. */
if (var_smtputf8_enable /* was: bounce_info->smtputf8 */ ) {
bounce_info->mime_encoding = "8bit"; bounce_info->mime_encoding = "8bit";
} else if (strcmp(encoding, MAIL_ATTR_ENC_8BIT) == 0) { } else if (strcmp(encoding, MAIL_ATTR_ENC_8BIT) == 0) {
bounce_info->mime_encoding = "8bit"; bounce_info->mime_encoding = "8bit";
@@ -442,7 +443,6 @@ void bounce_mail_free(BOUNCE_INFO *bounce_info)
bounce_info->queue_id); bounce_info->queue_id);
vstring_free(bounce_info->buf); vstring_free(bounce_info->buf);
vstring_free(bounce_info->sender); vstring_free(bounce_info->sender);
myfree(bounce_info->smtputf8_attr);
myfree(bounce_info->mail_name); myfree(bounce_info->mail_name);
myfree((char *) bounce_info->mime_boundary); myfree((char *) bounce_info->mime_boundary);
myfree((char *) bounce_info); myfree((char *) bounce_info);
@@ -460,6 +460,7 @@ int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
* headers and will make all addresses fully qualified. * headers and will make all addresses fully qualified.
*/ */
#define STREQ(a, b) (strcasecmp((a), (b)) == 0) #define STREQ(a, b) (strcasecmp((a), (b)) == 0)
#define STRNE(a, b) (strcasecmp((a), (b)) != 0)
/* /*
* Generic headers. * Generic headers.
@@ -493,15 +494,25 @@ int bounce_header(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
/* /*
* MIME header. * MIME header.
*/ */
#define NOT_US_ASCII(tp) \
STRNE(bounce_template_charset(template), "us-ascii")
#define NOT_7BIT_MIME(bp) \
(bp->mime_encoding && STRNE(bp->mime_encoding, MAIL_ATTR_ENC_7BIT))
post_mail_fputs(bounce, ""); post_mail_fputs(bounce, "");
post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary); post_mail_fprintf(bounce, "--%s", bounce_info->mime_boundary);
post_mail_fprintf(bounce, "Content-Description: %s", "Notification"); post_mail_fprintf(bounce, "Content-Description: %s", "Notification");
/* Fix 20140718: UTF-8 address or $myhostname expansion. */
post_mail_fprintf(bounce, "Content-Type: %s; charset=%s", post_mail_fprintf(bounce, "Content-Type: %s; charset=%s",
"text/plain", bounce_template_charset(template)); "text/plain", NOT_US_ASCII(template) ?
bounce_template_charset(template) :
NOT_7BIT_MIME(bounce_info) ?
"utf-8" : "us-ascii");
/* Fix 20140709: addresses may be 8bit. */ /* Fix 20140709: addresses may be 8bit. */
if (bounce_info->smtputf8) if (NOT_7BIT_MIME(bounce_info))
post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s",
bounce_info->mime_encoding); bounce_info->mime_encoding);
post_mail_fputs(bounce, ""); post_mail_fputs(bounce, "");
return (vstream_ferror(bounce)); return (vstream_ferror(bounce));
@@ -626,7 +637,7 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
(bounce_info->smtputf8 & SMTPUTF8_FLAG_REQUESTED) ? (bounce_info->smtputf8 & SMTPUTF8_FLAG_REQUESTED) ?
"global-" : ""); "global-" : "");
/* Fix 20140709: addresses may be 8bit. */ /* Fix 20140709: addresses may be 8bit. */
if (bounce_info->smtputf8) if (NOT_7BIT_MIME(bounce_info))
post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s",
bounce_info->mime_encoding); bounce_info->mime_encoding);
@@ -647,13 +658,15 @@ int bounce_header_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
} }
post_mail_fprintf(bounce, "X-%s-Queue-ID: %s", post_mail_fprintf(bounce, "X-%s-Queue-ID: %s",
bounce_info->mail_name, bounce_info->queue_id); bounce_info->mail_name, bounce_info->queue_id);
#define IS_UTF8_ADDRESS(str, len) \
((str)[0] != 0 && !allascii(str) && valid_utf8_string((str), (len)))
/* Fix 20140708: use "utf-8" or "rfc822" as appropriate. */ /* Fix 20140708: use "utf-8" or "rfc822" as appropriate. */
if (VSTRING_LEN(bounce_info->sender) > 0) if (VSTRING_LEN(bounce_info->sender) > 0)
post_mail_fprintf(bounce, "X-%s-Sender: %s; %s", post_mail_fprintf(bounce, "X-%s-Sender: %s; %s",
bounce_info->mail_name, bounce_info->smtputf8 bounce_info->mail_name, bounce_info->smtputf8
&& STR(bounce_info->sender)[0] && IS_UTF8_ADDRESS(STR(bounce_info->sender),
&& !allascii(STR(bounce_info->sender))
&& valid_utf8_string(STR(bounce_info->sender),
VSTRING_LEN(bounce_info->sender)) ? VSTRING_LEN(bounce_info->sender)) ?
"utf-8" : "rfc822", STR(bounce_info->sender)); "utf-8" : "rfc822", STR(bounce_info->sender));
if (bounce_info->arrival_time > 0) if (bounce_info->arrival_time > 0)
@@ -672,10 +685,9 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
post_mail_fputs(bounce, ""); post_mail_fputs(bounce, "");
/* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */
post_mail_fprintf(bounce, "Final-Recipient: %s; %s", post_mail_fprintf(bounce, "Final-Recipient: %s; %s",
bounce_info->smtputf8 && rcpt->address[0] bounce_info->smtputf8
&& !allascii(rcpt->address) && IS_UTF8_ADDRESS(rcpt->address,
&& valid_utf8_string(rcpt->address, strlen(rcpt->address)) ?
strlen(rcpt->address)) ?
"utf-8" : "rfc822", rcpt->address); "utf-8" : "rfc822", rcpt->address);
/* /*
@@ -702,10 +714,9 @@ int bounce_recipient_dsn(VSTREAM *bounce, BOUNCE_INFO *bounce_info)
} else if (NON_NULL_EMPTY(rcpt->orig_addr)) { } else if (NON_NULL_EMPTY(rcpt->orig_addr)) {
/* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */ /* Fix 20140708: Don't send "utf-8" type with non-UTF8 address. */
post_mail_fprintf(bounce, "Original-Recipient: %s; %s", post_mail_fprintf(bounce, "Original-Recipient: %s; %s",
bounce_info->smtputf8 && rcpt->orig_addr[0] bounce_info->smtputf8
&& !allascii(rcpt->orig_addr) && IS_UTF8_ADDRESS(rcpt->orig_addr,
&& valid_utf8_string(rcpt->orig_addr, strlen(rcpt->orig_addr)) ?
strlen(rcpt->orig_addr)) ?
"utf-8" : "rfc822", rcpt->orig_addr); "utf-8" : "rfc822", rcpt->orig_addr);
} }
post_mail_fprintf(bounce, "Action: %s", post_mail_fprintf(bounce, "Action: %s",
@@ -807,7 +818,7 @@ int bounce_original(VSTREAM *bounce, BOUNCE_INFO *bounce_info,
post_mail_fprintf(bounce, "Content-Type: %s", post_mail_fprintf(bounce, "Content-Type: %s",
headers_only == DSN_RET_HDRS ? headers_only == DSN_RET_HDRS ?
"text/rfc822-headers" : "message/rfc822"); "text/rfc822-headers" : "message/rfc822");
if (bounce_info->mime_encoding) if (NOT_7BIT_MIME(bounce_info))
post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s", post_mail_fprintf(bounce, "Content-Transfer-Encoding: %s",
bounce_info->mime_encoding); bounce_info->mime_encoding);
post_mail_fputs(bounce, ""); post_mail_fputs(bounce, "");

View File

@@ -85,7 +85,6 @@ typedef struct {
BOUNCE_LOG *log_handle; /* open logfile */ BOUNCE_LOG *log_handle; /* open logfile */
char *mail_name; /* $mail_name, cooked */ char *mail_name; /* $mail_name, cooked */
int smtputf8; /* SMTPUTF8 requested */ int smtputf8; /* SMTPUTF8 requested */
char *smtputf8_attr; /* pre-formatted record value */
} BOUNCE_INFO; } BOUNCE_INFO;
/* */ /* */

View File

@@ -117,6 +117,9 @@
#include <split_at.h> #include <split_at.h>
#include <stringops.h> #include <stringops.h>
#include <mymalloc.h> #include <mymalloc.h>
#ifndef NO_EAI
#include <midna.h>
#endif
/* Global library. */ /* Global library. */
@@ -198,6 +201,21 @@ static const BOUNCE_TIME_PARAMETER time_parameter[] = {
0, 0, 0, 0,
}; };
/*
* Parameters whose value may have to be converted to UTF-8 for presentation
* purposes.
*/
typedef struct {
const char *param_name; /* parameter name */
char **value; /* parameter value */
} BOUNCE_STR_PARAMETER;
static const BOUNCE_STR_PARAMETER str_parameter[] = {
VAR_MYHOSTNAME, &var_myhostname,
VAR_MYDOMAIN, &var_mydomain,
0, 0,
};
/* /*
* SLMs. * SLMs.
*/ */
@@ -387,8 +405,11 @@ static const char *bounce_template_lookup(const char *key, int unused_mode,
BOUNCE_TEMPLATE *tp = (BOUNCE_TEMPLATE *) context; BOUNCE_TEMPLATE *tp = (BOUNCE_TEMPLATE *) context;
const BOUNCE_TIME_PARAMETER *bp; const BOUNCE_TIME_PARAMETER *bp;
const BOUNCE_TIME_DIVISOR *bd; const BOUNCE_TIME_DIVISOR *bd;
const BOUNCE_STR_PARAMETER *sp;
static VSTRING *buf; static VSTRING *buf;
int result; int result;
const char *asc_val;
const char *utf8_val;
/* /*
* Look for parameter names that can have a time unit suffix, and scale * Look for parameter names that can have a time unit suffix, and scale
@@ -426,6 +447,33 @@ static const char *bounce_template_lookup(const char *key, int unused_mode,
key + bp->param_name_len + 1, key); key + bp->param_name_len + 1, key);
} }
} }
/*
* Look for parameter names that may have to be up-converted for
* presentation purposes.
*/
#ifndef NO_EAI
if (var_smtputf8_enable) {
for (sp = str_parameter; sp->param_name; sp++) {
if (strcmp(key, sp->param_name) == 0) {
asc_val = sp->value[0];
if (!allascii(asc_val)) {
msg_warn("%s: conversion \"%s\" failed: "
"non-ASCII input value: \"%s\"",
tp->origin, key, asc_val);
return (asc_val);
} else if ((utf8_val = midna_ascii_to_utf8(asc_val)) == 0) {
msg_warn("%s: conversion \"%s\" failed: "
"input value: \"%s\"",
tp->origin, key, asc_val);
return (asc_val);
} else {
return (utf8_val);
}
}
}
}
#endif
return (mail_conf_lookup_eval(key)); return (mail_conf_lookup_eval(key));
} }
@@ -453,13 +501,12 @@ void bounce_template_expand(BOUNCE_XP_PUT_FN out_fn, VSTREAM *fp,
VSTRING *buf = vstring_alloc(100); VSTRING *buf = vstring_alloc(100);
const char **cpp; const char **cpp;
int stat; int stat;
const char *filter = "\t !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER) if (tp->flags & BOUNCE_TMPL_FLAG_NEW_BUFFER)
bounce_template_parse_buffer(tp); bounce_template_parse_buffer(tp);
for (cpp = tp->message_text; *cpp; cpp++) { for (cpp = tp->message_text; *cpp; cpp++) {
stat = mac_expand(buf, *cpp, MAC_EXP_FLAG_NONE, filter, stat = mac_expand(buf, *cpp, MAC_EXP_FLAG_PRINTABLE, (char *) 0,
bounce_template_lookup, (char *) tp); bounce_template_lookup, (char *) tp);
if (stat & MAC_PARSE_ERROR) if (stat & MAC_PARSE_ERROR)
msg_fatal("%s: bad $name syntax in %s template: %s", msg_fatal("%s: bad $name syntax in %s template: %s",

View File

@@ -20,7 +20,7 @@
* Patches change both the patchlevel and the release date. Snapshots have no * Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only. * patchlevel; they change the release date only.
*/ */
#define MAIL_RELEASE_DATE "20140716" #define MAIL_RELEASE_DATE "20140720"
#define MAIL_VERSION_NUMBER "2.12" #define MAIL_VERSION_NUMBER "2.12"
#ifdef SNAPSHOT #ifdef SNAPSHOT

View File

@@ -146,10 +146,10 @@ VSTRING *uxtext_quote(VSTRING *quoted, const char *unquoted, const char *special
VSTRING *uxtext_unquote_append(VSTRING *unquoted, const char *quoted) VSTRING *uxtext_unquote_append(VSTRING *unquoted, const char *quoted)
{ {
const char *cp; const unsigned char *cp;
int ch; int ch;
for (cp = quoted; (ch = *cp) != 0; cp++) { for (cp = (const unsigned char *) quoted; (ch = *cp) != 0; cp++) {
if (ch == '\\' && cp[1] == 'x' && cp[2] == '{') { if (ch == '\\' && cp[1] == 'x' && cp[2] == '{') {
cp += 2; cp += 2;
int unicode = 0; int unicode = 0;

View File

@@ -101,10 +101,10 @@ VSTRING *xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
VSTRING *xtext_unquote_append(VSTRING *unquoted, const char *quoted) VSTRING *xtext_unquote_append(VSTRING *unquoted, const char *quoted)
{ {
const char *cp; const unsigned char *cp;
int ch; int ch;
for (cp = quoted; (ch = *cp) != 0; cp++) { for (cp = (const unsigned char *) quoted; (ch = *cp) != 0; cp++) {
if (ch == '+') { if (ch == '+') {
if (ISDIGIT(cp[1])) if (ISDIGIT(cp[1]))
ch = (cp[1] - '0') << 4; ch = (cp[1] - '0') << 4;

View File

@@ -1523,8 +1523,6 @@ load_file.o: vbuf.h
load_file.o: vstream.h load_file.o: vstream.h
load_file.o: warn_stat.h load_file.o: warn_stat.h
load_lib.o: load_lib.c load_lib.o: load_lib.c
load_lib.o: load_lib.h
load_lib.o: msg.h
load_lib.o: sys_defs.h load_lib.o: sys_defs.h
lowercase.o: lowercase.c lowercase.o: lowercase.c
lowercase.o: stringops.h lowercase.o: stringops.h
@@ -1542,6 +1540,7 @@ mac_expand.o: mac_expand.h
mac_expand.o: mac_parse.h mac_expand.o: mac_parse.h
mac_expand.o: msg.h mac_expand.o: msg.h
mac_expand.o: mymalloc.h mac_expand.o: mymalloc.h
mac_expand.o: stringops.h
mac_expand.o: sys_defs.h mac_expand.o: sys_defs.h
mac_expand.o: vbuf.h mac_expand.o: vbuf.h
mac_expand.o: vstring.h mac_expand.o: vstring.h
@@ -1599,6 +1598,7 @@ midna.o: msg.h
midna.o: mymalloc.h midna.o: mymalloc.h
midna.o: stringops.h midna.o: stringops.h
midna.o: sys_defs.h midna.o: sys_defs.h
midna.o: valid_hostname.h
midna.o: vbuf.h midna.o: vbuf.h
midna.o: vstring.h midna.o: vstring.h
msg.o: msg.c msg.o: msg.c

View File

@@ -54,6 +54,8 @@
/* string, including macro names in the values of conditional /* string, including macro names in the values of conditional
/* expressions. Do not expand macros, and do not write to the /* expressions. Do not expand macros, and do not write to the
/* result argument. /* result argument.
/* .IP MAC_EXP_FLAG_PRINTABLE
/* Use the printable() function instead of \fIfilter\fR.
/* .PP /* .PP
/* The constant MAC_EXP_FLAG_NONE specifies a manifest null value. /* The constant MAC_EXP_FLAG_NONE specifies a manifest null value.
/* .RE /* .RE
@@ -103,6 +105,7 @@
#include <msg.h> #include <msg.h>
#include <vstring.h> #include <vstring.h>
#include <mymalloc.h> #include <mymalloc.h>
#include <stringops.h>
#include <mac_parse.h> #include <mac_parse.h>
#include <mac_expand.h> #include <mac_expand.h>
@@ -197,7 +200,9 @@ static int mac_expand_callback(int type, VSTRING *buf, char *ptr)
} else { } else {
len = VSTRING_LEN(mc->result); len = VSTRING_LEN(mc->result);
vstring_strcat(mc->result, text); vstring_strcat(mc->result, text);
if (mc->filter) { if (mc->flags & MAC_EXP_FLAG_PRINTABLE) {
printable(vstring_str(mc->result) + len, '_');
} else if (mc->filter) {
cp = vstring_str(mc->result) + len; cp = vstring_str(mc->result) + len;
while (*(cp += strspn(cp, mc->filter))) while (*(cp += strspn(cp, mc->filter)))
*cp++ = '_'; *cp++ = '_';

View File

@@ -24,6 +24,7 @@
#define MAC_EXP_FLAG_RECURSE (1<<0) #define MAC_EXP_FLAG_RECURSE (1<<0)
#define MAC_EXP_FLAG_APPEND (1<<1) #define MAC_EXP_FLAG_APPEND (1<<1)
#define MAC_EXP_FLAG_SCAN (1<<2) #define MAC_EXP_FLAG_SCAN (1<<2)
#define MAC_EXP_FLAG_PRINTABLE (1<<3)
/* /*
* Real lookup or just a test? * Real lookup or just a test?

View File

@@ -10,6 +10,9 @@
/* /*
/* const char *midna_utf8_to_ascii( /* const char *midna_utf8_to_ascii(
/* const char *name) /* const char *name)
/*
/* const char *midna_ascii_to_utf8(
/* const char *name)
/* DESCRIPTION /* DESCRIPTION
/* The functions in this module transform domain names from /* The functions in this module transform domain names from
/* or to IDNA form. The result is cached to avoid repeated /* or to IDNA form. The result is cached to avoid repeated
@@ -18,6 +21,9 @@
/* midna_utf8_to_ascii() converts an UTF-8 domain name to /* midna_utf8_to_ascii() converts an UTF-8 domain name to
/* ASCII. The result is a null pointer in case of error. /* ASCII. The result is a null pointer in case of error.
/* /*
/* midna_ascii_to_utf8() converts an ASCII domain name to
/* UTF-8. The result is a null pointer in case of error.
/*
/* midna_cache_size specifies the size of the conversion result /* midna_cache_size specifies the size of the conversion result
/* cache. This value is used only once, upon the first lookup /* cache. This value is used only once, upon the first lookup
/* request. /* request.
@@ -55,6 +61,7 @@
#include <msg.h> #include <msg.h>
#include <ctable.h> #include <ctable.h>
#include <stringops.h> #include <stringops.h>
#include <valid_hostname.h>
#include <midna.h> #include <midna.h>
/* /*
@@ -99,9 +106,44 @@ static void *midna_utf8_to_ascii_create(const char *name, void *unused_context)
} }
} }
/* midna_utf8_to_ascii_free - cache element destructor */ /* midna_ascii_to_utf8_create - convert ASCII domain to UTF8 */
static void midna_utf8_to_ascii_free(void *value, void *unused_context) static void *midna_ascii_to_utf8_create(const char *name, void *unused_context)
{
const char myname[] = "midna_ascii_to_utf8_create";
char buf[1024]; /* XXX */
UErrorCode error = U_ZERO_ERROR;
UIDNAInfo info = UIDNA_INFO_INITIALIZER;
UIDNA *idna;
int anl;
/*
* Paranoia: do not expose uidna_*() to unfiltered network data.
*/
if (valid_hostname(name, DONT_GRIPE) == 0) {
msg_warn("%s: Problem translating domain \"%s\" to UTF8 form: %s",
myname, name, "malformed ASCII");
return (0);
}
idna = uidna_openUTS46(UIDNA_DEFAULT, &error);
anl = uidna_nameToUnicodeUTF8(idna,
name, strlen(name),
buf, sizeof(buf),
&info,
&error);
uidna_close(idna);
if (U_SUCCESS(error) && info.errors == 0 && anl > 0) {
return (mystrndup(buf, anl));
} else {
msg_warn("%s: Problem translating domain \"%s\" to IDNA form: %s",
myname, name, u_errorName(error));
return (0);
}
}
/* midna_cache_free - cache element destructor */
static void midna_cache_free(void *value, void *unused_context)
{ {
if (value) if (value)
myfree(value); myfree(value);
@@ -116,11 +158,25 @@ const char *midna_utf8_to_ascii(const char *name)
if (midna_utf8_to_ascii_cache == 0) if (midna_utf8_to_ascii_cache == 0)
midna_utf8_to_ascii_cache = ctable_create(midna_cache_size, midna_utf8_to_ascii_cache = ctable_create(midna_cache_size,
midna_utf8_to_ascii_create, midna_utf8_to_ascii_create,
midna_utf8_to_ascii_free, midna_cache_free,
(void *) 0); (void *) 0);
return (ctable_locate(midna_utf8_to_ascii_cache, name)); return (ctable_locate(midna_utf8_to_ascii_cache, name));
} }
/* midna_ascii_to_utf8 - convert UTF8 hostname to ASCII */
const char *midna_ascii_to_utf8(const char *name)
{
static CTABLE *midna_ascii_to_utf8_cache = 0;
if (midna_ascii_to_utf8_cache == 0)
midna_ascii_to_utf8_cache = ctable_create(midna_cache_size,
midna_ascii_to_utf8_create,
midna_cache_free,
(void *) 0);
return (ctable_locate(midna_ascii_to_utf8_cache, name));
}
#ifdef TEST #ifdef TEST
/* /*
@@ -128,6 +184,7 @@ const char *midna_utf8_to_ascii(const char *name)
* stderr. * stderr.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <locale.h>
#include <stringops.h> /* XXX temp_utf8_kludge */ #include <stringops.h> /* XXX temp_utf8_kludge */
#include <vstring.h> #include <vstring.h>
@@ -138,17 +195,44 @@ const char *midna_utf8_to_ascii(const char *name)
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
VSTRING *buffer = vstring_alloc(1); VSTRING *buffer = vstring_alloc(1);
const char *res; const char *bp;
const char *ascii;
const char *utf8;
if (setlocale(LC_ALL, "C") == 0)
msg_fatal("setlocale(LC_ALL, C) failed: %m");
msg_vstream_init(argv[0], VSTREAM_ERR); msg_vstream_init(argv[0], VSTREAM_ERR);
msg_verbose = 1; msg_verbose = 1;
temp_utf8_kludge = 1; temp_utf8_kludge = 1;
while (vstring_fgets_nonl(buffer, VSTREAM_IN)) { while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
msg_info("testing: \"%s\"", vstring_str(buffer)); msg_info("testing: \"%s\"", bp = vstring_str(buffer));
res = midna_utf8_to_ascii(vstring_str(buffer)); if (!allascii(bp)) {
if (res != 0) ascii = midna_utf8_to_ascii(bp);
msg_info("result: \"%s\"", res); if (ascii != 0) {
msg_info("\"%s\" -> \"%s\"", bp, ascii);
utf8 = midna_ascii_to_utf8(ascii);
if (utf8 != 0) {
msg_info("\"%s\" -> \"%s\" -> \"%s\"",
bp, ascii, utf8);
if (strcmp(utf8, bp) != 0)
msg_warn("\"%s\" != \"%s\"", bp, utf8);
}
}
} else {
utf8 = midna_ascii_to_utf8(bp);
if (utf8 != 0) {
msg_info("\"%s\" -> \"%s\"", bp, utf8);
ascii = midna_utf8_to_ascii(utf8);
if (ascii != 0) {
msg_info("\"%s\" -> \"%s\" -> \"%s\"",
bp, utf8, ascii);
if (strcmp(ascii, bp) != 0)
msg_warn("\"%s\" != \"%s\"", bp, ascii);
}
}
}
} }
exit(0); exit(0);
} }

View File

@@ -15,6 +15,7 @@
* External interface. * External interface.
*/ */
extern const char *midna_utf8_to_ascii(const char *); extern const char *midna_utf8_to_ascii(const char *);
extern const char *midna_ascii_to_utf8(const char *);
/* LICENSE /* LICENSE
/* .ad /* .ad