windows下如何用python抓取邮件内容和附件_使用python处理邮件正文及附件

用python接收邮件的功能非常的常见,我也研究了好久,参考了廖雪峰大大的相关教程和网上的一些资源才大概了解了相应的功能。其中好多代码是直接参考(copy)别人的,中文处理方面真的是折磨了我好久。

日常生活中使用QQ邮箱的频率很高,我在这里使用的也是QQ邮箱,像以前的话,QQ邮箱的pop3登录可以直接使用新密码就可以直接登录了,但现在我发现直接使用新设置的密码会报错。

poplib.error_proto: b'-ERR Please using authorized code to login.

因此我只能使用短信的方式获取验证码。

image.png

然后使用之后的授权码当做密码就不会再报错了。

首先是登录邮箱

import poplib

email='392361639@qq.com'

password='授权码'

server=poplib.POP3_SSL('pop.qq.com')

server.user(email)

server.pass_(password)

resp, mails, octets = server.list()

index = len(mails)#邮件的总数

#server.dele(index) 删除邮件 dele可以用于删除制定位置的邮件

resp, lines, octets = server.retr(index)#可以取出最新的邮件的信息

msg_content = b'\r\n'.join(lines).decode('utf-8','ignore') #将邮件组合到一起,生成邮件信息

print(msg_content)

msg_content大致内容.png

可以看到打印出来的msg_content文件信息大致是这样的,里面包含了邮件的头文件,如Date,Subject,From,TO等信息。接下来要取出邮件头部相关的信息。上图的头部信息并没有出现乱码,但有的邮件就会如下图所示

image.png

from email.parser import Parser

from email.header import decode_header

from email.utils import parseaddr#专门处理地址的模块

#email中专门处理邮件内容的模块

msg = Parser().parsestr(msg_content)

#通过msg.get('From')等方法可以获取头部,但会出现编码不对

#通过decode,将Subject其变为中文

def decode_str(s):

value, charset = decode_header(s)[0]

if charset:

value = value.decode(charset)

return value

def get_header(msg):

for header in ['From', 'To', 'Subject']:

value = msg.get(header, '')

if value:

#文章的标题有专门的处理方法

if header == 'Subject':

value = decode_str(value)

elif header in ['From','To']:

#地址也有专门的处理方法

hdr, addr = parseaddr(value)

value = decode_str(addr)

print(header + ':' + value)

头部信息取出后接着去正文内容,由于我平时的需求主要为文本信息或者附件,针对指定邮件获取信息,或者是取出附件,对一些广告邮件就不需要处理(我也不知道如何去处理)

邮件的正文部分处理

#邮件正文部分

#取附件

#邮件的正文部分在生成器中,msg.walk()

#如果存在附件,则可以通过.get_filename()的方式获取文件名称

def get_file(msg):

for part in msg.walk():

filename=part.get_filename()

if filename!=None:#如果存在附件

filename = decode_str(filename)#获取的文件是乱码名称,通过之前定义的函数解码

data = part.get_payload(decode = True)#取出文件正文内容

#此处可以自己定义文件保存位置

path=filename

f = open(path, 'wb')

f.write(data)

f.close()

print(filename,'download')

#接下来取正文信息

#获取邮件的字符编码,首先在message中寻找编码,如果没有,就在header的Content-Type中寻找

def guess_charset(msg):

charset = msg.get_charset()

if charset is None:

content_type = msg.get('Content-Type', '').lower()

pos = content_type.find('charset=')

if pos >= 0:

charset = content_type[pos+8:].strip()

return charset

def get_content(msg):

for part in msg.walk():

content_type = part.get_content_type()

charset = guess_charset(part)

#如果有附件,则直接跳过

if part.get_filename()!=None:

continue

email_content_type = ''

content = ''

if content_type == 'text/plain':

email_content_type = 'text'

elif content_type == 'text/html':

print('html 格式 跳过')

continue #不要html格式的邮件

email_content_type = 'html'

if charset:

try:

content = part.get_payload(decode=True).decode(charset)

#这里遇到了几种由广告等不满足需求的邮件遇到的错误,直接跳过了

except AttributeError:

print('type error')

except LookupError:

print("unknown encoding: utf-8")

if email_content_type =='':

continue

#如果内容为空,也跳过

print(email_content_type + ' ----- ' + content)

#邮件的正文内容就在content中

邮件正文结果

下面附上完整代码

import poplib

#解析邮件

from email.parser import Parser

from email.header import decode_header

from email.utils import parseaddr

#解析消息头中的字符串

#没有这个函数,print出来的会使乱码的头部信息。如'=?gb18030?B?yrXWpL3hufsueGxz?='这种

#通过decode,将其变为中文

def decode_str(s):

value, charset = decode_header(s)[0]

if charset:

value = value.decode(charset)

return value

#解码邮件信息分为两个步骤,第一个是取出头部信息

#首先取头部信息

#主要取出['From','To','Subject']

'''

From: "=?gb18030?B?anVzdHpjYw==?="

To: "=?gb18030?B?ztLX1Ly6tcTTys/k?=" <392361639@qq.com>

Subject: =?gb18030?B?dGV4dMTjusM=?=

'''

#如上述样式,均需要解码

def get_header(msg):

for header in ['From', 'To', 'Subject']:

value = msg.get(header, '')

if value:

#文章的标题有专门的处理方法

if header == 'Subject':

value = decode_str(value)

elif header in ['From','To']:

#地址也有专门的处理方法

hdr, addr = parseaddr(value)

name = decode_str(addr)

#value = name + ' < ' + addr + ' > '

value=name

print(header + ':' + value)

