gmail添加附件

This commit is contained in:
wanjia 2025-04-07 15:07:20 +08:00
parent b64af631e3
commit 083971a94a
5 changed files with 171 additions and 36 deletions

View File

@ -0,0 +1,10 @@
本期节目内容简介
在参加各类比赛时,肯定会遇到竞争对手。英语单词 rival、opponent、competitor 和 contestant 的含义相似,都可以用来指“与他人之间存在竞争关系的人或团队”。在本集《你问我答》节目中,我们将通过和体育比赛有关的实例来为大家阐释这四个近义词之间的区别和用法。
欢迎你加入并和我们一起讨论英语学习的方方面面。请通过微博“BBC英语教学”或邮件与我们取得联系。我们的邮箱地址是 questions.chinaelt@bbc.co.uk。
文字稿
(关于台词的备注: 请注意这不是广播节目的逐字稿件。本文稿可能没有体现录制、编辑过程中对节目做出的改变。)
Feifei
大家好,欢迎收听 BBC 英语教学的《你问我答》节目,我是冯菲菲。每集节目中,我们会回答大家在英语学习时遇到的一个问题。本集的问题来自 Adela。我们来听一下她的问题。

View File

@ -1,20 +1,41 @@
[
{
"id": "195d5c6094b7e85f",
"subject": "这是主题",
"from": "crush wds <ardonisierni@gmail.com>",
"date": "2025-03-27 12:04:29",
"body": "你好呀\r\n"
"body": "你好呀\r\n",
"attachments": []
},
{
"id": "195d5c72dbafcc13",
"subject": "",
"from": "wds crush <crushwds@gmail.com>",
"date": "2025-03-27 12:05:54",
"body": "你那里天气怎么样\r\n"
"body": "你那里天气怎么样\r\n",
"attachments": []
},
{
"id": "195d604a5ad5fabf",
"subject": "",
"from": "wds crush <crushwds@gmail.com>",
"date": "2025-03-27 13:13:03",
"body": "吃饭了吗\r\n"
"body": "吃饭了吗\r\n",
"attachments": []
},
{
"id": "1960eec066745682",
"subject": "Re: 这是主题",
"from": "wds crush <crushwds@gmail.com>",
"date": "2025-04-07 14:24:28",
"body": "测试附件内容\r\n\r\n\r\ncrush wds <ardonisierni@gmail.com> 于2025年3月27日周四 12:04写道\r\n\r\n> 你好呀\r\n>\r\n",
"attachments": [
{
"filename": "test2.txt",
"mimeType": "text/plain",
"size": 996,
"attachmentId": "ANGjdJ-f7-vJBk-5aJnh1zPE0rwbH0PXFzJHsXv9XL5LavJ0r4yQAayw1dw1pQ0AUhgwWyTP_hxcROnZO2C5W3MhBGGFmrcVpjwWE-yFr5BYA-I1-6sn24oEPFqX8Hem4dZxcYd2h6RgSfUfq3BqOe0AtZru0GWvUxRK7kadSCjpP2kigFkVhxvl18MiNmeR5B9aLkkjB6kwSCsTekw8uNTZxh01ZCkjOB1tRiCJnchmh4-TPfOrcZBfV0WNFcbend0DfK9tMRmcs3Gv5aWzFe0mF6eXE5dTAACMEkLwwOrvP-aXRq526DN43RFVasGMvq7-E81pjtcZN_8xPWNs"
}
]
}
]

View File

@ -1,25 +1,51 @@
==================================================
记录时间: 2025-03-27 13:15:18
==================================================
时间: 2025-03-27 12:04:29
发件人: crush wds <ardonisierni@gmail.com>
主题: 这是主题
内容:
你好呀
--------------------------------------------------
时间: 2025-03-27 12:05:54
发件人: wds crush <crushwds@gmail.com>
主题:
内容:
你那里天气怎么样
--------------------------------------------------
时间: 2025-03-27 13:13:03
发件人: wds crush <crushwds@gmail.com>
主题:
内容:
吃饭了吗
--------------------------------------------------
==================================================
记录时间: 2025-04-07 14:24:38
==================================================
时间: 2025-03-27 12:04:29
发件人: crush wds <ardonisierni@gmail.com>
主题: 这是主题
内容:
你好呀
--------------------------------------------------
时间: 2025-03-27 12:05:54
发件人: wds crush <crushwds@gmail.com>
主题:
内容:
你那里天气怎么样
--------------------------------------------------
时间: 2025-03-27 13:13:03
发件人: wds crush <crushwds@gmail.com>
主题:
内容:
吃饭了吗
--------------------------------------------------
时间: 2025-04-07 14:24:28
发件人: wds crush <crushwds@gmail.com>
主题: Re: 这是主题
内容:
测试附件内容
crush wds <ardonisierni@gmail.com> 于2025年3月27日周四 12:04写道
> 你好呀
>
附件:
- test2.txt (text/plain, 996 字节)
--------------------------------------------------

