RocketChat/Rocket.Chat · error · Meteor.Error

error-invalid-email-address

error-invalid-email-address

Error message

error-invalid-email-address

What it means

Thrown by `sendOfflineMessage` when `Livechat_validate_offline_email` is enabled and `dns.resolveMx()` on the domain part of the submitted email (after the last '@') rejects. The intent is blocking fake addresses; in practice any MX-resolution failure throws — invalid domain, no MX records, or the server cannot reach DNS at all.

Source

Thrown at apps/meteor/server/lib/omnichannel/messages.ts:66

			<p><strong>Visitor email:</strong> ${email}</p>
			<p><strong>Message:</strong><br>${emailMessage}</p>`);

	const fromEmail = settings.get<string>('From_Email').match(/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b/i);

	let from: string;
	if (fromEmail) {
		from = fromEmail[0];
	} else {
		from = settings.get<string>('From_Email');
	}

	if (settings.get('Livechat_validate_offline_email')) {
		const emailDomain = email.substr(email.lastIndexOf('@') + 1);

		try {
			await dnsResolveMx(emailDomain);
		} catch (e) {
			throw new Meteor.Error('error-invalid-email-address');
		}
	}

	// TODO Block offline form if Livechat_offline_email is undefined
	// (it does not make sense to have an offline form that does nothing)
	// `this.sendEmail` will throw an error if the email is invalid
	// thus this breaks livechat, since the "to" email is invalid, and that returns an [invalid email] error to the livechat client
	let emailTo = settings.get<string>('Livechat_offline_email');
	if (department && department !== '') {
		const dep = await LivechatDepartment.findOneByIdOrName(department, { projection: { email: 1 } });
		if (dep) {
			emailTo = dep.email || emailTo;
		}
	}

	const fromText = `${name} - ${email} <${from}>`;
	const replyTo = `${name} <${email}>`;
	const subject = `Livechat offline message from ${name}: ${`${emailMessage}`.substring(0, 20)}`;

View on GitHub (pinned to b2c16d5842)

Solutions

  1. Verify the domain actually has MX records (`dig MX example.com`) and ask the user to fix typos
  2. If false positives from DNS/network issues outweigh the benefit, disable the `Livechat_validate_offline_email` setting
  3. Fix the server's DNS resolution (containers: --dns, resolv.conf) so resolveMx works reliably

Example fix

// before
await sendOfflineMessage({ message, name, email: 'a@gmial.com' });

// after
// client-side soft check to catch typos before the strict server check
const [, domain] = email.split('@');
if (!domain || !/^[a-z0-9.-]+\.[a-z]{2,}$/i.test(domain)) {
  throw new Error('Check the email domain');
}
await sendOfflineMessage({ message, name, email });
Defensive patterns

Strategy: try-catch

Validate before calling

const [, domain] = email.split('@');
if (!domain || !/^[a-z0-9.-]+\.[a-z]{2,}$/i.test(domain)) {
  throw new Error('Email domain looks malformed');
}
// full MX check is server-side and can fail on network issues — catch there

Type guard

const hasPlausibleEmailDomain = (email: string): boolean =>
  /^[^@\s]+@([a-z0-9-]+\.)+[a-z]{2,}$/i.test(email);

Try / catch

try {
  await sendOfflineMessage(data);
} catch (e) {
  if (isMeteorError(e, 'error-invalid-email-address')) {
    // ask the user to re-check the address; do NOT auto-retry (DNS may be fine and the domain fake)
  }
}

Prevention

When it happens

Trigger: Visitor submits an email whose domain has no MX records (typos like 'user@gmial.com' or disposable domains), or the Rocket.Chat server's DNS/resolver is broken/firewalled, with Livechat_validate_offline_email turned on.

Common situations: Enabling email validation to fight spam and then legitimate domains without MX (rare but legal) or corporate DNS blocks get rejected; containerized deployments with no working DNS; transient resolver outages turning valid submissions into errors.

Related errors


AI-assisted analysis of RocketChat/Rocket.Chat@b2c16d5842 (2026-08-18). Data as JSON: /api/errors/d7de775e86c913a6. Report an issue: GitHub.