Проверка email без отправки: технический гайд

Leo
LeoFounder, BillionVerify

Проверка email без отправки писем: валидация синтаксиса, DNS-проверки, MX-записи и SMTP-рукопожатие.

Cover Image for Проверка email без отправки: технический гайд

Один из самых распространённых вопросов, которые задают разработчики и маркетологи: "Как проверить email-адрес, не отправляя на него письмо?" Это обоснованная озабоченность — отправка проверочных писем на потенциально недействительные адреса может навредить репутации отправителя, израсходовать ресурсы и создать плохой пользовательский опыт. К счастью, существует несколько проверенных методов валидации email-адресов без инициирования фактической доставки письма.

В этом всеобъемлющем руководстве мы рассмотрим пять различных подходов к проверке email-адресов без отправки, начиная от простой синтаксической валидации и заканчивая сложными техниками SMTP-рукопожатия. Независимо от того, являетесь ли вы разработчиком, создающим форму регистрации, или маркетологом, очищающим свой список рассылки, вы найдёте практические решения, соответствующие вашим техническим требованиям и потребностям в точности.

Понимание этих техник проверки email критически важно для всех, кто серьёзно относится к поддержанию доставляемости писем. Надёжная стратегия верификации email начинается со знания того, как проверить валидность email-адреса ещё до того, как ваше первое сообщение покинет почтовый сервер. Давайте погрузимся в методы, которые делают это возможным.

Зачем проверять email без отправки?

Прежде чем мы рассмотрим технические методы, давайте разберёмся, почему верификация email без отправки важна для вашего бизнеса:

Защита репутации отправителя

Каждое отправляемое вами письмо влияет на оценку репутации отправителя. Когда вы отправляете письма на недействительные адреса, они возвращаются обратно, и интернет-провайдеры это замечают. Слишком много возвратов сигнализирует почтовым провайдерам, что вы можете быть спамером, что может отправить ваши легитимные письма в папку спама или полностью внести ваш домен в чёрный список.

Проверяя email-адреса перед отправкой, вы предотвращаете возникновение этих разрушительных возвратов. Этот проактивный подход сохраняет вашу репутацию отправителя и гарантирует, что ваши важные сообщения достигнут предполагаемых получателей.

Экономия времени и ресурсов

Отправка писем стоит денег — независимо от того, платите ли вы за каждое письмо через ESP или поддерживаете собственную email-инфраструктуру. Зачем тратить ресурсы на отправку адресам, которые никогда не получат ваше сообщение? Предварительная верификация устраняет эти потери, отфильтровывая недействительные адреса до их попадания в ваш email-workflow.

Кроме того, обработка возвращённых писем требует вычислительной мощности и времени на ручную проверку. Выявляя недействительные email-адреса заранее, вы оптимизируете свои операции и позволяете команде сосредоточиться на более ценных задачах.

Улучшение пользовательского опыта

В формах регистрации валидация email в реальном времени предоставляет немедленную обратную связь пользователям, которые могли опечататься при вводе своего email-адреса. Эта мгновенная коррекция предотвращает разочарование от неполучения подтверждающих писем и уменьшает количество обращений в поддержку о "пропавших" ссылках верификации.

Поддержание качества данных

Ваш список рассылки — это ценный бизнес-актив. Каждый недействительный email-адрес в вашей базе данных представляет шум, который затрудняет анализ и делает сегментацию менее эффективной. Проверка email без отправки помогает поддерживать чистую, точную базу данных с первого дня.

Теперь давайте рассмотрим пять основных методов достижения верификации email без отправки реальных сообщений.

Метод 1: Синтаксическая валидация

Синтаксическая валидация — это первый и самый простой уровень проверки email. Она проверяет, соответствует ли email-адрес правильным правилам форматирования, определённым спецификациями RFC 5321 и RFC 5322.

Что проверяет синтаксическая валидация

Валидный email-адрес должен следовать определённым правилам форматирования:

  • Содержит ровно один символ @
  • Имеет локальную часть (до @), которая следует соглашениям по именованию
  • Имеет доменную часть (после @) с валидной структурой
  • Использует только разрешённые символы
  • Соблюдает ограничения по длине (локальная часть максимум 64 символа, общая длина максимум 254 символа)

Реализация на JavaScript

Вот практическая JavaScript-функция для синтаксической валидации email:

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());
}

Ограничения синтаксической валидации

Синтаксическая валидация сама по себе не может определить, существует ли email-адрес на самом деле. Адрес definitely.fake.address@gmail.com идеально проходит синтаксическую валидацию, но в Gmail нет такой учётной записи. По этой причине синтаксическая валидация должна быть вашей первой проверкой, но не единственной.

Уровень точности: ~30-40% (отлавливает только очевидные опечатки и ошибки форматирования)

