// Domailfix for Airtable: verify the email addresses in a table. // // Setup (once): in your base, open Extensions -> Add an extension -> Scripting. Delete the example // code, paste this whole file, and click Run. Pick the table, the view, the email field and a field // for the result (a "Single line text" field, for example "Email status"), and paste your Domailfix // API key from https://domailfix.achivix.com/account // // Records that already have a result are skipped, so you can stop and run it again at any time. // Each check uses 1 Domailfix credit; Unknown results are free (and are checked again next time). const BASE = "https://domailfix.achivix.com"; const settings = input.config({ title: "Verify emails with Domailfix", description: "Checks each email address (no email is sent) and saves the result.", items: [ input.config.table("table", { label: "Table" }), input.config.view("view", { label: "View (only records in this view are checked)", parentTable: "table" }), input.config.field("emailField", { label: "Email field", parentTable: "table" }), input.config.field("statusField", { label: "Field for the result (Single line text)", parentTable: "table" }), input.config.text("apiKey", { label: "Domailfix API key (dmf_...)" }), ], }); const apiKey = (settings.apiKey || "").trim(); if (!apiKey) { output.markdown("**Paste your Domailfix API key in the settings above, then run again.**"); } else { const query = await settings.view.selectRecordsAsync({ fields: [settings.emailField, settings.statusField] }); const todo = query.records.filter(r => { const email = (r.getCellValueAsString(settings.emailField) || "").trim(); const done = (r.getCellValueAsString(settings.statusField) || "").trim(); return email && (!done || done === "unknown"); }); output.markdown(`Checking **${todo.length}** email addresses...`); const counts = { deliverable: 0, undeliverable: 0, risky: 0, unknown: 0 }; let updates = []; let stopped = ""; for (let i = 0; i < todo.length; i++) { const rec = todo[i]; const email = rec.getCellValueAsString(settings.emailField).trim(); let status = "unknown"; try { const resp = await fetch(BASE + "/api/verify?email=" + encodeURIComponent(email), { headers: { "X-API-Key": apiKey, "Accept": "application/json" }, }); const data = await resp.json(); if (resp.status === 401) { stopped = "Domailfix did not accept the API key. Check it in the settings."; break; } if (resp.status === 402) { stopped = "Your Domailfix credits ran out. Buy more at " + BASE + " and run again."; break; } if (resp.status === 429) { await new Promise(r => setTimeout(r, 5000)); i--; continue; } if (resp.ok) { status = data.status; if (data.flags && data.flags.toxic && status !== "undeliverable") status = "toxic"; } } catch (e) { status = "unknown"; } counts[status === "toxic" ? "risky" : status] = (counts[status === "toxic" ? "risky" : status] || 0) + 1; updates.push({ id: rec.id, fields: { [settings.statusField.id]: status } }); if (updates.length === 50) { await settings.table.updateRecordsAsync(updates); updates = []; output.text(`${i + 1} of ${todo.length} checked`); } } if (updates.length) await settings.table.updateRecordsAsync(updates); if (stopped) output.markdown("**Stopped:** " + stopped); output.markdown(`**Done.** Deliverable: ${counts.deliverable}, undeliverable: ${counts.undeliverable}, ` + `risky (including toxic): ${counts.risky}, unknown (free): ${counts.unknown}.`); }