Your email and calendar are the richest record of your work week, and usually the most locked down. In the overview of my Obsidian and Claude setup I mentioned getting both into a local inbox with no API access at all. This is how, in enough detail to copy.
The obvious routes are closed
The clean way to read a corporate mailbox from a script is an API: Microsoft Graph, or plain old IMAP. In a lot of workplaces neither is realistic for a personal project. Graph needs an app registration, and corporate tenants often require admin consent for mailbox permissions. IMAP is often switched off. The front door is locked, and it's locked for good reasons.
Power Automate gives me another route. My company already provides it, and its approved connectors can read the mailbox and calendar and write files to OneDrive. OneDrive syncs those files to my laptop. From there, a small scheduled task drops them into the vault.
The shape of it
The whole path runs one direction, mailbox to local folder:
Every hop is dumb and independent. If OneDrive is slow, the flow still runs. If the laptop is off, the files wait in the cloud. Nothing holds a connection open, so nothing has a connection to lose. I prefer this to a proper integration because each step can fail without stopping the others.
Flow 1: capture the mail you care about
Received mail is captured by flag, not by firehose. I don't want every email in the vault, I want the ones that matter, so the flow triggers on When an email is flagged (V3) in the Inbox. I flag a message in Outlook, the flow fires, fetches the email, converts the HTML body to plain text, and writes a .txt into EmailCapture/Vault. Then it unflags the message to reduce repeat runs. That is not a guarantee: Microsoft says a flagged-email trigger can fire again when an already flagged message changes, so the filenames still need collision handling. Any attachments go alongside it in EmailCapture/Vault/Attachments, numbered so two files called report.pdf can't collide. If I tag the email with an Outlook category first (VIP, Follow Up, Waiting), the flow captures that too, and falls back to Uncategorized when I haven't.
The file the Compose step assembles comes out like this:
Type Category: VIP
Type From: sender@example.com
Type To: you@example.com
Type CC:
Type Subject: RE: Q2 Budget Review
Type Date: 2026-03-06T14:30:00Z
Type ConversationId: AAQkAGI2...
Could you review the attached budget before Thursday...That ConversationId is Outlook's thread identifier, captured so the vault can group a reply chain with certainty instead of guessing from the subject line. The Type prefix on every header is a Power Automate quirk, and I'll come back to it.
Flow 2: capture everything you send
Sent mail is the opposite. I want all of it with no effort, so that flow triggers automatically on every new item in Sent Items. A condition filters out the automatic meeting accept and decline replies so they don't become noise, then it converts the body to text and writes a .txt into EmailCapture/Sent. No flag, no thought.
That condition matches on the subject prefix, so it needs every language your calendar replies arrive in. Mine checks eleven prefixes across English, German, and Croatian, because a Declined: filter does nothing about an Abgelehnt: or an Odbijeno:. If your work spans more than a couple of countries, that list only grows, and every language you miss is a category of noise you'll be deleting by hand later. Check your own sent folder before you assume one covers it.
The sent file uses plain headers, and the From field comes out empty:
From:
To: colleague@example.com
CC:
Subject: RE: Some Subject Here
Date: 2026-03-06T14:30:00Z
ConversationId: AAQkAGI2...
Email body in plain text...The two-formats gotcha
Look at the two examples. Received mail prefixes every header with Type, sent mail doesn't, and sent mail has an empty From. That isn't a choice, it's how the two triggers serialize their data. Instead of fighting Power Automate into agreement, I let the parser downstream read both shapes. The capture layer has exactly one job: get each file into the right folder. That empty From on sent mail is the reason the bridge script matters later.
Flow 3: the senders you can't afford to miss
Flagging works on the days I'm reading my inbox. It fails on the days I'm not, and those are exactly the days something from the wrong person sits unread until Thursday. So the third flow watches people instead of messages.
The tagging half isn't Power Automate at all. An ordinary Outlook rule puts a VIP category on anything from the senders I list, the moment it arrives. Then the flow wakes up every 15 minutes and asks the mailbox for category:VIP NOT category:VIP-Captured, takes up to ten at a time, writes each one out the way Flow 1 does, and stamps the message with a second category, VIP-Captured.
That second category is the trick. Flow 1 can unflag a message to stop it firing twice, but this one can't clear the VIP tag, because I still want it there when I go looking. So it adds a marker instead, and the search query filters on it. There's no list of processed IDs anywhere, and if I ever want a message recaptured I delete one category by hand.
One difference from Flow 1 that matters downstream: VIP mail lands in its own EmailCapture/VIP/Vault folder, so the bridge script treats it as a separate source. Otherwise it behaves the same, attachments included.
And the calendar
The calendar is one more flow, scheduled to run every 30 minutes through the workday. It uses Get calendar view of events (V3) for today's range and a Select to keep the fields I care about (subject, start, end, organizer, attendees, online meeting link). The target is yyyy-MM-dd-calendar.json in EmailCapture/Calendar.
Do not rely on Create file to replace that file. Microsoft's OneDrive for Business reference does not document an overwrite option for that action. Make the replacement explicit: list the files in EmailCapture/Calendar, match the exact daily filename, and use Update file with its ID when it exists. Use Create file only when there is no match. Test the second run. The result should be one fresh snapshot, not a failed flow or a pile of duplicates.
The bridge: one scheduled task
The files are now in OneDrive, which syncs to the laptop. The last hop is a small PowerShell script on a 15-minute timer. It walks each capture folder in turn: received mail into the inbox as-is, VIP mail the same way from its own folder, sent mail with a SENT- prefix, and the calendar snapshot refreshed. The core of it, trimmed to three of the four:
$ErrorActionPreference = "Stop"
$Sent = "$env:USERPROFILE\OneDrive\EmailCapture\Sent"
$Received = "$env:USERPROFILE\OneDrive\EmailCapture\Vault"
$Calendar = "$env:USERPROFILE\OneDrive\EmailCapture\Calendar"
$Inbox = "$env:USERPROFILE\Obsidian\WorkVault\00-Inbox"
$SentProcessed = Join-Path $Sent "Processed"
$ReceivedProcessed = Join-Path $Received "Processed"
New-Item -ItemType Directory -Path $SentProcessed -Force | Out-Null
New-Item -ItemType Directory -Path $ReceivedProcessed -Force | Out-Null
# Sent mail -> inbox, tagged so the direction survives
Get-ChildItem -LiteralPath $Sent -Filter *.txt | ForEach-Object {
Copy-Item -LiteralPath $_.FullName -Destination (Join-Path $Inbox "SENT-$($_.Name)")
Move-Item -LiteralPath $_.FullName -Destination (Join-Path $SentProcessed $_.Name)
}
# Received mail -> inbox as-is
Get-ChildItem -LiteralPath $Received -Filter *.txt | ForEach-Object {
Copy-Item -LiteralPath $_.FullName -Destination (Join-Path $Inbox $_.Name)
Move-Item -LiteralPath $_.FullName -Destination (Join-Path $ReceivedProcessed $_.Name)
}
# Calendar -> overwrite today's snapshot
Get-ChildItem -LiteralPath $Calendar -Filter *-calendar.json | ForEach-Object {
Copy-Item -LiteralPath $_.FullName -Destination (Join-Path $Inbox $_.Name) -Force
}The full version adds a -2 suffix when a filename already exists and rotates its own log. The important line in the trimmed version is $ErrorActionPreference = "Stop". PowerShell's default for non-terminating errors is to report the error and continue. Without that stop, a failed copy can still reach Move-Item, which marks a file as processed before it reaches the inbox. The safe order is copy, stop on failure, then move.
The Move-Item into Processed is doing more work than it looks like. After a successful copy and move, the next run has nothing to reconsider and the capture folder does not grow forever. Copy and move are separate steps, though: if the copy succeeds and the move fails, the next run can create a suffixed duplicate. The original remains in Processed after a successful move.
That SENT- prefix is the dumbest and most useful line in the file. Power Automate hands me sent mail with an empty From, so the content alone can't tell me which way a message went. Four characters added at copy time settle it for good, and every step downstream just reads the filename.
Put it on a timer
Register the script as a scheduled task that fires every 15 minutes while you're logged in:
$Action = New-ScheduledTaskAction -Execute "powershell.exe" `
-Argument '-NoProfile -WindowStyle Hidden -File "C:\path\to\Pull-Emails.ps1"'
$Trigger = New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) `
-RepetitionInterval (New-TimeSpan -Minutes 15)
Register-ScheduledTask -TaskName "PullEmails" -Action $Action -Trigger $Trigger `
-Description "Copies captured mail and calendar into the vault inbox"Do not override the machine's execution policy here. If a managed laptop blocks the script, that is a policy decision to resolve with IT, not a switch to bypass in the task definition.
If the console window flashing every fifteen minutes bothers you, and it will, wrap the call in a one-line .vbs launched with wscript.exe so it runs fully hidden. Tiny thing, real quality-of-life gain.
If your vault already lives in OneDrive
Then you can skip most of this. Point the Power Automate Create file step straight at the vault's inbox folder and the files arrive on their own, no scheduled task anywhere.
I kept the task, and the reason is the three small things it does on the way past: the SENT- prefix, the Processed move, and the duplicate-name suffix. Write directly into the inbox and you lose all three, which means sent and received mail become indistinguishable and nothing ever gets swept out of the capture folder. If you don't need that distinction, take the shorter path. I did need it, so I pay one scheduled task for it.
What the AI actually sees
Worth being exact here, because "my work email goes into a folder an AI reads" deserves a straight answer.
Everything described so far moves your real mail. The file that lands in your inbox has real names and real addresses in it, and nothing is masked on this leg. Before the model step, the route is mailbox to corporate OneDrive to your laptop. It does not send mail to a model yet, but it does create new copies. Those copies can change who can access the data, how long it is kept, and which backups contain it. That needs the same policy check as the flow itself.
The masking happens one step later, before anything reaches a model. A script swaps addresses, phone numbers, and the other patterns that scan as private for tokens, and keeps the real values in a local map the model never gets handed. I went through that in the overview of the setup. It lowers what gets sent rather than pretending to eliminate it, and it's honest about the gap: subject lines and meeting titles still go out roughly as written.
So the capture layer is not the privacy layer, and this post only covers the first one.
Why text files instead of a real integration
This looks primitive next to a proper API client, and that is the point. A token-based integration is a thing that breaks. Tokens expire, scopes change, rate limits bite, a refresh quietly fails overnight and the sync is down until you happen to notice. A folder of text files avoids those token and API failure modes. Each email is one file, so failures are visible and retriable. The bridge still needs its log because a copy can succeed before the move fails. Keeping the transport alive is OneDrive's job, and OneDrive is very good at its job.
What this won't do
A few honest limits:
- It needs Power Automate access, and the license assigned to your account sets request limits.
- It isn't real-time. The VIP route can wait almost 15 minutes for the mailbox flow and another 15 for the local task, plus OneDrive sync. Flagged and sent mail can also wait on the connector, and Microsoft says rare trigger delays can reach one hour. Fine for a once-a-day review, not fine for a live assistant.
- The When a new email arrives (V3) trigger used for sent mail can skip messages above the tenant limit or 50 MB, whichever is lower. Microsoft also says it may skip protected mail or messages with invalid bodies or attachments. This is useful capture, not a complete archive.
- The scheduled task is Windows. The same pattern runs on a Mac or Linux box with
cronand a OneDrive-compatible sync client; the script is just shell instead of PowerShell. - Check your own policy. Exporting mail to files, even your own mail, may or may not be allowed where you work. This is a know-the-rules situation, not an ask-forgiveness one.
The boring part is the important part
None of this is clever. It is a flow, a sync folder, a timer, and a four-character prefix. But the rest of the pipeline only works when the data arrives. Make the capture reliable first. The interesting parts depend on it.
I don't think this is the permanent shape of it. My guess is that within a few years the assistant just has a sanctioned connector to your mailbox, IT is comfortable switching it on, and none of this plumbing is anyone's problem. That's a prediction, not a roadmap, and I've been wrong about timelines before. What I am confident about is the current gap. These tools could do much more with work context than most IT departments allow them to access. A flow and a sync folder is what half-automation looks like while you wait. I'd rather run the boring version today than wait for the clean one to get approved.
Next: what happens to all of this once it lands, and why most of that pipeline isn't AI at all.
Get Personalized Help
Copy this prompt to ChatGPT, Claude, or your favorite AI assistant. Fill in your details and get guidance tailored to your specific situation.
I read https://ivanmisic.net/blog/ai-tools/email-calendar-capture-without-api and I want to build this email and calendar capture for myself. Do not build anything yet, and do not open any tabs. Your job in this conversation is to interview me and then write me a set of prompts I will run separately, one per flow, in Claude for Chrome (https://claude.com/claude-for-chrome). I want them separate because building four flows in one browser session is a lot of state to hold, and because I may not want all four. STEP 1: INTERVIEW ME Ask all of this in a single message, with your recommended default marked on each, so I can reply "defaults" and move on: 1. Which pieces do I want? Flagged mail capture, sent mail capture, VIP sender capture, calendar snapshot. Give me one line per piece on what I lose by skipping it, and tell me which one to build first if I only ever build one. 2. If I want VIP capture: which senders or addresses count as never-miss? 3. What languages do my meeting accept and decline replies arrive in? Do not assume English only. 4. Is my notes vault already inside my OneDrive folder, or somewhere else on disk? 5. Windows, Mac, or Linux for the final copy step? 6. What should the OneDrive capture folder be called? Default: EmailCapture. If my answer to any of these is vague, ask once more rather than guessing. Then show me the build order you plan and wait for me to confirm before writing anything. STEP 2: WRITE ME ONE PROMPT PER PIECE Each prompt has to work in a brand new Claude for Chrome session with no memory of this conversation. That means each one must restate my actual answers as literal values, not placeholders, and must not say "as discussed earlier". Number them in build order and tell me to test each flow before running the next prompt. Wrap each generated prompt in its own code block so I can copy them one at a time. Build the prompts from these specs, adapted to my answers: FLAGGED MAIL CAPTURE. Trigger "When an email is flagged (V3)" on the Inbox. Get the full message, convert the HTML body to plain text, compose a header block, write a .txt into the capture folder, save attachments to an Attachments subfolder with numbered filenames so two files with the same name cannot collide, then unflag the message so it cannot fire twice. Capture the Outlook category if there is one and fall back to "Uncategorized". SENT MAIL CAPTURE. Trigger "When a new email arrives (V3)" pointed at Sent Items. Before writing anything, a condition that rejects automatic meeting replies by subject prefix, covering every language I named. List the exact prefixes so I can check them against my own sent folder. Then body to text, write a .txt to the Sent capture folder. VIP SENDER CAPTURE. Two halves. First, walk me through creating the plain Outlook rule that tags mail from my named senders with a VIP category on arrival, since that half is not Power Automate. Second, a flow on a 15-minute recurrence that searches "category:VIP NOT category:VIP-Captured", takes up to ten at a time, writes them out the same way the flagged flow does, and then assigns a second category "VIP-Captured". Explain why a marker category is used here instead of unflagging. CALENDAR SNAPSHOT. Scheduled every 30 minutes across the working day. "Get calendar view of events (V3)" for today, a Select step keeping only the fields worth having, a Create file that overwrites the same day's JSON each run so I get one fresh snapshot rather than a pile of duplicates. THE LAST HOP. Only if my vault is NOT already inside OneDrive: the scheduled task that copies each capture folder into the vault inbox, received mail as-is, VIP mail the same way, sent mail with a SENT- prefix so the direction survives, calendar overwritten, and originals moved to a Processed folder so nothing is copied twice. Match the script to my operating system. If my vault IS already inside OneDrive: say so, tell me to point the Create file steps straight at the vault inbox instead, and explain what I give up by skipping the script so I can decide for myself. STEP 3: TELL ME WHAT TO WATCH FOR Close with a short list of things likely to differ on my screen from any written guide: connectors renamed, actions moved, steps my licence will not allow. And flag anything here that might run into my organisation's policy before I start clicking. In each generated prompt, remind the assistant that it can see my screen, so where the interface does not match what the prompt describes it should tell me what it actually sees and adapt rather than pushing on.