EmailVerify LogoEmailVerify

Jotform

Email checker for JotForm with webhooks and custom widgets.

Intégrez EmailVerify avec JotForm pour vérifier les adresses email en temps réel et garantir des soumissions de formulaires de haute qualité.

Méthodes d'Intégration

MéthodeIdéale PourComplexité
WebhookVérification côté serveurFaible
WidgetValidation en temps réelMoyenne
ZapierAutomatisation sans codeFaible

Méthode 1 : Intégration par Webhook

Configurez un webhook pour vérifier les emails lors de la soumission des formulaires.

Configurer le Webhook JotForm

  1. Ouvrez votre formulaire dans JotForm
  2. Allez dans ParamètresIntégrations
  3. Recherchez WebHooks
  4. Ajoutez l'URL de votre webhook : https://yoursite.com/api/jotform/webhook

Gestionnaire de 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 envoie les données en form-urlencoded
    const { rawRequest, formID, submissionID } = req.body;

    // Analyser la requête brute
    const formData = JSON.parse(rawRequest || '{}');

    // Trouver le champ email
    const email = findEmailField(formData);

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

    // Vérifier l'email
    const result = await bv.verify({ email });

    // Traiter le résultat
    await processVerification({
        formId: formID,
        submissionId: submissionID,
        email,
        verification: result,
    });

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

function findEmailField(formData) {
    // Les noms de champs JotForm sont du type q3_email, q5_yourEmail, etc.
    for (const [key, value] of Object.entries(formData)) {
        if (typeof value === 'string' && value.includes('@')) {
            // Vérification basique du format email
            if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
                return value;
            }
        }
    }
    return null;
}

async function processVerification({ formId, submissionId, email, verification }) {
    // Stocker le résultat dans votre base de données
    await storeResult({
        formId,
        submissionId,
        email,
        status: verification.status,
        score: verification.score,
        isDisposable: verification.is_disposable,
        verifiedAt: new Date().toISOString(),
    });

    // Gérer les emails invalides
    if (verification.status === 'invalid' || verification.is_disposable) {
        await handleInvalidEmail({
            formId,
            submissionId,
            email,
            reason: verification.status === 'invalid'
                ? 'Invalid email address'
                : 'Disposable email detected',
        });
    }
}

async function handleInvalidEmail({ formId, submissionId, email, reason }) {
    // Option 1 : Envoyer une notification
    await sendNotification({
        type: 'invalid_email',
        formId,
        submissionId,
        email,
        reason,
    });

    // Option 2 : Mettre à jour la soumission JotForm (marquer comme spam)
    await updateSubmission(submissionId, {
        flag: 'spam',
        note: `Email verification failed: ${reason}`,
    });
}

Mettre à Jour une Soumission JotForm

Utilisez l'API JotForm pour marquer ou mettre à jour les soumissions :

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

Méthode 2 : Widget Personnalisé

Créez un widget JotForm personnalisé pour la validation d'email en temps réel.

Code du Widget

<!-- widget.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Email Verification Widget</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="Enter your email"
        />
        <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();
                }
            }
        };

        // Configuration from widget settings
        var widgetConfig = {};

        JFCustomWidget.subscribe('ready', function() {
            // Get widget settings
            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', 'Please enter a valid email format');
                    return;
                }

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

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

                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', '✓ Email verified');
                        isValid = true;
                    } else if (result.status === 'invalid') {
                        showStatus('invalid', '✗ Please enter a valid email');
                        isValid = false;
                    } else if (result.disposable && widgetConfig.blockDisposable) {
                        showStatus('invalid', '✗ Please use a permanent email');
                        isValid = false;
                    } else {
                        showStatus('valid', '✓ Email verified');
                        isValid = true;
                    }

                    // Envoyer la valeur à JotForm
                    JFCustomWidget.sendData({
                        value: email,
                        valid: isValid
                    });
                })
                .catch(function(error) {
                    console.error('Verification error:', error);
                    // Autoriser en cas d'erreur
                    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>

Héberger et Enregistrer le Widget

  1. Hébergez le HTML du widget sur votre serveur
  2. Dans JotForm, allez dans Créateur de FormulaireAjouter un Élément de FormulaireWidgets
  3. Recherchez votre widget ou utilisez "HTML Personnalisé"
  4. Configurez l'URL du widget

Méthode 3 : Intégration Zapier

Connectez JotForm à EmailVerify avec Zapier.

Configuration du Zap

Étape 1 : Déclencheur

  • App : JotForm
  • Événement : New Submission

Étape 2 : Vérifier l'Email

  • App : Webhooks by Zapier
  • Événement : POST
  • Configuration :
    URL: https://api.emailverify.ai/v1/verify
    Headers:
      Authorization: Bearer YOUR_API_KEY
      Content-Type: application/json
    Data:
      {"email": "{{email_field}}"}

Étape 3 : Filtre

  • Continuer seulement si : {{status}} n'est pas égal à valid

Étape 4 : Action (pour les emails invalides)

  • App : Gmail
  • Événement : Send Email
  • Configuration :
    To: admin@yourcompany.com
    Subject: Invalid Email Submission - JotForm
    Body: Email {{email}} failed verification. Status: {{status}}

Intégration de l'API JotForm

Pour des workflows avancés, utilisez l'API JotForm directement.

Récupérer et Vérifier les Soumissions

// 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,
            });

            // Mettre à jour la soumission avec le résultat de vérification
            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;
            }

            // Vérifier aussi les champs texte qui pourraient contenir un email
            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();
    }

    async addSubmissionNote(submissionId, note) {
        // JotForm n'a pas d'API de notes directe, mais vous pouvez mettre à jour des champs personnalisés
        // ou utiliser un système de suivi séparé
    }
}

