Yaltopia-Ticket-Email/README.md

10 KiB

Email Template Service

Production-ready email template service with beautiful React templates and secure backend API.

TypeScript React Express Docker

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

git clone <repository>
cd email-template-service
npm install

2. Environment Setup

cp .env.example .env
# Edit .env with your Resend API key and domain

3. Development

# Start template designer (frontend)
npm run dev

# Start API server (backend) - separate terminal
npm run server:dev

4. Production

# Docker (recommended)
docker-compose up -d

# Or Node.js
npm run build && npm start

📡 API Usage (For Yaltopia Backend)

Send Invitation Email

// 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

// 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

// 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

// 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

// 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

RESEND_API_KEY=re_your_api_key_here
FROM_DOMAIN=yaltopia.com

Optional Configuration

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

curl http://localhost:3001/health
# Returns: {"status": "healthy", "timestamp": "..."}

Structured Logging

{
  "level": "info",
  "message": "Email sent successfully",
  "timestamp": "2026-03-12T10:00:00.000Z",
  "meta": {
    "templateId": "invitation",
    "to": "u***@example.com",
    "messageId": "abc123"
  }
}

📚 Documentation

🚀 Deployment Options

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

npm run build
npm start

🧪 Development Scripts

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
  • 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 folder.