feat: name dragged/exported .eml files as "date (from-to) subject" with ASCII-only chars
This commit is contained in:
@@ -0,0 +1,43 @@
|
||||
import type { Email } from "@/lib/jmap/types";
|
||||
|
||||
// Restrict filenames to ASCII letters/digits and a small set of safe
|
||||
// punctuation. Everything else collapses to `_`. Keeps names predictable
|
||||
// across Windows/macOS/Linux file systems and avoids emoji/RTL/zero-width
|
||||
// surprises in subject lines.
|
||||
const SAFE_CHARS = /[^A-Za-z0-9 _\-().,!@#&+=[\]{}']/g;
|
||||
|
||||
function sanitizePart(input: string, maxLen: number): string {
|
||||
const cleaned = input
|
||||
.replace(SAFE_CHARS, "_")
|
||||
.replace(/_+/g, "_")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim()
|
||||
.replace(/^[._-]+|[._-]+$/g, "");
|
||||
return cleaned.slice(0, maxLen);
|
||||
}
|
||||
|
||||
function formatDate(iso: string | null | undefined): string {
|
||||
const d = iso ? new Date(iso) : new Date();
|
||||
if (Number.isNaN(d.getTime())) return "0000-00-00 00.00.00";
|
||||
const pad = (n: number) => String(n).padStart(2, "0");
|
||||
return (
|
||||
`${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` +
|
||||
`${pad(d.getHours())}.${pad(d.getMinutes())}.${pad(d.getSeconds())}`
|
||||
);
|
||||
}
|
||||
|
||||
function addressLabel(addr: { name?: string | null; email: string } | undefined, maxLen = 30): string {
|
||||
if (!addr) return "unknown";
|
||||
const raw = (addr.name && addr.name.trim()) || addr.email.split("@")[0] || addr.email;
|
||||
return sanitizePart(raw, maxLen) || "unknown";
|
||||
}
|
||||
|
||||
// Produce `YYYY-MM-DD HH.mm.SS (from-to) subject.eml`. All components are
|
||||
// sanitized to ASCII-safe filename characters.
|
||||
export function emailExportFilename(email: Email): string {
|
||||
const date = formatDate(email.receivedAt || email.sentAt);
|
||||
const from = addressLabel(email.from?.[0]);
|
||||
const to = addressLabel(email.to?.[0]);
|
||||
const subject = sanitizePart(email.subject || "no subject", 80) || "no subject";
|
||||
return `${date} (${from}-${to}) ${subject}.eml`;
|
||||
}
|
||||
Reference in New Issue
Block a user