ultisuite-client/lib/strip-executable-email-html.ts
R3D347HR4Y 8a02c10ba3 Add environment configuration and update email view components
- Created a .cursorignore file to manage local environment files.
- Updated .env.example to reflect changes in the public app URL.
- Modified the gmail workspace configuration to include the drive-suite path.
- Enhanced email view components to support attachment handling and fallback for plain text bodies.
- Improved user experience by updating attachment display logic and integrating inline attachment support.
2026-06-04 00:12:43 +02:00

68 lines
2.2 KiB
TypeScript

/**
* Remove scripts and other executable markup before displaying mail HTML.
* DOM-only (no broad regex) so newsletter markup is not corrupted.
*/
const EXECUTABLE_SELECTOR =
"script, iframe, object, embed, frame, frameset, link[rel='import'], link[as='script']"
const EVENT_HANDLER_ATTR = /^on/i
const URI_ATTRS = /^(?:href|src|srcset|data|action|formaction|xlink:href)$/i
const JAVASCRIPT_URI = /^javascript:/i
function stripExecutableFromDocument(doc: Document): void {
doc.querySelectorAll(EXECUTABLE_SELECTOR).forEach((el) => el.remove())
doc.querySelectorAll("svg script").forEach((el) => el.remove())
// <noscript> content is visible when scripts are blocked — unwrap it
for (const ns of doc.querySelectorAll("noscript")) {
const fragment = doc.createDocumentFragment()
const tpl = doc.createElement("template")
tpl.innerHTML = ns.textContent ?? ""
fragment.append(...Array.from(tpl.content.childNodes))
ns.replaceWith(fragment)
}
for (const el of doc.querySelectorAll("*")) {
for (const attr of [...el.attributes]) {
if (EVENT_HANDLER_ATTR.test(attr.name)) {
el.removeAttribute(attr.name)
continue
}
if (URI_ATTRS.test(attr.name) && JAVASCRIPT_URI.test(attr.value.trim())) {
el.removeAttribute(attr.name)
}
}
const style = el.getAttribute("style")
if (style && JAVASCRIPT_URI.test(style)) {
el.setAttribute(
"style",
style.replace(/javascript:[^;'")]+/gi, "about:blank")
)
}
}
for (const meta of doc.querySelectorAll('meta[http-equiv]')) {
if (meta.getAttribute("http-equiv")?.toLowerCase() !== "refresh") continue
const content = meta.getAttribute("content") ?? ""
if (JAVASCRIPT_URI.test(content)) meta.remove()
}
}
/** Strip scripts, nested frames, and inline handlers from an HTML fragment. */
export function stripExecutableEmailHtml(html: string): string {
if (!html || !html.trim()) return html
if (typeof DOMParser === "undefined") {
return html
}
try {
const doc = new DOMParser().parseFromString(html, "text/html")
stripExecutableFromDocument(doc)
return doc.body?.innerHTML ?? html
} catch {
return html
}
}