smtp-address-parser
Advanced tools
Comparing version 1.0.10 to 1.1.0
@@ -14,2 +14,7 @@ "use strict"; | ||
function parse(address) { | ||
// An insane length, to protect the parsing code from huge input. SMTP line limit, minus command size. | ||
const insane_length = 1000 - "MAIL FROM:<>\r\n".length; | ||
if (address.length > insane_length) { | ||
throw new Error("address too long"); | ||
} | ||
const parser = new nearley.Parser(grammar); | ||
@@ -20,2 +25,23 @@ parser.feed(address); | ||
} | ||
// Domain checks | ||
const at_idx = address.lastIndexOf('@'); // must be found, since parse was successful | ||
const domain = address.substring(at_idx + 1); | ||
if (domain[0] !== '[') { // Not an address literal | ||
if (domain.length > 253) { | ||
throw new Error("domain too long"); | ||
} | ||
const labels = domain.split("."); | ||
if (labels.length < 2) { | ||
throw new Error("domain not fully qualified"); | ||
} | ||
if (labels[labels.length - 1].length < 2) { | ||
throw new Error("top level domain label too short"); | ||
} | ||
labels.sort(function (a, b) { | ||
return b.length - a.length; | ||
}); | ||
if (labels[0].length > 63) { | ||
throw new Error("domain label too long"); | ||
} | ||
} | ||
return parser.results[0]; | ||
@@ -22,0 +48,0 @@ } |
@@ -25,5 +25,2 @@ "use strict"; | ||
}); | ||
it("local domain name with no TLD", function () { | ||
_check("admin@mailserver1", "admin", undefined, "mailserver1", undefined); | ||
}); | ||
it("space between the quotes", function () { | ||
@@ -35,2 +32,8 @@ _check('" "@example.org', undefined, '" "', "example.org", undefined); | ||
}); | ||
it("quoted string with angle brackets", function () { | ||
_check('"<john-doe>"@example.org', undefined, '"<john-doe>"', "example.org", undefined); | ||
}); | ||
it("quoted string with backslash escape", function () { | ||
_check('"\\<john-doe\\>"@example.org', undefined, '"\\<john-doe\\>"', "example.org", undefined); | ||
}); | ||
it('address in quoted local-part "john.doe@example.org"@example.org', function () { | ||
@@ -74,2 +77,7 @@ _check('"john.doe@example.org"@example.org', undefined, '"john.doe@example.org"', "example.org", undefined); | ||
describe("bad addresses fail", function () { | ||
it("local domain name with no TLD", function () { | ||
assert.throws(function () { | ||
parse("admin@mailserver1"); // Now fails. | ||
}); | ||
}); | ||
it('"foo@example.com+bob@attacker.com" is not an address', function () { | ||
@@ -167,2 +175,17 @@ assert.throws(function () { | ||
}); | ||
it("domain too long", function () { | ||
assert.throws(function () { | ||
parse("local-part@XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.xyz"); | ||
}); | ||
}); | ||
it("tld too short", function () { | ||
assert.throws(function () { | ||
parse("tld-too-short@foo.x"); | ||
}); | ||
}); | ||
it("label too long", function () { | ||
assert.throws(function () { | ||
parse("local-part@label_too_long_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.xyz"); | ||
}); | ||
}); | ||
}); | ||
@@ -169,0 +192,0 @@ describe("test normalize", function () { |
@@ -13,2 +13,10 @@ "use strict"; | ||
export function parse(address: string) { | ||
// An insane length, to protect the parsing code from huge input. SMTP line limit, minus command size. | ||
const insane_length = 1000 - "MAIL FROM:<>\r\n".length; | ||
if (address.length > insane_length) { | ||
throw new Error("address too long"); | ||
} | ||
const parser = new nearley.Parser(grammar); | ||
@@ -21,2 +29,25 @@ parser.feed(address); | ||
// Domain checks | ||
const at_idx = address.lastIndexOf('@'); // must be found, since parse was successful | ||
const domain = address.substring(at_idx + 1); | ||
if (domain[0] !== '[') { // Not an address literal | ||
if (domain.length > 253) { | ||
throw new Error("domain too long"); | ||
} | ||
const labels = domain.split("."); | ||
if (labels.length < 2) { | ||
throw new Error("domain not fully qualified"); | ||
} | ||
if (labels[labels.length - 1].length < 2) { | ||
throw new Error("top level domain label too short"); | ||
} | ||
labels.sort(function(a: string, b: string) { | ||
return b.length - a.length; | ||
}); | ||
if (labels[0].length > 63) { | ||
throw new Error("domain label too long"); | ||
} | ||
} | ||
return parser.results[0]; | ||
@@ -23,0 +54,0 @@ } |
{ | ||
"name": "smtp-address-parser", | ||
"version": "1.0.10", | ||
"version": "1.1.0", | ||
"description": "Parse an SMTP (RFC-5321) address", | ||
@@ -5,0 +5,0 @@ "main": "dist/lib/index.js", |
@@ -9,17 +9,23 @@ # smtp-address-parser | ||
Length limitations are not checked. | ||
** Changes in version 1.1.0: ** | ||
Technically a local-part of a Mailbox address is limited to 64 octets | ||
or less, see: <https://tools.ietf.org/html/rfc5321#section-4.5.3.1.1> | ||
** Domains are now checked beyond RFC-5321 syntax only ** | ||
Also, domain names are limited to 255 octets, see: | ||
<https://tools.ietf.org/html/rfc5321#section-4.5.3.1.2> | ||
Domain names must be fully qualified; that is with at least two labels. The top-level domain must have at least two octets. | ||
And individual labels within a domain name are limited to 63 | ||
octets or less, see: | ||
<https://tools.ietf.org/html/rfc1035> section 2.3.4. Size limits | ||
** Length limitations are now checked ** | ||
However, RFC-5321 section 4.5.3.1. “Size Limits and Minimums” says: | ||
Total length limit of an address is 986 octets; based on a 1,000 octet SMTP line length. | ||
See <https://tools.ietf.org/html/rfc1035> section 2.3.4. Size limits: | ||
Domain names are limited to 255 octets, when encoded with a length byte before each label, and including the top-level zero length label. So, the effctive limit with interstitial dots is 253 octets. | ||
Labels within a domain name are limited to 63 octets. | ||
The above are limits of the DNS protocol, not any particular implementation. | ||
RFC-5321 section 4.5.3.1. “Size Limits and Minimums” still says: | ||
“To the maximum extent possible, implementation techniques that impose | ||
no limits on the length of these objects should be used.” |
@@ -42,5 +42,2 @@ "use strict"; | ||
}); | ||
it("local domain name with no TLD", function () { | ||
_check("admin@mailserver1", "admin", undefined, "mailserver1", undefined); | ||
}); | ||
it("space between the quotes", function () { | ||
@@ -52,2 +49,8 @@ _check('" "@example.org', undefined, '" "', "example.org", undefined); | ||
}); | ||
it("quoted string with angle brackets", function () { | ||
_check('"<john-doe>"@example.org', undefined, '"<john-doe>"', "example.org", undefined); | ||
}); | ||
it("quoted string with backslash escape", function () { | ||
_check('"\\<john-doe\\>"@example.org', undefined, '"\\<john-doe\\>"', "example.org", undefined); | ||
}); | ||
it('address in quoted local-part "john.doe@example.org"@example.org', function () { | ||
@@ -92,2 +95,7 @@ _check('"john.doe@example.org"@example.org', undefined, '"john.doe@example.org"', "example.org", undefined); | ||
describe("bad addresses fail", function () { | ||
it("local domain name with no TLD", function () { | ||
assert.throws(function () { | ||
parse("admin@mailserver1"); // Now fails. | ||
}); | ||
}); | ||
it('"foo@example.com+bob@attacker.com" is not an address', function () { | ||
@@ -185,2 +193,17 @@ assert.throws(function () { | ||
}); | ||
it("domain too long", function () { | ||
assert.throws(function () { | ||
parse("local-part@XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.xyz"); | ||
}); | ||
}); | ||
it("tld too short", function () { | ||
assert.throws(function () { | ||
parse("tld-too-short@foo.x"); | ||
}); | ||
}); | ||
it("label too long", function () { | ||
assert.throws(function () { | ||
parse("local-part@label_too_long_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.xyz"); | ||
}); | ||
}); | ||
}); | ||
@@ -187,0 +210,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
78466
945
31