> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Email Notifications Guide

> Encore Health OS supports email delivery for in-app notifications, allowing users to receive important updates directly in their inbox. Emails are sent via the…

## Overview

Encore Health OS supports email delivery for in-app notifications, allowing users to receive important updates directly in their inbox. Emails are sent via the org-configured provider: **Microsoft Entra ID** (Graph API) or **Gmail** (Google Workspace).

## Configuration

### Prerequisites

* **Entra:** Configure in Settings → Integrations → Microsoft Entra ID; set `ENTRA_CLIENT_SECRET` in Supabase secrets.
* **Gmail:** Set `GMAIL_SERVICE_ACCOUNT_JSON` in Supabase secrets; set sender email in Settings → Integrations → Google Workspace (Gmail).
* Per-org provider choice in HR → Settings → Email (Entra or Gmail).

### Email Provider

The platform uses the shared email-provider abstraction (Entra or Gmail):

* Professional HTML templates
* Delivery tracking
* Bounce and failure handling
* Variable substitution

## Email Template Types

### Standard Notifications

Basic notifications with auto-generated template wrapper. Used for simple alerts and updates.

### Scheduled Report Emails

Professional branded templates for automated report delivery with:

* Branded Encore Health OS header with gradient
* Report details card (name, description)
* Statistics row (generated date, row count, format, file size)
* Prominent download button with signed URL
* Next scheduled run indicator
* Responsive design for mobile

### Report Failure Emails

Error notification template for when scheduled reports fail:

* Red accent error header
* Error details card with message
* Troubleshooting suggestions
* Link to reports page

## Localization Support

Email templates support localization via the `locale` parameter:

### Supported Locales

* `en` - English (default)
* `es` - Spanish (coming soon)
* `fr` - French (coming soon)

### Adding New Locales

1. Create locale file: `supabase/functions/_shared/email-templates/locales/{locale}.ts`
2. Export translations matching `ReportDeliveryStrings` and `ReportFailedStrings` interfaces
3. Add locale to `Locale` type in `types.ts`
4. Import and add to locale maps in template files

### Translation Keys

```typescript theme={null}
interface ReportDeliveryStrings {
  greeting: string;           // "Hello {{name}},"
  subject: string;            // "📊 Scheduled Report: {{report_name}}"
  reportReady: string;        // "Your scheduled report is ready"
  downloadButton: string;     // "Download Report"
  linkExpiry: string;         // "Link expires in {{days}} days"
  nextRun: string;            // "Next scheduled run: {{date}}"
  // ... more keys
}
```

**⚠️ Security Note:** All template variable values (`{{name}}`, `{{report_name}}`, etc.) must be escaped using `escapeHtml()` from `_shared/email-templates/utils.ts` before interpolation to prevent XSS attacks in rendered emails.

## Features

### Automatic Email Delivery

Notifications with `channel='email'` are automatically sent via the `send-email-notification` edge function.

### Pre-Rendered HTML Support

For complex templates like scheduled reports, you can provide pre-rendered HTML:

```typescript theme={null}
await supabase.functions.invoke('send-email-notification', {
  body: {
    notificationId,
    recipientEmail: 'user@example.com',
    recipientName: 'John',
    subject: 'Your Report',
    body: '', // Not used when skipTemplate is true
    html: preRenderedHtml,
    skipTemplate: true,
  },
});
```

### Template Variables

Emails support variable substitution using `{{variable}}` syntax:

* `{{user.name}}` - Recipient's name
* `{{org.name}}` - Organization name
* `{{action.url}}` - Action link
* Custom variables per notification type

### Delivery Tracking

All emails track:

* **Sent** - Successfully delivered via org provider (Entra or Gmail)
* **Delivered** - Confirmed received by recipient
* **Bounced** - Email address invalid or rejected
* **Failed** - Delivery error occurred

## Usage

### Sending Standard Email Notifications

```typescript theme={null}
import { supabase } from '@/integrations/supabase/client';

await supabase.from('pf_notifications').insert({
  user_id: userId,
  organization_id: orgId,
  title: 'Document Approved',
  body: 'Your document "{{document.name}}" has been approved.',
  type: 'document_approval',
  channel: 'email',
  action_url: '/documents/123',
});
```

### Using Report Email Templates

