⚠ Read this before you change anything
Everything on this page is an illustrative example, not a tested, certified, or supported configuration for your stack, framework, or environment. Blocking or flagging a major share of consumer addresses in a public-facing form has real trade-offs for your visitors and your support team.
You are solely responsible for reviewing, testing, and validating any change before it touches a production system, for confirming it's compatible with your existing forms and validation logic, and for any legal, contractual, or regulatory obligations that apply to your organisation's handling of user data.
By copying, adapting, or deploying any snippet or script from this page, you accept full responsibility for the consequences — including but not limited to broken form submissions and downstream impact on your users. DumpMicrosoft and its authors accept none. If you are not able or willing to take that responsibility, do not apply any of the changes described in this guide.
If your signup, checkout or contact form emails a confirmation link or receipt, an @outlook.com or @hotmail.com address is a real risk of "it never arrived" — which becomes your support team's problem, not Microsoft's. The pattern below warns the visitor immediately, in the browser, with the reason and a link to dumpmicrosoft.com/users.html. Client-side JavaScript is a UX aid only — always pair it with server-side validation, since JS can be disabled or bypassed entirely. This site's own contact form runs the exact pattern below end to end — hard block in the browser, matching check in a small CGI backend — if you'd like to see it working before wiring up your own.
1. Include the script
Grab js/email-domain-blocker.js from this site (view source, or copy the
block below) and host it on your own server alongside your other static assets:
<script src="/js/email-domain-blocker.js"></script>
2. Wire it up (or just let it auto-attach)
By default the script watches every input[type="email"] on the page in
non-blocking "warn" mode as soon as it loads. To block form submission outright
instead, or to customise the domain list, call watch() explicitly:
<input type="email" id="email" name="email" class="form-control" required>
<script src="/js/email-domain-blocker.js"></script>
<script>
DumpMicrosoftBlocker.watch('#email', {
mode: 'block', // or 'warn' to allow submission anyway
explainUrl: 'https://dumpmicrosoft.com/users.html'
});
</script>
The script adds Bootstrap's .is-invalid class and an
.invalid-feedback message next to the field automatically, so it renders
correctly if your form already uses Bootstrap form styling.
3. Full source, for reference
The complete script (also included with this site at
js/email-domain-blocker.js):
(function (window, document) {
"use strict";
var DEFAULT_DOMAINS = [
"hotmail.com", "hotmail.co.uk", "outlook.com", "outlook.co.uk",
"live.com", "live.co.uk", "msn.com"
];
var DEFAULT_MESSAGE =
"We can't reliably deliver to {domain} addresses. Microsoft's mail " +
"servers block legitimate mail without warning, so messages to and " +
"from this address can vanish with no bounce. Please use a different " +
"provider.";
function domainOf(email) {
var m = /@([^\s@]+)$/.exec(String(email || "").trim());
return m ? m[1].toLowerCase() : "";
}
function isBlockedDomain(email, domains) {
var d = domainOf(email);
return d ? domains.indexOf(d) !== -1 : false;
}
// The explanation link is rendered as a real <a> element (not
// pasted into the message text), and a blocked field also gets
// input.setCustomValidity(...) so it fails native :invalid too — see
// js/email-domain-blocker.js on this site for the full, commented
// version, including the watch()/DOM-wiring code.
})(window, document);
4. Validate on the server too
Client-side checks never replace server-side ones. A minimal PHP example:
<?php
$blocked_domains = ['hotmail.com', 'outlook.com', 'live.com', 'msn.com'];
$email = trim($_POST['email'] ?? '');
$domain = strtolower(substr(strrchr($email, '@'), 1));
if (in_array($domain, $blocked_domains, true)) {
http_response_code(422);
exit('We can\'t reliably deliver to @' . $domain . ' addresses. '
. 'See https://dumpmicrosoft.com/users.html for why, and for a '
. 'provider that will actually receive your mail.');
}
// ...continue with normal validation and processing...
Apply the equivalent check in whatever your backend actually is —
the logic is the same three lines in Node, Python, Ruby, or any other stack:
extract the domain after @, compare it against your block list, reject
with a clear message and a link to users.html.
Pointing an affected visitor here? Send them straight to the switching guide.
Open the user guide →