Install and enable

Activating MailWizard — the licence step, the three tables, the fifteen permission keys, the hourly cron job, the mail transport it depends on, and a smoke test that proves a campaign really sends.

7 min readUpdated 3 August 2026install, extension, cron, permissions, smtp

Activation is two minutes of clicking. The part that actually decides whether campaigns send is the mail configuration underneath it, and that is not something MailWizard checks or reports on. Work through this page in order and finish with the smoke test — a MailWizard install that is broken looks exactly like one that is working until an operator notices a campaign has been Active for six hours with zero recipients sent.

Before you activate

    • Bicrypto core installed and running — see Installing Bicrypto
    • Outbound mail works: a password-reset email from your install arrives in a real inbox
    • The cron PM2 app is running — campaigns are sent by a scheduled job and nothing else
    • Redis reachable, because the cron scheduler runs on BullMQ
    • Your CodeCanyon username and the MailWizard licence code to hand

The mail check is the one people skip. MailWizard does not own a transport, a queue or a sending domain — it calls the platform's mailer. If that is misconfigured, every recipient on every campaign fails, and the only place the reason appears is the cron log.

Activation

  1. Open Admin → System → Extensions — the screen is at /admin/system/extension.

  2. Find MailWizard and activate it — enter your CodeCanyon username and licence code. The platform verifies the purchase before enabling anything. The extension's internal name is mailwizard; that is the name you will see in the database and in cron logs.

  3. Confirm the menu appearsExtensions → Business Tools → Email Marketing in the admin navigation, landing on /admin/mailwizard/campaign.

  4. Confirm the addon's own header — the MailWizard screens carry their own three-item nav: Campaigns, Templates, Blocks.

Turning the extension off at /admin/system/extension stops the campaign cron within about a minute — the scheduler re-reads extension status on a 60-second loop and deregisters the job without a restart. Campaign, template and block rows are left alone, so re-enabling picks up exactly where you were. A campaign left ACTIVE when you disable the addon simply stops progressing.

What activation creates

Three tables, created automatically by the model sync:

Table Holds
mailwizard_template Templates: the exported HTML (content) and the editor's design JSON (design)
mailwizard_block Reusable blocks: a name, an optional category, and one or more editor rows as JSON
mailwizard_campaign Campaigns: name, subject, status, speed, template link, and the whole recipient list as a JSON string in targets

All three are paranoid — deletes are soft — and all three keep their bodies in TEXT('long') columns, because a single template with an inlined image passes 64 KB without difficulty.

The recipient list living inside the campaign row is the single most consequential design decision in this addon. It is why there is no per-recipient reporting, why the analytics screen cannot chart delivery, and why a campaign has a hard recipient ceiling. See Building and sending a campaign.

If you build from source, run pnpm types:generate once the tables exist.

Permissions

Fifteen keys are seeded — five actions across three objects. Assign them to roles at /admin/crm/role; Super Admin holds them all automatically.

Key Grants
access.mailwizard.campaign Opening the Campaigns screen and the addon's menu entry
view.mailwizard.campaign Reading campaigns, including the recipient list
create.mailwizard.campaign Creating a campaign
edit.mailwizard.campaign Editing, changing status, updating targets, retrying failures
delete.mailwizard.campaign Deleting campaigns, singly or in bulk
access.mailwizard.template Opening the Templates screen
view.mailwizard.template Reading templates, and the template dropdown on the campaign form
create.mailwizard.template Creating and importing templates
edit.mailwizard.template Saving from the visual editor
delete.mailwizard.template Deleting templates
access.mailwizard.block Opening the Blocks screen
view.mailwizard.block Reading blocks, and the editor's Blocks panel
create.mailwizard.block Creating a block, including Save as block in the template editor
edit.mailwizard.block Editing a saved block
delete.mailwizard.block Deleting blocks

The Add Targets dialog reads the platform's own user list through /api/admin/crm/user, which is gated by view.user — a core CRM permission, not a MailWizard one. A role holding every key in the table above and not view.user opens the picker to an empty list with no error, so the operator concludes there are no users to email.

access.* keys gate the admin pages; the view / create / edit / delete keys gate the API. Both matter: granting only the page key produces a screen that loads and then reports permission errors on every request.

