Email notifications
Configuring email notifications
Email notifications
From OpenCRVS 2.0, the country config server is responsible for sending all email and SMS messages. OpenCRVS Core never talks to an email provider directly — instead it calls action triggers on your country config server, and your country config decides whether and how to turn each trigger into a message.
This guide explains how email delivery is implemented in the reference country config (opencrvs-countryconfig), how to configure it, and how to customise the messages. All paths below are in the opencrvs-countryconfig repository unless stated otherwise.
There are two families of email notifications:
User notifications — account and authentication lifecycle (onboarding, password reset, 2FA, username reminders, all-user broadcasts). Triggered by Core via
/triggers/user/....Informant notifications — event lifecycle (a declaration is started, sent for review, registered, or rejected). Triggered by Core via the event action trigger.
Both families converge on the same email service, so the SMTP configuration and email-sending behaviour described here apply to all of them.
1. How an email is sent
The implementation lives in src/api/notification/:
handler.ts
Trigger handlers; notify() chooses email vs SMS and renders the template.
email-service.ts
sendEmail() — builds the nodemailer transport and sends the message.
email-templates/index.ts
Maps each notification type to a template file, subject, and expected variables.
informantNotification.ts
Builds informant (event) notifications from an EventDocument.
constant.ts
Reads the SMTP and notification environment variables.
2. SMTP configuration
Email delivery is configured entirely through environment variables on the country config server (src/api/notification/constant.ts):
SMTP_HOST
—
SMTP server hostname.
SMTP_PORT
587
SMTP server port.
SMTP_SECURE
false
Set to true to use an implicit TLS connection.
SMTP_USERNAME
—
SMTP authentication user.
SMTP_PASSWORD
—
SMTP authentication password.
SENDER_EMAIL_ADDRESS
—
The From address used for all outgoing mail.
Two further variables are used inside templates and operational mail: DOMAIN (your installation's domain) and ALERT_EMAIL (where infrastructure alerts are forwarded). LOGIN_URL is used to build onboarding and password-setup links.
In deployed environments the SMTP secrets are provided as deployment secrets rather than committed to the repository.
3. Choosing the delivery method
Whether a notification family is delivered by email, by SMS, or not at all is controlled in src/api/application/application-config.ts:
USER_NOTIFICATION_DELIVERY_METHOD
'email' | 'sms' | ''
User / authentication notifications.
INFORMANT_NOTIFICATION_DELIVERY_METHOD
'email' | 'sms' | ''
Informant / event notifications.
Set a value to 'email' to send email, 'sms' to send via the SMS service (Infobip in the reference config), or '' (empty) to disable that family entirely. If email is selected but a recipient has no email address, the notification is skipped and the reason is logged.
all-user-notification cannot be delivered over SMS — if USER_NOTIFICATION_DELIVERY_METHOD is 'sms', all-user broadcasts are skipped.
4. Email templates
Templates are Handlebars HTML files under src/api/notification/email-templates/, organised by event type:
email-templates/index.ts binds each notification type to a template file and a default subject, and declares the variables that template receives. Every template can use these globally available variables (resolved in email-service.ts): DOMAIN, ALERT_EMAIL, and SENDER_EMAIL_ADDRESS. Each template additionally receives applicationName, countryLogo, and its own type-specific variables.
4.1 User notification templates
Trigger
Template (other/)
Default subject
user-created
onboarding-invite.html
Welcome to OpenCRVS!
resend-invite
resend-invite.html
Your OpenCRVS account invitation
user-updated
username-updated.html
Account username updated
username-reminder
username-reminder.html
Account username reminder
reset-password
password-reset.html
Account password reset request
reset-password-by-admin
password-reset-by-system-admin.html
Account password reset invitation
2fa
2-factor-authentication.html
Two factor authentication
change-phone-number
change-phone-number.html
Phone number change request
change-email-address
change-email-address.html
Email address change request
all-user-notification
all-user-notification.html
(set by the admin sending the broadcast)
See the action triggers reference for the exact payload of each /triggers/user/... endpoint.
4.2 Informant notification templates
For each event type, the informant template is chosen from the pending action on the event:
NOTIFY
inProgress.html
Birth declaration in progress
DECLARE
inReview.html
Birth declaration in review
REGISTER
registration.html
Birth declaration registered
REJECT
rejection.html
Birth declaration required update
Informant templates receive trackingId, crvsOffice, registrationLocation, informantName, name (the subject of the event), and — for registration — registrationNumber.
5. Informant notifications in detail
When an event action is requested, Core calls the event action trigger on country config. The reference config wires this to onAnyActionHandler (src/api/events/handler.ts), which calls sendInformantNotification():
The pending action and the aggregated declaration are read from the
EventDocument.The recipient is resolved from the declaration —
informant.emailandinformant.phoneNo, with the name taken from the mother/father/informant (birth) or spouse/informant (death).The action type selects the template (see §4.2).
notify()renders the template and sends it using the informant delivery method.
Because the recipient's contact details come from the declaration, informant emails only go out when the informant provided an email address and INFORMANT_NOTIFICATION_DELIVERY_METHOD is 'email'.
6. Customising emails
Change wording or branding — edit the relevant
.htmlfile underemail-templates/. Templates are Handlebars, so you can use{{variable}}placeholders for any variable that template receives.Change a subject line — edit the
subjectfor that notification type inemail-templates/index.ts.Add a new global variable — register it in the
replaceVariablesmap inemail-service.tsso it resolves in every template'sfrom,to,subject, andhtml.Switch a family to SMS or disable it — change
USER_NOTIFICATION_DELIVERY_METHOD/INFORMANT_NOTIFICATION_DELIVERY_METHODinapplication-config.ts.Send entirely custom messages — implement your own logic in the trigger handlers; the trigger payloads (see action triggers) give you everything Core knows about the event or user.
7. Behaviour in development and testing
A few safeguards prevent accidental sends in non-production environments. Keep these in mind when testing:
Emails are only sent when
NODE_ENVisproduction. The/emailhandler short-circuits with a200(and logs the payload) whenNODE_ENVis notproduction, andnotify()logs to the console instead of sending whenNODE_ENVisdevelopment.Any recipient address ending in
@example.comis skipped — the seeded demo users (e.g. Farajaland) use@example.comaddresses, so they never receive real mail.
Last updated