Python 发送邮件各种姿势

Python 发送邮件各种姿势,第1张

概述电子邮件是互联网应用最广的通讯服务,在工作中经常会有自动发邮件的需求,例如监控告警、注册通知、激活链接等。而发送邮件是基于SMTP协议,接收邮件则是基于POP3或IMAP协议。那POP3与IMAP协议又有什么区别呢?最主要的区别是POP3在客户端邮箱中所做的 *** 作不会反馈到邮箱服务器,比如删

电子邮件是互联网应用最广的通讯服务,在工作中经常会有自动发邮件的需求,例如监控告警、注册通知、激活链接等。

而发送邮件是基于SMTP协议,接收邮件则是基于POP3或IMAP协议。

那POP3与IMAP协议又有什么区别呢?

最主要的区别是POP3在客户端邮箱中所做的 *** 作不会反馈到邮箱服务器,比如删除一封邮件,邮箱服务器并不会删除。IMAP则会反馈到邮箱服务器,会做相应的 *** 作。

Python对邮件服务完整的支持,分别提供相应的标准库:smtplib、poplib和imaplib。

顾名思义,其中smtplib库是用于发送邮件的,该库主要用smtplib.SMTP()类,它用于连接SMTP服务器和发送邮件。

这个类有几个常用的方法:


先看看官方示例:

>>> import smtplib>>> s=smtplib.SMTP("localhost")>>> toList=["one@one.org","two@two.org","three@three.org","four@four.org"]>>> msg = '''\... From: Me@my.org... Subject: testin'......... This is a test '''>>> s.sendmail("me@my.org",toList,msg){ "three@three.org" : ( 550 ,"User unkNown" ) }>>> s.quit()

接下来,给你分享 5 种最常用的发送邮件方式。

1、Python发送文本邮件

为方便测试,先在本机安装一个邮件服务,比如sendmail、postfix等。这里使用sendmail,如果你是CentOS系统直接安装启动即可:

# yum install sendmail# service sendmail start

按照官方示例在Python解释器执行:

>>> import smtplib>>> s = smtplib.SMTP("localhost")>>> toList = ["xxx@qq.com", "xxx@163.com"]>>> msg = '''\... From: Me@my.org... Subject: test... This is a test '''>>> s.sendmail("me@my.org", toList, msg){}

进入腾讯和网易收件人邮箱,就能看到刚发的测试邮件了,如果没有,请到垃圾邮箱看看。

可以看到,多个收件人可以放到一个列表中进行群发。msg对象里From表示发件人,Subject是邮件标题,换行后输入的是邮件内容。

使用自建邮箱服务器经常会出现被当做垃圾邮件、发件延迟,为解决这两个问题,一般使用知名邮件运营商。

例如使用163个人邮件作为发件人:

>>> import smtplib>>> s = smtplib.SMTP("smtp.163.com")>>> s.login("xxx@163.com", "xxx")(235, 'Authentication successful')>>> toList = ["xxx@qq.com", "xxx@163.com"]>>> msg = '''\... From: xxx@163.com... Subject: test... This is a test '''>>> s.sendmail("xxx@163.com", toList, msg)Traceback (most recent call last):  file "<stdin>", line 1, in <module>  file "/usr/lib64/python2.6/smtplib.py", line 725, in sendmail    raise SMTPDataError(code, resp)smtplib.SMTPDataError: (554, 'DT:SPM 163 smtp10,DsCowAAXIDDIJAtYkZiTAA--.65425S2 1477125592,please see http://mail.163.com/help/help_spam_16.htm?ip=119.57.73.67&hostID=smtp10&time=1477125592')

访问给出的163网址,SMTP554错误是:”554 DT:SUM 信封发件人和信头发件人不匹配;”

大概已经明白啥意思,看上面再使用本地SMTP服务器时候,收件人位置是“undisclosed-recipIEnts”,看这样163的SMTP服务器不给我们服务的原因就是这里收件人没指定。
重新修改下msg对象,添加上收件人:

>>> msg = '''\... From: xxx@163.com... To: xxx@qq.com ,xxx@163.com... Subject: test...... This is a test '''>>> s.sendmail("xxx@163.com", toList, msg){}

这样就可以正常发送邮件了。msg这个格式是SMTP规定的,一定要遵守。

2、发送邮件并抄送
#!/usr/bin/python# -*- Coding: utf-8 -*-import smtplibdef sendMail(body):    smtp_server = 'smtp.163.com'    from_mail = 'xxx@163.com'    mail_pass = 'xxx'    to_mail = ['xxx@qq.com', 'xxx@163.com']    cc_mail = ['xxx@gmail.com']    from_name = 'monitor'    subject = u'监控'.encode('gbk')   # 以gbk编码发送,一般邮件客户端都能识别#     msg = '''\# From: %s <%s># To: %s# Subject: %s# %s''' %(from_name, from_mail, to_mail_str, subject, body)  # 这种方式必须将邮件头信息靠左,也就是每行开头不能用空格,否则报SMTP 554    mail = [        "From: %s <%s>" % (from_name, from_mail),        "To: %s" % ','.join(to_mail),   # 转成字符串,以逗号分隔元素        "Subject: %s" % subject,        "Cc: %s" % ','.join(cc_mail),        "",        body        ]    msg = '\n'.join(mail)  # 这种方式先将头信息放到列表中,然后用join拼接,并以换行符分隔元素,结果就是和上面注释一样了    try:        s = smtplib.SMTP()        s.connect(smtp_server, '25')        s.login(from_mail, mail_pass)        s.sendmail(from_mail, to_mail+cc_mail, msg)        s.quit()    except smtplib.SMTPException as e:        print "Error: %s" %eif __name__ == "__main__":    sendMail("This is a test!")

