Python 邮件模块

python的邮件模块对于周期性邮件发送(如日报、周报)是非常高效的,搭配time库还能实现定时发送,搭配pandas、matplotlib可实现数据分析、可视化和报表发送的全流程自动化,对于工作效率提升有极高价值,本文简要介绍邮件模块的基本实现。

一、详细步骤

1.前提

  1. 设置邮箱的安全权限(设置为低)或者使用一个随机账号邮箱
  2. 设置gmail该页允许captcha,从而让python可以登录该gmail

2.载入库

smtplib(控制服务器通信)、mimetext(控制邮件的内容)、mimemultipart(控制邮件的样式和结构)

from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
import smtplib 

3. 库的使用

smtplib

  1. 建立连接
    server = smtplib.SMTP(host='smtp.163.com', port=25)
    创建一个SMTP连接实例

国内邮箱port一般为25

  1. 向ESMTP服务器标识身份(可选)
    SMTP.ehlo(name='')
    该方法可选,一般可在在send_mail方法中调用,name默认为本地主机名。

若是SMTP服务器则使用helo()方法

  1. 设置SMTP的联结模式,默认为TLS(Transport Layer Security)
    SMTP.starttls(keyfile=None, certfile=None, context=None)
    使用后,所有smtp命令都会被编码
  2. 登陆
    SMTP.login(user, password, *, initial_response_ok=True)
  3. 发送邮件
    SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())
    发送邮件,必须要有收件人和发件人地址,和一个信息字符串。from_addr放一个邮箱,to_addrs放一个邮箱列表。

如果没有明确定义EHLOHELO,则会优先使用ESMP测试服务器

  1. 终止进程并关闭连接
    SMTP.quit()

MIMEMultipart

class email.mime.multipart.MIMEMultipart(_subtype=‘mixed’, boundary=None, _subparts=None, *, policy=compat32, **_params)

  1. _subtype
    子类型,控制结构,一共三种可选,见下图,默认为mixed
    [image:F03CCC37-27D0-4243-B4B5-54225B6F4231-1376-0000A5E6CF0A5887/FBCC8C1A-E79A-44F4-86AA-B1CE0D6ABA26.png]
    msg = MIMEMultipart('alternative')
  2. _subparts
    控制初始化的内容,可以通过attach添加,如先用mimetext创建了对象,再添加到mimemultipart对象后
      if html != 'None':
        html_part = MIMEText(html, 'html')
        msg.attach(html_part)

对于html,需要一个完整的html模块来实现,可参考前端的html格式,同时可以借助pd中的to_html函数将任何类型的数据转换成html然后以html放入邮件中

  1. _params
    是关键字参数,可以通过字典赋值,如果没有设置,则在发件人和收件人的显示上仅显示邮箱和内容,没有主题和发件人收件人名称
   msg = MIMEMultipart('alternative')
    msg['To'] = ', '.join(to_email)
    msg['Subject'] = subject
    msg['From'] = from_email

其他关键字
[image:FCE83CEA-6538-4487-921C-2373B2521D15-1376-0000A70D9B96B2D4/715A658B-00BC-4D1B-A352-54AC2EBD56D2.png]

MIMEText

class email.mime.text.MIMEText(_text, _subtype=‘plain’, _charset=None, *, policy=compat32)
_text即变量名,_subtype为子类型,可以是html、plain等

MIMEApplication

class email.mime.application.MIMEApplication(_data, _subtype=‘octet-stream’, _encoder=email.encoders.encode_base64, *, policy=compat32, **_params)
此处_data是 attachment.read()
如果要更换可以使用set_payload更换内容

MIMEBase(基类)

实现附件添加
class email.mime.base.MIMEBase(_maintype, _subtype, *, policy=compat32, **_params)

  1. _maintype
    主类型(内容),例如是文本还是图像
    [image:80F4AF5B-C960-405F-86EB-A1A03D6AF884-1376-0000AC0074BDF04C/7073B2C3-D0C8-4E1C-865D-1AEC6F2EDAE9.png]
    [image:1F93C5C6-4C7A-4713-870E-69FC02257BDE-1376-0000BC7E806EFCCF/39E37A0C-FE13-4D0B-A78F-1B6636DA4928.png]
    其中application是指主类型,x-zip-compressed是其一个子类型
    可写作:
    part = MIMEBase(‘application’, ‘x-zip-compressed’)——即zip文件类型

常见主类型、子类型
[image:682DEEFD-B943-4688-894C-52541E3B618D-1376-0000AC3BD9B3F004/A52C6262-EB06-43BD-AA96-226F89BBD7A5.png]

  1. _subtype
    子类型,例如文本的格式是plain,图像的格式是gif
  2. _params
    关键字参数,键值字典,可以通过add_header添加
    part.add_header('Content-Dispostition', 'attachment; file_name =%s%'file_name)
    添加一个附件
    file_name = os.path.basename(file_location)
    attachment = open(file_location, 'rb') # 创建对象
    part = MIMEBase('application', 'octet-stream')
    part.set_payload((attachment).read()) # 添加有效载重
    encoders.encode_base64(part)
    part.add_header('Content-Dispostition', 'attachment; file_name =%s%'file_name)
    msg.attach(part)

二、总结

  1. 文件路径导入os读取文件名→
  2. 读取文件路径并将读取文件内容存储到变量中→
  3. 创建一个MIMEBase对象(设置参数)→
  4. m对象加载刚刚存储的文件变量→
  5. 给m对象添加参数告诉它要把文件以何名放在何处→
  6. 将m对象添加到multipart对象中去

对于不同的文件一定要选择不同的主类型和子类型,否则传输过程中会出错导致最终结果有误;另外如果要添加附件,参数一定要换成mixed

附:源码

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
import os.path

username = 'finnli1991@163.com'
password = 'UTRKSWKDNSHJGSFO'


def send_mail(
        text='Email Body', subject='Hello world',
        from_email='Finn li <finnli1991@163.com>',
        to_email=None, html=None, file_location=None):
    assert isinstance(to_email, list)
    msg = MIMEMultipart('alternative')
    msg['To'] = ', '.join(to_email)
    msg['Subject'] = subject
    msg['From'] = from_email
    txt_part = MIMEText(text, 'plain')
    msg.attach(txt_part)
    if html != 'None':
        html_part = MIMEText(html, 'html')
        msg.attach(html_part)
    msg_str = msg.as_string()

    file_name = os.path.basename(file_location)
    attachment = open(file_location, 'rb')
    # 创建对象
    part = MIMEBase('application', 'octet-stream')
    # 添加有效载重
    part.set_payload((attachment).read())
    encoders.encode_base64(part)
    part.add_header('Content-Dispostition', 'attachment; file_name =%s%'file_name)
    msg.attach(part)

    # 登录smtp服务器
    server = smtplib.SMTP(host='smtp.163.com', port=25)
    server.ehlo()
    server.starttls()
    server.login(username, password)
    server.sendmail(from_email, to_email, msg_str)
    server.quit()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。