Reading a message fetches its remote images through this server, so the sender learns nothing about the reader. Quoting the same message into a reply fetched them directly: same pixel, same reader, but the request carried their IP and user agent -- exactly what the proxy withholds. A quote now proxies them the way the message view does. That alone would be wrong, because a proxied URL belongs to this deployment: sent unchanged it would reach the recipient as images only this server can serve, broken for them and a beacon back here. So buildEmailObject turns them back into the addresses they came from, beside the pass that restores images blocked under pr411 and the one that turns editor blob URLs into cid: references. Deployments with the proxy off are unaffected: the quote fetches directly, as reading does there. Three tests from pr411 asserted the address sat in src when images were allowed, which was the old behaviour; they now ask whether the draft fetches it at all, proxied or not. No new strings.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import DOMPurify from "dompurify";
|
||||
import { withBase } from "@/lib/basePath";
|
||||
import { BASE_PATH, withBase } from "@/lib/basePath";
|
||||
|
||||
export interface SanitizeOptions {
|
||||
/** Map of Content-ID (without angle brackets) → URL for inline images. */
|
||||
@@ -158,6 +158,23 @@ export function proxiedImageUrl(url: string): string {
|
||||
return withBase(`/api/image?url=${encodeURIComponent(url)}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* The address a proxied image really points at, or null if this is not one.
|
||||
*
|
||||
* A proxied URL is this server's, so it is right for reading a message and
|
||||
* wrong for sending one: a quote left this way would hand the recipient
|
||||
* images that only load from inside this deployment (#412).
|
||||
*/
|
||||
export function unproxiedImageUrl(src: string): string | null {
|
||||
const path = `${BASE_PATH}/api/image?url=`;
|
||||
if (!src.startsWith(path)) return null;
|
||||
try {
|
||||
return decodeURIComponent(src.slice(path.length)) || null;
|
||||
} catch {
|
||||
return null; // Malformed escape: leave it alone rather than mangle it.
|
||||
}
|
||||
}
|
||||
|
||||
export function sanitizeEmailHtml(input: string, opts: SanitizeOptions = {}): SanitizeResult {
|
||||
ensureHooks();
|
||||
let bodyStyle = "";
|
||||
|
||||
Reference in New Issue
Block a user