Метод 2: Валидация домена/DNS

Второй уровень верификации проверяет, действительно ли существует доменная часть email-адреса и правильно ли она настроена в интернете.

Что проверяет DNS-валидация

Валидация домена проверяет, что:

  • Домен существует в DNS
  • Домен разрешается в валидные записи
  • Домен не истёк и не заброшен

Реализация на Node.js

Вот как выполнить DNS-валидацию в Node.js:

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)

Ограничения

Домен может существовать без приёма email. И наоборот, валидный email-домен может временно не проходить разрешение DNS из-за сетевых проблем. Валидация домена обеспечивает большую уверенность, чем только синтаксическая проверка, но не подтверждает доставляемость email.

Уровень точности: ~50-60% (фильтрует несуществующие домены)

Метод 3: Валидация MX-записей

Валидация MX (Mail Exchange) записей — это значительный шаг вперёд по сравнению с базовой проверкой домена. MX-записи конкретно указывают, какие почтовые серверы отвечают за приём email для домена.

Что нам говорят MX-записи

MX-записи в DNS указывают:

  • Какие серверы обрабатывают входящую почту для домена
  • Порядок приоритета нескольких почтовых серверов
  • Настроен ли домен вообще для приёма email

Домен без MX-записей может всё ещё существовать, но не может принимать email.

Реализация на 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-записи для основных email-провайдеров, вы увидите результаты, подобные этим:

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-записи обеспечивают избыточность — если один почтовый сервер недоступен, сообщения направляются на резервный сервер.

Уровень точности: ~70-75% (подтверждает, что домен может принимать email)

Метод 4: Верификация через SMTP-рукопожатие

Верификация через SMTP-рукопожатие — это самый сложный метод проверки существования email без отправки. Он имитирует начало процесса доставки email, останавливаясь непосредственно перед передачей сообщения.

Как работает SMTP-верификация

Протокол SMTP следует определённой последовательности для доставки email. SMTP-верификация выполняет ранние стадии:

  1. Подключение к почтовому серверу (обычно порт 25)
  2. HELO/EHLO - Идентификация себя почтовому серверу
  3. MAIL FROM - Указание адреса отправителя
  4. RCPT TO - Указание получателя (адрес, который вы проверяете)
  5. Анализ ответа - Ответ сервера указывает, существует ли получатель

