The admin screens
Every MailWizard screen and what it can and cannot tell you — the campaigns table and its alarm-led analytics, the templates and blocks libraries, permission wiring, and how demo mode masks recipient addresses.
MailWizard has three screens and no dashboard. Opening /admin/mailwizard
redirects straight to Campaigns, because there was never a landing page worth
building — the campaigns table with its analytics header does that job.
Find it under Admin → Extensions → Business Tools → Email Marketing. The addon draws its own header with three tabs: Campaigns, Templates, Blocks.
Campaigns
/admin/mailwizard/campaign — a standard admin table over the campaign rows,
with an analytics header above it.
The columns
| Column | Notes |
|---|---|
| Name | Sortable, searchable, filterable |
| Status | Badge. Filterable across all six campaign states |
| Subject | What the recipient sees |
| Progress | A bar plus sent/total and a failed count, computed in the browser from the recipient list on the row |
| Template | Links straight to the template the campaign uses |
| Speed | Emails per hour. Hidden until you expand a row |
| Created | Hidden until you expand a row |
The progress bar measures attempts — sent plus failed — which is why the caption states delivered and failed separately underneath it. A bar at 100% with a third of the list failed is not a successful campaign, and one percentage would hide that.
The view dialog
Opening a row gives you the campaign as an operator reads it rather than as a key/value grid: delivery progress first, then the delivery settings, then the recipients themselves as a list.
The recipient section is bucketed failures first, then pending, then sent, and truncated at 25 entries with a count of how many are not shown. That ordering is deliberate: the recipients you opened the panel for are exactly the ones a stored-order slice would bury. Each failed entry carries the transport's error text and its attempt count inline.
Two badges are worth reacting to. The status badge is the campaign's own state.
No recipients appears when the list is empty — an ACTIVE campaign in that
condition stays ACTIVE forever and sends nothing, which the recipient count
alone does not say.
The analytics header
The header leads with alarms rather than totals, because the failure mode of this addon is silence.
| Tile | What it means |
|---|---|
| Campaigns Sending Now | Count of ACTIVE campaigns |
| Stalled Sends | ACTIVE campaigns not written to in over an hour — the single most useful number on the page |
| Paused | Includes campaigns the send job paused itself. A rise here is an incident, not activity |
| Drafts Never Started | PENDING campaigns |
| Avg Throttle, Active Sends | Mean speed across campaigns actually sending — the number you turn down when your provider starts throttling you |
| Total Campaigns | Campaigns created in the selected window |
| Campaigns That Reached an End | Completed plus stopped plus cancelled |
| Completion Rate | Of the campaigns that finished one way or another, the share that finished by sending everything |
| Avg Time to Complete a Send | Time from creation to the send job's last write on completed campaigns |
Alongside them: a status distribution donut, a Busiest Templates bar showing which templates carry the volume, and a stacked bar of campaign states over time.
The send job rewrites a campaign row every time it drains a batch of ten
recipients. An ACTIVE campaign that has not been touched in an hour therefore
means the job is not running — a stopped cron process, a crashed worker, or an
extension that was disabled with a campaign still active.
Subtract Stalled Sends from Campaigns Sending Now to get the sends that are genuinely moving. If the two are equal, nothing is sending at all.
Recipients reached, emails delivered, failure rate, bounce pressure — none of it is reachable from this page. Per-recipient state lives inside a JSON column on the campaign row, so there is no queryable count of recipients, sends or failures for any aggregation to work over. That is why the progress column has to parse the list in the browser just to draw its bar.
This page reports on campaign rows. It cannot report on mail.
Avg Time to Complete a Send is a proxy. There is no completion timestamp in the schema, so the figure is measured from creation to the send job's last write. For a completed campaign that write is the moment it finished — unless somebody edits the row afterwards, which inflates it. Read it as an upper bound.
Templates
/admin/mailwizard/template — the template library. Create opens the full-screen
visual editor; edit reopens it on the stored design.
Beyond the list, the view dialog is the useful part. It renders the stored HTML in a sandboxed frame, breaks the design down row by row with its column counts and content types, and reports the HTML size — which is how you find the hundred-kilobyte template with base64 images inlined before you send it to a thousand people.
Two badges matter here:
- HTML only — the design cannot be parsed, so opening this template in the editor gives a blank canvas. It still sends correctly; it just cannot be edited visually.
- No content — the body is empty. Every campaign using this template delivers a blank email.
Blocks
/admin/mailwizard/block — saved rows that appear in the editor's Blocks panel.
Create, edit, group by category, delete.
The view dialog shows what a block actually contains, which is faster than opening the editor when you are trying to work out which of three similarly named headers is current.
Remember that a block is copied into a template on insertion, so editing or deleting one never changes templates already built with it. See Reusable blocks.
Permission wiring
Each screen is gated twice, and both halves have to be granted.
| Screen | Page permission | API permissions |
|---|---|---|
| Campaigns | access.mailwizard.campaign |
view / create / edit / delete .mailwizard.campaign |
| Templates | access.mailwizard.template |
view / create / edit / delete .mailwizard.template |
| Blocks | access.mailwizard.block |
view / create / edit / delete .mailwizard.block |
Granting only the access key produces a page that loads and then reports a
permission error on every request. Granting only the API keys hides the screen.
Three cross-cutting dependencies catch people out:
- The recipient picker needs
view.user, a core CRM permission. Without it the Add Targets dialog lists nobody, silently. - The template editor needs
view.mailwizard.blockto show its Blocks panel. Without it there is no panel and no explanation. - The campaign form needs
view.mailwizard.templateto populate its template dropdown, because that dropdown is served by the template options endpoint.
Assign roles at /admin/crm/role; see
Roles and permissions.
Licensing behaviour
The MailWizard admin area sits behind a licence gate scoped to the mailwizard
extension. The gate covers the content only — the header, navigation and
footer render regardless — so a licence check in flight shows a spinner in the
page body rather than blanking the whole screen.
A licence that fails to validate leaves the navigation in place and the screens
unusable. Disabling the extension at /admin/system/extension is the clean way
to remove it; that also stops the send job within about a minute.
Demo mode
With NEXT_PUBLIC_DEMO_STATUS=true, recipient email addresses are masked on the
way out of the API — partially obscured local part, partially obscured domain.
Both the campaign list and the campaign detail endpoint mask identically. This matters because the list is the first screen anyone opens: an earlier build masked only the detail view, so a demo instance handed every subscriber's real address to anyone who loaded the campaigns table.
The stored rows are untouched, and the number of recipients is preserved, so the progress column stays truthful while the addresses do not.
Audit trail
Every write goes to the admin activity log under the ADMIN_MAIL module, with
entries named for the action: create, update and delete for campaigns, templates
and blocks, plus status changes, target updates and retries. Read-only requests
are logged too, so the trail shows who opened a recipient list as well as who
changed one.
See The admin panel for where that log lives.