1.发送邮件函数:
import smtplib
def send_mail(trade_date, receivers=None, subject='数据采集完成', content='数据采集完成'):
mail_host = "smtp.qq.com"
mail_user = "XXXXXX@qq.com"
mail_pass = "XXXXXXXXXXXXXXX"
sender = 'XXXXXX@qq.com'
receivers = ['XXXXXX@qq.com'] if receivers is None else receivers
message = MIMEText(content, 'html', 'utf-8')
message['From'] = Header("YdSoft", 'utf-8')
message['To'] = Header("YdSoft", 'utf-8')
message['Subject'] = Header(trade_date + subject, 'utf-8')
try:
smtp_obj = smtplib.SMTP()
smtp_obj.connect(mail_host, 25)
smtp_obj.login(mail_user, mail_pass)
smtp_obj.sendmail(sender, receivers, message.as_string())
smtp_obj.quit()
print("邮件发送成功!")
except smtplib.SMTPException:
print("Error: 邮件发送失败!")
2.问题描述
在本地开发时,上述send_mail()函数可以正常发送邮件。但部署到阿里云服务器时,出现了问题,报SMTPServerDisconnected("Connection unexpectedly closed")错误:
Traceback (most recent call last):
File "D:\ydpy\ydtools\get_select_result.py", line 41, in <module>
d.select()
File "D:\ydpy\ydtools\get_select_result.py", line 35, in select
send_mail(self.trade_date, ['XXXXXX@qq.com'], '筛选结果', self.trade_date + '筛选结果为:<br/>' + result)
File "D:\ydpy\ydtools\func\yd_func.py", line 131, in send_mail
smtp_obj.connect(mail_host, 25)
File "D:\Program Files\Python\Python39\lib\smtplib.py", line 343, in connect
(code, msg) = self.getreply()
File "D:\Program Files\Python\Python39\lib\smtplib.py", line 400, in getreply
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
3.原因分析
上述send_mail()使用SMTP协议和25端口发送邮件,但由于smtp的25端口容易收到攻击,所以对于某些云服务器,比如说阿里云服务器,25端口是被禁止的。所以,此时应采用其他可用的端口和协议来发送邮件。
4.解决办法
改用SSL协议和465端口即可解决上述问题,即将send_mail()函数作如下修改:
将:
smtp_obj = smtplib.SMTP()
smtp_obj.connect(mail_host, 25)
改为:
smtp_obj = smtplib.SMTP_SSL(mail_host)
smtp_obj.connect(mail_host, 465)
如此,即可解决无法使用SMTP协议和25端口发送邮件的问题!