IsEmailAddress
→ booleanChecks whether a string is a valid email address format. More reliable than a custom regex for SFMC email validation.
Runtime verified
Test scripts included
Syntax
Platform.Function.IsEmailAddress(value)
1 argument
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
value |
string | Yes | String to validate as an email address |
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Parameters — Platform.Function.IsEmailAddress(value)
*
* Proves:
* 1. The member exists and is invocable with exactly 1 argument (a
* successful call is the only reliable existence proof for a
* Platform.Function member).
* 2. return_type is boolean: typeof the result is "boolean", and the
* result is strictly true / strictly false — never null, never
* undefined, never a string.
* 3. value is REQUIRED: the 0-argument form throws.
* 4. max_args is 1: the 2-argument and 3-argument forms throw. There is
* no reachable optional second argument.
* 5. The predicate DISCRIMINATES on FORMAT: a well-formed address answers
* true while every malformed shape (missing @, missing domain, missing
* local part, missing TLD, two @ signs, embedded or surrounding
* whitespace, an RFC display-name form, a comma-separated list) answers
* false. A PASS here is therefore not a constant.
* 6. It is a FORMAT check only — it never contacts a mail server, so an
* address at a domain that does not exist is still true.
* 7. Case is irrelevant: an all-uppercase address is true.
* 8. UNLIKE IsCHTMLBrowser, an empty string, null and undefined do NOT
* throw — they are answered false, which is what makes the
* "if (!IsEmailAddress(x))" guard on this page safe for absent input.
* 9. Non-string primitives are coerced and answered false rather than
* throwing; an array argument throws, even when it contains a valid
* address.
* 10. The bare-name Core Library form IsEmailAddress(value) DOES exist
* after Platform.Load and behaves identically to the qualified form.
* 11. The result stringifies to the lowercase JavaScript boolean literal
* "true" / "false".
*
* NOT ASSERTED (documented as a deliberate non-assertion): the validator is
* more permissive than RFC 5322 in at least one respect — a local part with
* consecutive dots ("a..b@example.com") is answered TRUE. That is asserted
* below as observed behaviour, not as a correctness claim; no guidance on
* the page depends on it.
*
* EXPECTED OUTPUT: every line starts with PASS. A FAIL means the runtime no
* longer matches the documented claim and the page must be revised.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
/* 1 + 2. The 1-argument call works and answers a genuine boolean. */
var valid = Platform.Function.IsEmailAddress("test@example.com");
assert("typeof the result is boolean", String(typeof valid), "boolean");
assert("a well-formed address is strictly true", valid === true ? "true" : "false", "true");
assert("the result is not null", valid === null ? "true" : "false", "false");
assert("the result is not undefined", valid === undefined ? "true" : "false", "false");
assert("the result is not the string 'true'", valid === "true" ? "true" : "false", "false");
var invalid = Platform.Function.IsEmailAddress("not-an-email");
assert("typeof the negative result is boolean too", String(typeof invalid), "boolean");
assert("a malformed value is strictly false", invalid === false ? "true" : "false", "true");
assert("the negative result is not undefined", invalid === undefined ? "true" : "false", "false");
/* 5. The predicate discriminates on format. */
assert("a plus-tagged address on a multi-label domain is true", Platform.Function.IsEmailAddress("first.last+tag@sub.example.co.uk") ? "true" : "false", "true");
assert("an underscore in the local part is true", Platform.Function.IsEmailAddress("first_last@example.com") ? "true" : "false", "true");
assert("a hyphenated domain is true", Platform.Function.IsEmailAddress("user@my-domain.com") ? "true" : "false", "true");
assert("a value with no @ is false", Platform.Function.IsEmailAddress("not-an-email") ? "true" : "false", "false");
assert("a value with no domain is false", Platform.Function.IsEmailAddress("user@") ? "true" : "false", "false");
assert("a value with no local part is false", Platform.Function.IsEmailAddress("@example.com") ? "true" : "false", "false");
assert("a domain with no TLD is false", Platform.Function.IsEmailAddress("user@example") ? "true" : "false", "false");
assert("a domain ending in a dot is false", Platform.Function.IsEmailAddress("user@example.com.") ? "true" : "false", "false");
assert("two @ signs are false", Platform.Function.IsEmailAddress("a@b@c.com") ? "true" : "false", "false");
assert("a space inside the local part is false", Platform.Function.IsEmailAddress("user name@example.com") ? "true" : "false", "false");
assert("a leading space is false - the value is NOT trimmed", Platform.Function.IsEmailAddress(" test@example.com") ? "true" : "false", "false");
assert("a trailing space is false - the value is NOT trimmed", Platform.Function.IsEmailAddress("test@example.com ") ? "true" : "false", "false");
assert("an RFC display-name form is false", Platform.Function.IsEmailAddress("Name <test@example.com>") ? "true" : "false", "false");
assert("a comma-separated list of two addresses is false", Platform.Function.IsEmailAddress("a@b.com,c@d.com") ? "true" : "false", "false");
/* 5 (continued). Observed permissiveness relative to RFC 5322. */
assert("OBSERVED consecutive dots in the local part are accepted (RFC 5322 forbids them)", Platform.Function.IsEmailAddress("a..b@example.com") ? "true" : "false", "true");
/* 6. Format only — no mail-server lookup. */
assert("a well-formed address at a non-existent domain is still true - format check only", Platform.Function.IsEmailAddress("nobody@this-domain-does-not-exist-97531.example") ? "true" : "false", "true");
/* 7. Case is irrelevant. */
assert("an all-uppercase address is true", Platform.Function.IsEmailAddress("TEST@EXAMPLE.COM") ? "true" : "false", "true");
/* 3. value is required. */
assertThrows("arity 0 throws (value is required)", function () {
return Platform.Function.IsEmailAddress();
});
/* 4. max_args is 1 — no optional second argument is reachable. */
assertThrows("arity 2 throws (max_args is 1)", function () {
return Platform.Function.IsEmailAddress("test@example.com", "x");
});
assertThrows("arity 3 throws (max_args is 1)", function () {
return Platform.Function.IsEmailAddress("test@example.com", "x", "y");
});
/* 8. Empty / null / undefined are answered false, NOT thrown. */
assert("an empty string is answered false, not thrown", Platform.Function.IsEmailAddress("") ? "true" : "false", "false");
assert("a whitespace-only string is answered false", Platform.Function.IsEmailAddress(" ") ? "true" : "false", "false");
assert("a null argument is answered false, not thrown", Platform.Function.IsEmailAddress(null) ? "true" : "false", "false");
assert("an undefined argument is answered false, not thrown", Platform.Function.IsEmailAddress(undefined) ? "true" : "false", "false");
assert("the empty-string result is a genuine boolean, not null", String(typeof Platform.Function.IsEmailAddress("")), "boolean");
/* 9. Non-string primitives are coerced; an array throws. */
assert("a number argument is coerced and answered false", Platform.Function.IsEmailAddress(123) ? "true" : "false", "false");
assert("a boolean argument is coerced and answered false", Platform.Function.IsEmailAddress(true) ? "true" : "false", "false");
assertThrows("an empty array argument throws", function () {
return Platform.Function.IsEmailAddress([]);
});
assertThrows("an array holding a valid address throws rather than unwrapping it", function () {
return Platform.Function.IsEmailAddress(["test@example.com"]);
});
/* 10. The bare-name Core Library form exists after Platform.Load. */
assert("typeof the bare-name IsEmailAddress is function after Platform.Load", String(typeof IsEmailAddress), "function");
assert("the bare-name form answers true for a well-formed address", IsEmailAddress("test@example.com") ? "true" : "false", "true");
assert("the bare-name form answers false for a malformed value", IsEmailAddress("nope") ? "true" : "false", "false");
/* 11. Stringification. */
assert("the positive result stringifies to lowercase 'true'", "" + Platform.Function.IsEmailAddress("test@example.com"), "true");
assert("the negative result stringifies to lowercase 'false'", "" + Platform.Function.IsEmailAddress("nope"), "false");
</script>
Examples
var email = Platform.Request.GetFormField("email");
if (!Platform.Function.IsEmailAddress(email)) {
Write('<p class="error">Please enter a valid email address.</p>');
} else {
// Process valid email
Platform.Function.UpsertData("Signups", ["Email"], [email], ["Status"], ["pending"]);
Platform.Response.Redirect("/thank-you", false);
}
// In a validation function
function validateInput(input) {
if (!input.email) { return "Email is required"; }
if (!Platform.Function.IsEmailAddress(input.email)) { return "Invalid email format"; }
return null;
}
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Examples — the form-handler guard and the validateInput() helper.
*
* Proves the shape of both documented examples without performing their
* side effects (UpsertData / Redirect are not exercised here — this script
* proves only the branch decision that gates them):
* 1. Example 1 line 1: Platform.Request.GetFormField("email") is callable
* on a CloudPage GET, and returns null when no such field was posted.
* 2. Example 1's guard "!Platform.Function.IsEmailAddress(email)" is SAFE
* for that null: it does not throw, and it evaluates to true, so the
* error branch — not the UpsertData/Redirect branch — is taken when the
* form field is absent. This is the whole reason the example is written
* with the negated guard.
* 3. The same guard evaluates to false for a well-formed address, so the
* success branch is reachable and the example is not a constant.
* 4. The guard's operand is a genuine boolean, so "!" is a plain boolean
* negation rather than a coercion of a string or null.
* 5. Example 2's validateInput() helper, reproduced verbatim, returns:
* - "Email is required" for a missing / empty / absent email
* - "Invalid email format" for a present but malformed email
* - null for a valid email
* including the ORDER of its two guards — the required-check fires
* before the format-check, so an empty string yields "Email is
* required" and never "Invalid email format".
* 6. The falsy pre-check "if (!input.email)" is what makes example 2's
* required-branch reachable: IsEmailAddress("") is itself false, so
* without that pre-check an empty email would report the wrong message.
*
* SCOPE: evidence gathered on a CloudPage GET. UpsertData() and
* Platform.Response.Redirect() from example 1 are deliberately NOT invoked —
* they write data and terminate the response, and neither is a claim about
* IsEmailAddress.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
Platform.Response.Write((actual === expected ? "PASS " : "FAIL ") + id + " -> [" + actual + "]\n");
}
/* 1. Example 1 line 1. */
var email = Platform.Request.GetFormField("email");
assert("GetFormField('email') returns null when the field was not posted", email === null ? "true" : "false", "true");
/* 2 + 4. The guard is safe for that null and takes the error branch. */
var guardThrew = false;
var guardTookErrorBranch = false;
var guardOperandType = "";
try {
guardOperandType = typeof Platform.Function.IsEmailAddress(email);
if (!Platform.Function.IsEmailAddress(email)) { guardTookErrorBranch = true; }
} catch (ex) {
guardThrew = true;
}
assert("the example's guard does not throw on a null form field", guardThrew ? "true" : "false", "false");
assert("the guard's operand is a genuine boolean", String(guardOperandType), "boolean");
assert("a null form field takes the error branch, not the UpsertData branch", guardTookErrorBranch ? "true" : "false", "true");
/* 3. The success branch is reachable. */
var validTookErrorBranch = false;
if (!Platform.Function.IsEmailAddress("test@example.com")) { validTookErrorBranch = true; }
assert("a well-formed address does NOT take the error branch", validTookErrorBranch ? "true" : "false", "false");
/* 5 + 6. Example 2's helper, verbatim. */
function validateInput(input) {
if (!input.email) { return "Email is required"; }
if (!Platform.Function.IsEmailAddress(input.email)) { return "Invalid email format"; }
return null;
}
assert("validateInput reports the required error when email is absent", String(validateInput({})), "Email is required");
assert("validateInput reports the required error when email is an empty string", String(validateInput({ email: "" })), "Email is required");
assert("validateInput reports the required error when email is null", String(validateInput({ email: null })), "Email is required");
assert("validateInput reports the format error for a malformed email", String(validateInput({ email: "not-an-email" })), "Invalid email format");
assert("validateInput reports the format error for an address with no TLD", String(validateInput({ email: "user@example" })), "Invalid email format");
assert("validateInput returns null for a valid email", validateInput({ email: "test@example.com" }) === null ? "true" : "false", "true");
assert("validateInput returns null for a valid plus-tagged email", validateInput({ email: "first.last+tag@sub.example.co.uk" }) === null ? "true" : "false", "true");
assert("the required-check fires BEFORE the format-check for an empty email", String(validateInput({ email: "" })) === "Invalid email format" ? "true" : "false", "false");
</script>