Python学习之旅(三十五)

Posted finsom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python学习之旅(三十五)相关的知识,希望对你有一定的参考价值。

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

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

在使用Python收发邮件前,请先准备好至少两个电子邮件,如[email protected][email protected][email protected]等,注意两个邮箱不要用同一家邮件服务商

电子邮件发送过程:

发件人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:[email protected].com
Password:1234
To: [email protected]
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?= <[email protected]>
To: [email protected]
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)

 

以上是关于Python学习之旅(三十五)的主要内容,如果未能解决你的问题,请参考以下文章

Android探索之旅(第三十五篇)Kotlin知识整集

Android探索之旅(第三十五篇)Kotlin知识整集

Python学习之旅(三十)

Python学习之旅(三十一)

Python学习笔记(三十五)struct

Python学习之旅(三十四)