The one cron job

Check it at /admin/system/cron, category mailwizard.

Job Every Does
processMailwizardCampaigns 60 minutes Picks up every ACTIVE campaign and sends up to speed emails from each

That is the entire sending mechanism. There is no queue worker, no second job and no other trigger — the Start button on a campaign only sets its status.

Scheduled jobs run in the cron PM2 app. If that process is stopped, crashed or never started, every campaign sits at ACTIVE and 0% forever, and nothing in the MailWizard screens says so. pm2 list is the check. See Processes and ports.

The Campaigns screen has one indicator for this: the Stalled Sends figure counts campaigns that are ACTIVE but have not been written to in over an hour. On a healthy install that number is zero.

Mail transport

MailWizard sends through whichever transport APP_EMAILER selects. It does not have settings of its own — there is no MailWizard settings screen.

Which transport sends every email, MailWizard campaigns included: nodemailer-service, nodemailer-smtp, nodemailer-sendgrid or local.

The From address and sender name are also global, and there is no per-campaign override:

Transport From address comes from Sender name comes from
nodemailer-service APP_NODEMAILER_SERVICE_SENDER APP_EMAIL_SENDER_NAME, else NEXT_PUBLIC_SITE_NAME, else Support
nodemailer-smtp NEXT_PUBLIC_APP_EMAIL if set, else APP_NODEMAILER_SMTP_SENDER same
nodemailer-sendgrid APP_SENDGRID_SENDER same
local NEXT_PUBLIC_APP_EMAIL, else no-reply@localhost same

Two consequences worth planning for. First, every campaign appears to come from the same address as your transactional email — a bounce storm on a marketing send damages the reputation of the address your password resets go out on. Second, DKIM signing configured through APP_NODEMAILER_DKIM_* only applies to the local sendmail transport. On SMTP, service or SendGrid, signing is your provider's job and must be set up in DNS.

The platform's global outbound kill switch is checked by the notification queue and by the templated sendEmail path. The MailWizard send loop calls the mailer directly and never consults it. Setting MAIL_DISABLED=true on a staging copy of production silences the rest of the platform and leaves any ACTIVE campaign sending real email to real customers.

Before restoring a production database onto a test box, set every campaign to PENDING or CANCELLED — or disable the mailwizard extension outright.

Smoke test

Prove the whole chain end to end before you point a campaign at real customers. Use your own mailbox as the only recipient.

  1. Create a template — Templates → Create, name it Smoke test, drop a text block onto the canvas with a recognisable sentence in it, and save. Reopen it from the list; the canvas should show what you built, not a blank page.

  2. Create a campaign — Campaigns → Create. Name and subject anything, pick the Smoke test template, set Emails per hour to 1.

  3. Add exactly one recipient — click Add Targets, search for your own account by first name (the search matches first name only), tick it, and Add selected. Save the campaign.

  4. Start it — on the campaign page press Start. The status becomes ACTIVE.

  5. Run the job rather than waiting an hour — open /admin/system/cron, find processMailwizardCampaigns under the mailwizard category and trigger it.

  6. Check the outcome — the recipient card should badge Sent, progress should read 100%, and the campaign status should be COMPLETED. The email should be in your inbox.

If the recipient badges Failed, the reason is written onto the recipient card itself — that text comes straight from the mail transport and is almost always an authentication or connection error rather than anything to do with MailWizard. Troubleshooting works through the common ones.

Upgrading an existing install

Run pnpm updator, then restart the backend so the campaign cron and the admin routes pick up the new build. Two things to check afterwards.

The old create flow discarded the design and the HTML it was given and stored a literal {} as the body, while reporting success. Every campaign using such a template delivered an empty email. Editing always saved correctly, so opening the template and saving once repairs it.

The Templates list flags these for you: a template whose design cannot be parsed carries an HTML only badge, and one with no body carries No content.

Saving a campaign whose recipient list exceeds 10,000 characters is refused. Campaigns that already hold a longer list keep sending — only saving is blocked, which means you cannot edit them at all. Plan to split them before you need to change one.

New permissions are seeded on start. If you added roles between versions, revisit /admin/crm/role after upgrading — the block permissions in particular did not exist before v6.2.0, and a role without them sees an empty Blocks panel in the editor.