python脚本发邮件,一般会用到smtplib和email这两个模块。看看该模块怎么使用,先看smtplib模块。
smtplib模块定义了一个简单的SMTP客户端,可以用来在互联网上发送邮件。 定义的类有如下:
1 2 3 | class smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])
class smtplib.SMTP_SSL([host[, port[, local_hostname[, keyfile[, certfile[, timeout]]]]]])
class smtplib.LMTP([host[, port[, local_hostname]]])
|
还有一些已经定义好的异常
1 2 3 4 5 6 7 8 9 | exception smtplib.SMTPException
exception smtplib.SMTPServerDisconnected
exception smtplib.SMTPResponseException
exception smtplib.SMTPSenderRefused
exception smtplib.SMTPRecipientsRefused
exception smtplib.SMTPDataError
exception smtplib.SMTPConnectError
exception smtplib.SMTPHeloError
exception smtplib.SMTPAuthenticationError
|
这么多已定义的类中,我们最常用的的还是smtplib.SMTP类,就具体看看该类的用法: smtp实例封装一个smtp连接,它支持所有的SMTP和ESMTP操作指令,如果host和port参数被定义,则smtp会在初始化期间自动调用connect()方法,如果connect()方法失败,则会触发SMTPConnectError异常,timeout参数设置了超时时间。在一般的调用过程中,应该遵connetc()、sendmail()、quit()步骤。
下面我们来看看该类的方法:
SMTP.set_debuglevel(level) 设置输出debug调试信息,默认不输出调试信息。 SMTP.docmd(cmd[, argstring]) 发送一个command到smtp服务器, SMTP.connect([host[, port]]) 连接到指定的smtp服务器,默认是本机的25端口。也可以写成hostname:port的形式。 SMTP.helo([hostname]) 使用helo指令向smtp服务器确认你的身份。 SMTP.ehlo([hostname]) 使用ehlo指令向esmtp服务器确认你的身份。 SMTP.ehlo_or_helo_if_needed() 如果在以前的会话连接中没有提供ehlo或者helo指令,这个方法调用ehlo()或者helo()。 SMTP.has_extn(name) 判断指定的名称是否在smtp服务器上。 SMTP.verify(address) 判断邮件地址是否在smtp服务器上存在。 SMTP.login(user, password) 登陆需要验证的smtp服务器,如果之前没有提供ehlo或者helo指令,则会先尝试ESMTP的ehlo指令。 SMTP.starttls([keyfile[, certfile]]) 使smtp连接运行在TLS模式,所有的smtp指令都会被加密。 SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]) 发送邮件,该方法需要一些邮件地址和消息。 SMTP.quit() 终止smtp会话并且关闭连接。
经过搜索学习发现网上大多都是用smtp类的sendmail这个方法来发邮件,那就先看看这个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/python
import smtplib
from_mail = 'xxx@126.com'
to_mail = 'yyy@qq.com'
server = smtplib.SMTP( 'smtp.126.com' )
server.docmd( 'ehlo' , 'xxx@126.com' )
server.login( 'xxx@126.com' , 'password' )
msg = '''from:xxx@126.com
to:yyy@qq.com
subject:I am guol
I'm come 126
.
'''
server.sendmail(from_mail,to_mail,msg)
server.quit()
|
上例是使用sendmail方式,采用邮箱验证的模式来发邮件,因为现在大多数邮件系统都有反垃圾邮件机制及验证机制,我在开始实验非验证模式时就被126当作垃圾邮件而拒绝发送。
下面这个例子采用原始的smtp指令来发邮件。常用的smtp指令如下:
HELO 向服务器标识用户身份 MAIL 初始化邮件传输 mail from: RCPT 标识单个的邮件接收人;常在MAIL命令后面,可有多个rcpt to: DATA 在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输,以.结束 VRFY 用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令 EXPN 验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用 HELP 查询服务器支持什么命令 NOOP 无操作,服务器应响应OK QUIT 结束会话 RSET 重置会话,当前传输被取消 MAIL FROM 指定发送者地址 RCPT TO 指明的接收者地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/usr/bin/python
import base64
import smtplib
from_mail = 'xxx@126.com'
to_mail = 'yyy@qq.com'
user = base64.encodestring( 'xxx@126.com' ).strip()
passwd = base64.encodestring( 'password' ).strip()
server = smtplib.SMTP( 'smtp.126.com' )
server.set_debuglevel( 1 )
server.docmd( 'ehlo' , 'xxx@126.com' )
server.docmd( 'auth login' )
server.docmd(user)
server.docmd(passwd)
server.docmd( 'mail FROM:<%s>' % from_mail)
server.docmd( 'rcpt TO:<%s>' % to_mail)
server.docmd( 'data' )
server.docmd( '''from:xxx@126.com
to:yyy@qq.com
subject:I am guol
I'm come here
.
''' )
server.getreply()
server.quit()
|
注意在以上两个例子中在发送消息的subject后面书写正文时,需要空一行,正文以'.'结尾。
果然简单,如果想在邮件中携带附件、使用html书写邮件,附带图片等等,就需要使用email模块及其子模块。下面来看看email包,email包是用来管理email信息的,它包括MIME和其他基于RFC 2822的消息格式。email包的主要特征是在它内部解析和生成email信息是分开的模块来实现的。
MIME消息由消息头和消息体两大部分组成,在邮件里就是邮件头和邮件体。邮件头与邮件体之间以空行进行分隔。
邮件头包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第一个空白字符不是信息本身固有的。
邮件体包含邮件的内容,它的类型由邮件头的“Content-Type”域指出。最常见的类型有text/plain(纯文本)和text/html(超文本)。邮件体被分为多个段,每个段又包含段头和段体两部分,这两部分之间也以空行分隔。常见的multipart类型有三种:multipart/mixed, multipart/related和multipart/alternative。
在email的包里面包含了很多模块:
email.message email.parser email.generator email.mime 创建email和MIME对象 email.header email.charset email.encoders email.ereors email.utils email.iterators
主要来看看email.mime,在邮件中携带附件、图片、音频时,主要使用的是该模块。一般情况下,你通过解析一个文件或者一段text来生成一个消息对象结构,你也可以从头开始建立一个消息结构,实际上,你可以给一个已经存在的消息结构追加一个新的消息对象。你可以通过创建message实例来创建一个对象结构,然后给该结构追加附件和头部信息。email包提供了一些子类使得该操作变得很容易。
email.mime中常用的类如下:
email.mime.base email.mime.base.MIMEBase(_maintype, _subtype, **_params) email.mime.nonmultipart email.mime.nonmultipart.MIMENonMultipart email.mime.multipart email.mime.multipart.MIMEMultipart([_subtype[, boundary[, _subparts[, _params]]]])
1 | A subclass of MIMEBase, this is an intermediate base class for MIME messages that are multipart. Optional _subtype defaults to mixed, but can be used to specify the subtype of the message. A Content - Type header of multipart / _subtype will be added to the message object . A MIME - Version header will also be added.
|
email.mime.application email.mime.application.MIMEApplication(_data[, _subtype[, _encoder[, **_params]]])
email.mime.audio email.mime.audio.MIMEAudio(_audiodata[, _subtype[, _encoder[, **_params]]])
email.mime.image email.mime.image.MIMEImage(_imagedata[, _subtype[, _encoder[, **_params]]])
1 | A subclass of MIMENonMultipart, the MIMEImage class is used to create MIME message objects of major type image. _imagedata is a string containing the raw image data.
|
email.mime.message email.mime.message.MIMEMessage(_msg[, _subtype])
email.mime.text email.mime.text.MIMEText(_text[, _subtype[, _charset]])
1 | A subclass of MIMENonMultipart, the MIMEText class is used to create MIME objects of major type text. _text is the string for the payload. _subtype is the minor type and defaults to plain. _charset is the character set of the text and is passed as a parameter to the MIMENonMultipart constructor; it defaults to us - ascii. If _text is unicode , it is encoded using the output_charset of _charset, otherwise it is used as - is .
|
只解释了常用的几个类,详细信息见: http://docs./2/library/email.mime.html
模拟在邮件内容中携带图片,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from_mail = 'xxx@126.com'
to_mail = 'yyy@qq.com'
msg = MIMEMultipart()
msg[ 'From' ] = from_mail
msg[ 'To' ] = to_mail
msg[ 'Subject' ] = 'I am from email package'
body = 'I am come 126,i content with pic'
con = MIMEText( '<b>%s</b><br><img src="cid:/opt/25343674.png"><br>' % body, 'html' )
msg.attach(con)
img = MIMEImage( file ( '/opt/25343674.png' , 'rb' ).read())
img.add_header( 'Content-ID' , '/opt/25343674.png' )
msg.attach(img)
server = smtplib.SMTP( 'smtp.126.com' )
server.docmd( 'ehlo' , 'xxx@126.com' )
server.login( 'yyy@126.com' , 'password' )
server.sendmail(from_mail,to_mail,msg.as_string())
server.quit()
|
模拟在
邮件中携带附件
,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from_mail = 'xxx@126.com'
to_mail = 'yyy@qq.com'
msg = MIMEMultipart()
msg[ 'From' ] = from_mail
msg[ 'To' ] = to_mail
msg[ 'Subject' ] = 'I am from email package'
content = MIMEText( '<b>I am come 126,i with attach<b>' , 'html' )
msg.attach(content)
attac = MIMEImage( file ( '/opt/25343674.png' , 'rb' ).read())
attac[ 'Content-Type' ] = 'application/octet-stream'
attac.add_header( 'content-disposition' , 'attachment' ,filename = '/opt/25343674.png' )
msg.attach(attac)
server = smtplib.SMTP( 'smtp.126.com' )
server.docmd( 'ehlo' , 'xxx@126.com' )
server.login( 'yyy@126.com' , 'password' )
server.sendmail(from_mail,to_mail,msg.as_string())
server.quit()
|
以上代码均在python2.7下经过测试。
参考:
http:///code-snippet/1105/python-usage-smtplib-fayoujian-carry-fujian-code http://docs./2/library/smtplib.html http:///questions/3362600/how-to-send-email-attachments-with-python
|