Email System
PBS Knowledge sends automated notifications and admin-composed emails through Microsoft 365, using templates stored in Firestore and a Redis-backed queue.
Overview
Email Capabilities
The system supports:
- Transactional Emails — automated notifications triggered by workflows, deadlines, and system events
- Template Management — Firestore-stored templates editable in the admin UI
- Manual & Scheduled Sends — compose one-off emails or schedule recurring sends
- Meeting Invites — calendar invitations (e.g., defense scheduling) sent as proper invites
Email Architecture
Event Trigger → Template (Firestore) → Handlebars Rendering → Queue (BullMQ) → Microsoft 365 Graph API
- Provider: Microsoft 365 via the Graph API, sending from the department service account (
MICROSOFT_SERVICE_EMAIL). - Queue: emails go through the
email-jobsqueue with retry (3 attempts, exponential backoff) and rate limiting (configurable per minute/hour). - Templates: stored in the Firestore
emailTemplatescollection — there are no template files on disk.
Email Templates
How Template Storage Works
Template content lives only in Firestore. At startup the backend seeds any missing templates from embedded defaults, so a fresh deployment always has a working set. When a template is rendered, the lookup order is:
- The Firestore document (admin-edited content)
- A last-known-good cached copy (used if Firestore is temporarily unavailable)
- The embedded default
Editing a template in the admin UI takes effect immediately — no deploy or restart needed.
Template Components
Each template has:
- Name / key — identifying name used by the code that triggers it
- Subject — email subject line (supports variables)
- Body — HTML email content (supports variables)
- Variables — Handlebars placeholders filled at send time
Editing Templates
- Go to Admin → Email
- Open the Templates list
- Select a template to edit its subject and body
- Save — changes apply to the next send
Template Variables
Templates use Handlebars syntax:
Hello {{ student_name }}, your milestone "{{ milestone_name }}" is due on {{ due_date }}.
Available variables depend on the notification type (the template editor shows what each template receives). Common ones include student/faculty names, entity titles (thesis, milestone, application), due dates, and the application URL.
Notification Types
Workflow Notifications
Automatic emails are sent on workflow transitions — for example:
- A request or application is submitted (approvers are notified)
- An approval decision is made (the requester is notified)
- A revision is requested
Deadline Notifications
The daily deadline jobs (see Jobs & Scheduling) scan for approaching deadlines and overdue items:
- Deadline reminders to the responsible person
- Escalation notices to advisors when items become overdue
Manual Sending
Send an email from the admin UI:
- Go to Admin → Email
- Compose directly or start from a template
- Choose recipients
- Send now, or schedule it
Scheduled sends are managed as queue schedulers — they appear in the scheduled jobs list in the same section and can be cancelled there.
Meeting Invites
The email section can also send calendar meeting invites (used for defense scheduling and similar events). These arrive as actual calendar invitations rather than plain emails.
Configuration
Provider Settings
Microsoft 365 integration is configured by environment variables:
MICROSOFT_TENANT_ID,MICROSOFT_CLIENT_ID,MICROSOFT_CLIENT_SECRET— Graph API credentialsMICROSOFT_SERVICE_EMAIL— the mailbox emails are sent from
Rate Limiting
Sending rate is controlled by:
EMAIL_RATE_LIMIT_PER_MINUTE(default 10)EMAIL_RATE_LIMIT_PER_HOUR(default 100)
Excess emails wait in the queue rather than failing.
Troubleshooting
Emails Not Sending
- Check the
email-jobsqueue in Admin → Jobs & Scheduling for failed jobs and their error messages - Verify the Microsoft Graph credentials and service mailbox are valid
- Check rate limits — a burst of notifications may simply still be queued
Template Problems
- If an edited template renders incorrectly, check its Handlebars variables against what the notification provides
- If Firestore is unreachable, the system falls back to the cached/default template content — sends keep working, but admin edits won't apply until Firestore is back
Delivery Issues
- Confirm the recipient address on the person's profile
- Check the failed-jobs list for Graph API errors (the full error is recorded on the job)