For web & application server administrators · Section B

Validate email addresses in web forms

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.

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 →