361 lines
10 KiB
Markdown
361 lines
10 KiB
Markdown
# Email Template Service
|
|
|
|
**Production-ready email template service with beautiful React templates and secure backend API.**
|
|
|
|
[](https://www.typescriptlang.org/)
|
|
[](https://reactjs.org/)
|
|
[](https://expressjs.com/)
|
|
[](https://www.docker.com/)
|
|
|
|
## ✨ Features
|
|
|
|
### 📧 Email Templates
|
|
- **Event Invitations** - Event invitations with RSVP functionality
|
|
- **Team Invitations** - Team member invitations with branded styling and acceptance links
|
|
- **Payment Requests** - Basic payment requests with payment buttons or bank transfer details
|
|
- **Enhanced Payment Requests** - Detailed payment requests with itemized line items and automatic status updates
|
|
- **Invoice Sharing** - Secure invoice sharing with expiration and access limits
|
|
- **Password Reset** - Secure password recovery emails
|
|
- **Invoices** - Professional proforma invoices
|
|
- **Tax Reports** - VAT and withholding tax reports
|
|
- **Newsletters** - Marketing and announcement emails
|
|
|
|
### 🛡️ Production Ready
|
|
- **Security**: Input validation, rate limiting, CORS protection
|
|
- **Monitoring**: Health checks, structured logging, error tracking
|
|
- **Performance**: Optimized templates, request caching
|
|
- **Reliability**: Comprehensive error handling, graceful shutdown
|
|
|
|
### 🎨 Developer Experience
|
|
- **Visual Designer**: React-based template editor
|
|
- **Type Safety**: Full TypeScript coverage
|
|
- **Hot Reload**: Development server with instant updates
|
|
- **Docker Support**: One-command deployment
|
|
|
|
## 🚀 Quick Start
|
|
|
|
### 1. Installation
|
|
```bash
|
|
git clone <repository>
|
|
cd email-template-service
|
|
npm install
|
|
```
|
|
|
|
### 2. Environment Setup
|
|
```bash
|
|
cp .env.example .env
|
|
# Edit .env with your Resend API key and domain
|
|
```
|
|
|
|
### 3. Development
|
|
```bash
|
|
# Start template designer (frontend)
|
|
npm run dev
|
|
|
|
# Start API server (backend) - separate terminal
|
|
npm run server:dev
|
|
```
|
|
|
|
### 4. Production
|
|
```bash
|
|
# Docker (recommended)
|
|
docker-compose up -d
|
|
|
|
# Or Node.js
|
|
npm run build && npm start
|
|
```
|
|
|
|
## 📡 API Usage (For Yaltopia Backend)
|
|
|
|
### Send Invitation Email
|
|
```javascript
|
|
// From your Yaltopia backend when user registers for event
|
|
const invitationData = {
|
|
to: user.email,
|
|
eventName: event.name,
|
|
dateTime: "March 25, 2026 at 2:00 PM",
|
|
location: event.location,
|
|
ctaUrl: `https://yaltopia.com/events/${event.id}/rsvp`,
|
|
company: {
|
|
name: "Yaltopia Ticket",
|
|
logoUrl: "https://yaltopia.com/logo.png"
|
|
}
|
|
}
|
|
|
|
const response = await fetch('http://email-service:3001/api/emails/invitation', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(invitationData)
|
|
})
|
|
```
|
|
|
|
### Send Team Invitation
|
|
```javascript
|
|
// From your Yaltopia backend when inviting team members
|
|
const teamInvitationData = {
|
|
to: user.email,
|
|
recipientName: user.name,
|
|
inviterName: inviter.name,
|
|
teamName: team.name,
|
|
invitationLink: `https://yaltopia.com/teams/join?token=${invitationToken}`,
|
|
customMessage: "Join our team and let's build something amazing!",
|
|
company: {
|
|
name: "Yaltopia Ticket",
|
|
logoUrl: "https://yaltopia.com/logo.png",
|
|
primaryColor: "#10b981"
|
|
}
|
|
}
|
|
|
|
const response = await fetch('http://email-service:3001/api/emails/team-invitation', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(teamInvitationData)
|
|
})
|
|
```
|
|
|
|
### Send Enhanced Payment Request
|
|
```javascript
|
|
// From your Yaltopia backend for detailed payment requests
|
|
const enhancedPaymentData = {
|
|
to: customer.email,
|
|
recipientName: customer.name,
|
|
paymentRequestNumber: "PR-2026-001",
|
|
amount: 2500.00,
|
|
currency: "USD",
|
|
description: "Monthly subscription and services",
|
|
dueDate: "March 31, 2026",
|
|
lineItems: [
|
|
{
|
|
description: "Yaltopia Pro Subscription",
|
|
quantity: 1,
|
|
unitPrice: 199.00,
|
|
total: 199.00
|
|
},
|
|
{
|
|
description: "Setup and Configuration",
|
|
quantity: 5,
|
|
unitPrice: 150.00,
|
|
total: 750.00
|
|
}
|
|
],
|
|
notes: "Payment is due within 30 days.",
|
|
company: {
|
|
name: "Yaltopia Ticket",
|
|
bankDetails: {
|
|
bankName: "Your Bank",
|
|
accountName: "Yaltopia Ticket Ltd",
|
|
accountNumber: "123456789",
|
|
referenceNote: "Payment for PR-2026-001"
|
|
}
|
|
}
|
|
}
|
|
|
|
const response = await fetch('http://email-service:3001/api/emails/enhanced-payment-request', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(enhancedPaymentData)
|
|
})
|
|
```
|
|
|
|
### Send Invoice Share
|
|
```javascript
|
|
// From your Yaltopia backend for invoice sharing
|
|
const invoiceShareData = {
|
|
to: recipient.email,
|
|
recipientName: recipient.name,
|
|
senderName: sender.name,
|
|
invoiceNumber: invoice.number,
|
|
customerName: invoice.customer.name,
|
|
amount: invoice.totalAmount,
|
|
currency: "USD",
|
|
status: "SENT", // 'DRAFT', 'SENT', 'PAID', 'OVERDUE', 'CANCELLED'
|
|
shareLink: `https://yaltopia.com/invoices/shared/${shareToken}`,
|
|
expirationDate: "March 31, 2026",
|
|
accessLimit: 5,
|
|
customMessage: "Please review this invoice.",
|
|
company: {
|
|
name: "Yaltopia Ticket",
|
|
logoUrl: "https://yaltopia.com/logo.png"
|
|
}
|
|
}
|
|
|
|
const response = await fetch('http://email-service:3001/api/emails/invoice-share', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(invoiceShareData)
|
|
})
|
|
```
|
|
|
|
### Send Password Reset
|
|
```javascript
|
|
// From your Yaltopia backend for password reset
|
|
const resetData = {
|
|
to: user.email,
|
|
resetLink: `https://yaltopia.com/reset-password?token=${resetToken}`,
|
|
recipientName: user.firstName,
|
|
company: {
|
|
name: "Yaltopia Ticket"
|
|
}
|
|
}
|
|
|
|
const response = await fetch('http://email-service:3001/api/emails/password-reset', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify(resetData)
|
|
})
|
|
```
|
|
|
|
## 🏗️ Architecture
|
|
|
|
```
|
|
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
│ Yaltopia │ │ Email Service │ │ Resend │
|
|
│ Backend │───▶│ (Express.js) │───▶│ Email API │
|
|
│ (with data) │ │ + Templates │ │ │
|
|
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
│ │ │
|
|
▼ ▼ ▼
|
|
Has Event Data Renders Templates Email Delivery
|
|
```
|
|
|
|
**Simple & Efficient**: Yaltopia backend calls this service with data, service renders beautiful templates and sends emails via Resend.
|
|
|
|
## 📁 Project Structure
|
|
|
|
```
|
|
├── src/
|
|
│ ├── components/ # React UI components
|
|
│ ├── templates/ # Email template components
|
|
│ ├── lib/ # Utilities and services
|
|
│ │ ├── config.ts # Environment configuration
|
|
│ │ ├── logger.ts # Structured logging
|
|
│ │ ├── validation.ts # Input validation schemas
|
|
│ │ └── resendService.ts # Email service
|
|
│ └── ...
|
|
├── docs/ # Documentation
|
|
├── server.ts # Production API server
|
|
├── docker-compose.yml # Docker configuration
|
|
└── .env.example # Environment template
|
|
```
|
|
|
|
## 🔧 Configuration
|
|
|
|
### Required Environment Variables
|
|
```env
|
|
RESEND_API_KEY=re_your_api_key_here
|
|
FROM_DOMAIN=yaltopia.com
|
|
```
|
|
|
|
### Optional Configuration
|
|
```env
|
|
FROM_EMAIL=noreply@yaltopia.com
|
|
NODE_ENV=production
|
|
PORT=3001
|
|
RATE_LIMIT_MAX=20
|
|
RATE_LIMIT_WINDOW_MS=900000
|
|
CORS_ORIGIN=https://yaltopia.com
|
|
LOG_LEVEL=info
|
|
```
|
|
|
|
## 🛡️ Security Features
|
|
|
|
- **Input Validation**: Zod schemas for all API inputs
|
|
- **Rate Limiting**: Configurable email sending limits (default: 10/15min)
|
|
- **Security Headers**: Helmet.js with CSP, HSTS, XSS protection
|
|
- **CORS Protection**: Configurable origin restrictions
|
|
- **Privacy Protection**: Email/IP masking in logs
|
|
- **Error Handling**: No sensitive data in error responses
|
|
|
|
## 📊 Monitoring
|
|
|
|
### Health Check
|
|
```bash
|
|
curl http://localhost:3001/health
|
|
# Returns: {"status": "healthy", "timestamp": "..."}
|
|
```
|
|
|
|
### Structured Logging
|
|
```json
|
|
{
|
|
"level": "info",
|
|
"message": "Email sent successfully",
|
|
"timestamp": "2026-03-12T10:00:00.000Z",
|
|
"meta": {
|
|
"templateId": "invitation",
|
|
"to": "u***@example.com",
|
|
"messageId": "abc123"
|
|
}
|
|
}
|
|
```
|
|
|
|
## 📚 Documentation
|
|
|
|
- **[API Reference](docs/API.md)** - Complete API documentation with examples
|
|
- **[Deployment Guide](docs/DEPLOYMENT.md)** - Production deployment instructions
|
|
- **[Security Guide](docs/SECURITY.md)** - Security features and best practices
|
|
|
|
## 🚀 Deployment Options
|
|
|
|
### Docker (Recommended)
|
|
```bash
|
|
docker-compose up -d
|
|
```
|
|
|
|
### Cloud Platforms
|
|
- **Vercel**: `vercel --prod`
|
|
- **Railway**: `railway up`
|
|
- **Heroku**: `git push heroku main`
|
|
- **AWS/GCP**: Standard Node.js deployment
|
|
|
|
### Manual Node.js
|
|
```bash
|
|
npm run build
|
|
npm start
|
|
```
|
|
|
|
## 🧪 Development Scripts
|
|
|
|
```bash
|
|
npm run dev # Start frontend development
|
|
npm run server:dev # Start backend with hot reload
|
|
npm run build # Build for production
|
|
npm run type-check # Validate TypeScript
|
|
npm run lint # Run ESLint
|
|
npm run validate # Full validation (lint + build)
|
|
npm start # Start production server
|
|
```
|
|
|
|
## 🔍 Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
**"Domain not verified"**
|
|
- Verify your domain in [Resend dashboard](https://resend.com/domains)
|
|
- Add SPF record: `v=spf1 include:_spf.resend.com ~all`
|
|
|
|
**"Rate limit exceeded"**
|
|
- Check current limits: `curl http://localhost:3001/api`
|
|
- Adjust `RATE_LIMIT_MAX` in environment variables
|
|
|
|
**"Email not delivered"**
|
|
- Check Resend logs in dashboard
|
|
- Verify recipient email address
|
|
- Check spam folder
|
|
|
|
## 🤝 Contributing
|
|
|
|
1. Fork the repository
|
|
2. Create a feature branch
|
|
3. Make your changes
|
|
4. Run tests: `npm run validate`
|
|
5. Submit a pull request
|
|
|
|
## 📄 License
|
|
|
|
Private - Internal use only
|
|
|
|
---
|
|
|
|
**Ready for production with enterprise-grade security and reliability!** 🚀
|
|
|
|
For detailed documentation, see the [docs](docs/) folder. |