【问题标题】:How to encode special characters in e-mail-adresses如何对电子邮件地址中的特殊字符进行编码
【发布时间】:2015-07-31 05:49:25
【问题描述】:

电子邮件地址不仅包含以下部分:

localpart@domain.tld

下一行的完整字符串(包括引号之间的部分、引号本身和尖括号)也是有效地址:

“John Doe”

当我用我自己的名字替换“John Doe”时,我会得到一个地址,我可以输入我的电子邮件客户端而不会收到任何投诉(注意 »ö« 在我的姓氏是非 ASCII 字符):

“Hubert Schölnast”

看来(对于 Thunderbird 等标准电子邮件客户端的用户而言),引用部分中的特殊字符似乎是可以的。

但是当我使用 cpan-module Email::Valid 在 perl 脚本中检查这个完整的电子邮件地址时,我收到一个错误,说这个地址不符合 rfc822 的规则,并且该模块的文档说,rfc822 不允许在电子邮件地址的任何部分中使用任何非 ascii 字符。 (当我省略字母 ö 或将其替换为 ascii 字母时,支票表明地址有效。)

显然,任何电子邮件客户端在向 smtp 服务器发送电子邮件之前都必须对电子邮件地址进行编码,并且在收到新电子邮件时必须对其进行解码并将标题信息显示给用户。但我不知道这是怎么做到的,而且我确实在谷歌上尽了最大努力。

我需要这种编码算法,因为我想编写一个 perl 脚本,它接受任何有效的电子邮件地址(在引用部分中也包含特殊字符),然后将电子邮件发送到这些地址。

【问题讨论】:

  • 顺便说一句,您的真实姓名不需要双引号,看起来就像您将其放在引号中,因为它不是您的“真实”姓名。 (要么这样,要么你使用的是 Microsoft 的电子邮件软件。无论哪种方式,都很尴尬。)
  • @tripleee:嗯,这是我的真名(查看我的个人资料)。但是,当名称包含特殊字符时,某些电子邮件客户端(不确定是哪一个)需要引号。
  • 当您对它进行 RFC2047 编码时,该值不再包含任何特殊字符。

标签: perl email encoding special-characters


【解决方案1】:

Perl 核心有Encode.pm:

#!/usr/bin/perl
use strict;
use warnings;
use Encode;

my $from_header = decode_utf8 q{From: "Hubert Schölnast" <localpart@domain.tld>};
print encode('MIME_Header', $from_header);

1;
__END__
From: "=?UTF-8?B?SHViZXJ0IFNjaMO2bG5hc3Q=?=" <localpart@domain.tld>

RFC822/2822 背后有很多要求,这使得处理电子邮件变得困难。

RFC2822 还禁止消息中的每一行超过 998 个字符。 长行必须通过缩进续行来拆分为多行。

这意味着当我们修改它们时,我们必须注意行长度,只是转换特殊字符并添加标题标签之后。

【讨论】:

  • 提示:这假定一个 UTF-8 编码的源文件。在这种情况下,请使用use utf8;。然后,您不必在任何地方都使用decode_utf8
  • @ernix:谢谢!我希望 cpan-modul Email:Sender 能正确处理 line-length 和所有这些东西。这就是我使用模块的原因。
  • 我在我的邮件服务器上搜索了存储我所有电子邮件的文件,并发现我的地址以encode('MIME_Header', $address) 生成的方式存储。谢谢! (而且我在所有脚本中总是使用use utf8;,所以不需要decode_utf8。)
【解决方案2】:

使用MIME::Words 对地址、主题等进行编码或解码。

例如创建电子邮件时:

#!/usr/bin/perl
use strict;
use warnings;
use utf8;

use MIME::Words qw{ encode_mimeword };

my $encoded = encode_mimeword('Hubert Schölnast');

要使用地址对名称进行编码,请使用encode_mimewords

处理电子邮件时,请改用decode_mimewords

【讨论】:

  • 也许还链接到定义此编码的RFC2047
  • 对完整地址使用此方法是否安全("Hubert Schölnast" )?
  • @tripleee:感谢您提供的链接,但 RFC 总是那么长且难以阅读。有没有更简短的算法描述?
  • 总之,编码字符串的形式为=?&lt;charset&gt;?&lt;bq&gt;?&lt;encoded&gt;?=,其中charset 是一个字符集说明符,如iso-8859-1enc 是一个编码说明符,b 表示 base64(的变体)或 q 表示引号可打印的(变体),encoded 是这样编码的字符串。
  • @HubertSchölnast:复数。 word ne words.
猜你喜欢
  • 2019-01-22
  • 2010-10-03
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
  • 2017-06-15
  • 1970-01-01
  • 2012-12-14
相关资源
最近更新 更多