EmailVerify LogoEmailVerify

Jotform

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

Integre EmailVerify con JotForm para verificar direcciones de correo electrónico en tiempo real y garantizar envíos de formularios de alta calidad.

Métodos de Integración

MétodoMejor ParaComplejidad
WebhookVerificación del lado del servidorBaja
WidgetValidación en tiempo realMedia
ZapierAutomatización sin códigoBaja

Método 1: Integración por Webhook

Configure un webhook para verificar correos electrónicos cuando se envíen los formularios.

Configurar Webhook de JotForm

  1. Abra su formulario en JotForm
  2. Vaya a ConfiguraciónIntegraciones
  3. Busque WebHooks
  4. Agregue la URL de su webhook: https://yoursite.com/api/jotform/webhook

Manejador del 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 envía datos como form-urlencoded
    const { rawRequest, formID, submissionID } = req.body;

    // Analizar la solicitud sin procesar
    const formData = JSON.parse(rawRequest || '{}');

    // Buscar campo de correo electrónico
    const email = findEmailField(formData);

    if (!email) {
        return res.status(200).json({ message: 'No se encontró campo de correo electrónico' });
    }

    // Verificar correo electrónico
    const result = await bv.verify({ email });

    // Procesar resultado
    await processVerification({
        formId: formID,
        submissionId: submissionID,
        email,
        verification: result,
    });

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

function findEmailField(formData) {
    // Los nombres de campo de JotForm son como q3_email, q5_yourEmail, etc.
    for (const [key, value] of Object.entries(formData)) {
        if (typeof value === 'string' && value.includes('@')) {
            // Verificación básica de patrón de correo
            if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
                return value;
            }
        }
    }
    return null;
}

async function processVerification({ formId, submissionId, email, verification }) {
    // Guardar resultado en su base de datos
    await storeResult({
        formId,
        submissionId,
        email,
        status: verification.status,
        score: verification.score,
        isDisposable: verification.is_disposable,
        verifiedAt: new Date().toISOString(),
    });

    // Manejar correos electrónicos inválidos
    if (verification.status === 'invalid' || verification.is_disposable) {
        await handleInvalidEmail({
            formId,
            submissionId,
            email,
            reason: verification.status === 'invalid'
                ? 'Dirección de correo electrónico inválida'
                : 'Correo electrónico desechable detectado',
        });
    }
}

async function handleInvalidEmail({ formId, submissionId, email, reason }) {
    // Opción 1: Enviar notificación
    await sendNotification({
        type: 'invalid_email',
        formId,
        submissionId,
        email,
        reason,
    });

    // Opción 2: Actualizar envío de JotForm (marcar como spam)
    await updateSubmission(submissionId, {
        flag: 'spam',
        note: `Verificación de correo electrónico fallida: ${reason}`,
    });
}

Actualizar Envío de JotForm

Use la API de JotForm para marcar o actualizar envíos:

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étodo 2: Widget Personalizado

Cree un widget personalizado de JotForm para validación de correo electrónico en tiempo real.

Código del 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, Oxygin, 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;
                    }

                    // Enviar valor a JotForm
                    JFCustomWidget.sendData({
                        value: email,
                        valid: isValid
                    });
                })
                .catch(function(error) {
                    console.error('Error de verificación:', error);
                    // Permitir en caso de 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>

Alojar y Registrar Widget

  1. Aloje el HTML del widget en su servidor
  2. En JotForm, vaya a Creador de FormulariosAgregar Elemento de FormularioWidgets
  3. Busque su widget o use "HTML Personalizado"
  4. Configure la URL del widget

Método 3: Integración con Zapier

Conecte JotForm a EmailVerify usando Zapier.

Configuración del Zap

Paso 1: Disparador

  • Aplicación: JotForm
  • Evento: Nuevo Envío

Paso 2: Verificar Correo Electrónico

  • Aplicación: Webhooks by Zapier
  • Evento: POST
  • Configuración:
    URL: https://api.emailverify.ai/v1/verify
    Headers:
      Authorization: Bearer YOUR_API_KEY
      Content-Type: application/json
    Data:
      {"email": "{{email_field}}"}

Paso 3: Filtro

  • Solo continuar si: {{status}} no es igual a valid

Paso 4: Acción (para correos electrónicos inválidos)

  • Aplicación: Gmail
  • Evento: Enviar Correo Electrónico
  • Configuración:
    To: admin@yourcompany.com
    Subject: Envío de Correo Electrónico Inválido - JotForm
    Body: El correo electrónico {{email}} falló la verificación. Estado: {{status}}

Integración con la API de JotForm

Para flujos de trabajo avanzados, use la API de JotForm directamente.

Obtener y Verificar Envíos

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

            // Update submission with verification result
            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;
            }

            // Also check text fields that might contain 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 no tiene una API de notas directa, pero puede actualizar campos personalizados
        // o usar un sistema de seguimiento separado
    }
}

