EmailVerify LogoEmailVerify

Jotform

Email checker for Jotform. Verify emails in Jotform submissions and workflows.

JotForm に EmailVerify を統合し、リアルタイムでメールアドレスを検証して高品質なフォーム送信を確保しましょう。

連携方法

方法最適な用途複雑さ
Webhookサーバーサイド検証
ウィジェットリアルタイム検証
Zapierノーコード自動化

方法 1:Webhook 連携

フォーム送信時にメールを検証する Webhook をセットアップします。

JotForm Webhook の設定

  1. JotForm でフォームを開く
  2. 設定連携 に移動
  3. WebHooks を検索
  4. Webhook URL を追加:https://yoursite.com/api/jotform/webhook

Webhook ハンドラー

// pages/api/jotform/webhook.js
import EmailVerify from '@emailverify/sdk';

const bv = new EmailVerify(process.env.EMAILVERIFY_API_KEY);

export default async function handler(req, res) {
    if (req.method !== 'POST') {
        return res.status(405).json({ error: 'Method not allowed' });
    }

    // JotForm は form-urlencoded でデータを送信
    const { rawRequest, formID, submissionID } = req.body;

    // raw request をパース
    const formData = JSON.parse(rawRequest || '{}');

    // メールフィールドを見つける
    const email = findEmailField(formData);

    if (!email) {
        return res.status(200).json({ message: 'No email field found' });
    }

    // メールを検証
    const result = await bv.verify({ email });

    // 結果を処理
    await processVerification({
        formId: formID,
        submissionId: submissionID,
        email,
        verification: result,
    });

    res.status(200).json({ success: true });
}

function findEmailField(formData) {
    // JotForm のフィールド名は q3_email、q5_yourEmail のような形式
    for (const [key, value] of Object.entries(formData)) {
        if (typeof value === 'string' && value.includes('@')) {
            // 基本的なメールパターンチェック
            if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
                return value;
            }
        }
    }
    return null;
}

async function processVerification({ formId, submissionId, email, verification }) {
    // データベースに結果を保存
    await storeResult({
        formId,
        submissionId,
        email,
        status: verification.status,
        score: verification.score,
        isDisposable: verification.is_disposable,
        verifiedAt: new Date().toISOString(),
    });

    // 無効なメールを処理
    if (verification.status === 'invalid' || verification.is_disposable) {
        await handleInvalidEmail({
            formId,
            submissionId,
            email,
            reason: verification.status === 'invalid'
                ? '無効なメールアドレス'
                : '使い捨てメールを検出',
        });
    }
}

async function handleInvalidEmail({ formId, submissionId, email, reason }) {
    // オプション 1:通知を送信
    await sendNotification({
        type: 'invalid_email',
        formId,
        submissionId,
        email,
        reason,
    });

    // オプション 2:JotForm 送信を更新(スパムとしてマーク)
    await updateSubmission(submissionId, {
        flag: 'spam',
        note: `メール検証に失敗: ${reason}`,
    });
}

JotForm 送信の更新

JotForm API を使用して送信をマークまたは更新:

async function updateSubmission(submissionId, updates) {
    const response = await fetch(
        `https://api.jotform.com/submission/${submissionId}?apiKey=${process.env.JOTFORM_API_KEY}`,
        {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
            },
            body: new URLSearchParams({
                'submission[flag]': updates.flag || '0',
                'submission[new]': '0',
            }),
        }
    );

    return response.json();
}

方法 2:カスタムウィジェット

リアルタイムメール検証用のカスタム JotForm ウィジェットを作成します。

ウィジェットコード

<!-- widget.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>メール検証ウィジェット</title>
    <link href="https://cdn.jotfor.ms/stylebuilder/static/form-common.css" rel="stylesheet">
    <style>
        .widget-container {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
        }

        .email-input {
            width: 100%;
            padding: 10px;
            font-size: 14px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }

        .email-input:focus {
            outline: none;
            border-color: #4a90d9;
        }

        .email-input.valid {
            border-color: #28a745;
        }

        .email-input.invalid {
            border-color: #dc3545;
        }

        .status-message {
            margin-top: 5px;
            font-size: 12px;
        }

        .status-message.verifying {
            color: #666;
        }

        .status-message.valid {
            color: #28a745;
        }

        .status-message.invalid {
            color: #dc3545;
        }

        .loader {
            display: inline-block;
            width: 12px;
            height: 12px;
            border: 2px solid #ccc;
            border-top-color: #666;
            border-radius: 50%;
            animation: spin 1s linear infinite;
        }

        @keyframes spin {
            to { transform: rotate(360deg); }
        }
    </style>
