引言

本篇博文是一个我之前没有想要去关注,但就是这样看似轻松的事情,却出现了很多的bug,我尝试用了163,、QQ以及谷歌邮箱去发送邮件,中间遇到了很多波折,其中一根谷歌的小号邮箱也被封了,所以想在这里总结下我的一些错误与笔记。

STMP协议介绍

对于Python来说,需要编写脚本调用邮件服务器来发送邮件,使用的协议是SMTP。接收邮件,使用的协议是POP3和IMAP。这三种的区别与用处后面再提,其实在上述三种邮箱的使用中,差别并不是很大,比如说QQ邮箱的STMP / IMAP是共用一个授权码,而谷歌邮箱则是按照端口划分。

在python中,提供收发邮件的库为smtplib、poplib和imaplib,而我们常用的为smtplib,下面为stmplib的一些常规方法介绍:

方法 描述
SMTP.set_debuglevel(level) 设置输出debug调试信息,默认不输出
SMTP.docmd(cmd[, argstring]) 发送一个命令到SMTP服务器
SMTP.connect([host[, port]]) 连接到指定的SMTP服务器
SMTP.helo([hostname]) 使用helo指令向SMTP服务器确认你的身份
SMTP.ehlo(hostname) 使用ehlo指令像ESMTP(SMTP扩展)确认你的身份
SMTP.ehlo_or_helo_if_needed() 如果在以前的会话连接中没有提供ehlo或者helo指令,这个方法会调用ehlo()或helo()
SMTP.has_extn(name) 判断指定名称是否在SMTP服务器上
SMTP.verify(address) 判断邮件地址是否在SMTP服务器上
SMTP.starttls([keyfile[, certfile]]) 使SMTP连接运行在TLS模式,所有的SMTP指令都会被加密
SMTP.login(user, password) 登录SMTP服务器
SMTP.sendmail(from_addr, to_addrs, msg, mail_options=[], rcpt_options=[]) 发送邮件
from_addr:邮件发件人
to_addrs:邮件收件人
msg:发送消息
SMTP.quit() 关闭SMTP会话
SMTP.close() 关闭SMTP服务器连接

以上表格转自https://blog.51cto.com/lizhenliang/1875330,那么我们就可以写一个范例如下:

#!/usr/bin/python
# -*- coding: UTF-8 -*-import smtplib
from email.mime.text import MIMEText
from email.utils import formataddrmy_sender='1004995307@qq.com'    # 发件人邮箱账号
my_pass = 'xxxxxxxxxx'              # 发件人邮箱密码
my_user='1004995307@qq.com'      # 收件人邮箱账号,我这边发送给自己
def mail():ret=Truetry:msg=MIMEText('successful!','plain','utf-8')msg['From']=formataddr(["FromRunoob",my_sender])  # 括号里的对应发件人邮箱昵称、发件人邮箱账号msg['To']=formataddr(["FK",my_user])              # 括号里的对应收件人邮箱昵称、收件人邮箱账号msg['Subject']="放假通知"                # 邮件的主题,也可以说是标题server=smtplib.SMTP_SSL("smtp.qq.com", 465)  # 发件人邮箱中的SMTP服务器,端口是25server.login(my_sender, my_pass)  # 括号中对应的是发件人邮箱账号、邮箱密码server.sendmail(my_sender,[my_user,],msg.as_string())  # 括号中对应的是发件人邮箱账号、收件人邮箱账号、发送邮件server.quit()  # 关闭连接except Exception:  # 如果 try 中的语句没有执行,则会执行下面的 ret=Falseret=Falsereturn retret=mail()
if ret:print("邮件发送成功")
else:print("邮件发送失败")

将其保存为py文件,然后运行就能去邮箱内查看到当前邮件了,但自己发给自己并不能说明是遵循STMP协议才发送或收到,所以我们需要将其放入一个固定任务中,将收件人当成我们要传的参数,然后检测是否能收到邮件才算是验证成功,这里的这种定时任务,可以简单的使用django和celery达到想要的效果,并且django中也有提供内置的mail模块,但没有stmplib好用,感觉bug有点多省略很多东西,所以还是以stmplib来构造函数:

