Skip to main content
The pipeline has a single entry point: python -m src.main. Three modes, controlled by flags.

Modes

Default — fetch from Outlook

  • Connects to Microsoft Graph via MSAL client credentials
  • Fetches unread emails matching Metaweave Forms: in the subject
  • Processes each one: Parse → Map → Write
  • Marks each email as read after successful processing
  • Commits the session per email; rolls back on error
  • Logs Done: X/N processed successfully at the end
This is what you’d schedule (cron, Cloud Scheduler, etc.).

Single-file — process a saved email

  • Skips the Outlook fetch entirely
  • Reads the body from a local file
  • Runs Parse → Map → Write
  • Useful for: testing, replay, debugging a specific submission
The file should contain the full email body — preferably with the BEGIN MW FORM DATA / END MW FORM DATA markers so the parser hits the encrypted path. Without markers, it falls back to text parsing (limited).

Schema setup — create tables

  • Calls Base.metadata.create_all(engine) on the configured database
  • Creates the 17 tables if missing; no-ops if they exist
  • Exits immediately — does not process any emails
Run this once per database. Idempotent.

Scheduled invocation

A typical cron entry (every 10 minutes):
For Cloud Scheduler / Lambda / Cloud Functions, the same idea — invoke the entry point on the cadence you want.

Log output

The pipeline logs at INFO level with timestamps. A successful run looks like:
A failing email is logged but doesn’t stop the run:
Failed emails are not marked as read by default — they’ll be re-attempted on the next run. Investigate by reading the body and replaying with --file.

What happens per email

Idempotency and replay

Re-running the same email is safe because:
  • The Vessel upsert keys on IMO (won’t duplicate)
  • The Voyage upsert keys on (vessel_id, voyage_number)
  • The Report uses delete-then-insert on (vessel_id, report_type, report_datetime_utc)
So the same email always produces the same final database state. This is also how corrections work — re-submit a corrected Noon and it overwrites cleanly. Mark-as-read is the only side effect on re-run — once marked, the default-mode fetcher skips it. To re-process, either:
  • Mark unread in Outlook manually
  • Save the body to a file and use --file

Failure modes

See also