</head>
<body>
    <div class="widget-container">
        <input
            type="email"
            id="email"
            class="email-input"
            placeholder="メールアドレスを入力"
        />
        <div id="status" class="status-message"></div>
    </div>

    <script src="https://cdn.jotfor.ms/static/prototype.forms.js"></script>
    <script src="https://cdn.jotfor.ms/static/jotform.forms.js"></script>
    <script>
        var JFCustomWidget = {
            subscribe: function(event, callback) {
                if (event === 'ready') {
                    callback();
                }
            }
        };

        // ウィジェット設定からの構成
        var widgetConfig = {};

        JFCustomWidget.subscribe('ready', function() {
            // ウィジェット設定を取得
            var settings = JFCustomWidget.getWidgetSettings();
            widgetConfig.apiEndpoint = settings.apiEndpoint || '/api/verify-email';
            widgetConfig.blockDisposable = settings.blockDisposable !== 'false';

            initWidget();
        });

        function initWidget() {
            var emailInput = document.getElementById('email');
            var statusEl = document.getElementById('status');
            var verifyTimeout;
            var isValid = false;

            emailInput.addEventListener('blur', function() {
                var email = this.value.trim();

                if (!email) {
                    clearStatus();
                    return;
                }

                if (!isValidFormat(email)) {
                    showStatus('invalid', '有効なメール形式を入力してください');
                    return;
                }

                clearTimeout(verifyTimeout);
                verifyTimeout = setTimeout(function() {
                    verifyEmail(email);
                }, 300);
            });

            function verifyEmail(email) {
                showStatus('verifying', '<span class="loader"></span> 確認中...');

                fetch(widgetConfig.apiEndpoint, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ email: email })
                })
                .then(function(response) { return response.json(); })
                .then(function(result) {
                    if (result.status === 'valid' && !result.disposable) {
                        showStatus('valid', '✓ メール確認済み');
                        isValid = true;
                    } else if (result.status === 'invalid') {
                        showStatus('invalid', '✗ 有効なメールを入力してください');
                        isValid = false;
                    } else if (result.disposable && widgetConfig.blockDisposable) {
                        showStatus('invalid', '✗ 恒久的なメールを使用してください');
                        isValid = false;
                    } else {
                        showStatus('valid', '✓ メール確認済み');
                        isValid = true;
                    }

                    // JotForm に値を送信
                    JFCustomWidget.sendData({
                        value: email,
                        valid: isValid
                    });
                })
                .catch(function(error) {
                    console.error('検証エラー:', error);
                    // エラー時は許可
                    isValid = true;
                    clearStatus();
                    JFCustomWidget.sendData({ value: email, valid: true });
                });
            }

            function showStatus(type, message) {
                statusEl.innerHTML = message;
                statusEl.className = 'status-message ' + type;
                emailInput.className = 'email-input ' + (type === 'verifying' ? '' : type);
            }

            function clearStatus() {
                statusEl.innerHTML = '';
                statusEl.className = 'status-message';
                emailInput.className = 'email-input';
            }

            function isValidFormat(email) {
                return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
            }
        }
    </script>
</body>
</html>

ウィジェットのホストと登録

  1. ウィジェット HTML をサーバーにホスト
  2. JotForm で フォームビルダーフォーム要素を追加ウィジェット に移動
  3. ウィジェットを検索または「Custom HTML」を使用
  4. ウィジェット URL を設定

方法 3:Zapier 連携

Zapier を使用して JotForm を EmailVerify に接続します。

Zap のセットアップ

ステップ 1:トリガー

  • アプリ:JotForm
  • イベント:New Submission

ステップ 2:メールを検証

  • アプリ:Webhooks by Zapier
  • イベント:POST
  • 設定:
    URL: https://api.emailverify.ai/v1/verify
    Headers:
      Authorization: Bearer YOUR_API_KEY
      Content-Type: application/json
    Data:
      {"email": "{{email_field}}"}

