@@ -4,6 +4,7 @@ import { i18n } from "~/i18n"
44import { localeFromRequest } from "~/lib/language"
55import { createLead } from "~/lib/salesforce"
66import { inferenceSpendOptions } from "~/lib/inference-spend"
7+ import { contactReasons } from "~/lib/contact-reason"
78import { ENTERPRISE_SPAM_THRESHOLD , enterpriseSpamProbability } from "~/lib/enterprise-spam"
89import { verifyHcaptcha } from "~/lib/hcaptcha"
910
@@ -13,13 +14,22 @@ interface EnterpriseFormData {
1314 company ?: string
1415 email : string
1516 phone ?: string
17+ /** A country name; the Lead's Country is a text field. */
18+ country ?: string
1619 inferenceSpend ?: string
20+ inRegionRouting ?: boolean
21+ dpa ?: boolean
22+ /** Set only for an inquiry that isn't for sales; its `contactReasons` value. */
23+ reason ?: string
1724 alias ?: string
1825 message : string
1926 captcha ?: string
2027}
2128
2229const EMAIL_OCTOPUS_LIST_ID = "1b381e5e-39bd-11f1-ba4a-cdd4791f0c43"
30+ // An inquiry that isn't for sales skips Salesforce and EmailOctopus. It's emailed here, titled with its reason, to be
31+ // forwarded to the team that handles it.
32+ const CONTACT_INBOX_EMAIL = "stefan@anoma.ly"
2333
2434function splitFullName ( fullName : string ) {
2535 const parts = fullName
@@ -42,10 +52,19 @@ function escapeHtml(value: unknown) {
4252
4353export function enterpriseEmailContent ( body : EnterpriseFormData , inferenceSpend ?: string ) {
4454 const field = ( value ?: unknown ) => ( value ? `${ escapeHtml ( value ) } <br>` : "" )
55+ const requirements = [
56+ body . inRegionRouting && "In-region routing (EU or US)" ,
57+ body . dpa && "Data Processing Agreement (DPA)" ,
58+ ] . filter ( ( item ) => typeof item === "string" )
59+ const details = [
60+ inferenceSpend && `Current monthly inference spend: ${ inferenceSpend } ` ,
61+ body . country && `Country: ${ body . country } ` ,
62+ requirements . length > 0 && `Compliance requirements: ${ requirements . join ( ", " ) } ` ,
63+ ] . filter ( ( item ) => typeof item === "string" )
4564 return {
4665 html : `
4766${ escapeHtml ( body . message ) } <br><br>
48- ${ inferenceSpend ? `Current monthly inference spend: ${ escapeHtml ( inferenceSpend ) } <br><br>` : "" }
67+ ${ details . length > 0 ? ` ${ details . map ( escapeHtml ) . join ( "<br>" ) } <br><br>` : "" }
4968--<br>
5069${ field ( body . name ) }
5170${ field ( body . role ) }
@@ -54,7 +73,7 @@ ${field(body.phone)}`.trim(),
5473 text : [
5574 body . message ,
5675 "" ,
57- ...( inferenceSpend ? [ `Current monthly inference spend: ${ inferenceSpend } ` , "" ] : [ ] ) ,
76+ ...( details . length > 0 ? [ ... details , "" ] : [ ] ) ,
5877 "--" ,
5978 ...[ body . name , body . role , body . company , body . email , body . phone ] . filter ( Boolean ) ,
6079 ] . join ( "\n" ) ,
@@ -97,6 +116,7 @@ export async function handleEnterpriseRequest(
97116 options : {
98117 salesforceSubmit ?: ( payload : Record < string , unknown > ) => Promise < boolean >
99118 notifications ?: boolean
119+ send ?: typeof sendEmail
100120 spam ?: Parameters < typeof enterpriseSpamProbability > [ 1 ]
101121 captcha ?: Parameters < typeof verifyHcaptcha > [ 1 ]
102122 } = { } ,
@@ -110,7 +130,10 @@ export async function handleEnterpriseRequest(
110130 return Response . json ( { success : true , message : dict [ "enterprise.form.success.submitted" ] } , { status : 200 } )
111131 }
112132
113- if ( ! body . name || ! body . role || ! body . email || ! body . message ) {
133+ // A sales inquiry names its sender and their role; any other inquiry only needs its reason.
134+ const reason = body . reason === undefined ? undefined : contactReasons . find ( ( item ) => item . value === body . reason )
135+ const complete = body . reason === undefined ? Boolean ( body . name && body . role ) : reason !== undefined
136+ if ( ! body . email || ! body . message || ! complete ) {
114137 return Response . json ( { error : dict [ "enterprise.form.error.allFieldsRequired" ] } , { status : 400 } )
115138 }
116139
@@ -119,6 +142,16 @@ export async function handleEnterpriseRequest(
119142 return Response . json ( { error : dict [ "enterprise.form.error.invalidEmailFormat" ] } , { status : 400 } )
120143 }
121144
145+ // The Lead's Country holds up to 80 characters.
146+ const structured =
147+ ( body . country === undefined || ( typeof body . country === "string" && body . country . trim ( ) . length <= 80 ) ) &&
148+ ( body . inRegionRouting === undefined || typeof body . inRegionRouting === "boolean" ) &&
149+ ( body . dpa === undefined || typeof body . dpa === "boolean" )
150+ if ( ! structured ) {
151+ return Response . json ( { error : dict [ "enterprise.form.error.allFieldsRequired" ] } , { status : 400 } )
152+ }
153+ const country = body . country ?. trim ( ) || undefined
154+
122155 const inferenceSpend = inferenceSpendOptions . find ( ( option ) => option . value === body . inferenceSpend )
123156 if ( body . inferenceSpend && ! inferenceSpend ) {
124157 return Response . json ( { error : dict [ "enterprise.form.error.invalidInferenceSpend" ] } , { status : 400 } )
@@ -145,7 +178,27 @@ export async function handleEnterpriseRequest(
145178 return Response . json ( { success : true , message : dict [ "enterprise.form.success.submitted" ] } , { status : 200 } )
146179 }
147180
148- const emailContent = enterpriseEmailContent ( body , inferenceSpend ?. salesforceValue )
181+ const send = options . send ?? sendEmail
182+
183+ if ( reason ) {
184+ const sent = await send ( {
185+ to : CONTACT_INBOX_EMAIL ,
186+ subject : reason . label ,
187+ body : `${ escapeHtml ( body . message ) } <br><br>--<br>${ escapeHtml ( body . email ) } ` ,
188+ text : [ body . message , "" , "--" , body . email ] . join ( "\n" ) ,
189+ replyTo : body . email ,
190+ } ) . then (
191+ ( ) => true ,
192+ ( err ) => {
193+ console . error ( "Failed to send contact email:" , err )
194+ return false
195+ } ,
196+ )
197+ if ( ! sent ) return Response . json ( { error : dict [ "enterprise.form.error.internalServer" ] } , { status : 500 } )
198+ return Response . json ( { success : true , message : dict [ "enterprise.form.success.submitted" ] } , { status : 200 } )
199+ }
200+
201+ const emailContent = enterpriseEmailContent ( { ...body , country } , inferenceSpend ?. salesforceValue )
149202
150203 const [ lead , mail , octopus ] = await Promise . all ( [
151204 createLead (
@@ -155,7 +208,10 @@ export async function handleEnterpriseRequest(
155208 company : body . company ,
156209 email : body . email ,
157210 phone : body . phone ,
211+ country,
158212 inferenceSpend : inferenceSpend ?. salesforceValue ,
213+ inRegionRouting : body . inRegionRouting === true ,
214+ dpa : body . dpa === true ,
159215 message : body . message ,
160216 } ,
161217 options . salesforceSubmit ,
@@ -165,7 +221,7 @@ export async function handleEnterpriseRequest(
165221 } ) ,
166222 options . notifications === false
167223 ? Promise . resolve ( false )
168- : sendEmail ( {
224+ : send ( {
169225 to : Resource . ENTERPRISE_SALES_INBOX_EMAIL . value ,
170226 subject : `Enterprise Inquiry from ${ body . name } ` ,
171227 body : emailContent . html ,
0 commit comments