Parse Tesco order confirmation .eml files into an itemized receipt summary using the Anthropic Claude API, and optionally post it to a Telegram group with per-item ownership buttons (Mine / Split / Skip). Use when processing email receipts, parsing .eml files, extracting grocery order line items, verifying receipt arithmetic, sending receipts to Telegram, or when the user mentions Tesco email orders or flatmate expense splitting.
Parses Tesco order confirmation .eml files end-to-end using Claude (Anthropic API):
.eml, strip HTML → clean plain textOrder / OrderItem JSONpip install anthropic requests python-telegram-bot
Configure in email-processor/config.py:
ANTHROPIC_API_KEY = "sk-ant-..."
TEXT_MODEL = "claude-opus-4-5"
TELEGRAM_BOT_TOKEN = "" # from @BotFather
TELEGRAM_CHAT_ID = "" # group chat ID (negative integer)
# Itemized summary (stdout only)
python email-processor/process_eml.py path/to/order.eml
# Parse + send to Telegram group with inline buttons
python email-processor/process_eml.py path/to/order.eml --telegram
# Also dump raw parsed JSON
python email-processor/process_eml.py path/to/order.eml --json
# Skip QA check (faster, one LLM call)
python email-processor/process_eml.py path/to/order.eml --skip-qa
# Start the bot callback handler (keep running alongside)
python email-processor/bot.py
Run all commands from the repo root.
The parsed receipt matches the shared schema in receipt-processor/scripts/schema.py. Key fields:
merchant — store name, e.g. "Tesco"ordered_at — ISO 8601 date-time or nullcurrency — 3-letter code, defaults to "GBP"subtotal, delivery_fee, total — monetary totalsbasket_discounts[] — basket-level adjustments; each has description and amountpayment_method — e.g. "Pay online", "Clubcard Pay+"items[] — one entry per line item:
raw_label — label exactly as it appears in the emailnormalized_label — cleaned, human-readable product namequantity, unit_price, line_totalitem_discount — positive saving if an offer applies; null otherwiseErrors from the LLM or JSON parsing are printed as {"error": "..."} to stdout and the process exits with code 1. Always check the exit code or error key before consuming output.
When --telegram is passed, telegram_sender.py sends the receipt as HTML to the group with one button row per item:
[✅ Mine] [½ Split 2] [👥 All share] [⏭ Skip]
...
[✅ Done — settle up] [🔄 Reset all]
bot.py (polling process) handles button taps:
✅ Mine — @user)Telegram setup checklist:
TELEGRAM_BOT_TOKENTELEGRAM_CHAT_ID (use /getUpdates or @userinfobot)When asked to process and share a Tesco email receipt:
bot.py is running: python email-processor/bot.pypython email-processor/process_eml.py path/to/order.eml --telegram✗ QA check FAILED warnings and report discrepancies