{"record":{"id":"2c0993f0e70fe124","repo":"koala73/worldmonitor","slug":"please-use-a-corporate-email-address","errorCode":null,"errorMessage":"Please use a corporate email address.","messagePattern":"Please use a corporate email address\\.","errorType":"http","errorClass":"ApiError","httpStatus":422,"severity":"warning","filePath":"server/worldmonitor/leads/v1/submit-contact.ts","lineNumber":183,"sourceCode":"      },\n      body: JSON.stringify({\n        name: safeName,\n        email: email.trim(),\n        organization: safeOrg,\n        phone: safePhone,\n        message: safeMsg,\n        source: safeSource,\n      }),\n      signal: AbortSignal.timeout(10_000),\n    });\n  } catch {\n    throw new ApiError(503, 'Service unavailable', '');\n  }\n  if (response.status === 429) {\n    throw new ApiError(429, 'Too many recent submissions for this email; try again later.', '');\n  }\n  if (response.status === 422) {\n    throw new ApiError(422, 'Please use a corporate email address.', '');\n  }\n  if (!response.ok) {\n    throw new ApiError(503, 'Service unavailable', '');\n  }\n  const result: unknown = await response.json().catch(() => null);\n  if (!result || typeof result !== 'object' || !('status' in result) || result.status !== 'sent') {\n    throw new ApiError(503, 'Service unavailable', '');\n  }\n\n  const emailSent = await sendNotificationEmail(\n    safeName,\n    email.trim(),\n    safeOrg,\n    safePhone,\n    safeMsg,\n    ip,\n    country,\n  );","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/koala73/worldmonitor/blob/7d06c8633d256c18e38133030bc3613976a96ec9/server/worldmonitor/leads/v1/submit-contact.ts#L165-L201","documentation":"The Convex action rejected the submitted email with 422 because it is not a corporate/free-form-allowed address (the backend enforces a corporate-email policy). The handler maps it to a user-friendly 422 ApiError.","triggerScenarios":"Calling submitContact with an email that fails the backend's corporate-email check — e.g. gmail.com, yahoo.com, or a disposable domain.","commonSituations":"End users entering personal email addresses into an enterprise contact form; test fixtures using example.com or gmail.com; a disposable-domain list update newly classifying a customer's domain.","solutions":["Resubmit with a corporate/business email address","Show the validation message in the form UI before submission by pre-checking common free-mail domains","If a legitimate corporate address is rejected, check/extend the allowed-domain list in the Convex action","Use a role-based address at your company domain (e.g. sales@company.com) for testing"],"exampleFix":"// before\n// client sends whatever email the user typed\nawait api.submitContact({ email: 'user@gmail.com', ... });\n// after\nconst FREE_MAIL = /^[^@]+@(gmail|yahoo|hotmail|outlook)\\./i;\nif (FREE_MAIL.test(email)) showFormError('Please use a corporate email address.');\nelse await api.submitContact({ email, ... });","handlingStrategy":"validation","validationCode":"const FREE_MAIL = /^[^@\\s]+@(gmail|googlemail|yahoo|hotmail|outlook|aol|icloud|proton|mail\\.)[a-z.]*$/i;\nif (!/^[^@\\s]+@[^@\\s]+\\.[a-z]{2,}$/i.test(email) || FREE_MAIL.test(email)) {\n  throw new Error('Please use a corporate email address.');\n}","typeGuard":"function isCorporateEmail(email: string): boolean {\n  return /^[^@\\s]+@[^@\\s]+\\.[a-z]{2,}$/i.test(email) && !FREE_MAIL.test(email);\n}","tryCatchPattern":"try {\n  await submitContact(form);\n} catch (e) {\n  if (e instanceof ApiError && e.status === 422) {\n    setFieldError('email', 'Please use a corporate email address.');\n  } else throw e;\n}","preventionTips":["Validate the corporate-email policy in the form before submission","Keep the free/disposable domain list shared between client and Convex backend","Use corporate-domain fixtures in tests"],"tags":["validation","email","http-422"],"backgroundTag":"invalid-argument-value","analyzedSha":"7d06c8633d256c18e38133030bc3613976a96ec9","analyzedAt":"2026-09-15T16:44:39.439Z","contentChangedAt":"2026-09-15T16:44:39.439Z","schemaVersion":2},"datasetVersion":"2026-09-15T18:17:12.389Z"}