Python 之 Email 库详解
Python 标准库中提供了强大的 email
模块,可以帮助我们轻松地处理电子邮件。本文将详细介绍如何使用 Python 的 email
库来创建、解析和发送电子邮件。
一、安装与导入
首先,email
库是 Python 标准库的一部分,因此无需额外安装。我们可以直接导入所需的模块:
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
二、创建电子邮件
使用 email
模块,我们可以创建简单的文本邮件、包含附件的邮件等。
1. 创建简单文本邮件
以下代码展示了如何创建一个简单的文本电子邮件:
# 设置邮件内容
msg = MIMEText('这是邮件的正文内容', 'plain', 'utf-8')
# 设置邮件主题、发件人、收件人
msg['Subject'] = '邮件主题'
msg['From'] = 'your_email@example.com'
msg['To'] = 'recipient_email@example.com'
2. 创建包含附件的邮件
如果我们需要发送包含附件的邮件,可以使用 MIMEMultipart
组合多个部分:
# 创建MIMEMultipart对象
msg = MIMEMultipart()
msg['Subject'] = '带附件的邮件'
msg['From'] = 'your_email@example.com'
msg['To'] = 'recipient_email@example.com'
# 邮件正文
body = MIMEText('这是带附件的邮件的正文部分', 'plain', 'utf-8')
msg.attach(body)
# 添加附件
filename = 'example.pdf'
with open(filename, 'rb') as attachment:
part = MIMEBase('application', 'octet-stream')
part.set_payload(attachment.read())
# 编码附件
encoders.encode_base64(part)
part.add_header('Content-Disposition', f'attachment; filename={filename}')
msg.attach(part)
三、发送电子邮件
创建好电子邮件后,我们需要使用 smtplib
模块发送邮件。
# 连接到SMTP服务器
smtp_server = 'smtp.example.com'
smtp_port = 587
username = 'your_email@example.com'
password = 'your_password'
with smtplib.SMTP(smtp_server, smtp_port) as server:
server.starttls() # 启用TLS加密
server.login(username, password)
server.sendmail(msg['From'], msg['To'], msg.as_string())
四、解析电子邮件
除了创建和发送邮件,我们还可以使用 email
模块来解析收到的电子邮件。
class EmailUtil:
"""
Email公共方法
"""
imap = None
def __init__(self, host, port):
"""
初始化方法
:param host: 域名
:param port: 端口
"""
self.host = host
self.port = port
self.imap = imaplib.IMAP4_SSL(host=self.host, port=int(self.port))
def login(self, username, password):
"""
登录邮箱
:param username: 用户名
:param password: 密码
:return:
"""
self.username = username
self.password = password
self.imap.login(user=self.username, password=self.password)
def get_unsee_mail(self):
"""
获取未读邮件ID
:return:
"""
self.imap.select("inbox", readonly=False)
result, email_ids = self.imap.search(None, 'UNSEEN')
email_ids = email_ids[0].split()
return email_ids
def get_all_mail(self):
"""
获取所有邮件ID
:return:
"""
self.imap.select("inbox", readonly=False)
# 搜索电子邮件
status, email_ids = self.imap.search(None, "ALL")
email_ids = email_ids[0].split()
return email_ids
def get_email_content(self, num):
# 通过邮件编号获取邮件内容
typ1, msg_data = self.imap.fetch(num, "(RFC822)")
raw_email = msg_data[0][1]
if typ1 == 'OK':
# 将原始的邮件数据解析为邮件对象
msg = email.message_from_bytes(raw_email)
print(msg)
# 解析并打印邮件的各个部分
# 获取邮件的发件人
sender = msg['From']
# 解析发件人字符串以获取电子邮件地址和显示名称
realname, email_address = parseaddr(sender)
sender = email_address
print(realname,email_address)
if realname:
decoded_realname, charset = decode_header(realname)[0]
if charset:
realname = decoded_realname.decode(charset)
else:
realname = decoded_realname # 如果charset为None,则可能是字节串或已经是str
print('From:', email_address)
if realname:
print('Display Name:', realname)
# 获取邮件的收件人
to = msg['To']
to, charset = decode_header(to)[0]
if charset:
to = to.decode(charset)
print('To:', to)
# 获取邮件的主题
if 'Subject' in msg:
subject, encoding = decode_header(msg['Subject'])[0]
if encoding:
subject = subject.decode(encoding, errors='replace')
else:
subject = ''
print('Subject:', subject)
# 获取邮件的日期
email_date = msg['Date']
print("email_date", email_date)
# 使用email.utils解析日期字符串和时间区信息
parsed_date = email.utils.parsedate_tz(email_date)
# 检查是否解析成功
if parsed_date is not None:
# 提取日期和时间信息(不包括时区)
time_tuple = parsed_date[:9]
# 创建一个naive datetime对象(即没有时区信息的datetime对象)
naive_dt = datetime(*time_tuple[:6])
naive_dt = naive_dt.replace(microsecond=time_tuple[6])
# 提取时区偏移量(单位为秒)
tz_offset = parsed_date[9]
# 创建一个带有时区信息的datetime对象
aware_dt = naive_dt.replace(tzinfo=timezone(timedelta(seconds=tz_offset)))
# 转换到上海时区
shanghai_tz = pytz.timezone('Asia/Shanghai')
shanghai_dt = aware_dt.astimezone(shanghai_tz).strftime("%Y-%m-%d %H:%M:%S")
# 打印上海时区的时间
print(shanghai_dt)
else:
print("无法解析日期字符串")
print('Date:', shanghai_dt)
# 初始化一个字符串来保存按顺序拼接的内容
pure_text_content = ""
# 遍历邮件的所有部分(包括附件)
for part in msg.walk():
# 忽略附件
if part.get_content_type() == 'multipart':
continue
# elif part.get_content_type()=='image/jpeg':
# print("该内容是图片")
# 如果是文本部分
elif part.get_content_type() == 'text/plain':
body = part.get_payload(decode=True)
pure_text_content += body.decode('utf-8', errors='replace')
# print('Text body:', body.decode('utf-8',errors='replace'))
# 如果是HTML部分
elif part.get_content_type() == 'text/html':
body = part.get_payload(decode=True)
if part.get('Content-Transfer-Encoding') == 'base64':
body = body.decode('utf-8')
soup = BeautifulSoup(body, 'html.parser')
if soup.find('body'):
body_tag = soup.body
# 遍历 <body> 标签的所有子节点
for child in body_tag.contents:
# 检查 child 是否是 NavigableString(即文本节点)
if isinstance(child, NavigableString):
# 去除字符串前后的空白字符并添加到拼接字符串中
stripped_text = child.strip()
if stripped_text:
if stripped_text not in pure_text_content:
pure_text_content += stripped_text
# 检查 child 是否是 Tag 并且标签名为 'div'
elif isinstance(child, Tag) and child.name == 'div':
# 如果是 div 标签,获取其内部的纯文本内容并添加到拼接字符串中
if child.get_text(strip=True) not in pure_text_content:
pure_text_content += child.get_text(strip=True)
pure_text_content += "\n"
# 如果 div 后面紧跟着文本节点,可能需要添加换行或空格来分隔内容
# 这里可以根据你的需求决定是否添加
else:
for div in soup.find_all('div'):
# 提取<div>的内容(只提取文本内容,不包括标签)
if div.get_text(strip=True,
separator=" ") not in pure_text_content:
pure_text_content += div.get_text(strip=True,
separator=" ") # strip=True去除每段文本前后的空白,separator指定文本间的分隔符
# 将当前<div>的内容添加到总字符串中
pure_text_content += "\n" # 可以根据需要添加换行符或其他分隔符
print("邮件内容:", pure_text_content)
# 检查邮件标志
_, flags_data = self.imap.fetch(num, '(FLAGS)')
flags = flags_data[0].decode('utf-8')
# 检查邮件是否已读(\Seen)和是否已回复(\Answered)
print(flags)
if '\Answered' in flags:
email_status = 'Answered'
elif '\Seen' in flags:
email_status = 'Seen'
else:
email_status = 'Unseen'
print(email_status)
return num, sender, to, shanghai_dt, subject, pure_text_content,email_status
五、总结
Python 的 email
库提供了丰富的功能,可以帮助我们轻松地创建、发送和解析电子邮件。通过本文的介绍,希望大家能够更好地理解和使用这个强大的工具。无论是简单的文本邮件,还是复杂的带附件的邮件,都可以通过 email
库轻松实现。
如果你对本文有任何疑问或建议,欢迎在评论区留言讨论。