コンテンツへスキップ
Integration

パッケージをインストールせずに Node.js でメールを検証する方法

| 7 min read

3 つの API 呼び出しにより、構文、MX レコード、および使い捨てドメインがチェックされます。 npm インストール、正規表現ファイル、SMTP タイムアウトはありません。 どの Node.js バージョンでもフェッチから動作します。

Email validation interface on a laptop screen
Photo by Stephen Phillips on Unsplash

正規表現は形式をキャッチします。 他のすべてが欠けています。 user@fakdomain123.com 通ります。 user@mailinator.com 通ります。 admin@company.com (フラグを立てるべきロールベースのアドレス) は合格します。 Stack Overflow からコピーするすべての正規表現には同じ盲点があります。それは、インフラストラクチャではなく文字を検証するということです。

npm パッケージでもこれは解決されません。 email-validator 依存関係を追加しますが、形式のチェックのみを行います。 deep-email-validator SMTP プローブを実行します。ファイアウォールの内側でタイムアウトになり、サーバー IP がメール プロバイダーによってブロックリストに登録されます。

構文、MX レコード、および使い捨てプロバイダーの検出という 3 つのチェックが必要です。 botoi API は、3 つすべてを 1 つの POST で実行します。 インストールはありません。 正規表現ファイルがありません。 SMTP接続がありません。

API呼び出し

応答の形状を確認するには、次のカール コマンドを 1 つ実行します。

curl -X POST https://api.botoi.com/v1/email/validate \\
  -H "Content-Type: application/json" \\
  -d '{"email": "test@tempmail.xyz"}'

応答により、アドレスに関するすべてがわかります。

{
  "success": true,
  "data": {
    "email": "test@tempmail.xyz",
    "is_valid": false,
    "reason": "no_mx_records",
    "is_free": false,
    "is_role": false,
    "is_disposable": true,
    "domain": "tempmail.xyz",
    "format_valid": true
  }
}

format_valid 構文を確認します。 is_valid フォーマット、MX、配信可能性を単一のブール値に結合します。 is_disposable 使い捨てプロバイダーにフラグを立てます。 is_role 次のようなアドレスをキャッチします admin@ そして info@reason 次の場合に検証が失敗した理由を示します is_valid は誤りです。

Node.js 統合: 高速サインアップ ルート

これは、POST で電子メールを検証する完全な Express ルート ハンドラーです。 /signup ネイティブフェッチを使用します。 フェールオープン パターンにより、botoi の停止によって実際のサインアップがブロックされることがなくなります。

import express from 'express';

const app = express();
app.use(express.json());

app.post('/signup', async (req, res) => {
  const { email, password } = req.body;

  if (!email || !password) {
    return res.status(400).json({ error: 'Email and password are required' });
  }

  // Validate email before creating the account
  try {
    const validation = await fetch('https://api.botoi.com/v1/email/validate', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
      },
      body: JSON.stringify({ email }),
      signal: AbortSignal.timeout(3000),
    });

    const result = await validation.json();

    if (result.success && !result.data.is_valid) {
      return res.status(422).json({
        error: 'Invalid email address',
        reason: result.data.reason,
      });
    }
  } catch {
    // Fail open: if the API is unreachable, let the signup proceed
    console.warn('Email validation API unreachable, skipping check');
  }

  // Email passed validation; continue with account creation
  // await createUser(email, password);

  return res.status(201).json({ message: 'Account created' });
});

app.listen(3000);

ルートは、422 および特定のメールを含む無効な電子メールを拒否します。 reason APIから。 API にアクセスできない場合は、サインアップが続行されます。 小切手を逃した代わりに、中断されないユーザー フローを得ることができます。

3層検証

/v1/email/validate エンドポイントは基本をカバーします。 徹底的にチェックするには、次の 3 つのエンドポイントを組み合わせます。

  • /v1/email/validate 構文と形式については
  • /v1/email-mx/verify MX レコード検証用
  • /v1/disposable-email/check 使い捨て検出用

このヘルパー関数は 3 つすべてを呼び出し、構造化された結果を返します。

interface ValidationResult {
  valid: boolean;
  formatValid: boolean;
  mxValid: boolean;
  isDisposable: boolean;
  reason: string | null;
}

const API_BASE = 'https://api.botoi.com/v1';
const headers = {
  'Content-Type': 'application/json',
  'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
};

