安全工资单下载器
通过与Claude Desktop集成,从Gmail自动下载每月工资单。
一个安全的MCP(模型上下文协议)服务器,使用OAuth身份验证自动从Gmail下载PDF工资单,并支持通过cron进行定时下载。
✨ 特性
- 🔒 安全OAuth 2.0身份验证 -带有只读访问功能的Gmail API
- 📅 每月自动下载 -使用系统cron设置并忘记
- 🤖 Claude桌面集成 -5个用于交互式管理的MCP工具
- 📁 有序存储 -按年份保存的文件:
~/Documents/Payslips/YYYY/ - 🔐 安全第一设计 -文件权限、路径遍历阻止、凭据编辑
- 📄 PDF验证 -Magic bytes验证确保只下载PDF
- 🌍 时区支持 -已配置为以色列时区(亚洲/耶路撒冷)
- 📊 综合录井 -所有记录了敏感数据的操作均已编辑
🏗️ 建筑
secure-payslip-downloader/
├── src/
│ ├── server.py # FastMCP server with 5 tools
│ ├── gmail_client.py # Gmail API with OAuth & rate limiting
│ ├── scheduler.py # Schedule management (JSON-based)
│ ├── config.py # Configuration management
│ └── security.py # Security utilities
├── scripts/
│ ├── oauth_setup.py # OAuth authentication wizard
│ ├── run_scheduled_downloads.py # Cron runner script
│ └── test_scheduler.py # Scheduler tests
├── credentials/ # OAuth credentials (gitignored)
├── schedules/ # Schedule storage (gitignored)
├── logs/ # Application logs (gitignored)
└── pyproject.toml # uv dependencies
🚀 快速开始
先决条件
- Python 3.9+ 随着 紫外线 安装
- 谷歌云项目 启用Gmail API
- Claude桌面版 (用于MCP集成)
安装
# 1. Clone or navigate to project directory
cd /Users/galsened/secure-payslip-downloader
# 2. Install dependencies (already done if using uv)
uv sync
# 3. Set up Google OAuth (see GOOGLE_CLOUD_SETUP.md)
# Download credentials.json to credentials/
# 4. Run OAuth setup
uv run python scripts/oauth_setup.py
# 5. Add MCP server to Claude Desktop
# See "Claude Desktop Configuration" section belowClaude桌面配置
将此添加到您的 ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"secure-payslip-downloader": {
"command": "uv",
"args": [
"--directory",
"/Users/galsened/secure-payslip-downloader",
"run",
"python",
"src/server.py"
],
"env": {
"GMAIL_CREDS_PATH": "/Users/galsened/secure-payslip-downloader/credentials/credentials.json",
"DOWNLOAD_BASE_PATH": "/Users/galsened/Documents/Payslips",
"TIMEZONE": "Asia/Jerusalem",
"LOG_LEVEL": "INFO"
}
}
}
}注: 如果安装到其他位置,请更新路径。
🛠️ MCP工具
服务器提供了5个可通过Claude Desktop访问的工具:
1. search_payslip_email
搜索来自特定发件人的工资单电子邮件。
search_payslip_email(
sender_email="payroll@company.com",
subject_keywords="payslip", // optional
days_back=30 // optional
)退货: 带有附件元数据的匹配电子邮件列表。
2. download_payslip
下载特定的PDF附件。
download_payslip(
message_id="18f3a4b5c6d7e8f9",
attachment_id="ANGjdJ8...",
filename="Payslip_November_2025.pdf"
)退货: 下载状态和文件路径。
3. create_monthly_schedule
创建自动月度下载计划。
create_monthly_schedule(
sender_email="payroll@company.com",
day_of_month=11,
hour=9, // optional, default: 9
minute=0, // optional, default: 0
subject_keywords="payslip", // optional
description="Monthly payslip from Company Ltd" // optional
)退货: 计划ID和cron设置说明。
4. list_schedules
列出所有已配置的计划。
list_schedules(
enabled_only=false // optional
)退货: 所有带有状态和统计信息的日程表。
5. delete_schedule
删除计划下载。
delete_schedule(
schedule_id="abc123..."
)退货: 删除确认。
📅 设置自动下载
第一步:通过Claude创建日程表
You: Create a monthly schedule to download payslips from payroll@company.com
on the 11th of each month at 9 AM with subject keyword "payslip"克劳德将使用 create_monthly_schedule 工具并返回cron命令。
步骤2:添加到Crontab
# Edit crontab
crontab -e
# Add the cron command from Step 1 (example):
0 9 11 * * cd /Users/galsened/secure-payslip-downloader && uv run python scripts/run_scheduled_downloads.py >> logs/cron.log 2>&1
# Save and exit步骤3:验证
# Check crontab entry
crontab -l
# Test manually
uv run python scripts/run_scheduled_downloads.py
# Check logs
tail -f logs/cron.log有关详细的cron设置说明,请参阅 CRON_SETUP.md.
📖 使用示例
示例1:一次性下载
You: Search for payslips from payroll@mycompany.com in the last 7 days
Claude: [Uses search_payslip_email tool]
Found 1 email with 1 PDF attachment: "Payslip_November_2025.pdf"
You: Download it
Claude: [Uses download_payslip tool]
Downloaded to: ~/Documents/Payslips/2025/Payslip_November_2025.pdf示例2:设置自动化
You: Set up automatic monthly download from hr@company.com on the 11th at 9 AM
Claude: [Uses create_monthly_schedule tool]
Schedule created! Add this to your crontab:
0 9 11 * * cd /path/to/project && uv run python scripts/run_scheduled_downloads.py >> logs/cron.log 2>&1
You: [Adds to crontab]示例3:管理时间表
You: Show me all my scheduled downloads
Claude: [Uses list_schedules tool]
You have 2 active schedules:
1. Company A payslips - Every 11th at 09:00
2. Company B payslips - Every 15th at 14:00
You: Delete the first one
Claude: [Uses delete_schedule tool]
Schedule deleted successfully🔒 安全特性
认证
- 仅限OAuth 2.0 -没有密码或API密钥
- Gmail只读范围 -无法修改或删除电子邮件
- 安全令牌存储 -token.pickle上的0600权限
- 自动令牌刷新 -无需人工干预
文件安全性
- 路径遍历预防 -文件名清理
- 安全权限 -敏感目录为0700,文件为0600
- PDF验证 -魔术字节检查(%PDF-)
- 有组织的存储 -按年份分组的文件
日志安全
- 凭证编辑 -令牌、密码、API密钥被屏蔽
- 电子邮件部分编辑 -日志中仅显示域
- 安全日志权限 -日志目录上的0700
速率限制
- 5次呼叫/秒 用于搜索操作
- 3次呼叫/秒 下载
- 指数退避 API错误(429500503)
🧪 测试
运行综合测试套件:
# Test scheduler module
uv run python scripts/test_scheduler.py
# Test OAuth setup (requires credentials.json)
uv run python scripts/oauth_setup.py
# Test cron runner (requires OAuth token)
uv run python scripts/run_scheduled_downloads.py
# Verify MCP server
uv run python -c "import sys; sys.path.insert(0, 'src'); from server import mcp; print('✓ MCP server OK')"📁 文件组织
下载
~/Documents/Payslips/
├── 2024/
│ ├── Payslip_December_2024.pdf
│ └── Payslip_November_2024.pdf
└── 2025/
├── Payslip_January_2025.pdf
└── Payslip_February_2025.pdf日程表
存储在 schedules/tasks.json:
{
"abc123-456": {
"sender_email": "payroll@company.com",
"subject_keywords": "payslip",
"schedule": "0 9 11 * *",
"enabled": true,
"created_at": "2025-01-15T10:30:00",
"last_run": "2025-02-11T09:00:05",
"description": "Monthly payslip from Company Ltd"
}
}日志
logs/app.log-应用程序日志logs/cron.log-Cron执行日志
⚙️ 配置
环境变量
GMAIL_CREDS_PATH-credentials.json的路径(默认:credentials/credentials.json)DOWNLOAD_BASE_PATH-基本下载目录(默认:~/Documents/Payslips)TIMEZONE-日程安排的时区(默认值:Asia/Jerusalem)LOG_LEVEL-日志记录级别(默认值:INFO)
目录结构
敏感目录(凭据、计划、日志)使用0700权限。 下载目录使用0755权限。
🐛 故障排除
OAuth身份验证失败
# Re-run OAuth setup
uv run python scripts/oauth_setup.py
# Check credentials exist
ls -l credentials/credentials.json
# Check permissions
chmod 600 credentials/credentials.jsonCron作业未运行
# Check crontab
crontab -l
# Check cron service (macOS)
sudo launchctl list | grep cron
# Check logs
tail -50 logs/cron.log
# Test manually
uv run python scripts/run_scheduled_downloads.py未找到电子邮件
# Test search via Claude Desktop
# Use: search_payslip_email tool
# Check Gmail API quota
# Visit: Google Cloud Console > APIs & Services > Quotas
# Verify sender email is exact
# Gmail search is case-sensitive for email addresses下载失败
# Check disk space
df -h ~/Documents/Payslips
# Check permissions
ls -ld ~/Documents/Payslips
ls -ld ~/Documents/Payslips/2025
# Check logs for details
grep ERROR logs/app.log📚 文档
- CRON_SETUP.md -详细的cron配置指南
- GOOGLE_CLOUD_SETUP.md -谷歌云项目设置(即将推出)
- .env.示例 -环境变量模板
🔗 依赖项
- fastmcp -MCP服务器框架
- 谷歌认证 -OAuth身份验证
- googleapi-python客户端 -Gmail API客户端
- python日期工具 -日期/时间实用程序
- 皮丹提克 -数据验证
中的完整依赖关系列表 pyproject.toml.
📋 需求
- Python 3.9或更高版本
- macOS或Linux(带WSL的Windows)
- 具有OAuth凭据的Gmail帐户
- Claude Desktop(用于MCP集成)
🤝 贡献
这是一个个人工具,但请随时根据您的需求进行分叉和调整。
📄 许可证
MIT许可证-有关详细信息,请参阅许可证文件。
⚠️ 重要提示
- OAuth令牌安全:
- 永不承诺 credentials/ 目录 - 永远不要分享你的 token.pickle 文件 - 令牌提供只读Gmail访问
- Cron环境:
- Cron在最小环境下运行 - 始终使用绝对路径 - 首先手动测试cron命令
- Gmail API限制:
- 免费等级:10亿配额单位/天 - 搜索:5个单位/请求 - 下载:10个单位/请求 - 典型使用量:~1000台/月
- 文件组织:
- 按电子邮件日期年份组织的文件 - 自动跳过重复文件 - 保留(净化)原始文件名
🙏 致谢
内置:
______________________________________________________________________
状态: ✅ 完全实施和测试
最后更新时间: 2025-01-29
如需支持或疑问,请在GitHub上发布问题。
