Some checks failed
CI/CD Pipeline / Test Suite (push) Has been cancelled
CI/CD Pipeline / Security Audit (push) Has been cancelled
CI/CD Pipeline / Performance Benchmarks (push) Has been cancelled
Rust CI / Security Audit (push) Has been cancelled
Rust CI / Check + Test + Lint (nightly) (push) Has been cancelled
Rust CI / Check + Test + Lint (stable) (push) Has been cancelled
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
CI/CD Pipeline / Cleanup (push) Has been cancelled
821 lines
17 KiB
Markdown
821 lines
17 KiB
Markdown
# Email System Documentation
|
|
|
|
This document provides comprehensive documentation for the Rustelo email system, including setup, configuration, usage, and examples.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Features](#features)
|
|
- [Quick Start](#quick-start)
|
|
- [Configuration](#configuration)
|
|
- [Email Providers](#email-providers)
|
|
- [Templates](#templates)
|
|
- [API Endpoints](#api-endpoints)
|
|
- [Client Components](#client-components)
|
|
- [Server Usage](#server-usage)
|
|
- [Environment Variables](#environment-variables)
|
|
- [Security Considerations](#security-considerations)
|
|
- [Troubleshooting](#troubleshooting)
|
|
- [Examples](#examples)
|
|
|
|
## Overview
|
|
|
|
The Rustelo email system provides a comprehensive solution for sending emails from your web application. It supports multiple email providers, template-based emails, form submissions, and both server-side and client-side integration.
|
|
|
|
### Architecture
|
|
|
|
- **Email Service**: Core service that handles email sending
|
|
- **Providers**: Pluggable email providers (SMTP, SendGrid, Console)
|
|
- **Templates**: Handlebars-based email templates
|
|
- **Forms**: Ready-to-use contact and support form components
|
|
- **API**: REST endpoints for email operations
|
|
|
|
## Features
|
|
|
|
✨ **Multiple Providers**
|
|
- SMTP (Gmail, Outlook, custom servers)
|
|
- SendGrid API
|
|
- Console output (development)
|
|
|
|
📧 **Template System**
|
|
- Handlebars templates
|
|
- HTML and text versions
|
|
- Custom helpers
|
|
- Variable substitution
|
|
|
|
🔧 **Form Integration**
|
|
- Contact forms
|
|
- Support forms with priorities
|
|
- Custom form handling
|
|
|
|
🛡️ **Security**
|
|
- Input validation
|
|
- Rate limiting
|
|
- CSRF protection
|
|
- Secure configuration
|
|
|
|
🎨 **Rich Components**
|
|
- React/Leptos form components
|
|
- Real-time validation
|
|
- Error handling
|
|
- Success feedback
|
|
|
|
## Quick Start
|
|
|
|
### 1. Enable Email Feature
|
|
|
|
Make sure the email feature is enabled in your `Cargo.toml`:
|
|
|
|
```toml
|
|
[features]
|
|
default = ["email"]
|
|
email = ["lettre", "handlebars", "urlencoding"]
|
|
```
|
|
|
|
### 2. Basic Configuration
|
|
|
|
Add email configuration to your `config.toml`:
|
|
|
|
```toml
|
|
[email]
|
|
enabled = true
|
|
provider = "console" # Start with console for development
|
|
from_email = "noreply@yourapp.com"
|
|
from_name = "Your App"
|
|
template_dir = "templates/email"
|
|
```
|
|
|
|
### 3. Create Template Directory
|
|
|
|
```bash
|
|
mkdir -p templates/email/html
|
|
mkdir -p templates/email/text
|
|
```
|
|
|
|
### 4. Start Using
|
|
|
|
```rust
|
|
// Send a simple email
|
|
let result = email_service.send_simple_email(
|
|
"user@example.com",
|
|
"Welcome!",
|
|
"Thank you for signing up!"
|
|
).await?;
|
|
|
|
// Send a contact form
|
|
let result = email_service.send_contact_form(
|
|
"John Doe",
|
|
"john@example.com",
|
|
"Question about pricing",
|
|
"I'd like to know more about your pricing plans.",
|
|
"admin@yourapp.com"
|
|
).await?;
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Email Configuration Options
|
|
|
|
```toml
|
|
[email]
|
|
# Basic settings
|
|
enabled = true
|
|
provider = "smtp" # "smtp", "sendgrid", "console"
|
|
from_email = "noreply@yourapp.com"
|
|
from_name = "Your App Name"
|
|
template_dir = "templates/email"
|
|
|
|
# SMTP settings (when provider = "smtp")
|
|
smtp_host = "smtp.gmail.com"
|
|
smtp_port = 587
|
|
smtp_username = "your-email@gmail.com"
|
|
smtp_password = "your-app-password"
|
|
smtp_use_tls = false
|
|
smtp_use_starttls = true
|
|
|
|
# SendGrid settings (when provider = "sendgrid")
|
|
sendgrid_api_key = "your-sendgrid-api-key"
|
|
sendgrid_endpoint = "https://api.sendgrid.com/v3/mail/send"
|
|
```
|
|
|
|
### Environment-Specific Configuration
|
|
|
|
```toml
|
|
# Development
|
|
[environments.development]
|
|
email.provider = "console"
|
|
email.enabled = true
|
|
|
|
# Production
|
|
[environments.production]
|
|
email.provider = "sendgrid"
|
|
email.sendgrid_api_key = "${SENDGRID_API_KEY}"
|
|
email.enabled = true
|
|
```
|
|
|
|
## Email Providers
|
|
|
|
### Console Provider
|
|
|
|
Perfect for development and testing. Prints emails to the console.
|
|
|
|
```toml
|
|
[email]
|
|
provider = "console"
|
|
```
|
|
|
|
**Features:**
|
|
- No external dependencies
|
|
- Immediate feedback
|
|
- Safe for development
|
|
|
|
### SMTP Provider
|
|
|
|
Use any SMTP server including Gmail, Outlook, or custom servers.
|
|
|
|
```toml
|
|
[email]
|
|
provider = "smtp"
|
|
smtp_host = "smtp.gmail.com"
|
|
smtp_port = 587
|
|
smtp_username = "your-email@gmail.com"
|
|
smtp_password = "your-app-password"
|
|
smtp_use_starttls = true
|
|
```
|
|
|
|
**Common SMTP Configurations:**
|
|
|
|
**Gmail:**
|
|
```toml
|
|
smtp_host = "smtp.gmail.com"
|
|
smtp_port = 587
|
|
smtp_use_starttls = true
|
|
# Requires App Password (not regular password)
|
|
```
|
|
|
|
**Outlook:**
|
|
```toml
|
|
smtp_host = "smtp-mail.outlook.com"
|
|
smtp_port = 587
|
|
smtp_use_starttls = true
|
|
```
|
|
|
|
**Custom Server:**
|
|
```toml
|
|
smtp_host = "mail.yourdomain.com"
|
|
smtp_port = 587
|
|
smtp_use_starttls = true
|
|
```
|
|
|
|
### SendGrid Provider
|
|
|
|
Professional email service with high deliverability.
|
|
|
|
```toml
|
|
[email]
|
|
provider = "sendgrid"
|
|
sendgrid_api_key = "your-api-key"
|
|
```
|
|
|
|
**Setup Steps:**
|
|
1. Sign up at [SendGrid](https://sendgrid.com)
|
|
2. Create an API key
|
|
3. Verify your sender identity
|
|
4. Add API key to configuration
|
|
|
|
## Templates
|
|
|
|
### Template Structure
|
|
|
|
Templates are organized in HTML and text directories:
|
|
|
|
```
|
|
templates/email/
|
|
├── html/
|
|
│ ├── contact.hbs
|
|
│ ├── notification.hbs
|
|
│ └── welcome.hbs
|
|
└── text/
|
|
├── contact.hbs
|
|
├── notification.hbs
|
|
└── welcome.hbs
|
|
```
|
|
|
|
### Template Naming
|
|
|
|
Templates are named using the pattern: `{template_name}_{format}.hbs`
|
|
|
|
- `contact_html` - HTML version of contact template
|
|
- `contact_text` - Text version of contact template
|
|
|
|
### Handlebars Helpers
|
|
|
|
The system includes several built-in helpers:
|
|
|
|
**Date Formatting:**
|
|
```handlebars
|
|
{{date_format submitted_at "%B %d, %Y at %I:%M %p UTC"}}
|
|
```
|
|
|
|
**Capitalization:**
|
|
```handlebars
|
|
{{capitalize form_type}}
|
|
```
|
|
|
|
**Truncation:**
|
|
```handlebars
|
|
{{truncate user_agent 100}}
|
|
```
|
|
|
|
**Default Values:**
|
|
```handlebars
|
|
{{default action_text "Take Action"}}
|
|
```
|
|
|
|
**URL Encoding:**
|
|
```handlebars
|
|
{{url_encode email}}
|
|
```
|
|
|
|
### Example Template
|
|
|
|
**HTML Template (contact.hbs):**
|
|
```html
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Contact Form Submission</title>
|
|
</head>
|
|
<body>
|
|
<h1>New Contact Form Submission</h1>
|
|
|
|
<p><strong>Name:</strong> {{name}}</p>
|
|
<p><strong>Email:</strong> {{email}}</p>
|
|
<p><strong>Subject:</strong> {{subject}}</p>
|
|
|
|
<div>
|
|
<strong>Message:</strong>
|
|
<p>{{message}}</p>
|
|
</div>
|
|
|
|
<hr>
|
|
<p>Submitted on {{date_format submitted_at}}</p>
|
|
</body>
|
|
</html>
|
|
```
|
|
|
|
**Text Template (contact.hbs):**
|
|
```text
|
|
Contact Form Submission
|
|
|
|
Name: {{name}}
|
|
Email: {{email}}
|
|
Subject: {{subject}}
|
|
|
|
Message:
|
|
{{message}}
|
|
|
|
---
|
|
Submitted on {{date_format submitted_at}}
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### GET /api/email/status
|
|
|
|
Get email service status and available templates.
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"enabled": true,
|
|
"provider": "smtp",
|
|
"configured": true,
|
|
"templates": ["contact_html", "contact_text", "notification_html"]
|
|
}
|
|
```
|
|
|
|
### POST /api/email/contact
|
|
|
|
Submit a contact form.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"name": "John Doe",
|
|
"email": "john@example.com",
|
|
"subject": "Question about pricing",
|
|
"message": "I'd like to know more about your plans.",
|
|
"recipient": "admin@yourapp.com"
|
|
}
|
|
```
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"message": "Contact form submitted successfully",
|
|
"message_id": "smtp-1234567890",
|
|
"status": "sent"
|
|
}
|
|
```
|
|
|
|
### POST /api/email/support
|
|
|
|
Submit a support form with priority and category.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"name": "Jane Smith",
|
|
"email": "jane@example.com",
|
|
"subject": "Login issues",
|
|
"message": "I can't log into my account.",
|
|
"priority": "high",
|
|
"category": "technical",
|
|
"recipient": "support@yourapp.com"
|
|
}
|
|
```
|
|
|
|
### POST /api/email/send
|
|
|
|
Send a custom email (admin only).
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"to": "user@example.com",
|
|
"subject": "Welcome to our service",
|
|
"template": "welcome",
|
|
"template_data": {
|
|
"user_name": "John",
|
|
"activation_link": "https://app.com/activate/123"
|
|
}
|
|
}
|
|
```
|
|
|
|
### POST /api/email/notification
|
|
|
|
Send a notification email.
|
|
|
|
**Request:**
|
|
```json
|
|
{
|
|
"to": "user@example.com",
|
|
"title": "Account Verification",
|
|
"message": "Please verify your email address",
|
|
"content": "<p>Click the link below to verify...</p>"
|
|
}
|
|
```
|
|
|
|
## Client Components
|
|
|
|
### ContactForm Component
|
|
|
|
```jsx
|
|
import { ContactForm } from './components/forms';
|
|
|
|
<ContactForm
|
|
title="Get in Touch"
|
|
description="We'd love to hear from you"
|
|
recipient="contact@yourapp.com"
|
|
showSuccess={true}
|
|
resetAfterSuccess={true}
|
|
/>
|
|
```
|
|
|
|
**Props:**
|
|
- `recipient`: Email address to send form to
|
|
- `title`: Form title
|
|
- `description`: Form description
|
|
- `class`: Custom CSS class
|
|
- `showSuccess`: Show success message
|
|
- `resetAfterSuccess`: Reset form after success
|
|
- `submitText`: Custom submit button text
|
|
|
|
### SupportForm Component
|
|
|
|
```jsx
|
|
import { SupportForm } from './components/forms';
|
|
|
|
<SupportForm
|
|
title="Support Request"
|
|
recipient="support@yourapp.com"
|
|
showPriority={true}
|
|
showCategory={true}
|
|
categories={customCategories}
|
|
/>
|
|
```
|
|
|
|
**Additional Props:**
|
|
- `showPriority`: Show priority selector
|
|
- `showCategory`: Show category selector
|
|
- `categories`: Custom category options
|
|
|
|
### Form Validation
|
|
|
|
Both forms include comprehensive validation:
|
|
- Required field validation
|
|
- Email format validation
|
|
- Length limits
|
|
- Real-time error display
|
|
- Accessibility support
|
|
|
|
## Server Usage
|
|
|
|
### Basic Email Sending
|
|
|
|
```rust
|
|
use crate::email::{EmailService, EmailServiceBuilder};
|
|
|
|
// Initialize service
|
|
let email_service = EmailServiceBuilder::new()
|
|
.smtp_provider(smtp_config)
|
|
.default_from("noreply@app.com")
|
|
.default_from_name("My App")
|
|
.build()
|
|
.await?;
|
|
|
|
// Send simple email
|
|
let result = email_service.send_simple_email(
|
|
"user@example.com",
|
|
"Welcome!",
|
|
"Thank you for signing up!"
|
|
).await?;
|
|
```
|
|
|
|
### Template-Based Emails
|
|
|
|
```rust
|
|
use std::collections::HashMap;
|
|
use serde_json::json;
|
|
|
|
let mut template_data = HashMap::new();
|
|
template_data.insert("user_name".to_string(), json!("John"));
|
|
template_data.insert("login_url".to_string(), json!("https://app.com/login"));
|
|
|
|
let result = email_service.send_templated_email(
|
|
"user@example.com",
|
|
"Welcome to Our Service",
|
|
"welcome",
|
|
template_data
|
|
).await?;
|
|
```
|
|
|
|
### Form Handling
|
|
|
|
```rust
|
|
// Contact form
|
|
let result = email_service.send_contact_form(
|
|
"John Doe",
|
|
"john@example.com",
|
|
"Question",
|
|
"Message content",
|
|
"admin@app.com"
|
|
).await?;
|
|
|
|
// Support form
|
|
let result = email_service.send_support_form(
|
|
"Jane Smith",
|
|
"jane@example.com",
|
|
"Bug report",
|
|
"Description of the bug",
|
|
Some("high"), // priority
|
|
Some("technical"), // category
|
|
"support@app.com"
|
|
).await?;
|
|
```
|
|
|
|
### Custom Email Messages
|
|
|
|
```rust
|
|
use crate::email::EmailMessage;
|
|
|
|
let message = EmailMessage::new("user@example.com", "Custom Subject")
|
|
.from("custom@app.com")
|
|
.from_name("Custom Sender")
|
|
.html_body("<h1>HTML Content</h1>")
|
|
.text_body("Text content")
|
|
.cc("manager@app.com")
|
|
.reply_to("reply@app.com");
|
|
|
|
let result = email_service.send_email(&message).await?;
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
### Common Variables
|
|
|
|
```bash
|
|
# SMTP Configuration
|
|
SMTP_HOST=smtp.gmail.com
|
|
SMTP_PORT=587
|
|
SMTP_USERNAME=your-email@gmail.com
|
|
SMTP_PASSWORD=your-app-password
|
|
|
|
# SendGrid Configuration
|
|
SENDGRID_API_KEY=your-sendgrid-api-key
|
|
|
|
# General Email Settings
|
|
EMAIL_FROM_ADDRESS=noreply@yourapp.com
|
|
EMAIL_FROM_NAME="Your App Name"
|
|
EMAIL_ENABLED=true
|
|
```
|
|
|
|
### Using in Configuration
|
|
|
|
```toml
|
|
[email]
|
|
smtp_username = "${SMTP_USERNAME}"
|
|
smtp_password = "${SMTP_PASSWORD}"
|
|
sendgrid_api_key = "${SENDGRID_API_KEY}"
|
|
from_email = "${EMAIL_FROM_ADDRESS}"
|
|
```
|
|
|
|
## Security Considerations
|
|
|
|
### 1. Credential Management
|
|
|
|
**❌ Never do:**
|
|
```toml
|
|
# Don't commit real credentials
|
|
smtp_password = "real-password-123"
|
|
sendgrid_api_key = "SG.real-api-key"
|
|
```
|
|
|
|
**✅ Do instead:**
|
|
```toml
|
|
# Use environment variables
|
|
smtp_password = "${SMTP_PASSWORD}"
|
|
sendgrid_api_key = "${SENDGRID_API_KEY}"
|
|
```
|
|
|
|
### 2. Input Validation
|
|
|
|
All email inputs are validated:
|
|
- Email format validation
|
|
- Length limits (name: 100, subject: 200, message: 5000)
|
|
- Required field checking
|
|
- HTML sanitization
|
|
|
|
### 3. Rate Limiting
|
|
|
|
- Built-in rate limiting per IP address
|
|
- Configurable limits
|
|
- Automatic blocking of suspicious activity
|
|
|
|
### 4. CSRF Protection
|
|
|
|
- CSRF tokens on all forms
|
|
- Secure cookie settings
|
|
- SameSite cookie protection
|
|
|
|
### 5. Email Provider Security
|
|
|
|
**Gmail:**
|
|
- Use App Passwords, not regular passwords
|
|
- Enable 2-Factor Authentication
|
|
- Monitor for suspicious activity
|
|
|
|
**SendGrid:**
|
|
- Rotate API keys regularly
|
|
- Use least-privilege API keys
|
|
- Monitor sending quotas
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
**1. Gmail Authentication Failed**
|
|
```
|
|
Error: SMTP authentication failed
|
|
```
|
|
|
|
**Solution:**
|
|
- Enable 2-Factor Authentication
|
|
- Generate an App Password
|
|
- Use App Password instead of regular password
|
|
|
|
**2. SendGrid 401 Unauthorized**
|
|
```
|
|
Error: SendGrid API error: 401
|
|
```
|
|
|
|
**Solution:**
|
|
- Check API key is correct
|
|
- Verify API key has send permissions
|
|
- Ensure sender is verified
|
|
|
|
**3. Template Not Found**
|
|
```
|
|
Error: Template not found: welcome_html
|
|
```
|
|
|
|
**Solution:**
|
|
- Check template exists in correct directory
|
|
- Verify template naming convention
|
|
- Check template_dir configuration
|
|
|
|
**4. Port Connection Refused**
|
|
```
|
|
Error: Connection refused (port 587)
|
|
```
|
|
|
|
**Solution:**
|
|
- Check firewall settings
|
|
- Try different ports (465, 25)
|
|
- Verify SMTP server settings
|
|
|
|
### Debug Mode
|
|
|
|
Enable debug logging to troubleshoot issues:
|
|
|
|
```toml
|
|
[logging]
|
|
level = "debug"
|
|
|
|
[email]
|
|
enabled = true
|
|
# Debug output will show detailed email information
|
|
```
|
|
|
|
### Testing Email Delivery
|
|
|
|
**1. Use Console Provider:**
|
|
```toml
|
|
[email]
|
|
provider = "console"
|
|
```
|
|
|
|
**2. Use Test SMTP Service:**
|
|
- [Mailtrap](https://mailtrap.io) - Testing SMTP
|
|
- [MailHog](https://github.com/mailhog/MailHog) - Local testing
|
|
- [Ethereal Email](https://ethereal.email) - Temporary testing
|
|
|
|
**3. Check Email Status Endpoint:**
|
|
```bash
|
|
curl http://localhost:3030/api/email/status
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Complete Contact Page
|
|
|
|
```rust
|
|
use leptos::prelude::*;
|
|
use crate::components::ContactForm;
|
|
|
|
#[component]
|
|
pub fn ContactPage() -> impl IntoView {
|
|
view! {
|
|
<div class="max-w-2xl mx-auto py-12 px-4">
|
|
<div class="text-center mb-8">
|
|
<h1 class="text-3xl font-bold text-gray-900 mb-4">
|
|
"Contact Us"
|
|
</h1>
|
|
<p class="text-lg text-gray-600">
|
|
"We'd love to hear from you. Send us a message and we'll respond as soon as possible."
|
|
</p>
|
|
</div>
|
|
|
|
<ContactForm
|
|
title="Send us a message"
|
|
recipient="contact@yourapp.com"
|
|
class="bg-white shadow-lg rounded-lg p-6"
|
|
/>
|
|
</div>
|
|
}
|
|
}
|
|
```
|
|
|
|
### Custom Email Service Integration
|
|
|
|
```rust
|
|
use crate::email::{EmailService, EmailServiceBuilder, SmtpConfig};
|
|
|
|
pub async fn setup_email_service() -> Result<EmailService, Box<dyn std::error::Error>> {
|
|
let smtp_config = SmtpConfig {
|
|
host: "smtp.gmail.com".to_string(),
|
|
port: 587,
|
|
username: std::env::var("SMTP_USERNAME")?,
|
|
password: std::env::var("SMTP_PASSWORD")?,
|
|
use_tls: false,
|
|
use_starttls: true,
|
|
};
|
|
|
|
let service = EmailServiceBuilder::new()
|
|
.smtp_provider(smtp_config)
|
|
.default_from("noreply@yourapp.com")
|
|
.default_from_name("Your App")
|
|
.template_dir("./templates/email")
|
|
.enabled(true)
|
|
.build()
|
|
.await?;
|
|
|
|
Ok(service)
|
|
}
|
|
|
|
// Usage in your application
|
|
pub async fn send_welcome_email(
|
|
email_service: &EmailService,
|
|
user_email: &str,
|
|
user_name: &str,
|
|
) -> Result<(), Box<dyn std::error::Error>> {
|
|
let mut template_data = HashMap::new();
|
|
template_data.insert("user_name".to_string(), json!(user_name));
|
|
template_data.insert("app_name".to_string(), json!("Your App"));
|
|
template_data.insert("support_email".to_string(), json!("support@yourapp.com"));
|
|
|
|
email_service.send_templated_email(
|
|
user_email,
|
|
"Welcome to Your App!",
|
|
"welcome",
|
|
template_data
|
|
).await?;
|
|
|
|
Ok(())
|
|
}
|
|
```
|
|
|
|
### Advanced Form with Custom Fields
|
|
|
|
```rust
|
|
#[component]
|
|
pub fn CustomSupportForm() -> impl IntoView {
|
|
let custom_categories = vec![
|
|
CategoryOption {
|
|
value: "bug".to_string(),
|
|
label: "Bug Report".to_string(),
|
|
icon: "🐛".to_string(),
|
|
description: "Something isn't working correctly".to_string(),
|
|
},
|
|
CategoryOption {
|
|
value: "feature".to_string(),
|
|
label: "Feature Request".to_string(),
|
|
icon: "✨".to_string(),
|
|
description: "Suggest a new feature or improvement".to_string(),
|
|
},
|
|
CategoryOption {
|
|
value: "billing".to_string(),
|
|
label: "Billing Question".to_string(),
|
|
icon: "💳".to_string(),
|
|
description: "Questions about your account or billing".to_string(),
|
|
},
|
|
];
|
|
|
|
view! {
|
|
<SupportForm
|
|
title="Support Request"
|
|
description="Tell us how we can help you"
|
|
recipient="support@yourapp.com"
|
|
categories=custom_categories
|
|
show_priority=true
|
|
show_category=true
|
|
submit_text="Submit Support Request"
|
|
class="max-w-lg mx-auto"
|
|
/>
|
|
}
|
|
}
|
|
```
|
|
|
|
This email system provides a robust, secure, and user-friendly solution for all your application's email needs. From simple notifications to complex form handling, it scales with your application's requirements while maintaining security and reliability.
|