ステップ 3:フィルター

  • 続行条件:{{status}}valid と等しくない

ステップ 4:アクション(無効なメールの場合)

  • アプリ:Gmail
  • イベント:Send Email
  • 設定:
    To: admin@yourcompany.com
    Subject: 無効なメール送信 - JotForm
    Body: メール {{email}} の検証に失敗しました。ステータス: {{status}}

JotForm API 連携

高度なワークフローには JotForm API を直接使用します。

送信の取得と検証

// services/jotform.js
import EmailVerify from '@emailverify/sdk';

const bv = new EmailVerify(process.env.EMAILVERIFY_API_KEY);
const jotformApiKey = process.env.JOTFORM_API_KEY;

class JotFormService {
    async getFormSubmissions(formId, options = {}) {
        const params = new URLSearchParams({
            apiKey: jotformApiKey,
            limit: options.limit || 100,
            offset: options.offset || 0,
            filter: JSON.stringify(options.filter || {}),
        });

        const response = await fetch(
            `https://api.jotform.com/form/${formId}/submissions?${params}`
        );

        const data = await response.json();
        return data.content;
    }

    async verifySubmissions(formId) {
        const submissions = await this.getFormSubmissions(formId, {
            filter: { 'status:ne': 'DELETED' }
        });

        const results = [];

        for (const submission of submissions) {
            const email = this.findEmailInSubmission(submission);

            if (!email) continue;

            const verification = await bv.verify({ email });

            results.push({
                submissionId: submission.id,
                email,
                status: verification.status,
                score: verification.score,
                isDisposable: verification.is_disposable,
            });

            // 無効な送信をフラグ
            if (verification.status === 'invalid' || verification.is_disposable) {
                await this.flagSubmission(submission.id);
            }
        }

        return results;
    }

    findEmailInSubmission(submission) {
        const answers = submission.answers || {};

        for (const [questionId, answer] of Object.entries(answers)) {
            if (answer.type === 'control_email') {
                return answer.answer;
            }

            // メールを含む可能性のあるテキストフィールドもチェック
            if (answer.answer && typeof answer.answer === 'string') {
                if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(answer.answer)) {
                    return answer.answer;
                }
            }
        }

        return null;
    }

    async flagSubmission(submissionId) {
        const response = await fetch(
            `https://api.jotform.com/submission/${submissionId}?apiKey=${jotformApiKey}`,
            {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
                body: new URLSearchParams({
                    'submission[flag]': '1',
                }),
            }
        );

        return response.json();
    }
}

export const jotformService = new JotFormService();

使用例

import { jotformService } from './services/jotform';

// フォームのすべての送信を検証
async function verifyFormSubmissions(formId) {
    const results = await jotformService.verifySubmissions(formId);

    const stats = {
        total: results.length,
        valid: results.filter(r => r.status === 'valid' && !r.isDisposable).length,
        invalid: results.filter(r => r.status === 'invalid').length,
        disposable: results.filter(r => r.isDisposable).length,
    };

    console.log('検証結果:', stats);

    return results;
}

ベストプラクティス

1. API エラーを適切に処理

try {
    const result = await verifyEmail(email);
    // 結果を処理
} catch (error) {
    console.error('検証に失敗:', error);
    // API エラー時は送信をブロックしない
    return { valid: true };
}

2. 結果をキャッシュ

const cache = new Map();
const CACHE_TTL = 24 * 60 * 60 * 1000; // 24 時間

async function verifyWithCache(email) {
    const cached = cache.get(email);
    if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
        return cached.result;
    }

    const result = await bv.verify({ email });
    cache.set(email, { result, timestamp: Date.now() });

    return result;
}

3. Webhook のレート制限

const rateLimiter = new Map();

function checkRateLimit(ip, limit = 10, windowMs = 60000) {
    const now = Date.now();
    const requests = rateLimiter.get(ip) || [];

    // 古いリクエストを削除
    const recent = requests.filter(time => now - time < windowMs);

    if (recent.length >= limit) {
        return false;
    }

    recent.push(now);
    rateLimiter.set(ip, recent);

    return true;
}

関連リソース

On this page