Skip to main content
Glama
leeguooooo
by leeguooooo
setup.py14.1 kB
#!/usr/bin/env python3 """ 邮箱账户配置脚本 支持配置多个邮箱账户 """ import json import os import sys import imaplib from pathlib import Path from getpass import getpass def load_existing_config(): """加载现有配置""" # 使用 data/ 目录下的 accounts.json config_file = Path(__file__).parent / 'data' / 'accounts.json' if config_file.exists(): try: with open(config_file, 'r', encoding='utf-8') as f: return json.load(f) except: return {"accounts": {}, "default_account": None} return {"accounts": {}, "default_account": None} def save_config(config): """保存配置""" # 使用 data/ 目录下的 accounts.json config_file = Path(__file__).parent / 'data' / 'accounts.json' # 确保 data 目录存在 config_file.parent.mkdir(exist_ok=True) with open(config_file, 'w', encoding='utf-8') as f: json.dump(config, f, indent=2, ensure_ascii=False) print(f"\n✅ 配置已保存到: {config_file}") def print_providers(): """打印支持的邮箱提供商""" print("\n📧 支持的邮箱提供商:") print("1. 163邮箱 (完全支持)") print("2. Gmail (需要应用专用密码)") print("3. QQ邮箱 (需要授权码)") print("4. Outlook/Hotmail") print("5. 自定义邮箱服务器") def get_provider_config(provider): """获取提供商特定的配置指南""" guides = { '163': """ 163邮箱配置步骤: 1. 登录 https://mail.163.com 2. 点击右上角设置 → POP3/SMTP/IMAP 3. 开启 IMAP/SMTP 服务 4. 完成手机验证后获取授权码 ⚠️ 使用授权码,不是邮箱密码! """, 'gmail': """ Gmail配置步骤: 1. 开启两步验证: https://myaccount.google.com/security 2. 生成应用专用密码: https://myaccount.google.com/apppasswords 3. 选择"邮件"和您的设备 4. 使用生成的16位密码 """, 'qq': """ QQ邮箱配置步骤: 1. 登录 https://mail.qq.com 2. 设置 → 账户 → POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 3. 开启 IMAP/SMTP 服务 4. 生成授权码(需要发送短信) ⚠️ 使用授权码,不是QQ密码! """, 'outlook': """ Outlook/Hotmail配置步骤: 1. 使用您的Microsoft账户邮箱地址 2. 直接使用邮箱密码登录 3. 如果开启了两步验证,需要生成应用密码 4. 访问: https://account.microsoft.com/security """, 'custom': """ 自定义邮箱配置需要提供: - IMAP服务器地址和端口 - SMTP服务器地址和端口(可选) - 邮箱地址和密码 """ } return guides.get(provider, "") def add_account(config): """添加新账户""" print("\n➕ 添加新邮箱账户") print_providers() provider_map = {'1': '163', '2': 'gmail', '3': 'qq', '4': 'outlook', '5': 'custom'} choice = input("\n请选择邮箱类型 (1-5): ").strip() provider = provider_map.get(choice) if not provider: print("❌ 无效的选择") return # 显示配置指南 guide = get_provider_config(provider) if guide: print(guide) # 输入基本信息 email = input("邮箱地址: ").strip() if not email: print("❌ 邮箱地址不能为空") return # 生成账户ID account_id = email.split('@')[0] + '_' + provider if account_id in config['accounts']: print(f"⚠️ 账户 {email} 已存在") if input("是否覆盖? (y/n): ").lower() != 'y': return # 输入密码/授权码 password = getpass(f"{'授权码' if provider in ['163', 'qq'] else '密码'}: ") if not password: print("❌ 密码/授权码不能为空") return # 构建账户配置 account_config = { "email": email, "password": password, "provider": provider, "description": input("账户描述 (可选): ").strip() or f"{provider}邮箱" } # 自定义邮箱需要额外配置 if provider == 'custom': account_config['imap_server'] = input("IMAP服务器地址: ").strip() imap_port = input("IMAP端口 (默认993): ").strip() account_config['imap_port'] = int(imap_port) if imap_port else 993 if input("是否配置SMTP服务器? (y/n): ").lower() == 'y': account_config['smtp_server'] = input("SMTP服务器地址: ").strip() smtp_port = input("SMTP端口 (默认465): ").strip() account_config['smtp_port'] = int(smtp_port) if smtp_port else 465 # 保存配置 config['accounts'][account_id] = account_config # 设置默认账户 if not config['default_account'] or input("设置为默认账户? (y/n): ").lower() == 'y': config['default_account'] = account_id print(f"\n✅ 账户 {email} 添加成功!") def list_accounts(config): """列出所有账户""" if not config['accounts']: print("\n📭 还没有配置任何账户") return print("\n📧 已配置的邮箱账户:") for account_id, account in config['accounts'].items(): default_mark = " ⭐" if account_id == config['default_account'] else "" print(f"\n• {account_id}{default_mark}") print(f" 邮箱: {account['email']}") print(f" 类型: {account['provider']}") print(f" 描述: {account.get('description', '无')}") def remove_account(config): """删除账户""" if not config['accounts']: print("\n📭 还没有配置任何账户") return list_accounts(config) account_id = input("\n请输入要删除的账户ID: ").strip() if account_id in config['accounts']: if input(f"确认删除 {config['accounts'][account_id]['email']}? (y/n): ").lower() == 'y': del config['accounts'][account_id] if config['default_account'] == account_id: config['default_account'] = list(config['accounts'].keys())[0] if config['accounts'] else None print("✅ 删除成功") else: print("❌ 账户不存在") def set_default_account(config): """设置默认账户""" if not config['accounts']: print("\n📭 还没有配置任何账户") return list_accounts(config) account_id = input("\n请输入要设为默认的账户ID: ").strip() if account_id in config['accounts']: config['default_account'] = account_id print(f"✅ 已将 {config['accounts'][account_id]['email']} 设为默认账户") else: print("❌ 账户不存在") def test_single_connection(email, password, provider="other"): """测试单个账户的IMAP连接""" # Provider-specific IMAP settings imap_settings = { "163": ("imap.163.com", 993), "gmail": ("imap.gmail.com", 993), "qq": ("imap.qq.com", 993), "outlook": ("outlook.office365.com", 993), "hotmail": ("outlook.office365.com", 993), } # Determine IMAP server if provider in imap_settings: imap_host, imap_port = imap_settings[provider] else: # Try to guess from email domain domain = email.split('@')[1].lower() if domain == "163.com": imap_host, imap_port = imap_settings["163"] elif domain == "gmail.com": imap_host, imap_port = imap_settings["gmail"] elif domain == "qq.com": imap_host, imap_port = imap_settings["qq"] elif domain in ["outlook.com", "hotmail.com"]: imap_host, imap_port = imap_settings["outlook"] else: return False, f"未知的邮箱提供商: {domain}" try: # Connect to IMAP server imap = imaplib.IMAP4_SSL(imap_host, imap_port) # Special handling for 163.com if provider == "163" or email.endswith("@163.com"): try: # Send IMAP ID command manually id_args = [ "name", "Mozilla Thunderbird", "version", "91.0", "vendor", "Mozilla", "support-url", "https://support.mozilla.org/" ] tag = imap._new_tag() id_string = " ".join(f'"{arg}"' for arg in id_args) command = f'{tag.decode()} ID ({id_string})' imap.send(command.encode() + b'\r\n') # Read response while True: resp = imap.readline() resp_str = resp.decode().strip() if resp_str.startswith(tag.decode()): break elif resp_str.startswith('*'): continue else: break except: pass # Continue even if IMAP ID fails # Login imap.login(email, password) # List folders to verify connection status, folders = imap.list() if status == 'OK': # Try to select INBOX status, data = imap.select('INBOX', readonly=True) message_count = data[0].decode() if status == 'OK' else "未知" imap.logout() return True, f"连接成功! 收件箱有 {message_count} 封邮件" else: imap.logout() return False, "无法获取邮箱文件夹列表" except imaplib.IMAP4.error as e: error_msg = str(e) if "AUTHENTICATIONFAILED" in error_msg: hint = "" if provider == "gmail" or email.endswith("@gmail.com"): hint = "\n💡 Gmail需要使用应用专用密码,而不是常规密码" elif provider == "qq" or email.endswith("@qq.com"): hint = "\n💡 QQ邮箱需要使用授权码,而不是QQ密码" return False, f"认证失败: {error_msg}{hint}" return False, f"IMAP错误: {error_msg}" except Exception as e: return False, f"连接错误: {type(e).__name__}: {str(e)}" def test_connections(config): """测试所有账户的连接""" if not config['accounts']: print("\n📭 还没有配置任何账户") return print(f"\n🚀 开始测试 {len(config['accounts'])} 个账户的连接...") print("=" * 50) success_count = 0 failed_accounts = [] for account_id, account in config['accounts'].items(): email = account.get("email") password = account.get("password") provider = account.get("provider", "other") print(f"\n🔍 测试账户: {account_id}") print(f"📧 邮箱: {email}") if not email or not password: print("❌ 缺少邮箱或密码") failed_accounts.append((account_id, "配置不完整")) continue success, message = test_single_connection(email, password, provider) if success: print(f"✅ {message}") success_count += 1 else: print(f"❌ {message}") failed_accounts.append((account_id, message)) print("\n" + "=" * 50) print("📊 测试汇总:") print(f"✅ 成功: {success_count}/{len(config['accounts'])}") print(f"❌ 失败: {len(failed_accounts)}/{len(config['accounts'])}") if failed_accounts: print("\n❌ 失败的账户:") for account_id, error in failed_accounts: print(f" • {account_id}: {error}") input("\n按回车键继续...") def migrate_from_env(): """从环境变量迁移配置""" from dotenv import load_dotenv load_dotenv() email = os.getenv('EMAIL_ADDRESS') password = os.getenv('EMAIL_PASSWORD') provider = os.getenv('EMAIL_PROVIDER', '163') if email and password: config = load_existing_config() # 检查是否已经导入过该邮箱 for account_id, account in config['accounts'].items(): if account['email'] == email: # 已经存在,不再提示 return False print(f"\n🔄 检测到环境变量配置:") print(f"邮箱: {email}") print(f"提供商: {provider}") if input("是否导入到账户配置? (y/n): ").lower() == 'y': account_id = f"env_{provider}" config['accounts'][account_id] = { "email": email, "password": password, "provider": provider, "description": "从环境变量导入" } if not config['default_account']: config['default_account'] = account_id save_config(config) print("✅ 导入成功!") return True return False def main(): """主函数""" print("🎯 MCP Email Service - 邮箱账户配置工具") print("=" * 50) # 检查是否有环境变量配置 migrate_from_env() config = load_existing_config() while True: print("\n📋 请选择操作:") print("1. 添加邮箱账户") print("2. 查看所有账户") print("3. 删除账户") print("4. 设置默认账户") print("5. 测试连接") print("6. 保存并退出") print("0. 退出不保存") choice = input("\n请选择 (0-6): ").strip() if choice == '1': add_account(config) elif choice == '2': list_accounts(config) elif choice == '3': remove_account(config) elif choice == '4': set_default_account(config) elif choice == '5': test_connections(config) elif choice == '6': save_config(config) print("\n👋 再见!") break elif choice == '0': print("\n👋 再见!") break else: print("❌ 无效的选择") if __name__ == "__main__": main()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/leeguooooo/email-mcp-service'

If you have feedback or need assistance with the MCP directory API, please join our Discord server