This guide covers the developer setup for email delivery in PropOps Web — including sending methods, template customisation, and environment configuration.Documentation Index
Fetch the complete documentation index at: https://help.propops.app/llms.txt
Use this file to discover all available pages before exploring further.
Choosing a sending method
PropOps Web supports two email sending methods. Each template can be configured independently.| Method | When to use |
|---|---|
| Local (built-in) | Development, self-hosted, or when you don’t need Brevo. Sends via PHP mail() or Mailpit. Works out of the box with no API key. |
| Brevo API | Production environments where you want deliverability tracking, domain verification, and analytics. Requires a BREVO_API_KEY. |
You can mix both methods — use Brevo for customer-facing emails and local templates for internal notifications.
Setting up local email
Local email works immediately with no configuration. Templates are rendered fromviews/emails/ and sent via PHP mail().
Setting up Brevo
Create a Brevo account
Sign up at brevo.com if you don’t already have an account.
Verify your sender domain
In Brevo, go to Senders, Domains & Dedicated IPs and verify the domain you’re sending from. This improves deliverability and prevents emails being marked as spam.
How template resolution works
Each email type is mapped to anEMAIL_TEMPLATE_* variable in .env. The value determines how PropOps Web sends that email:
| Value type | Behaviour |
|---|---|
String (e.g. welcome) | Renders the local HTML template from views/emails/welcome.html |
Number (e.g. 30) | Sends via the Brevo API using that template ID |
| Empty | Falls back to a local template derived from the env key name |
Local templates use
{"{{ params.COLUMN_NAME }}"} syntax — the same format Brevo uses — so migrating between local and Brevo is seamless.Customising templates
Editing an existing template
All 47 pre-built templates live inviews/emails/. Each template is a standalone HTML fragment that gets wrapped in layout.html.
Edit the HTML
Templates are plain HTML. Use
{"{{ params.VARIABLE_NAME }}"} placeholders for dynamic content. Check the existing template to see which variables are available.Creating a new template
Create the HTML file
Create a new
.html file in views/emails/. The filename should match the template name you’ll use in .env — for example my_custom_email.html.Add a subject line
Include a subject in an HTML comment at the top of the file:You can use placeholders in the subject:
Write your template content
Add your HTML content. The template will be automatically wrapped in
layout.html (logo, footer, styling). You only need to write the inner content:Editing the layout
The shared layout inviews/emails/layout.html wraps every template. It contains:
- The outer email structure (background, centring)
- Your brand logo (centred)
- The white content card
- The footer with
APP_URLand copyright - Dark mode styles
- Responsive breakpoints
layout.html to change the look of all emails at once. The placeholder {"{{ TEMPLATE_CONTENT }}"} is where each template’s content is injected.
Auto-injected variables
These variables are available in every template automatically:| Variable | Source |
|---|---|
APP_NAME | From .env |
APP_URL | From .env |
APP_LOGO_PATH | From .env |
BRAND_PRIMARY_COLOR | From .env (default: #2563eb) |
CURRENT_YEAR | Auto-generated |
Environment configuration
Core settings
Template mappings
Each email type has anEMAIL_TEMPLATE_* variable. Set it to a local template name or a Brevo template ID:
Troubleshooting
Emails not being sent
Emails not being sent
- If using Brevo, check that
BREVO_API_KEYis set correctly in your.env - If using local, check your server’s
mail()function is working (php -r "mail('test@example.com','Test','Body');") - Verify the sender domain is confirmed in Brevo (if applicable)
- Check the Email Log in Admin → Email Log for error messages
Emails going to spam
Emails going to spam
- Ensure your sender domain has SPF, DKIM, and DMARC records configured
- Verify the domain in Brevo’s sender settings
- Use a professional sender address (avoid free email providers)
Template not rendering correctly
Template not rendering correctly
- Check the template file exists in
views/emails/with the correct filename - Verify placeholder names match exactly (case-sensitive):
{"{{ params.USER_NAME }}"}not{"{{ params.user_name }}"} - If the template falls back to the generic template, the specific file may be missing or misspelt
- Use Mailpit to preview rendered HTML during development
Switching between local and Brevo
Switching between local and Brevo
- To use a local template: set the env value to the template name (e.g.
welcome) - To use Brevo: set the env value to the numeric Brevo template ID (e.g.
30) - You can mix both — each template is independent