qq邮件相关
1.正文带图片
# 导入相关模块
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
# 定义一个函数,用于发邮件和发图片,用qq邮箱发送,图片在正文显示
def send_email_with_image(sender, password, receiver, subject, content, image_file):
"""
sender: 发件人邮箱
password: 发件人邮箱密码或授权码
receiver: 收件人邮箱
subject: 邮件主题
content: 邮件内容
image_file: 图片文件名
"""
# 创建一个带附件的邮件实例
msg = MIMEMultipart()
msg["From"] = sender # 设置发件人
msg["To"] = receiver # 设置收件人
msg["Subject"] = subject # 设置主题
# 创建邮件正文,使用HTML格式,并插入邮件内容和图片
body = f"""
<p>{content}</p>
<p>Here is the image:</p>
<p><img src="cid:image1"></p>
"""
msg.attach(MIMEText(body, "html")) # 将正文添加到邮件实例中
# 指定图片文件的路径,打开并读取为二进制数据
fp = open(image_file, "rb")
img = MIMEImage(fp.read())
fp.close()
# 定义图片的ID,在HTML文本中引用
img.add_header("Content-ID", "<image1>")
msg.attach(img) # 将图片添加到邮件实例中
# 创建一个SMTP对象,连接到QQ邮箱的服务器
smtp = smtplib.SMTP_SSL("smtp.qq.com", 465)
smtp.login(sender, password) # 登录发件人邮箱
smtp.sendmail(sender, receiver, msg.as_string()) # 发送邮件
smtp.quit() # 退出SMTP对象
print("Email sent successfully.") # 打印发送成功的提示信息
# 调用函数,传入相应的参数
send_email_with_image("your_qq_email@qq.com", "your_qq_email_password", "someone_email@domain.com", "This is a test email with image", "Hi, this is a test email with image.", "test.jpg")
2.删除邮件
import imaplib
import email # 虽然在这个删除场景中email库不是必须的,但引入是标准做法
def delete_emails_combined(EMAIL_ACCOUNT, PASSWORD, inbox_subject_keyword=None):
"""
连接邮箱,删除收件箱中主题包含指定关键词的邮件,
并删除发件箱中的所有邮件。
Args:
EMAIL_ACCOUNT (str): 邮箱账号。
PASSWORD (str): 邮箱的IMAP授权码。
inbox_subject_keyword (str, optional): 收件箱邮件主题中需要匹配的关键词。
如果为None或空字符串,则不删除收件箱邮件。
"""
# QQ邮箱的IMAP服务器信息
IMAP_SERVER = 'imap.qq.com'
IMAP_PORT = 993
mail = None # 初始化 mail 对象为 None
try:
# 连接到IMAP服务器
print(f"正在连接到 {IMAP_SERVER}:{IMAP_PORT}...")
mail = imaplib.IMAP4_SSL(IMAP_SERVER, IMAP_PORT)
print("连接成功.")
# 登录到邮箱
print(f"尝试登录邮箱账户: {EMAIL_ACCOUNT}...")
# mail.login() 返回状态和响应数据
login_status, login_response = mail.login(EMAIL_ACCOUNT, PASSWORD)
print(f"登录状态: {login_status}, 响应: {login_response}")
if login_status != 'OK':
print("登录失败. 请检查邮箱账号和授权码是否正确.")
# 如果需要,可以打印更详细的登录失败响应
# print(f"登录响应详情: {login_response}")
return # 登录失败,停止执行
print("登录成功.")
# --- 处理收件箱邮件 ---
if inbox_subject_keyword:
print(f"\n--- 正在处理收件箱,查找主题包含 '{inbox_subject_keyword}' 的邮件 ---")
try:
# 选择收件箱
print("正在选择 'inbox' 文件夹...")
status, mail_count_inbox = mail.select('inbox')
print(f"选择 Inbox 状态: {status}")
if status == 'OK':
# 搜索所有标题包含指定关键词的邮件
# 搜索条件需要编码为 bytes
search_criteria = f'(SUBJECT "{inbox_subject_keyword}")'.encode('utf-8')
print(f"正在搜索条件: {search_criteria}...")
status, data = mail.search(None, search_criteria)
print(f"搜索状态: {status}, 数据长度: {len(data[0]) if data and data[0] else 0}")
if status == 'OK' and data[0]:
# 获取邮件ID列表
mail_ids_bytes = data[0]
mail_ids = mail_ids_bytes.split()
print(f"找到 {len(mail_ids)} 封邮件符合条件.")
# 删除邮件
deleted_count = 0
print("正在标记收件箱邮件以删除...")
for mail_id in mail_ids:
# 标记 \Deleted flag
store_status, _ = mail.store(mail_id, '+FLAGS', '\\Deleted')
if store_status == 'OK':
deleted_count += 1
# else: print(f"标记收件箱邮件 ID {mail_id} 失败. Status: {store_status}") # 可选,如果想看每个失败的标记
# 永久删除标记为删除的邮件
if deleted_count > 0:
print(f"已标记 {deleted_count} 封收件箱邮件. 正在执行永久删除 (Expunge)...")
expunge_status, expunge_response = mail.expunge()
print(f"Expunge 状态: {expunge_status}")
if expunge_status == 'OK':
print(f"成功从收件箱中永久删除了 {deleted_count} 封邮件.")
else:
print("收件箱 Expunge 操作失败.")
else:
print("没有收件箱邮件被标记删除.")
elif status == 'OK' and not data[0]:
print("收件箱搜索成功,但没有找到符合条件的邮件.")
else:
print(f"收件箱搜索失败. 状态: {status}")
else:
print("未能选择 'inbox' 文件夹.")
except Exception as e:
print(f"处理收件箱时发生错误: {e}")
# 可以选择在这里调用 mail.unselect(),或者依赖下次 select 自动取消选择
else:
print("\n--- 未指定收件箱关键词,跳过收件箱处理 ---")
# --- 处理发件箱邮件 ---
print("\n--- 正在处理发件箱,删除所有邮件 ---")
try:
# 定义可能的发件箱文件夹名称列表
# 注意:文件夹名称需要用双引号或单引号包围,这里使用双引号因为IMAP协议要求
sent_folders_to_try = ['"Sent Messages"', '"已发送"']
selected_folder_name = None
# 尝试选择发件箱文件夹
print("正在尝试选择发件箱文件夹...")
for folder_name in sent_folders_to_try:
print(f"尝试选择文件夹: {folder_name}...")
# mail.select() 返回状态和文件夹内的邮件数量信息
status, mail_count_data = mail.select(folder_name)
# print(f"选择文件夹 {folder_name} 的状态: {status}, 邮件数量信息: {mail_count_data}") # 可选,如果想看详细信息
if status == 'OK':
selected_folder_name = folder_name
print(f"成功选择发件箱文件夹: {selected_folder_name}")
break # 找到并选中了文件夹,不再尝试其他名称
if selected_folder_name:
# 搜索所有邮件 (因为要删除全部)
print(f"正在搜索 '{selected_folder_name}' 中的所有邮件...")
status, data = mail.search(None, "ALL")
print(f"搜索状态: {status}, 数据长度: {len(data[0]) if data and data[0] else 0}")
if status == 'OK' and data[0]: # 检查状态是否OK且数据非空
mail_ids_bytes = data[0] # data[0] 是 bytes 类型,包含所有邮件ID,用空格分隔
mail_ids = mail_ids_bytes.split() # 转换为列表
print(f"找到 {len(mail_ids)} 封发件箱邮件需要删除.")
deleted_count = 0
print("正在标记发件箱邮件以删除...")
# 通过标记 \Deleted flag 来删除邮件
for mail_id in mail_ids:
store_status, _ = mail.store(mail_id, '+FLAGS', '\\Deleted')
# print(f"标记发件箱邮件 ID {mail_id} 状态: {store_status}") # 可选,如果邮件很多,这个会非常冗余
if store_status == 'OK':
deleted_count += 1
# else: print(f"标记发件箱邮件 ID {mail_id} 失败. Status: {store_status}") # 可选
# 永久删除标记为删除的邮件
if deleted_count > 0:
print(f"已标记 {deleted_count} 封发件箱邮件. 正在执行永久删除 (Expunge)...")
expunge_status, expunge_response = mail.expunge()
print(f"Expunge 状态: {expunge_status}")
if expunge_status == 'OK':
print(f"成功从 '{selected_folder_name}' 中永久删除了 {deleted_count} 封邮件.")
else:
print("发件箱 Expunge 操作失败.")
else:
print("没有发件箱邮件被标记删除.")
elif status == 'OK' and not data[0]:
print("发件箱搜索成功,但在选定的文件夹中没有找到任何邮件.")
else:
print(f"发件箱搜索操作失败. 状态: {status}")
else:
print("未能选择任何已知的发件箱文件夹. 请检查文件夹名称.")
# 可选:列出所有可用文件夹,帮助诊断
# print("尝试列出所有可用文件夹...")
# status_list, folder_list_data = mail.list()
# if status_list == 'OK':
# print("可用的文件夹列表:")
# for folder_info in folder_list_data:
# print(f" {folder_info}") # 文件夹信息格式可能复杂,需要解析
except Exception as e:
print(f"处理发件箱时发生错误: {e}")
except imaplib.IMAP4.error as e:
print(f"发生 IMAP 错误: {e}")
except Exception as e:
print(f"发生未知错误: {e}")
finally:
# 关闭连接并退出登录
if mail:
try:
mail.close()
print("\n连接已关闭.")
except Exception as e:
print(f"关闭连接时出错: {e}")
try:
mail.logout()
print("已退出登录.")
except Exception as e:
print(f"退出登录时出错: {e}")
print("\n所有指定的删除过程结束.")
# --- 示例用法 ---
# 请替换为您的实际邮箱账号和授权码
# 注意:PASSWORD 必须是授权码!不是登录密码!
your_email = "你的QQ邮箱账号@qq.com"
your_password = "你的QQ邮箱授权码" # <<<<<< 请务必替换为授权码!
# 要删除的收件箱邮件主题关键词 (如果不需要删除收件箱,可以将这个设置为 None 或 "")
inbox_keyword_to_delete = "adb连接失败"
# 调用合并后的函数
delete_emails_combined(your_email, your_password, inbox_subject_keyword=inbox_keyword_to_delete)
# 如果只需要删除发件箱全部邮件,收件箱关键词设为None
# delete_emails_combined(your_email, your_password, inbox_subject_keyword=None)
# 如果只需要删除收件箱特定邮件,不删除发件箱,可以在函数内部注释掉发件箱处理部分
代码说明:
- 函数签名变化: 函数
delete_emails_combined
现在接受三个参数:邮箱账号、授权码,以及一个可选的inbox_subject_keyword
参数,用于指定收件箱要删除的邮件主题关键词。 - 登录只执行一次: 连接和登录逻辑被放在了函数开头,确保只需要登录一次。
- 分别处理: 代码被分成了两个主要部分:处理收件箱和处理发件箱。
- 收件箱处理:
- 只有当
inbox_subject_keyword
参数被提供(不是None
或空字符串)时,才会执行收件箱删除逻辑。 - 选择 'inbox' 文件夹。
- 使用提供的关键词进行搜索。
- 标记并删除找到的邮件。
- 只有当
- 发件箱处理:
- 这部分逻辑与您原先的
delete_mail_sent
函数类似,尝试选择"Sent Messages"
或"已发送"
文件夹。 - 搜索该文件夹内的所有邮件 (
"ALL"
)。 - 标记并删除找到的所有邮件。
- 这部分逻辑与您原先的
- 错误处理和打印: 代码保留并增强了错误处理 (
try...except
) 和详细的打印输出,帮助您诊断问题出在哪里(登录失败、选择文件夹失败、搜索失败、找不到邮件等)。 finally
块: 使用finally
块确保无论是否发生错误,都会尝试关闭邮箱连接 (mail.close()
) 和退出登录 (mail.logout()
)。- 授权码: 再次强调,
PASSWORD
参数必须是QQ邮箱的IMAP 授权码,不是您的QQ密码或邮箱登录密码。
使用这个合并后的函数,传入您的邮箱账号、授权码以及您想删除的收件箱关键词(如果不删除收件箱,就传入 None
),就可以执行这两个任务了。如果遇到问题,请查看打印输出的错误信息。
本文作者: 永生
本文链接: https://yys.zone/detail/?id=284
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!
评论列表 (0 条评论)