Skip to content

Commit be1e476

Browse files
committed
feat: implement React Email and Mailgun support
- Add React Email for modern email templates - Integrate Mailgun for reliable email delivery - Create type-safe email templates - Add comprehensive error handling - Update configuration and documentation - Maintain backward compatibility This commit implements the React Email and Mailgun support feature from the roadmap, replacing the previous Nodemailer implementation while maintaining backward compatibility.
1 parent aa2c87e commit be1e476

16 files changed

+5638
-3941
lines changed

.env.development

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# APP CONFIG
2+
PORT="3000"
3+
4+
# FOR CORS AND EMAILS
5+
CLIENT_SIDE_URL="http://localhost:3000"
6+
7+
# JWT
8+
JWT_SECRET="some-secret"
9+
JWT_EXPIRES_IN="1h"
10+
11+
# SESSION
12+
SESSION_EXPIRES_IN="1d"
13+
14+
# AUTH
15+
PASSWORD_RESET_TOKEN_EXPIRES_IN="1d"
16+
SET_PASSWORD_TOKEN_EXPIRES_IN="1d"
17+
SET_SESSION=0
18+
19+
# DATABSES
20+
REDIS_URL="redis://localhost:6380"
21+
MONGO_DATABASE_URL="mongodb://localhost:27018/typescript-backend-toolkit"

.env.production

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# APP CONFIG
2+
PORT="3000"
3+
4+
# FOR CORS AND EMAILS
5+
CLIENT_SIDE_URL="http://localhost:3000"
6+
7+
# JWT
8+
JWT_SECRET="some-secret"
9+
JWT_EXPIRES_IN="1h"
10+
11+
# SESSION
12+
SESSION_EXPIRES_IN="1d"
13+
14+
# AUTH
15+
PASSWORD_RESET_TOKEN_EXPIRES_IN="1d"
16+
SET_PASSWORD_TOKEN_EXPIRES_IN="1d"
17+
SET_SESSION=0
18+
19+
# DATABSES
20+
REDIS_URL="redis://localhost:6380"
21+
MONGO_DATABASE_URL="mongodb://localhost:27018/typescript-backend-toolkit"

.env.sample

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,20 @@
22
PORT=""
33
NODE_ENV=""
44

5-
# SMTP
5+
# EMAIL (Choose either SMTP or Mailgun configuration)
6+
# SMTP Configuration (Legacy)
67
SMTP_HOST=""
78
SMTP_PORT=""
89
SMTP_USERNAME=""
910
EMAIL_FROM=""
1011
SMTP_FROM=""
1112
SMTP_PASSWORD=""
1213

14+
# Mailgun Configuration (Recommended)
15+
MAILGUN_API_KEY=""
16+
MAILGUN_DOMAIN=""
17+
MAILGUN_FROM_EMAIL=""
18+
1319
# FOR CORS AND EMAILS
1420
CLIENT_SIDE_URL=""
1521

@@ -32,4 +38,4 @@ GOOGLE_REDIRECT_URI = ''
3238

3339
# DATABSES
3440
REDIS_URL=""
35-
MONGO_DATABASE_URL=""
41+
MONGO_DATABASE_URL=""

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,3 +131,4 @@ dist
131131

132132
# database
133133
.database
134+
.aider*

docker-compose.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,5 @@ services:
3232

3333
volumes:
3434
mongodb_typescript_backend_toolkit:
35-
external: true
3635
redis_typescript_backend_toolkit:
37-
external: true
3836
postgres_typescript_backend_toolkit:
39-
external: true

