A HubSpot form is a contact-capture machine: every submission creates or updates
a contact record, sets properties, and can enrol that contact in a workflow. What
it won't do is tell you whether the address someone typed is actually real.
HubSpot's email field runs a format check — it confirms there's an @ and a
domain — but it can't see that the mailbox is dead, disposable, or a typo of
gmail.com. This guide shows two practical ways to verify emails from HubSpot forms
with Qualisend: in real time, with an Operations Hub workflow that POSTs each new
address to the Qualisend API, and in bulk, by exporting contacts to a CSV. Neither
needs a native connector — there isn't one yet — just HubSpot's built-in workflow
actions or its export button.
The short answer#
Pick the path that matches when you need the answer:
- Real time — enrol new form submitters in a workflow. A custom-code or
webhook action calls the Qualisend API with the email, and a branch writes
the verdict to a contact property, then routes or suppresses the record based on
the returned
status. - Bulk — export your contacts to CSV, run them through Qualisend's bulk verification, and suppress the undeliverables before your next send.
Why HubSpot's form field can't confirm a mailbox#
HubSpot's email field validates format — it checks that the string looks like
an address before it lets the form submit. That's the same class of check a regex
does, and it fails for the same reasons:
format is not deliverability.
jane@gmial.com passes the format check. So does throwaway@mailinator.com, and
so does a real-looking address at a domain that shut down last year.
None of those are caught until you send — and by then a dead address is a hard bounce that chips at your bounce rate and sender reputation. Real verification adds the layers HubSpot can't: a DNS/MX lookup and an SMTP mailbox probe, plus flags for disposable, role, and catch-all addresses. If that pipeline is new to you, what email verification actually checks is the primer.
Two ways to verify emails from HubSpot forms#
The important constraint first: a standard HubSpot form can't block a bad email mid-submit. There's no supported way to call an external API between the "Submit" click and the record being created, so real-time verification happens just after submission, inside a workflow — not as an inline gate. That shapes both paths below.
| Path | When it runs | Best for |
|---|---|---|
| Real-time workflow | Seconds after each submission | Live intake — tag, route, or hold follow-up before the first send |
| Bulk CSV | On demand, in batches | Existing contact backlogs and periodic list hygiene |
Path 1: real-time with an Operations Hub workflow#
Build a contact-based workflow and set the enrolment trigger to "Form submission", scoped to the form you care about. Every new submitter now flows into the workflow, where you make the verification call and act on the result.
There are two ways to make that call — pick the one that fits your portal and your stack.
Option A — a custom-code action (self-contained). If you're on Operations Hub
Professional or Enterprise, a custom-code action
runs Node.js (or Python) right inside the workflow. Add the enrolled contact's
email as an input property, store your key as a secret named
QUALISEND_API_KEY, and call Qualisend from the action:
// HubSpot custom-code action (Node.js) — input property: email, secret: QUALISEND_API_KEY
const QUALISEND_ENDPOINT = "https://api.qualisend.com/v1/verify"; // confirm the path in /developers
exports.main = async (event, callback) => {
const email = event.inputFields.email;
const res = await fetch(QUALISEND_ENDPOINT, {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.QUALISEND_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ email }),
});
// Fail open — never block a real lead on a transient API error.
if (!res.ok) return callback({ outputFields: { email_status: "unknown" } });
const { result } = await res.json();
callback({
outputFields: {
email_status: result.status, // deliverable / risky / undeliverable / unknown
email_score: result.score,
},
});
};
The action exposes email_status and email_score as outputs. Follow it with a
Copy property value step that writes email_status into a custom contact
property, then use an if/then branch to route on it — the whole reason you ran
the check.
Option B — a webhook action to your own function. Prefer to keep the logic in your own codebase, or not on a custom-code tier? Add a webhook action that POSTs to a small serverless function you control. The function pulls the email, calls Qualisend, and writes the verdict back to the contact with HubSpot's CRM API. It's the same server-side shape as the verify-at-signup pattern: the API key never leaves the server, and you act on the result. The endpoint code in the Node.js walkthrough or the Python walkthrough drops almost straight in — only the payload parsing is HubSpot-specific.
Either way, the underlying request is the same, and the placeholders are yours to fill from the developer docs:
POST https://api.qualisend.com/v1/verify
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "email": "jane@example.com" }
A deliverable address comes back like this — a status, a 0–100 score, a
reason, and a set of sub_flags:
{
"result": {
"status": "deliverable",
"score": 95,
"reason": null,
"sub_flags": { "disposable": false, "role": false, "free": false, "catch_all": false }
}
}
Two rules keep this robust. Use a scoped key minted for this workflow rather
than a full-access key, so if it ever leaks from a log it can only verify —
nothing else. And fail open: if Qualisend times out or the plan limit is hit,
treat the address as unknown and keep the contact rather than dropping a real
lead over a transient blip — which is exactly what the !res.ok branch above
does.
Downstream, the verdict is just a branch. Set a custom "Email status" property
from the output, then let your workflow decide: a deliverable contact continues
into the nurture sequence; an undeliverable or disposable one gets the
follow-up held back, gets flagged for review, or is set to non-marketing so it's
excluded from active lists and sends. The workflow is the plumbing; the routing is
yours.
Path 2: bulk-verify a CSV export#
If you already have thousands of contacts, or you'd rather clean on a schedule than run per-submission checks, go in batches — and this route needs no workflow, so it works below the Operations Hub tiers too. In HubSpot, open Contacts, pick a list or filter, and Export to CSV. You'll get one row per contact with the email in its own column.
Then:
- Upload the CSV to Qualisend's bulk verification and let it run the full pipeline — MX, SMTP, and the disposable/role/catch-all flags — across every row.
- Download the annotated file. Each address comes back with a
status, areason, and a 0–100score. - Suppress the undeliverables back in HubSpot: import the results to set your "Email status" property, then exclude anything that isn't deliverable from your active lists and marketing sends.
Bulk is the right tool for a backlog, but it's cleanup, not prevention: an address you catch here has usually already been sitting in your database. Pair a periodic bulk pass with the real-time workflow so new bad addresses are flagged the moment they arrive.
Acting on the verdict#
Whichever path returns the result, the shape is the same — a status, a reason,
a score, and the sub-flags. Map each to an action:
| Result | What to do in HubSpot |
|---|---|
deliverable | Accept — continue the workflow and send normally. |
undeliverable | Suppress. Set the contact to non-marketing or exclude it from sends;
check the reason to see whether it's a bad domain or a dead
mailbox. |
disposable flag | Reject or tag, depending on how strict your funnel is — see role, disposable & free addresses. |
risky / catch-all | Accept but segment. A catch-all domain can't confirm the individual mailbox, so send cautiously. |
unknown | Accept and re-check later — the infrastructure didn't answer, so never drop a real lead over it. |
If you're weighing HubSpot's workflow approach against calling the API directly from your own backend, the same trade-off applies as with any glue: workflows win on speed-to-set-up, a direct integration wins on cost and control at scale. The same webhook pattern also powers the sibling guides for Zapier and Typeform if some of your intake lives outside HubSpot.
Frequently asked questions#
Is there a native Qualisend integration for HubSpot?#
Not right now. Qualisend's native platform integrations are being rebuilt, so there's no branded app to install in the HubSpot Marketplace yet — it's on the roadmap. Until it ships, the supported way to verify emails from HubSpot forms is a workflow custom-code or webhook action pointed at the Qualisend API, exactly as this guide describes. That approach is also more flexible: you control the request, the branching, and which contact property the verdict lands in.
Do I need Operations Hub to verify emails from HubSpot forms?#
For the real-time workflow, effectively yes. Workflows require a Professional tier, and the webhook and custom-code actions specifically require Operations Hub Professional or Enterprise. If your portal is on a lower tier, use the CSV export and bulk-verify route instead — it needs no workflow and no custom code, just an export and a file upload, so it works on any plan that lets you export contacts.
Can I block a bad email before the form is submitted?#
Not reliably. A standard HubSpot form has no supported way to call an external API mid-submit and stop the record from being created, so real-time verification runs just after submission, inside the workflow. In practice that's fine: you verify within seconds and act before the address ever receives a message — you hold the welcome email, tag the contact, or route it to review rather than blocking the form itself.
How is this different from cleaning my existing HubSpot list?#
Verifying at intake stops new bad addresses from entering; cleaning your existing list removes the ones already in it. This guide is about the first — catching each submission as it lands. For the second, you're doing a one-off (or scheduled) pass over your whole database, deciding what to suppress and how to re-engage stale contacts. The full routine, including where each status belongs, is in how to clean an email list. Most teams do both.
Ready to wire it up? Grab a scoped key and the exact request format in the developer docs, sanity-check a single address in the free email checker, or start with the 100 free credits on every plan to test the workflow end to end before you turn it on.