What is a role-based email address?
Addresses like info@ and support@ belong to a team, not a person — here's why that changes how you onboard them, and what Boundstone's role_account flag can and can't tell you.
Contents
What is a role-based email address?
A role-based email address is one whose local part — the bit before the @ — names a function instead of a person: info@, support@, admin@, sales@, billing@, no-reply@. Ask "what is a role-based email address" and the short answer is a mailbox that belongs to a team, not an individual. jane@acme.com is almost certainly Jane. support@acme.com is a queue that three people, a shared inbox, and a ticketing bot all read.
That distinction sounds academic until you send to one.
Why role addresses matter
Three reasons, in rough order of how much they'll cost you.
Personalization breaks. Your onboarding sequence opens with "Hi Jane" — except there's no Jane behind info@. A first-name merge on a role address reads as a mass email, because it is one. The people who see it never signed up as themselves; they inherited the inbox.
Deliverability risk goes up. Shared inboxes get more mail, get read less carefully, and generate more spam complaints per send. Some are monitored as spam traps. A pile of role addresses on your list drags your sender reputation down, which quietly costs you inbox placement for every other address too.
It can be a weak fraud signal. Someone spinning up throwaway signups sometimes reaches for admin@ or test@ on a domain they don't personally own. On its own that proves nothing — plenty of real buyers sign up with orders@ — but combined with other signals it's worth noticing.
How detection works — and where it stops
Role detection is not clever. You take the local part, lowercase it, and check it against a list of known role names:
ROLE_LOCAL_PARTS = {
"admin", "administrator", "info", "support", "sales", "billing",
"help", "helpdesk", "contact", "office", "hello", "team",
"marketing", "noreply", "no-reply", "postmaster", "webmaster",
"abuse", "hr", "jobs", "careers", "accounts", "orders",
}
def is_role_account(email: str) -> bool:
local = email.rsplit("@", 1)[0].strip().lower()
return local in ROLE_LOCAL_PARTS
is_role_account("support@acme.com") # True
is_role_account("jane.doe@acme.com") # False
That is genuinely the whole mechanism, and for a lot of teams that fifteen-line function is all you need — ship it and move on.
Here's the honest limit: a list reads the local part, and nothing else. It cannot see who is actually behind the mailbox. info@ at a one-person consultancy is read by exactly one human who takes it personally. j.smith@ might be a shared alias three people watch. The list will call the first a role account and miss the second, and it will do that every time, because the only thing it has to go on is a string. Role detection is a heuristic about a name, not a fact about a person.
Where Boundstone fits
If you already validate email — see validating email in Python — you can add role detection with the set above and never call an API. Do that first; often it's enough.
The API earns its place when you want one consistent contract across every client and every check in one call. POST /v1/verify/email returns a role_account boolean alongside syntax, live-MX, and disposable checks — the last being a separate concept worth understanding on its own:
curl -s https://api.boundstone.io/v1/verify/email \
-H "Authorization: Bearer bs_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"support@acme.com"}'
{
"valid_syntax": true,
"domain": "acme.com",
"mx_found": true,
"disposable": false,
"role_account": true,
"free_provider": false,
"checks": {
"performed": ["syntax", "mx", "disposable_list", "role_list"],
"not_performed": ["smtp_mailbox", "catch_all"]
}
}
Note checks. role_list sits in performed — we checked the local part against a role list, and that's exactly what role_account reflects, nothing more. Meanwhile smtp_mailbox and catch_all sit in not_performed: Boundstone does not knock on the mailbox to confirm a specific human reads it, and does not detect catch-all domains. mx_found: true means the domain accepts mail; it does not mean support@acme.com is a live, monitored inbox. We'd rather list what we skipped than let a green checkmark imply more than it earned. That not_performed array is the point — it's why you can trust the fields that are filled in.
Treat it as a signal, not a switch
role_account: true is information, not a verdict. Reject on it blindly and you'll bounce real customers whose company routes signups through accounts@ or purchasing@. Use it to route instead:
const res = await fetch("https://api.boundstone.io/v1/verify/email", {
method: "POST",
headers: {
"Authorization": "Bearer bs_live_YOUR_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({ email }),
});
const { role_account } = await res.json();
if (role_account) {
// Don't block. Skip the "Hi {first_name}" merge and
// send the team-friendly welcome instead.
sendGenericWelcome(email);
} else {
sendPersonalizedOnboarding(email);
}
Same door for everyone; different mat depending on who's likely on the other side.
The short version
- A role-based email address names a function (
info@,support@,no-reply@), so it belongs to a team, not a person. - It matters because personalization falls flat, deliverability risk rises, and it's an occasional fraud signal.
- Detection is a local-part list — fifteen lines of your own code, and often all you need. Its limit: it reads the name, never the human behind it.
- Boundstone returns a
role_accountflag withrole_listinchecks.performed, in one call alongside syntax, MX, and disposable — and tells you plainly, vianot_performed, that it never checked the mailbox itself. - Use the flag to route, not to reject. Try it with no key on the free email validator.