Campaigns
Send personalized bulk email, simply.
Everything runs on your machine. Your contacts and your password never leave it.
-
1
Connect your mail account
Most providers want an app password rather than your normal one. We will tell you exactly how to get one.
-
2
Try it with sample contacts
See the whole flow in about thirty seconds, without your own file.
Review
Everything checked before a single email goes out.
Pre-flight checks
Send yourself a test
One email, to one address, using your first contact's data. The best way to see exactly what people will receive.
Send
Ready to send
Sending…
Runs
Every send, with what happened to each recipient.
Suppressed addresses
Never mailed, on any campaign. Bounces and unsubscribes land here.
Settings
Stored on this machine only.
Your mail account
Unsubscribe
Gmail and Yahoo have required a one-click unsubscribe header from bulk senders since February 2024. Without one, more of your mail is filtered.
Sending speed
AI personalization
Optional. The model fills labelled gaps and never sees the rest of your email.
How it works
Wrap one sentence in an ai block. Everything outside it
is byte-identical for every recipient — that is the point.
Hi {{ first_name }},
{% ai "opener" max_words=25 fallback="Hope your week is going well." %}
One warm sentence about {{ company }}. No greeting, no exclamation marks.
{% endai %}
The rest of my email is the same for everyone.
Provider
Point this at Ollama, LM Studio, vLLM, Groq, OpenRouter — anything that speaks the OpenAI chat API. Local models need no key and make no cloud call.
Plugins
Add transports, AI providers, contact sources and UI panels without forking.
Writing one
Publish a package that exposes a sahajmails.plugins
entry point, or drop a .py file in your plugins folder and enable it
below. A plugin runs with your full privileges — the same trust model as any
pip install.