A production-ready, serverless newsletter and contact form management system built on Cloudflare Workers with enterprise-grade security, dual-layer data persistence, and multiple email provider support.
- Newsletter Management: Automated RSS feed monitoring and batch email delivery
- Contact Forms: Integrated contact system with auto-subscribe option
- Subscriber Management: Double opt-in support with secure unsubscribe links
- Multiple Email Providers: Gmail SMTP, MailerLite API, and Cloudflare Email Routing
- Admin Panel Security: Session-only authentication, no external API access
- Bot Protection: Cloudflare Turnstile CAPTCHA integration
- Native Rate Limiting Only:
- Uses Cloudflare's built-in Rate Limiting API exclusively
- No KV operations for rate limiting (prevents hitting free tier limits)
- Multi-layer protection: burst, global, forms, admin, API, bot
- XSS Protection: Comprehensive input sanitization
- No PII Exposure: Customer data never exposed through APIs
- Dual Storage System:
- KV for operational data (fast access, subscriber management)
- D1 database for archival (SQL-based, permanent append-only storage)
- Real-time D1 Replication: Automatic async replication from KV to D1
- Auto-Cleanup: TTL-based expiration for temporary data
- Append-Only Archive: D1 maintains permanent audit trail
- Async Processing: Non-blocking D1 replication using ctx.waitUntil()
- Prefix-Based Queries: Efficient KV operations using prefix filtering
- Batch Processing: Configurable batch sizes for email delivery
- Retry Logic: Exponential backoff with dead letter queue
graph TB
subgraph "Public Endpoints"
HOME[Homepage /]
SUB[Subscribe /subscribe]
UNSUB[Unsubscribe /unsubscribe]
CONTACT[Contact /contact]
end
subgraph "Protected Admin"
ADMIN[Admin Panel /admin]
STATUS[Status /admin/status]
CHECK[Check Now /admin/api/check-now]
end
subgraph "Security Layers"
TURN[Turnstile CAPTCHA]
RATE[Rate Limiting]
SESSION[Session Auth]
end
subgraph "Data Storage"
KV[(Cloudflare KV)]
D1[(D1 Database)]
end
subgraph "Email Providers"
GMAIL[Gmail SMTP]
MAILER[MailerLite]
WORKER[Worker Email]
end
HOME --> TURN
SUB --> TURN --> KV
CONTACT --> TURN --> KV
ADMIN --> SESSION --> KV
KV -.->|Async Replication| D1
KV --> GMAIL
KV --> MAILER
KV --> WORKER
graph LR
subgraph "Real-time Operations"
F1[Form Submission] --> F2[Save to KV]
F2 --> F3[Immediate Response]
F2 -.->|Async| F4[Replicate to D1]
end
subgraph "Data Layers"
KV[KV Storage<br/>Operational Data]
D1[D1 Database<br/>Permanent Archive]
end
subgraph "TTL Cleanup"
T1[Rate Limits] -->|2 min| T2[Auto Expire]
T3[Bot Detection] -->|24 hr| T2
T4[Temp Data] -->|Configurable| T2
end
F4 --> D1
KV --> D1
src/
βββ index.js # Main entry point & route handler
βββ config/
β βββ config.js # Centralized configuration
βββ newsletter/
β βββ frontend/
β β βββ subscribe.js # Subscribe form & handler
β β βββ unsubscribe.js # Unsubscribe form & handler
β βββ backend/
β βββ processor.js # RSS feed processing & email queue
βββ contact/
β βββ frontend.js # Contact form with retry logic
βββ email/
β βββ gmailProvider.js # Gmail SMTP via worker-mailer
β βββ mailerLiteProvider.js # MailerLite API integration
β βββ workerEmailProvider.js # Cloudflare Email routing
β βββ emailFactory.js # Provider factory pattern
βββ middleware/
β βββ protection.js # Rate limiting & bot protection
βββ pages/
β βββ status.js # System status page
β βββ admin.js # Admin panel interface
βββ utils/
βββ kv.js # KV storage utilities
βββ d1Replication.js # D1 database replication (async)
βββ validation.js # Input validation & sanitization
βββ retry.js # Retry logic implementation
βββ nativeRateLimit.js # Native Cloudflare rate limiting
βββ feedParser.js # Universal feed parser
- Admin Panel: Session-based authentication only
- API Access: Completely disabled for maximum security
- Turnstile Protection: All forms require CAPTCHA validation
- Native Rate Limiting Only (No KV operations):
- Burst Protection: 5 requests per 10 seconds (prevents rapid-fire attacks)
- Global: 20 requests per minute per IP
- Forms: 2 requests per minute per IP (subscribe, unsubscribe, contact)
- Admin: 2 requests per minute per IP
- API Endpoints: 3 requests per minute per IP
- Newsletter Check: 2 requests per minute per IP
- Bot Detection: 1 request per minute for suspicious user agents
- No PII Exposure: Customer emails/IPs never returned in API responses
- Sanitized Responses: Only counts and success indicators returned
- XSS Prevention: All inputs sanitized with proper escaping
- Append-Only D1: No deletes, maintaining complete audit trail
sequenceDiagram
participant User
participant CF as Cloudflare Worker
participant KV as KV Storage
participant D1 as D1 Database
participant Email as Email Provider
User->>CF: Subscribe Request
CF->>CF: Validate Turnstile
CF->>CF: Check Native Rate Limit
CF->>KV: Store Subscriber
CF-->>D1: Async Replicate (waitUntil)
CF->>User: Success Response
CF->>Email: Send Welcome Email
Note over CF,KV: Newsletter Check (Hourly)
CF->>KV: Read Subscribers
CF->>Email: Send Batch Emails
CF->>KV: Update Sent Records
Note over KV: TTL Auto-Cleanup
KV->>KV: Expire Rate Limits (2 min)
KV->>KV: Expire Bot Detection (24 hr)
# Email Provider Configuration
EMAIL_PROVIDER = "gmail" # Options: gmail, mailerlite, worker-email
# Batch Processing
BATCH_SIZE = 95 # Recipients per batch (95 to be safe, Gmail allows 100)
BATCH_WAIT_MINUTES = 3 # Wait between batches
# TTL Configuration (seconds)
TTL_BOT_DETECT = 86400 # 24 hours
# Native Rate Limiting Configuration (ONLY rate limiting method used)
# Add these to your wrangler.toml file:
# [[ratelimits]]
# name = "GLOBAL_RATE_LIMITER"
# namespace_id = "1001"
# simple = { limit = 20, period = 60 } # 20 requests per minute
#
# [[ratelimits]]
# name = "FORM_RATE_LIMITER"
# namespace_id = "1002"
# simple = { limit = 2, period = 60 } # 2 form submissions per minute
#
# [[ratelimits]]
# name = "ADMIN_RATE_LIMITER"
# namespace_id = "1003"
# simple = { limit = 2, period = 60 } # 2 admin requests per minute
#
# [[ratelimits]]
# name = "BURST_RATE_LIMITER"
# namespace_id = "1011"
# simple = { limit = 5, period = 10 } # 5 requests per 10 seconds# Core Requirements
wrangler secret put EMAIL_FROM_ADDRESS
wrangler secret put TURNSTILE_SITE_KEY
wrangler secret put TURNSTILE_SECRET_KEY
# For Gmail Provider
wrangler secret put GMAIL_USER
wrangler secret put GMAIL_PASSWORD # App Password
# For MailerLite Provider
wrangler secret put MAILERLITE_API_TOKEN- Cloudflare account with Workers enabled
- KV namespace created
- D1 database created with tables
- Email provider credentials
- Turnstile site configured
# Clone the repository
git clone <your-repo-url>
cd newsletter-and-contact-system
# Install dependencies
npm install
# Configure secrets
wrangler secret put EMAIL_FROM_ADDRESS
# ... (add other secrets)
# Deploy
npx wrangler deploy- Configure Cloudflare Zero Trust for
/admin/*paths (optional) - Set up custom domain (optional)
- Test all endpoints
- Monitor logs in Cloudflare dashboard
- Prefix Filtering: All operations use efficient prefix queries
- Batch Processing: Configurable batch sizes for email delivery
- CPU Safety: Optimized for Cloudflare Workers execution limits
- Async Processing: Uses ctx.waitUntil() for non-blocking writes
- Error Resilient: Failures don't affect user experience
- Append-Only: No deletes or complex queries
- Batch Size: 100 emails per batch
- Retry Logic: 3 attempts with exponential backoff
- Dead Letter Queue: Failed emails stored for manual review
https://your-worker.workers.dev/admin
https://your-worker.workers.dev/admin/status
- Hourly: Newsletter feed checking
- Continuous: TTL-based expiration for temporary data
- Real-time: Async D1 replication on form submissions
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Homepage |
/subscribe |
GET/POST | Newsletter subscription |
/unsubscribe |
GET/POST | Newsletter unsubscription |
/contact |
GET/POST | Contact form |
/robots.txt |
GET | Robots.txt file |
| Endpoint | Method | Description |
|---|---|---|
/admin |
GET | Admin panel (Turnstile) |
/admin/status |
GET | System status |
/admin/api/check-now |
POST | Trigger newsletter check |
- Fork the repository
- Create your feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This project is licensed under the MIT License.
- Cloudflare Workers platform
- worker-mailer library for SMTP support
- MailerLite API
- Cloudflare D1 Database
For issues and questions, please create an issue in the GitHub repository.
Version: 2.0.0 Status: Production Ready Last Updated: 11 November 2025