如何对电子邮件地址中的特殊字符进行编码

问题描述 投票:0回答:3

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

[电子邮件受保护]

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

“John Doe”<[电子邮件受保护]>

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

“Hubert Schölnast”<[电子邮件受保护]>

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

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

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

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

perl email encoding special-characters
3个回答
5
投票

Perl 核心有

Encode.pm
:

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

my $from_header = decode_utf8 q{From: "Hubert Schölnast" <[email protected]>};
print encode('MIME_Header', $from_header);

1;
__END__
From: "=?UTF-8?B?SHViZXJ0IFNjaMO2bG5hc3Q=?=" <[email protected]>

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

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

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


编辑

从Encode.pm版本2.80开始,MIME-Header编码被重写以符合RFC2047,我上面发布的原始代码现在无法使用。

参见:

https://metacpan.org/pod/Encode::MIME::Header#BUGS

最直接的替代方案是同时使用

Email::MIME

Email::Address::XS
,尽管这些包不在核心中:

#!/usr/bin/perl use strict; use warnings; use utf8; use open qw/:std :encoding(UTF-8)/; use Email::Address::XS; use Email::MIME::Header::AddressList; my $address = Email::Address::XS->new('Hubert Schölnast' => '[email protected]'); my $addr_list = Email::MIME::Header::AddressList->new($address); print $addr_list->as_mime_string; 1; __END__ =?UTF-8?B?SHViZXJ0IFNjaMO2bG5hc3Q=?= <[email protected]>
    

1
投票
使用

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


0
投票
这个答案的灵感来自于 ernix 接受的回复,但你不需要涉及 Email::Address:XS,你可以只说:

print Email::MIME::Header::AddressList->from_string("Hubert Schölnast <[email protected]>, John Doe <[email protected]>")->as_mime_string
如您所见,此解决方案也适用于多个地址,例如在 CC 标头中。

© www.soinside.com 2019 - 2024. All rights reserved.