Если почтовый сервер принимает команду RCPT TO (код ответа 250), email-адрес, вероятно, существует. Отклонение (ответ 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 критически важно для интерпретации результатов верификации:

КодЗначениеИнтерпретация
250OKEmail-адрес существует и принимает почту
251User not localБудет перенаправлен на другой адрес
450Mailbox unavailableВременная проблема, попробуйте позже
451Local errorПроблема на стороне сервера
452Insufficient storageПочтовый ящик переполнен
550Mailbox not foundEmail-адрес не существует
551User not localПереадресация не настроена
553Mailbox name invalidСинтаксическая ошибка в имени почтового ящика

Важные ограничения

SMTP-верификация имеет несколько значительных ограничений:

  1. Catch-All домены: Некоторые почтовые серверы принимают все адреса независимо от того, существуют ли они, возвращая 250 для всего. Эти конфигурации "catch-all" делают SMTP-верификацию бесполезной.

  2. Greylisting: Серверы могут временно отклонять сообщения от неизвестных отправителей. Ваша верификация может получить отклонение, которое успешно пройдёт при повторной попытке.

  3. Ограничение скорости: Почтовые серверы часто ограничивают попытки подключения. Верификация большого объёма может вызвать блокировки.

  4. IP-репутация: IP-репутация вашего сервера верификации влияет на то, будут ли почтовые серверы отвечать честно.

  5. Ограничения брандмауэра: Многие сети блокируют исходящий SMTP-трафик на порту 25 из соображений безопасности.

Уровень точности: ~85-90% (когда серверы отвечают честно)

Метод 5: API-сервисы верификации email

Для производственных приложений использование профессионального API верификации email предлагает лучший баланс точности, скорости и надёжности. Сервисы, такие как BillionVerify, обрабатывают всю сложность многометодной верификации, предоставляя дополнительные проверки, которые отдельные методы не могут достичь.

Преимущества API-верификации

Более высокая точность: Профессиональные сервисы комбинируют все методы верификации (синтаксис, DNS, MX, SMTP) с дополнительным интеллектом, таким как обнаружение одноразовых email, идентификация ролевых адресов и обработка catch-all доменов.

Лучшая инфраструктура: API-сервисы поддерживают выделенные пулы IP с сильной репутацией, распределённые серверы для более быстрого глобального отклика и прямые отношения с основными email-провайдерами.

Без обслуживания: Вам не нужно поддерживать код SMTP-верификации, обрабатывать пограничные случаи или беспокоиться о блокировке вашего сервера верификации.

Масштабируемость: API обрабатывают миллионы верификаций без проблем с инфраструктурой.

Интеграция API BillionVerify

Вот как интегрировать API BillionVerify для верификации email:

Пример Node.js:

const axios = require('axios');

const BV_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 ${BV_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

BV_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 {BV_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 предлагает верификацию в реальном времени, которая может валидировать email-адреса по мере ввода пользователем:

// 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%МгновенноНизкаяБесплатноПервичная фильтрация
Проверка домена/DNS50-60%БыстроНизкаяБесплатноБыстрые предварительные проверки
Валидация MX-записей70-75%БыстроСредняяБесплатноВалидация форм
SMTP-рукопожатие85-90%МедленноВысокаяИнфраструктураПакетная очистка
API-сервис97-99%БыстроНизкаяЗа запросПроизводственные системы

Рекомендации по случаям использования

Формы регистрации: Используйте комбинацию клиентской синтаксической валидации для мгновенной обратной связи плюс API-верификацию при отправке. Это обеспечивает плавный пользовательский опыт при гарантии качества данных.

Email-маркетинговые кампании: Используйте API-сервис для массовой верификации перед отправкой. Стоимость за верификацию значительно меньше, чем ущерб от высоких показателей возврата.

Проекты очистки данных: API-сервисы с возможностью массовой загрузки предлагают лучший баланс точности и эффективности для очистки существующих списков.

Разработка/Тестирование: Синтаксическая и MX-валидация обеспечивают достаточную точность для сред разработки, где идеальная точность не критична.

Лучшие практики верификации email

Реализуйте несколько уровней

Не полагайтесь на один метод верификации. Реализуйте многоуровневый подход:

  1. Немедленно: Синтаксическая валидация на стороне клиента
  2. При отправке: Проверка MX-записей для быстрой серверной валидации
  3. Перед кампанией: Полная API-верификация для подтверждения доставляемости

Корректно обрабатывайте пограничные случаи

Некоторые результаты верификации неоднозначны (catch-all домены, временные сбои). Спроектируйте свою систему так, чтобы:

  • Принимать адреса с неопределёнными результатами верификации, но помечать их для проверки
  • Реализовать логику повторных попыток для временных сбоев
  • Отслеживать результаты верификации для выявления паттернов

Проверяйте в правильное время

  • Регистрация: Проверяйте перед созданием учётной записи
  • Импорт: Проверяйте при импорте списков из внешних источников
  • Периодически: Повторно проверяйте неактивные адреса перед кампаниями повторного вовлечения
  • Перед крупными рассылками: Всегда проверяйте перед большими кампаниями

Соблюдайте ограничения скорости

Независимо от того, используете ли вы собственную SMTP-верификацию или API, соблюдайте ограничения скорости для поддержания хороших отношений с почтовыми серверами и сервис-провайдерами.

Заключение

Проверка email-адресов без отправки реальных писем не только возможна, но и необходима для поддержания доставляемости email и репутации отправителя. От простых синтаксических проверок до сложной API-верификации, у вас есть множество вариантов в зависимости от ваших требований к точности и технических возможностей.

Для большинства производственных приложений мы рекомендуем:

  1. Начните с простого: Реализуйте синтаксическую валидацию для немедленной обратной связи
  2. Добавьте глубину: Включите DNS и MX-проверки для серверной валидации
  3. Переходите на профессиональный уровень: Используйте API-сервис, такой как BillionVerify для верификации производственного качества

Готовы внедрить профессиональную верификацию email? Попробуйте наш инструмент проверки email, чтобы увидеть верификацию в действии, или изучите API BillionVerify для бесшовной интеграции в ваши приложения.

Внедряя правильную верификацию email, вы защитите репутацию отправителя, улучшите показатели доставляемости и гарантируете, что ваши сообщения достигнут людей, которые хотят их получить. Начните верифицировать умнее уже сегодня.

Команды, использующие Instantly или Smartlead, улучшают доставляемость, очищая списки с BillionVerify перед каждой кампанией.

Сравните BillionVerify с ZeroBounce по точности и скорости, прежде чем выбирать поставщика верификации.

Leo
LeoFounder, BillionVerify
Аналитика проверки Email

Начните проверку сегодня

Начните проверять email с BillionVerify уже сегодня. Получите 100 бесплатных кредитов при регистрации — кредитная карта не требуется. Присоединяйтесь к тысячам компаний, улучшающих ROI email-маркетинга с помощью точной проверки email.

Кредитная карта не требуется · 100+ бесплатных кредитов в день · Начать за 30 секунд

99.9%
Точность
Real-time
Скорость API
$0.00014
За email
100/day
Бесплатно навсегда