python与POP3

来源:互联网 发布:java中ant怎么用 编辑:程序博客网 时间:2024/05/21 17:37

邮件由三部分组成:信封,邮件头,邮件体
信封显然可以不含有二进制信息,而其它两部分则可能包含任意二进制序列,因此需要加以改进。MIME正是抓住了这两个地方来对他们加以改进。
1) 新增了一些邮件头信息,用来协商MIME的一些参数。
2) 定义了许多邮件内容的格式,对多媒体电子邮件的表示方法进行了标准化。
3) 定义了传送编码,从而可以传送任意二进制文件。

邮件头:
包含了发件人、收件人、主题、时间、MIME版本、邮件内容的类型等重要信息。每条信息称为一个域,由域名后加“: ”和信息内容构成,可以是一行,较长的也可以占用多行。域的首行必须“顶头”写,即左边不能有空白字符(空格和制表符);续行则必须以空白字符打头,且第一个空白字符不是信息本身固有的,解码时要过滤掉。
常见的域有:
这里写图片描述

邮件体:
邮件体又有许多段组成,每一段有自己的段头和段体
常见的头信息有:

类型 描述 Content-Type: 它定义了数据的类型,以便数据能被适当的处理。有效的类型有:text,image,audio,video, applications,multipart和message。注意任何一个二进制附件都应该被叫做application/octet- stream。这个头的一些用例为:image/jpg, application/mswork,multipart/mixed,这只是很少的一部分。 Content-Transfer-Encoding: 这是所有头中最重要的一个,因为它说明了对数据所执行的编码方式,客户/MUA 将用它对附件进行解码。对于每个附件,可以使用7bit,8bit,binary ,quoted-printable,base64和custom中的一种编码方式。7bit编码是用在US ASCII字符集上的常用的一种编码方式,也就是,保持它的原样。8bit和binary编码一般不用。对人类可读的标准文本,如果传输要经过对格式有影响的网关时对其进行保护,可以使用quoted printable 。Base64是一种通用方法,在需要决定使用哪一种编码方法时,它提供了一个不用费脑子的选择;它通常用在二进制,非文本数据上。注意,任何非7bit 数据必须用一种模式编码,这样它就可以通过Internet邮件网关! Content-ID: 如果Content-Type是message/external-body或multipart/alternative时,这个头就有用了。它超出了本文的范围。 Content-Description: 这是一个可选的头。它是任何信息段内容的自由文本描述。描述必须使用us-ascii码。 Content-Disposition: 一个试验性的头,它用于给客户程序/MUA提供提示,来决定是否在行内显示附件或作为单独的附件。MIME段头(出现在实际的MIME附件部分的头),除了MIME-Version头,可以拥有以上任何头字段。如果一个MIME头是信息块的一部分,它将作用于整个信息体。例如,如果Content-Transfer-Encoding显示在信息(指整个信息)头中,它应用于整个信息体,但是如果它显示在一个MIME段里,它”只能”用于那个段中.

注意:其可以对自动对收到的邮件进行解密

Content-Type的格式:

header(“Content-type:text/html;charset=utf-8”);

Content-Dispostion的格式:

格式说明: content-disposition = “Content-Disposition” “:”
disposition-type *( “;” disposition-parm )   字段说明:
Content-Disposition为属性名 disposition-type是以什么方式下载,如attachment为以附件方式下载
disposition-parm为默认保存时的文件名
服务端向客户端游览器发送文件时,如果是浏览器支持的文件类型,一般会默认使用浏览器打开,比如txt、jpg等,会直接在浏览器中显示,如果需要提示用户保存,就要利用Content-Disposition进行一下处理,关键在于一定要加上attachment:

还有常见的MIME类型,请参考上一篇博客。

下面关于SMTP和POP3的代码参考自:廖雪峰的官方网站
写的很好,帮助很大。

import smtplib,poplibfrom time import sleepfrom email.mime.text import MIMETextfrom email import encodersfrom email.header import Headerfrom email import parserimport emailfrom email.header import decode_headerfrom DecodeEmail import print_infofrom email.utils import parseaddr,formataddrdef format_addr(s):    name,addr=parseaddr(s)    return formataddr((Header(name,'utf-8').encode(),addr))smtpmailserver='smtp.qq.com'pop3mailserver='pop.qq.com'sender='xxxxxx@qq.com'receiver='xxxxxx@qq.com'username='xxxxxx@qq.com'password='xxxxxx'msg=MIMEText('''I am a programmer!what's your name?My name is tanying.enhengYou are my baby!hahahahahah''','plain','utf-8')msg['Subject']=Header('SMTP发邮件','utf-8').encode()msg['From']=format_addr('Python爱好者<%s>' % sender)msg['To']=format_addr('管理员<%s>' % receiver)smtp=smtplib.SMTP(smtpmailserver)smtp.set_debuglevel(1)smtp.login(username,password)smtp.sendmail(sender,receiver,msg.as_string())smtp.quit()pop=poplib.POP3(pop3mailserver)pop.user(username)pop.pass_(password)#retr()返回一个tuple,其中包含了结果代码和邮件。但是邮件并不是字符串格式,而是一个字符串的列表。每一个元素表示该邮件的一行。我们可以使用”\n”.join(lines)来把它们转换成标准的字符串。resp,mails,size=pop.retr(pop.stat()[0])msg_content=b'\r\n'.join(mails)#parser.Parser().parsestr将字符串解析成Message,参数只能是字符串msg=parser.Parser().parsestr(bytes.decode(msg_content))pop.quit()print_info(msg,0)
__author__ = 'qingjin'import emailfrom email.parser import Parserfrom email.header import decode_headerfrom email.utils import parseaddrdef decode_header_str(s):    #decode_header解析头部字符串,返回一个list,包含字符串的值和编码方式    value,charset=decode_header(s)[0]    if charset:        value=value.decode(charset)    return valuedef guess_charset(msg):    charset=msg.get_charset()    if charset is None:        #如果没有那么从Content-type中获得charset的值        #Content-type格式是这样的header("Content-type:text/html;charset=utf-8");        content_type=msg.get('Content-Type','').lower()        pos=content_type.find('charset=')        if(pos>=0):            charset=content_type[pos+8:].strip()    return charsetdef print_info(msg,index=0):    if not index:        for x in ['Subject','From','To']:            value=msg[x]            if value:                if x=='Subject':                    value=decode_header_str(x)                else :                    #邮件的地址可以是这种形式:name<addr@163.com>                    #parseaddr返回name和addr                    name,addr=parseaddr(value)                    name=decode_header_str(name)                    value=u'%s<%s>' % (name,addr)            print('%s%s: %s' % (' '*index,x,value))    if msg.is_multipart():        #get_payload return a list of Message        #get_payload返回这个段中的Message列表        parts=msg.get_payload()        for n,part in enumerate(parts):            print('%spart %d' % (' '*index,n))            print('%s-------------------------' % (' '*index))            print_info(part,index+1)    else:        #get_content_type返回Message的MIME类型        content_type=msg.get_content_type()        if content_type in ['text/plain','text/html']:            content=msg.get_payload(decode=True)            charset=guess_charset(msg)            if charset:                content=content.decode(charset)            print('%sText: %s' % (' '*index,content+'...'))        else:            print('%sAttachment: %s'%(' '*index,content_type))

还有几个地址也解决了我几个问题
python字符串str和字节数组相互转化
header中Content-Disposition的作用与使用方法

1 0