Scheduled email reminders that actually arrive.
Write an email once — attach files, images or archives — and Aevistle sends it on time, even with the window closed. Once, every weekday at 09:00, on the 1st of the month, or on any cron expression you like. It knows your public holidays, so the Monday report does not go out on a Monday nobody is working. Windows and Android, no account, no server, no telemetry. Two devices stay in step over your own network — no cloud in the middle.
The weekly report every Friday. The invoice on the 1st. The birthday message at midnight while you are asleep.
Every mail client can send an email. Almost none of them can promise you it will go out at 07:00 next Tuesday with the right file attached, whether or not you remember, whether or not the app is open.
Aevistle is that promise first. No account to create — it connects to the SMTP server you already have (Gmail, Outlook, QQ, 163, your company's server) and sends. Receiving is there too, but it stays out of the way until you turn it on: point an account at its IMAP server and Aevistle pulls in a unified inbox, lifts out verification codes and login links automatically, and leaves everything else alone by default.
People use it to send a weekly report every Friday at 17:00 · remind a class about homework the night before it is due · mail an invoice on the 1st of every month · post a birthday message at midnight while asleep · deliver a rent reminder every 30 days · schedule a follow-up so a reply lands in the morning rather than at 02:00 · grab a login code the moment it lands without switching apps.
It might not be for you if you want a full-featured mail client — no folder management, no push IDLE sync, no server-side delete, on purpose — a marketing tool with tracking pixels and open rates, or a hosted service that keeps sending while your devices are switched off. Aevistle sends and reads from your machine using your mailbox, which is exactly why it needs no account of its own and collects nothing.
Aevistle has no server. There is no account to create, no telemetry and no crash reporting.
A short, fixed list of things ever leaves your device: the SMTP connection to
your own provider; the IMAP connection to your own provider, for accounts
where you turned receiving on; a remote image in a received message, only
when you ask for that one by name; an update check to api.github.com, if
you leave it on; and one year of public holiday dates, when you press
"check online". The last two are whitelisted by host and exact path and leave
from the trusted process, not from the part of the app that renders mail —
which has no outbound network reach at all.
Pairing two devices adds nothing to that list. They talk to each other on your own network, with no cloud and no relay in the middle.
With updates switched off, every remaining request in that list is one you pressed a button for.
Where each thing is stored, what moving the data folder does, and the two things that deliberately stay behind → docs/PRIVACY.md.
| ⏰ Fires when closed | A tray process on Windows, an exact alarm plus WorkManager on Android. Closing the window does not cancel your reminders. → |
| 🔁 Real recurrence | Once, every N minutes, daily, weekly, monthly, yearly, or a full 5-field cron expression. → |
| 📎 Attachments that survive the wait | Files are snapshotted when you schedule, so moving or renaming the original does not silently break the send. → |
| 🎌 Working calendars | Public holidays, weekends of your own choosing, 调休 make-up days, six country presets and .ics both ways. Each reminder opts in. → |
| 🌐 Delivery windows | A reminder lands inside the recipient's working day, not yours — and it is reported, never held back, when the windows cannot agree. → |
| 📆 The month grid is the schedule | Drag to move, click to open, tinted by how busy the day is — plus recipient chips, a body preview and delivery badges. → |
| 📥 Optional inbox | IMAP, unified across accounts, remote images blocked by default, with verification codes lifted onto a screen of their own. → |
| 🔤 Merge variables | Per-recipient contact fields plus calendar ones like {{nextWorkday}}, resolved at send time, with Cc and Bcc dropped from the copies. → |
| 🔐 Passwords stay put | Encrypted by the OS: DPAPI on Windows, the hardware-backed Keystore on Android. Never in the settings file, never in an export. → |
| 🎨 Seven visual styles | Each with a real light and a real dark form, and one of them WCAG AAA throughout rather than approximately. → |
Thirty-six of these, each with the reasoning behind it → docs/FEATURES.md
What changed recently → Releases
(each tag has notes; older ones are also in the release-notes-0.1.*.md files).
Grab the latest build from Releases.
| Platform | File to pick | Notes |
|---|---|---|
| Windows 10/11 (x64) | Aevistle-<version>-win-x64-setup.exe |
Installer, adds a Start-menu and desktop shortcut |
| Windows 10/11 (x64) | Aevistle-<version>-win-x64-portable.exe |
Single file, no installation, runs from a USB stick |
| Android 7.0+ | Aevistle-<version>.apk |
Phones and tablets. Enable "install unknown apps" for your browser or file manager for this first install; later updates are offered inside the app. |
<version> is whatever the latest release
page is showing — the badge at the top of this page reads it from the same
place. Deliberately not written out here, so this table cannot go stale.
Verifying a download. Every release publishes
SHA256SUMS.txt, a detached signatureSHA256SUMS.txt.asc, and the public key that made it:gpg --import aevistle-public-key.asc gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt sha256sum -c SHA256SUMS.txtThe checksums alone prove the file arrived intact; the signature proves it came from this project's key. The fingerprint is in SECURITY.md.
Windows SmartScreen will warn about an unrecognised publisher. That is what a release without a paid code-signing certificate looks like; choose More info → Run anyway, or check the SHA-256 from the release page first.
- Add your mailbox. Settings → Add account, then type your email address.
The domain is enough: Aevistle fills in the provider, both servers, both
ports, the encryption and the username, and prints what it decided directly
under the box. A domain no preset knows still gets values, guessed from the
smtp./imap.convention — the panel says so rather than letting a guess pass for a certainty. - Get an app password. Gmail, Outlook, Yahoo, iCloud, QQ and 163 all refuse your normal login password from a third-party app. The account dialog links straight to the page where you create one.
- Test the connection. One button. It authenticates without sending anything, so you find out now rather than at 03:00.
- Write your reminder, attach what you need, and choose Schedule.
"Aevistle has not completed the Google verification process" — Error 403: access_denied. Expected — this project's Google OAuth registration is not verified for public use. Use an app password instead (step 2 above); it needs no verification and is the supported path for Gmail. Details, and how to register your own OAuth client if you want that route instead, are in
src/core/oauth.ts.
For scheduled sends to fire while the window is closed, leave Keep running in the tray on (Windows), and allow exact alarms and notifications when Android asks.
The threat model, the hardening choices, and how to report a vulnerability are in SECURITY.md.
The short version: the renderer runs with no Node access, context isolation on and a strict CSP; every string bound for a mail header is rejected if it contains a line break (that is how open relays happen); TLS certificates are verified unless you explicitly turn that off per account; a received message's HTML is sanitized in the main process to a strict allowlist before it ever reaches the renderer, and rendered in a sandboxed iframe with no script execution allowed regardless; and the Android alarm receiver is not exported, so no other app can make Aevistle send mail.
You can check all of that yourself with npm run audit:self — 21 checks,
plain-language output, exit code 1 if anything needs attention.
Requirements — Node.js 20+, and for Android: JDK 17+, Android SDK
(platform 36, build-tools 35+). npm run build:android finds a JDK and an SDK
that are installed but not on PATH, so setting JAVA_HOME is optional.
git clone https://github.com/Aevorine/Aevistle.git
cd Aevistle
npm install| Task | Command |
|---|---|
| Run in a browser (no SMTP, everything else live) | npm run dev |
| Type-check | npm run typecheck |
| Security audit (21 checks) | npm run audit:self |
| Everything CI runs (42 checks) | npm run check |
| Run the desktop app | npm start |
| Build Windows installers | npm run dist:win |
| Build the Android APK | npm run build:android |
Release signing for Android reads ~/.aevistle/keystore.properties or the
AEVISTLE_KEYSTORE* environment variables. Without either, the build falls
back to the debug key so you still get an installable APK.
One React + TypeScript interface, two native shells.
src/core/ platform-independent: domain model, recurrence engine,
validation, SMTP provider presets — no DOM, no Node, no Android
src/ the React interface (six locales, seven visual styles, each in
a real light and a real dark form)
↓ PlatformBridge — the single seam between the UI and an operating system
electron/ Windows: nodemailer + imapflow, DPAPI secret storage, tray,
hybrid tick/precise scheduler, HTML sanitization for received mail
android/ Android: JavaMail (send + receive), Keystore, AlarmManager + WorkManager
More detail in docs/ARCHITECTURE.md.
Not promises — the things most likely to come next.
- OAuth 2.0 for Gmail and Microsoft 365, so app passwords stop being needed
- A rich-text composer. Inline images already work; the box itself is still plain text with Markdown
- macOS and Linux desktop builds (the code already targets them)
-
docs/FEATURES.mdin the other five languages - iOS
Something missing? Open an issue — feature requests are genuinely welcome.
Pull requests are welcome. See CONTRIBUTING.md for the layout of the codebase and what a good change looks like, and CODE_OF_CONDUCT.md for how people are expected to treat each other here. Adding a seventh language is one file and needs no build tooling — the type system tells you exactly which strings are missing.
Bug reports and feature requests have
templates; every pull
request runs the same npm run check you would run locally.
| English | 简体中文 | Français |
| Español | Русский | العربية |
MIT © Aevistle contributors

