Files
rentall-app/backend/services/email/core/emailUtils.js
2026-01-14 23:42:04 -05:00

116 lines
3.5 KiB
JavaScript

/**
* Email utility functions shared across all email services
*/
/**
* Convert HTML to plain text for email fallback
* Strips HTML tags and formats content for plain text email clients
* @param {string} html - HTML content to convert
* @returns {string} Plain text version of the HTML
*/
function htmlToPlainText(html) {
return (
html
// Remove style and script tags and their content
.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, "")
.replace(/<script[^>]*>[\s\S]*?<\/script>/gi, "")
// Convert common HTML elements to text equivalents
.replace(/<br\s*\/?>/gi, "\n")
.replace(/<\/p>/gi, "\n\n")
.replace(/<\/div>/gi, "\n")
.replace(/<\/li>/gi, "\n")
.replace(/<\/h[1-6]>/gi, "\n\n")
.replace(/<li>/gi, "• ")
// Remove remaining HTML tags
.replace(/<[^>]+>/g, "")
// Decode HTML entities
.replace(/&nbsp;/g, " ")
.replace(/&amp;/g, "&")
.replace(/&lt;/g, "<")
.replace(/&gt;/g, ">")
.replace(/&quot;/g, '"')
.replace(/&#39;/g, "'")
// Remove emojis and special characters that don't render well in plain text
.replace(/[\u{1F600}-\u{1F64F}]/gu, "") // Emoticons
.replace(/[\u{1F300}-\u{1F5FF}]/gu, "") // Misc Symbols and Pictographs
.replace(/[\u{1F680}-\u{1F6FF}]/gu, "") // Transport and Map
.replace(/[\u{2600}-\u{26FF}]/gu, "") // Misc symbols
.replace(/[\u{2700}-\u{27BF}]/gu, "") // Dingbats
.replace(/[\u{FE00}-\u{FE0F}]/gu, "") // Variation Selectors
.replace(/[\u{1F900}-\u{1F9FF}]/gu, "") // Supplemental Symbols and Pictographs
.replace(/[\u{1FA70}-\u{1FAFF}]/gu, "") // Symbols and Pictographs Extended-A
// Clean up excessive whitespace
.replace(/\n\s*\n\s*\n/g, "\n\n")
.trim()
);
}
/**
* Format a date consistently for email display
* @param {Date|string} date - Date to format
* @returns {string} Formatted date string
*/
function formatEmailDate(date) {
const dateObj = typeof date === "string" ? new Date(date) : date;
return dateObj.toLocaleString("en-US", {
weekday: "long",
year: "numeric",
month: "long",
day: "numeric",
hour: "numeric",
minute: "2-digit",
hour12: true,
});
}
/**
* Format a date as a short date (no time)
* @param {Date|string} date - Date to format
* @returns {string} Formatted date string
*/
function formatShortDate(date) {
const dateObj = typeof date === "string" ? new Date(date) : date;
return dateObj.toLocaleString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
}
/**
* Format currency for email display
* @param {number} amount - Amount in cents or smallest currency unit
* @param {string} currency - Currency code (default: USD)
* @returns {string} Formatted currency string
*/
function formatCurrency(amount, currency = "USD") {
return new Intl.NumberFormat("en-US", {
style: "currency",
currency: currency,
}).format(amount / 100);
}
/**
* Escape HTML special characters to prevent XSS attacks
* Converts characters that could be interpreted as HTML into safe entities
* @param {*} str - Value to escape (will be converted to string)
* @returns {string} HTML-escaped string safe for insertion into HTML
*/
function escapeHtml(str) {
if (str === null || str === undefined) return "";
return String(str)
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
module.exports = {
htmlToPlainText,
formatEmailDate,
formatShortDate,
formatCurrency,
escapeHtml,
};