瑞瑞哥的博客

阿里云企业邮箱SMTP无法发送邮件,及python代码范例

阿里云企业邮箱SMTP无法发送邮件,及python代码范例

本文更新说明

学习了廖雪峰老师的SMTP发送邮件一文,试着写出如下工具函数,希望能够发送邮件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import smtplib
from email.mime.text import MIMEText
from email.header import Header
import traceback

from myifttt.common.log.log import getLogger

LOG = getLogger(__name__)


def send_normal_mail(user=None, password=None, port=None,
host=None, subject=None, from_user=None,
to_user=None, body=None, from_nickname=None, to_nickname=None):
"""[summary]

[description]

Keyword Arguments:
user {[type]} -- 邮箱用户名 (default: {None})
password {[type]} -- 邮箱密码 (default: {None})
port {[type]} -- SMTP服务器端口 (default: {None})
host {[type]} -- SMTP服务器地址 (default: {None})
subject {[type]} -- 邮件标题 (default: {None})
from_user {[type]} -- from的邮箱地址 (default: {None})
to_user {[type]} -- to的邮箱地址 (default: {None})
body {[type]} -- 邮件正文 (default: {None})
from_nickname {[type]} -- 发送者的昵称 (default: {None})
to_nickname {[type]} -- 接受者的昵称 (default: {None})
"""

LOG.info("entering func send_normal_mail")

# 接收人列表
receivers = [to_user, ]

# 正文 subtype 字符集
message = MIMEText(body, 'plain', 'utf-8')
message['From'] = '%s <%s>' % (
Header(from_nickname.decode('utf-8')).encode(), from_user)
message['To'] = '%s <%s>' % (
Header(to_nickname.decode('utf-8')).encode(), to_user)

message['Subject'] = Header(subject, 'utf-8')

try:
smtpObj = smtplib.SMTP()
smtpObj.connect(host, port)
smtpObj.login(user, password)
smtpObj.sendmail(from_user, receivers, message.as_string())
except smtplib.SMTPException:
print "Error: 无法发送邮件"
traceback.print_exc()

端口是25,结果执行时候报Connection timed out错误:

1
2
3
4
5
6
7
8
9
10
11
"/root/code/test/myifttt/common/utils/SMTPutils.py", line 55, in send_normal_mail
2017-11-19 22:48:43.617 7918 ERROR demo smtpObj.connect(host, port)
2017-11-19 22:48:43.617 7918 ERROR demo File "/usr/lib/python2.7/smtplib.py", line 316, in connect
2017-11-19 22:48:43.617 7918 ERROR demo self.sock = self._get_socket(host, port, self.timeout)
2017-11-19 22:48:43.617 7918 ERROR demo File "/usr/lib/python2.7/smtplib.py", line 291, in _get_socket
2017-11-19 22:48:43.617 7918 ERROR demo return socket.create_connection((host, port), timeout)
2017-11-19 22:48:43.617 7918 ERROR demo File "/usr/lib/python2.7/socket.py", line 575, in create_connection
2017-11-19 22:48:43.617 7918 ERROR demo raise err
2017-11-19 22:48:43.617 7918 ERROR demo error: [Errno 110] Connection timed out
2017-11-19 22:48:43.617 7918 ERROR demo
:set nonu

好歹玩了VPS那么多年,第一反应就是25端口默认封掉。但是网上包括阿里云文档都说没有封掉,于是把端口改成SSL的465,再执行一把,报Connection unexpectedly closed

1
2
3
4
5
6
7
8
Traceback (most recent call last):
File "send.py", line 52, in send_normal_mail
smtpObj.connect(host, port)
File "/usr/lib/python2.7/smtplib.py", line 317, in connect
(code, msg) = self.getreply()
File "/usr/lib/python2.7/smtplib.py", line 368, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
SMTPServerDisconnected: Connection unexpectedly closed

查询教程发现,是因为连接对象是非SSL的,但是端口是SSL的。于是把smtpObj = smtplib.SMTP()改成smtpObj = smtplib.SMTP_SSL(),再次测试发现OK了。

至于为什么25端口不好使这里也没有细究了。

另外,阿里云上密码就是企业邮箱网页的登录密码,听说163和QQ的SMTP服务,需要上网页上申请一个密码才行,和登录的貌似还不太一样

参考

https://www.waitig.com/python%E7%94%A8qq%E9%82%AE%E7%AE%B1%E5%90%91%E7%BD%91%E6%98%93%E9%82%AE%E7%AE%B1%E5%8F%91%E9%82%AE%E4%BB%B6%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3-2.html

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832745198026a685614e7462fb57dbf733cc9f3ad000