瑞瑞哥的博客

python使用SMTP发邮件,Gmail却显示未知发件人

python使用SMTP发邮件,Gmail却显示未知发件人

问题发现

今天尝试在python下用SMTP发邮件,使用的是阿里云的企业邮箱,却发现发到谷歌那里,始终提示未知发件人,具体如下图:

Gmail提示垃圾邮件

可以看到,Gmail这边发件人是未知,或者只给出了域名ruiruige1991.xyz,而不是具体的邮箱名`weather@ruiruige1991.xyz。这显然是不正常的,大家收邮件时候也从来不会只显示qq.com,肯定是123456@qq.com`。

定位

打开上图中的了解详情,里面解释了为什么会把邮件弄成垃圾邮件,因为邮件的发送人是未知的。我第一反映就是SPF,具体这个解释大家可以百度一下。但是阿里云企业邮箱在配置的时候就提示我设置了,我的SPF记录也是没问题的。

后来又去阿里云云栖论坛找了另外一个例子(地址),却正确的显示邮件的发送者,而且也不会归结到垃圾邮件了,具体如下:

Gmail显示正常邮件

这就奇怪了,具体代码我就不贴了,经过一番反复比对,发现问题在某一行。

有问题的:

1
message['From'] = Header("天气 <weather@ruiruige1991.xyz>", 'utf-8')

没问题的:

1
message['From'] = '%s <%s>' % (Header('天气'.decode('utf-8')).encode(), "weather@ruiruige1991.xyz")

乍一看没什么两样,而且也都用了UTF-8编码,实则还是有区别的:

  • 如果仅仅是把前面的汉字和后面的英文地址进行编码,那么这两行没区别,一个是对前面汉字编码再加上后面的英文地址;另一个是加在一起再进行编码。毕竟utf8是变成编码,这两个应该是效果一样的。
  • 实际上不是这样的,问题就出在Header上,这个函数会给内部的字符串两端加上一堆内容(这里暂时理解成两端加上一个符号),那么第一行相当于所有的数据都在符号里面;而第二个相当于只有汉字在符号里面,邮箱地址是在符号外面的。这显然就导致了问题,那么是不是这样的呢?

验证

Gmail上下载了邮件的原始内容,节选了From部分。

不正常的邮件:

1
2
3
From: =?utf-8?b?5aSp5rCU5o+Q6YaSIDx3ZWF0aGVyQHJ1aXJ1aWdlMTk5MS54eXo+?=
To: =?utf-8?b?55Ge55GeIDx3aHgyMDIwMkBnbWFpbC5jb20+?=
Subject: =?utf-8?b?5aSp5rCU?=

正常的邮件:

1
2
From: =?utf-8?b?6Ieq5a6a5LmJ5Y+R5L+h5pi156ew?= <weather@ruiruige1991.xyz>
To: whx20202@gmail.com

由对比可以看到,不正常的邮件把邮件地址也编入到问号中间的Base64编码里了,把5aSp5rCU5o+Q6YaSIDx3ZWF0aGVyQHJ1aXJ1aWdlMTk5MS54eXo+这段解码,结果是:天气提醒 <weather@ruiruige1991.xyz>

而实际上这里只应该存放别名,实际的地址在等于号、问号的后面,无需编码,这就造成了错误。

而这个问题只在Gmail上出现,QQ邮箱则没出现。说明谷歌校验的还是严格啊,或者说QQ做了防呆设计?

参考

https://cn.aliyun.com/ss/c210cOS5i3B5dGhvbuWmguS9leiwg-eUqA

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001432005226355aadb8d4b2f3f42f6b1d6f2c5bd8d5263000