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éthode | Idéale Pour | Complexité |
|---|---|---|
| Webhook | Vérification côté serveur | Faible |
| Widget | Validation en temps réel | Moyenne |
| Zapier | Automatisation sans code | Faible |
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
- Ouvrez votre formulaire dans JotForm
- Allez dans Paramètres → Intégrations
- Recherchez WebHooks
- 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
- Hébergez le HTML du widget sur votre serveur
- Dans JotForm, allez dans Créateur de Formulaire → Ajouter un Élément de Formulaire → Widgets
- Recherchez votre widget ou utilisez "HTML Personnalisé"
- 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;
}