博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python学习笔记 - 发送邮件
阅读量:5941 次
发布时间:2019-06-19

本文共 6287 字,大约阅读时间需要 20 分钟。

电子邮件的传输协议是SMTP,Python内置了对SMTP协议的支持,对应的模块是smtplib和email模块。

  • smtplib

    smtplib模块负责在发送邮件的过程中和服务器通信,简单来说就是:

    • 连接服务器
    • 登录邮箱
    • 发送邮件
    • 退出服务器
  • email

    email模块负责和服务器通信的信息,比如邮件内容,附件,收件人,发件人,主题等等。

也就是说smtplib模块负责发邮件,email模块负责写邮件

发送一份邮件的步骤:

用qq邮箱举例:

  1. 第一步要做的就是连接服务器。这里用到的是smtplib模块的SMTP方法:

    • host,SMTP 服务器主机地址
    • port,端口号,默认端口是25

    需要传入上面两个参数,因为不知道所以查一下:

    在qq邮箱的帮助中心找到了。

    但是还没完,因为邮件是私密的信息,不可能用明文传输,所以一般都会加密,所以还要找一下qq邮箱的加密标准。

    同样的在qq邮箱帮助中心找到,是SSL方式加密的。

    smtp模块的不同的加密写法如下:

    import smtplib# 端口是用TLS加密smtplib_obj = smtplib.SMTP('服务器地址',端口)# 端口是用SSL加密smtplib_obj = smtplib.SMTP_SSL('服务器地址',端口)复制代码

    好了,现在就写代码,连接服务器:

    import smtplibqq_mail = smtplib.SMTP_SSL('smtp.qq.com', 465)复制代码
  2. 然后写用户名密码登录邮箱:

    from_address = input('请输入邮箱账号:')password = input('请输入邮箱密码:')qq_mail.login(from_address, password)复制代码

    登录是用login方法

  3. 写邮件,这里先不用email模块去构造,先直接写一个看看

    to_address = input('请输入收件人地址:')message = input('请输入邮件内容:')复制代码

    获取收件人地址和邮件内容

  4. 发送邮件

    qq_mail.sendmail(from_address, [to_address], message)复制代码

    sendmail方法用来发送邮件,它的参数是:

    • from_addr: 邮件发送者地址。
    • to_addrs: 字符串列表,邮件发送地址。
    • msg: 发送消息
  5. 退出服务器

    qq_mail.quit()复制代码
  6. 运行

    这里还有一个小坑,如果你的文件名叫email.py的话,它会报这个错

    AttributeError: module 'smtplib' has no attribute 'SMTP_SSL'复制代码

    具体原因看这里,解决办法就是不要用email这个文件名

    如果按照上面的例子一步一步写,那么会出现这个错误:

    smtplib.SMTPAuthenticationError

    这是因为你的邮箱没有开启SMTP服务。现在去开启: 在【设置】- 【账户设置】往下拉会看到这个:

    开启它

    然后你会得到一个16位的授权码,你用smtplib登录邮箱的密码就是这个,不再是邮箱原本的密码。

    用户就会收到一封这样的邮件,没有发件人没有主题,连我们输入的邮件内容都没有

  7. 使用email模块添加主题等信息

    • 使用MIMEText构造邮件内容。

      email.mime.text.MIMEText(_text[, _subtype[, _charset]])

      MIMEText 类用于创建主要类型 text 的MIME对象。

      • _text: 文本内容
      • _subtype:指定文本类型,支持 plain(默认值)或 html类型的字符串。
      • _charset:用于指定文本内容的编码表
      from email.mime.text import MIMETextmsg = MIMEText('你好,这是用python发送的邮件', 'plain', 'utf-8')复制代码
    • 使用Header添加邮件的收件人,发件人,主题

      email.header.Header(s=None, charset=None, maxlinelen=None, header_name=None, continuation_ws=' ', errors='strict')

      创建一个MIME兼容的头,可以包含不同字符集中的字符串。

      常用的参数是s和charset(其他参数还没搞清楚 +_+)

      • s:初始标头值
      • charset:charset指定编码表
      from email.header import Headermsg['From'] = Header("发件人",'utf-8')msg['To'] = Header("收件人",'utf-8')msg['Subject'] = Header('主题', 'utf-8')复制代码
    • 使用 parseaddr, formataddr格式化邮件头部信息。

      • email.utils.parseaddr(address)

        email.utils.parseaddr接受包含了邮件地址的字符串,然后返回一个解析后的元组。例子:

        print(parseaddr('name
        '))# ('name', 'email_address@qq.com')复制代码
      • email.utils.formataddr(pair, charset='utf-8')

        formataddr是parseaddr方法的逆,接受包含收件人昵称和邮箱账号的元组或列表,返回一个字符串,例子:

        print(formataddr(('name', 'email_address@qq.com'), 'utf-8'))# name 
        复制代码
    • 发送

      qq_mail.sendmail(from_address, [to_address], msg.as_string())复制代码

      as_string是MIME实例对象的方法,将整个消息作为字符串返回。

    我在看廖雪峰大神的Python教程的时候,发现他的收件人信息等等都进行了编码处理,教程上说如果有中文的话需要通过Header对象进行编码,我自己写的时候没有编码,直接用的中文也是成功了,所以我也不确定需不需要加这个处理。这里还是加上吧,可能不加会有一些我没遇到的坑,最终用email模块构造邮件的代码是:

    import smtplibfrom email.header import Headerfrom email.mime.text import MIMETextfrom email.utils import parseaddr, formataddrdef format_addr(str):    name, address = parseaddr(str)    return formataddr([Header(name, 'utf-8').encode(), address])try:    qq_mail = smtplib.SMTP_SSL('smtp.qq.com', 465)    from_address = input('请输入邮箱账号:')    password = input('请输入邮箱密码:')    qq_mail.login(from_address, password)    to_address = input('请输入收件人地址:')    message = input('请输入邮件内容:')    msg = MIMEText(message, 'plain', 'utf-8')    msg['From'] = format_addr('神秘人 <%s>' % from_address)    msg['To'] = format_addr('另一个神秘人 <%s>' % to_address)    msg['Subject'] = Header('今天吃了吗?', 'utf-8').encode()    qq_mail.sendmail(from_address, [to_address], msg.as_string())    print('发送成功')    qq_mail.quit()except smtplib.SMTPException as e:    print('邮件发送失败,原因:%s' % e)复制代码

    结果

    但是收件人的名字并不是代码里写的,而是qq的昵称,可能腾讯对这个做了什么限制吧。

    一般的文本内容发送就是以上这些了,下面看一下发送附件怎么发送。

  • 发送html邮件

    发送html的邮件很简单,只需要将MIMEText方法中的plain改为html,然后text参数传入html字符串。例子:

    message = '''                    
    test

    google

    点我 '''msg = MIMEText(message, 'html', 'utf-8')复制代码

  • 发送图片

    图片可以作为邮件本身的内容,也可以作为附件发送。先看作为附件怎么发送:

    from email.mime.base import MIMEBasefrom email.mime.multipart import MIMEMultipart  # 带多个部分的邮件,比如既有图片又有文本from email.mime.text import MIMEText  # html格式和文本格式的对象from email.mime.image import MIMEImage  # 附件为图片格式的对象from email.mime.audio import MIMEAudio  # 附件为音频格式的对象from email import encoders  # 编码器复制代码

    把图片作为附件发送

    # 因为既有文本又有图片附件,所以用MIMEMultipart创建实例msg = MIMEMultipart()# attach方法相当于给msg对象,添加不同的部分msg.attach(MIMEText('发个图片', 'plain', 'utf-8'))# 从本地读取一个图片添加为附件:with open('./test.jpeg', 'rb') as f:    mes_image = MIMEImage(f.read())    # 给图片一个id,如果图片放入html中,那么就要用到它    mes_image.add_header('Content-ID', 'img_0')    # 给附件一个名字    mes_image.add_header('Content-Disposition', 'attachment', filename='test.jpeg')    # 添加到MIMEMultipart    msg.attach(mes_image)复制代码

    结果:

    完整代码:

    import smtplibfrom email.header import Headerfrom email.mime.text import MIMETextfrom email.utils import parseaddr, formataddrfrom email.mime.multipart import MIMEMultipartfrom email.mime.image import MIMEImagedef format_addr(str):    name, address = parseaddr(str)    return formataddr([Header(name, 'utf-8').encode(), address])try:    qq_mail = smtplib.SMTP_SSL('smtp.qq.com', 465)    from_address = input('请输入邮箱账号:')    password = input('请输入邮箱密码:')    qq_mail.login(from_address, password)    to_address = input('请输入收件人地址:')    # 因为既有文本又有图片附件,所以用MIMEMultipart创建实例    msg = MIMEMultipart()    # attach方法相当于给msg对象,添加不同的部分    msg.attach(MIMEText('发个图片', 'plain', 'utf-8'))    # 从本地读取一个图片添加为附件:    with open('./test.jpeg', 'rb') as f:        mes_image = MIMEImage(f.read())        # 给图片一个id,如果图片放入html中,那么就要用到它        mes_image.add_header('Content-ID', 'img_0')        # 给附件一个名字        mes_image.add_header('Content-Disposition', 'attachment', filename='test.jpeg')        # 添加到MIMEMultipart        msg.attach(mes_image)    msg['From'] = format_addr('神秘人 <%s>' % from_address)    msg['To'] = format_addr('另一个神秘人 <%s>' % to_address)    msg['Subject'] = Header('今天吃了吗?', 'utf-8').encode()    qq_mail.sendmail(from_address, [to_address], msg.as_string())    print('发送成功')    qq_mail.quit()except smtplib.SMTPException as e:    print('邮件发送失败,原因:%s' % e)复制代码

    作为邮件内容发送,作为邮件内容发送,需要使用html格式的内容,然后将图片的id写在img标签的src属性里就可以了:

    msg.attach(MIMEText('''                    
    Document

    发个图片

    ''', 'html', 'utf-8'))复制代码

转载于:https://juejin.im/post/5c25c8e76fb9a049fe3537b9

你可能感兴趣的文章
我的友情链接
查看>>
我的友情链接
查看>>
wdcp 安装
查看>>
C语言运算符优先级相关问题
查看>>
MP4视频播放器代码
查看>>
Nginx 匹配 iphone Android 微信
查看>>
ldap
查看>>
Yum软件仓库配置
查看>>
linux 压缩与解压总结
查看>>
mysql脚本1064 - You have an error in your SQL syntax; check the manual
查看>>
nessus 本地扫描(一)
查看>>
linux服务器磁盘陈列
查看>>
python----tcp/ip http
查看>>
我的友情链接
查看>>
第一本docker书学习笔记1-3章
查看>>
一個典型僵尸網絡淺析
查看>>
vmware克隆Centos6.4虚拟机网卡无法启动问题
查看>>
dba学习
查看>>
asterisk配置
查看>>
GA操作步骤和技巧(二)——用户行为分析
查看>>