Local, compliance-friendly Outlook “triage” automation for Windows 11 + Classic Outlook (M365).
This project:
- Scans recent Inbox items
- Assigns an Outlook Category (
Urgent/Action/Waiting/FYI/Noise) - Flags Urgent/Action for follow-up
- Optionally moves obvious noise to a Read Later folder
- Writes an Excel triage report you can label to train a lightweight model
- (Optional) Trains a local sklearn model to learn your inbox patterns — no cloud calls
Designed for locked-down environments: runs entirely on your PC and writes to
OneDrive\AI_Outlook\...(or local OneDrive folder).
-
outlook_triage.py
Main script: triage + categorize + report export. -
train_model.py
Training script: learns from labeled rows in the triage reports and savesmodel/triage_model.joblib. -
OutlookTriage_Task.xml
Windows Task Scheduler task to runoutlook_triage.pyon a schedule. -
TrainModel_Task.xml
Windows Task Scheduler task to runtrain_model.py(weekly by default + manual run as needed). -
config/vip_senders.example.csv
Template only (copy locally to create your private VIP sender list).
By default, the scripts use:
%OneDrive%\AI_Outlook\
config\vip_senders.csv(one email per line)data\inbox_scored_YYYY-mm-dd_HHMM.csvoutputs\triage_report_YYYY-mm-dd_HHMM.xlsxmodel\triage_model.joblib
If %OneDrive% is not set, it falls back to C:\Users\<you>\OneDrive\AI_Outlook.
- Classic Outlook for Windows (COM automation).
- You must be signed in and able to open your Inbox normally.
- Recommended: Python 3.12 (64-bit)
Note:
outlook_triage.pyprints a warning that pywin32 may not be compatible with Python 3.13 in your environment. If you hit that, use Python 3.12.
pywin32pandasopenpyxlscikit-learnjoblib
If your environment blocks internet access, install from an internal package source or pre-downloaded wheels.
Open PowerShell in the repo folder:
py -3.12 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pipOnline (if allowed):
pip install pywin32 pandas openpyxl scikit-learn joblibOffline (common in locked-down environments):
- On a machine that can download packages, download wheels:
mkdir wheels pip download -d wheels pywin32 pandas openpyxl scikit-learn joblib
- Copy the
wheelsfolder to your work PC. - Install locally:
pip install --no-index --find-links .\wheels pywin32 pandas openpyxl scikit-learn joblib
Sometimes Outlook COM needs this after install:
python -m pywin32_postinstall -install.\.venv\Scripts\Activate.ps1
python outlook_triage.pyExpected output includes:
- How many emails were processed
- Path to the Excel report and CSV log
- Path to
vip_senders.csv
In Outlook, you should see Categories applied to recent emails and flags on Urgent/Action.
All key tuning knobs are at the top of outlook_triage.py:
DAYS_BACK(default7) — lookback window for inbox scanning.MAX_ITEMS(default500) — hard cap on COM iteration size.MOVE_NOISE_TO_READ_LATER(defaultFalse) — whether to auto-move Noise mail.DRY_RUN(defaultTrue) — safe mode: score/report only, no mailbox mutations.PROTECT_NON_TRIAGE_CATEGORIES(defaultTrue) — guardrail that skips emails with any non-triage category.
Recommended rollout:
- Keep
DRY_RUN=Truefor initial validation. - Keep
MOVE_NOISE_TO_READ_LATER=Falseuntil you confirm yourRead Laterbehavior. - When confident, set
DRY_RUN=False.
Edit:
%OneDrive%\AI_Outlook\config\vip_senders.csv
One SMTP address per line, e.g.
vip1@company.com
vip2@company.com
This repo includes a local template at config/vip_senders.example.csv; copy it to %OneDrive%\AI_Outlook\config\vip_senders.csv on your machine.
VIP senders get a scoring boost (+50).
- The VIP sender list is usually not a secret credential, but it can contain sensitive personal/business contacts (PII).
- Keep real lists local (for example
%OneDrive%\AI_Outlook\config\vip_senders.csv) and out of Git. - This repository intentionally tracks only
config/vip_senders.example.csvand ignores real local VIP CSV files via.gitignore. - Optional: set
VIP_SENDERS_CSV_PATHto point to a different local file location if required by policy.
- Run
outlook_triage.pyto generate a report:outputs\triage_report_*.xlsx
- Open the Excel report, sheet All Scored
- Fill the
labelcolumn with one of:Urgent,Action,Waiting,FYI,Noise
- Save the workbook
- Train the model:
python train_model.py
- Run triage again:
python outlook_triage.py
Even with a model trained, rules override the model when risk is high:
- Rule
Urgentalways staysUrgent - Strong
NoisestaysNoisewhen score < 0 - If
PROTECT_NON_TRIAGE_CATEGORIES=True, emails already carrying non-triage/manual categories are never modified.
This prevents the model from “down-ranking” critical items or clobbering user-managed categories.
- Open Task Scheduler
- Choose Import Task…
- Import:
OutlookTriage_Task.xmlTrainModel_Task.xml
- Edit each task:
- Set User account to your Windows user (not SYSTEM)
- Select Run only when user is logged on
- Confirm Triggers
- Update Actions paths:
- Python:
<repo>\.venv\Scripts\python.exe - Script:
<repo>\outlook_triage.pyor<repo>\train_model.py
- Python:
- Keep MultipleInstancesPolicy = StopExisting to avoid silent skipped runs from a stuck task.
- Keep
TrainModelscheduled weekly. - Also run manual retraining after you add 20–50 new labeled rows.
Outlook COM automation often fails in non-interactive sessions. If a scheduled run doesn’t work, run it while logged in.
Categories/folders:
- Categories:
Urgent/Action/Waiting/FYI/Noise - Folder:
Read Later(created under Inbox if missing)
- This script modifies your mailbox (Categories, Flags, and optionally moves mail).
- Start with a smaller window (
DAYS_BACK=2) andMOVE_NOISE_TO_READ_LATER=Falseuntil you trust it. - Keep your reports; they are your audit trail (
outputs\triage_report_*.xlsx).
- Use Python 3.12 64-bit
- Reinstall
pywin32 - Run:
python -m pywin32_postinstall -install
- Your org may restrict programmatic access to Outlook.
- Try running Outlook and the script as the same user.
- If prompts appear, your security policy may require admin changes (Group Policy / Trust Center).
- Outlook Categories exist per mailbox/profile.
- The script sets
mail_item.Categories = "<Category>". If you want color-coded categories, define them in Outlook manually once.
MIT