Email Receipts
Email Receipts automatically sends a formatted receipt to a customer's email address after every completed sale. The email includes a full itemized HTML receipt and a PDF attachment — no manual action required from the cashier.
Email Receipts are disabled by default. To enable them, go to Settings → Edit Settings → Notifications and check Enable Email Receipts.
How It Works
- A sale is completed in the POS register.
- The server enqueues a background job (
SalePostCompletionJob) immediately after the sale is saved. - The job checks three conditions before sending:
- The store has
enable_email_receiptsturned on. - The customer on the sale has a valid email address on file.
- The customer's
email_receipt_opt_inis not explicitly set tofalse(it defaults totruefor all customers).
- The store has
- If all three conditions pass,
ReceiptMailer#sale_receiptis dispatched viadeliver_later(Sidekiq queue). - The mailer generates a PDF receipt using
ReceiptPdfServiceand attaches it to the email before sending.
Emails are sent asynchronously — the POS API response is never delayed waiting for the email to send. If PDF generation fails for any reason, the email is still sent without the attachment and the error is logged.
Email Content
Subject line
Your receipt from <Store Name> - <Receipt Number>
HTML body
The email contains:
| Section | Details |
|---|---|
| Header | Store name and store address (if configured) |
| Receipt info | Receipt number and sale timestamp |
| Line items | Product name, quantity, unit price, and line total for each item. Freebie items show "FREE" instead of a price. Per-item discounts appear as a sub-row below the affected item. |
| Totals | Subtotal, order-level discount (if any), tax, additional tax (if applicable), and grand total |
| Payment | Payment method (cash, card, e-transfer, store credit, split). For card payments: card brand and last four digits, and auth code if present. For cash: change given. For split payments: each method and amount listed individually. |
| Loyalty block | Shown only when the store has loyalty enabled and the customer has a point balance or earned points on the sale. Displays points earned this visit, current point balance, and loyalty tier with discount percentage. |
| Footer | Uses the store's configured receipt_footer text. Falls back to "Thank you for your purchase!" if no footer is set. A note indicating the PDF is attached is always included. |
A plain-text version of the same receipt is also sent alongside the HTML version for email clients that do not render HTML.
PDF attachment
The attached PDF is generated by ReceiptPdfService using the Prawn library, formatted as a standard 80mm thermal receipt width (226pt). It includes the store header, line items, totals, payment details, and footer — the same information as the printed receipt.
The attachment filename follows the pattern: receipt-<receipt_number>.pdf.
Sender Address
Emails are sent from:
<Store Name> <noreply@brotherpos.ca>
The store name is taken from the store's configured name. The domain is controlled by the MAILER_DOMAIN environment variable and defaults to brotherpos.ca.
Customers cannot reply to these emails.
Customer Requirements
Email receipts are only sent when:
- The customer profile attached to the sale has an email address on file.
- The customer has not opted out of email receipts (
email_receipt_opt_inistrueby default for all customers).
Customers without an email address or customers with opt-in explicitly set to false will not receive a receipt email, even if the feature is enabled store-wide.
POS Confirmation
When a sale completes and an email receipt is sent, the POS Payment Success screen displays a confirmation message:
Receipt emailed to customer@example.com
This message only appears when email_receipt_sent is returned in the sale API response and a customer_email is present.
Configuration
The only store-level setting for email receipts is the on/off toggle under Settings → Edit Settings → Notifications.
There are no per-customer settings exposed in the admin UI. The email_receipt_opt_in flag on each customer record defaults to true and can only be managed programmatically or via the API at this time.
Other store settings that affect email receipt content:
| Setting | Effect |
|---|---|
store_name | Appears in the email header and sender name |
store_address | Appears in the email header if set |
receipt_footer | Appears at the bottom of the email body |
loyalty_enabled | Controls whether the loyalty points block is included |
currency_symbol | Used for all monetary values in the email |
Best Practices
- Add email addresses to customer profiles. Email receipts only work when a customer with an email address is attached to the sale. Walk-up (no-customer) sales never receive an email receipt.
- Set a
receipt_footer. Under Settings → Edit Settings → General, configure a receipt footer message (e.g., store return policy, website URL). This footer appears at the bottom of every email receipt. - Verify Sidekiq is running. Email receipts are sent via background job. If the Sidekiq worker is stopped, emails queue up but are not delivered until Sidekiq restarts.
- Test with a real transaction. After enabling the feature, complete a test sale with a customer that has a valid email address to confirm delivery end-to-end.