diff --git a/apps/website/app/api/contact/route.ts b/apps/website/app/api/contact/route.ts index cdf54df..b437e7f 100644 --- a/apps/website/app/api/contact/route.ts +++ b/apps/website/app/api/contact/route.ts @@ -4,6 +4,8 @@ import type { NextRequest } from "next/server"; import { NextResponse } from "next/server"; import { Resend } from "resend"; +const FREE_EMAIL_DOMAINS: Set = new Set(require("free-email-domains")); + interface ContactFormData { inquiryType: "support" | "sales"; firstName: string; @@ -52,6 +54,17 @@ export async function POST(request: NextRequest) { ); } + // Reject free email providers for sales inquiries + if (body.inquiryType === "sales") { + const domain = body.email.split("@")[1]?.toLowerCase(); + if (domain && FREE_EMAIL_DOMAINS.has(domain)) { + return NextResponse.json( + { error: "Please use your work email address to contact sales" }, + { status: 400 }, + ); + } + } + // Submit to HubSpot if it's a sales inquiry if (body.inquiryType === "sales") { try { diff --git a/apps/website/components/ContactForm.tsx b/apps/website/components/ContactForm.tsx index 9932a58..bf2fb3c 100644 --- a/apps/website/components/ContactForm.tsx +++ b/apps/website/components/ContactForm.tsx @@ -12,6 +12,8 @@ import { } from "@/components/ui/select"; import { useState } from "react"; +const FREE_EMAIL_DOMAINS: Set = new Set(require("free-email-domains")); + interface ContactFormData { inquiryType: "" | "support" | "sales"; deploymentType: "" | "cloud" | "self-hosted"; @@ -69,6 +71,12 @@ export function ContactForm({ newErrors.email = "Email is required"; } else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) { newErrors.email = "Please enter a valid email address"; + } else if ( + formData.inquiryType === "sales" && + FREE_EMAIL_DOMAINS.has(formData.email.split("@")[1]?.toLowerCase()) + ) { + newErrors.email = + "Please use your work email address to contact sales"; } if (!formData.company.trim()) { newErrors.company = "Company name is required"; diff --git a/apps/website/package.json b/apps/website/package.json index cb18537..7a4285b 100644 --- a/apps/website/package.json +++ b/apps/website/package.json @@ -35,6 +35,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.0", "framer-motion": "^11.3.19", + "free-email-domains": "^1.2.26", "hast-util-to-jsx-runtime": "^2.3.5", "lucide-react": "0.364.0", "next": "16.1.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f993cb3..b112bbb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,7 +32,7 @@ importers: dependencies: '@next/third-parties': specifier: 16.0.7 - version: 16.0.7(next@16.1.5(@babel/core@7.26.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react@19.2.1) + version: 16.0.7(next@16.1.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react@19.2.1) '@radix-ui/react-dropdown-menu': specifier: ^2.1.16 version: 2.1.16(@types/react-dom@19.2.2(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) @@ -111,7 +111,7 @@ importers: version: 0.2.1(tailwindcss@3.4.7) '@next/third-parties': specifier: 16.0.7 - version: 16.0.7(next@16.1.5(@babel/core@7.26.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react@19.2.1) + version: 16.0.7(next@16.1.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react@19.2.1) '@prettier/plugin-xml': specifier: ^3.4.1 version: 3.4.1(prettier@3.3.3) @@ -172,6 +172,9 @@ importers: framer-motion: specifier: ^11.3.19 version: 11.3.19(react-dom@19.2.1(react@19.2.1))(react@19.2.1) + free-email-domains: + specifier: ^1.2.26 + version: 1.2.26 hast-util-to-jsx-runtime: specifier: ^2.3.5 version: 2.3.6 @@ -2783,6 +2786,10 @@ packages: react-dom: optional: true + free-email-domains@1.2.26: + resolution: {integrity: sha512-HHk4Fp8ts63MDIpnd3LCbfUNAqj6Ea9kjXWUv15zbmEZRR7f7TtBLUvK56ZtyjR6voCdZ1xG1DNIme7yUl9vww==} + engines: {node: '>= 18'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -5153,7 +5160,7 @@ snapshots: '@next/swc-win32-x64-msvc@16.1.5': optional: true - '@next/third-parties@16.0.7(next@16.1.5(@babel/core@7.26.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react@19.2.1)': + '@next/third-parties@16.0.7(next@16.1.5(react-dom@19.2.1(react@19.2.1))(react@19.2.1))(react@19.2.1)': dependencies: next: 16.1.5(@babel/core@7.26.9)(react-dom@19.2.1(react@19.2.1))(react@19.2.1) react: 19.2.1 @@ -6858,6 +6865,8 @@ snapshots: react: 19.2.1 react-dom: 19.2.1(react@19.2.1) + free-email-domains@1.2.26: {} + fsevents@2.3.3: optional: true