better logging in order to investigate later one on this kind of error (#12326)

# extracting domain emails

Added new test cases covering weird but valid email formats (plus
addressing, subdomains, international domains, etc.) to identify
potential failures in the current implementation.

Two tests with quoted local parts containing @ symbols or quotes are
marked as skipped since they're expected to fail with the current simple
string splitting approach. They are too exotic IMO, we should throw
errors.

## Next
We will monitor errors related to this and update accordingly later on.


### Note 
technically, quotes are possible in RFC see
[here](https://stackoverflow.com/questions/4816424/are-single-quotes-legal-in-the-name-part-of-an-email-address)

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Guillim
2025-05-27 18:10:48 +02:00
committed by GitHub
parent f210d274bf
commit 017940b2cb
4 changed files with 57 additions and 4 deletions

View File

@ -24,4 +24,53 @@ describe('getDomainNameByEmail', () => {
it('should throw an error if domain part is empty', () => {
expect(() => getDomainNameByEmail('user@')).toThrow('Invalid email format');
});
// Edge cases with weird but potentially valid email formats
it('should handle email with plus addressing', () => {
expect(getDomainNameByEmail('user+tag@example.com')).toBe('example.com');
});
it('should handle email with dots in local part', () => {
expect(getDomainNameByEmail('user.name@example.com')).toBe('example.com');
});
it('should handle email with subdomain', () => {
expect(getDomainNameByEmail('user@mail.example.com')).toBe(
'mail.example.com',
);
});
it('should handle email with numeric domain', () => {
expect(getDomainNameByEmail('user@123.456.1.2')).toBe('123.456.1.2');
});
it('should handle email with hyphenated domain', () => {
expect(getDomainNameByEmail('user@my-domain.com')).toBe('my-domain.com');
});
it('should handle email with international domain (punycode)', () => {
expect(getDomainNameByEmail('user@xn--nxasmq6b.com')).toBe(
'xn--nxasmq6b.com',
);
});
it('should handle email with very long domain', () => {
const longDomain = 'a'.repeat(160) + '.com';
expect(getDomainNameByEmail(`user@${longDomain}`)).toBe(longDomain);
});
it('should handle email with quoted local part containing spaces', () => {
expect(getDomainNameByEmail('"user name"@example.com')).toBe('example.com');
});
xit('should handle email with special characters in quoted local part', () => {
expect(getDomainNameByEmail('"user@#$%"@example.com')).toBe('example.com');
});
xit('should handle email with quoted local part containing @', () => {
expect(getDomainNameByEmail('"user@local"@example.com')).toBe(
'example.com',
);
});
});

View File

@ -1,18 +1,20 @@
import { isNonEmptyString } from '@sniptt/guards';
export const getDomainNameByEmail = (email: string) => {
if (!email) {
if (!isNonEmptyString(email)) {
throw new Error('Email is required');
}
const fields = email.split('@');
if (fields.length !== 2) {
throw new Error('Invalid email format');
throw new Error(`Invalid email format (${fields.length - 1} @) ${email}`);
}
const domain = fields[1];
if (!domain) {
throw new Error('Invalid email format');
throw new Error(`Invalid email format (no domain) ${email}`);
}
return domain;