整體來講python處理郵件仍是比較方便的,庫提供了不少工具.下面我把心得寫出來,給新手一個啓迪,也請高手給些更好的方法.
先說接受郵件. poplib 方法.
1.poplib.POP3('這裏填入你pop郵件服務器地址') 登錄服務器.
2.poplib.user('用戶名 ') poplib.pass_('密碼')
3.poplib.stat()方法返回一個元組:(郵件數,郵件尺寸)
mailCount,size=poplib.stat()
這樣mailCount就是郵件的數量,size,就是全部郵件的大小.
4.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郵件包含多個字段。我下面的函數就能夠處理,顯示郵件的所有內容。 python
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
下面說說發送郵件,其實我感受發送比接收郵件要容易。仍是使用mail.Message裏的方法。咱們一步一步來。 1:發送一個普通的文本郵件。
msg=mail.Message.Message() #一個實例
msg['to']='love@python.com' #發送到哪裏
msg['from']='my@email.com' #本身的郵件地址
msg['date']=time.ctime() #時間日期
msg['subject']=email.Header.Header('郵件主題','gb2312')
#這裏用Header方法處理subject.
完成後的樣子.
>>>print msg.as_string()
to: love@python.com
from: my@email.com
date: Mon Jul 11 20:18:13 2005
subject: =?gb2312?b?08q8/tb3zOI=?=
下面開始寫內容。 app
body=email.MIMEText.MIMEText('這裏是郵件內容',_subtype='plain',_charset='gb2312')
MIMEText()方法包括3個參數,內容,_subtype類型,_charset字符編碼,完成後的樣子:
>>>print body.as_string()
Content-Type: text/plain; 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: love@python.com
from: my@email.com
date: Mon Jul 11 20:18:13 2005
subject: =?gb2312?b?08q8/tb3zOI=?=
Content-Type: text/plain; charset="gb2312"
MIME-Version: 1.0
Content-Transfer-Encoding: base64
1eLA78rHxNrI3Q==
如何發送.
server=smtplib.SMTP('smtp.mail.yahoo.com') #你發送服務器的地址
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-stream;name="myself.py"')
#前面講過Content-type:他的值能夠是text/plain text/heml 等等,若是是附件,就是Application/octet-stream,後面的;name="myself.py"是附件的文件名.默認的MIMEText()後這裏的內容是text/plain的,因此須要替換
attachment.add_header('Content-Disposition','attachment;filename="myself.py")
#這裏添加一個標題,Content-Disposition,attachment說明是一個附件,filename說明文件名.mail裏有一個get_filename()的方法能夠獲得附件裏的文件名.
attach.attach(attachment) #如今咱們把編碼好的附件也加進去
完成後的郵件像下面這樣 函數
to: asdf@tom.com
from: asdf@tom.com
subject: =?gb2312?b?1vfM4g==?=
Content-Type: multipart/mixed; boundary="===============0572491976=="
MIME-Version: 1.0
--===============0572491976== Content-Type: text/plain; charset="gb2312" MIME-Version: 1.0 Content-Transfer-Encoding: base64 1eLA78rHxNrI3Q== --===============0572491976== Content-Type: Application/octet-stream;name="myself.py" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment;filename="myself.py" ZnJvbSBlbWFpbC5NSU1FVGV4dCBpbXBvcnQgTUlNRVRleHQKZnJvbSBlbWFpbC5NSU1FTXVsdGlw YXJ0IGltcG9ydCBNSU1FTXVsdGlwYXJ0CmZyb20gZW1haWwuSGVhZGVyIGltcG9ydCBIZWFkZXIK ZnJvbSBlbWFpbC5IZWFkZXIgaW1wb3J0IGRlY29kZV9oZWFkZXIKZnJvbSB0eXBlcyBpbXBvcnQg --===============0572491976==--
好了,能夠發送了.
server=smtplib.SMTP('smtp.mail.yahoo.com')
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']='asdf@tom.com'
attach['from']='asdfd@tom.com'
attach['date']=time.ctime()
attach['subject']=Header('直接發送的標題','gb2312')
這樣添加完之後直接attach.as_string()發送就能夠了,包括了主題,內容,附件.
全文完,菜鳥學習通過,僅供新手參考.
但願高手能多多指點.工具
最後把我寫的一個簡陋的,幼稚的一個字符平臺的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 not 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'))
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])
#顯示郵件內容,要求一個處理過的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)
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)