215 lines
5.9 KiB
Python
215 lines
5.9 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Email Queue Processor - Handle user commands for pending emails
|
|
Reads pending_emails.json and executes user commands (archive/keep/reply)
|
|
"""
|
|
|
|
import json
|
|
import imaplib
|
|
import os
|
|
import sys
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
SCRIPT_DIR = Path(__file__).parent
|
|
DATA_FILE = SCRIPT_DIR / "data" / "pending_emails.json"
|
|
|
|
def load_pending():
|
|
"""Load pending emails from JSON file"""
|
|
if not DATA_FILE.exists():
|
|
return {}
|
|
with open(DATA_FILE, 'r', encoding='utf-8') as f:
|
|
return json.load(f)
|
|
|
|
def save_pending(pending):
|
|
"""Save pending emails to JSON file"""
|
|
DATA_FILE.parent.mkdir(exist_ok=True)
|
|
with open(DATA_FILE, 'w', encoding='utf-8') as f:
|
|
json.dump(pending, f, indent=2, ensure_ascii=False)
|
|
|
|
def connect_imap(config):
|
|
"""Connect to IMAP server"""
|
|
mail = imaplib.IMAP4_SSL(config['imap']['host'], config['imap']['port'])
|
|
mail.login(config['imap']['email'], config['imap']['password'])
|
|
return mail
|
|
|
|
def show_pending_list():
|
|
"""Display all pending emails"""
|
|
pending = load_pending()
|
|
|
|
if not pending:
|
|
print("📭 没有待处理的邮件")
|
|
return
|
|
|
|
print(f"\n📧 待处理邮件列表 ({len(pending)} 封)")
|
|
print("=" * 60)
|
|
|
|
# Sort by email_date
|
|
sorted_items = sorted(
|
|
pending.items(),
|
|
key=lambda x: x[1].get('email_date', '')
|
|
)
|
|
|
|
for msg_id, data in sorted_items:
|
|
if data.get('status') == 'pending':
|
|
print(f"\n🆔 {msg_id}")
|
|
print(f" 主题: {data.get('subject', 'N/A')[:50]}")
|
|
print(f" 发件人: {data.get('sender', 'N/A')}")
|
|
print(f" 收件人: {data.get('recipient', 'N/A')}")
|
|
print(f" 时间: {data.get('email_date', 'N/A')}")
|
|
print(f" 摘要: {data.get('summary', 'N/A')[:80]}")
|
|
|
|
print("\n" + "=" * 60)
|
|
print("\n可用指令:")
|
|
print(" • 归档 [ID] - 移动到 Archive 文件夹")
|
|
print(" • 保留 [ID] - 标记已读,留在收件箱")
|
|
print(" • 删除 [ID] - 移动到 Trash")
|
|
print(" • 全部处理 - 列出所有并批量操作")
|
|
|
|
def archive_email(config, msg_id):
|
|
"""Archive a specific email by ID"""
|
|
pending = load_pending()
|
|
|
|
if msg_id not in pending:
|
|
print(f"❌ 未找到邮件 ID: {msg_id}")
|
|
return False
|
|
|
|
email_data = pending[msg_id]
|
|
uid = email_data.get('imap_uid')
|
|
|
|
if not uid:
|
|
print(f"❌ 邮件 {msg_id} 没有 UID")
|
|
return False
|
|
|
|
try:
|
|
mail = connect_imap(config)
|
|
mail.select('INBOX')
|
|
|
|
# Copy to Archive
|
|
result = mail.copy(uid, 'Archive')
|
|
if result[0] == 'OK':
|
|
# Mark original as deleted
|
|
mail.store(uid, '+FLAGS', '\\Deleted')
|
|
mail.expunge()
|
|
|
|
# Update status
|
|
pending[msg_id]['status'] = 'done'
|
|
pending[msg_id]['action'] = 'archived'
|
|
pending[msg_id]['processed_at'] = datetime.now().isoformat()
|
|
save_pending(pending)
|
|
|
|
print(f"✅ 已归档: {email_data.get('subject', 'N/A')[:40]}")
|
|
return True
|
|
else:
|
|
print(f"❌ 归档失败: {result}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ 错误: {e}")
|
|
return False
|
|
finally:
|
|
try:
|
|
mail.logout()
|
|
except:
|
|
pass
|
|
|
|
def keep_email(config, msg_id):
|
|
"""Keep email in inbox, mark as read"""
|
|
pending = load_pending()
|
|
|
|
if msg_id not in pending:
|
|
print(f"❌ 未找到邮件 ID: {msg_id}")
|
|
return False
|
|
|
|
email_data = pending[msg_id]
|
|
uid = email_data.get('imap_uid')
|
|
|
|
if not uid:
|
|
print(f"❌ 邮件 {msg_id} 没有 UID")
|
|
return False
|
|
|
|
try:
|
|
mail = connect_imap(config)
|
|
mail.select('INBOX')
|
|
|
|
# Mark as read (Seen)
|
|
mail.store(uid, '+FLAGS', '\\Seen')
|
|
|
|
# Update status
|
|
pending[msg_id]['status'] = 'done'
|
|
pending[msg_id]['action'] = 'kept'
|
|
pending[msg_id]['processed_at'] = datetime.now().isoformat()
|
|
save_pending(pending)
|
|
|
|
print(f"✅ 已保留: {email_data.get('subject', 'N/A')[:40]}")
|
|
return True
|
|
|
|
except Exception as e:
|
|
print(f"❌ 错误: {e}")
|
|
return False
|
|
finally:
|
|
try:
|
|
mail.logout()
|
|
except:
|
|
pass
|
|
|
|
def delete_email(config, msg_id):
|
|
"""Move email to Trash"""
|
|
pending = load_pending()
|
|
|
|
if msg_id not in pending:
|
|
print(f"❌ 未找到邮件 ID: {msg_id}")
|
|
return False
|
|
|
|
email_data = pending[msg_id]
|
|
uid = email_data.get('imap_uid')
|
|
|
|
if not uid:
|
|
print(f"❌ 邮件 {msg_id} 没有 UID")
|
|
return False
|
|
|
|
try:
|
|
mail = connect_imap(config)
|
|
mail.select('INBOX')
|
|
|
|
# Copy to Trash
|
|
result = mail.copy(uid, 'Trash')
|
|
if result[0] == 'OK':
|
|
mail.store(uid, '+FLAGS', '\\Deleted')
|
|
mail.expunge()
|
|
|
|
# Update status
|
|
pending[msg_id]['status'] = 'done'
|
|
pending[msg_id]['action'] = 'deleted'
|
|
pending[msg_id]['processed_at'] = datetime.now().isoformat()
|
|
save_pending(pending)
|
|
|
|
print(f"✅ 已删除: {email_data.get('subject', 'N/A')[:40]}")
|
|
return True
|
|
else:
|
|
print(f"❌ 删除失败: {result}")
|
|
return False
|
|
|
|
except Exception as e:
|
|
print(f"❌ 错误: {e}")
|
|
return False
|
|
finally:
|
|
try:
|
|
mail.logout()
|
|
except:
|
|
pass
|
|
|
|
def main():
|
|
"""Main function - show pending list"""
|
|
import json
|
|
|
|
# Load config
|
|
config_file = Path(__file__).parent / "config.json"
|
|
with open(config_file) as f:
|
|
config = json.load(f)
|
|
|
|
show_pending_list()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|