52 lines
1.6 KiB
TypeScript
52 lines
1.6 KiB
TypeScript
/** Détecte les ressources distantes dans le HTML d'un mail. */
|
|
|
|
const REMOTE_RESOURCE_ATTR =
|
|
/\s(?:src|srcset|data-src|data-original|data-srcset|poster|background|data)\s*=\s*["']?(?:https?:\/\/|\/\/)/i
|
|
|
|
const RELATIVE_RESOURCE_ATTR =
|
|
/\s(?:src|srcset|data-src|data-original|href|background|poster)\s*=\s*["'](?!https?:|\/\/|data:|cid:|mailto:|#|javascript:)([^"']+)["']/i
|
|
|
|
const REMOTE_LINK_STYLESHEET =
|
|
/<link[^>]+href\s*=\s*["']?(?:https?:\/\/|\/\/)/i
|
|
|
|
const CSS_REMOTE_URL = /url\s*\(\s*['"]?(?:https?:\/\/|\/\/|[^'"data:#][^'")]*)/i
|
|
|
|
export function htmlHasRemoteContent(html: string): boolean {
|
|
if (!html?.trim()) return false
|
|
|
|
const hasRemoteSignals =
|
|
REMOTE_RESOURCE_ATTR.test(html) ||
|
|
RELATIVE_RESOURCE_ATTR.test(html) ||
|
|
REMOTE_LINK_STYLESHEET.test(html) ||
|
|
CSS_REMOTE_URL.test(html)
|
|
|
|
if (hasRemoteSignals) return true
|
|
|
|
if (/<!DOCTYPE|<html[\s>]/i.test(html)) {
|
|
return (
|
|
/<img\b/i.test(html) ||
|
|
/<link[^>]+rel=["']?stylesheet/i.test(html) ||
|
|
/<style\b/i.test(html)
|
|
)
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
export function buildEmailPreviewCsp(blockRemoteContent: boolean): string {
|
|
if (blockRemoteContent) {
|
|
return "default-src 'none'; style-src 'unsafe-inline'; img-src data: blob:;"
|
|
}
|
|
return [
|
|
"default-src 'none'",
|
|
"style-src 'unsafe-inline' https: http:",
|
|
"style-src-elem 'unsafe-inline' https: http:",
|
|
// url() in style="" (Gmail signatures often use background-image on table cells)
|
|
"style-src-attr 'unsafe-inline' https: http:",
|
|
"img-src https: http: data: blob: cid:",
|
|
"font-src https: http: data:",
|
|
"media-src https: http:",
|
|
"child-src https: http:",
|
|
].join("; ")
|
|
}
|