{"record":{"id":"da634b1fde018242","repo":"RocketChat/Rocket.Chat","slug":"invalid-email","errorCode":"invalid email","errorMessage":"invalid email","messagePattern":"invalid email","errorType":"error_code","errorClass":"Meteor.Error","httpStatus":null,"severity":"error","filePath":"apps/meteor/server/lib/notifications/email/api.ts","lineNumber":158,"sourceCode":"export const sendNoWrap = async ({\n\tto,\n\tfrom,\n\treplyTo,\n\tsubject,\n\thtml,\n\ttext,\n\theaders,\n}: {\n\tto: string | string[];\n\tfrom: string;\n\treplyTo?: string;\n\tsubject: string;\n\thtml?: string;\n\ttext?: string;\n\theaders?: string;\n}) => {\n\tif (!checkAddressFormat(to)) {\n\t\tthrow new Meteor.Error('invalid email');\n\t}\n\n\tif (!text) {\n\t\ttext = html ? stripHtml(html).result : undefined;\n\t}\n\n\tif (settings.get('email_plain_text_only')) {\n\t\thtml = undefined;\n\t}\n\n\tconst value = await Settings.incrementValueById('Triggered_Emails_Count', 1, { returnDocument: 'after' });\n\tif (value) {\n\t\tvoid notifyOnSettingChanged(value);\n\t}\n\n\tconst email = { to, from, replyTo, subject, html, text, headers };\n\n\tconst eventResult = await Apps.self?.triggerEvent(AppEvents.IPreEmailSent, { email });","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/RocketChat/Rocket.Chat/blob/b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0/apps/meteor/server/lib/notifications/email/api.ts#L140-L176","documentation":"Mailer.sendNoWrap (and Mailer.send, which delegates to it) validates every recipient with validateEmail from @rocket.chat/tools via checkAddressFormat before sending; if any 'to' address fails the format check it throws Meteor.Error('invalid email'). This is a pre-SMTP format check - the mail never reaches the transport. Arrays are checked with every(), so one malformed recipient fails the whole call.","triggerScenarios":"Mailer.send({ to: 'user@@example' }), to: '', to: ['ok@x.com', 'nope'], or an untrimmed address with spaces/newlines coming from stored user profile data.","commonSituations":"Unverified or typo'd user email addresses; passing user.emails[0] (an object) instead of .address; templating code injecting undefined into the address; addresses imported from LDAP/CSV with stray quotes or whitespace.","solutions":["Log and inspect the exact 'to' value being sent; fix its format","Pre-validate with Mailer.checkAddressFormat (or validateEmail from @rocket.chat/tools) before calling send","Trim addresses and build 'Name <addr@domain>' only from verified, fully qualified fields"],"exampleFix":"// before\nawait Mailer.send({ to: user.emails[0], from, subject, html }); // object, not string\n\n// after\nconst addr = user.emails?.[0]?.address?.trim() ?? '';\nif (!Mailer.checkAddressFormat(addr)) throw new Error('bad recipient');\nawait Mailer.send({ to: addr, from, subject, html });","handlingStrategy":"validation","validationCode":"import { Mailer } from '.../email/api';\nconst recipients = ([] as string[]).concat(to).map((a) => a.trim());\nif (!Mailer.checkAddressFormat(recipients)) {\n  // drop or fix bad recipients before sending\n  throw new Error('invalid recipient');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await Mailer.send({ to, from, subject, html });\n} catch (err) {\n  if (err instanceof Meteor.Error && err.error === 'invalid email') {\n    // log the 'to' value and fix its format; nothing was sent\n  } else throw err;\n}","preventionTips":["Always use user.emails[0].address, never the emails[0] object","Trim and validate addresses at the boundary where users enter them","Validate the whole recipient array before any bulk send"],"tags":["email","mailer","validation","rocket-chat"],"backgroundTag":"invalid-email-address","analyzedSha":"b2c16d5842cbe6b69b59bdf6fc5e5f1afcd1f0b0","analyzedAt":"2026-08-18T15:26:39.429Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}