@bernierllc/email-sendgrid-plugin
SendGrid-specific template management, sender verification, and advanced features plugin for email template services.
Installation
npm install @bernierllc/email-sendgrid-plugin
Overview
This package provides a comprehensive plugin for integrating SendGrid's template management and sender verification features into your email template service. It includes:
- Template CRUD Operations - Create, read, update, and delete SendGrid templates
- Verified Sender Management - Manage and validate SendGrid verified senders
- Template Synchronization - Bi-directional sync between local and SendGrid templates
- Safety Features - Shared account protection and template ownership validation
- Rate Limiting - Built-in API rate limiting to respect SendGrid quotas
- Template Versioning - Support for SendGrid template versions and activation
Key Features
Template Management
- Full CRUD operations with SendGrid API
- Template versioning and activation
- Shared account safety (application-scoped operations)
- Template prefix enforcement
- Conflict detection and resolution
Verified Sender Integration
- Sender verification status checking
- Domain matching and validation
- Automatic sender selection
- Sender configuration management
Safety and Security
- Application-scoped operations (never access non-app templates)
- Template prefix enforcement
- Shared account protection
- Operation auditing and logging
- Strict/permissive safety modes
Usage
Basic Setup
import { SendGridTemplatePlugin } from '@bernierllc/email-sendgrid-plugin';
const plugin = new SendGridTemplatePlugin({
apiKey: process.env.SENDGRID_API_KEY!,
templatePrefix: 'MyApp - ',
safetyMode: 'strict',
rateLimits: {
templatesPerMinute: 60,
apiCallsPerSecond: 10
}
});
// Initialize the plugin
await plugin.initialize({});
Creating Templates
import { Template } from '@bernierllc/email-sendgrid-plugin';
const template: Template = {
id: 'local-123',
name: 'Welcome Email',
subject: 'Welcome to {{appName}}',
htmlContent: '<html><body><h1>Welcome {{userName}}</h1></body></html>',
textContent: 'Welcome {{userName}}',
category: 'transactional',
tags: ['welcome', 'onboarding'],
version: '1.0.0',
isActive: true,
requiredVariables: ['appName', 'userName'],
createdAt: new Date(),
updatedAt: new Date(),
createdBy: 'system',
lastModifiedBy: 'system'
};
const sendgridTemplateId = await plugin.createTemplate(template);
console.log(`Created SendGrid template: ${sendgridTemplateId}`);
Managing Templates
// Get template
const template = await plugin.getTemplate('sendgrid-template-id');
// List all templates
const templates = await plugin.listTemplates();
// Update template
await plugin.updateTemplate('sendgrid-template-id', updatedTemplate);
// Delete template
await plugin.deleteTemplate('sendgrid-template-id');
Sender Verification
// Get all verified senders
const senders = await plugin.getVerifiedSenders();
// Validate sender email
const validation = await plugin.validateSender('noreply@myapp.com');
if (!validation.isValid) {
console.log('Sender validation failed:');
validation.errors.forEach(error => console.log(`- ${error}`));
console.log('Suggestions:');
validation.suggestions.forEach(suggestion => console.log(`- ${suggestion}`));
}
// Select best sender for outgoing email
const bestSender = await plugin.selectBestSender('noreply@myapp.com');
if (bestSender) {
console.log(`Using verified sender: ${bestSender.email}`);
}
Template Synchronization
// Sync local template to SendGrid
const syncResult = await plugin.syncToProvider(localTemplate);
if (syncResult.success) {
console.log(`Synced template ${syncResult.action}: ${syncResult.providerTemplateId}`);
} else {
console.error(`Sync failed: ${syncResult.error}`);
}
// Pull template from SendGrid
const localTemplate = await plugin.syncFromProvider('sendgrid-template-id');
// Batch synchronization
const results = await plugin.batchSyncTemplates([template1, template2, template3]);
const successful = results.filter(r => r.success).length;
console.log(`Batch sync: ${successful}/${results.length} successful`);
Template Versioning
// Create new template version
const versionId = await plugin.createTemplateVersion('sendgrid-template-id', {
name: 'v2.0.0',
subject: 'Updated Subject',
htmlContent: '<html><body>Updated content</body></html>',
textContent: 'Updated content',
active: false
});
// Activate template version
await plugin.activateTemplateVersion('sendgrid-template-id', versionId);
Configuration
SendGridPluginConfig
interface SendGridPluginConfig {
// SendGrid API key (required)
apiKey: string;
// Template prefix for shared account safety (required)
templatePrefix: string;
// Safety mode: 'strict' or 'permissive' (required)
safetyMode: 'strict' | 'permissive';
// Whether using shared SendGrid account (optional)
sharedAccount?: boolean;
// API rate limits (optional)
rateLimits?: {
templatesPerMinute: number;
apiCallsPerSecond: number;
};
// Webhook configuration (optional)
webhookConfig?: {
secret: string;
eventTypes: string[];
};
}
Safety Modes
Strict Mode (Recommended):
- Only allows operations on templates registered with the application
- Throws
UnauthorizedTemplateAccessError
for unregistered templates - Provides maximum safety in shared account environments
Permissive Mode:
- Allows operations on any template
- Useful for administrative tools or migration scripts
- Use with caution in shared account environments
Rate Limiting
The plugin includes built-in rate limiting to respect SendGrid's API quotas:
const plugin = new SendGridTemplatePlugin({
apiKey: process.env.SENDGRID_API_KEY!,
templatePrefix: 'MyApp - ',
safetyMode: 'strict',
rateLimits: {
templatesPerMinute: 60, // Max 60 template operations per minute
apiCallsPerSecond: 10 // Max 10 API calls per second
}
});
Plugin Capabilities
The plugin provides information about its capabilities:
// Get all capabilities
const capabilities = plugin.getCapabilities();
// Check if feature is supported
if (plugin.supportsFeature('sender-verification')) {
console.log('Sender verification is supported');
}
// Get feature configuration
const config = plugin.getFeatureConfig('template-management');
console.log(`Supports versioning: ${config.supportsVersioning}`);
Available Capabilities
- template-management: Full CRUD operations for SendGrid templates
- sender-verification: SendGrid verified sender management
- template-analytics: Template usage and performance analytics
- batch-operations: Efficient bulk template operations
Error Handling
The plugin provides specific error types for different failure scenarios:
import {
SendGridApiError,
TemplateNotFoundError,
UnauthorizedTemplateAccessError,
TemplateConflictError,
RateLimitError
} from '@bernierllc/email-sendgrid-plugin';
try {
await plugin.getTemplate('template-id');
} catch (error) {
if (error instanceof TemplateNotFoundError) {
console.log('Template does not exist');
} else if (error instanceof UnauthorizedTemplateAccessError) {
console.log('Template not owned by this application');
} else if (error instanceof SendGridApiError) {
console.log(`SendGrid API error: ${error.statusCode}`);
} else if (error instanceof RateLimitError) {
console.log('Rate limit exceeded');
}
}
Integration with Email Template Service
This plugin is designed to work with @bernierllc/email-template-service
:
import { SendGridTemplatePlugin } from '@bernierllc/email-sendgrid-plugin';
import { EmailTemplateService } from '@bernierllc/email-template-service';
const sendGridPlugin = new SendGridTemplatePlugin({
apiKey: process.env.SENDGRID_API_KEY!,
templatePrefix: 'MyApp - ',
sharedAccount: true,
safetyMode: 'strict',
rateLimits: {
templatesPerMinute: 60,
apiCallsPerSecond: 10
}
});
const templateService = new EmailTemplateService({
providers: [sendGridPlugin],
syncConfig: {
enabled: true,
providers: {
sendgrid: {
enabled: true,
strategy: 'auto',
direction: 'bidirectional'
}
}
}
});
await templateService.initialize();
Testing
Run the test suite:
# Run tests in watch mode
npm test
# Run tests with coverage
npm run test:coverage
# Run tests once
npm run test:run
API Reference
SendGridTemplatePlugin
Core Methods
initialize(config: PluginConfig): Promise<void>
- Initialize the plugindestroy(): Promise<void>
- Cleanup and destroy the plugin
Template Operations
createTemplate(template: Template): Promise<string>
- Create a new templateupdateTemplate(id: string, template: Template): Promise<void>
- Update existing templatedeleteTemplate(id: string): Promise<void>
- Delete a templategetTemplate(id: string): Promise<ProviderTemplate>
- Get template by IDlistTemplates(): Promise<ProviderTemplate[]>
- List all templates
Sender Operations
getVerifiedSenders(): Promise<VerifiedSender[]>
- Get all verified sendersvalidateSender(email: string): Promise<SenderValidationResult>
- Validate sender emailselectBestSender(email: string): Promise<VerifiedSender | null>
- Auto-select best sender
Synchronization
syncToProvider(template: Template): Promise<SyncResult>
- Sync template to SendGridsyncFromProvider(id: string): Promise<Template>
- Pull template from SendGridbatchSyncTemplates(templates: Template[]): Promise<SyncResult[]>
- Batch sync
Versioning
createTemplateVersion(id: string, version: TemplateVersion): Promise<string>
- Create versionactivateTemplateVersion(id: string, versionId: string): Promise<void>
- Activate version
Capabilities
getCapabilities(): ProviderCapability[]
- Get all capabilitiessupportsFeature(feature: string): boolean
- Check feature supportgetFeatureConfig(feature: string): FeatureConfig | null
- Get feature config
Integration Status
- Logger: Optional - All SendGrid operations and safety events
- Docs-Suite: Ready - Complete API documentation
- NeverHub: Optional - SendGrid API health monitoring and template sync events
NeverHub Integration
This package supports optional NeverHub integration for enhanced observability and event-driven workflows:
import { SendGridTemplatePlugin } from '@bernierllc/email-sendgrid-plugin';
import { NeverHubAdapter } from '@bernierllc/neverhub-adapter';
const plugin = new SendGridTemplatePlugin({
apiKey: process.env.SENDGRID_API_KEY!,
templatePrefix: 'MyApp - ',
safetyMode: 'strict'
});
// Auto-detect NeverHub availability
const neverhub = await NeverHubAdapter.detectNeverHub()
? new NeverHubAdapter()
: null;
if (neverhub) {
// Register plugin capabilities
await neverhub.register({
type: 'email-plugin',
name: '@bernierllc/email-sendgrid-plugin',
capabilities: ['template-management', 'sender-verification']
});
// Subscribe to template events
await neverhub.subscribe('template.updated', async (event) => {
await plugin.syncFromProvider(event.templateId);
});
}
await plugin.initialize({});
The plugin works fully without NeverHub integration - all core functionality is available regardless of NeverHub presence.
Dependencies
@sendgrid/mail
- Official SendGrid SDK@bernierllc/logger
- Operation logging (optional)@bernierllc/retry-policy
- API call retries@bernierllc/rate-limiter
- API rate limiting
License
Copyright (c) 2025 Bernier LLC. All rights reserved.
See Also
- @bernierllc/email-template-service - Email template service
- @bernierllc/email-sender - Email sending abstraction
- @bernierllc/retry-policy - Retry policy utilities
- @bernierllc/rate-limiter - Rate limiting utilities