Notifications
Email and digests
Send VitNode notifications by email, right away or in a daily or weekly digest in each member's time zone, with checks at send time, delivery records and retries.
A notification type can also reach members by email, either right away or bundled into a daily or weekly digest. You turn email on in the type, and each member picks one mode per type: none, immediate, daily or weekly. Core plans, sends, retries and records every email through your configured email adapter.
Before you begin
Configure an email adapter. Without one, no type offers email, and members see no email choice.
Turn on email for the type
Add email: true and pick the default mode for members who never change it:
export const topicReplyNotification = buildNotificationType({
id: 'forum.topic_reply',
// other options unchanged
defaults: { inApp: true, email: 'daily' },
email: true,
})email: true reuses the title, body and target from present. Each email links to the item and to Manage notification preferences on /settings/notifications. A default other than 'none' without email throws when the module loads.
Word the email separately (optional)
Pass a function instead of true when the email needs its own subject or button label:
email: ({ data, t }) => ({
subject: t('@acme/forum.notifications.topic_reply.email_subject', {
title: data.topicTitle,
}),
title: t('@acme/forum.notifications.topic_reply.title', {
title: data.topicTitle,
}),
actionLabel: t('@acme/forum.notifications.topic_reply.email_action'),
}),It receives the same arguments as present, in the recipient's language. Add the new keys to src/locales/api/en.json.
How digests are scheduled
Daily digests go out at 08:00 and weekly digests on Monday at 08:00, in each member's time zone. The hour and day are the same for everyone, and members cannot change them.
- A daily digest covers the 24 hours before 08:00. A weekly one covers the seven days before Monday 08:00. A notification that arrives after 08:00 waits for the next digest.
- The time zone comes from the member's Region setting on
/settings, then from their language, then UTC. - Periods follow local time, so on the night clocks change a day lasts 23 or 25 hours. No day is skipped or sent twice.
- Each notification joins exactly one digest, and an empty digest is never sent.
- A digest lists up to 25 notifications, newest first, and says how many more are waiting.
The notifications-schedule cron plans digests every 5 minutes, so a digest can arrive up to 5 minutes after 08:00.
What is checked at send time
Right before an email or digest goes out, core checks each notification again: the member's current email mode, the type's policy in the AdminCP, the type's access check, and whether the member already read it.
Digests and delayed emails include only notifications that are still unread. A member who read or archived an item in the inbox does not get it by email too. A member who switched modes since the notification arrived gets it in the new mode, or not at all for none. A member who takes a type by email only has no inbox item to read, so their email always goes out.
Delivery records and retries
Every send, including test emails, is a row in core_notification_deliveries. List them with GET /deliveries in the AdminCP API.
| Status | Meaning |
|---|---|
pending | Waiting for its send time |
sending | Claimed by a worker |
sent | The provider accepted it. providerMessageId holds the provider's id |
failed | All 5 attempts failed. lastError holds the error with addresses and tokens redacted |
skipped | Nothing to send. skipReason says why, such as empty, email_disabled or user_missing |
A failed attempt is retried after 10 seconds, then 20, 40 and 80. Every attempt passes the same idempotencyKey to your adapter, so a provider that deduplicates, such as Resend, never delivers a retry twice. SMTP through Nodemailer cannot deduplicate, so a crash between "accepted" and "recorded" can send one email twice. To forward the key from your own adapter, see Custom email adapter.
Check the result
- Open AdminCP → System → Notifications, select Settings, and run Send a test email to me. The email arrives at your own address.
- Set Replies to your topics to Right away on
/settings/notifications, then trigger a reply as another member. The email arrives within about a minute, as long as your cron adapter runs the queue worker. - If it does not, see Emails are not sending.