How to Set a Role-Based Email Signup Policy
by EmailGuard Marketing
Share this article
Enjoyed this article?
More notes on building products, infrastructure, and teams.
by EmailGuard Marketing
More notes on building products, infrastructure, and teams.
A role-based email signup policy is a per-field rule: block, allow, or confirm when the address is a shared inbox like admin@ or support@. The product job for that field decides the action. A workspace-owner login is not the same job as a support ticket or a newsletter form. Prefix lists from Mailchimp or Klaviyo describe marketing-list hygiene, not account ownership.
This guide is the implementation counterpart to what a role-based email address is. You will leave with a written matrix, a server-side check, and a recovery path when you reject ops@ as the owner login.
By the end, you will:
role_address with disposable and public-domain flags.Prerequisites: A signup or form handler you control, an API key with the email:detect scope, and a place to store a boolean flag on the user or lead. Staging first.
A role-based email address uses a functional local part instead of a person's name. There is no RFC that defines "role address." RFC 5322 only constrains syntax. RFC 2142 names mailboxes for common services (postmaster, webmaster, hostmaster). Product detectors extend that idea to sales@, billing@, and noreply@.
EmailGuard returns role_address after syntax validation. The flag does not mean the mailbox is monitored, that SMTP accepted mail, or that one human owns the password. An abandoned jobs@ still looks like a role address. If you need existence proof, that is a different product. We do not SMTP-probe.
Deliverable also is not the same as marketing-safe. support@acme.com can receive invoices and still be a poor list row for a promo campaign.
Copying an ESP blocklist into your registration handler is the usual mistake.
Mailchimp's role-based address help (retrieved 2026-08-31) does three different things on one page:
The import list includes prefixes Mailchimp associates with bounces and complaints: abuse@, admin@, billing@, support@, noreply@, postmaster@, and others on that page. Form opt-in is explicitly carved out.
Klaviyo's role-address article (updated 2025-08-05) auto-blocks a different prefix set from marketing campaigns and flows. Sends are skipped with reason Invalid Email. Klaviyo says it cannot remove those blocks. Their published list includes paypal@, domains@, and post@. It does not include several prefixes Mailchimp lists, including admin@, billing@, and support@.
Treat those pages as send-time hygiene for their platforms. Your product account still needs its own matrix.
Try sample addresses in the role address detector before you freeze prefixes in application code.
Write the email field's job in one sentence. If you cannot, you will over-block.
| Product job | What the address must do after signup |
|---|---|
| Workspace owner / login | Receive password reset, MFA, and legal notices for one recoverable human |
| Billing contact | Receive invoices; may be a finance queue |
| Newsletter or marketing list | Consent to promotional mail; engagement is attributed to a person when possible |
| Support or contact form | Land in a team inbox on purpose |
| CRM / demo lead | Give sales a named buyer when you can; still capture the company if you cannot |
| Team invite or secondary email | Attach a person to an existing workspace without making them the owner |
Same prefix, different jobs. billing@ as the only login is a recovery risk. billing@ as the invoice CC is normal.
Three actions. Not a boolean.
Block. Reject the request and do not create the account or list row. Use this when a shared inbox cannot satisfy the job. Typical: consumer login, KYC identity, or any flow where password reset must reach one person you can lock out.
Allow. Accept the address and continue. Use this when the shared inbox is the destination. Typical: support forms, hello@ contact pages, partner intake that already assumes a team queue.
Confirm. Accept only after a second proof. Examples: require a personal work address before paid conversion, send an invite to a named teammate, or hold the trial as flagged for sales review. Confirm is the default for B2B self-serve when you do not want to lose it@ trials and you also do not want info@ as the forever owner.
| Product job | Recommended action | Why |
|---|---|---|
| Workspace owner / primary login | Confirm on B2B self-serve; block on consumer or KYC | You need a recoverable human. A hard block loses real IT buyers who start on ops@. |
| Billing contact (separate field) | Allow, store role_address | Finance queues are supposed to be shared. |
| Newsletter / marketing capture | Confirm or block for promo lists; keep transactional | ESPs already suppress many role prefixes on import or send. Do not pretend your signup form is Mailchimp. |
| Support / contact | Allow | The role inbox is the feature. |
| CRM demo request | Allow + flag | Sales can still work sales@acme.com. Score it below a named inbox. |
| Team invite / member email | Block role as the invitee if the seat is a person; allow a shared inbox only for a shared "ops" seat you designed | Inviting support@ as a named member recreates the owner problem one layer down. |
Do not infer a job title from the prefix. success@ is not proof of a Customer Success hire.
Call detect once. Branch in order.
disposable. A role prefix on a throwaway domain is still throwaway. Use the same pattern as blocking disposable emails at signup.public_domain + role_address (info@gmail.com) as freemail-plus-role if you require a company domain. The work-email matrix lives in how to require a work email at signup.relay_domain separately. Privacy relays are not role inboxes.function applySignupPolicy(result, job) {
if (!result.syntax_validation) {
return { action: "block", reason: "syntax" };
}
if (result.disposable) {
return { action: "block", reason: "disposable" };
}
if (!result.role_address) {
return { action: "allow", reason: "personal" };
}
switch (job) {
case "support_form":
case "billing_contact":
return { action: "allow", reason: "role_ok_for_job" };
case "workspace_owner":
return { action: "confirm", reason: "need_personal_or_invite" };
case "consumer_login":
case "kyc":
return { action: "block", reason: "role_not_allowed" };
default:
return { action: "confirm", reason: "role_review" };
}
}Keep the API key on the server. Fail open on timeouts if a downed checker would freeze paid signup. Cache by normalized address if the same email is posted twice in a burst.
See what to check before you store an address for the rest of the signal set.
GET /api/v1/emails/detect?email=support%40acme.com
Authenticate with a team key that includes email:detect. Persist role_address on the user or lead. You will want it later for sales routing and for "require personal email before plan upgrade."
Error copy should name the job, not the jargon.
Never tell the user "role-based email detected" unless they are an admin debugging a sandbox.
If you confirm or block support@ as owner, the next screen cannot be a dead end.
Patterns that work:
roleAddress: true, then require an invite to alex@acme.com before admin actions or billing.role_address is true. The secondary address is the login. The role address becomes a notification CC.Invites need the same policy. If the invitee field is "this seat is a person," block role there too. If you sell a shared "on-call" seat, allow it and label the seat in the UI so you do not pretend it is Jane.
You run B2B project software. Three fields:
| Field | Job | Policy |
|---|---|---|
| Registration email | Workspace owner | Confirm |
| Invoice email (settings) | Billing contact | Allow |
| Contact page | Support | Allow |
it@acme.com signs up. Detect returns role_address: true, disposable: false. You create the trial, store the flag, and ask for a named admin before card entry. billing@acme.com in settings is stored without friction. help@acme.com on the contact form is accepted.
admin@tempmail.example is rejected on disposable before the role rule runs.
That is the whole policy. Prefix worship is optional.
Shipping Mailchimp's import list as your login rule. You will block admin@ trials that Mailchimp would have accepted on a form, and you still will not have solved password recovery.
Assuming Klaviyo's list is universal. It is not Mailchimp's list, and Klaviyo will not unlist those prefixes for you.
Hard-blocking every B2B trial. IT and ops often start on a shared inbox. Confirm beats block when the credit card still needs a person.
Ignoring the second flag. Role plus disposable is disposable.
No invite path. A red error with no alternative trains people to type first.last+fake@gmail.com.
No. Block only when the field needs one recoverable human. Allow shared inboxes on support and contact. Confirm on B2B owner signup when you will accept the company but not the shared login forever.
No. Mailchimp blocks many prefixes on import, allows form opt-in, and rejects role addresses for Mailchimp accounts. Klaviyo auto-blocks a different list from campaigns and flows, skips them as Invalid Email, and cannot remove those blocks. Check each vendor's help article before you copy a list.
No. It classifies the local part after syntax checks. EmailGuard does not probe SMTP or catch-all.
Block as disposable. Apply role policy only when disposable is false.
role_address through detect and store the flag.+tag, separators).