如何在python程序中发邮件

Python031

如何在python程序中发邮件,第1张

python中email模块使得处理邮件变得比较简单,今天着重学习了一下发送邮件的具体做法,这里写写自己的的心得,也请高手给些指点。

一、相关模块介绍

发送邮件主要用到了smtplib和email两个模块,这里首先就两个模块进行一下简单的介绍:

1、smtplib模块

smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])

SMTP类构造函数,表示与SMTP服务器之间的连接,通过这个连接可以向smtp服务器发送指令,执行相关操作(如:登陆、发送邮件)。所有参数都是可选的。

host:smtp服务器主机名

port:smtp服务的端口,默认是25;如果在创建SMTP对象的时候提供了这两个参数,在初始化的时候会自动调用connect方法去连接服务器。

smtplib模块还提供了SMTP_SSL类和LMTP类,对它们的操作与SMTP基本一致。

smtplib.SMTP提供的方法:

SMTP.set_debuglevel(level):设置是否为调试模式。默认为False,即非调试模式,表示不输出任何调试信息。

SMTP.connect([host[, port]]):连接到指定的smtp服务器。参数分别表示smpt主机和端口。注意: 也可以在host参数中指定端口号(如:smpt.yeah.net:25),这样就没必要给出port参数。

SMTP.docmd(cmd[, argstring]):向smtp服务器发送指令。可选参数argstring表示指令的参数。

SMTP.helo([hostname]) :使用"helo"指令向服务器确认身份。相当于告诉smtp服务器“我是谁”。

SMTP.has_extn(name):判断指定名称在服务器邮件列表中是否存在。出于安全考虑,smtp服务器往往屏蔽了该指令。

SMTP.verify(address) :判断指定邮件地址是否在服务器中存在。出于安全考虑,smtp服务器往往屏蔽了该指令。

SMTP.login(user, password) :登陆到smtp服务器。现在几乎所有的smtp服务器,都必须在验证用户信息合法之后才允许发送邮件。

SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]) :发送邮件。这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意msg的格式。这个格式就是smtp协议中定义的格式。

SMTP.quit() :断开与smtp服务器的连接,相当于发送"quit"指令。(很多程序中都用到了smtp.close(),具体与quit的区别google了一下,也没找到答案。)

2、email模块

emial模块用来处理邮件消息,包括MIME和其他基于RFC 2822 的消息文档。使用这些模块来定义邮件的内容,是非常简单的。其包括的类有:

class email.mime.base.MIMEBase(_maintype, _subtype, **_params):这是MIME的一个基类。一般不需要在使用时创建实例。其中_maintype是内容类型,如text或者image。_subtype是内容的minor type 类型,如plain或者gif。 **_params是一个字典,直接传递给Message.add_header()。