# settings.py文件中:
EMAIL_USE_TLS = False
EMAIL_USE_SSL = FalseEMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.163.com'
#MAIL_USE_DEBUG = True
#MAIL_USE_TLS = True# EMAIL_HOST = 'smtp.maxhichina.com'
EMAIL_PORT = 25
# 发送邮件的邮箱
EMAIL_HOST_USER = 'a1004995307@163.com'
# 在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'xxxx'
# 收件人看到的发件人
# EMAIL_FROM = 'postmaster@hybridtec.cn'
EMAIL_FROM = 'xxx<a1004995307@163.com>'

然后创建一个celery的模块包,里面的task.py文件写下发邮件的脚本:

#from django.core.mail import send_mail
from celery.main import app
from django.conf import settings
import randomimport smtplib
from email.mime.text import MIMEText
from email.header import Header@app.task(name='send_verify_mail', bing=True)
def send_verify_mail(to_email, code):sender = settings.EMAIL_HOST_USERreceiver = [to_email]subject = '放假通知'username = settings.EMAIL_HOST_USERpassword = settings.EMAIL_HOST_PASSWORDmsg = MIMEText('hello code %s' % code,_charset='utf-8')  #中文需参数‘utf-8',单字节字符不需要msg['Subject'] = Header(subject, 'utf-8')msg['From'] = settings.EMAIL_FROMmsg['To'] = to_emailsmtp = smtplib.SMTP_SSL()smtp.connect(settings.EMAIL_HOST)smtp.login(username, password)smtp.sendmail(sender, receiver, msg.as_string())smtp.quit()

然后后面如果要发送邮件,只要调用这个函数,并启动celery就行了,但这里就出现了非常多的坑是各种邮箱完全不相同的验证,另外还有相关的HOST和PORT,这里将关于POP3/STMP/IMAP三种对应端口的情况列成一张表格为:

邮箱类型 服务器名称 服务器地址 SSL协议端端口 端口
QQ邮箱 POP3 pop.qq.com 110
SMTP smtp.qq.com 465 25
IMAP imap.qq.com 993
163邮箱 POP3 pop.163.com 110
SMTP smtp.163.com 465 25
IMAP imap.163.com 993
gmail邮箱 POP3 pop.gmail.com 995
SMTP smtp.gmail.com 587 / 465 25(我试验是可以)
IMAP imap.gmail.com 993
yahoo邮箱 POP3 pop.mail.yahoo.com 110
SMTP smtp.mail.yahoo.com 25
IMAP imap.mail.yahoo.com 993

表中列举到的,除了谷歌邮箱,其它都是用的国内的邮箱账号,我们主要是看STMP协议这一项,如果不做设置,可能会出现如下的情况:

这里就需要我们去开启自己邮箱里的相关设置,这里我详细说的是QQ和谷歌,因为这两个也是我试验得最久的两个了。

QQ邮箱设置

  • 进入邮箱,点击设置-账户
  • 在账户栏目下,往下拉,找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务所在位置

    然后将上述两个服务开启,一般会提示要验证绑定邮箱的一些东西,比如说向某个号码发短信,或者是密保令牌获取验证码,完成这其中的一步操作后才能看到QQ邮箱为每个账号设置的QQ授权码,然后如果是作为发信息,那么有用的为第二个,那么代码中可以修改为:
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com'
MAIL_USE_DEBUG = True
MAIL_USE_TLS = True# EMAIL_HOST = 'smtp.maxhichina.com'
EMAIL_PORT = 465
# 发送邮件的邮箱
EMAIL_HOST_USER = '1004995307@qq.com'
# 在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'xxx'
# 收件人看到的发件人
EMAIL_FROM = 'Tim<1004995307@qq.com>'

一般如果照上面这么写基本上是没啥问题的,可能Email_port改成25也能发送邮件,那表示是未加密的网关,可能就会自动判别为垃圾邮件了,如果是465的话更保险些。QQ邮箱还是没有啥太大的坑,最多全部都是退信,但Gmail的套路就可能是一环接一环了。

谷歌邮箱设置

上述国内邮箱的设置还能用Foxmail软件直接设置,QQ邮箱中就有一个很详细的说明:Foxmail常用邮件客户端软件设置

