- 📦 Module:
email
- 🔢 Version:
v0.01
This module provides comprehensive email sending capabilities for the application through SendGrid integration:
- Simple email sending with text/HTML content
- Template-based email sending with dynamic data substitution
- Multiple recipient support with personalization
- Automated email workflows triggered by database events
- Email delivery tracking and error handling
- Configuration management for SendGrid API integration
- Comprehensive error handling and logging
Design
Requirements
Email Module Testing
- Core Module: Uses shared
AppState for service integration
- Demo Module: Provides automated email workflows for business processes
- SendGrid API: External email service provider for delivery
- Environment Configuration: Requires API keys and sender verification
- API Layer (
api/): Core email service implementation and SendGrid integration
- Entity Layer (
entity/): Email data structures and content management
- Routes (
routes.rs): HTTP endpoints for email operations (currently empty)
- Constants (
constants.rs): Email configuration constants and defaults
- SendGrid Integration: Full API integration with authentication and error handling
- Template System: Dynamic template emails with variable substitution
- Multiple Recipients: Support for CC, BCC, and multiple TO recipients
- Content Types: Support for plain text, HTML, and mixed content emails
- Error Recovery: Comprehensive error handling with graceful degradation
- EmailService: Main service class handling SendGrid communication
- EmailConfig: Configuration management with environment variable loading
- EmailError: Comprehensive error type system for all failure scenarios
- SimpleEmail: Direct email sending with content
- TemplateEmail: Template-based email with dynamic data
// Simple Email with Direct Content
SimpleEmail {
to: Vec<String>,
from: String,
subject: String,
content: EmailContent,
reply_to: Option<String>,
}
// Template Email with Dynamic Data
TemplateEmail {
to: Vec<String>,
from: String,
template_id: String,
dynamic_template_data: HashMap<String, String>,
reply_to: Option<String>,
}
- API Key: Requires valid SendGrid API key starting with "SG."
- Sender Verification: Sender email must be verified with SendGrid
- Domain Authentication: Optional but recommended for deliverability
- Environment Variables:
SENDGRID_API_KEY and SENDER_EMAIL
- Single and Multiple Recipients: Support for multiple TO, CC, BCC
- Personalization: Per-recipient dynamic content
- Template Engine: SendGrid dynamic templates with variable substitution
- Content Types: Plain text, HTML, and mixed content support
- Delivery Tracking: Message ID tracking for delivery confirmation
- SeaORM after_save Hooks: Automatic email sending on database events
- Vendor Interest Emails: Triggered when
send_copy=true on vendor inquiries
- LOI Confirmation Emails: Sent upon successful Letter of Intent submission
- Email Verification: Secure token-based email verification workflows
graph TD
A[Database Event] --> B[after_save Hook]
B --> C[EmailService::new]
C --> D[Create Email Content]
D --> E[SendGrid API Call]
E --> F[Return Message ID]
F --> G[Log Success/Error]
E --> H[Network Error]
E --> I[API Error]
E --> J[Rate Limit]
H --> G
I --> G
J --> G
¶ Error Handling System
pub enum EmailError {
InvalidApiKey, // API key invalid or missing
NetworkError, // Network connectivity issues
InvalidEmailAddress, // Email format validation failed
ConfigError, // Environment configuration missing
SendGridApiError(String), // SendGrid API specific errors
SerializationError, // JSON serialization issues
}
- Graceful Degradation: Database operations continue even if email fails
- Error Logging: All email failures logged with context
- Retry Logic: Network errors can be retried (future enhancement)
- Fallback Mechanisms: Alternative notification methods (future)
- Trigger: Vendor inquiry submission with
send_copy=true
- Template: Professional business inquiry confirmation
- Content: Includes submitted information and next steps
- Error Handling: Logged but doesn't block form submission
- Trigger: Successful Letter of Intent submission
- Template: LOI confirmation with business details
- Content: LOI reference, business information, timeline
- Integration: Links with business entity and Google Places data
- Trigger: LOI workflow email verification step
- Template: Secure verification link email
- Content: Verification token and instructions
- Security: Time-limited tokens with secure generation
- API Key Protection: Keys stored securely, never logged
- Environment Isolation: Separate keys for development/production
- Rate Limiting: SendGrid API rate limits respected
- SSL/TLS: All communication encrypted via HTTPS
- Template Injection: Protection against template injection attacks
- Content Validation: Email content properly escaped and validated
- Recipient Validation: Email address format validation
- Spam Prevention: Professional templates and sender reputation
- PII Handling: Personal information properly handled in emails
- Retention Policy: Email content not stored locally after sending
- Compliance: GDPR and CAN-SPAM compliance considerations
- Unsubscribe: Mechanisms for email opt-out (future enhancement)
# SendGrid Configuration
SENDGRID_API_KEY=SG.your_sendgrid_api_key_here
SENDER_EMAIL=noreply@yourdomain.com
# Optional Email Configuration
EMAIL_REPLY_TO=support@yourdomain.com
EMAIL_BCC_ADMIN=admin@yourdomain.com
- Account Creation: Valid SendGrid account with API access
- Sender Verification: Single sender verification or domain authentication
- Template Creation: Dynamic templates for automated emails
- Quota Management: Sufficient email sending quota for expected volume
- Webhook Configuration: Delivery status webhooks (optional)
- Email Sending: Typically 1-3 seconds per email
- Template Emails: Slightly faster than simple emails
- Multiple Recipients: Linear scaling with recipient count
- Error Scenarios: Fast fail for configuration errors
- SendGrid Limits: Respects SendGrid API rate limits
- Concurrent Sending: Safe for multiple simultaneous email operations
- Queue Management: Future enhancement for high-volume scenarios
- Batching: Support for batch sending (future enhancement)
The email module currently operates as a service layer without direct HTTP endpoints. Integration occurs through:
- Database Triggers: Automatic emails via SeaORM hooks
- Direct Service Calls:
EmailService::send_template() and EmailService::send_simple()
- AppState Integration: Service available throughout application
| Method |
Path |
Description |
| POST |
/api/email/send |
Send simple email |
| POST |
/api/email/template |
Send template email |
| GET |
/api/email/templates |
List available templates |
| GET |
/api/email/status/:id |
Check email delivery status |
- Email Attempts: All email sending attempts logged
- Success Tracking: Message IDs logged for delivery tracking
- Error Details: Comprehensive error logging with context
- Performance Metrics: Email sending times and success rates
- Service Health: Email service configuration validation
- API Connectivity: SendGrid API reachability checks
- Quota Monitoring: SendGrid quota usage tracking
- Template Validation: Template availability verification
- Email Volume: Daily/hourly email sending volumes
- Success Rates: Email delivery success percentages
- Error Rates: Error categorization and frequency
- Performance: Average email sending response times
- SendGrid Account: Production SendGrid account with appropriate tier
- Domain Authentication: Recommended for better deliverability
- IP Warming: For high-volume senders
- Monitoring: Email delivery monitoring and alerting
- Backup Strategy: Alternative email providers for redundancy
# Production Environment
SENDGRID_API_KEY=SG.production_key_here
SENDER_EMAIL=noreply@yourdomain.com
# Development Environment
SENDGRID_API_KEY=SG.development_key_here
SENDER_EMAIL=dev-noreply@yourdomain.com
- High Volume: Consider SendGrid dedicated IP for >100k emails/month
- Geographic Distribution: SendGrid global infrastructure
- Failover: Multiple SendGrid accounts for redundancy
- Queue Management: Redis-based email queue for high throughput
graph TB
EmailService --> EmailConfig
EmailService --> Sender
EmailConfig --> |env vars| SENDGRID_API_KEY
EmailConfig --> |env vars| SENDER_EMAIL
EmailService --> SimpleEmail
EmailService --> TemplateEmail
SimpleEmail --> EmailContent
TemplateEmail --> DynamicData
EmailContent --> TextContent
EmailContent --> HtmlContent
EmailContent --> MixedContent
DynamicData --> Variables[HashMap Variables]
erDiagram
EmailService ||--|| EmailConfig : uses
EmailService ||--o{ SimpleEmail : sends
EmailService ||--o{ TemplateEmail : sends
SimpleEmail ||--|| EmailContent : contains
TemplateEmail ||--|| DynamicData : contains
EmailConfig {
string api_key
string sender_email
}
SimpleEmail {
string_array to
string from
string subject
EmailContent content
string reply_to
}
TemplateEmail {
string_array to
string from
string template_id
hashmap dynamic_template_data
string reply_to
}
EmailContent {
enum content_type
string text_content
string html_content
}
// In vendor_interest.rs after_save hook
#[async_trait::async_trait]
impl ActiveModelBehavior for ActiveModel {
async fn after_save<C>(model: Model, db: &C, insert: bool) -> Result<Model, DbErr> {
if insert && model.send_copy {
if let Err(e) = Self::send_vendor_interest_email(&model).await {
eprintln!("Failed to send vendor interest email: {}", e);
}
}
Ok(model)
}
}
// Direct email service usage
let email_service = EmailService::new().await?;
let template_email = TemplateEmail {
to: vec!["user@example.com".to_string()],
from: email_service.sender_email().to_string(),
template_id: "vendor_interest_confirmation".to_string(),
dynamic_template_data: variables,
reply_to: None,
};
let message_id = email_service.send_template(template_email).await?;