Every Friday my partners send dense recap emails—action items, field visit schedules, and a cascade of “please confirm�threads. Even with labels, the real planning lived in my head. This iterative build logs how I translate those messages into an Outlook calendar that updates itself overnight.
Why email-to-calendar mattered
We coordinate interviews across three time zones, with staff cycling in and out of the thread. Outlook calendars already power our resource planning, but only after I manually retyped each agreed slot. I needed an automation that could:
- Parse unstructured email bullets and inline tables without assuming a single template.
- Respect privacy—no scraping attachments or personal notes without explicit consent.
- Keep a human review step so accidental double bookings never propagate to dozens of people.
Architecture at a glance
The flow relies on components my team already trusts, stitched together with deliberate checkpoints:
- Azure Logic App listener: Watches a filtered mailbox folder and forwards the email body (minus signatures) to an Azure Function.
- Prompt-classifier: A temperature-stable GPT-4o-mini call that identifies agenda lines, time expressions, and participants, returning structured JSON.
- Validation layer: Simple Python checks ensure date formats, time zones, and participant identifiers align with our staff directory. Misfits trigger a Teams alert instead of touching the calendar.
- Microsoft Graph writer: Confirmed events are inserted into a dedicated Outlook calendar, tagged by project and workstream.
- Digest email: A final HTML summary—generated from the same JSON feed—lands in my inbox for a one-click “approve�before the Graph call runs.
This design keeps the base infrastructure low-code but adds enough frictionless oversight to trust the output.
Prompt shape & evaluation
The classifier prompt instructs the model to only return fields the downstream validator expects. A trimmed example:
{
"context": "Identify meetings or deadlines suitable for calendar events.",
"fields": ["title", "summary", "start_time", "end_time", "timezone", "location", "participants"],
"constraints": [
"Use ISO 8601 datetime with explicit offsets",
"Infer timezone from city names when explicit times are missing",
"Flag uncertain entries with `requires_review: true`"
]
}
I evaluate each run with a small set of regression tests: messy bullet lists, bilingual notes, and emails that intentionally lack times. Anything flagged for review stops the automation, forcing me to decide whether the item deserves a manual slot.
Rollout checklist
To move from prototype to team-ready, I tick through three safeguards:
- Consent log: Recipients confirm (via a simple Microsoft Form) that the automation can process their emails.
- Change log: Every calendar insertion includes a link back to the original email stored in a SharePoint folder, making audits painless.
- Fallback mode: A Power Automate button pauses the pipeline and sends daily digests instead of committing events if something looks off.
The result is a calendar link I can hand to collaborators who prefer subscribing over refreshing their inbox. It is still human-in-the-loop, but the repetitive parsing is gone, and the energy now goes into negotiating the actual fieldwork.
If you want a deeper teardown—or have tooling suggestions—reply to the newsletter or leave a note via the contact page. I plan to release the prompt pack and validation scripts once we finish longer-term testing.