gmail邮箱是没有授权码的,应该说国外的邮箱好像很少要授权码,都是直接拿密码当成授权码用,但这个里面的坑就多了。

其实我写这篇文章的原因也是我在gmail邮箱上试了很长一段时间,原因是这个坑有点深,也可能我的搜索方式不对。当我直接用密码房授权码时,发送邮件的时候会报错为:

b"5.7.8 username or password not accept,那么也能说明这个密码是无效的。在此之前,还遇到的bug是newwork is unreachable,即是网络达不到要求,那个是因为之前用的阿里云国内服务器,然后用的25网关,但找了半天,发现好像不适用,阿里云的STMP服务地址为:

所以在这里提一下,因为当时我是拿我自己服务器测试,发现谷歌连接不上了。但项目是在国外服务器上,所以我直接在国外服务器上把邮箱替换成谷歌邮箱,然后回到这个错误:b"5.7.8 username or password not accept

然后翻遍了Stack Overflow还有一些国外怎么设置谷歌邮箱的帖子,发现了三步:

将【安全性较低的应用程式存储权限】设为【启用】

我们可以进入https://myaccount.google.com/lesssecureapps界面将设置开起来,最好是用gmail浏览器已经进行过登录,那么就能跳过一些繁琐的登录。

开启后,重新以STMP协议发送邮件,然后这个时候可能就会报错为:b"5.7.7,图没有截了,大致意思应该说是验证密码错误,也就是说开了这个后不能登录上去,如果没用,那么就下一步。

解除人机验证锁定

进入https://accounts.google.com/b/0/DisplayUnlockCaptcha 页面中,Google 可能會在您透過新的裝置或應用程式登入時,要求您完成這項額外步驟。如要授權存取,請按下方的 [繼續] 按鈕。然后我们就进入到了授权码的选择界面,

一路选是就OK了,之后可以再次尝试,如果还是不成功,这里报啥错忘了,如果还是不成功,那么就最后一步。

开启两步验证

第三步也是最后一步,如果还是不行,那只能采用这种冒险的方式,为啥说冒险呢,如果真的要做这步,就很有可能被封号几天,我当时是啥也不懂,看到有人这样搞,然后我也去搞了一波,但结果就不太好了。

这一步需要我们进入网址:https://myaccount.google.com/signinoptions/two-step-verification/enroll-welcome?utm_source=google-account&utm_medium=web,然后手动去获取一个授权码,并将密码设置为授权码的方式。

中间过程我就不再说了,当时配置的时候没有截图,这里默认有五种可以选,有windows、mac、Android、iPhone还有其它,这里选择其它直接确定,就能拿到授权码,然后把密码改完后感觉挺好的,但第二天就被封号了,可能我一次申请的有点多,也可能是其它各种原因,所以奉劝看到这里的朋友,别轻易尝试这种,如果上述两步没用,那么就可以考虑换邮箱了,下面是我的惨痛教训:

然后是申请复查,天地良心,我还没开始搞啥破坏呢。。。

中间还有 b"5.7.14b"5.7.4b"5.7.7,我记得其中分别是认证密码错误,stmp连接错误等,如果走完上面两步还出现这类问题,第一是看拼写有没有问题,如果和我上面写的QQ格式基本一致,端口是587或者465没用,那可以尝试重新走一遍上述步骤,可能中间哪里没有开起来,或者按第三步来,但我实验是被封了两天。

总结

后来还尝试了雅虎还有网易企业邮箱,我都不知道我为什么要试这么多种邮箱,因为最近一个项目是海外项目,老板搞了各种邮箱,但一直想换,那没办法咯,我就只能陪着他换。企业邮箱的话就是要做域名解析,如果是阿里云服务器的话,这里就不再说了,直接后台改就完事了。感觉这篇文章算一个科普性质的,科普我从错误里的经验,还有就是邮箱咋设置,我感觉现在啥邮箱都能搞一搞了。。。

