éçºè ãããŒã±ã¿ãŒãããæ±ãçåã®äžã€ã«ãå®éã«ã¡ãŒã«ãéä¿¡ããã«ã¡ãŒã«ã¢ãã¬ã¹ãæ€èšŒããããšã¯ã§ããã®ã?ããšãããã®ããããŸããããã¯æ£åœãªæžå¿µã§ããç¡å¹ãªã¢ãã¬ã¹ã«æ€èšŒã¡ãŒã«ãéä¿¡ãããšãéä¿¡è ã¬ãã¥ããŒã·ã§ã³ãå·ã€ãããªãœãŒã¹ãç¡é§ã«ãªãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæªåããå¯èœæ§ããããŸãã幞ããªããšã«ãå®éã®ã¡ãŒã«é ä¿¡ãããªã¬ãŒããã«ã¡ãŒã«ã¢ãã¬ã¹ãæ€èšŒããããã®å®èšŒæžã¿ã®æ¹æ³ãããã€ãååšããŸãã
ãã®å æ¬çãªã¬ã€ãã§ã¯ãã¡ãŒã«éä¿¡ãªãã§ã¡ãŒã«ã¢ãã¬ã¹ãæ€èšŒããããã®5ã€ã®ç°ãªãã¢ãããŒããæ¢ããŸããã·ã³ãã«ãªæ§ææ€èšŒããé«åºŠãª SMTP ãã³ãã·ã§ã€ã¯æè¡ãŸã§ãæè¡èŠä»¶ãšç²ŸåºŠããŒãºã«åã£ãå®çšçãªãœãªã¥ãŒã·ã§ã³ãã玹ä»ããŸãããµã€ã³ã¢ãããã©ãŒã ãæ§ç¯ããéçºè ã§ãããã¡ãŒã«ãªã¹ããã¯ãªãŒãã³ã°ããããŒã±ã¿ãŒã§ããã圹ç«ã€æ¹æ³ãèŠã€ããã§ãããã
ãããã®ã¡ãŒã«æ€èšŒæè¡ãçè§£ããããšã¯ãã¡ãŒã«é ä¿¡æ§ã®ç¶æã«çå£ã«åãçµããã¹ãŠã®äººã«ãšã£ãŠäžå¯æ¬ ã§ããå ç¢ãªã¡ãŒã«æ€èšŒæŠç¥ã¯ãæåã®ã¡ãã»ãŒãžãã¡ãŒã«ãµãŒããŒããéä¿¡ãããåã«ãã¡ãŒã«ã®æå¹æ§ããã§ãã¯ããæ¹æ³ãç¥ãããšããå§ãŸããŸããããã§ã¯ããããå¯èœã«ããæ¹æ³ã詳ããèŠãŠãããŸãããã
ã¡ãŒã«éä¿¡ãªãã§æ€èšŒããçç±
æè¡çãªæ¹æ³ãæ¢ãåã«ããªãã¡ãŒã«éä¿¡ãªãã§ã¡ãŒã«ãæ€èšŒããããšãããžãã¹ã«ãšã£ãŠéèŠãªã®ããçè§£ããŸãããã
éä¿¡è ã¬ãã¥ããŒã·ã§ã³ãä¿è·
éä¿¡ãããã¹ãŠã®ã¡ãŒã«ã¯ãéä¿¡è ã¬ãã¥ããŒã·ã§ã³ã¹ã³ã¢ã«åœ±é¿ãäžããŸããç¡å¹ãªã¢ãã¬ã¹ã«ã¡ãŒã«ãéä¿¡ãããšããããã¯ããŠã³ã¹ããã¯ããISP ãããã«æ°ã¥ããŸããããŠã³ã¹ãå€ããããšãã¹ãããŒã§ããå¯èœæ§ã瀺ãã·ã°ãã«ãšãªããæ£åœãªã¡ãŒã«ãã¹ãã ãã©ã«ãã«æ¯ãåãããããããã¡ã€ã³ãå®å šã«ãã©ãã¯ãªã¹ãã«ç»é²ããããããå¯èœæ§ããããŸãã
ã¡ãŒã«éä¿¡åã«ã¡ãŒã«ã¢ãã¬ã¹ãæ€èšŒããããšã§ããããã®æå®³ãªããŠã³ã¹ãçºçããã®ãé²ããŸãããã®ããã¢ã¯ãã£ããªã¢ãããŒãã¯ãéä¿¡è ã¬ãã¥ããŒã·ã§ã³ãç¶æããéèŠãªã¡ãã»ãŒãžãæå³ããåä¿¡è ã«ç¢ºå®ã«å±ãããã«ããŸãã
æéãšãªãœãŒã¹ãç¯çŽ
ã¡ãŒã«éä¿¡ã«ã¯ã³ã¹ããããããŸããESP ãéããŠã¡ãŒã«ããšã«æéãæ¯æã£ãŠããå Žåã§ããç¬èªã®ã¡ãŒã«ã€ã³ãã©ã¹ãã©ã¯ãã£ãç¶æããŠããå Žåã§ããã¡ãã»ãŒãžãåä¿¡ããããšã®ãªãã¢ãã¬ã¹ã«éä¿¡ããŠãªãœãŒã¹ãç¡é§ã«ããçç±ã¯ãããŸãããéä¿¡åæ€èšŒã¯ãç¡å¹ãªã¢ãã¬ã¹ãã¡ãŒã«ã¯ãŒã¯ãããŒã«å ¥ãåã«ãã£ã«ã¿ãªã³ã°ããããšã§ããã®ç¡é§ãæé€ããŸãã
ããã«ãããŠã³ã¹ã¡ãŒã«ã®åŠçã«ã¯åŠçèœåãšæåã¬ãã¥ãŒæéãå¿ èŠã§ããç¡å¹ãªã¡ãŒã«ãäºåã«ãã£ããããããšã§ãæ¥åãåçåããããŒã ããã䟡å€ã®ããã¿ã¹ã¯ã«éäžãããããšãã§ããŸãã
ãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãåäž
ãµã€ã³ã¢ãããã©ãŒã ã§ã¯ããªã¢ã«ã¿ã€ã ã®ã¡ãŒã«æ€èšŒã«ãããã¡ãŒã«ã¢ãã¬ã¹ãèª€å ¥åããå¯èœæ§ã®ãããŠãŒã¶ãŒã«å³åº§ã«ãã£ãŒãããã¯ãæäŸããŸãããã®å³åº§ã®ä¿®æ£ã«ããã確èªã¡ãŒã«ãåä¿¡ã§ããªããšãããã©ã¹ãã¬ãŒã·ã§ã³ãé²ãããèŠã€ãããªããæ€èšŒãªã³ã¯ã«é¢ãããµããŒããã±ãããæžããããšãã§ããŸãã
ããŒã¿å質ãç¶æ
ã¡ãŒã«ãªã¹ãã¯è²Žéãªããžãã¹è³ç£ã§ããããŒã¿ããŒã¹å ã®ãã¹ãŠã®ç¡å¹ãªã¡ãŒã«ã¢ãã¬ã¹ã¯ãåæãå°é£ã«ããã»ã°ã¡ã³ããŒã·ã§ã³ã®å¹æãäœäžããããã€ãºã衚ããŸããã¡ãŒã«éä¿¡ãªãã§ã¡ãŒã«ãæ€èšŒããããšã§ã忥ããã¯ãªãŒã³ã§æ£ç¢ºãªããŒã¿ããŒã¹ãç¶æã§ããŸãã
ããã§ã¯ãå®éã®ã¡ãã»ãŒãžãéä¿¡ããã«ã¡ãŒã«æ€èšŒãå®çŸããããã®5ã€ã®äž»èŠãªæ¹æ³ãèŠãŠãããŸãããã
æ¹æ³1:æ§ææ€èšŒ
æ§ææ€èšŒã¯ãã¡ãŒã«æ€èšŒã®æåã§æãã·ã³ãã«ãªã¬ã€ã€ãŒã§ããRFC 5321 ããã³ RFC 5322 仿§ã§å®çŸ©ãããé©åãªåœ¢åŒã«ãŒã«ã«ã¡ãŒã«ã¢ãã¬ã¹ãåŸã£ãŠãããã©ããããã§ãã¯ããŸãã
æ§ææ€èšŒããã§ãã¯ããå 容
æå¹ãªã¡ãŒã«ã¢ãã¬ã¹ã¯ãç¹å®ã®åœ¢åŒã«ãŒã«ã«åŸãå¿ èŠããããŸã:
- @ èšå·ãæ£ç¢ºã«1ã€å«ã
- åœåèŠåã«åŸã£ãããŒã«ã«éšå(@ ã®å)ãæã€
- æå¹ãªæ§é ã®ãã¡ã€ã³éšå(@ ã®åŸ)ãæã€
- èš±å¯ãããæåã®ã¿ã䜿çšãã
- é·ãå¶éãå®ã(ããŒã«ã«éšåæå€§64æåãåèšæå€§254æå)
JavaScript å®è£
ã¡ãŒã«æ§ææ€èšŒã®ããã®å®çšç㪠JavaScript 颿°ã¯æ¬¡ã®ãšããã§ã:
function validateEmailSyntax(email) {
// Trim whitespace
email = email.trim();
// Check basic length constraints
if (email.length > 254) {
return { valid: false, reason: 'Email address too long' };
}
// RFC 5322 compliant regex pattern
const emailRegex = /^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i;
if (!emailRegex.test(email)) {
return { valid: false, reason: 'Invalid email format' };
}
// Extract local part and check length
const localPart = email.split('@')[0];
if (localPart.length > 64) {
return { valid: false, reason: 'Local part too long' };
}
return { valid: true, reason: 'Syntax is valid' };
}
// Usage examples
console.log(validateEmailSyntax('user@example.com'));
// { valid: true, reason: 'Syntax is valid' }
console.log(validateEmailSyntax('invalid.email@'));
// { valid: false, reason: 'Invalid email format' }
console.log(validateEmailSyntax('user@domain'));
// { valid: false, reason: 'Invalid email format' }
äžè¬çãªãŠãŒã¹ã±ãŒã¹åãã®ç°¡ç¥åãããæ£èŠè¡šçŸ
RFC æºæ ã®æ£èŠè¡šçŸã¯å æ¬çã§ãããå€ãã®ã¢ããªã±ãŒã·ã§ã³ã¯ãæãäžè¬çãªåœ¢åŒãšã©ãŒããã£ããããããç°¡åãªãã¿ãŒã³ã䜿çšããŸã:
function simpleEmailValidation(email) {
const simpleRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return simpleRegex.test(email.trim());
}
æ§ææ€èšŒã®å¶éäºé
æ§ææ€èšŒã ãã§ã¯ãã¡ãŒã«ã¢ãã¬ã¹ãå®éã«ååšãããã©ããã倿ã§ããŸãããã¢ãã¬ã¹ definitely.fake.address@gmail.com ã¯æ§ææ€èšŒãå®å
šã«ãã¹ããŸãããGmail ã«ã¯ãã®ãããªã¢ã«ãŠã³ãã¯ãããŸããããã®ãããæ§ææ€èšŒã¯æåã®ãã§ãã¯ã§ããã¹ãã§ãããå¯äžã®ãã§ãã¯ã§ãã£ãŠã¯ãªããŸããã
粟床ã¬ãã«: çŽ30-40%(æãããªã¿ã€ããã¹ãšåœ¢åŒãšã©ãŒã®ã¿ããã£ãã)
æ¹æ³2:ãã¡ã€ã³/DNS æ€èšŒ
æ€èšŒã®ç¬¬2å±€ã¯ãã¡ãŒã«ã¢ãã¬ã¹ã®ãã¡ã€ã³éšåãå®éã«ååšããã€ã³ã¿ãŒãããäžã§é©åã«èšå®ãããŠãããã©ããããã§ãã¯ããŸãã
DNS æ€èšŒããã§ãã¯ããå 容
ãã¡ã€ã³æ€èšŒã¯ä»¥äžã確èªããŸã:
- ãã¡ã€ã³ã DNS ã«ååšãã
- ãã¡ã€ã³ãæå¹ãªã¬ã³ãŒãã«è§£æ±ºããã
- ãã¡ã€ã³ãæéåããŸãã¯æŸæ£ãããŠããªã
Node.js å®è£
Node.js ã§ DNS æ€èšŒãå®è¡ããæ¹æ³ã¯æ¬¡ã®ãšããã§ã:
const dns = require('dns').promises;
async function validateDomain(email) {
const domain = email.split('@')[1];
if (!domain) {
return { valid: false, reason: 'No domain found in email' };
}
try {
// Try to resolve the domain's A or AAAA records
const addresses = await dns.resolve(domain);
if (addresses && addresses.length > 0) {
return {
valid: true,
reason: 'Domain exists',
addresses: addresses
};
}
return { valid: false, reason: 'Domain has no DNS records' };
} catch (error) {
if (error.code === 'ENOTFOUND') {
return { valid: false, reason: 'Domain does not exist' };
}
if (error.code === 'ENODATA') {
return { valid: false, reason: 'No data for domain' };
}
return { valid: false, reason: `DNS error: ${error.message}` };
}
}
// Usage
async function checkEmail(email) {
const result = await validateDomain(email);
console.log(`${email}: ${result.reason}`);
return result;
}
checkEmail('user@google.com'); // Domain exists
checkEmail('user@thisisnotarealdomain12345.com'); // Domain does not exist
Python å®è£
import dns.resolver
def validate_domain(email):
try:
domain = email.split('@')[1]
except IndexError:
return {'valid': False, 'reason': 'Invalid email format'}
try:
# Try to resolve A records
answers = dns.resolver.resolve(domain, 'A')
return {
'valid': True,
'reason': 'Domain exists',
'addresses': [str(rdata) for rdata in answers]
}
except dns.resolver.NXDOMAIN:
return {'valid': False, 'reason': 'Domain does not exist'}
except dns.resolver.NoAnswer:
return {'valid': False, 'reason': 'No DNS records found'}
except dns.exception.Timeout:
return {'valid': False, 'reason': 'DNS query timeout'}
except Exception as e:
return {'valid': False, 'reason': f'DNS error: {str(e)}'}
# Usage
result = validate_domain('user@gmail.com')
print(result)
å¶éäºé
ãã¡ã€ã³ã¯ã¡ãŒã«ãåãå ¥ããã«ååšã§ããŸããéã«ãæå¹ãªã¡ãŒã«ãã¡ã€ã³ããããã¯ãŒã¯ã®åé¡ã«ããäžæçã« DNS 解決ã«å€±æããå¯èœæ§ããããŸãããã¡ã€ã³æ€èšŒã¯æ§æåç¬ãããä¿¡é Œæ§ãé«ãã§ãããã¡ãŒã«é ä¿¡å¯èœæ§ã確èªãããã®ã§ã¯ãããŸããã
粟床ã¬ãã«: çŽ50-60%(ååšããªããã¡ã€ã³ããã£ã«ã¿ãªã³ã°)
æ¹æ³3:MX ã¬ã³ãŒãæ€èšŒ
MX(Mail Exchange)ã¬ã³ãŒãæ€èšŒã¯ãåºæ¬çãªãã¡ã€ã³ãã§ãã¯ããã®å€§ããªã¹ãããã¢ããã§ããMX ã¬ã³ãŒãã¯ããã¡ã€ã³ã®ã¡ãŒã«ãåãå ¥ãã責任ãæã€ã¡ãŒã«ãµãŒããŒãå ·äœçã«ç€ºããŸãã
MX ã¬ã³ãŒããæããŠãããããš
DNS ã® MX ã¬ã³ãŒãã¯ä»¥äžãæå®ããŸã:
- ãã¡ã€ã³ã®åä¿¡ã¡ãŒã«ãåŠçãããµãŒããŒ
- è€æ°ã®ã¡ãŒã«ãµãŒããŒã®åªå é äœ
- ãã¡ã€ã³ãã¡ãŒã«ãåä¿¡ããããã«èšå®ãããŠãããã©ãã
MX ã¬ã³ãŒãã®ãªããã¡ã€ã³ã¯ååšããå¯èœæ§ããããŸãããã¡ãŒã«ãåä¿¡ããããšã¯ã§ããŸããã
Node.js å®è£
const dns = require('dns').promises;
async function validateMXRecords(email) {
const domain = email.split('@')[1];
if (!domain) {
return { valid: false, reason: 'No domain found' };
}
try {
const mxRecords = await dns.resolveMx(domain);
if (mxRecords && mxRecords.length > 0) {
// Sort by priority (lower number = higher priority)
mxRecords.sort((a, b) => a.priority - b.priority);
return {
valid: true,
reason: 'MX records found',
mxRecords: mxRecords.map(mx => ({
host: mx.exchange,
priority: mx.priority
}))
};
}
return { valid: false, reason: 'No MX records configured' };
} catch (error) {
if (error.code === 'ENOTFOUND') {
return { valid: false, reason: 'Domain does not exist' };
}
if (error.code === 'ENODATA') {
// Some domains use A records as fallback for email
try {
const aRecords = await dns.resolve(domain);
if (aRecords && aRecords.length > 0) {
return {
valid: true,
reason: 'No MX records, but A records exist (fallback)',
fallbackAddress: aRecords[0]
};
}
} catch {
// Ignore fallback check errors
}
return { valid: false, reason: 'No MX records and no fallback' };
}
return { valid: false, reason: `Error: ${error.message}` };
}
}
// Example usage
async function checkMX(email) {
const result = await validateMXRecords(email);
console.log(`\n${email}:`);
console.log(`Valid: ${result.valid}`);
console.log(`Reason: ${result.reason}`);
if (result.mxRecords) {
console.log('MX Records:');
result.mxRecords.forEach(mx => {
console.log(` Priority ${mx.priority}: ${mx.host}`);
});
}
return result;
}
// Test different domains
checkMX('user@gmail.com');
checkMX('user@outlook.com');
checkMX('user@fakeinvaliddomain123.com');
Python å®è£
import dns.resolver
def validate_mx_records(email):
try:
domain = email.split('@')[1]
except IndexError:
return {'valid': False, 'reason': 'Invalid email format'}
try:
mx_records = dns.resolver.resolve(domain, 'MX')
records = sorted(
[(r.preference, str(r.exchange)) for r in mx_records],
key=lambda x: x[0]
)
return {
'valid': True,
'reason': 'MX records found',
'mx_records': [{'priority': p, 'host': h} for p, h in records]
}
except dns.resolver.NXDOMAIN:
return {'valid': False, 'reason': 'Domain does not exist'}
except dns.resolver.NoAnswer:
# Check for A record fallback
try:
a_records = dns.resolver.resolve(domain, 'A')
return {
'valid': True,
'reason': 'No MX records, using A record fallback',
'fallback': str(a_records[0])
}
except:
return {'valid': False, 'reason': 'No MX records and no fallback'}
except Exception as e:
return {'valid': False, 'reason': f'Error: {str(e)}'}
# Example usage
emails = ['user@gmail.com', 'user@microsoft.com', 'user@nodomainhere.xyz']
for email in emails:
result = validate_mx_records(email)
print(f"\n{email}:")
print(f" Valid: {result['valid']}")
print(f" Reason: {result['reason']}")
if 'mx_records' in result:
for mx in result['mx_records']:
print(f" MX: {mx['priority']} - {mx['host']}")
MX ã¬ã³ãŒãçµæã®çè§£
äž»èŠãªã¡ãŒã«ãããã€ããŒã® MX ã¬ã³ãŒããã¯ãšãªãããšã次ã®ãããªçµæã衚瀺ãããŸã:
Gmail (google.com):
- Priority 5: gmail-smtp-in.l.google.com
- Priority 10: alt1.gmail-smtp-in.l.google.com
- Priority 20: alt2.gmail-smtp-in.l.google.com
Outlook (outlook.com):
- Priority 10: outlook-com.olc.protection.outlook.com
è€æ°ã® MX ã¬ã³ãŒãã¯åé·æ§ãæäŸããŸãã1ã€ã®ã¡ãŒã«ãµãŒããŒãããŠã³ããŠããå Žåãã¡ãã»ãŒãžã¯ããã¯ã¢ãããµãŒããŒã«ã«ãŒãã£ã³ã°ãããŸãã
粟床ã¬ãã«: çŽ70-75%(ãã¡ã€ã³ãã¡ãŒã«ãåä¿¡ã§ããããšã確èª)
æ¹æ³4:SMTP ãã³ãã·ã§ã€ã¯æ€èšŒ
SMTP ãã³ãã·ã§ã€ã¯æ€èšŒã¯ãã¡ãŒã«éä¿¡ãªãã§ã¡ãŒã«ã®ååšããã§ãã¯ããããã®æãé«åºŠãªæ¹æ³ã§ããã¡ãŒã«é ä¿¡ããã»ã¹ã®éå§ãã·ãã¥ã¬ãŒãããå®éã«ã¡ãã»ãŒãžãéä¿¡ããçŽåã§åæ¢ããŸãã
SMTP æ€èšŒã®ä»çµã¿
SMTP ãããã³ã«ã¯ãã¡ãŒã«é ä¿¡ã®ããã®ç¹å®ã®ã·ãŒã±ã³ã¹ã«åŸããŸããSMTP æ€èšŒã¯åææ®µéãå®è¡ããŸã:
- æ¥ç¶ - ã¡ãŒã«ãµãŒããŒã«æ¥ç¶(éåžžã¯ããŒã25)
- HELO/EHLO - ã¡ãŒã«ãµãŒããŒã«èªåãèå¥
- MAIL FROM - éä¿¡è ã¢ãã¬ã¹ãæå®
- RCPT TO - åä¿¡è ãæå®(æ€èšŒããã¢ãã¬ã¹)
- å¿çãåæ - ãµãŒããŒã®å¿çãåä¿¡è ã®ååšã瀺ã
ã¡ãŒã«ãµãŒããŒã RCPT TO ã³ãã³ããåãå ¥ããå Žå(å¿çã³ãŒã250)ãã¡ãŒã«ã¢ãã¬ã¹ã¯ååšããå¯èœæ§ãé«ãã§ããæåŠ(5xx å¿ç)ã¯éåžžãã¢ãã¬ã¹ãç¡å¹ã§ããããšãæå³ããŸãã
Node.js å®è£
const net = require('net');
const dns = require('dns').promises;
class SMTPVerifier {
constructor(timeout = 10000) {
this.timeout = timeout;
}
async verify(email) {
const domain = email.split('@')[1];
// First, get MX records
let mxHost;
try {
const mxRecords = await dns.resolveMx(domain);
mxRecords.sort((a, b) => a.priority - b.priority);
mxHost = mxRecords[0].exchange;
} catch (error) {
return {
valid: false,
reason: 'Could not resolve MX records',
email
};
}
return new Promise((resolve) => {
const socket = new net.Socket();
let step = 0;
let response = '';
const commands = [
null, // Initial server greeting
'EHLO verify.local\r\n',
'MAIL FROM:<verify@verify.local>\r\n',
`RCPT TO:<${email}>\r\n`,
'QUIT\r\n'
];
socket.setTimeout(this.timeout);
socket.on('connect', () => {
console.log(`Connected to ${mxHost}`);
});
socket.on('data', (data) => {
response = data.toString();
const code = parseInt(response.substring(0, 3));
console.log(`Step ${step}: ${response.trim()}`);
// Handle each step
if (step === 0) {
// Server greeting - expect 220
if (code === 220) {
socket.write(commands[1]);
step++;
} else {
resolve({ valid: false, reason: 'Server rejected connection', email });
socket.destroy();
}
} else if (step === 1) {
// EHLO response - expect 250
if (code === 250) {
socket.write(commands[2]);
step++;
} else {
resolve({ valid: false, reason: 'EHLO rejected', email });
socket.destroy();
}
} else if (step === 2) {
// MAIL FROM response - expect 250
if (code === 250) {
socket.write(commands[3]);
step++;
} else {
resolve({ valid: false, reason: 'MAIL FROM rejected', email });
socket.destroy();
}
} else if (step === 3) {
// RCPT TO response - this is the verification result
socket.write(commands[4]);
if (code === 250) {
resolve({ valid: true, reason: 'Email address exists', email });
} else if (code === 550 || code === 551 || code === 553) {
resolve({ valid: false, reason: 'Email address does not exist', email });
} else if (code === 452 || code === 421) {
resolve({ valid: null, reason: 'Server temporarily unavailable', email });
} else {
resolve({ valid: null, reason: `Uncertain: ${response.trim()}`, email });
}
socket.destroy();
}
});
socket.on('timeout', () => {
resolve({ valid: null, reason: 'Connection timeout', email });
socket.destroy();
});
socket.on('error', (error) => {
resolve({ valid: null, reason: `Socket error: ${error.message}`, email });
socket.destroy();
});
// Connect to mail server
socket.connect(25, mxHost);
});
}
}
// Usage
async function verifyEmail(email) {
const verifier = new SMTPVerifier();
const result = await verifier.verify(email);
console.log(`\nResult for ${email}:`);
console.log(`Valid: ${result.valid}`);
console.log(`Reason: ${result.reason}`);
return result;
}
verifyEmail('test@example.com');
Python å®è£
import socket
import dns.resolver
class SMTPVerifier:
def __init__(self, timeout=10):
self.timeout = timeout
def get_mx_host(self, domain):
"""Get the primary MX host for a domain."""
try:
records = dns.resolver.resolve(domain, 'MX')
mx_records = sorted(
[(r.preference, str(r.exchange).rstrip('.')) for r in records],
key=lambda x: x[0]
)
return mx_records[0][1]
except Exception as e:
return None
def verify(self, email):
"""Verify an email address via SMTP handshake."""
try:
domain = email.split('@')[1]
except IndexError:
return {'valid': False, 'reason': 'Invalid email format'}
mx_host = self.get_mx_host(domain)
if not mx_host:
return {'valid': False, 'reason': 'Could not resolve MX records'}
try:
# Connect to mail server
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(self.timeout)
sock.connect((mx_host, 25))
# Receive greeting
response = sock.recv(1024).decode()
if not response.startswith('220'):
return {'valid': False, 'reason': 'Server rejected connection'}
# Send EHLO
sock.send(b'EHLO verify.local\r\n')
response = sock.recv(1024).decode()
if not response.startswith('250'):
return {'valid': False, 'reason': 'EHLO rejected'}
# Send MAIL FROM
sock.send(b'MAIL FROM:<verify@verify.local>\r\n')
response = sock.recv(1024).decode()
if not response.startswith('250'):
return {'valid': False, 'reason': 'MAIL FROM rejected'}
# Send RCPT TO - this is the verification
sock.send(f'RCPT TO:<{email}>\r\n'.encode())
response = sock.recv(1024).decode()
code = int(response[:3])
# Close connection
sock.send(b'QUIT\r\n')
sock.close()
# Analyze response
if code == 250:
return {'valid': True, 'reason': 'Email address exists'}
elif code in [550, 551, 553]:
return {'valid': False, 'reason': 'Email address does not exist'}
elif code in [452, 421]:
return {'valid': None, 'reason': 'Server temporarily unavailable'}
else:
return {'valid': None, 'reason': f'Uncertain response: {response}'}
except socket.timeout:
return {'valid': None, 'reason': 'Connection timeout'}
except socket.error as e:
return {'valid': None, 'reason': f'Socket error: {str(e)}'}
except Exception as e:
return {'valid': None, 'reason': f'Error: {str(e)}'}
# Usage
verifier = SMTPVerifier()
result = verifier.verify('test@example.com')
print(f"Valid: {result['valid']}")
print(f"Reason: {result['reason']}")
SMTP å¿çã³ãŒãã®èª¬æ
æ€èšŒçµæãè§£éããã«ã¯ãSMTP å¿çã³ãŒããçè§£ããããšãéèŠã§ã:
| ã³ãŒã | æå³ | è§£é |
|---|---|---|
| 250 | OK | ã¡ãŒã«ã¢ãã¬ã¹ãååšããã¡ãŒã«ãåãå ¥ãã |
| 251 | ãŠãŒã¶ãŒãããŒã«ã«ã«ããªã | å¥ã®ã¢ãã¬ã¹ã«è»¢éããã |
| 450 | ã¡ãŒã«ããã¯ã¹å©çšäžå¯ | äžæçãªåé¡ãåŸã§åè©Šè¡ |
| 451 | ããŒã«ã«ãšã©ãŒ | ãµãŒããŒåŽã®åé¡ |
| 452 | ã¹ãã¬ãŒãžäžè¶³ | ã¡ãŒã«ããã¯ã¹ããã£ã±ã |
| 550 | ã¡ãŒã«ããã¯ã¹ãèŠã€ãããªã | ã¡ãŒã«ã¢ãã¬ã¹ãååšããªã |
| 551 | ãŠãŒã¶ãŒãããŒã«ã«ã«ããªã | 転éãèšå®ãããŠããªã |
| 553 | ã¡ãŒã«ããã¯ã¹åãç¡å¹ | ã¡ãŒã«ããã¯ã¹åã®æ§æãšã©ãŒ |
éèŠãªå¶éäºé
SMTP æ€èšŒã«ã¯ããã€ãã®éèŠãªå¶éããããŸã:
ãã£ãããªãŒã«ãã¡ã€ã³: äžéšã®ã¡ãŒã«ãµãŒããŒã¯ãååšãããã©ããã«é¢ä¿ãªããã¹ãŠã®ã¢ãã¬ã¹ãåãå ¥ãããã¹ãŠã«å¯ŸããŠ250ãè¿ããŸãããããã®ããã£ãããªãŒã«ãèšå®ã¯ SMTP æ€èšŒãç¡å¹ã«ããŸãã
ã°ã¬ã€ãªã¹ãã£ã³ã°: ãµãŒããŒã¯æªç¥ã®éä¿¡è ããã®ã¡ãã»ãŒãžãäžæçã«æåŠããå ŽåããããŸããæ€èšŒãæåŠãããŠããå詊è¡ãããšæåããå¯èœæ§ããããŸãã
ã¬ãŒãå¶é: ã¡ãŒã«ãµãŒããŒã¯æ¥ç¶è©Šè¡ãå¶éããããšããããããŸããå€§éæ€èšŒã¯ãããã¯ãããªã¬ãŒããå¯èœæ§ããããŸãã
IP ã¬ãã¥ããŒã·ã§ã³: æ€èšŒãµãŒããŒã® IP ã¬ãã¥ããŒã·ã§ã³ã¯ãã¡ãŒã«ãµãŒããŒãæ£çŽã«å¿çãããã©ããã«åœ±é¿ããŸãã
ãã¡ã€ã¢ãŠã©ãŒã«å¶é: å€ãã®ãããã¯ãŒã¯ã¯ãã»ãã¥ãªãã£äžã®çç±ããããŒã25ã§ã®éä¿¡ SMTP ãã©ãã£ãã¯ããããã¯ããŸãã
粟床ã¬ãã«: çŽ85-90%(ãµãŒããŒãæ£çŽã«å¿çããå Žå)
æ¹æ³5:ã¡ãŒã«æ€èšŒ API ãµãŒãã¹
æ¬çªã¢ããªã±ãŒã·ã§ã³ã«ã¯ããããã§ãã·ã§ãã«ãªã¡ãŒã«æ€èšŒ API ã䜿çšããããšãã粟床ãé床ãä¿¡é Œæ§ã®æé©ãªãã©ã³ã¹ãæäŸããŸããBillionVerify ã®ãããªãµãŒãã¹ã¯ããã«ãã¡ãœããæ€èšŒã®ãã¹ãŠã®è€éããåŠçããªãããåã ã®æ¹æ³ã§ã¯éæã§ããªã远å ã®ãã§ãã¯ãæäŸããŸãã
API ããŒã¹æ€èšŒã®å©ç¹
é«ç²ŸåºŠ: ãããã§ãã·ã§ãã«ãµãŒãã¹ã¯ããã¹ãŠã®æ€èšŒæ¹æ³(æ§æãDNSãMXãSMTP)ããäœ¿ãæšãŠã¡ãŒã«æ€åºã圹å²ããŒã¹ã¢ãã¬ã¹èå¥ããã£ãããªãŒã«ãã¡ã€ã³åŠçãªã©ã®è¿œå ã€ã³ããªãžã§ã³ã¹ãšçµã¿åãããŸãã
åªããã€ã³ãã©ã¹ãã©ã¯ãã£: API ãµãŒãã¹ã¯ã匷åãªã¬ãã¥ããŒã·ã§ã³ãæã€å°çš IP ããŒã«ãããé«éãªã°ããŒãã«å¿çã®ããã®åæ£ãµãŒããŒãäž»èŠãªã¡ãŒã«ãããã€ããŒãšã®çŽæ¥çãªé¢ä¿ãç¶æããŠããŸãã
ã¡ã³ããã³ã¹äžèŠ: SMTP æ€èšŒã³ãŒããç¶æãããããšããžã±ãŒã¹ãåŠçããããæ€èšŒãµãŒããŒããããã¯ãããããšãå¿é ãããããå¿ èŠã¯ãããŸããã
ã¹ã±ãŒã©ããªãã£: API ã¯ãã€ã³ãã©ã¹ãã©ã¯ãã£ã®æžå¿µãªãã«æ°çŸäžã®æ€èšŒãåŠçããŸãã
BillionVerify API çµ±å
ã¡ãŒã«æ€èšŒã®ããã« BillionVerify API ãçµ±åããæ¹æ³ã¯æ¬¡ã®ãšããã§ã:
Node.js ã®äŸ:
const axios = require('axios');
const BILLIONVERIFY_API_KEY = 'your_api_key_here';
const API_URL = 'https://api.billionverify.com/v1';
async function verifyEmailWithAPI(email) {
try {
const response = await axios.post(
`${API_URL}/verify`,
{ email },
{
headers: {
'Authorization': `Bearer ${BILLIONVERIFY_API_KEY}`,
'Content-Type': 'application/json'
}
}
);
const result = response.data;
return {
email: result.email,
valid: result.deliverable,
status: result.status,
details: {
syntaxValid: result.syntax_valid,
domainExists: result.domain_exists,
mxRecords: result.mx_found,
smtpCheck: result.smtp_check,
disposable: result.is_disposable,
roleAddress: result.is_role_address,
catchAll: result.is_catch_all,
freeProvider: result.is_free_provider
},
score: result.quality_score
};
} catch (error) {
console.error('API Error:', error.response?.data || error.message);
throw error;
}
}
// Usage
async function main() {
const emails = [
'valid.user@gmail.com',
'fake.address@company.com',
'temp@10minutemail.com'
];
for (const email of emails) {
const result = await verifyEmailWithAPI(email);
console.log(`\n${email}:`);
console.log(` Deliverable: ${result.valid}`);
console.log(` Status: ${result.status}`);
console.log(` Quality Score: ${result.score}`);
console.log(` Disposable: ${result.details.disposable}`);
console.log(` Catch-All: ${result.details.catchAll}`);
}
}
main();
Python ã®äŸ:
import requests
BILLIONVERIFY_API_KEY = 'your_api_key_here'
API_URL = 'https://api.billionverify.com/v1'
def verify_email_with_api(email):
"""Verify an email address using BillionVerify API."""
headers = {
'Authorization': f'Bearer {BILLIONVERIFY_API_KEY}',
'Content-Type': 'application/json'
}
response = requests.post(
f'{API_URL}/verify',
json={'email': email},
headers=headers
)
if response.status_code != 200:
raise Exception(f'API Error: {response.text}')
result = response.json()
return {
'email': result['email'],
'valid': result['deliverable'],
'status': result['status'],
'details': {
'syntax_valid': result['syntax_valid'],
'domain_exists': result['domain_exists'],
'mx_records': result['mx_found'],
'smtp_check': result['smtp_check'],
'disposable': result['is_disposable'],
'role_address': result['is_role_address'],
'catch_all': result['is_catch_all'],
'free_provider': result['is_free_provider']
},
'score': result['quality_score']
}
# Usage
emails = ['user@gmail.com', 'contact@company.com', 'test@tempmail.com']
for email in emails:
try:
result = verify_email_with_api(email)
print(f"\n{email}:")
print(f" Deliverable: {result['valid']}")
print(f" Status: {result['status']}")
print(f" Quality Score: {result['score']}")
except Exception as e:
print(f"Error verifying {email}: {e}")
ãªã¢ã«ã¿ã€ã ãã©ãŒã çµ±å
ãµã€ã³ã¢ãããã©ãŒã ã§ã¯ãBillionVerify ã¯ãŠãŒã¶ãŒãå ¥åããŠããéã«ã¡ãŒã«ã¢ãã¬ã¹ãæ€èšŒã§ãããªã¢ã«ã¿ã€ã æ€èšŒãæäŸããŸã:
// React component example
import { useState, useCallback } from 'react';
import debounce from 'lodash/debounce';
function EmailInput() {
const [email, setEmail] = useState('');
const [validation, setValidation] = useState(null);
const [loading, setLoading] = useState(false);
const verifyEmail = useCallback(
debounce(async (emailToVerify) => {
if (!emailToVerify || emailToVerify.length < 5) return;
setLoading(true);
try {
const response = await fetch('/api/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: emailToVerify })
});
const result = await response.json();
setValidation(result);
} catch (error) {
console.error('Verification failed:', error);
} finally {
setLoading(false);
}
}, 500),
[]
);
const handleChange = (e) => {
const newEmail = e.target.value;
setEmail(newEmail);
verifyEmail(newEmail);
};
return (
<div className="email-input-wrapper">
<input
type="email"
value={email}
onChange={handleChange}
placeholder="Enter your email"
className={validation?.valid === false ? 'invalid' : ''}
/>
{loading && <span className="loading">Verifying...</span>}
{validation && !loading && (
<span className={validation.valid ? 'valid' : 'invalid'}>
{validation.valid ? 'â Valid email' : 'â ' + validation.reason}
</span>
)}
</div>
);
}
粟床ã¬ãã«: 97-99%以äž(ãã¹ãŠã®æ¹æ³ã远å ã€ã³ããªãžã§ã³ã¹ãšçµã¿åãã)
æ¹æ³ã®æ¯èŒ:é©åãªã¢ãããŒãã®éžæ
ããŒãºã«åã£ãé©åãªæ€èšŒæ¹æ³ãéžæããããã®å æ¬çãªæ¯èŒã¯æ¬¡ã®ãšããã§ã:
| æ¹æ³ | 粟床 | é床 | è€éã | ã³ã¹ã | æé©ãªçšé |
|---|---|---|---|---|---|
| æ§ææ€èšŒ | 30-40% | å³åº§ | äœ | ç¡æ | 第äžç·ãã£ã«ã¿ãªã³ã° |
| ãã¡ã€ã³/DNS ãã§ã㯠| 50-60% | é«é | äœ | ç¡æ | ã¯ã€ãã¯ãã¬ãã§ã㯠|
| MX ã¬ã³ãŒãæ€èšŒ | 70-75% | é«é | äž | ç¡æ | ãã©ãŒã æ€èšŒ |
| SMTP ãã³ãã·ã§ã€ã¯ | 85-90% | é ã | é« | ã€ã³ãã© | ãããã¯ãªãŒãã³ã° |
| API ãµãŒãã¹ | 97-99% | é«é | äœ | ã¯ãšãªæ¯ | æ¬çªã·ã¹ãã |
ãŠãŒã¹ã±ãŒã¹å¥ã®æšå¥šäºé
ãµã€ã³ã¢ãããã©ãŒã : å³åº§ã®ãã£ãŒãããã¯ã®ããã«ã¯ã©ã€ã¢ã³ãåŽã®æ§ææ€èšŒãšãéä¿¡æã® API æ€èšŒãçµã¿åãããŠäœ¿çšããŸããããã«ãããããŒã¿å質ã確ä¿ããªãããã¹ã ãŒãºãªãŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸããŸãã
ã¡ãŒã«ããŒã±ãã£ã³ã°ãã£ã³ããŒã³: éä¿¡åã«äžæ¬æ€èšŒã®ããã« API ãµãŒãã¹ã䜿çšããŸããæ€èšŒãããã®ã³ã¹ãã¯ãé«ãããŠã³ã¹çã«ããæå®³ãããã¯ããã«å°ãªãã§ãã
ããŒã¿ã¯ãªãŒãã³ã°ãããžã§ã¯ã: äžæ¬ã¢ããããŒãæ©èœãåãã API ãµãŒãã¹ã¯ãæ¢åã®ãªã¹ããã¯ãªãŒãã³ã°ããããã®ç²ŸåºŠãšå¹çã®æé©ãªãã©ã³ã¹ãæäŸããŸãã
éçº/ãã¹ã: æ§æãš MX æ€èšŒã¯ãå®ç§ãªç²ŸåºŠãéèŠã§ãªãéçºç°å¢ã«é©åãªç²ŸåºŠãæäŸããŸãã
ã¡ãŒã«æ€èšŒã®ãã¹ããã©ã¯ãã£ã¹
è€æ°ã®ã¬ã€ã€ãŒãå®è£
åäžã®æ€èšŒæ¹æ³ã«é Œããªãã§ãã ãããéå±€åãããã¢ãããŒããå®è£ ããŸã:
- å³åº§: ã¯ã©ã€ã¢ã³ãåŽã§ã®æ§ææ€èšŒ
- éä¿¡æ: ã¯ã€ãã¯ãµãŒããŒåŽæ€èšŒã®ããã® MX ã¬ã³ãŒããã§ãã¯
- ãã£ã³ããŒã³å: é ä¿¡å¯èœæ§ç¢ºèªã®ããã®å®å šãª API æ€èšŒ
ãšããžã±ãŒã¹ãé©åã«åŠç
äžéšã®æ€èšŒçµæã¯æ±ºå®çã§ã¯ãããŸãã(ãã£ãããªãŒã«ãã¡ã€ã³ãäžæçãªé害)ãã·ã¹ãã ãæ¬¡ã®ããã«èšèšããŸã:
- äžç¢ºå®ãªæ€èšŒçµæãæã€ã¢ãã¬ã¹ãåãå ¥ããããã¬ãã¥ãŒã®ããã«ãã©ã°ãç«ãŠã
- äžæçãªé害ã«å¯Ÿããå詊è¡ããžãã¯ãå®è£ ãã
- ãã¿ãŒã³ãèå¥ããããã«æ€èšŒçµæã远跡ãã
é©åãªã¿ã€ãã³ã°ã§æ€èšŒ
- ç»é²: ã¢ã«ãŠã³ãäœæåã«æ€èšŒ
- ã€ã³ããŒã: å€éšãœãŒã¹ãããªã¹ããã€ã³ããŒãããéã«æ€èšŒ
- 宿ç: åãšã³ã²ãŒãžã¡ã³ããã£ã³ããŒã³åã«äŒç ã¢ãã¬ã¹ãåæ€èšŒ
- å€§èŠæš¡éä¿¡å: å€§èŠæš¡ãã£ã³ããŒã³åã«åžžã«æ€èšŒ
ã¬ãŒãå¶éãå°é
ç¬èªã® SMTP æ€èšŒã䜿çšããå Žåã§ã API ã䜿çšããå Žåã§ããã¡ãŒã«ãµãŒããŒããµãŒãã¹ãããã€ããŒãšã®è¯å¥œãªé¢ä¿ãç¶æããããã«ã¬ãŒãå¶éãå°éããŠãã ããã
ãŸãšã
å®éã«ã¡ãŒã«ãéä¿¡ããã«ã¡ãŒã«ã¢ãã¬ã¹ãæ€èšŒããããšã¯ãå¯èœã§ããã ãã§ãªããã¡ãŒã«é ä¿¡å¯èœæ§ãšéä¿¡è ã¬ãã¥ããŒã·ã§ã³ãç¶æããããã«äžå¯æ¬ ã§ããã·ã³ãã«ãªæ§æãã§ãã¯ããé«åºŠãª API ããŒã¹ã®æ€èšŒãŸã§ã粟床èŠä»¶ãšæè¡çèœåã«å¿ããŠè€æ°ã®ãªãã·ã§ã³ããããŸãã
ã»ãšãã©ã®æ¬çªã¢ããªã±ãŒã·ã§ã³ã«ã¯ã次ã®ããšããå§ãããŸã:
- ã·ã³ãã«ã«å§ãã: å³åº§ã®ãã£ãŒãããã¯ã®ããã«æ§ææ€èšŒãå®è£
- æ·±ãã远å : ãµãŒããŒåŽæ€èšŒã®ããã« DNS ãš MX ãã§ãã¯ãå«ãã
- ãããã§ãã·ã§ãã«ã«é²ã: æ¬çªåè³ªã®æ€èšŒã®ããã« BillionVerify ã®ãã㪠API ãµãŒãã¹ã䜿çš
ãããã§ãã·ã§ãã«ãªã¡ãŒã«æ€èšŒãå®è£ ããæºåã¯ã§ããŸããã?åœç€Ÿã®ã¡ãŒã«ãã§ãã«ãŒããŒã«ã§æ€èšŒã®åäœã確èªããããã¢ããªã±ãŒã·ã§ã³ãžã®ã·ãŒã ã¬ã¹ãªçµ±åã®ããã« BillionVerify API ãæ¢çŽ¢ããŠãã ããã
é©åãªã¡ãŒã«æ€èšŒãå®è£ ããããšã§ãéä¿¡è ã¬ãã¥ããŒã·ã§ã³ãä¿è·ããé ä¿¡çãåäžãããã¡ãã»ãŒãžãåä¿¡ããã人ã«ç¢ºå®ã«å±ããããšãã§ããŸãã仿¥ããããã¹ããŒããªæ€èšŒãå§ããŸãããã