使用Python和Postfix发送VERP合规邮件

1 投票
2 回答
2056 浏览
提问于 2025-04-18 06:44

我想在Python中发送电子邮件,这样我就可以处理退信。VERP(可变电子邮件回执地址)似乎是解决这个问题的方法。不过,当我把发件人地址(不是MIMEMultipart对象的“From”值)设置为包含VERP分隔符时,我没有收到退信通知。

我可以自己创建一个VERP发件人吗?比如说,如果我想发邮件给user@domain.com,我能把发件人地址设置为“mysender+user-domain-com.mydomain.com”吗?这样就能正常工作吗?还是说我需要配置postfix,以便它能正确解析失败的DSN(送达状态通知)?我的问题是如何收到失败通知,而不是如何把邮件送到有效的收件人那里。

也许举个例子会更清楚。

当我从myuser@domain.com发送邮件时,我能正常收到退信通知。

但是当我从myuser+verp_identifier@domain.com发送邮件时,我就收不到任何退信通知了。(不过,发送给正确地址的邮件,比如valid_user@gmail.com,都是能正常送达的。)Perl的邮件模块有一个VERP子模块,Python有没有类似的东西呢?

2 个回答

1

为了正确处理VERP,Postfix需要进行特别配置。smtpd_authorized_verp_clients这个设置列出了哪些客户端可以使用VERP,它只配置了发送部分。实际上,它列出了可以使用XVERP命令的客户端,这个命令会自动在发件人地址后面加上+dest

但是在默认配置下,Postfix并不会自动把发送给sender+ext的消息送到sender那里。要让这个功能正常工作,你需要在main.cf文件中添加(或者取消注释)recipient_delimiter = +。在默认配置中,这一行是存在的,但被注释掉了。

所以,如果你能自己形成VERP发件人地址,比如说发件人地址是myuser+verpid@domain.com,那么只要你有recipient_delimiter = +,就不需要做其他事情:目标SMTP服务器会把退信发送到这个地址,而你的Postfix会正确地把它送到myuser@domain.com。

我不知道有没有哪个Python包可以自动添加XVERB命令。所以在我看来,如果你想让它自动使用,你应该按照Postfix VERP使用指南中描述的步骤来做:

你可以使用smtpd_command_filter功能来为旧软件的SMTP命令添加XVERP。这需要Postfix 2.7或更高版本。

/etc/postfix/main.cf:
    smtpd_command_filter = pcre:/etc/postfix/append_verp.pcre
    smtpd_authorized_verp_clients = $mynetworks

/etc/postfix/append_verp.pcre:
    /^(MAIL FROM:<listname@example\.com>.*)/ $1 XVERP
3

你应该使用“Return-Path”而不是“FROM”作为退信的发送地址。用Postfix发送邮件时,设置退信地址并不需要特别的配置。

对于Postfix处理不同的入站邮件,可以使用地址中的“+”符号,因为“+”后面的内容通常会被忽略。所以,如果把Return-Path设置为joe+bounce@here.com,邮件会送到joe@here.com,而收件人地址仍然是joe+bounce@here.com。你可以通过在master.cf文件中添加一个过滤器来编程处理这些邮件。

在服务列表中加入这个:

smtp      inet  n       -       -       -       -       smtpd
  -o content_filter=filter:dummy

然后在这里定义过滤器:

filter    unix  -       n       n       -      10       pipe
  flags=Rq user=filter null_sender=
  argv=/home/filter/InboundProcessor.py -f ${sender} -- ${recipient}

这样,InboundProcessor.py脚本就会通过管道接收所有入站邮件。如果收件人地址中包含“+”后面跟着某个退信的关键值,你可以把这个已经不再有效的地址在你的数据库中标记为不活跃。

撰写回答