Python中发送邮件可通过stmplib模块来发送,但如果要发送附件等信息需其他模块辅助,如可采用email模块发送电子邮件附件。发送一个未知MIME类型的文件附件其基本思路如下:

1. 构造MIMEMultipart对象做为根容器

2、设置根容器属性 (即设置邮件的头部信息,title,from,to)。

3. 构造MIMEText对象做为邮件显示内容并附加到根容器 (注意有两种形式的邮件正文:普通明文邮件和html形式邮件)

4. 构造MIMEBase对象做为文件附件内容并附加到根容器

a. 读入文件内容并格式化

b. 设置附件头

5. 得到格式化后的完整文本

6. 用smtp发送邮件

具体内容参见 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等危险附件,即使你压缩了也不行。