邮件删了 GB忘接收邮件服务器了 怎么办

[原创] 用Python处理邮件,全文完. - ChinaUnix.net
[原创] 用Python处理邮件,全文完.
http://www.chinaunix.net 作者:&&发表于: 16:27:48
总体来说python处理邮件还是比较方便的,库提供了很多工具.下面我把心得写出来,给新手一个启迪,也请高手给些更好的方法.
先说接受邮件.&&poplib&方法.
1.poplib.POP3('这里填入你pop邮件服务器地址')&登陆服务器.
2.poplib.user('用户名&')&poplib.pass_('密码')
3.poplib.stat()方法返回一个元组:(邮件数,邮件尺寸)
&&&mailCount,size=poplib.stat()
&&&这样mailCount就是邮件的数量,size,就是所有邮件的大小.
3.poplib.rert('邮件号码')方法返回一个元组:(状态信息,邮件,邮件尺寸)&
&&hdr,message,octet=server.retr(1)&读去第一个邮件信息.
&&&hdr的内容就是响应信息和邮件大小比如'+OK&12498&octets'
&&&message&是包含邮件所有行的列表.
&&&octet&是这个邮件的内容.
&得到的message是邮件的原始内容,也就是没有解码过的,里面的内容和标题基本上都是base64编码的,下面说说如何处理原始邮件.
python&的email库里提供了很多处理邮件的方法,我们先把原始邮件转成email实例,这样就可以用库方法处理邮件.
email.message_from_string()&这个方法能把String的邮件转换成email.message实例.
比如我们上面的message,向下面这样调用.
mail=email.message_from_string(string.join(message,'\n'))
这样我们就生成了一个email.Message实例
现在我们来提取邮件内容,和标题,mail支持字典操作.比如下面的操作.
mail['subject']&,mail.get('subject')
mail['To'],mail.get('to')'
mail.keys()&,mail.items()&等等.
中文邮件的标题和内容都是base64编码的.解码可以使用email.Header&里的decode_header()方法.
比如&print&mail['subject']&&&显示的都未处理的编码.
'=?GB2312?B?UmU6IFtweXRob24tY2hpbmVzZV0g?=\n\t=?GB2312?B?y63E3LDvztLV0tbQzsS1xFBZVEhPTrP10afRp8+wtcTXysHP?='
email.Header.decode_header(mail['subject'])&下面是解码后的信息.
[('Re:&[python-chinese]&\xcb\xad\xc4\xdc\xb0\xef\xce\xd2\xd5\xd2\xd6\xd0\xce\xc4\xb5\xc4PYTHON\xb3\xf5\xd1\xa7\xd1\xa7\xcf\xb0\xb5\xc4\xd7\xca\xc1\xcf',&'gb2312')]
返回的是一个列表,里面的内容保存在一个元组里,(解码后的字串,字符编码)
显示解码后的标题就象下面这样
print&email.Header.decode_header(mail['subject'])[0][0]
Re:&[python-chinese]&谁能帮我找中文的PYTHON初学学习的资料
上面的mail标题编码是'gb2312'的,在我的winxp机器上可以直接显示,如果编码是别的比如'utf-8'编码,那么显示出来的就是乱码了.所以我们需要使用unicode()方法,unicode('这里是string','这里是编码,比如UTF-8'),比如
subject=email.Header.decode_header(mail['subject'])[0][0]
subcode=email.Header.decode_header(mail['subject'])[0][1])
print&unicode(subject,subcode)
Re:&[python-chinese]&谁能帮我找中文的PYTHON初学学习的资料
下面看如何处理邮件内容.
mail里有很多方法,熟悉这些方法处理邮件就很容易了。
get_payload()&这个方法可以把邮件的内容解码并且显示出来.第一个可选择参数是mail实例,第二个参数是decode='编码'&,一般都是,'base64'编码
is_multipart(),这个方法返回boolean值,如果实例包括多段,就返回True,
print&mail.is_multipart()
true&&,这说明这个mail邮件包含多个字段。我下面的函数就可以处理,显示邮件的全部内容。
def&showmessage(mail):
&&&&if&mail.is_multipart():
&&&&&&&&for&part&in&mail.get_payload():
&&&&&&&&&&&&showmessage(part)
&&&&else:
&&&&&&&&type=mail.get_content_charset()
&&&&&&&&if&type==None:
&&&&&&&&&&&&print&mail.get_payload()
&&&&&&&&else:
&&&&&&&&&&&&try:
&&&&&&&&&&&&&&&&print&unicode(mail.get_payload('base64'),type)
&&&&&&&&&&&&except&UnicodeDecodeError:
&&&&&&&&&&&&&&&&print&mail
最后,有点要说明,如果邮件里的中文用mail.Header.decode_header()方法,和unicode()方法都不能正常显示,那么说明这个中文无法处理了,显示出来就是乱码.比如:看看看见,最终处理完成后,还是乱麻。
&;&;&;mail.get('subject')
'Re:&[python-chinese]&=?UTF-8?B?wrnDmMOTw5p4bWzCscOgw4LDq8K1w4TDjg==?=\n\t=?UTF-8?B?w4rDjMOi?='
&;&;&;decode_header(&mail.get('subject'))
[('Re:&[python-chinese]',&None),&('\xc2\xb9\xc3\x98\xc3\x93\xc3\x9axml\xc2\xb1\xc3\xa0\xc3\x82\xc3\xab\xc2\xb5\xc3\x84\xc3\x8e\xc3\x8a\xc3\x8c\xc3\xa2',&'utf-8')]
&;&;&;print&decode_header(&mail.get('subject'))[1][0]
鹿脴脫脷xml卤脿脗毛碌脛脦脢脤芒
&;&;&;print&unicode(decode_header(&mail.get('subject'))[1][0],'utf-8')
1?óúxml±à??μ??êìa
& 回复于: 20:22:35
下面说说发送邮件,其实我感觉发送比接收邮件要容易。还是使用mail.Message里的方法。我们一步一步来。
1:发送一个普通的文本邮件。
msg=mail.Message.Message()&&&&#一个实例
msg['to']=''&&&&&&#发送到哪里
msg['from']=''&&&&&&&#自己的邮件地址
msg['date']=time.ctime()&&&&&&&&&&&&&#时间日期
msg['subject']=email.Header.Header('邮件主题','gb2312')
#这里用Header方法处理subject.
完成后的样子.
&;&;&;print&msg.as_string()
to:&
from:&
date:&Mon&Jul&11&20:18:13&2005
subject:&=?gb2312?b?08q8/tb3zOI=?=&
下面开始写内容。
body=email.MIMEText.MIMEText('这里是邮件内容',_subtype='plain',_charset='gb2312')
MIMEText()方法包括3个参数,内容,_subtype类型,_charset字符编码,完成后的样子:
&;&;&;print&body.as_string()
Content-Type:&text/&charset="gb2312"
MIME-Version:&1.0
Content-Transfer-Encoding:&base64
1eLA78rHxNrI3Q==
Content-Type,说明内容类型,这里是txt/plain,纯文本类型。如果添加附件
那么就是Application/octet-stream
Content-Transfer-Encoding这个就是编码类型,这里是base64,现在的email都是base64编码
写完以后如何组合起来?mail有一个as_string()方法,顾名思义。显示成一个字符串.我上面也用了。smtplib里的sendmail()方法里需要的是字符串类型。所以我们这里可以这样:&完整的内容加起来就行了。
&;&;&;print&msg.as_string()+body.as_string()
to:&
from:&
date:&Mon&Jul&11&20:18:13&2005
subject:&=?gb2312?b?08q8/tb3zOI=?=
Content-Type:&text/&charset="gb2312"
MIME-Version:&1.0
Content-Transfer-Encoding:&base64
1eLA78rHxNrI3Q==
如何发送.
server=smtplib.SMTP('smtp.')& #你发送服务器的地址
server.login('username','password')&&&&&&&#用户名和密码
server.sendmail('from','to','msg.as_string()[:-1]+body.as_string()')
#这样就完成了邮件的发送.
有一点要注意.只有内容前面有一个空行,其他的地方都不能有空行.前面我们直接print&msg.as_string()+body.as_string()可以看见在subject:&和Content-type:这里有一个空行,所以我用'msg.as_string()[:-1]把多余的空行去掉.让他和body保持格式.
下面看看如何发带附件的邮件,和上面差不多.
attach=mail.MIMEMultipart.MIMEMultipart()&&#这里创建一个带附件的实例
attach.attach(body)& #把我们刚才写的邮件内容加进去.
attachment=MIMEText(open('myself.py','r').read(),'base64')
#第一个参数打开文件read()方法读出所有内容,刚好是字符串格式,第二个参数是希望的编码,这种方法比较简单.
attachment.replace_header('Content-type','Application/octet-name="myself.py"')
#前面讲过Content-type:他的值可以是text/plain&text/heml&等等,如果是附件,就是Application/octet-stream,后面的;name="myself.py"是附件的文件名.默认的MIMEText()后这里的内容是text/plain的,所以需要替换
attachment.add_header('Content-Disposition','filename="myself.py")
#这里添加一个标题,Content-Disposition,attachment说明是一个附件,filename说明文件名.mail里有一个get_filename()的方法可以得到附件里的文件名.
attach.attach(attachment)& #现在我们把编码好的附件也加进去
完成后的邮件像下面这样
to:&
from:&
subject:&=?gb2312?b?1vfM4g==?=
Content-Type:&multipart/&boundary="================="
MIME-Version:&1.0
--=================
Content-Type:&text/&charset="gb2312"
MIME-Version:&1.0
Content-Transfer-Encoding:&base64
1eLA78rHxNrI3Q==
--=================
Content-Type:&Application/octet-name="myself.py"
MIME-Version:&1.0
Content-Transfer-Encoding:&base64
Content-Disposition:&filename="myself.py"
ZnJvbSBlbWFpbC5NSU1FVGV4dCBpbXBvcnQgTUlNRVRleHQKZnJvbSBlbWFpbC5NSU1FTXVsdGlw
YXJ0IGltcG9ydCBNSU1FTXVsdGlwYXJ0CmZyb20gZW1haWwuSGVhZGVyIGltcG9ydCBIZWFkZXIK
ZnJvbSBlbWFpbC5IZWFkZXIgaW1wb3J0IGRlY29kZV9oZWFkZXIKZnJvbSB0eXBlcyBpbXBvcnQg
--=================--
好了,可以发送了.
server=smtplib.SMTP('smtp.')& 
server.login('username','password')&&&&&&&
server.sendmail('from','to','msg.as_string()[:-1]+attach.as_string()')
刚才说了,附件也可以不用MIMEText()方法创建像下面这样也可以.
att=base64.encodestring(open('file','r').read())
att=MIMEText(att)
然后就和前面一样,换标题Content-type,&加Content-Disposition标题,等等.显然比较麻烦.
当然更简单的方法就是创建上面的attach以后,直接在attach里添加 主题等标题.
attach['to']=''
attach['from']=''
attach['date']=time.ctime()
attach['subject']=Header('直接发送的标题','gb2312')
这样添加完以后直接attach.as_string()发送就可以了,包括了主题,内容,附件.
全文完,菜鸟学习经过,仅供新手参考.
希望高手能多多指点.
& 回复于: 21:40:33
发现自己的表达能力太差,看来要多练练,大家将就着看好了。
这个星期研究Tk学会了写个GUI界面的邮件程序.学好了再上来写心得.
& 回复于: 21:44:34
最后把我写的一个简陋的,幼稚的一个字符平台的email程序贴上来.希望高手能给指点指点.
程序的菜单截面根据Programming&Python&ed2,里面的程序改的,否则我肯定是想不出来这样的菜单截面.(想象力差,还是经验不足,晕)
保存邮件方法没有做出来.发送邮件也没写.from&email.MIMEText&import&MIMEText
from&email.MIMEMultipart&import&MIMEMultipart
from&email.Header&import&Header
from&email.Header&import&decode_header
from&types&import&*
import&smtplib,poplib,string,sys,os,email
helptext&=&"""
Available&commands:
i&&&&&-&index&display
l&n?&&-&list&all&messages&(or&just&message&n)
d&n?&&-&mark&all&messages&for&deletion&(or&just&message&n)
s&n?&&-&save&input&num&messages&to&a&file&(or&just&message&n)
m&&&&&-&compose&and&send&a&new&mail&message
q&&&&&-&quit&pymail
?&&&&&-&display&this&help&text
"""
#简单的菜单处理,无返回值,要求一个处理过的mail列表
def&interact(processmail):
&&&&#showindex(processmail)
&&&&while&1:
&&&&&&&&try:
&&&&&&&&&&&&command=raw_input('[Pymail]&Action?&(i,&l,&d,&s,&m,&q,&?)&')
&&&&&&&&except&EOFError:
&&&&&&&&&&&&command='q'
&&&&&&&&if&command=='q'&or¬&command:
&&&&&&&&&&&&break
&&&&&&&&elif&command[0]=='i':
&&&&&&&&&&&&showindex(processmail)
&&&&&&&&elif&command[0]=='l':
&&&&&&&&&&&&if&len(command)==1:
&&&&&&&&&&&&&&&&for&mail&in&processmail:
&&&&&&&&&&&&&&&&&&&&showmessage(mail)
&&&&&&&&&&&&&&&&&&&&print&string.join(message)
&&&&&&&&&&&&else:
&&&&&&&&&&&&&&&&if&0&msgnum(command)&=len(processmail):
&&&&&&&&&&&&&&&&&&&&num=msgnum(command)
&&&&&&&&&&&&&&&&&&&&showsubject(processmail[num-1])
&&&&&&&&&&&&&&&&&&&&showmessage(processmail[num-1])
&&&&&&&&elif&command[0]=='s':
&&&&&&&&&&&&if&len(command)==1:
&&&&&&&&&&&&&&&&print&'请输入要保存的邮件号码'
&&&&&&&&&&&&&&&&continue
&&&&&&&&&&&&else:
&&&&&&&&&&&&&&&&if&0&msgnum(command)&=len(processmail):
&&&&&&&&&&&&&&&&&&&&num=msgnum(command)
&&&&&&&&&&&&&&&&&&&&savemail(processmail[num-1])
&&&&&&&&elif&command[0]=='?':
&&&&&&&&&&&&print&helptext
&&&&&&&&else:
&&&&&&&&&&&&print&'What?&--&type&"?"&for&commands&help'
&#保存email未完成&&&&&&&&&&&
def&savemail(mail):
&&&&filename=raw_input('Enter&a&file&name:')
&&&&file=open('filename','w')
&&&&print&&;&;&file,showsubject(mail),showmessage(mail)
&&&&print&'saving&mail&to&%s&ok.'&%(filename)
#处理输入的数字&&&
def&msgnum(command):
&&&&try:
&&&&&&&&return&string.atoi(string.split(command)[1])
&&&&except:
&&&&&&&&return&-1
#用于接收&邮件的相关处理,返回一个server实例&&&
def&POPconnect():
&&&&sname,user,passwd=popconfig()
&&&&server=poplib.POP3(sname)
&&&&server.user(user)
&&&&server.pass_(passwd)
&&&&print&server.getwelcome()
&&&&return&server
#用于发送&邮件的相关处理,返回一个server实例&
def&SMTPconnect():
&&&&server=smtplib.SMTP(sname)
&&&&server.login(user,passwd)
&&&&return&server
#从服务器读取邮件到maillist.列表,位处理的原始字符串
def&loadmail():
&&&&server=POPconnect()
&&&&try:
&&&&&&&&print&server.list()
&&&&&&&&(mailCount,mailByte)=server.stat()
&&&&&&&&print&'There&are',mailCount,'mail&messages&in',mailByte,'bytes'
&&&&&&&&print&'Retrieving:'
&&&&&&&&mailList=[]
&&&&&&&&for&i&in&range(mailCount):
&&&&&&&&&&&&print&i+1,
&&&&&&&&&&&&(hdr,message,octet)=server.retr(i+1)
&&&&&&&&&&&&mailList.append(string.join(message,'\n'))
&&&&&&&&print
&&&&&&&&assert&len(mailList)==mailCount
&&&&&&&&return&mailList
&&&&finally:
&&&&&&&&server.quit()
#处理loadmain返回的原始mail列表,返回处理过的processmail列表
def&processmail(mailList):
&&&&processmaillist=[]
&&&&for&i&in&range(len(mailList)):
&&&&&&&&processmaillist.append(email.message_from_string(mailList))
&&&&return&processmaillist
#显示邮件主题,要求一个处理过的mail做参数
def&showsubject(mail):
&&&&header=[]
&&&&for&head&in&decode_header(mail.get('subject')):
&&&&&&&&if&head[1]=='utf-8':
&&&&&&&&&&&&header.append(unicode(head[0],'utf-8'))
&&&&&&&&else:
&&&&&&&&&&&&header.append(head[0])
&&&&&&&&&&&&
&&&&for&sub&in&('From','Date','Subject'):
&&&&&&&&if&sub=='Subject':
&&&&&&&&&&&&print&'Subject:',
&&&&&&&&&&&&for&subject&in&header:
&&&&&&&&&&&&&&&&try:
&&&&&&&&&&&&&&&&&&&&print&subject,
&&&&&&&&&&&&&&&&except&UnicodeEncodeError:
&&&&&&&&&&&&&&&&&&&&print&'注意:这个邮件标题无法正常显示...'
&&&&&&&&else:
&&&&&&&&&&&&print&'%s:%s'&%(sub,mail[sub])
&&&&print&&&&&&
&&&&&&&&
#显示邮件内容,要求一个处理过的mail做参数
def&showmessage(mail):
&&&&if&mail.is_multipart():
&&&&&&&&for&part&in&mail.get_payload():
&&&&&&&&&&&&showmessage(part)
&&&&else:
&&&&&&&&type=mail.get_content_charset()
&&&&&&&&if&type==None:
&&&&&&&&&&&&print&mail.get_payload()
&&&&&&&&else:
&&&&&&&&&&&&try:
&&&&&&&&&&&&&&&&print&unicode(mail.get_payload(decode='base64'),type)
&&&&&&&&&&&&except&UnicodeDecodeError:
&&&&&&&&&&&&&&&&print&mail
#显示全部邮件主题要求整个处理过的邮件列表
def&showindex(processmaillist):
&&&&count=1
&&&&for&mail&in&processmaillist:
&&&&&&&&print&count,
&&&&&&&&showsubject(mail)
&&&&&&&&print&
&&&&&&&&if&count%5==0:
&&&&&&&&&&&&raw_input("\n[Press&Enter&key]")
&&&&&&&&count+=1
#输入发送时需要的服务器名等相关信息,返回一个元组
def&sendconfig():
&&&&SMTPname=raw_input('SMTPserverName?')
&&&&SMTPuser=raw_input('SMTPusername?')
&&&&SMTPpass=raw_input('SMTPServerPassword?')
&&&&To=raw_input('To?')
&&&&From=raw_input('From?')
&&&&return&SMTPname,SMTPuser,SMTPpass,to,From
#输入接收邮件时需要的相关输入,返回一个元组
def&popconfig():
&&&POPname=raw_input('POPServerName?')
&&&POPuser=raw_input('POPusername?')
&&&POPpass=raw_input('POPpassword?')
&&&return&POPname,POPuser,POPpass
if&__name__=='__main__':
&&&&list=loadmail()
&&&&maillist=processmail(list)
&&&&interact(maillist)
&&&&
& 回复于: 09:09:12
& 回复于: 09:20:57
& 回复于: 09:23:46
对于汉字编码的转换,可以这样做,我试过效果不错。
a='中国'
a.decode('gb2312').encode("utf-8")
& 回复于: 11:17:03
very&good&!
& 回复于: 22:13:30
鼓励一下
帮你顶一下,向你学习![&本帖最后由&kai0200&于&&22:22&编辑&]
& 回复于: 14:58:22
请教一个问题,如何判断邮件的附件?
btw,楼主的showmessage()用walk()来实现似乎更好一点。
& 回复于: 14:56:54
判断某个part的编码应该使用Content-Transfer-Encoding。
& 回复于: 16:27:48
处理邮件内容时,这样做更好一些:
参数mail是通过message_from_string()得到的instance
def&mail_content(mail):
&&&&content&=&&&&''
&&&&for&part&in&mail.walk():
&&&&&&&&if&part.is_multipart():
&&&&&&&&&&&&continue
&&&&&&&&ch&=&&&&part.get_content_charset()
&&&&&&&&if&ch:
&&&&&&&&&&&&content&+=&&&&unicode(part.get_payload(decode&=&True),ch).encode('utf-8')
&&&&&&&&else:
&&&&&&&&&&&&content&+=&&&&part.get_payload(decode&=&True).decode('gb2312').encode('utf-8')
&&&&return&content
原文链接:
转载请注明作者名及原文出处查看:6344|回复:4
提示: 作者被禁止或删除 内容自动屏蔽
论坛运营团队的非正规军
不知道你有没有设置对已删除的邮件的保留时间,如果有并且在时间之内,那就可以很容易的恢复
如果没有,那就只能在备份里恢复了,比较麻烦
(EXCHG.80).aspx
提示: 作者被禁止或删除 内容自动屏蔽
论坛运营团队的非正规军
那你有没有平时做备份啊,可以在备份里恢复
51CTO学院讲师
可以尝试一下用浏览器登录到Exchange服务器,在邮箱的选项里有一个恢复已删除的邮件功能,可以尝试一下。原理是Exchange服务器在删除邮件后,还会把邮件保留一段时间,如果你的邮件删除时间不长,还是有恢复的可能性的。

参考资料

 

随机推荐