Cashier for mailcow — guide
Before you start
- The mailcow Toolkit package 0.4.0 or newer, installed with
install.shas described in the mailcow Toolkit guide. Cashier for mailcow is part of the package. - Sign-up for mailcow with its own valid license and set up (see the Sign-up guide): paid accounts are created through its registration page.
- Your Cashier for mailcow license key (a mailcow bundle key works too), or an e-mail address for the free 30-day trial.
- Your own Stripe account. Payments go into it directly; MediaLab Works is not involved in your sales.
- The mailcow UI reachable from the internet over HTTPS (Stripe calls the webhook there), and outgoing HTTPS to api.stripe.com and medialab.works.
License and free trial
Open System > Updates (Toolkit) and use the card License · Cashier for mailcow: enter the key and press Activate, or start the free 30-day trial with your e-mail address (the card is asked on the Stripe checkout page of medialab.works and not charged during the 30 days). Each mailcow tool has its own trial, once per server and per e-mail address. With a mailcow bundle key, enter the same key in each product's card. On the shell: docker compose exec -u www-data php-fpm-mailcow php /web/mlw-toolkit/cli.php activate mailcow-cashier <KEY> from the mailcow folder.
The license is checked when the server starts and once a day; without internet Cashier keeps working for 7 days after the last successful check. Without a valid license no new checkout starts and the timer jobs stop for Cashier (grace periods are not turned into suspensions until the license is back). The webhooks of existing subscribers are still processed, and a checkout completed meanwhile waits until the license is back. Nothing is deleted.
Connecting Stripe
Open System > Cashier. In the Stripe card:
- In your Stripe Dashboard create a restricted key (Developers > API keys > Create restricted key) with write access to Customers, Checkout Sessions, Customer portal, Products, Prices, Subscriptions, Subscription items and Webhook Endpoints, and read access to Invoices. A secret key (
sk_…) works too, but a restricted key (rk_…) is safer. - Paste the Publishable key (
pk_test_…orpk_live_…) and the Secret / restricted key; both must be test keys or both live keys. Cashier checks them with Stripe and shows the account and the mode. The secret key is stored encrypted and never shown again (leave the field empty to keep it). - Press Create the webhook. Cashier registers
https://<mail host>/mlw-cashier/webhook.phpin your Stripe account with the events it needs and saves its signing secret. If a proxy rewrites the host name, set Public webhook address under Rules first. A webhook added by hand in Stripe also works: paste its Signing secret. - Last event shows the last event Stripe sent; use it to check that the webhook arrives.
Disconnect removes the keys from the server (your Stripe account is not changed). To move from test mode to live mode, connect the live keys and create the webhook again.
Plans
In Plans press New plan:
- Kind: mailbox (one mailbox with its quota) or domain package (for domain administrators: Domains (package), Mailboxes / domain, Aliases / domain, Quota (MB; package: per domain), Default quota / mailbox (MB)).
- Name (English), Name (Romanian) and the descriptions in both languages, shown on the registration page in the visitor's language.
- Monthly price and/or Yearly price, in your Stripe account's currency. Cashier creates the product and the prices in your Stripe account.
- Trial days (0 = none) — the trial of your plan, for your customers.
- Visible on the registration page — untick it for a hidden plan, reachable only through its direct link (
/mlw-signup/?plan=<token>) or an invitation code bound to the plan.
Edit changes a plan: a changed amount creates a new price in Stripe and deactivates the old one, which existing subscribers keep. Archive takes the plan off sale (its prices are deactivated in Stripe); existing subscribers keep it.
Add-ons
In Add-ons, an add-on is bought with a quantity on the subscription: extra mailboxes on each domain of the package, or extra storage (MB per domain; on a mailbox plan, per mailbox). Set the Unit (mailboxes / MB), the names, the monthly and yearly prices and Visible. Customers add them on My account; Stripe prorates the price and the new limits are applied to mailcow at once.
Rules
- Grace period after a failed payment (days, 0–90) — the account keeps working while the customer pays (default 7 days).
- After the grace period the account is suspended — no sign-in: mail is still received (default) or inactive: mailboxes, domain administrator and domains. Nothing is ever deleted; a payment restores the account immediately.
- E-mail the subscribers about invoices and receipts.
- Public webhook address (empty = automatic), Stripe product tax code (with the default, the code recommended with the license is used;
noneleaves it out), Stripe name prefix (when several mailcow servers share one Stripe account).
What your customers see
- On the registration page they choose a plan (monthly or yearly), confirm their address and pay on Stripe's checkout page. The account is created when Stripe confirms the payment.
- On My account: the plan, the next payment date, the add-ons, Change plan (prorated; a plan smaller than what they use now is refused) and Card, invoices and cancellation (Stripe), Stripe's customer portal.
- A failed payment sends an e-mail with the link to pay and the date of the suspension. A suspended customer who cannot sign in gets the payment link from
/mlw-cashier/billing.phpby entering the account's e-mail address. - A cancellation takes effect at the end of the paid period.
Subscribers and free grants
Subscribers lists every subscription with its state (active, grace, suspended, ended), the plan, the amount and the link to Stripe, and the Monthly revenue. Grant a plan for free gives a plan to an account (mailbox or domain administrator) for a number of Days, without Stripe; a grant can be ended early. Recent Stripe events shows what the webhook received.
Data and backups
Plans, customers and subscriptions are in mailcow's database (tables mlw_ca_*), part of mailcow's backups. The keys and the webhook secret are in the Toolkit's shared folder, encrypted with AES-256-GCM; the encryption key is kept apart, in mailcow's redis. uninstall.sh removes Cashier with the Toolkit but keeps the tables and every account; the encrypted keys go with the shared folder, so you would connect Stripe again after a reinstall.
Common problems
Stripe refused the key. Check that both keys are of the same mode (test or live) and that the restricted key has every permission listed above; Stripe's message is shown on the page.
Payments succeed but no account appears. The webhook does not arrive: check Last event, the webhook's deliveries in the Stripe Dashboard, and that the mailcow UI is reachable from the internet over HTTPS. Then press Create the webhook again.
The registration page shows no paid plans. The plan is hidden, has no price, Stripe is not connected, or the Cashier or Sign-up license is not valid.
A customer cannot change to a smaller plan. The account uses more than the new plan allows (domains, mailboxes, aliases or quota); the message says what to reduce.