Python实现QQ邮箱收发功能(简单易懂)

前言:

关于代码中:

sender_email = 'XXXX@qq.com'   #这个就是你的邮箱地址,不多说了
password = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX' #在QQ邮箱设置里拿到的码,自己去查.需要手机发信息过去,0.1/RMB一个;为期大概一个月!

1.发送邮箱:

import smtplib
from email.mime.text import MIMEText
from email.header import Header

# 邮件内容
subject = '邮件主题'
body = '邮件正文'

# 构建邮件
msg = MIMEText(body, 'plain', 'utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = 'XXXX@qq.com'
msg['To'] = 'XXXX@qq.com'

# 发送邮件
smtp_server = 'smtp.qq.com'
smtp_port = 587
sender_email = 'XXXX@qq.com'
password = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXX' #在QQ邮箱设置里拿到的码

try:
    with smtplib.SMTP(smtp_server, smtp_port) as server:
        server.starttls()
        server.login(sender_email, password)
        server.sendmail(sender_email, [msg['To']], msg.as_string())
    print('邮件发送成功')
except smtplib.SMTPException as e:
    print('邮件发送失败:', str(e))

2.接收邮箱—(打印发件人/主题,解决收件人乱码问题)

import base64
import poplib
from email.parser import BytesParser
import email.header as jiexi
import re

#这个代码会检查邮件发件人,如果发件人存在,才会进行解析和输出,否则将直接跳过邮件。并且我改变了邮件解析的方法,使用了email.header.decode_header函数来解析邮件的头部信息和主题。

# 连接到POP3服务器
pop_server = poplib.POP3_SSL('pop.qq.com', 995)
pop_server.user('xxxx@qq.com')
pop_server.pass_('xxxxxxxxxx')

# 获取邮箱中的邮件信息
num_emails = len(pop_server.list()[1])

# 遍历每封邮件
for i in range(num_emails):
    # 获取邮件内容
    response, lines, octets = pop_server.retr(i + 1)
    email_content = b'\r\n'.join(lines)

    # 解析邮件内容
    email_parser = BytesParser()
    email = email_parser.parsebytes(email_content)

    # 解析邮件头部信息
    email_from = email.get('From').strip()
    email_from = str(jiexi.make_header(jiexi.decode_header(email_from)))

    if email_from:  # 只处理存在发件人的邮件
        # 解析邮件主题
        subject = email.get('Subject').strip()
        decoded_subject = str(jiexi.make_header(jiexi.decode_header(subject))) if subject else None

        print("------------------")
        print("From:", email_from)
        print("Subject:", decoded_subject)
    else:
        continue  # 跳过缺失发件人的邮件

# 关闭连接
pop_server.quit()

3.接收邮箱v02—(打印出邮件的正文body部分)

import poplib
from email import policy
from email.parser import BytesParser
from email.header import decode_header, make_header

#在这段代码中,我定义了一个函数get_html_payload()来提取邮件的payload。
# 如果邮件的主题是多部分的(即包含多个部分,例如文本和HTML),那么我们会遍历每个部分,
# 找出HTML部分并返回。如果邮件主题只有一个部分且是HTML,则直接返回该部分。如果没有合适的部分,
# 那么函数将返回None。
def get_html_payload(email_message):
    if email_message.is_multipart():
        for part in email_message.iter_parts():
            content_type = part.get_content_type()
            if content_type == 'text/html':
                return part.get_content()
            else:
                continue
    elif email_message.get_content_type() == 'text/html':
        return email_message.get_content()

# 连接到POP3服务器
pop_server = poplib.POP3_SSL('pop.qq.com', 995)
pop_server.user('xxxxxx@qq.com')
pop_server.pass_('xxxxxxx')

# 获取邮箱中的邮件信息
num_emails = len(pop_server.list()[1])

# 遍历每封邮件
for i in range(num_emails):
    # 获取邮件内容
    response, lines, octets = pop_server.retr(i + 1)
    email_content = b'\r\n'.join(lines)

    # 解析邮件内容
    email_parser = BytesParser(policy=policy.default)
    email = email_parser.parsebytes(email_content)

    # 解析邮件头部信息
    email_from = email.get('From').strip()
    email_from = str(make_header(decode_header(email_from)))
    if email_from:  # 只处理存在发件人的邮件
        # 解析邮件主题
        subject = email.get('Subject').strip()
        decoded_subject = str(make_header(decode_header(subject))) if subject else None

        # 提取邮件正文
        email_body = get_html_payload(email)
        print("------------------")
        print("From:", email_from)
        print("Subject:", decoded_subject)
        print("Body:", email_body)
    else:
        continue  # 跳过缺失发件人的邮件

# 关闭连接
pop_server.quit()

4.接收邮箱v03—(打印出邮件的正文body部分,并分类存文件到目录,以html/图片/text分类)

import os
import base64
import poplib
from email import policy
from email.parser import BytesParser
from email.header import decode_header, make_header


def sanitize_folder_name(name):
    #清理邮箱地址,移除或替换那些非法字符
    invalid_characters = "<>:\"/\\|?*@"
    for char in invalid_characters:
        name = name.replace(char, "_")
    return name


def get_payload(email_message):
    #------------------解析正文-------------------
    # 我在循环中使用了这个新的信息,根据正文的类型执行不同的操作。对于纯文本类型,它只打印正文;
    # 对于html和image类型,它创建一个目录(如果还不存在),然后将正文写入一个文件。对于image,
    # 我还添加了一个把数据从base64格式解码回二进制格式的步骤,这是因为图片通常会以base64格式存储在邮件中。
    if email_message.is_multipart():
        for part in email_message.iter_parts():
            content_type = part.get_content_type()
            if content_type == 'text/html':
                return part.get_content(), 'html'
            elif content_type == 'text/plain':
                return part.get_content(), 'text'
            elif content_type.startswith('image/'):
                return part.get_content(), 'image', part.get_content_type().split('/')[-1]
            else:
                continue
    elif email_message.get_content_type() == 'text/html':
        return email_message.get_content(), 'html'
    elif email_message.get_content_type() == 'text/plain':
        return email_message.get_content(), 'text'


# 连接到POP3服务器
pop_server = poplib.POP3_SSL('pop.qq.com', 995)
pop_server.user('xxxx@qq.com')
pop_server.pass_('xxxxxx')

# 获取邮箱中的邮件信息
num_emails = len(pop_server.list()[1])

# 遍历每封邮件
for i in range(num_emails):
    # 获取邮件内容
    response, lines, octets = pop_server.retr(i + 1)
    email_content = b'\r\n'.join(lines)

    # 解析邮件内容
    email_parser = BytesParser(policy=policy.default)
    email = email_parser.parsebytes(email_content)

    # 解析邮件头部信息
    email_from = email.get('From').strip()
    email_from = str(make_header(decode_header(email_from)))
    if email_from:  # 只处理存在发件人的邮件
        # 解析邮件主题
        subject = email.get('Subject').strip()
        decoded_subject = str(make_header(decode_header(subject))) if subject else None

        # 提取邮件正文
        email_body, body_type, *extras = get_payload(email)

        # 创建安全的文件夹名和文件名
        safe_folder_name = sanitize_folder_name(email_from)
        safe_subject = sanitize_folder_name(decoded_subject)

        print("------------------")
        print("From:", email_from)
        print("Subject:", decoded_subject)
        print("Body Type:", body_type)

        # 根据正文类型处理
        if body_type == 'text':
            print("Body:", email_body)
        elif body_type == 'html':
            directory = safe_folder_name
            if not os.path.exists(directory):
                os.makedirs(directory)
            with open(f'{directory}/{safe_subject}.html', 'w') as f:
                f.write(email_body)
        elif body_type == 'image':
            directory = safe_folder_name
            if not os.path.exists(directory):
                os.makedirs(directory)
            image_data = base64.b64decode(email_body)
            image_extension = extras[0]  # Get the image extension
            with open(f'{directory}/{safe_subject}.{image_extension}', 'wb') as f:
                f.write(image_data)
    else:
        continue  # 跳过缺失发件人的邮件

# 关闭连接
pop_server.quit()

5.接收邮箱v04–(接收指定的邮箱,并把它封装好!完整版,可直接使用)

import os
import base64
import poplib
from email import policy
from email.parser import BytesParser
from email.header import decode_header, make_header


# 定义EmailClient类,用于连接到POP3服务器并从指定的邮件地址获取邮件
class EmailClient:
    # 在初始化函数中,设置POP3服务器的来源、用户、密码和待查询的目标邮件地址
    def __init__(self, host, user, password, target_email):
        self.pop_server = poplib.POP3_SSL(host)  # 使用POP3协议通过SSL安全连接到邮件服务器
        self.pop_server.user(user)  # 输入用户邮箱
        self.pop_server.pass_(password)  # 输入用户邮箱密码
        self.target_email = target_email  # 输入待查询的目标邮件地址

    # 定义一个函数,用以清除文件名中的无效字符
    def sanitize_folder_name(self, name):
        invalid_characters = "<>:\"/\\|?*@"
        for char in invalid_characters:  # 遍历所有无效字符
            name = name.replace(char, "_")  # 将无效字符替换为下划线
        return name  # 返回清理后的名称

    # 定义一个函数,用以提取邮件的payload(有效载荷,即邮件主体内容)
    def get_payload(self, email_message):
        if email_message.is_multipart():  # 判断邮件是否为多部分邮件
            for part in email_message.iter_parts():  # 如果是,则遍历其中的每一部分
                content_type = part.get_content_type()  # 获取该部分的内容类型
                if content_type == 'text/html':  # 如果内容类型为HTML,则返回该部分内容
                    return part.get_content()
                elif content_type == 'text/plain':  # 如果内容类型为纯文本,则返回该部分内容
                    return part.get_content()
        elif email_message.get_content_type() == 'text/html':  # 如果邮件非多部分形式,且为HTML类型,则返回邮件内容
            return email_message.get_content()
        elif email_message.get_content_type() == 'text/plain':  # 如果邮件非多部分形式,且为纯文本类型,则返回邮件内容
            return email_message.get_content()

    # 定义一个函数,用以获取邮件信息
    def fetch_email(self):
        num_emails = len(self.pop_server.list()[1])  # 获取邮箱内的邮件数量

        # 遍历每一封邮件
        for i in range(num_emails):
            # 获取邮件内容
            response, lines, octets = self.pop_server.retr(i + 1)  # retr函数返回指定邮件的全部文本
            email_content = b'\r\n'.join(lines)  # 将所有行连接成一个bytes对象

            # 解析邮件内容
            email_parser = BytesParser(policy=policy.default)  # 创建一个邮件解析器
            email = email_parser.parsebytes(email_content)  # 解析邮件内容,返回一个邮件对象

            # 解析邮件头部信息并提取发件人信息
            email_from = email.get('From').strip()  # 获取发件人信息,并去除尾部的空格
            email_from = str(make_header(decode_header(email_from)))  # 解码发件人信息,并将其转换为字符串
            if email_from == self.target_email:  # 如果发件人地址与指定的目标邮件地址一致,对邮件进行处理
                # 解析邮件时间
                email_time = email.get('Date')  # 获取邮件时间

                # 提取邮件正文
                email_body = self.get_payload(email)  # 获取邮件正文

                return email_body, email_time  # 返回邮件正文和时间

        print("No new emails from", self.target_email)  # 如果没有从目标邮件地址收到新邮件,打印相应信息
        return None, None  # 返回None

——-封装他————

from shou_self import EmailClient
client = EmailClient('pop.qq.com', '你的邮箱', '邮箱提取出的密码', '需要针对的目标邮箱')
body, time = client.fetch_email()
print("Time:", time)
print("Body:", body)

物联沃分享整理
物联沃-IOTWORD物联网 » Python实现QQ邮箱收发功能(简单易懂)

发表评论