From 25b75de4577e48de127f2da71a58c9bd8401a74d Mon Sep 17 00:00:00 2001 From: Hashim Khan Date: Wed, 22 Jul 2026 23:42:22 +0500 Subject: [PATCH] fix: allow allowUnderscore option on string().email() email() documented and typed allowUnderscore but rejected it in assertOptions, unlike string().domain(). Accept the option so it reaches @hapi/address validation. Closes #2972 --- lib/types/string.js | 2 +- test/types/string.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/types/string.js b/lib/types/string.js index 48303763..f169c2d5 100755 --- a/lib/types/string.js +++ b/lib/types/string.js @@ -313,7 +313,7 @@ module.exports = Any.extend({ email: { method(options = {}) { - Common.assertOptions(options, ['allowFullyQualified', 'allowUnicode', 'ignoreLength', 'maxDomainSegments', 'minDomainSegments', 'multiple', 'separator', 'tlds']); + Common.assertOptions(options, ['allowFullyQualified', 'allowUnicode', 'allowUnderscore', 'ignoreLength', 'maxDomainSegments', 'minDomainSegments', 'multiple', 'separator', 'tlds']); assert(options.multiple === undefined || typeof options.multiple === 'boolean', 'multiple option must be an boolean'); const address = internals.addressOptions(options); diff --git a/test/types/string.js b/test/types/string.js index 829059bd..e8f0d820 100755 --- a/test/types/string.js +++ b/test/types/string.js @@ -1453,6 +1453,34 @@ describe('string', () => { expect(() => Joi.string().email({ multiple: false })).to.not.throw(); expect(() => Joi.string().email({ multiple: {} })).to.throw('multiple option must be an boolean'); expect(() => Joi.string().email({ multiple: 'abc' })).to.throw('multiple option must be an boolean'); + + expect(() => Joi.string().email({ allowUnderscore: true })).to.not.throw(); + expect(() => Joi.string().email({ allowUnderscore: false })).to.not.throw(); + }); + + it('validates email with underscores in domain', () => { + + const validSchema = Joi.string().email({ allowUnderscore: true }); + Helper.validate(validSchema, [ + ['user@_acme-challenge.example.com', true], + ['user@_abc.example.com', true] + ]); + + const invalidSchema = Joi.string().email(); + Helper.validate(invalidSchema, [ + ['user@_acme-challenge.example.com', false, { + message: '"value" must be a valid email', + path: [], + type: 'string.email', + context: { value: 'user@_acme-challenge.example.com', invalids: ['user@_acme-challenge.example.com'], label: 'value' } + }], + ['user@_abc.example.com', false, { + message: '"value" must be a valid email', + path: [], + type: 'string.email', + context: { value: 'user@_abc.example.com', invalids: ['user@_abc.example.com'], label: 'value' } + }] + ]); }); it('validates email', () => {