A production-ready contact form API built with NestJS. Accepts contact form submissions, validates them against Google reCAPTCHA Enterprise, and sends dual confirmation emails (admin notification + user confirmation) via the Resend email service.
- Contact form endpoint with full input validation and sanitization
- Google reCAPTCHA Enterprise verification with configurable risk score threshold
- Dual email sending — admin notification and user confirmation via Resend
- Rate limiting — 10 requests per 60 seconds per IP
- IP tracking and logging for security monitoring
- PostgreSQL persistence for email audit logs
- Static file serving with custom 404 handling
Handles contact form submissions.
Request body:
{
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"message": "I'm interested in your services.",
"recaptchaToken": "<google-recaptcha-token>"
}Validation rules:
firstName/lastName— required, max 50 charactersemail— required, valid email formatmessage— required, max 500 charactersrecaptchaToken— required for spam protection
Success response:
{
"success": true,
"message": "Your message has been sent successfully. We will get back to you soon!"
}Error responses:
400— Missing reCAPTCHA token or invalid input401— reCAPTCHA verification failed429— Rate limit exceeded (includesRetry-Afterheader)500— Internal server error
Returns all stored email records from the database.
Returns a single email record by ID.
Serves the static home page (public/index.html).
- Node.js 18+
- PostgreSQL database
- Resend account and API key
- Google Cloud project with reCAPTCHA Enterprise enabled
npm installCreate a .env file in the project root:
# Email service
RESEND_API_KEY=your-resend-api-key
ADMIN_EMAIL=admin@yourdomain.com
# CORS allowed origin
DOMAIN=https://yourdomain.com
# Google reCAPTCHA Enterprise
RECAPTCHA_PROJECT_ID=your-gcp-project-id
RECAPTCHA_API_KEY=your-google-cloud-api-key
RECAPTCHA_SITE_KEY=your-recaptcha-site-key
# Server
PORT=3005# Development
npm run start
# Watch mode (auto-reload)
npm run start:dev
# Production
npm run start:prod# Unit tests
npm run test
# End-to-end tests
npm run test:e2e
# Test coverage
npm run test:covsrc/
├── app.module.ts # Root module
├── app.controller.ts # Home page route
├── main.ts # Bootstrap (CORS, validation, static files)
├── mailer/ # Contact form feature
│ ├── mailer.controller.ts # POST /mail/send
│ ├── mailer.service.ts # Email sending via Resend
│ ├── mailer.dto.ts # Input validation schema
│ └── mailer.module.ts
├── recaptcha/ # Google reCAPTCHA Enterprise
│ ├── recaptcha.service.ts # Token verification + risk scoring
│ └── recaptcha.module.ts
├── email/ # Email audit log (PostgreSQL)
│ ├── email.controller.ts
│ ├── email.service.ts
│ ├── email.entity.ts
│ └── email.module.ts
├── common/guards/
│ └── custom-throttler.guard.ts # Rate limiting (10 req / 60s)
└── filters/
└── not-found.filter.ts # Global 404 handler
public/
├── index.html
└── 404.html
- All input is sanitized (HTML stripped) before processing or emailing
- reCAPTCHA Enterprise risk score must meet a minimum threshold (default: 0.5)
- Rate limiting is enforced per IP per route
- CORS is restricted to configured origins
- Validation pipe rejects any extra/unexpected fields (whitelist mode)