```typescript theme={null}
import { 
  renderReportDeliveryEmail, 
  getReportDeliverySubject 
} from '../_shared/email-templates/index.ts';

const emailHtml = renderReportDeliveryEmail({
  recipientName: 'John',
  reportName: 'Monthly Revenue',
  reportDescription: 'Revenue summary by department',
  generatedAt: new Date(),
  rowCount: 1500,
  format: 'csv',
  fileSizeBytes: 45000,
  downloadUrl: signedUrl,
  expiryDays: 7,
  nextRunAt: new Date('2026-02-01'),
  organizationName: 'Acme Corp',
  locale: 'en',
});

const subject = getReportDeliverySubject('Monthly Revenue', 'en');
```

### Checking Delivery Status

```typescript theme={null}
import { useNotificationDelivery } from '@/platform/notifications/hooks/useNotificationDelivery';

function NotificationRow({ notificationId }) {
  const { data: delivery } = useNotificationDelivery(notificationId);
  
  return (
    <div>
      Status: {delivery?.delivery_status}
      {delivery?.delivered_at && `Delivered at: ${delivery.delivered_at}`}
      {delivery?.delivery_error && `Error: ${delivery.delivery_error}`}
    </div>
  );
}
```

### UI Component

```typescript theme={null}
import { NotificationDeliveryStatus } from '@/platform/notifications/components/NotificationDeliveryStatus';

<NotificationDeliveryStatus notificationId={notification.id} />
```

## Email Template Architecture

```
supabase/functions/_shared/email-templates/
├── index.ts              # Exports all templates and utilities
├── base-layout.ts        # Shared HTML layout (header, footer, styles)
├── report-delivery.ts    # Scheduled report delivery template
├── report-failed.ts      # Report failure notification template
└── locales/
    ├── types.ts          # Translation key type definitions
    └── en.ts             # English translations
```

## Template Features

### Base Layout (`base-layout.ts`)

* Responsive design (max-width 600px)
* Branded header with Encore Health OS gradient
* Dark mode ready with `prefers-color-scheme` meta
* Consistent footer with preferences link
* Utility functions: `interpolate()`, `formatBytes()`, `formatDate()`

### Report Delivery Template

* Personalized greeting
* Report details card
* Stats row with 4 columns
* Large download CTA button
* Column summary (optional)
* Next run indicator
* Auto-generated notice

### Report Failed Template

* Error-state red header
* Error details card with message
* Suggestion box with troubleshooting tips
* View Reports button

## Best Practices

1. **Use Clear Subjects**: Keep subject lines under 50 characters
2. **Provide Context**: Include relevant details in the body
3. **Add Action URLs**: Always link to the relevant page
4. **Test Variables**: Ensure all variables are defined before sending
5. **Monitor Bounces**: Review bounced emails and update user profiles
6. **Use Pre-Rendered HTML**: For complex templates, use `skipTemplate: true`

## Error Handling

Failed emails are automatically logged with:

* Error message stored in `delivery_error`
* Status set to `'failed'`
* Notification remains viewable in-app

Common errors:

* Invalid email address → Update user profile
* Rate limit exceeded → Emails queued automatically
* Auth/API error → Check Entra or Gmail configuration (Settings → Integrations)

## Rate Limits

Provider rate limits:

* **Free tier**: 100 emails/day
* **Paid tier**: Custom limits

Batch sending automatically respects rate limits with exponential backoff.

## Testing

### Development Testing

Test email delivery:

1. Configure Entra or Gmail per org (Settings → Integrations)
2. In HR → Settings → Email, use "Send Test Email" to verify

### Production Testing

1. Verify sender identity (Entra mailbox or Gmail/Workspace user)
2. Update `from` address in edge function
3. Test with real email addresses
4. Monitor delivery in Supabase logs and provider dashboards

## Troubleshooting

### Emails Not Sending

1. Check Entra or Gmail secrets and org config (Settings → Integrations)
2. Verify edge function deployed successfully
3. Check notification has `channel='email'`
4. Review edge function logs

### Emails Bouncing

1. Verify email address format (must be valid)
2. Check recipient's email server isn't blocking
3. Confirm sender domain is verified (production)
4. Review function logs and provider dashboards for bounce/failure reasons

### Variables Not Replacing

1. Ensure variables use `{{key}}` format
2. Verify variable data is provided in notification
3. Check for typos in variable names
4. Test with simple variables first

### Pre-Rendered HTML Not Working

1. Ensure `skipTemplate: true` is set
2. Verify `html` field contains valid HTML
3. Check that `body` field is empty string (not undefined)

## Related Documentation

* [Notifications System](./notifications-guide.md)
* [Report Scheduling Guide](./report-scheduling-guide.md)
* [SMS Notifications](./sms-notifications-guide.md)
* [Notification Preferences](./notifications-guide.md#preferences)
