From c292c4bc6b9099c2986b3afb8fdc2e7602c6b103 Mon Sep 17 00:00:00 2001 From: Lucas Cantor Date: Fri, 13 Jun 2025 09:48:09 -0700 Subject: [PATCH 1/2] Add ExtractEmails.js Extracts, deduplicates, and sorts email addresses from your text --- Scripts/ExtractEmails.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Scripts/ExtractEmails.js diff --git a/Scripts/ExtractEmails.js b/Scripts/ExtractEmails.js new file mode 100644 index 00000000..c8fe6d05 --- /dev/null +++ b/Scripts/ExtractEmails.js @@ -0,0 +1,34 @@ +/** + { + "api":1, + "name":"Extract Emails", + "description":"Extracts, deduplicates, and sorts email addresses from your text", + "author":"Lucas Cantor", + "icon":"at", + "tags":"email,extract,unique,deduplicate,sort" + } +**/ + +function main(state) { + // Regex to extract email addresses + const emailRegex = /[a-zA-Z0-9+._-]+@[a-zA-Z0-9._-]+/g; + const text = state.text || ""; + const matches = text.match(emailRegex) || []; + + // Deduplicate email addresses (case-insensitive) + const seen = new Set(); + const uniqueEmails = []; + for (const email of matches) { + const lower = email.toLowerCase(); + if (!seen.has(lower)) { + seen.add(lower); + uniqueEmails.push(email); + } + } + + // Sort email addresses (case-insensitive) + uniqueEmails.sort((a, b) => a.toLowerCase().localeCompare(b.toLowerCase())); + + // Output email address one per line + state.text = uniqueEmails.join('\n'); +} From 0bfced2cef189fcc95f6adff70b270fe1c6fa8bc Mon Sep 17 00:00:00 2001 From: Lucas Cantor Date: Fri, 13 Jun 2025 09:53:08 -0700 Subject: [PATCH 2/2] avoid ReDoS vulnerabilities --- Scripts/ExtractEmails.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/ExtractEmails.js b/Scripts/ExtractEmails.js index c8fe6d05..badcb65f 100644 --- a/Scripts/ExtractEmails.js +++ b/Scripts/ExtractEmails.js @@ -10,8 +10,8 @@ **/ function main(state) { - // Regex to extract email addresses - const emailRegex = /[a-zA-Z0-9+._-]+@[a-zA-Z0-9._-]+/g; + // Regex to extract email addresses while avoiding ReDoS vulnerabilities + const emailRegex = /\b[A-Za-z0-9](?:[A-Za-z0-9._+-]*[A-Za-z0-9])?@[A-Za-z0-9](?:[A-Za-z0-9.-]*[A-Za-z0-9])?\.[A-Za-z]{2,}\b/g; const text = state.text || ""; const matches = text.match(emailRegex) || [];