export const jotformService = new JotFormService();

Uso

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

// Verificar todos los envíos de un formulario
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('Resultados de Verificación:', stats);

    return results;
}

Integración de Lógica Condicional

Use los resultados de verificación para controlar el comportamiento del formulario.

Validación Previa al Envío

// Incruste esto en su página de formulario
<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;

    // Verificar al perder el foco
    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) {
            // Permitir en caso de error
            emailVerified = true;
        }
    });

    // Validar al enviar
    form.addEventListener('submit', function(e) {
        if (!emailVerified) {
            e.preventDefault();

            alert('Por favor ingrese una dirección de correo electrónico válida para continuar.');
            emailField.focus();
            return false;
        }
    });

    function updateFieldUI(field, result) {
        // Eliminar clases existentes
        field.classList.remove('valid', 'invalid');

        // Encontrar o crear elemento de estado
        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 = '✓ Correo electrónico verificado';
            statusEl.style.color = '#28a745';
        } else {
            field.classList.add('invalid');
            statusEl.textContent = result.disposable
                ? '✗ Por favor use un correo electrónico permanente'
                : '✗ Por favor ingrese un correo electrónico válido';
            statusEl.style.color = '#dc3545';
        }
    }
});
</script>

Verificación en Lote para Datos Existentes

Procese envíos históricos:

async function bulkVerifyJotFormData(formId) {
    console.log('Iniciando verificación en lote...');

    // Obtener todos los envíos
    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(`Obtenidos ${allSubmissions.length} envíos...`);
    }

    console.log(`Total de envíos: ${allSubmissions.length}`);

    // Extraer correos electrónicos
    const emailMap = new Map();
    for (const submission of allSubmissions) {
        const email = jotformService.findEmailInSubmission(submission);
        if (email) {
            emailMap.set(submission.id, email);
        }
    }

    console.log(`Encontrados ${emailMap.size} correos electrónicos para verificar`);

    // Verificación en lote
    const emails = [...emailMap.values()];
    const job = await bv.verifyBulk(emails);

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

    // Esperar finalización
    let status;
    do {
        await sleep(5000);
        status = await bv.getBulkJobStatus(job.job_id);
        console.log(`Progreso: ${status.progress_percent}%`);
    } while (status.status !== 'completed');

    // Obtener resultados
    const results = await bv.getBulkJobResults(job.job_id);

    // Procesar resultados
    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++;

        // Encontrar y marcar envíos inválidos
        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('Verificación completa:', stats);
    return stats;
}

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

Mejores Prácticas

1. Manejar Errores de API con Gracia

try {
    const result = await verifyEmail(email);
    // Procesar resultado
} catch (error) {
    console.error('Verificación fallida:', error);
    // No bloquear el envío en caso de errores de API
    return { valid: true };
}

2. Almacenar Resultados en Caché

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

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. Limitación de Velocidad para Webhooks

const rateLimiter = new Map();

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

    // Eliminar solicitudes antiguas
    const recent = requests.filter(time => now - time < windowMs);

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

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

    return true;
}

Recursos Relacionados

On this page