Files
thrilltrack-explorer/supabase/functions/validate-email-backend/index.ts
gpt-engineer-app[bot] e28dc97d71 Migrate Phase 1 Functions
Migrate 8 high-priority functions (admin-delete-user, mfa-unenroll, confirm-account-deletion, request-account-deletion, send-contact-message, upload-image, validate-email-backend, process-oauth-profile) to wrapEdgeFunction pattern. Replace manual CORS/auth, add shared validations, integrate standardized error handling, and preserve existing rate limiting where applicable. Update implementations to leverage context span, requestId, and improved logging for consistent error reporting and tracing.
2025-11-11 03:03:26 +00:00

76 lines
2.3 KiB
TypeScript

import { corsHeaders } from '../_shared/cors.ts';
import { rateLimiters, withRateLimit } from '../_shared/rateLimiter.ts';
import { createEdgeFunction } from '../_shared/edgeFunctionWrapper.ts';
import { validateString } from '../_shared/typeValidation.ts';
// Common disposable email domains (subset for performance)
const DISPOSABLE_DOMAINS = new Set([
'tempmail.com', 'guerrillamail.com', '10minutemail.com', 'mailinator.com',
'throwaway.email', 'temp-mail.org', 'fakeinbox.com', 'maildrop.cc',
'yopmail.com', 'sharklasers.com', 'guerrillamailblock.com'
]);
interface EmailValidationResult {
valid: boolean;
reason?: string;
suggestions?: string[];
}
function validateEmailFormat(email: string): EmailValidationResult {
// Basic format validation
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
return { valid: false, reason: 'Invalid email format' };
}
// Extract domain
const domain = email.split('@')[1].toLowerCase();
// Check against disposable domains
if (DISPOSABLE_DOMAINS.has(domain)) {
return {
valid: false,
reason: 'Disposable email addresses are not allowed. Please use a permanent email address.',
suggestions: ['gmail.com', 'outlook.com', 'yahoo.com', 'protonmail.com']
};
}
// Check for suspicious patterns
if (domain.includes('temp') || domain.includes('disposable') || domain.includes('trash')) {
return {
valid: false,
reason: 'This email domain appears to be temporary. Please use a permanent email address.',
};
}
return { valid: true };
}
// Apply lenient rate limiting (30 req/min) for email validation
const handler = createEdgeFunction(
{
name: 'validate-email-backend',
requireAuth: false,
corsHeaders: corsHeaders
},
async (req, context) => {
const { email } = await req.json();
validateString(email, 'email', { requestId: context.requestId });
context.span.setAttribute('action', 'validate_email');
// Validate email
const result = validateEmailFormat(email.toLowerCase().trim());
return new Response(
JSON.stringify(result),
{
status: 200,
headers: { 'Content-Type': 'application/json' }
}
);
}
);
export default withRateLimit(handler, rateLimiters.lenient, corsHeaders);