View File

@ -21,18 +21,47 @@ if not creds or creds.invalid:
creds = tools.run_flow(flow, store)
GMAIL = discovery.build('gmail', 'v1', http=creds.authorize(Http()))
def download_attachment(message_id, attachment_id, filename):
"""下载邮件附件"""
try:
attachment = GMAIL.users().messages().attachments().get(
userId='me',
messageId=message_id,
id=attachment_id
).execute()
data = attachment['data']
file_data = base64.urlsafe_b64decode(data)
# 创建附件目录
if not os.path.exists('attachments'):
os.makedirs('attachments')
# 保存附件
filepath = os.path.join('attachments', filename)
with open(filepath, 'wb') as f:
f.write(file_data)
return filepath
except Exception as e:
print(f"Error downloading attachment: {str(e)}")
return None
def get_email_content(message):
"""提取邮件内容"""
try:
message_id = message['id'] # 获取邮件ID
payload = message['payload']
headers = payload['headers']
# 获取邮件基本信息
email_data = {
'id': message_id, # 保存邮件ID
'subject': '',
'from': '',
'date': '',
'body': ''
'body': '',
'attachments': [] # 新增附件列表
}
# 提取头部信息
@ -45,16 +74,37 @@ def get_email_content(message):
date = parser.parse(header['value'])
email_data['date'] = date.strftime('%Y-%m-%d %H:%M:%S')
# 提取邮件正文
if 'parts' in payload:
parts = payload['parts']
# 定义一个递归函数来处理所有部分和附件
def process_parts(parts):
for part in parts:
if part['mimeType'] == 'text/plain':
# 检查是否是附件
if 'filename' in part and part['filename']:
attachment = {
'filename': part['filename'],
'mimeType': part['mimeType'],
'size': part['body'].get('size', 0)
}
# 如果有附件内容数据可以获取附件ID
if 'attachmentId' in part['body']:
attachment['attachmentId'] = part['body']['attachmentId']
email_data['attachments'].append(attachment)
# 处理文本内容
if part['mimeType'] == 'text/plain' and not email_data['body']:
data = part['body'].get('data', '')
if data:
text = base64.urlsafe_b64decode(data).decode('utf-8')
email_data['body'] = text
break
# 递归处理多部分内容
if 'parts' in part:
process_parts(part['parts'])
# 处理邮件正文和附件
if 'parts' in payload:
process_parts(payload['parts'])
elif 'body' in payload:
data = payload['body'].get('data', '')
if data:
@ -123,6 +173,13 @@ def save_conversations(conversations, output_file):
f.write(f"主题: {msg['subject']}\n")
f.write("内容:\n")
f.write(f"{msg['body']}\n")
# 添加附件信息
if msg['attachments']:
f.write("\n附件:\n")
for att in msg['attachments']:
f.write(f" - {att['filename']} ({att['mimeType']}, {att['size']} 字节)\n")
f.write("-" * 50 + "\n")
print(f"对话记录已保存到: {output_file}")
@ -152,18 +209,39 @@ def main():
if conversations:
print(f"找到 {len(conversations)} 条对话记录")
# 保存对话记录(追加模式)
# 统计附件
total_attachments = 0
for msg in conversations:
total_attachments += len(msg['attachments'])
# 保存对话记录
save_conversations(conversations, output_file)
# 打印对话统计
print("\n对话统计:")
print(f"总消息数: {len(conversations)}")
print(f"总附件数: {total_attachments}")
senders = {}
for msg in conversations:
sender = msg['from']
senders[sender] = senders.get(sender, 0) + 1
for sender, count in senders.items():
print(f"{sender}: {count} 条消息")
# 提示用户是否下载附件
if total_attachments > 0:
download_choice = input(f"\n发现 {total_attachments} 个附件,是否下载? (y/n): ")
if download_choice.lower() == 'y':
print("\n开始下载附件...")
downloaded = 0
for msg in conversations:
for att in msg['attachments']:
if 'attachmentId' in att:
filepath = download_attachment(msg['id'], att['attachmentId'], att['filename'])
if filepath:
downloaded += 1
print(f"已下载: {att['filename']} -> {filepath}")
print(f"\n完成! 成功下载了 {downloaded}/{total_attachments} 个附件到 'attachments' 目录")
else:
print("未找到对话记录")