#头部信息已取出

#获取邮件的字符编码,首先在message中寻找编码,如果没有,就在header的Content-Type中寻找

def guess_charset(msg):

charset = msg.get_charset()

if charset is None:

content_type = msg.get('Content-Type', '').lower()

pos = content_type.find('charset=')

if pos >= 0:

charset = content_type[pos+8:].strip()

return charset

#邮件正文部分

#取附件

#邮件的正文部分在生成器中,msg.walk()

#如果存在附件,则可以通过.get_filename()的方式获取文件名称

def get_file(msg):

for part in msg.walk():

filename=part.get_filename()

if filename!=None:#如果存在附件

filename = decode_str(filename)#获取的文件是乱码名称,通过一开始定义的函数解码

data = part.get_payload(decode = True)#取出文件正文内容

#此处可以自己定义文件保存位置

path=filename

f = open(path, 'wb')

f.write(data)

f.close()

print(filename,'download')

def get_content(msg):

for part in msg.walk():

content_type = part.get_content_type()

charset = guess_charset(part)

#如果有附件,则直接跳过

if part.get_filename()!=None:

continue

email_content_type = ''

content = ''

if content_type == 'text/plain':

email_content_type = 'text'

elif content_type == 'text/html':

print('html 格式 跳过')

continue #不要html格式的邮件

email_content_type = 'html'

if charset:

try:

content = part.get_payload(decode=True).decode(charset)

except AttributeError:

print('type error')

except LookupError:

print("unknown encoding: utf-8")

if email_content_type =='':

continue

#如果内容为空,也跳过

print(email_content_type + ' ----- ' + content)

#get_file(msg)

if __name__ == '__main__':

email='392361639@qq.com'

password='ngq*******rznbici'

server=poplib.POP3_SSL('pop.qq.com')

server.user(email)

server.pass_(password)

#登录的过程

resp, mails, octets = server.list()

index = len(mails)#邮件的总数

#此处的循环是取最近的几封邮件

for i in range(index-2,index+1):

resp, lines, octets = server.retr(i)#取邮件

msg_content = b'\r\n'.join(lines).decode('utf-8','ignore')

msg = Parser().parsestr(msg_content)

#server.dele(index) 删除邮件

get_header(msg)

get_file(msg)

get_content(msg)

server.quit()

下面是发送正文及附件,相对读取邮件信息,发送邮件要比读取要简单很多

import smtplib

from email.mime.multipart import MIMEMultipart

from email.mime.text import MIMEText

import os

sender = 'justonezcc@sina.com'

receiver = '392361639@qq.com'

subject = 'python email test'

smtpserver = 'smtp.sina.com'

password = '***'

from email import encoders

msgRoot = MIMEMultipart('alternative')

msgRoot['Subject'] = subject

msgRoot['From'] = sender

msgRoot['To']=receiver

#发送正文

content='你好,这是一封测试邮件'

cont=MIMEText(content,'plain','utf-8')

msgRoot.attach(cont)

#发送附件

file_name='实证结果.xls'#要发送文件的文字

row_path=os.getcwd()#或者其他路径

path=os.path.join(row_path,file_name)

att = MIMEText(open(path, 'rb').read(), 'base64', 'gb2312')

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

att.add_header('Content-Disposition', 'attachment', filename=('gb2312', '', file_name))

msgRoot.attach(att)

smtp = smtplib.SMTP()

smtp.connect(smtpserver)

smtp.login(sender, password)

smtp.sendmail(sender, receiver, msgRoot.as_string())

smtp.quit()

好的,这是一个比较复杂的任务,需要使用Python中的一些库来实现。以下是一个大致的实现思路: 1. 使用Python中的openpyxl库读取Excel文件,并抓取网址和jira代号。 2. 使用Python中的正则表达式或者BeautifulSoup库来解析网址,获取目标jira代号。 3. 使用openpyxl库将抓取到的jira代号写入Excel文件中。 4. 使用Python中的smtplib库连接到邮件服务器,并使用email库构建邮件,将Excel文件作为附件发送。 下面是一份大致的代码实现,需要根据具体需求进行适当修改和调整: ```python import openpyxl import re import smtplib from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email.mime.text import MIMEText from email import encoders # 邮件发送配置 mail_sender = 'sender@example.com' mail_password = 'password' mail_receiver = 'receiver@example.com' mail_subject = 'Excel中的jira代号' mail_body = '请查收附件' # 打开Excel文件 wb = openpyxl.load_workbook('example.xlsx') ws = wb.active # 抓取网址和jira代号 for row in ws.iter_rows(min_row=2, values_only=True): url = row[0] jira = re.findall(r'[A-Z]{2,}-\d+', url) if jira: row[1] = jira[0] # 保存Excel文件 wb.save('example.xlsx') # 发送邮件 msg = MIMEMultipart() msg['From'] = mail_sender msg['To'] = mail_receiver msg['Subject'] = mail_subject msg.attach(MIMEText(mail_body, 'plain')) attachment = open('example.xlsx', 'rb') p = MIMEBase('application', 'octet-stream') p.set_payload((attachment).read()) encoders.encode_base64(p) p.add_header('Content-Disposition', "attachment; filename= example.xlsx") msg.attach(p) s = smtplib.SMTP('smtp.gmail.com', 587) s.starttls() s.login(mail_sender, mail_password) text = msg.as_string() s.sendmail(mail_sender, mail_receiver, text) s.quit() ``` 这份代码中使用了正则表达式来抓取jira代号,如果Excel中的网址和jira代号的格式不规范,可能会出现抓取不到jira代号的情况。另外,邮件发送的配置需要根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值