python与POP3

邮件由三部分组成:信封,邮件头,邮件体
信封显然可以不含有二进制信息,而其它两部分则可能包含任意二进制序列,因此需要加以改进。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,poplib
from time import sleep
from email.mime.text import MIMEText
from email import encoders
from email.header import Header
from email import parser
import email
from email.header import decode_header
from DecodeEmail import print_info
from email.utils import parseaddr,formataddr


def 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.
enheng
You 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 email
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr

def decode_header_str(s):
    #decode_header解析头部字符串,返回一个list,包含字符串的值和编码方式
    value,charset=decode_header(s)[0]
    if charset:
        value=value.decode(charset)
    return value
def 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 charset

def 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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值