diff --git a/apps/api/src/services/notification/email_notification.ts b/apps/api/src/services/notification/email_notification.ts index 660c83d8..cf238b06 100644 --- a/apps/api/src/services/notification/email_notification.ts +++ b/apps/api/src/services/notification/email_notification.ts @@ -48,6 +48,17 @@ const emailTemplates: Record< }, }; +// Map notification types to email categories +const notificationToEmailCategory: Record = { + [NotificationType.APPROACHING_LIMIT]: 'system_alerts', + [NotificationType.LIMIT_REACHED]: 'system_alerts', + [NotificationType.RATE_LIMIT_REACHED]: 'rate_limit_warnings', + [NotificationType.AUTO_RECHARGE_SUCCESS]: 'system_alerts', + [NotificationType.AUTO_RECHARGE_FAILED]: 'system_alerts', + [NotificationType.CONCURRENCY_LIMIT_REACHED]: 'rate_limit_warnings', + [NotificationType.AUTO_RECHARGE_FREQUENT]: 'system_alerts', +}; + export async function sendNotification( team_id: string, notificationType: NotificationType, @@ -66,14 +77,57 @@ export async function sendNotification( ); } -export async function sendEmailNotification( +async function sendEmailNotification( email: string, notificationType: NotificationType, ) { const resend = new Resend(process.env.RESEND_API_KEY); try { - const { data, error } = await resend.emails.send({ + // Get user's email preferences + const { data: user, error: userError } = await supabase_service + .from("users") + .select("id") + .eq("email", email) + .single(); + + if (userError) { + logger.debug(`Error fetching user: ${userError}`); + return { success: false }; + } + + // Check user's email preferences + const { data: preferences, error: prefError } = await supabase_service + .from("notification_preferences") + .select("unsubscribed_all, email_preferences") + .eq("user_id", user.id) + .single(); + + if (prefError) { + logger.debug(`Error fetching preferences: ${prefError}`); + return { success: false }; + } + + // If user has unsubscribed from all emails or we can't find their preferences, don't send + if (!preferences || preferences.unsubscribed_all) { + logger.debug(`User ${email} has unsubscribed from all emails or preferences not found`); + return { success: true }; // Return success since this is an expected case + } + + // Get the email category for this notification type + const emailCategory = notificationToEmailCategory[notificationType]; + + // If user has unsubscribed from this category of emails, don't send + if ( + preferences.email_preferences && + Array.isArray(preferences.email_preferences) && + !preferences.email_preferences.includes(emailCategory) + ) { + logger.debug(`User ${email} has unsubscribed from ${emailCategory} emails`); + return { success: true }; // Return success since this is an expected case + } + + const { error } = await resend.emails.send({ from: "Firecrawl ", to: [email], reply_to: "help@firecrawl.com", @@ -85,13 +139,15 @@ export async function sendEmailNotification( logger.debug(`Error sending email: ${error}`); return { success: false }; } + + return { success: true }; } catch (error) { logger.debug(`Error sending email (2): ${error}`); return { success: false }; } } -export async function sendNotificationInternal( +async function sendNotificationInternal( team_id: string, notificationType: NotificationType, startDateString: string | null,