Burak Kaan Köse 2040d4abce Optimize mail fetching with batch DB queries and in-memory caching (#827)
* perf: batch-load folders, accounts, and contacts in FetchMailsAsync

Replace the sequential per-mail property-loading loop with a three-step
batch pre-load strategy, eliminating the N+1 DB call pattern that was
the main bottleneck when building the mail list with threading enabled.

Changes:
- Pre-seed the folder cache from MailListInitializationOptions.Folders
  so that the most common folders (inbox, sent, etc.) never trigger a DB
  lookup at all.
- Load all accounts in a single GetAccountsAsync() call instead of one
  GetAccountAsync() call per mail (typically 1–5 accounts total).
- Fetch all sender contacts in a single SQL IN(...) query via the new
  GetContactsByAddressesAsync() method instead of one query per address.
- Property assignment is now fully synchronous (no awaits in the loop)
  since all data is pre-loaded into plain Dictionary<K,V>.
- Thread-expansion follows the same pattern: new folder IDs are loaded
  in parallel via Task.WhenAll; new contact addresses are batch-fetched
  with a second IN(...) query.
- Also apply batch pre-loading to GetMailItemsAsync (used by merge-inbox
  sync path) which had the same sequential issue.
- Remove the now-unused LoadAssignedPropertiesWithCacheAsync helper and
  the ConcurrentDictionary dependency it required.
- Tighten GetMailsByThreadIdsAsync to skip the Id NOT IN clause entirely
  when the exclusion set is empty.

https://claude.ai/code/session_018bqahGc6zi95JJhc2aARKS

* test: add MailFetchingTests with correctness and performance coverage

Adds integration tests for MailService.FetchMailsAsync that exercise the
full real-service stack (MailService → FolderService / AccountService /
ContactService) backed by the shared in-memory SQLite helper.

Four tests are included:

• ExpandsSiblingsOutsidePage – proves thread expansion fetches mails that
  fall beyond the initial SQL page (6 mails, page=4, expects 6 returned).

• NeverExpandsSiblings – proves threading is truly opt-in; with
  CreateThreads=false the result exactly matches the raw page size.

• ResolvesFromAllThreeSources – verifies contact resolution for a known
  contact (from the AccountContact table), an unknown sender (ad-hoc
  fallback), and a self-sent mail (built from account metadata).

• 1000Mails_70Threads_CompletesWithinBudget – the performance scenario:
  1 000 mails (70 threads × 7 + 510 standalone), 40 rotating sender
  addresses (20 with DB contacts). Times and reports two scenarios:
    - Default first-page fetch (100 mails) + expansion of one partial
      thread (expects > 100 mails returned).
    - Full load of all 1 000 mails with threading enabled (expects
      exactly 1 000 mails returned, all 70 threads intact, < 5 s).

  Elapsed times for both scenarios are written to xUnit test output so
  they appear in CI logs and can be tracked across builds.

https://claude.ai/code/session_018bqahGc6zi95JJhc2aARKS

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-01 09:14:02 +01:00
2025-11-14 18:51:48 +01:00
2024-04-18 01:44:37 +02:00
2026-02-06 01:18:10 +01:00
2024-04-18 01:44:37 +02:00
2024-04-18 01:19:30 +02:00
2024-07-01 22:48:45 +02:00
2026-01-03 19:33:36 +01:00

Wino Mail

Native mail client for Windows device families.


pdark

Motivation

I'm a big fan of Windows Mail & Calendars due to its simplicity. Personally, I find it more intuitive for daily use cases compared to Outlook desktop and the new WebView2 powered Outlook version. Seeing Microsoft deprecating it dragged me into starting to work on Wino a couple of years ago. Wino's main motivation is to bring all the existing functionality from Mail & Calendars over time without changing the user experience that millions have loved since the Windows 8 days in Mail & Calendars

Features

  • API integration for Outlook and Gmail
  • IMAP/SMTP support for custom mail servers
  • Send, receive, mark as (read,important,spam etc), move mails.
  • Linked/Merged Accounts
  • Toast notifications with background sync.
  • Instant startup performance
  • Offline use / search.
  • Modern and responsive UI
  • Lots of personalization options
  • Dark / Light mode for mail reader

Download

Download latest version of Wino Mail from Microsoft Store for free.

Beta Releases

Stable releases will always be distributed on Microsoft Store. However, beta releases will be distributed in GitHub Releases. Please keep in mind that beta releases might not be for daily use, only for testing purposes and recommended for experienced users or developers. Beta releases are also managed manually. Therefore, code in the repository might be ahead of the released Beta version at the moment. Make sure to compare versions before tryout out the Beta version.

These releases are distributed as side-loaded packages. To install them, download the .msixbundle file in GitHub releases and follow the steps explained here.

Contributing

Check out the contribution guidelines before diving into the source code or opening an issue. There are multiple ways to contribute and all of them are explained in detail there.

Donate

Your donations will motivate me more to work on Wino in my spare time and cover the expenses to keep project's website alive.

  • You can donate via Paypal by clicking here
  • You can buy Unlimited Accounts add-on in the application. It's a one-time payment for lifetime, not a monthly recurring payment.
S
Description
Built-in Mail & Calendars app clone for Windows.
Readme 27 MiB
Languages
C# 95.8%
JavaScript 3.7%
Python 0.4%
HTML 0.1%