export const jotformService = new JotFormService();

Utilisation

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

// Vérifier toutes les soumissions d'un formulaire
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('Verification Results:', stats);

    return results;
}

Intégration de Logique Conditionnelle

Utilisez les résultats de vérification pour contrôler le comportement du formulaire.

Validation Avant Soumission

// Intégrez ceci dans votre page de formulaire
<script>
document.addEventListener('DOMContentLoaded', function() {
    const form = document.querySelector('form[id^="form_"]');
    const emailField = document.querySelector('input[type="email"]');

    let emailVerified = false;
    let verificationResult = null;

    // Vérifier lors de la perte de focus
    emailField.addEventListener('blur', async function() {
        const email = this.value;

        if (!email) return;

        try {
            const response = await fetch('/api/verify-email', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ email }),
            });

            verificationResult = await response.json();
            emailVerified = verificationResult.status === 'valid' &&
                           !verificationResult.disposable;

            updateFieldUI(emailField, verificationResult);
        } catch (error) {
            // Autoriser en cas d'erreur
            emailVerified = true;
        }
    });

    // Valider lors de la soumission
    form.addEventListener('submit', function(e) {
        if (!emailVerified) {
            e.preventDefault();

            alert('Veuillez entrer une adresse email valide pour continuer.');
            emailField.focus();
            return false;
        }
    });

    function updateFieldUI(field, result) {
        // Supprimer les classes existantes
        field.classList.remove('valid', 'invalid');

        // Trouver ou créer l'élément de statut
        let statusEl = field.parentNode.querySelector('.email-status');
        if (!statusEl) {
            statusEl = document.createElement('span');
            statusEl.className = 'email-status';
            field.parentNode.appendChild(statusEl);
        }

        if (result.status === 'valid' && !result.disposable) {
            field.classList.add('valid');
            statusEl.textContent = '✓ Email vérifié';
            statusEl.style.color = '#28a745';
        } else {
            field.classList.add('invalid');
            statusEl.textContent = result.disposable
                ? '✗ Veuillez utiliser un email permanent'
                : '✗ Veuillez entrer un email valide';
            statusEl.style.color = '#dc3545';
        }
    }
});
</script>

Vérification en Masse pour les Données Existantes

Traitez les soumissions historiques :

async function bulkVerifyJotFormData(formId) {
    console.log('Starting bulk verification...');

    // Récupérer toutes les soumissions
    const allSubmissions = [];
    let offset = 0;
    const limit = 100;

    while (true) {
        const submissions = await jotformService.getFormSubmissions(formId, {
            limit,
            offset,
        });

        if (submissions.length === 0) break;

        allSubmissions.push(...submissions);
        offset += limit;

        console.log(`Fetched ${allSubmissions.length} submissions...`);
    }

    console.log(`Total submissions: ${allSubmissions.length}`);

    // Extraire les emails
    const emailMap = new Map();
    for (const submission of allSubmissions) {
        const email = jotformService.findEmailInSubmission(submission);
        if (email) {
            emailMap.set(submission.id, email);
        }
    }

    console.log(`Found ${emailMap.size} emails to verify`);

    // Vérification en masse
    const emails = [...emailMap.values()];
    const job = await bv.verifyBulk(emails);

    console.log(`Job ID: ${job.job_id}`);

    // Attendre la fin
    let status;
    do {
        await sleep(5000);
        status = await bv.getBulkJobStatus(job.job_id);
        console.log(`Progress: ${status.progress_percent}%`);
    } while (status.status !== 'completed');

    // Obtenir les résultats
    const results = await bv.getBulkJobResults(job.job_id);

    // Traiter les résultats
    const stats = { valid: 0, invalid: 0, disposable: 0 };

    for (const result of results.results) {
        if (result.status === 'valid') stats.valid++;
        else stats.invalid++;
        if (result.is_disposable) stats.disposable++;

        // Trouver et marquer les soumissions invalides
        if (result.status === 'invalid' || result.is_disposable) {
            for (const [submissionId, email] of emailMap.entries()) {
                if (email === result.email) {
                    await jotformService.flagSubmission(submissionId);
                    break;
                }
            }
        }
    }

    console.log('Verification complete:', stats);
    return stats;
}

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

Bonnes Pratiques

1. Gérer les Erreurs API avec Élégance

try {
    const result = await verifyEmail(email);
    // Traiter le résultat
} catch (error) {
    console.error('Verification failed:', error);
    // Ne pas bloquer la soumission en cas d'erreurs API
    return { valid: true };
}

2. Mettre en Cache les Résultats

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

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. Limitation de Débit pour les Webhooks

const rateLimiter = new Map();

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

    // Supprimer les anciennes requêtes
    const recent = requests.filter(time => now - time < windowMs);

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

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

    return true;
}

Ressources Associées

On this page