Files
thrilltrack-explorer/supabase/functions/validate-email-backend/index.ts
gpt-engineer-app[bot] 2d65f13b85 Connect to Lovable Cloud
Add centralized errorFormatter to convert various error types into readable messages, and apply it across edge functions. Replace String(error) usage with formatEdgeError, update relevant imports, fix a throw to use toError, and enhance logger to log formatted errors. Includes new errorFormatter.ts and widespread updates to 18+ edge functions plus logger integration.
2025-11-10 18:09:15 +00:00

123 lines
3.6 KiB
TypeScript

import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3';
import { edgeLogger } from "../_shared/logger.ts";
import { formatEdgeError } from "../_shared/errorFormatter.ts";
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};
// Simple request tracking
const startRequest = () => ({ requestId: crypto.randomUUID(), start: Date.now() });
const endRequest = (tracking: { start: number }) => Date.now() - tracking.start;
// 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 };
}
serve(async (req) => {
const tracking = startRequest();
// Handle CORS preflight requests
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const { email } = await req.json();
if (!email || typeof email !== 'string') {
return new Response(
JSON.stringify({ valid: false, reason: 'Email is required', requestId: tracking.requestId }),
{
status: 400,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
}
);
}
// Validate email
const result = validateEmailFormat(email.toLowerCase().trim());
const duration = endRequest(tracking);
return new Response(
JSON.stringify({ ...result, requestId: tracking.requestId }),
{
status: 200,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
}
);
} catch (error) {
const duration = endRequest(tracking);
const errorMessage = formatEdgeError(error);
edgeLogger.error('Email validation error', {
error: errorMessage,
requestId: tracking.requestId,
duration
});
return new Response(
JSON.stringify({
valid: false,
reason: 'Failed to validate email. Please try again.',
requestId: tracking.requestId
}),
{
status: 500,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
}
);
}
});