async function validateEmail(email: string): Promise<ValidationResult> {
  const result: ValidationResult = {
    valid: true,
    formatValid: false,
    mxValid: false,
    isDisposable: false,
    reason: null,
  };

  // Layer 1: Syntax and format check
  const formatRes = await fetch(\`\${API_BASE}/email/validate\`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });
  const formatData = await formatRes.json();

  if (!formatData.success || !formatData.data.format_valid) {
    return { ...result, valid: false, reason: 'invalid_format' };
  }
  result.formatValid = true;

  // Layer 2: MX record verification
  const mxRes = await fetch(\`\${API_BASE}/email-mx/verify\`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });
  const mxData = await mxRes.json();

  if (!mxData.success || !mxData.data.has_mx) {
    return { ...result, valid: false, reason: 'no_mx_records' };
  }
  result.mxValid = true;

  // Layer 3: Disposable provider detection
  const dispRes = await fetch(\`\${API_BASE}/disposable-email/check\`, {
    method: 'POST',
    headers,
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });
  const dispData = await dispRes.json();

  if (dispData.success && dispData.data.is_disposable) {
    return { ...result, valid: false, isDisposable: true, reason: 'disposable_provider' };
  }

  return result;
}

次のように使用します。

const result = await validateEmail('user@tempmail.xyz');

if (!result.valid) {
  console.log(\`Rejected: \${result.reason}\`);
  // Rejected: disposable_provider
}

各層は、異なるクラスの不正メールを捕捉します。 フォーマットチェックにより、ガベージ入力が停止されます。 MX チェックは、発明されたドメインを停止します。 使い捨て小切手により、使い捨てのサインアップがなくなります。 これらを組み合わせることで、正規表現によって生じるギャップをカバーします。

Next.js API ルートへの追加

同じロジックが、次の Next.js App Router ルート ハンドラーでも機能します。 app/api/validate-email/route.ts。 このバージョンでは、フォーマット チェックと使い捨てチェックを並行して実行して、レイテンシを短縮します。

import { NextResponse } from 'next/server';

const API_BASE = 'https://api.botoi.com/v1';
const headers = {
  'Content-Type': 'application/json',
  'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
};

export async function POST(req: Request) {
  const body = await req.json();
  const email = body.email?.trim().toLowerCase();

  if (!email) {
    return NextResponse.json(
      { error: 'Email is required' },
      { status: 400 }
    );
  }

  try {
    // Run format check and disposable check in parallel
    const [formatRes, dispRes] = await Promise.all([
      fetch(\`\${API_BASE}/email/validate\`, {
        method: 'POST',
        headers,
        body: JSON.stringify({ email }),
        signal: AbortSignal.timeout(3000),
      }),
      fetch(\`\${API_BASE}/disposable-email/check\`, {
        method: 'POST',
        headers,
        body: JSON.stringify({ email }),
        signal: AbortSignal.timeout(3000),
      }),
    ]);

    const [formatData, dispData] = await Promise.all([
      formatRes.json(),
      dispRes.json(),
    ]);

    if (formatData.success && !formatData.data.format_valid) {
      return NextResponse.json(
        { valid: false, reason: 'Invalid email format' },
        { status: 422 }
      );
    }

    if (dispData.success && dispData.data.is_disposable) {
      return NextResponse.json(
        { valid: false, reason: 'Disposable emails are not allowed' },
        { status: 422 }
      );
    }

    // Then check MX records
    const mxRes = await fetch(\`\${API_BASE}/email-mx/verify\`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ email }),
      signal: AbortSignal.timeout(3000),
    });
    const mxData = await mxRes.json();

    if (mxData.success && !mxData.data.has_mx) {
      return NextResponse.json(
        { valid: false, reason: 'Email domain has no mail server' },
        { status: 422 }
      );
    }

    return NextResponse.json({ valid: true });
  } catch {
    // Fail open on API errors
    return NextResponse.json({ valid: true });
  }
}

サインアップフォームからこのルートを呼び出します onBlur ユーザーが送信する前に電子メールを検証するハンドラー。 パラレル Promise.all ほとんどのリクエストの応答時間を 200 ミリ秒未満に保ちます。

特殊なケースの処理

素朴なバリデーターにつまずく 3 つのパターン:

キャッチオール ドメイン

一部のドメインでは、任意のアドレスの電子メールを受け入れます。 anything@catch-all-domain.com 弾まないし、 ただし、メールボックスが存在しない可能性があります。 MX チェックにより、ドメインにメール サーバーがあることが確認されます。 特定のメールボックスを確認するには電子メールを送信する必要がありますが、このアプローチでは意図的に回避されています。 ほとんどのサインアップ フローでは、ドメイン レベルの検証で十分です。

役割ベースのアドレス

のようなアドレス admin@info@、 そして support@ 共有受信箱です。 これらは有効ですが、単一の人物が管理していないため、アカウントの所有権の候補としては適していません。 API はこれらにフラグを付けます。 is_role: true。 製品のニーズに基づいて、ユーザーに警告したり、サインアップをブロックしたりできます。

プラスアドレス指定

user+tag@gmail.com に配達します user@gmail.com。 これは正当な機能であり、悪用ではありません。 ただし、1 人が同じメールボックスで多数のアカウントを作成できるようになります。 これを防ぎたい場合は、 + 検証の前にサフィックスを追加し、正規化されたアドレスを保存します。

3 つすべてを処理する関数は次のとおりです。

async function validateEmailStrict(email: string): Promise<{
  valid: boolean;
  warnings: string[];
  reason: string | null;
}> {
  const warnings: string[] = [];

  // Check for plus addressing (user+tag@gmail.com)
  const localPart = email.split('@')[0];
  if (localPart.includes('+')) {
    warnings.push('plus_addressing');
  }

  const res = await fetch('https://api.botoi.com/v1/email/validate', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': \`Bearer \${process.env.BOTOI_API_KEY}\`,
    },
    body: JSON.stringify({ email }),
    signal: AbortSignal.timeout(3000),
  });

  const data = await res.json();

  if (!data.success) {
    return { valid: false, warnings, reason: 'api_error' };
  }

  // Flag role-based addresses (admin@, info@, support@)
  if (data.data.is_role) {
    warnings.push('role_based_address');
  }

  // Reject disposable providers
  if (data.data.is_disposable) {
    return { valid: false, warnings, reason: 'disposable_provider' };
  }

  // Reject domains with no MX records
  if (!data.data.is_valid && data.data.reason === 'no_mx_records') {
    return { valid: false, warnings, reason: 'no_mx_records' };
  }

  return { valid: data.data.is_valid, warnings, reason: null };
}
const result = await validateEmailStrict('admin+test@example.com');
// {
//   valid: true,
//   warnings: ['plus_addressing', 'role_based_address'],
//   reason: null
// }

npm パッケージと API のアプローチ

特徴 電子メールバリデーター ディープメールバリデーター ボトイAPI
依存関係 1 5+ 0 (ネイティブフェッチ)
フォーマットチェック はい はい はい
MXチェック いいえ はい (SMTP) はい (DNS)
使い捨て検出器 いいえ はい (ローカルリスト) はい (700 以上のドメイン)
SMTP プローブ いいえ はい(信頼性が低い) いいえ (DNS ベース)
ファイアウォールセーフ はい いいえ はい
メンテナンス あなたが更新します あなたが更新します APIのアップデート

npm パッケージのアプローチでは、検証ロジックとそのデータ (ドメイン リスト、正規表現パターン) をコードベースに配置します。 アップデートの所有者はあなたです。 新しい使い捨てプロバイダーが起動すると、誰かが PR を開いてそれを追加する必要があります。 API アプローチにより、そのメンテナンスの負荷が軽減されます。 ドメインリストはサーバー側で更新されます。 コードは変わりません。

トレードオフ: API によりネットワーク依存性が追加されます。 Express および Next.js の例に示されているフェールオープン パターン がこれを処理します。 API がダウンしている場合、検証はパスし、他のサインアップ保護 (メール確認、レート制限) に依存します。 API が回復するまで。

FAQ

パッケージをインストールせずに Node.js でメール アドレスを検証するにはどうすればよいですか?
ネイティブ フェッチ API を使用して、botoi 電子メール API などの検証エンドポイントを呼び出します。 電子メール アドレスを指定して POST リクエストを送信すると、API は形式の有効性、MX レコードのステータス、および使い捨てプロバイダーの検出を返します。 npm インストール、正規表現のメンテナンス、SMTP 接続は必要ありません。
Node.js に最適な電子メール検証 API は何ですか?
最適な API は、構文検証、MX レコード検証、および使い捨てドメイン検出の 3 つのチェックを 1 つの呼び出しで組み合わせます。 botoi API は 3 つすべてをカバーしており、100 ミリ秒未満で結果を返します。 フェッチ (18 以降) をサポートする任意の Node.js バージョンで動作し、無料枠では 1 日あたり 100 リクエストを処理します。
メッセージを送信せずに電子メール アドレスが存在するかどうかを確認するにはどうすればよいですか?
DNS ベースのチェックを使用して、ドメインに有効な MX レコードがあることを確認できます。これにより、メール サーバーが存在し、接続が受け入れられることが確認されます。 botoi /v1/email-mx/verify エンドポイントは、SMTP 接続を開かずに DNS 経由でこれを実行するため、IP がブロックリストに登録されることはありません。 このアプローチでは、ドメインが本物であることは確認されますが、特定のメールボックスが存在するかどうかは確認できません。
Node.js で使い捨てメール アドレスを検出するにはどうすればよいですか?
電子メール アドレスを使用して、botoi /v1/disposable-email/check エンドポイントを呼び出します。 700 以上の既知の使い捨てプロバイダーをチェックし、is_disposable ブール値を返します。 これをフォーマット検証および MX チェックと組み合わせて、すべてネイティブのフェッチ呼び出しを使用して、徹底的な検証パイプラインを実現できます。
Node.js でのメール検証には正規表現で十分ですか?
いいえ。正規表現は形式のみをチェックします。 user@fakdomain123.com のような電子メールは正規表現を通過しますが、メール サーバーがありません。 user@mailinator.com は正規表現を渡しますが、使い捨てアドレスです。 効果的な検証には、MX レコードのチェックと使い捨てプロバイダーのスクリーニングが必要ですが、正規表現では実行できません。

botoiで開発を始めよう

150以上のAPIエンドポイント。検索、テキスト処理、画像生成、開発者ユーティリティに対応。無料プラン、クレジットカード不要。