{"record":{"id":"57c56b996103685c","repo":"RocketChat/Rocket.Chat","slug":"error-invalid-email-57c56b","errorCode":"error-invalid-email","errorMessage":"error-invalid-email","messagePattern":"error-invalid-email","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/omnichannel/messages.ts","lineNumber":37,"sourceCode":"const dnsResolveMx = util.promisify(dns.resolveMx);\n\ntype OfflineMessageData = {\n\tmessage: string;\n\tname: string;\n\temail: string;\n\tdepartment?: string;\n\thost?: string;\n};\n\nexport async function sendOfflineMessage(data: OfflineMessageData) {\n\tif (!settings.get('Livechat_display_offline_form')) {\n\t\tthrow new Error('error-offline-form-disabled');\n\t}\n\n\tconst { message, name, email, department, host } = data;\n\n\tif (!email) {\n\t\tthrow new Error('error-invalid-email');\n\t}\n\n\tconst emailMessage = `${message}`.replace(/([^>\\r\\n]?)(\\r\\n|\\n\\r|\\r|\\n)/g, '$1<br>$2');\n\n\tlet html = '<h1>New livechat message</h1>';\n\tif (host && host !== '') {\n\t\thtml = html.concat(`<p><strong>Sent from:</strong><a href='${host}'> ${host}</a></p>`);\n\t}\n\thtml = html.concat(`\n\t\t\t<p><strong>Visitor name:</strong> ${name}</p>\n\t\t\t<p><strong>Visitor email:</strong> ${email}</p>\n\t\t\t<p><strong>Message:</strong><br>${emailMessage}</p>`);\n\n\tconst fromEmail = settings.get<string>('From_Email').match(/\\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\\.)+[A-Z]{2,4}\\b/i);\n\n\tlet from: string;\n\tif (fromEmail) {\n\t\tfrom = fromEmail[0];","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/omnichannel/messages.ts#L19-L55","documentation":"Thrown by `sendOfflineMessage` when the destructured `email` field of the offline message data is falsy. The offline email needs a reply-to address, so the payload is rejected before any template/DNS work — a plain required-field gate, distinct from error 918's domain-validity check.","triggerScenarios":"Submitting the offline form with an empty email input — the widget/API did not enforce the field client-side, or the payload was constructed programmatically without an `email` key.","commonSituations":"Custom offline-form frontends that drop the email input or mark it optional; middleware stripping unknown/empty fields; users submitting with whitespace-only input that survives naive checks.","solutions":["Make the email field required and validated (non-empty, basic format) in the form before submission","If building the payload in code, assert `data.email` is a non-empty string first","For API consumers, return a 400-style validation message instead of surfacing the raw error"],"exampleFix":"// before\nawait sendOfflineMessage({ message, name, email: '' });\n\n// after\nif (!email || !/.+@.+\\..+/.test(email)) {\n  throw new Error('A valid email is required');\n}\nawait sendOfflineMessage({ message, name, email });","handlingStrategy":"validation","validationCode":"if (!data.email || !/^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$/.test(data.email)) {\n  throw new Error('Email is required');\n}\nawait sendOfflineMessage(data);","typeGuard":"const hasContactEmail = (d: { email?: string }): boolean =>\n  typeof d.email === 'string' && d.email.trim().length > 0;","tryCatchPattern":"try {\n  await sendOfflineMessage(data);\n} catch (e) {\n  if (e instanceof Error && e.message === 'error-invalid-email') {\n    // mark the email input as required in the form\n  }\n}","preventionTips":["Make email a required, validated input in every offline form frontend","Assert payload shape in API wrappers before calling","Trim and basic-format-check email client-side"],"tags":["omnichannel","offline-form","email","validation","required-field"],"backgroundTag":"required-field-missing","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}