Title: Casa Mail
Author: sendemailtoday
Published: <strong>June 5, 2026</strong>
Last modified: June 5, 2026

---

Search plugins

![](https://ps.w.org/casa-mail/assets/banner-772x250.png?rev=3562067)

![](https://ps.w.org/casa-mail/assets/icon-256x256.png?rev=3562067)

# Casa Mail

 By [sendemailtoday](https://profiles.wordpress.org/sendemailtoday/)

[Download](https://downloads.wordpress.org/plugin/casa-mail.1.4.1.zip)

 * [Details](https://wordpress.org/plugins/casa-mail/#description)
 * [Reviews](https://wordpress.org/plugins/casa-mail/#reviews)
 *  [Installation](https://wordpress.org/plugins/casa-mail/#installation)
 * [Development](https://wordpress.org/plugins/casa-mail/#developers)

 [Support](https://wordpress.org/support/plugin/casa-mail/)

## Description

Casa Mail intercepts `wp_mail()` and delivers each message through the Casa Mail
transactional email service operated by CodeCasa Studios on the OnlineStoreNotifications
infrastructure (api.onlinestorenotifications.com).

If your WordPress site doesn’t send emails yet, Casa Mail is the perfect solution
to start sending with no technical experience or SMTP API keys. Already send mail?
Switch to Casa Mail, save money and improve deliverability.

The plugin is intended for sites that want an easy, hassle free wp_mail setup! Improve
deliverability of order confirmations, password resets, account-verification emails,
and similar transactional traffic with our built-in SMTP server. It does not change
anything about how WordPress queues mail; it only changes how the SMTP step is performed.

#### How it works

 * `pre_wp_mail` is hooked at priority 1. Each call is converted to a JSON payload
   and POSTed to the gateway.
 * If the gateway accepts on the first POST, `wp_mail()` returns true and the message
   is durably enqueued upstream.
 * If the gateway is unreachable on the first POST, the payload is written to a 
   durable outbox table (`<prefix>casamail_outbox`) and a cron tick retries with
   30s, 2m, 10m backoff.
 * A separate transmit log table (`<prefix>casamail_sends`) records every attempt
   for visibility on the plugin dashboard. Rows older than 30 days are pruned automatically.

#### Onboarding

After activation, an in-WordPress wizard collects:

 1. Site name, site URL, contact email address.
 2. A 6-digit code emailed by the gateway to confirm the address.
 3. Plan selection (one free plan today; paid tiers planned).
 4. Optional: authenticate a sender domain so customer email goes out from your domain
    with aligned DKIM.

#### Trademark note

This plugin is not affiliated with or endorsed by WooCommerce, Automattic, or any
third party. The WooCommerce name appears only as a compatibility note (when WooCommerce
is detected, the plugin’s admin menu attaches under it for convenience; otherwise
it lands under Settings).

### External services

This plugin transmits data to a third-party SMTP gateway. WordPress.org policy requires
this be disclosed.

#### Endpoints contacted

The plugin makes HTTPS requests to:

 * `https://api.onlinestorenotifications.com/v1/onboard/request` — during onboarding,
   to send your verification email.
 * `https://api.onlinestorenotifications.com/v1/onboard/verify` — during onboarding,
   to confirm the code and provision an account.
 * `https://api.onlinestorenotifications.com/v1/send` — for every `wp_mail()` call
   once the plugin is onboarded.
 * `https://api.onlinestorenotifications.com/v1/email/domain` (GET / add / verify)—
   when the site administrator interacts with the Sender Domain page.

The gateway is operated by CodeCasa Studios under the Casa Mail brand and runs on
the OnlineStoreNotifications infrastructure. Casa Mail and OnlineStoreNotifications
are sister brands of the same company; the API hostname reflects the shared backbone
rather than a third-party dependency.

#### Data sent

During onboarding (one-time, before any send): site administrator email address,
site name, site URL.

For each `wp_mail()` call once onboarded: sender email address, sender name, recipient
email address(es), subject, message body, message headers (after stripping `From`/`
To`/`Subject`/`Date`/`Message-ID`/`MIME-Version`/`Content-Type`/`Content-Transfer-
Encoding`).

#### Terms and privacy

 * Terms of service: https://sendemailtoday.io/terms.html
 * Privacy policy: https://sendemailtoday.io/privacy.html

### Privacy

When activated, this plugin transmits email content (recipient, sender, subject,
body, headers) to a third-party SMTP gateway for delivery. This is the plugin’s 
only purpose. The data lifecycle is described above under “External services” and
on the linked privacy policy.

The plugin also writes a `wp_add_privacy_policy_content()` block describing what
is transmitted; this lets site administrators include the disclosure in the WordPress-
managed privacy policy page (Settings -> Privacy).

Account deletion: a “Request account deletion” button on the plugin’s Settings page
emails the gateway operator. Upon confirmation, the tenant record, API key(s), domain-
authentication records, and recent sending history are removed from the gateway 
side. The plugin uninstall additionally removes the plugin’s WordPress-side options
+ tables.

## Screenshots

 * [[
 * Dashboard with daily-cap stat card and recent sends panel.
 * [[
 * Email Gateway Settings
 * [[
 * Email Sent Logs

## Installation

 1. Upload the plugin zip via Plugins -> Add New -> Upload Plugin, or extract `casa-
    mail` into `wp-content/plugins/`.
 2. Activate.
 3. WooCommerce -> Casa Mail (or Settings -> Casa Mail if WooCommerce is not installed)
    launches the onboarding wizard.

The plugin requires PHP 7.4 or newer and WordPress 6.0 or newer.

## FAQ

### Does this replace existing SMTP plugins?

Yes. The plugin hooks `pre_wp_mail` at priority 1, which runs before most SMTP plugins.
For predictable behaviour, disable other mail routers (FluentSMTP, WP Mail SMTP,
etc) when this plugin is active.

### What happens if the gateway is unreachable?

Calls land in a durable retry outbox and a 60-second cron drains them with 30s /
2m / 10m backoff. After three failed retries the row is marked failed and preserved
for diagnosis. `wp_mail()` always returns true (the plugin guarantees zero-loss 
+ zero-blocking).

### How is the From: address handled?

If the site has verified a sender domain through the plugin’s Sender Domain page,
the plugin rewrites the From address to `noreply@<verified-domain>` so DKIM aligns.
If the caller (WooCommerce, WordPress core, etc) already supplies a From address
inside the verified domain, that address is honored. A “Default From” override is
also available on the Settings page.

### Where can I see what was sent?

The dashboard’s “Recent sends” panel lists the most recent 10 wp_mail() calls intercepted
by the plugin. The Logs page extends this to the last 200. Rows older than 30 days
are pruned automatically.

### How do I delete my account?

Settings -> Delete my account -> Request account deletion. This emails the gateway
operator who removes the tenant + API key + history within 48 hours and replies 
to the contact email on completion. The plugin uninstall (Plugins -> Delete) handles
the WordPress-side cleanup.

### Is this affiliated with WooCommerce?

No. WooCommerce is an Automattic trademark and this plugin is not endorsed by or
affiliated with Automattic. The plugin only mentions WooCommerce as a compatibility
note (the admin menu nests under WooCommerce when present, for ergonomic reasons).

## Reviews

There are no reviews for this plugin.

## Contributors & Developers

“Casa Mail” is open source software. The following people have contributed to this
plugin.

Contributors

 *   [ sendemailtoday ](https://profiles.wordpress.org/sendemailtoday/)
 *   [ codecasastudios ](https://profiles.wordpress.org/codecasastudios/)

[Translate “Casa Mail” into your language.](https://translate.wordpress.org/projects/wp-plugins/casa-mail)

### Interested in development?

[Browse the code](https://plugins.trac.wordpress.org/browser/casa-mail/), check 
out the [SVN repository](https://plugins.svn.wordpress.org/casa-mail/), or subscribe
to the [development log](https://plugins.trac.wordpress.org/log/casa-mail/) by [RSS](https://plugins.trac.wordpress.org/log/casa-mail/?limit=100&mode=stop_on_copy&format=rss).

## Changelog

#### 1.4.0

Renamed the plugin to Casa Mail (display name and slug). No functional change to
mail handling – the same CodeCasa-operated transactional gateway on the OnlineStoreNotifications
backbone. WordPress option keys, the outbox table, and the sends-log table now use
the `casamail_` prefix; the admin menu pages, AJAX actions, cron hooks, script handles,
and PHP namespace were prefixed to match. Existing installs re-run onboarding once
after upgrade because the stored option keys changed prefix.

#### 1.3.5

Sender Domain page no longer shows the yellow “Using Cloudflare?” advice boxes once
a record is OK. They were setup hints meant for users who hadn’t added the entries
yet; sitting next to a green VERIFIED pill they made it look like something was 
wrong. Now hidden per-record: the apex “trim the dot” hint hides once overall status
is `verified`, the Return-Path “set to DNS only” hint hides once that individual
record’s status is `OK`.

#### 1.3.4

WordPress.org Plugin Check pass. All ERROR-level findings resolved: `translators:`
comments added on the two placeholder-bearing translation strings; output escaped
in the dashboard stat cards (`esc_html(number_format_i18n(...))`); `parse_url()`
replaced with `wp_parse_url()`; `$wpdb->prepare()` brought to the OUTBOX_TABLE INSERT;`
Tested up to` bumped to 7.0. Removed `load_plugin_textdomain()` (auto-loaded on 
WP.org since 4.6). Added `phpcs:disable` blocks with documented rationale for the
false-positive WARNING-level findings: NonceVerification on AJAX handlers (the nonce
IS verified – in `ajax_guard()`, just not inline), DirectDatabaseQuery + InterpolatedNotPrepared
on the plugin’s own custom tables (table names are hard-coded class constants, no
user input, no object-cache layer for transmit logs), and PrefixAllGlobals on template
files whose locals come from `extract()`. Bootstrap rewritten to use a closure so
no `$set_gateway` global leaks into the WordPress namespace.

#### 1.3.3

Dashboard banner (“Sending from the shared sender”) no longer hardcodes `noreply@onlinestorenotifications.
com` – it now shows the tenant’s actual `<slug>@onlinestorenotifications.com` address(
the inbox they picked at Step 3), matching what customers actually see in the From
line. Fallback is the legacy `noreply@` for tenants on installs older than 1.1 who
don’t have a mailbox_slug yet.

#### 1.3.2

Step 3 (“Your inbox”) no longer pre-locks the domain in the customer’s mental model.
The preview now reads `slug@...` (with a literal ellipsis after the `@`), and a 
short helper line tells them Step 5 is where they pick the actual domain (the shared
one, or their own). The host hint next to the rename input is also `@...`. Step 
5 “Use this address” button no longer pops a confirmation modal – the card already
explains the trade-offs, the second confirmation was pure friction; the click now
fires the AJAX straight away. Stale “noreply@” copy in the populated Sender Domain
page banner and the success notice is gone; both now use the tenant’s actual slug
address. Translated into all 8 bundled locales.

#### 1.3.1

Step 5 (the sender-domain choice) now shows the user’s actual inbox slug + addresses
instead of generic placeholders. The page leads with “Your inbox name is `acmestore`.
Where would you like to use it?” and each choice card previews the literal address
customers will see (`acmestore@onlinestorenotifications.com` or `acmestore@yourstore.
com`). Inline domain-input form’s example also uses the user’s slug. SG.mailboxSlug
+ SG.mailboxEmail stay in sync through OTP verify + rename so step 5 always reflects
the chosen slug, even if the user renamed in step 3.

#### 1.3

Wizard step 5 (“Sender domain”) rewritten for non-technical users:
 * Step heading
is now “Where should your emails come from?” instead of “Authenticate your sender
domain”. * Two equal-weight side-by-side cards present the choice as either/or, 
not as “do this complex thing OR skip it”. One card is “Use the Casa Mail address”(
easiest), the other is “Use your own domain” (on-brand). On phones the cards stack.*
Domain input field is hidden until the user picks “Set up my own domain” – clicking
the card’s button reveals a small inline form. Keeps the choice screen uncluttered.*
DNS-records copy after provisioning uses plain English: “Add these 3 entries to 
your domain settings” instead of “Publish these 3 DNS records”. Mentions Cloudflare/
GoDaddy / Namecheap / Google Domains by name so users recognise where they’re going.“
Verify DNS” button relabelled “Check my domain”. * SPF helper text explains the “
merge into existing v=spf1 record” instruction in plain English. * Cloudflare grey-
cloud tip explains why (not just “set to DNS only”) – replies coming back from your
customers depend on it. * The duplicate “Use shared sender” button in the wizard
footer is gone – the shared-sender path is now one of the two main cards. The footer
now shows only “I will decide later” + the post-verify “Finish” CTA.

#### 1.2

 * Use the tenant’s chosen `mailbox_slug` as the From local-part on their own verified
   domain too, not just on the OSN side. Onboarding picks (or the user renames) `
   acmestore` as the inbox handle, and from then on customer-facing emails go from`
   acmestore@theirdomain.com` (after domain verification) AND `acmestore@onlinestorenotifications.
   com` (Reply-To target, where replies route through). One consistent identity 
   across both addresses; no more `noreply@` in the customer-facing From.
 * Gateway’s `activateTenantSender` now overwrites any `@onlinestorenotifications.
   com` sender_email when a tenant verifies their own domain — previously it only
   matched the legacy shared `noreply@osn` value, leaving v1.1 per-tenant slug addresses
   stuck on OSN after domain verification.
 * Operator-configured `default_from` on the Settings page still wins over the slug-
   based default.

#### 1.1

Per-tenant inbox feature (foundation for the paid webmail tier):
 * Every onboarded
tenant now gets their own inbox at `<slug>@onlinestorenotifications.com`. The slug
is derived from the site URL host (strips common subdomain noise like `www.`, `shop.`,`
sms.`) with a fallback to `store-xxxxxx` for collisions. * New wizard step between
OTP verification and plan selection lets the user accept the suggested inbox name
or rename it inline with live availability checking. * When the tenant is on the
shared sender, every wp_mail() now goes from `<slug>@onlinestorenotifications.com`
instead of the generic `noreply@onlinestorenotifications.com`. Replies route directly
to the tenant’s inbox. * When the tenant has authenticated their own domain, From
stays on their domain but a `Reply-To: <slug>@onlinestorenotifications.com` header
is injected so replies still arrive in the OSN inbox. * Free tier auto-forwards 
inbox mail to the tenant’s contact email via a Postfix virtual-alias map backed 
by a MariaDB view. The view is regenerated every 60s by a host systemd timer; no
manual sync needed when tenants onboard or rename. * New gateway endpoints: `GET/
v1/email/mailbox` (read current inbox state), `POST /v1/email/mailbox/check` (live
slug validation without mutating), `POST /v1/email/mailbox/rename` (atomic rename
with UNIQUE-index protection). * A `webmail_enabled` flag exists on tenants for 
the future paid tier; when flipped on, the alias destination changes from “forward
to contact_email” to “store in Maildir” — Roundcube auto-login + IMAP provisioning
will arrive in a follow-up release.

#### 1.0

First stable public release. Consolidates the 0.4.x WordPress.org compliance work
and the 0.5.0 shared-sender feature, plus two correctness fixes shipped during end-
to-end testing:
 * Onboarding submenu is now registered even when the plugin is 
already onboarded – the wizard URL gracefully renders the “Setup is already complete–
Open dashboard” branch instead of WP’s bare “not allowed” page when the admin_init
redirect races a page-cache or back-button. * Stale-clone fix on the standalone 
Sender Domain page: the verified-state celebration banner (cloned from a template
with the `hidden` HTML attribute) was being forced visible by `display: flex` in
CSS, leaking a green “verified” banner onto the pending-records view. CSS now uses`:
not([hidden])` so the attribute wins. * `activateTenantSender()` on the gateway 
now overwrites the shared-sender address when a tenant who previously opted into
the shared path verifies their own domain. Previously the `COALESCE` guard kept `
sender_email` pinned to `noreply@onlinestorenotifications.com` forever, so verification
succeeded but sends never moved over to the customer’s domain.

#### 0.5.0

 * Add the “Use shared sender” option to the onboarding wizard’s step 4 and the 
   standalone Sender Domain page. Tenants who don’t want to authenticate their own
   domain can route every wp_mail() from `noreply@onlinestorenotifications.com` 
   instead – DKIM + SPF + Return-Path are already configured for that domain on 
   the gateway side, so mail arrives signed and aligned (cost: Gmail shows “via 
   onlinestorenotifications.com” in the sender chrome).
 * New gateway endpoint: `POST /v1/email/domain/skip` – sets `tenants.sender_email`
   to the shared address so Transport’s `fromFor()` picks it up on every send.
 * Plugin’s `from_email()` now short-circuits to the shared address when `domain_status
   === 'shared'`, so the WP-side `wp_casamail_sends` log reflects the actual From
   the recipient will see (no drift between plugin log and Postal envelope).
 * Inject a `Reply-To` header whenever the plugin rewrites the From, so customer
   replies still reach the original mailbox (caller-supplied From, or the tenant’s
   contact email as fallback). Skipped when the caller already set Reply-To.
 * Dashboard banner gains a blue informational variant for the shared-sender state(
   vs. the existing orange warning for “authenticate your domain”).

#### 0.4.2

 * Switch the account-deletion + error-message support address from `support@sendemailtoday.
   io` to `support@onlinestorenotifications.com`. The OSN mailbox already exists
   on the gateway’s role-mailbox stack and is the same support address the onboarding
   OTP email body has always referenced.

#### 0.4.1

 * Replace the inline `<script>` block in `show_onboarding_notice` with a separately-
   enqueued `assets/js/notice-dismiss.js`, loaded only when the notice would render.
 * Remove dead URL-based notice-dismiss code path (was unreachable from the UI –
   everything went via the AJAX path).
 * Route the account-deletion request email through the gateway instead of bypassing
   it – the previous `X-SET-Outbox: 1` shortcut relied on the host’s PHP `mail()`
   being functional, which most managed WordPress hosts disable.
 * Drop unused `set_gateway_get_dashboard` and `set_gateway_get_logs` AJAX endpoints
   that were scaffolded for a polling feature never implemented.
 * Replace the `woocommerce` readme tag with `deliverability` to sidestep the trademark
   concern when listing on WordPress.org.

#### 0.4.0

 * Add `readme.txt` and WP.org submission compliance.
 * Add `wp_add_privacy_policy_content()` registration for Settings -> Privacy.
 * Add data-disclosure paragraph on the onboarding wizard’s first step.
 * Add Settings -> Delete my account flow that emails the gateway operator.
 * Make the persistent onboarding notice dismissible per-user, resurfaces on plugin
   upgrade.
 * Replace `window.prompt()` calls with an accessible in-page modal.
 * Move every user-facing JS string through `wp_localize_script` so the plugin is
   fully translatable.
 * Add `load_plugin_textdomain` and ship translations for `de_DE`, `es_ES`, `fr_FR`,`
   it_IT`, `ja`, `nl_NL`, `pl_PL`, `pt_BR`.
 * Replace `wp_unschedule_event` with `wp_clear_scheduled_hook` in deactivate to
   defend against duplicate-scheduled hooks.
 * Annotate intentional unprepared `$wpdb` queries with `phpcs:ignore` comments 
   + justifications.
 * Replace inline `style=""` attributes with CSS classes (`set-gw-notice-cta`, `
   set-logs-section-heading`, `set-danger-zone`, `set-gw-modal`).
 * Move sales copy out of the plugin header into the Description section here.

#### 0.3.2

 * Add `Sent (24h)` stat card on the dashboard.

#### 0.3.1

 * Add post-verify celebration banner with Send Test Email and Open Dashboard CTAs.
 * Patch the verifier to bypass `systemd-resolved` and query DNS via `dig @1.1.1.1`
   directly so a freshly-flipped Cloudflare proxy switch is reflected immediately.

#### 0.3.0

 * Auto-rewrite From to `noreply@<verified-domain>` when the WC-supplied From is
   outside the verified domain.
 * Add `wp_casamail_sends` transmit-log table + Recent sends dashboard panel.
 * On plugin reinstall, rotate the API key and surface any existing sender-domain
   record so missing DNS records are visible immediately.

#### 0.2.0

 * In-WordPress onboarding wizard.
 * Durable retry outbox.

## Meta

 *  Version **1.4.1**
 *  Last updated **12 hours ago**
 *  Active installations **Fewer than 10**
 *  WordPress version ** 6.0 or higher **
 *  Tested up to **7.0**
 *  PHP version ** 7.4 or higher **
 * Tags
 * [deliverability](https://wordpress.org/plugins/tags/deliverability/)[email](https://wordpress.org/plugins/tags/email/)
   [smtp](https://wordpress.org/plugins/tags/smtp/)[transactional email](https://wordpress.org/plugins/tags/transactional-email/)
   [wp_mail](https://wordpress.org/plugins/tags/wp_mail/)
 *  [Advanced View](https://wordpress.org/plugins/casa-mail/advanced/)

## Ratings

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/casa-mail/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/casa-mail/reviews/)

## Contributors

 *   [ sendemailtoday ](https://profiles.wordpress.org/sendemailtoday/)
 *   [ codecasastudios ](https://profiles.wordpress.org/codecasastudios/)

## Support

Got something to say? Need help?

 [View support forum](https://wordpress.org/support/plugin/casa-mail/)