2

我们的 webapp 有一项功能,允许用户通过向特定电子邮件地址发送电子邮件来导入数据。当我们的应用程序收到电子邮件时,它们的处理方式会因发送者的不同而有所不同。我们查看电子邮件的“发件人”字段,并将其与数据库中的用户进行匹配。一旦确定了发送电子邮件的用户,我们将根据该用户的个人设置处理该电子邮件。

对于大多数用户来说,这通常运行良好。但是,某些用户抱怨他们的电子邮件没有得到处理。当我们查看它时,我们发现他们的电子邮件服务器正在向发件人的电子邮件地址添加信息,这导致电子邮件地址与数据库中我们的用户表中的内容不匹配。例如,用户的电子邮件可能testuser@example.com在数据库中,但我们收到的电子邮件中的“发件人”字段可能类似于btv1==502867923ab==testuser@example.com. 一些研究表明这是由发件人的服务器使用的退回地址标签验证 (BATV)引起的。

我们需要能够从提供给我们的“发件人”字段中提取规范的电子邮件地址,以便我们可以将其与我们的用户表相匹配。这里的其他开发人员之一编写了一个函数来执行此操作,并将其提交给我进行代码审查。这是他写的(C#):

private static string SanitizeEmailSender(string sender)
{
    if (sender == null)
        return null;
    return System.Text.RegularExpressions.Regex.Replace(
        sender, 
        @"^((btv1==.{11}==)|(prvs=.{9}=))", 
        "", 
        System.Text.RegularExpressions.RegexOptions.None);
} 

此处的正则表达式模式涵盖了我们在电子邮件日志中看到的特定情况。我担心的是正则表达式可能过于具体。这些标签中是否使用btv1并且prvs唯一的前缀?后面总是正好有 9 个字符prvs=吗?除了 BATV 之外,还有其他我们需要注意的电子邮件发件人标记方案吗?我不希望将此修复程序投入生产,只是为了发现下个月我们需要再次修复它,因为还有其他情况我们没有考虑。

我的直觉是将电子邮件地址修剪为仅包含最后一个=. 但是,研究表明这=是电子邮件地址中的有效字符,因此可能是用户规范电子邮件地址的一部分。我个人从未见过=在某种标记或子地址方案之外的电子邮件地址中使用过,但你永远不知道。墨菲定律表明,一旦我假设用户的电子邮件地址中永远不会包含某个字符,那么拥有该地址的人就会立即注册。

我的问题是:如果给定更长的地址,可能包含 BATV 或其他标签,是否有行业接受的可靠方法来提取用户的规范电子邮件地址?如果做不到这一点,是否有至少比我们目前所拥有的更可靠的方法?还是我们所拥有的真的足够了?

4

2 回答 2

1

由于 BATV 添加的信息总是以 BATV 标记开头并分隔两个 ==字符串之间的信息,因此我应该使用以下内容:

((btv1|prvs)==([^=]|=[^=])*==))

当然,从某种意义上说,您是正确的,即=在电子邮件地址中允许符号作为有效字符,但这正是使用该序列(形成有效电子邮件地址)的原因。

如果您尝试深入了解与电子邮件相关的 RFC,您会发现 MIME 添加了一些结构,通过使用带引号的可打印功能允许非 ascii 字符到电子邮件地址。需要阅读一些 RFC 来选择如何正确处理这些事情。

最后,回答你的问题,因为邮件服务器被授权修改/重写信封地址---这些是用于路由邮件消息的控制协议 SMTP 中的地址---(sendmail 甚至可以在邮件中进行标题字段)您问题的正确答案是没有可靠的方法(工业接受与否)来提取发件人规范电子邮件地址。随着消息发送到目标收件人,地址会被重写,并且信息会在途中丢失。您无法恢复使用的原始地址。

最后,稍微说明一下:

  • 发件人字段由最终的 SMTP 收件人添加,以在电子邮件中包含信封发件人的地址(FROM: <sender@address.com>在原始 SMTP 协议消息中使用的地址)
  • From字段由原始邮件客户端添加以识别消息的来源。如果消息被重新发送,则此行为可以通过存在Resent-fromResent-sender字段来修改。这些标识消息的重新发送。
  • 最后,发送者可以使用回复头来指示要发送到该地址的响应。

要了解 SMTP 协议的工作原理,请阅读密集的 RFC-2821(SMTP 协议)和 RFC-2822(互联网邮件消息格式)文档。

于 2015-04-10T05:29:05.593 回答
1

btv1 和 prvs 是这些标签中唯一使用的前缀吗?

prvs是符合RFC 中定义的“元语法”的前缀。btv1梭子鱼设备无效欺骗抑制重写,它不遵循 BATV 标准(因此使用双等号)。

只匹配所有 BATV 本地部分的正则表达式将是

[0-9A-Za-z\-]+=[0-9A-Za-z\-]+=.+@.+]

但这不会赶上梭子鱼btv1重写(和其他重写)

prvs= 之后总是正好有 9 个字符吗?

不,规范说有 10 个,但在野外通常是 9 个

除了 BATV 之外,还有其他我们需要注意的电子邮件发件人标记方案吗?

是的,见下文。

给定更长的地址(可能包含 BATV 或其他标签),是否有行业接受的可靠方法来提取用户的规范电子邮件地址?

通过查看各种代码库,看起来每个人都实现了自己的解决方案。一些复杂性来自以下事实:

这是一个单元测试,其中包含可能的发件人重写示例列表,这里是一些在野外发现的语法示例

如果做不到这一点,是否有至少比我们目前所拥有的更可靠的方法?还是我们所拥有的真的足够了?

看起来最好的方法是以ezmlm-idxrspamd的方式解决每个条件。

您使用的正则表达式不会涵盖

  • loc-core带和tag-val反转的prvs
  • 遵循规范的 10 个字符而不是 9 个字符的 prv
  • SRS
  • 谷歌转发
于 2017-11-03T20:31:10.223 回答