Uh oh!
There was an error while loading. Please reload this page.
Email demo mbox - #198
Conversation
- hardened mbox reading to cope with also invalid entries and other codecs, e.g. - ubuntu-devel.mbox and kubuntu-users.mbox contained kind of special mails, which resulted in errors without this hardening first.
- added mbox handling - added filters for first n, or last n mails of mbox - added filters for selecting mails with a date range, after or before - use verbose option to debug ingestion in detail
There was a problem hiding this comment.
Pull request overview
This PR adds mbox file support to the email ingestion tool, enabling processing of mbox mailbox files in addition to individual .eml files. The changes include filtering capabilities (first/last N emails, date ranges) and hardened encoding/header handling for robustness with real-world email data.
Changes:
- Added mbox file format support with index-based and date-based filtering
- Refactored argument parsing to use mutually exclusive groups for --eml and --mbox sources
- Enhanced email header handling to properly coerce Header objects to strings
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 7 comments.
| File | Description |
|---|---|
| tools/ingest_email.py | Added mbox support, filtering options (--first/--last/--after/--before), refactored email iteration logic into _iter_emails function |
| src/typeagent/emails/email_import.py | Added import_emails_from_mbox and count_emails_in_mbox functions, improved header type handling with _header_to_str, enhanced encoding error handling |
| .gitignore | Added /tests/testdata/email-mbox to ignore test data files |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
more memory efficient for large mbox Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
- added testcases
Uh oh!
There was an error while loading. Please reload this page.
Two changes: 1. Default charset: or "utf-8" → or "latin-1" — when no charset header is present, latin-1 preserves all bytes. 2. LookupError fallback: same switch to "latin-1" (no errors param needed since latin-1 never fails on any byte value).
Guido van Rossum (gvanrossum)
left a comment
There was a problem hiding this comment.
I haven't looked at the tests yet, but let's first get these comments out of the way. :-)
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- mbox are expanded to eml - removed test data - fixed argument handling dates - removed first/last argument handling and replaced with limit etc
Bernhard Merkle (bmerkle)
commented
Feb 17, 2026
we could also remove the --eml switch again, because it is now the only way to import |
Guido van Rossum (gvanrossum)
left a comment
There was a problem hiding this comment.
Somehow I can't seem to view test_mbox.py on this flight. I'll look into it later.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Guido van Rossum (gvanrossum)
commented
Feb 17, 2026
Yes please. |
Guido van Rossum (gvanrossum)
left a comment
There was a problem hiding this comment.
Here's the review for test_mbox.py.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Updated .gitignore to reflect new email test data structure. - Modified demos.md to clarify usage of email ingestion tools and updated command-line arguments. - Changed references from `tools/gmail/` to `tools/mail/` in documentation and scripts. - Refactored test cases in test_mbox.py to use new date filtering parameters: --start-date and --stop-date. - Updated ingest_email.py to replace --after and --before with --start-date and --stop-date for date filtering. - Added new tools for downloading Gmail and Outlook emails as .eml files: gmail_dump.py and outlook_dump.py. - Introduced mbox_dump.py for extracting emails from mbox files into individual .eml files.
…in date filtering tests
Bernhard Merkle (bmerkle)
commented
Feb 17, 2026
all review points should be implemented now |
Guido van Rossum (gvanrossum)
left a comment
There was a problem hiding this comment.
Bunch more nits. Getting pretty close!
I don't have the courage to look at outlook_dump.py yet. :-)
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- improve date parsing logic - add option for output-dir similar to gmail client - remove outlook-dump.py as this is handeled in microsoft#199 (copilot added the file arbitraritly, grrr.)
Bernhard Merkle (bmerkle)
commented
Feb 19, 2026
Copilot added the file arbitrarily and i did not notice it during commit. |
Guido van Rossum (gvanrossum)
left a comment
There was a problem hiding this comment.
LGTM
3b6e29b
into
microsoft:mainUh oh!
There was an error while loading. Please reload this page.
## Summary - Document the half-open `[start, stop)` interval convention for date/time range handling in AGENTS.md (agreed in #198) - Bump pyright dependency to 1.1.411 and widen the `uv_build` requirement to `<0.12.0` - Minor import reordering in `src/typeagent/knowpro/answers.py` ## Test plan - [ ] `make check` / `pytest` pass with the updated pyright version
…op)) A search time range whose stop_date carries no time compiled to that day's midnight, so "Jan 1 to Jan 5" became [Jan 1 00:00, Jan 5 00:00) and every message on Jan 5 was silently excluded. Reported in PR microsoft#296. Both timestamp index backends already filter half-open (get_in_range: "End is exclusive"; SQLite: start_timestamp >= ? AND start_timestamp < ?), so the fix is to make the compiled stop the exclusive bound the storage layer expects: for a bare date, midnight of the following day. A stop with an explicit time is already exclusive and is kept as-is. This follows the [start, stop) convention agreed in PR microsoft#198 and documented in AGENTS.md, rather than padding an inclusive end to 23:59:59.999999. Also fixes two boundary inconsistencies this uncovered: - DateRange documented and implemented its end as inclusive (start <= dt <= end) while both storage backends excluded it. It is now documented and implemented as half-open, so the two scope-filtering paths agree: with a timestamp index (lookup_range) and without one (get_text_range_for_date_range, which uses __contains__). - get_time_range_for_conversation builds an inclusive-looking end from the last message's timestamp; documented as prompt-display only, not for index lookups. get_enclosing_date_range_for_text_range already used the exclusive end ordinal's timestamp, so it needed no change. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…op)) (#309) ## The bug `date_range_from_datetime_range` compiled a `stop_date` with no time to that day's midnight, so a query like "Jan 1 to Jan 5" became `[Jan 1 00:00, Jan 5 00:00)` and every message on Jan 5 was silently dropped. Reproduced on `main` before the fix: ``` compiled DateRange: DateRange(2023-01-01 00:00+00:00, 2023-01-05 00:00+00:00) index hits: ['2023-01-01T00:00:00+00:00', '2023-01-04T09:30:00+00:00'] # dropped: 2023-01-05T00:00, 2023-01-05T09:30, 2023-01-05T23:59 ``` This is the bug reported by @LuShadowX in #296 — credit for finding it goes to them. That PR fixed it by padding the (then inclusive) end to `23:59:59.999999`; this PR fixes it with the half-open `[start, stop)` convention agreed in #198 and documented in AGENTS.md instead. ## The fix Three source edits 1. searchlang.py — new exclusive_stop_from_date_time(); a stop_date with no time now rolls to next-day midnight. One if, plus docstrings. 2. interfaces_core.py — DateRange.end comment inclusive → exclusive, and __contains__ <= → <. Plus a docstring. 3. convutils.py — docstring only, no code. Tests: one regression test for the bug, unit tests for the new helper, two DateRange.__contains__ tests, and test_start_and_stop updated to expect Jan 1 instead of Dec 31. Full `make` is green: isort/black clean, pyright clean, 756 tests pass, build OK. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
added mbox handling
testdata which i am using:
currently ingested fwts and bazzaar mbox.
unbunt mbox contain several 10k of mails hence we shall use selectors there (e.g. date ranges)