Minimal local Python desktop/CLI pipeline for summarizing unread email into a Markdown file.
The app is intentionally not an autonomous agent. It has no email mutation capabilities and uses the local LLM only as a text summarization function.
- Opens IMAP mailbox with
readonly=Truein IMAP mode. - Fetches IMAP message content with
BODY.PEEK[]. - Does not include email sending, draft, label, folder, or mailbox mutation functions.
- Does not use SMTP, OAuth, databases, web UI, agent frameworks, vector stores, or external LLM APIs.
- Writes only Markdown files inside the configured output folder.
- In local test mode, reads only
.emlfiles from the configured project-local test folder. - The GUI can start
llama-server.exe, but only from the explicit executable/model paths. It does not accept arbitrary shell commands and usesshell=False.
Install Python 3.11 or newer, then install runtime dependencies:
pip install -r requirements.txtCreate your local config from the public example:
Copy-Item config.example.yaml config.yaml -Forceconfig.yaml is intentionally ignored by Git because it contains local paths and account settings.
Run the GUI directly from source:
python gui.pyThe GUI lets a user:
- choose local
.emltest mode or read-only IMAP mode - select the test email folder and output folder
- configure the local llama.cpp endpoint/model
- start, stop, and check the local llama.cpp server
- run the summary job with visible progress logs
- copy the generated Markdown path
- switch the interface theme between light, dark, and system
- switch the interface language between Chinese and English
The UI preference fields are stored in your local config.yaml:
ui:
theme: "system"
language: "zh"Valid theme values are light, dark, and system. Valid language values are zh and en.
Configure these fields in the GUI or config.yaml:
llm_server:
executable_path: "E:/llama.cpp/llama-server.exe"
model_path: "E:/llama.cpp/models/Qwen3-4B-Instruct-2507-Q4_K_M.gguf"
host: "127.0.0.1"
port: 8080
context_size: 8192Click Start llama.cpp, then Check API. When the API is ready, run Generate summary.
The LLM endpoint should match the launcher host/port:
llm:
endpoint: "http://localhost:8080/v1/chat/completions"The default config.example.yaml is set to local .eml testing:
input:
mode: "local_eml"
test_folder: "test_emails"Put test .eml files in test_emails/.
CLI run:
python run.pyExpected output:
Loaded config.
Reading local test email folder...
Found 2 local test emails.
Summarized 2 emails.
Markdown summary written to: ...\outputs\unread_email_summary_2026-05-08_103000.md
Done.
To switch back to real mailbox reading, edit config.yaml or use the GUI:
input:
mode: "imap"
test_folder: "test_emails"Set your IMAP account values. Do not put your email password in the file. Set the environment variable named by email.password_env_var.
PowerShell example:
$env:EMAIL_APP_PASSWORD = "your-app-password"Install build dependency:
pip install -r requirements-build.txtBuild:
.\scripts\build_windows_gui.ps1The executable will be created at:
dist\EmailSummaryAgent\EmailSummaryAgent.exe
The build script also copies config.example.yaml as config.yaml, copies test_emails/, and creates outputs/ next to the executable.
Do not commit dist/ to the source repository. Attach packaged builds to GitHub Releases instead.
pip install -r requirements-dev.txt
pytest