python利用STMP发送gmail、QQ邮件错误及笔记总结相关推荐

  1. Python 发送邮件 和 发送带附件邮件

    摘要:      平时运行一些脚本,需要把结果发送到邮箱,可以用python来处理,如下: 1,有邮件服务器: #!/bin/env python # -*- encoding: utf-8 -*- ...

  2. Python利用SMTP/IMTP制作简单邮件(QQ邮箱)发送程序(保姆级)

    先看效果图和代码 效果图 import smtplib from email.mime.text import MIMEText # 邮件正文 from email.header import Hea ...

  3. 利用Jmail发送和接收邮件

    private void Button1_Click(object sender, System.EventArgs e)             {                 SendMail ...

  4. smtplib 抄送邮件_python 2.7 利用smtplib发送、抄送邮件以及发送html表格

    开发语言: python2.7 包:smtplib 导入包:import smtplib 定义一个函数:def send_mail(to_list, cc_list, html, sub): me = ...

  5. html发送qq邮件消息,Python3实现发送QQ邮件功能(html)_python

    这篇文章主要为大家详细介绍了Python3实现发送QQ邮件功能,html格式的qq邮件,具有一定的参考价值,对Python3感兴趣的小伙伴们可以参考一下本文,本文为大家分享了Python3实现发送QQ ...

  6. oracle 发的邮件qq,python基于SMTP发送QQ邮件

    python基于SMTP发送QQ邮件,供大家参考,具体内容如下 第一步: 1.打开qq邮箱,开启smtp服务 2.验证密保 3.获取授权码 python代码里面使用 在Python中, smtplib ...

  7. 使用Python登录QQ邮箱发送QQ邮件

    这真是黑科技啊,原来推送的广告邮件就是这样产生的.好人用来发节日贺卡,给女朋友纪念邮件:坏人会学着发广告,垃圾邮件.我希望大家能学会了做些有趣的有意义的事情. 今天我带大家实现下简单的发邮件功能.我们 ...

  8. python发送qq邮件_python使用SMTP发送qq或sina邮件

    python使用qq邮箱(个人邮箱)发送邮件需开启qq邮箱的SMTP服务 在设置中开启pop3/SMTP服务,返回的密码就是之后代码中登录使用账户密码(在完整代码中标识了出来) 之后出现如下错误 复制 ...

  9. python发送qq邮件(加密非加密)

    python发送qq邮件,加密发送,非加密发送 设置qq邮箱 设置开启客户端功能 设置--->账户 开启POP3/SMTP服务 根据提示开启 授权码 开启成功 查看qq邮件服务器信息1 查看qq ...

最新文章

  1. ASP.NET Core Web Razor Pages系列教程六:添加搜索功能
  2. 【BZOJ5469】[FJOI2018]领导集团问题(动态规划,线段树合并)
  3. linux的系统移植——内核启动
  4. 详解 URLLC 前世今生,你 Get 了吗?
  5. vmware-linux虚拟机上网配置
  6. Java中的List、Set、Map
  7. -pie can only be used when targeting iOS 4.2 or later
  8. mysql5.6.10开启二进制日志_mysql二进制日志的开启和使用
  9. 32位汇编语言helloworld_编程语言发展70年,50种不同语言输出Hello World,你知多少?...
  10. web平台安全测试方案
  11. (一)hadoop 权威指南---气象数据获取
  12. Cocosbuilder使用教程
  13. 体重增长:目前为止我们所知道的一切器
  14. 为什么Android项目mainactivity中有一个变量R_教我兄弟学Android逆向12 编写xpose模块...
  15. python爬取网站突破_python最强的代理池,突破IP的封锁爬取海量数据
  16. 用学习和发展在职场中站稳脚跟
  17. 神经网络占用内存(显存)的计算
  18. 网络运维工程师 ,需要掌握知识的总结。
  19. VS2019 KEY
  20. 32位系统无法运行64位系统安装文件

热门文章

  1. 自来水厂自动化控制系统
  2. 混沌分形之谢尔宾斯基(Sierpinski)
  3. ubutnu 安装broadcom 驱动
  4. android添加横幅广告,Android关于横幅banner广告的实现
  5. 多路由器组局域网设置要点
  6. 2015-03-29-绘图和可视化(3)-绘制地图:图形化显示海地地震危机数据
  7. 找歌软件测试自学,为用户而改变 酷我音乐2012For Android版本重构软件测试
  8. .Net MVC 图片合成、证书生成
  9. QT帮助文档搜索不到任何东西
  10. win10 前面板 耳机