zoukankan      html  css  js  c++  java
  • Python学习之旅(三十五)

    Python基础知识(34):电子邮件(Ⅰ)

    几乎所有的编程语言都支持发送和接收电子邮件

    在使用Python收发邮件前,请先准备好至少两个电子邮件,如xxx@163.comxxx@sina.comxxx@qq.com等,注意两个邮箱不要用同一家邮件服务商

    电子邮件发送过程:

    发件人email->MUA(mail user agent:邮件用户代理)->MTA(mail transfer agent:邮件传输代理)->MDA(mail delivery agent:邮件投递代理,即服务器)<-MUA<-收件人

    使用SMTP发送邮件

    SMTP是发送邮件的协议,Python内置对SMTP的支持,可以发送纯文本邮件、HTML邮件以及带附件的邮件

    Python对SMTP支持有smtplibemail两个模块,email负责构造邮件,smtplib负责发送邮件

    注:以下所有代码本人未进行测试,故无法确定是否能够正常运行

    一、发送邮件

    1、构造邮件

    from email.mime.text import MIMEText
    
    msg = MIMEText('Hello, world', 'plain', 'utf-8')

    到构造MIMEText对象时,第一个参数就是邮件正文,第二个参数是MIME的subtype,传入'plain'表示纯文本,最终的MIME就是'text/plain',最后一定要用utf-8编码保证多语言兼容性

    2、通过SMTP发送邮件

    SMTP.sendmail(from_addr, [to_addr], msg.as_string())

    sendmail()方法就是发邮件,由于可以一次发给多个人,所以传入一个list,邮件正文是一个stras_string()MIMEText对象变成str

    必须把FromToSubject添加到MIMEText中,才是一封完整的邮件

    from email import encoders
    from email.header import Header
    from email.mime.text import MIMEText
    from email.utils import parseaddr, formataddr
    
    import smtplib
    
    
    # 考虑到编码的原因,这里统一将name属性值改成utf-8,地址的话一定是统一的邮箱地址结构,所以不考虑
    def __format_addr(s):
        name, addr = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), addr))
    
    # 一些基本信息的定义
    from_addr = input('From:')
    password = input('Password:')
    to_addr = input('To: ')
    smtp_server = input('SMTP server: ')
    
    # 纯文本邮件定义
    msg = MIMEText('Hello world!', 'plain', 'utf-8')
    # 定义发送人,接收人,以及描述信息(主题)
    msg['From'] = __format_addr('发件人 <%s>' % from_addr)
    msg['To'] = __format_addr('收件人: <%s>' % to_addr)
    msg['Subject'] = Header('SMTP......', 'utf-8').encode()
    
    print(msg)

    结果如下

    From:xxx@163.com
    Password:1234
    To: xxxxx@qq.com
    SMTP server: smtp.163.com
    Content-Type: text/plain; charset="utf-8"
    MIME-Version: 1.0
    Content-Transfer-Encoding: base64
    From: =?utf-8?b?5Y+R5Lu25Lq6?= <xxx@163.com>
    To: xxxxx@qq.com
    Subject: =?utf-8?b?U01UUC4uLi4uLg==?=
    
    SGVsbG8gd29ybGQh

    二、发送HTML邮件

    在构造MIMEText对象时,把HTML字符串传进去,再把第二个参数由plain变为html

    msg = MIMEText('<html><body><h1>Hello</h1>' +
        '<p>send by <a href="http://www.python.org">Python</a>...</p>' +
        '</body></html>', 'html', 'utf-8')

    三、发送附件

    带附件的邮件可以看做包含若干部分的邮件:文本和各个附件本身,所以,可以构造一个MIMEMultipart对象代表邮件本身,然后往里面加上一个MIMEText作为邮件正文,再继续往里面加上表示附件的MIMEBase对象即可

    # 邮件对象:
    msg = MIMEMultipart()
    msg['From'] = _format_addr('Python爱好者 <%s>' % from_addr)
    msg['To'] = _format_addr('管理员 <%s>' % to_addr)
    msg['Subject'] = Header('来自SMTP的问候……', 'utf-8').encode()
    
    # 邮件正文是MIMEText:
    msg.attach(MIMEText('send with file...', 'plain', 'utf-8'))
    
    # 添加附件就是加上一个MIMEBase,从本地读取一个图片:
    with open('/Users/michael/Downloads/test.png', 'rb') as f:
        # 设置附件的MIME和文件名,这里是png类型:
        mime = MIMEBase('image', 'png', filename='test.png')
        # 加上必要的头信息:
        mime.add_header('Content-Disposition', 'attachment', filename='test.png')
        mime.add_header('Content-ID', '<0>')
        mime.add_header('X-Attachment-Id', '0')
        # 把附件的内容读进来:
        mime.set_payload(f.read())
        # 用Base64编码:
        encoders.encode_base64(mime)
        # 添加到MIMEMultipart:
        msg.attach(mime)

    按正常发送流程把msg(注意类型已变为MIMEMultipart)发送出去 

    四、发送图片

    不能直接在HTML邮件中链接图片地址,因为大部分邮件服务商都会自动屏蔽带有外链的图片,因为不知道这些链接是否指向恶意网站

    要把图片嵌入到邮件正文中,只需按照发送附件的方式,先把邮件作为附件添加进去,然后,在HTML中通过引用src="cid:0"就可以把附件作为图片嵌入了。如果有多个图片,给它们依次编号,然后引用不同的cid:x即可

    把上面代码加入MIMEMultipartMIMETextplain改为html,然后在适当的位置引用图片

    msg.attach(MIMEText('<html><body><h1>Hello</h1>' +
        '<p><img src="cid:0"></p>' +
        '</body></html>', 'html', 'utf-8'))

    五、同时支持HTML和Plain格式

    如果收件人使用的设备太古老,查看不了HTML邮件,必须在发送HTML的同时再附加一个纯文本,如果收件人无法查看HTML格式的邮件,就可以自动降级查看纯文本邮件

    利用MIMEMultipart就可以组合一个HTML和Plain,要注意指定subtype是alternative 

    msg = MIMEMultipart('alternative')
    msg['From'] = ...
    msg['To'] = ...
    msg['Subject'] = ...
    
    msg.attach(MIMEText('hello', 'plain', 'utf-8'))
    msg.attach(MIMEText('<html><body><h1>Hello</h1></body></html>', 'html', 'utf-8'))
    # 正常发送msg对象...

    六、加密SMTP

    想要更安全地发送邮件,防止发送的邮件被窃听,可以加密SMTP会话,实际上就是先创建SSL安全连接,然后再使用SMTP协议发送邮件

    只需要在创建SMTP对象后,立刻调用starttls()方法,就创建了安全连接

    smtp_server = 'smtp.gmail.com'
    smtp_port = 587
    server = smtplib.SMTP(smtp_server, smtp_port)
    server.starttls()
    # 剩下的代码和前面的一模一样:
    server.set_debuglevel(1)
  • 相关阅读:
    js属性对象的hasOwnProperty方法
    利用递归的方式在JSON 数据中找到某个节点的多有父节点
    数组中的方法 --- 不改变原数组的方法
    数组中的方法-- 会改变原数组的
    break continue return 的区别
    解决vue中对象属性改变视图不更新的问题
    怎么实现无痛刷新token
    正则的使用记录
    一级域名的登录信息在二级域名中获取
    没有什么问题是不能通过增加一个抽象层解决的
  • 原文地址:https://www.cnblogs.com/finsomway/p/10126024.html
Copyright © 2011-2022 走看看