fix: disable Redis and fix email configuration

- Remove Redis rate limiting for security reasons
- Update SMTP port from 587 to 2525 (matching working websites)
- Add requireTLS to nodemailer configuration
- Remove Redis environment variables
- Update rate-limit.ts with graceful fallback
- Add debugging logs to contact API
- Contact form functionality verified and working
This commit is contained in:
TheMaddax 2025-10-04 09:11:45 -06:00
parent efb26e7791
commit e1ba653276
4 changed files with 45 additions and 87 deletions

View file

@ -1,9 +1,6 @@
GOOGLE_EMAIL=system@sigd.net
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_PORT=2525
SMTP_SECURE=false
RECIPIENT_EMAIL=chris@sigd.net
GOOGLE_APP_PASSWORD=fvjivgqewtmtpdez
UPSTASH_REDIS_REST_URL=https://gusc1-resolved-jaybird-30779.upstash.io
UPSTASH_REDIS_REST_TOKEN=AXg7ASQgNDMzMDE0MTYtNWE0Ni00OTc3LThhYjktM2IxMzMxNGMyMzMxNWRiNGMyOGU2MjE0NGUyNTkwMTQyNmUxZTU2NzE4NDI=
GOOGLE_APP_PASSWORD=fvjivgqewtmtpdez

View file

@ -7,27 +7,27 @@
- Ready for development tasks
## What I'm Working On Now
- Just completed Memory Bank setup
- No active development tasks currently
- Awaiting user instructions for next steps
- Recently completed Redis removal and email configuration fixes
- Contact form functionality has been verified and is working
- Ready to commit changes to git repository
## Recent Changes
- Created `cline_docs/` directory
- Established complete Memory Bank documentation:
- productContext.md - Project purpose and goals
- activeContext.md - Current work status (this file)
- systemPatterns.md - Architecture and patterns
- techContext.md - Technical setup and dependencies
- progress.md - Development status
- **Disabled Redis for security reasons:**
- Removed Redis rate limiting from contact API route
- Removed Redis environment variables from .env.local
- Updated rate-limit.ts to provide graceful fallback without Redis
- **Fixed email configuration:**
- Updated SMTP port from 587 to 2525 (matching working websites)
- Added requireTLS: true to nodemailer configuration
- Added debugging logs to contact API for troubleshooting
- **Contact form verification:**
- User confirmed contact form is now working properly
- Email sending functionality restored
## Next Steps
- Await user instructions for specific tasks
- Potential areas for development:
- Feature enhancements
- Bug fixes
- Content updates
- Performance optimizations
- Accessibility improvements
- Commit current changes to git with proper message
- Clean up any debugging logs if needed
- Continue with any additional development tasks
## Current Understanding
The website is a professional portfolio for Chris Haulmark, a global Deaf advocate. It's built with Next.js 14, TypeScript, and TailwindCSS. The site includes:

View file

@ -1,6 +1,5 @@
import { NextResponse } from 'next/server'
import nodemailer from 'nodemailer'
import { rateLimit } from '@/lib/rate-limit'
interface FormData {
name: string
@ -43,16 +42,11 @@ const sanitizeInput = (input: string): string => {
export async function POST(req: Request) {
try {
// Rate limiting check
const rateLimitResult = await rateLimit()
if (!rateLimitResult.success) {
return NextResponse.json(
{ success: false, message: 'Too many requests. Please try again later.' },
{ status: 429 }
)
}
// Rate limiting disabled for security reasons
console.log('Contact API called')
const data: FormData = await req.json()
console.log('Form data received:', { ...data, message: data.message?.substring(0, 50) + '...' })
// Input validation
const validation = validateInput(data)
@ -71,10 +65,20 @@ export async function POST(req: Request) {
message: sanitizeInput(data.message)
}
console.log('Environment check:', {
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
secure: process.env.SMTP_SECURE,
hasEmail: !!process.env.GOOGLE_EMAIL,
hasPassword: !!process.env.GOOGLE_APP_PASSWORD,
hasRecipient: !!process.env.RECIPIENT_EMAIL
})
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT),
secure: process.env.SMTP_SECURE === 'true',
requireTLS: true,
auth: {
user: process.env.GOOGLE_EMAIL,
pass: process.env.GOOGLE_APP_PASSWORD,
@ -99,7 +103,9 @@ export async function POST(req: Request) {
`,
}
console.log('Attempting to send email...')
await transporter.sendMail(mailOptions)
console.log('Email sent successfully')
return NextResponse.json({
success: true,

View file

@ -1,5 +1,5 @@
import { Redis } from '@upstash/redis'
import { headers } from 'next/headers'
// Redis disabled for security reasons
// Graceful fallback without rate limiting
export interface RateLimitConfig {
interval: number // in seconds
@ -13,60 +13,15 @@ export interface RateLimitResult {
reset: number // timestamp in seconds
}
export class RateLimit {
private redis: Redis
private prefix: string
constructor() {
this.redis = Redis.fromEnv()
this.prefix = 'ratelimit'
}
private getIP(): string {
const headersList = headers()
const forwardedFor = headersList.get('x-forwarded-for')
const realIP = headersList.get('x-real-ip')
const ip = forwardedFor?.split(',')[0] || realIP || 'unknown'
return ip
}
private getKey(identifier: string): string {
return `${this.prefix}:${identifier}`
}
async check(config: RateLimitConfig): Promise<RateLimitResult> {
const ip = this.getIP()
const key = this.getKey(ip)
const now = Math.floor(Date.now() / 1000)
const windowStart = now - (now % config.interval)
const windowKey = `${key}:${windowStart}`
const pipeline = this.redis.pipeline()
pipeline.incr(windowKey)
pipeline.expire(windowKey, config.interval)
const [count] = await pipeline.exec()
const remaining = Math.max(0, config.limit - (count as number))
return {
success: (count as number) <= config.limit,
limit: config.limit,
remaining,
reset: windowStart + config.interval
}
}
}
// Default configuration
const DEFAULT_CONFIG: RateLimitConfig = {
interval: 60 * 60, // 1 hour
limit: 5 // 5 requests per hour
}
// Helper function for easy usage
// Helper function for easy usage - always allows requests
export async function rateLimit(
config: RateLimitConfig = DEFAULT_CONFIG
config?: RateLimitConfig
): Promise<RateLimitResult> {
const limiter = new RateLimit()
return limiter.check(config)
// Always return success since Redis is disabled
return {
success: true,
limit: 999,
remaining: 999,
reset: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now
}
}