Files
govoplan-mail/webui/src/features/mail/mailAddressIntegration.ts
T

45 lines
1.6 KiB
TypeScript

type MailAddressLookupCandidateLike = {
display_name: string;
email?: string | null;
};
export type MailAddressValue = {
name?: string | null;
email: string;
};
const EMAIL_PATTERN = /([^<>;,\s]+@[^<>;,\s]+)/g;
export function mailLookupSuggestions(candidates: readonly MailAddressLookupCandidateLike[]): MailAddressValue[] {
const seen = new Set<string>();
const suggestions: MailAddressValue[] = [];
for (const candidate of candidates) {
const email = String(candidate.email ?? "").trim().toLocaleLowerCase();
if (!email || seen.has(email)) continue;
seen.add(email);
suggestions.push({ name: candidate.display_name || email, email });
}
return suggestions;
}
export function mailboxHeaderAddresses(value?: string | null): MailAddressValue[] {
const input = String(value ?? "").trim();
if (!input) return [];
const results: MailAddressValue[] = [];
const seen = new Set<string>();
for (const match of input.matchAll(EMAIL_PATTERN)) {
const email = match[1]?.replace(/[)>]+$/, "").toLocaleLowerCase();
if (!email || seen.has(email)) continue;
seen.add(email);
const prefix = input.slice(Math.max(0, input.lastIndexOf(",", match.index) + 1), match.index).trim();
const name = prefix.replace(/[<"']/g, "").trim() || undefined;
results.push({ name, email });
}
return results;
}
export function mailtoHref(recipients: readonly MailAddressValue[]): string {
const addresses = recipients.map((recipient) => recipient.email.trim()).filter(Boolean);
return `mailto:${addresses.map(encodeURIComponent).join(",")}`;
}