Mask Email Addresses for Logs
Mask the local part of email addresses while preserving the domain, with short-address handling and an option to hide subdomains.
Code
export function maskEmail(email, options = {}) {
if (typeof email !== "string") {
throw new TypeError("email must be a string");
}
const { maskDomain = false } = options;
const address = email.trim();
if (address.length === 0 || address.length > 254) {
throw new Error("invalid email length");
}
if (/\s/.test(address)) {
throw new Error("invalid email address");
}
const atIndex = address.indexOf("@");
if (
atIndex <= 0 ||
atIndex !== address.lastIndexOf("@") ||
atIndex === address.length - 1
) {
throw new Error("invalid email address");
}
const local = address.slice(0, atIndex);
const domain = address.slice(atIndex + 1);
if (
!domain.includes(".") ||
domain.startsWith(".") ||
domain.endsWith(".") ||
domain.includes("..")
) {
throw new Error("invalid email domain");
}
let maskedLocal;
if (local.length === 1) {
maskedLocal = "*";
} else if (local.length === 2) {
maskedLocal = `${local[0]}*`;
} else {
maskedLocal = `${local[0]}***${local[local.length - 1]}`;
}
let maskedDomain = domain;
if (maskDomain) {
const labels = domain.split(".");
maskedDomain = labels
.map((label, index) =>
index === labels.length - 1 ? label : "*".repeat(Math.max(1, label.length)),
)
.join(".");
}
return `${maskedLocal}@${maskedDomain}`;
}
console.log(maskEmail("[email protected]"));
console.log(maskEmail("[email protected]"));
console.log(maskEmail("[email protected]"));
console.log(maskEmail("[email protected]", { maskDomain: true }));
try {
maskEmail("not-an-email");
} catch (error) {
console.log(error.message);
}Report a problem with this exampleOpens a pre-filled issue on GitHub.