s.sendmail(from_mail,to_mail+cc_mail, msg) 在这里注意下,收件人和抄送人为什么放一起发送呢?其实无论是收件人还是抄送人,它们收到的邮件都是一样的,SMTP都是认为收件人这样一封一封的发出。所以实际上并没有抄送这个概念,只是在邮件头加了抄送人的信息罢了!

另外,如果不需要抄送人,直接把上面cc的信息去掉即可。

3、Python发送邮件带附件

由于SMTP.sendmail()方法不支持添加附件,所以可以使用email模块来满足需求。email模块是一个构造邮件和解析邮件的模块。
先看下如何用email库构造一个简单的邮件:

message = Message()message['Subject'] = '邮件主题'message['From'] = from_mailmessage['To'] = to_mailmessage['Cc'] = cc_mailmessage.set_payload('邮件内容')

基本的格式就是这样的。

继续回到主题,发送邮件带附件:

#!/usr/bin/python# -*- Coding: utf-8 -*-import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.header import headerfrom email import encodersfrom email.mime.base import MIMEBasefrom email.utils import parseaddr, formataddr# 格式化邮件地址def formatAddr(s):    name, addr = parseaddr(s)    return formataddr((header(name, 'utf-8').encode(), addr))def sendMail(body, attachment):    smtp_server = 'smtp.163.com'    from_mail = 'xxx@163.com'    mail_pass = 'xxx'    to_mail = ['xxx@qq.com', 'xxx@163.com']    # 构造一个MIMEMultipart对象代表邮件本身    msg = MIMEMultipart()    # header对中文进行转码    msg['From'] = formatAddr('管理员 <%s>' % from_mail).encode()    msg['To'] = ','.join(to_mail)    msg['Subject'] = header('监控', 'utf-8').encode()    # plain代表纯文本    msg.attach(MIMEText(body, 'plain', 'utf-8'))    # 二进制方式模式文件    with open(attachment, 'rb') as f:        # MIMEBase表示附件的对象        mime = MIMEBase('text', 'txt', filename=attachment)        # filename是显示附件名字        mime.add_header('Content-disposition', 'attachment', filename=attachment)        # 获取附件内容        mime.set_payload(f.read())        encoders.encode_base64(mime)        # 作为附件添加到邮件        msg.attach(mime)    try:        s = smtplib.SMTP()        s.connect(smtp_server, "25")        s.login(from_mail, mail_pass)        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string()把MIMEText对象变成str        s.quit()    except smtplib.SMTPException as e:        print "Error: %s" % eif __name__ == "__main__":    sendMail('附件是测试数据, 请查收!', 'test.txt')

4、Python发送HTML邮件
#!/usr/bin/python# -*- Coding: utf-8 -*-import smtplibfrom email.mime.text import MIMETextfrom email.mime.multipart import MIMEMultipartfrom email.header import headerfrom email.utils import parseaddr, formataddr# 格式化邮件地址def formatAddr(s):    name, addr = parseaddr(s)    return formataddr((header(name, 'utf-8').encode(), addr))def sendMail(body):    smtp_server = 'smtp.163.com'    from_mail = 'baojingtongzhi@163.com'    mail_pass = 'xxx'    to_mail = ['xxx@qq.com', 'xxx@163.com']    # 构造一个MIMEMultipart对象代表邮件本身    msg = MIMEMultipart()    # header对中文进行转码    msg['From'] = formatAddr('管理员 <%s>' % from_mail).encode()    msg['To'] = ','.join(to_mail)    msg['Subject'] = header('监控', 'utf-8').encode()    msg.attach(MIMEText(body, 'HTML', 'utf-8'))    try:        s = smtplib.SMTP()        s.connect(smtp_server, "25")        s.login(from_mail, mail_pass)        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string()把MIMEText对象变成str        s.quit()    except smtplib.SMTPException as e:        print "Error: %s" % eif __name__ == "__main__":    body = """    <h1>测试邮件</h1>    <h2 >This is a test</h1>    """    sendMail(body)

5、Python发送图片邮件
#!/usr/bin/python# -*- Coding: utf-8 -*-import smtplibfrom email.mime.text import MIMETextfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipartfrom email.header import headerfrom email.utils import parseaddr, formataddr# 格式化邮件地址def formatAddr(s):    name, addr = parseaddr(s)    return formataddr((header(name, 'utf-8').encode(), addr))def sendMail(body, image):    smtp_server = 'smtp.163.com'    from_mail = 'xxx@163.com'    mail_pass = 'xxx'    to_mail = ['xxx@qq.com', 'xxx@163.com']    # 构造一个MIMEMultipart对象代表邮件本身    msg = MIMEMultipart()    # header对中文进行转码    msg['From'] = formatAddr('管理员 <%s>' % from_mail).encode()    msg['To'] = ','.join(to_mail)    msg['Subject'] = header('监控', 'utf-8').encode()    msg.attach(MIMEText(body, 'HTML', 'utf-8'))    # 二进制模式读取图片    with open(image, 'rb') as f:        msgimage = MIMEImage(f.read())    # 定义图片ID    msgimage.add_header('Content-ID', '<image1>')    msg.attach(msgimage)    try:        s = smtplib.SMTP()        s.connect(smtp_server, "25")        s.login(from_mail, mail_pass)        s.sendmail(from_mail, to_mail, msg.as_string())  # as_string()把MIMEText对象变成str        s.quit()    except smtplib.SMTPException as e:        print "Error: %s" % eif __name__ == "__main__":    body = """    <h1>测试图片</h1>    <img src="cID:image1"/>    # 引用图片    """    sendMail(body, 'test.png')

END - 总结

以上是内存溢出为你收集整理的Python 发送邮件各种姿势全部内容,希望文章能够帮你解决Python 发送邮件各种姿势所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1188713.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存