class email.mime.multipart.MIMEMultipart([_subtype[, boundary[, _subparts[, _params]]]]:MIMEBase的一个子类,多个MIME对象的集合,_subtype默认值为mixed。boundary是MIMEMultipart的边界,默认边界是可数的。

class email.mime.application.MIMEApplication(_data[, _subtype[, _encoder[, **_params]]]):MIMEMultipart的一个子类。

class email.mime.audio. MIMEAudio(_audiodata[, _subtype[, _encoder[, **_params]]]): MIME音频对象

class email.mime.image.MIMEImage(_imagedata[, _subtype[, _encoder[, **_params]]]):MIME二进制文件对象。

class email.mime.message.MIMEMessage(_msg[, _subtype]):具体的一个message实例,使用方法如下:

msg=mail.Message.Message()#一个实例

msg['to']='[email protected]' #发送到哪里

msg['from']='[email protected]' #自己的邮件地址

msg['date']='2012-3-16' #时间日期

msg['subject']='hello world'#邮件主题

class email.mime.text.MIMEText(_text[, _subtype[, _charset]]):MIME文本对象,其中_text是邮件内容,_subtype邮件类型,可以是text/plain(普通文本邮件),html/plain(html邮件), _charset编码,可以是gb2312等等。

二、几种邮件的具体实现代码

1、普通文本邮件

普通文本邮件发送的实现,关键是要将MIMEText中_subtype设置为plain。首先导入smtplib和mimetext。创建smtplib.smtp实例,connect邮件smtp服务器,login后发送,具体代码如下:(python2.6下实现)

# -*- coding: UTF-8 -*-

import smtplib

from email.mime.text import MIMEText

mailto_list=[[email protected]]

mail_host="smtp.XXX.com" #设置服务器

mail_user="XXXX"#用户名

mail_pass="XXXXXX" #口令

mail_postfix="XXX.com" #发件箱的后缀

def send_mail(to_list,sub,content):

me="hello"+"<"+mail_user+"@"+mail_postfix+">"

msg = MIMEText(content,_subtype='plain',_charset='gb2312')

msg['Subject'] = sub

msg['From'] = me

msg['To'] = "".join(to_list)

try:

server = smtplib.SMTP()

server.connect(mail_host)

server.login(mail_user,mail_pass)

server.sendmail(me, to_list, msg.as_string())

server.close()

return True

except Exception, e:

print str(e)

return False

if __name__ == '__main__':

if send_mail(mailto_list,"hello","hello world!"):

print "发送成功"

else:

print "发送失败"

2、html邮件的发送

与text邮件不同之处就是将将MIMEText中_subtype设置为html。具体代码如下:(python2.6下实现)

# -*- coding: utf-8 -*-

import smtplib

from email.mime.text import MIMEText

mailto_list=["[email protected]"]

mail_host="smtp.XXX.com" #设置服务器

mail_user="XXX"#用户名

mail_pass="XXXX" #口令

mail_postfix="XXX.com" #发件箱的后缀

def send_mail(to_list,sub,content): #to_list:收件人;sub:主题;content:邮件内容

me="hello"+"<"+mail_user+"@"+mail_postfix+">" #这里的hello可以任意设置,收到信后,将按照设置显示

msg = MIMEText(content,_subtype='html',_charset='gb2312')#创建一个实例,这里设置为html格式邮件

msg['Subject'] = sub#设置主题

msg['From'] = me

msg['To'] = "".join(to_list)

try:

s = smtplib.SMTP()

s.connect(mail_host) #连接smtp服务器

s.login(mail_user,mail_pass) #登陆服务器

s.sendmail(me, to_list, msg.as_string()) #发送邮件

s.close()

return True

except Exception, e:

print str(e)

return False

if __name__ == '__main__':

if send_mail(mailto_list,"hello","<a href=''>小五义</a>"):

print "发送成功"

else:

print "发送失败"

3、发送带附件的邮件

发送带附件的邮件,首先要创建MIMEMultipart()实例,然后构造附件,如果有多个附件,可依次构造,最后利用smtplib.smtp发送。

# -*- coding: cp936 -*-

from email.mime.text import MIMEText

from email.mime.multipart import MIMEMultipart

import smtplib

#创建一个带附件的实例

msg = MIMEMultipart()

#构造附件1

att1 = MIMEText(open('d:\\123.rar', 'rb').read(), 'base64', 'gb2312')

att1["Content-Type"] = 'application/octet-stream'

att1["Content-Disposition"] = 'attachmentfilename="123.doc"'#这里的filename可以任意写,写什么名字,邮件中显示什么名字

msg.attach(att1)

#构造附件2

att2 = MIMEText(open('d:\\123.txt', 'rb').read(), 'base64', 'gb2312')

att2["Content-Type"] = 'application/octet-stream'

att2["Content-Disposition"] = 'attachmentfilename="123.txt"'

msg.attach(att2)

#加邮件头

msg['to'] = '[email protected]'

msg['from'] = '[email protected]'

msg['subject'] = 'hello world'

#发送邮件

try:

server = smtplib.SMTP()

server.connect('smtp.XXX.com')

server.login('XXX','XXXXX')#XXX为用户名,XXXXX为密码

server.sendmail(msg['from'], msg['to'],msg.as_string())

server.quit()

print '发送成功'

except Exception, e:

print str(e)

4、利用MIMEimage发送图片

# -*- coding: cp936 -*-

import smtplib

import mimetypes

from email.mime.text import MIMEText

from email.mime.multipart import MIMEMultipart

from email.mime.image import MIMEImage

def AutoSendMail():

msg = MIMEMultipart()

msg['From'] = "[email protected]"

msg['To'] = "[email protected]"

msg['Subject'] = "hello world"

txt = MIMEText("这是中文的邮件内容哦",'plain','gb2312')

msg.attach(txt)

file1 = "C:\\hello.jpg"

image = MIMEImage(open(file1,'rb').read())

image.add_header('Content-ID','<image1>')

msg.attach(image)

server = smtplib.SMTP()

server.connect('smtp.XXX.com')

server.login('XXX','XXXXXX')

server.sendmail(msg['From'],msg['To'],msg.as_string())

server.quit()

if __name__ == "__main__":

AutoSendMail()

利用MIMEimage发送图片,原本是想图片能够在正文中显示,可是代码运行后发现,依然是以附件形式发送的,希望有高手能够指点一下,如何可以发送在正文中显示的图片的邮件,就是图片是附件中存在,但同时能显示在正文中,具体形式如下图。

系统编程:提供API(Application Programming Interface应用程序编程接口),能方便进行系统维护和管理,Linux下标志性语言之一,是很多系统管理员理想的编程工具。

图形处理:有PIL、Tkinter等图形库支持,能方便进行图形处理。

数学处理:NumPy扩展提供大量与许多标准数学库的接口。

文本处理:python提供的re模块能支持正则表达式,还提供SGML,XML分析模块,许多程序员利用python进行XML程序的开发。

数据库编程:程序员可通过遵循Python DB-API(数据库应用程序编程接口)规范的模块与Microsoft SQL Server,Oracle,Sybase,DB2,MySQL、SQLite等数据库通信。python自带有一个Gadfly模块,提供了一个完整的SQL环境。

网络编程:提供丰富的模块支持sockets编程,能方便快速地开发分布式应用程序。很多大规模软件开发计划例如Zope,Mnet 及BitTorrent. Google都在广泛地使用它。

Web编程:应用的开发语言,支持最新的XML技术。

多媒体应用:Python的PyOpenGL模块封装了“OpenGL应用程序编程接口”,能进行二维和三维图像处理。PyGame模块可用于编写游戏软件。

pymo引擎:PYMO全称为python memories off,是一款运行于Symbian S60V3,Symbian3,S60V5, Symbian3, Android系统上的AVG游戏引擎。因其基于python2.0平台开发,并且适用于创建秋之回忆(memories off)风格的AVG游戏,故命名为PYMO。

黑客编程:python有一个hack的库,内置了你熟悉的或不熟悉的函数,但是缺少成就感。

著名应用:Pylons-Web应用框架

Zope- 应用服务器

Plone- 内容管理系统

Django- 鼓励快速开发的Web应用框架

Uliweb- 国人开发的轻量级Web框架

TurboGears- 另一个Web应用快速开发框架

Twisted--Python的网络应用程序框架

Python Wikipedia Robot Framework- MediaWiki的机器人程序

MoinMoinWiki- Python写成的Wiki程序

flask- Python 微Web框架

Webpy- Python 微Web框架

Bottle- Python 微Web框架

EVE- 网络游戏EVE大量使用Python进行开发

Reddit - 社交分享网站

Dropbox - 文件分享服务

Pylons - Web应用框架

TurboGears - 另一个Web应用快速开发框架

Fabric - 用于管理成百上千台Linux主机的程序库

Trac - 使用Python编写的BUG管理系统

Mailman - 使用Python编写的邮件列表软件

Mezzanine - 基于Django编写的内容管理系统系统

Blender - 以C与Python开发的开源3D绘图软件

很多对Python不熟悉的人,认为Python在最近这些年的兴起是运气而已。本文帮助大家回顾一下过去十几年Python的3次增长和对应的历史背景。

Python设计之处的特点,包括易学易用,以及作为胶水语言。易学易用是个难以量化的东西,但至少我接触的绝大多数朋友都认同Python在学习和使用上是比大部分语言简单的。有些人不认同Python通常也不是认为Python相对其他语言难学,而是认为Python的运行速度慢,或者动态类型语言的通病。至于胶水语言就比较窄了,面向作为胶水而设计的语言是很少的,印象里只有Lua算得上一个。另一个Python相较其他语言的优势是字符串处理。

以下介绍Python获得发展的3次机遇期。

2006年的搜索/NLP:2006年前后正好是搜索引擎公司发展的爆发期。那一年Google中国李开复搞了关门弟子计划,百度也做了诸多广告,比如百度更懂中文系列。在那个时代搜索引擎就是IT行业的高科技。之后不久,阿里巴巴也搞了个ASC(阿里巴巴搜索技术研究中心),后来多次追潮流更名,一直作为阿里巴巴内部的前沿研发部门。

而Python用作搜索引擎和NLP是很有历史的。早期Google在90年代开发搜索引擎爬虫就是使用Python实现的。而即便是现在,开发爬虫,Python也基本上就是第一选择。很多人学习Python的入门程序也是爬虫。而Python适合开发爬虫的关键在于Python的字符串处理是很方便的。

也就是从2006年末开始,国内的python-cn邮件列表涌入了大量的新人,并以爬虫为例开始深入学习Python。

2010年的WEB创业潮:2010年开始,国内外出现了新一轮的创业潮,大家开发的是各种各样的网站。此时的WEB开发上,Python已经逐步成为主流WEB服务器开发选项中的一种。相对于同时代的Java和PHP等,有着开发效率上的优势。

正因为早期创业公司需要迅速的迭代和试错,使得这个时代的Python成为了一个不错的选项。进而让更多工程师开始学习起来Python。

也就是从这个时期开始,才逐渐有较多的公司会公开招聘Python工程师。在此前招聘Python工程师的广告是非常非常少见的。

2014年的Deep Learning:从2014年开始火起来的深度学习上,Python的优势是近乎绝对的。深度学习的主流开发语言只有C++和Python两种了,其他语言可以认为根本就没能在这里分到什么像样的空间。所有主流的Deep Learning框架,也是官方直接提供了C++和Python两种接口。而由于C++开发的难度,当前确实有不少从业工程师是直接用Python搞定深度学习的相关步骤。

这次Python的增长期被更多不了解Python的人认为是Python的狗屎运。但其背后的逻辑反倒是非常坚固的。原因就是Python是个很好的胶水。最初的起点是numpy库。

numpy是封装了BLAS的科学计算库。BLAS是对CPU向量指令集高度优化的数学运算库。通过BLAS进行科学计算可以得到顶级的计算性能,这个计算性能比未经向量指令集优化的C程序还能快上数倍。而numpy的另一个重要特点就是,把buffer做了封装,使得buffer的内容是无需Python处理的,而是实际交给特定的软件库来处理,numpy只是负责维护该buffer的生命周期,形状等元数据。这就使得numpy的计算性能不会受到Python的影响,但同时却可以利用Python的易学易用来管理buffer的生命周期。

numpy对buffer的管理带来的易用性优势在后来得到了很大的发展。如以下几点:

OpenCV:在opencv-python中就是使用了numpy.array来管理图像数据,却没有像C++接口一样使用Mat。同样的顶级性能。

PyCuda/PyOpenCL:也是利用了numpy.array来透明传递数据给GPU做高性能计算。尤其是集成了JIT,使得可以用字符串的方式传递kernel function,不再像C++一样要独立编译一遍。

Caffe/TensorFlow:同样利用了numpy.array,并利用了PyCuda/PyOpenCL的集成。

所以这样一路发现下来,由Python是个好胶水,就真的把若干很好用的库全流程的粘在了一起。在流程集成上都是顶级的性能,而没有Python的性能损耗,同时带来了非常好的易用性。

相比其他语言,对这些C/C++库的玩法都是先封装一层对象,包准封装的前后对不上。而且因为大部分语言并不是面向胶水设计,开发C接口都很困难。自然与这些高性能计算库的结合困难重重。累计起来就与Python产生了差距。

题主所提到的R语言,是一种领域相关的语言,是做统计领域的,类似的还有做科学计算的Matlab。如果程序的输出只是一份报告,甚至一份统计图,问题是不大的。但想要成为产品,与其他系统集成则成了难题。一般的服务器部署产品,是不会选择在工程上这么不专业的语言。所以,实际应用时,还是要有工程师负责将算法提取出来,移植到产品级的语言和平台上。举个例子,R虽然可以正常的访问MySQL数据库之类的。但产品级系统中,涉及到memcache、kafka、etcd等,可就没有R语言的接口了。所以这些领域相关语言,写一些自己电脑上跑的小程序还可以,进入产品是没什么希望了。

再者就是因为通用性一直难以跨越出自己的领域,所以这类语言的生命周期一般都不太长,失去自己领域的强支撑后会很快消亡。所以建议题主还是花一些精力去看看业界通用的一些语言。