Python中发送邮件可通过stmplib模块来发送,但如果要发送附件等信息需其他模块辅助,如可采用email模块发送电子邮件附件。发送一个未知MIME类型的文件附件其基本思路如下:
1. 构造MIMEMultipart对象做为根容器
2、设置根容器属性 (即设置邮件的头部信息,title,from,to)。
3. 构造MIMEText对象做为邮件显示内容并附加到根容器 (注意有两种形式的邮件正文:普通明文邮件和html形式邮件)
4. 构造MIMEBase对象做为文件附件内容并附加到根容器
a. 读入文件内容并格式化
b. 设置附件头
5. 得到格式化后的完整文本
6. 用smtp发送邮件
具体内容参见<programing python(3rd)> 14章第6节 “email: Parsing and Composing Mails”。发送一个未知MIME类型的文件附件实例代码如下:
import smtplib import email.MIMEMultipart import email.MIMEText import email.MIMEBase import os.path From = "sender address" To = "recipients" file_name = "file name" server = smtplib.SMTP("smtp server address") server.login("username","password") #仅smtp服务器需要验证时 # 构造MIMEMultipart对象做为根容器 main_msg = email.MIMEMultipart.MIMEMultipart() # 构造MIMEText对象做为邮件显示内容并附加到根容器 text_msg = email.MIMEText.MIMEText("this is a test text to text mime") main_msg.attach(text_msg) # 构造MIMEBase对象做为文件附件内容并附加到根容器 contype = 'application/octet-stream' maintype, subtype = contype.split('/', 1) ## 读入文件内容并格式化 data = open(file_name, 'rb') file_msg = email.MIMEBase.MIMEBase(maintype, subtype) file_msg.set_payload(data.read( )) data.close( ) email.Encoders.encode_base64(file_msg) ## 设置附件头 basename = os.path.basename(file_name) file_msg.add_header('Content-Disposition', 'attachment', filename = basename) main_msg.attach(file_msg) # 设置根容器属性 main_msg['From'] = From main_msg['To'] = To main_msg['Subject'] = "attach test " main_msg['Date'] = email.Utils.formatdate( ) # 得到格式化后的完整文本 fullText = main_msg.as_string( ) # 用smtp发送邮件 try: server.sendmail(From, To, fullText) finally: server.quit()
上面的代码只是发送邮件的大体代码,下面讲一下详细发送代码和注意事项:
一、gmail邮箱
发送代码如下:
#! /usr/bin/env python #coding=utf-8 ''' 发送邮件学习 ''' import smtplib, mimetypes from email.mime.base import MIMEBase from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.Header import Header from email.Encoders import encode_base64 import os.path def getAttachment(attachmentFilePath): print 'get path:',attachmentFilePath contentType, encoding = mimetypes.guess_type(attachmentFilePath) print contentType, encoding if contentType is None or encoding is not None: contentType = 'application/octet-stream' mainType, subType = contentType.split('/', 1) print mainType, subType file = open(attachmentFilePath, 'rb') attachment = MIMEBase(mainType, subType) attachment.set_payload(file.read()) encode_base64(attachment) file.close() #下面设置附件的头 attachment.add_header('Content-Disposition', 'attachment ; filename="%s"' %attachmentFilePath.encode('gb2312')) print "finish" print attachment return attachment def gmail_send(from_addr,to_addr,header,subject,username,password,msg_content,msg_type='plain',attachment=None): try: #构造邮件头部信息 msg = MIMEMultipart() msg['From'] = from_addr msg['To'] = to_addr msg['Subject'] = Header(header,charset='UTF-8') print u"头部构造完成" #添加邮件内容,先判断是明文邮件内容还是html内容 msg_type = msg_type.lower() if msg_type == 'plain': msg.attach(MIMEText(msg_content, _subtype='plain', _charset='UTF-8')) elif msg_type == 'html': msg.attach(MIMEText(msg_content, _subtype='html', _charset='UTF-8')) else: print u"不是有效的邮件内容类型" return False #添加邮件附件 if attachment is not None: for att in attachment: msg.attach(getAttachment(att)) except Exception,e: print u"构造邮件内容失败",e return False ''' 下面是gmail发送邮件过程 ''' try: smtp = smtplib.SMTP() smtp.set_debuglevel(1) smtp.connect('smtp.gmail.com',587) smtp.ehlo() smtp.starttls() smtp.ehlo() smtp.login(username,password) smtp.sendmail(from_addr, to_addr.split(','), msg.as_string()) print u"发送成功" return True except smtplib.SMTPException,e: print u"由于SMTP原因发送失败",e return False except Exception,e: print u"发送失败",e return False finally: smtp.quit() if __name__ == '__main__': #gmail_send('duhaizhang@gmail.com','1036914434@qq.com','这是中文邮件主题~~','测试','duhaizhang','wldroyogbwqzlqty','测试邮件正文','plain',u'K:\\安全协议概述.ppt') gmail_send('duhaizhang01@gmail.com','duhaizhang@gmail.com,1036914434@qq.com','这是中文邮件主题~~','测试','duhaizhang01','duhaizhang','测试邮件正文','plain',[u'杜.doc','baidu.txt'])
上面是gmail的发送代码,需要注意的内容有一下几点:
1、头部主题是中文时需要进行编码,编码是通过email.Header.Header()函数来进行的。因此,传入的主题参数不需要转换为unicode。
2、邮件内容分为两种,两种类型有点不同。
3、函数的附件路径需要传入时需加u转换为unicode是因为函数里面要读文件,而设置附件头的附件名称时需要将其重新编码。
4、gmail邮箱如果启用二次验证,会导致输入原始密码而提示口令错误,因此应该使用应用密码。
5、gmail对附件类型做了限制,限制不能上传包含有exe等危险附件,即使你压缩了也不行。
1、头部主题是中文时需要进行编码,编码是通过email.Header.Header()函数来进行的。因此,传入的主题参数不需要转换为unicode。
2、邮件内容分为两种,两种类型有点不同。
3、函数的附件路径需要传入时需加u转换为unicode是因为函数里面要读文件,而设置附件头的附件名称时需要将其重新编码。
4、gmail邮箱如果启用二次验证,会导致输入原始密码而提示口令错误,因此应该使用应用密码。
5、gmail对附件类型做了限制,限制不能上传包含有exe等危险附件,即使你压缩了也不行。
参考网站:PYTHON俱乐部:http://www.pythonclub.org
1、MIME邮件格式分析及信息提取 http://www.pythonclub.org/python-files/mime-type
2、Python SMTP 发送带附件电子邮件 http://www.pythonclub.org/python-network-application/smtp
转载请注明:jinglingshu的博客 » Python SMTP 发送带附件电子邮件