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:
parent
efb26e7791
commit
e1ba653276
4 changed files with 45 additions and 87 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue