The following snippet checks email addresses using the URL interface and if it looks ok does a DNS lookup for the related MX record. It fully supports internationalized and valid character sets. The DNS lookup should work in browsers and Cloudflare workers, and the commented segment in Deno.
async function validEmail(address, checkDomain=false){
const emailPattern = /^[^@]{1,64}@[a-z0-9][a-z0-9\.-]{3,252}$/i;
let email, valid = false, error, same = false, domain;
try{
// URL handles punycode, etc using browser implementation
const url = new URL(`http://${ address }`);
const { username, hostname } = url;
email = `${username}@${hostname}`;
same = address === email;
valid = emailPattern.test( email );
if(!valid) throw new Error(`invalid email ${ email }`);
if(checkDomain){
// function hasMX(dns){ return dns?.[0]?.exchange ? true: false; }
// domain = await Deno.resolveDns(hostname, 'MX').then(hasMX).catch(hasMX);
function hasMX(dns){ return dns?.Answer?.[0]?.data ? true: false; }
domain = await fetch(`https://cloudflare-dns.com/dns-query?name=${ hostname }&type=MX`, {headers:{Accept: "application/dns-json"}}).then(res=>res.json()).then(hasMX).catch(hasMX);
}
}catch(fail){
error = fail;
};
return {email, same, valid, error, domain};
}
[
'user+this@はじめよう.みんな'
, 'stuff@things.eu'
, 'stuff@things'
, 'user+that@host.com'
, 'Jean+François@anydomain.museum','هيا@יאללה'
, '试@例子.测试.مثال.آزمایشی'
, 'not@@really'
, 'no'
].forEach(async address=>{
let result = await validEmail(address);
console.log(result, address);
});
[
'someone@dev.to'
].forEach(async address=>{
let result = await validEmail(address, true);
console.log(result, address);
});
Top comments (0)