Email System Documentation
Email System Documentation
Note: This documentation has been moved to a more comprehensive location.
Please see the new documentation at /docs/email/resend/
Quick Links
- Overview & Quick Start
- Email Templates
- useSendEmail Hook
- API Reference
- Configuration
- Protections (Rate Limiting, etc.)
Environment Variables (Quick Reference)
Add these to your .env file:
# Resend API Configuration
RESEND_API_KEY=re_xxxxxxxxxx
RESEND_FROM_EMAIL=noreply@suitsbooks.com
RESEND_FROM_NAME=SuitsBooks
RESEND_REPLY_TO=support@suitsbooks.com
# Optional: Enable test mode (logs instead of sending)
EMAIL_TEST_MODE=false
```typescript
## Usage
### Basic Email Sending
```tsx
import { useSendEmail } from "@/hooks/use-send-email";
function MyComponent() {
const { sendEmail, isLoading, isError, error } = useSendEmail();
const handleSendEmail = async () => {
const result = await sendEmail({
to: "recipient@example.com",
subject: "Hello from SuitsBooks",
template_id: "welcome",
template_data: {
USER_NAME: "John Doe",
LOGIN_URL: "https://app.suitsbooks.com/login",
SUPPORT_EMAIL: "support@suitsbooks.com",
},
});
if (result.success) {
console.log("Email sent:", result.email_id);
}
};
return (
<button onClick={handleSendEmail} disabled={isLoading}>
Send Email
</button>
);
}
```typescript
### With Notifications
```tsx
import { useSendEmailWithNotification } from "@/hooks/use-send-email-with-notification";
function MyComponent() {
const { sendEmail, isLoading } = useSendEmailWithNotification({
showSuccessNotification: true,
showErrorNotification: true,
messages: {
sendSuccess: "Invoice sent successfully!",
sendError: "Failed to send invoice",
},
});
// ... same usage as above
}
```typescript
### Custom Configuration
```tsx
const { sendEmail } = useSendEmail({
// Rate limiting
enableRateLimiting: true,
maxEmailsPerMinute: 5,
maxEmailsPerHour: 50,
maxEmailsPerDay: 200,
// Duplicate detection
enableDuplicateDetection: true,
duplicateWindowSeconds: 120, // 2 minutes
// Domain restrictions
blockedRecipientDomains: ["tempmail.com", "mailinator.com"],
allowedRecipientDomains: [], // Empty = all allowed
// Bulk settings
requireBulkConfirmation: true,
bulkThreshold: 10,
// Callbacks
onSuccess: (response) => console.log("Sent:", response),
onError: (error) => console.error("Error:", error),
onRateLimited: () => console.warn("Rate limited!"),
});
```typescript
### Bulk Email Sending
```tsx
const { sendBulkEmails } = useSendEmail();
const emails = [
{
id: "email-1",
to: "user1@example.com",
subject: "Invoice #001",
template_id: "invoice",
template_data: { INVOICE_NUMBER: "001", AMOUNT: "€100" },
},
{
id: "email-2",
to: "user2@example.com",
subject: "Invoice #002",
template_id: "invoice",
template_data: { INVOICE_NUMBER: "002", AMOUNT: "€200" },
},
];
const result = await sendBulkEmails(emails, {
skipConfirmation: true, // Skip confirmation for bulk > 10
batchDelay: 1000, // 1 second between batches
});
console.log(`Sent: ${result.sent}/${result.total}`);
```typescript
### Check Rate Limit Status
```tsx
const { getRateLimitStatus, canSendEmail } = useSendEmail();
// Check if we can send
const { canSend, reason } = canSendEmail("user@example.com", "Test Subject");
if (!canSend) {
console.log("Cannot send:", reason);
}
// Get detailed status
const status = getRateLimitStatus();
console.log(`Remaining today: ${status.remainingDay}`);
```typescript
## Available Templates
| Template ID | Description | Required Variables |
|------------|-------------|-------------------|
| `invoice` | Invoice notification | AUTHOR_NAME, AMOUNT_TOTAL, DUE_DATE, RECIPIENT_NAME, INVOICE_URL, INVOICE_NUMBER |
| `company-invite` | Team invitation | TEAM_NAME, ORGANIZATION_NAME, RECIPIENT_NAME, SENDER_NAME, SENDER_EMAIL, INVITE_LINK |
| `quote-recipient` | Quote for customer | Similar to invoice |
| `quote-author` | Quote viewed notification | - |
| `batch-invoice` | Multiple invoices | - |
| `password-reset` | Password reset | USER_NAME, RESET_URL, EXPIRY_TIME, REQUEST_IP, REQUEST_LOCATION |
| `welcome` | New user welcome | USER_NAME, LOGIN_URL, SUPPORT_EMAIL |
| `verification` | Email verification | USER_NAME, VERIFICATION_URL, VERIFICATION_CODE, EXPIRY_TIME |
| `payment-received` | Payment confirmation | RECIPIENT_NAME, AUTHOR_NAME, AMOUNT_PAID, PAYMENT_DATE, PAYMENT_METHOD, RECEIPT_URL |
| `payment-reminder` | Payment reminder | RECIPIENT_NAME, AUTHOR_NAME, INVOICE_NUMBER, AMOUNT_DUE, DUE_DATE, DAYS_OVERDUE, INVOICE_URL |
| `custom` | Custom HTML | html_body required |
## API Endpoints
### POST /api/email/send
Send a single email.
```json
{
"to": "user@example.com",
"subject": "Hello",
"template_id": "welcome",
"template_data": {
"USER_NAME": "John"
}
}
```typescript
### POST /api/email/bulk
Send multiple emails.
```json
{
"emails": [
{
"id": "1",
"to": "user1@example.com",
"subject": "Hello 1",
"template_id": "welcome",
"template_data": {}
}
],
"batchDelay": 1000
}
```typescript
### GET /api/email/status/[email_id]
Get email status.
### GET /api/email/track?view_key=xxx
Track email opens (returns tracking pixel).
## Database Schema
Emails are stored in the `emails` table with fields including:
- `email_id` - Unique identifier
- `status` - pending, sent, delivered, opened, failed, etc.
- `template_id` - Template used
- `recipient_email` - Recipient address
- `opened` - Whether email was opened
- `delivered` - Whether email was delivered
- `view_key` - Unique key for tracking
- `resource_type_ref` / `resource_id_ref` - Link to other resources (e.g., invoice_id)
## Adding New Templates
1. Create a new file in `emails/templates/`:
```tsx
// emails/templates/my-template.tsx
import { Html, Head, Preview, Body, ... } from "@react-email/components";
export default function MyTemplate() {
return (
<Html>
<Head />
<Preview>Preview text</Preview>
<Body>
Hello {"{{USER_NAME}}"}!
</Body>
</Html>
);
}
```typescript
2. Add to `emails/templates/index.ts`:
```tsx
import MyTemplate from "./my-template";
export const EMAIL_TEMPLATES = {
// ... existing templates
"my-template": MyTemplate,
};
```typescript
3. Add to types in `lib/email/types.ts`:
```tsx
export type EmailTemplateId =
| // ... existing
| "my-template";
```typescript
4. Add config in `lib/email/config.ts`:
```tsx
export const TEMPLATE_CONFIG = {
// ... existing
"my-template": {
defaultSubject: "My Template Subject",
requiresAuth: true,
category: "notification",
},
};
Preview Templates
Run the React Email dev server:
pnpm email
This opens a preview at http://localhost:3040 where you can view and test templates.