docs/EMAIL.md

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Email Service Documentation
2+
3+
This document outlines the email service implementation using React Email for templating and Mailgun for delivery.
4+
5+
## Overview
6+
7+
The email service provides a robust, type-safe way to send transactional emails using:
8+
- [React Email](https://react.email/) for building and maintaining email templates
9+
- [Mailgun](https://www.mailgun.com/) for reliable email delivery
10+
- TypeScript for type safety and better developer experience
11+
12+
## Configuration
13+
14+
### Environment Variables
15+
16+
Add the following variables to your `.env` file:
17+
18+
```env
19+
MAILGUN_API_KEY="your-mailgun-api-key"
20+
MAILGUN_DOMAIN="your-mailgun-domain"
21+
MAILGUN_FROM_EMAIL="[email protected]"
22+
```
23+
24+
## Email Templates
25+
26+
Email templates are built using React Email components and are located in `src/email/templates/`. Each template is a React component that accepts typed props for the dynamic content.
27+
28+
### Available Templates
29+
30+
1. **Reset Password Email** (`ResetPassword.tsx`)
31+
```typescript
32+
interface ResetPasswordEmailProps {
33+
userName: string;
34+
resetLink: string;
35+
}
36+
```
37+
38+
## Usage
39+
40+
### Sending Reset Password Email
41+
42+
```typescript
43+
import { sendResetPasswordEmail } from '../email/email.service';
44+
45+
await sendResetPasswordEmail({
46+
47+
userName: 'John Doe',
48+
resetLink: 'https://yourdomain.com/reset-password?token=xyz'
49+
});
50+
```
51+
52+
### Creating New Email Templates
53+
54+
1. Create a new template in `src/email/templates/`
55+
2. Use React Email components for consistent styling
56+
3. Export the template component with proper TypeScript interfaces
57+
4. Add a new method in `EmailService` class to send the email
58+
59+
Example:
60+
```typescript
61+
// src/email/templates/WelcomeEmail.tsx
62+
import * as React from 'react';
63+
import { Button, Container, Head, Html, Preview, Text } from '@react-email/components';
64+
65+
interface WelcomeEmailProps {
66+
userName: string;
67+
}
68+
69+
export const WelcomeEmail = ({ userName }: WelcomeEmailProps) => (
70+
<Html>
71+
<Head />
72+
<Preview>Welcome to our platform</Preview>
73+
<Container>
74+
<Text>Welcome {userName}!</Text>
75+
<Button href="https://yourdomain.com/getting-started">
76+
Get Started
77+
</Button>
78+
</Container>
79+
</Html>
80+
);
81+
82+
export default WelcomeEmail;
83+
```
84+
85+
## Error Handling
86+
87+
The email service includes comprehensive error handling:
88+
89+
- Custom `EmailError` class for email-specific errors
90+
- Detailed error logging using the application logger
91+
- Type-safe error propagation
92+
93+
## Benefits
94+
95+
1. **Type Safety**: Full TypeScript support for templates and service methods
96+
2. **Maintainable Templates**: React components for building and maintaining email templates
97+
3. **Reliable Delivery**: Mailgun integration for professional email delivery
98+
4. **Error Handling**: Comprehensive error handling and logging
99+
5. **Developer Experience**: Easy to create and modify email templates using React
100+
101+
## Migration from Nodemailer
102+
103+
The service maintains backward compatibility with the previous Nodemailer implementation through exported functions. The internal implementation has been updated to use React Email and Mailgun while keeping the same interface.
104+
105+
## Testing Emails
106+
107+
To test emails in development:
108+
109+
1. Set up a Mailgun sandbox domain (free)
110+
2. Use the sandbox domain and API key in your `.env.development`
111+
3. Add verified recipient emails in Mailgun sandbox settings
112+
4. Use these verified emails for testing
113+
114+
## Best Practices
115+
116+
1. Always use TypeScript interfaces for template props
117+
2. Include proper error handling in your email sending logic
118+
3. Use React Email components for consistent styling
119+
4. Test emails with different email clients
120+
5. Keep templates simple and mobile-responsive

package.json

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
"description": "",
55
"main": "dist/main.js",
66
"scripts": {
7-
"dev": "dotenv -e .env -- ts-node-dev --transpile-only ./src/main.ts",
8-
"seeder": "ts-node --transpile-only ./src/seeder.ts",
7+
"dev": "dotenv -e .env.development -- tsx ./src/main.ts",
8+
"seeder": "tsx ./src/seeder.ts",
99
"build": "tsup --config build.ts",
10-
"start:prod": "dotenv -e .env -- node ./dist/main.js",
11-
"start:local": "dotenv -e .env -- node ./dist/main.js",
10+
"start:prod": "dotenv -e .env.production -- node ./dist/main.js",
11+
"start:local": "dotenv -e .env.local -- node ./dist/main.js",
1212
"lint": "eslint",
1313
"lint:fix": "eslint --fix",
1414
"migrate:dev": "pnpm dlx prisma migrate dev",
@@ -44,9 +44,8 @@
4444
"globals": "^15.3.0",
4545
"prisma": "^5.18.0",
4646
"rimraf": "^5.0.1",
47-
"ts-node": "^10.9.1",
48-
"ts-node-dev": "^2.0.0",
4947
"tsup": "^8.1.0",
48+
"tsx": "^4.19.2",
5049
"typescript": "*",
5150
"typescript-eslint": "^7.11.0"
5251
},
@@ -56,7 +55,10 @@
5655
"@bull-board/api": "^5.19.0",
5756
"@bull-board/express": "^5.16.0",
5857
"@prisma/client": "^5.13.0",
58+
"@react-email/components": "^0.0.28",
59+
"@react-email/render": "^1.0.2",
5960
"@types/compression": "^1.7.2",
61+
"@types/react": "^18.3.12",
6062
"argon2": "^0.30.3",
6163
"axios": "^1.4.0",
6264
"batch": "^0.6.1",
@@ -74,12 +76,14 @@
7476
"express-async-handler": "^1.2.0",
7577
"express-session": "^1.18.0",
7678
"firebase-admin": "^12.3.0",
79+
"form-data": "^4.0.1",
7780
"geolib": "^3.3.4",
7881
"helmet": "^6.0.1",
7982
"http-status-codes": "^2.3.0",
8083
"ioredis": "^5.3.2",
8184
"jsonwebtoken": "^9.0.2",
8285
"lodash": "^4.17.21",
86+
"mailgun.js": "^10.2.4",
8387
"mongoose": "^8.5.1",
8488
"morgan": "^1.10.0",
8589
"multer": "^1.4.5-lts.1",
@@ -92,6 +96,7 @@
9296
"pino": "^9.1.0",
9397
"pino-http": "^10.1.0",
9498
"pino-pretty": "^11.1.0",
99+
"react": "^18.3.1",
95100
"redis": "^4.6.11",
96101
"socket.io": "^4.7.5",
97102
"swagger-ui-express": "^5.0.1",
@@ -100,5 +105,6 @@
100105
"zod": "^3.21.4"
101106
},
102107
"author": "",
103-
"license": "ISC"
108+
"license": "ISC",
109+
"packageManager": "[email protected]+sha512.60c18acd138bff695d339be6ad13f7e936eea6745660d4cc4a776d5247c540d0edee1a563695c183a66eb917ef88f2b4feb1fc25f32a7adcadc7aaf3438e99c1"
104110
}

0 commit comments

Comments
 (0)