View File

@ -1 +1 @@
{"access_token": "ya29.a0AeXRPp7jfizXj6NfUavzABcDOEH-PD7TckkeCwQWFksLZwkFXqAaVe1gCeZZIWtP4hMD3F2-K7-hdSQAzCiyP7Z_72YPr_r3UDfflr6XOV7czJ937QknW_236kLJK1DDggpB4BFCB1cXtSJa6V4pbyez4lkka021mZWegOdGaCgYKATkSARISFQHGX2Mi7Ua3f90G-JLtvzu2YJgvoA0175", "client_id": "240872828479-570luspoc31259l1faab6kmjmpcsa9n9.apps.googleusercontent.com", "client_secret": "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", "refresh_token": "1//0eUNnePCc4hEKCgYIARAAGA4SNwF-L9IrIRfxg1JwnMu0WHZAu-uCWT7cx1PncId3bPZr4x53Mo57xGXr2WjiF4szuSQQkeL4hNU", "token_expiry": "2025-03-27T06:13:12Z", "token_uri": "https://oauth2.googleapis.com/token", "user_agent": null, "revoke_uri": "https://oauth2.googleapis.com/revoke", "id_token": null, "id_token_jwt": null, "token_response": {"access_token": "ya29.a0AeXRPp7jfizXj6NfUavzABcDOEH-PD7TckkeCwQWFksLZwkFXqAaVe1gCeZZIWtP4hMD3F2-K7-hdSQAzCiyP7Z_72YPr_r3UDfflr6XOV7czJ937QknW_236kLJK1DDggpB4BFCB1cXtSJa6V4pbyez4lkka021mZWegOdGaCgYKATkSARISFQHGX2Mi7Ua3f90G-JLtvzu2YJgvoA0175", "expires_in": 3599, "scope": "https://www.googleapis.com/auth/gmail.modify", "token_type": "Bearer", "refresh_token_expires_in": 599654}, "scopes": ["https://www.googleapis.com/auth/gmail.modify"], "token_info_uri": "https://oauth2.googleapis.com/tokeninfo", "invalid": false, "_class": "OAuth2Credentials", "_module": "oauth2client.client"}
{"access_token": "ya29.a0AZYkNZjEUAU0zL5oOFtnyDomfMZSzeAVMn5tvmHziV8CaMb4LaK3FAwZ_YC3itk2XlUQlIX0jZ4LQbqZZvdgk7fuwlimFzOHIrfkLt2nd6TPt-L3OqJbmYbYsJRgZ6twrlkX4-nvDsvK0br-WByC5WZj4Ih2FevlMb_-n6J-aCgYKAUUSARISFQHGX2MiYlBZMAAMwlcMNHHm-HnGiA0175", "client_id": "240872828479-570luspoc31259l1faab6kmjmpcsa9n9.apps.googleusercontent.com", "client_secret": "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", "refresh_token": "1//0e45xAmjtJtxpCgYIARAAGA4SNwF-L9Ir7GKiW_h2fGY6auAsSxOtmpocidE68QpFfuUDtwPhSJYHhS_1ZfYDNu8pRcD85X1Kh_Y", "token_expiry": "2025-04-07T07:20:36Z", "token_uri": "https://oauth2.googleapis.com/token", "user_agent": null, "revoke_uri": "https://oauth2.googleapis.com/revoke", "id_token": null, "id_token_jwt": null, "token_response": {"access_token": "ya29.a0AZYkNZjEUAU0zL5oOFtnyDomfMZSzeAVMn5tvmHziV8CaMb4LaK3FAwZ_YC3itk2XlUQlIX0jZ4LQbqZZvdgk7fuwlimFzOHIrfkLt2nd6TPt-L3OqJbmYbYsJRgZ6twrlkX4-nvDsvK0br-WByC5WZj4Ih2FevlMb_-n6J-aCgYKAUUSARISFQHGX2MiYlBZMAAMwlcMNHHm-HnGiA0175", "expires_in": 3599, "refresh_token": "1//0e45xAmjtJtxpCgYIARAAGA4SNwF-L9Ir7GKiW_h2fGY6auAsSxOtmpocidE68QpFfuUDtwPhSJYHhS_1ZfYDNu8pRcD85X1Kh_Y", "scope": "https://www.googleapis.com/auth/gmail.readonly", "token_type": "Bearer", "refresh_token_expires_in": 604799}, "scopes": ["https://www.googleapis.com/auth/gmail.readonly"], "token_info_uri": "https://oauth2.googleapis.com/tokeninfo", "invalid": false, "_class": "OAuth2Credentials", "_module": "oauth2client.client"}