Skip to main content
Version: 1.1.0
Last Updated: 2026-03-11
This guide documents how to configure email and SMS notification services for the Encore OS Platform.

Table of Contents

  1. Overview
  2. Email Service (Entra ID & Gmail)
  3. SMS Service (RingCentral)
  4. Template Configuration
  5. Rate Limiting & Quotas
  6. Cost Optimization
  7. Error Handling
  8. Testing
  9. Troubleshooting

Overview

Encore OS uses external services for email and SMS delivery:
  • Email: Microsoft Entra ID (Graph API) or Gmail (Google Workspace) — org-level sending. Configure per organization in HR Settings and Settings → Integrations.
  • SMS: RingCentral (primary provider)
Email is sent via the shared email-provider abstraction used by:
  • send-email-notification - Single notification delivery
  • send-pending-notifications - Batch processing
  • hr-portal-invite, hr-reference-request, hr-send-communication, hr-test-email - HR recruitment
  • automation-executor - Workflow send-email actions
  • Signature flows: send-signature-request, send-signature-reminder, auto-signature-reminders use the shared email-provider (Entra/Gmail) per organization.

Email Service (Entra ID & Gmail)

Org-level email supports two providers. Choose one per organization in HR → Settings → Email Provider (and optionally set a fallback).
1
  • Configure the Entra ID integration in Settings → Integrations → Microsoft Entra ID (tenant, app registration, admin consent with Mail.Send).
  • Set the sender email in the same page (or in pf_organizations.settings.entra_sender_email).
  • Set ENTRA_CLIENT_SECRET in Supabase secrets (client secret for the app registration).
  • In HR → Settings → Email, select Microsoft Entra ID and optionally set From Email Address / From Name.
  • If Entra is selected but fails (e.g. token issue), the system can fall back to Gmail when Gmail is configured for the org.

    Gmail (Google Workspace)

    1
  • Google Cloud: Create a project, enable Gmail API, create a service account.
  • Domain-wide delegation: In Google Workspace Admin, grant the service account domain-wide delegation for scope https://www.googleapis.com/auth/gmail.send.
  • Supabase secret: Set the service account JSON as a secret:
  • Per-organization sender: In Settings → Integrations → Google Workspace (Gmail), set Sender email address to the Gmail/Workspace user to impersonate (e.g. recruiting@yourcompany.com). This is stored in pf_organizations.settings.gmail_sender_email.
  • In HR → Settings → Email, select Gmail (Google Workspace) and optionally set From Email Address / From Name.
  • Required secret: GMAIL_SERVICE_ACCOUNT_JSON (full JSON key for the service account). Edge functions: All email senders use supabase/functions/_shared/email-provider.ts; no separate provider-specific integration is required beyond Entra/Gmail configuration.

    SMS Service (RingCentral)

    1. Create a RingCentral App

    1
  • Go to the RingCentral Developer Console
  • Create an app with SMS permissions (and JWT auth credential)
  • Note your environment (Production vs Sandbox)
  • 2. Get Credentials

    Client ID / Client Secret:
    1. Open your app → Credentials
    2. Copy the Client ID and Client Secret
    JWT Credential:
    1
  • Go to CredentialsJWT
  • Create a JWT credential scoped to the app
  • Copy the JWT token
  • SMS-enabled phone number:
    1
  • Provision an SMS-enabled number on your RingCentral account
  • Configure it per-org in CE Settings → SMS (ringcentral_sms_phone_number)
  • 3. Set Supabase Secrets

    4. Configure Edge Function

    Edge Function: sms-send Required Secrets:
    • RINGCENTRAL_CLIENT_ID
    • RINGCENTRAL_CLIENT_SECRET
    • RINGCENTRAL_JWT_TOKEN
    Function Location: supabase/functions/sms-send/index.ts

    Template Configuration

    Email Templates

    Template Variables:
    • Use {{variable_name}} syntax
    • Variables replaced at send time
    • Case-sensitive
    Example Template:
    Usage in Code:

    SMS Templates

    Message Limits:
    • Single SMS: 160 characters
    • Messages > 160 characters are truncated
    • Use concise templates
    Example Template:
    Usage in Code:

    Rate Limiting & Quotas

    Email (Entra / Gmail) Limits

    Microsoft Graph (Entra): Throttling and quotas apply per tenant; see Microsoft documentation. Gmail API: Quotas and sending limits apply per Google Cloud project and per user; see Google documentation.

    RingCentral Limits

    Sandbox Account:
    • Limited to numbers on the developer account
    • SMS only to allowed numbers
    Production Account:
    • Subject to your RingCentral plan’s SMS allotment
    • Pay/throttle per plan terms
    Rate Limits:
    • RingCentral enforces per-app/per-extension SMS rate limits
    • Throttling may occur at high volumes

    Platform Limits

    Encore OS Rate Limiting (Planned):
    • Email: Max 100 emails/hour per organization
    • SMS: Max 50 SMS/hour per organization
    • Enforced in edge functions
    Current Status: Rate limiting not yet implemented

    Cost Optimization

    Email Costs (Entra / Gmail)

    Entra: Included with Microsoft 365 licensing; Graph API usage subject to tenant limits. Gmail: Subject to Google Workspace and Gmail API quotas; no per-message fee for typical org usage. Optimization Tips:
    1
  • Batch notifications when possible
  • Use send-pending-notifications for batch processing
  • Monitor email volume per organization
  • Consider email digests for non-urgent notifications
  • SMS Costs (RingCentral)

    Pricing:
    • Included in your RingCentral plan’s SMS allotment; overage billed per RingCentral terms
    • International: Varies by country
    • MMS: Higher cost
    Optimization Tips:
    1
  • Use SMS only for urgent notifications
  • Prefer email for non-urgent communications
  • Batch SMS when possible (future feature)
  • Monitor SMS volume per organization
  • Cost Monitoring

    Email providers (Entra/Gmail):
    • Monitor provider dashboards for delivery volume, throttling, and failures
    • Configure provider-side alerts/notifications for quota and auth issues
    RingCentral:
    • Admin console / analytics shows SMS usage
    • Monitor plan allotment and overage

    Error Handling

    Email Errors

    Entra (Graph API): 4xx/5xx from Graph; check tenant, app permissions, and sender identity. Gmail API: 4xx/5xx from Gmail; check service account, domain-wide delegation, and sender email. Error Handling: The shared email-provider returns EmailSendResult with success and errorMessage; callers update notification status and log accordingly.

    SMS Errors

    Common Error Codes:
    • 400 - Invalid phone number
    • 403 - Account suspended or insufficient permissions
    • 500 - RingCentral service error
    Error Handling in Function:

    Retry Logic

    Current Implementation:
    • No automatic retries
    • Failed notifications marked as failed in database
    • Manual retry via send-pending-notifications
    Future Enhancement:
    • Automatic retry with exponential backoff
    • Max 3 retries
    • Alert on persistent failures

    Testing

    Test Email Delivery

    Development:
    Production:
    • Send to verified email addresses
    • Check Supabase function logs and provider dashboards (Entra/Gmail) for delivery status

    Test SMS Delivery

    Development:
    Production:
    • Use a RingCentral sandbox app for testing
    • Send to allowed phone numbers (sandbox)
    • Check the RingCentral console for delivery status

    Test Templates

    Test Template Variables:

    Troubleshooting

    Issue: Email Not Sending

    Symptoms:
    • No email received
    • Function returns success but no email
    Solutions:
    1
  • Entra: Verify ENTRA_CLIENT_SECRET and org Entra config (tenant, app, sender email). Check Graph consent includes Mail.Send.
  • Gmail: Verify GMAIL_SERVICE_ACCOUNT_JSON and org gmail_sender_email in Settings → Integrations → Gmail. Confirm domain-wide delegation for gmail.send.
  • Verify recipient email address is valid.
  • Check spam folder.
  • Review function logs in Supabase dashboard.
  • Issue: SMS Not Sending

    Symptoms:
    • No SMS received
    • Function returns error
    Solutions:
    1
  • Check RingCentral credentials are set correctly
  • Verify phone number format: +1234567890
  • Check the RingCentral app has SMS permissions/allotment
  • Verify the number is allowed (sandbox account)
  • Check the RingCentral console for delivery status
  • Review function logs in Supabase dashboard
  • Issue: Template Variables Not Replaced

    Symptoms:
    • Email/SMS contains {{variable}} literally
    Solutions:
    1
  • Verify variables object includes all template variables
  • Check variable names match exactly (case-sensitive)
  • Verify template syntax: {{variable_name}}
  • Check function logs for variable replacement
  • Issue: Rate Limit Exceeded

    Symptoms:
    • 429 errors from email provider or RingCentral
    • Notifications fail
    Solutions:
    1
  • Implement rate limiting in application
  • Batch notifications when possible
  • For Entra/Gmail, check tenant or Google project quotas
  • Use send-pending-notifications for batch processing
  • Add retry logic with backoff
  • Issue: High Costs

    Symptoms:
    • Unexpected charges from RingCentral (or cloud provider)
    Solutions:
    1
  • Monitor usage in provider dashboards
  • Implement rate limiting per organization
  • Use email digests for non-urgent notifications
  • Prefer email over SMS when possible
  • Monitor SMS allotment in the RingCentral console

  • Best Practices

    1. Email Best Practices

    • Use verified domains (Entra: org mailbox; Gmail: Workspace domain)
    • Set up SPF/DKIM/DMARC per your domain
    • Monitor bounce rates and handle bounces
    • Use templates for consistency
    • Test templates before production use
    • Monitor delivery via Supabase logs and provider dashboards (Graph / Gmail)

    2. SMS Best Practices

    • Use SMS only for urgent notifications
    • Keep messages concise (< 160 characters)
    • Include opt-out instructions (if required)
    • Verify phone numbers before sending
    • Monitor delivery rates in the RingCentral console
    • Handle failed deliveries gracefully

    3. Security

    • Never log full email addresses or phone numbers
    • Sanitize user input in templates
    • Validate email/phone formats before sending
    • Use HTTPS for all API calls
    • Rotate API keys regularly
    • Monitor for abuse (unusual sending patterns)

    • Edge Functions: docs/integrations/EDGE_FUNCTIONS.md
    • Environment Variables: docs/development/ENVIRONMENT_VARIABLES.md
    • Secrets Management: docs/security/SECRETS_MANAGEMENT.md
    • Notifications: specs/pf/specs/PF-10-notification-system.md

    Document Owner: Platform Team
    Review Frequency: Quarterly
    Last Updated: 2025-01-07