Fix highlighting and all rich text formatting in emails by converting HTML tags to inline styles before sending. Email clients strip <style> blocks, so inline styles are the only reliable method. Changes: - Convert <mark> tags to <span> with inline background-color (#fef08a) - Add inline styles to all rich text elements (strong, em, u, s, headings, lists) - Process HTML conversion in email API before sending - Simplified email template by removing unreliable <style> block - All formatting now uses inline styles directly on elements This ensures highlights and all other formatting (bold, italic, underline, strikethrough, headings, lists) render correctly across all email clients including Gmail, Outlook, Apple Mail, etc. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
125 lines
3.8 KiB
TypeScript
125 lines
3.8 KiB
TypeScript
import { getSermonNote, getSermonBySlug, getUserByUsername, getDatabase } from '~/server/utils/database'
|
|
import { getSessionUsername } from '~/server/utils/auth'
|
|
import { sendSermonNotesEmail } from '~/server/utils/email'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const username = await getSessionUsername(event)
|
|
|
|
if (!username) {
|
|
throw createError({
|
|
statusCode: 401,
|
|
message: 'Unauthorized'
|
|
})
|
|
}
|
|
|
|
const sermonId = parseInt(event.context.params?.sermonId || '')
|
|
|
|
if (!sermonId) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
message: 'Invalid sermon ID'
|
|
})
|
|
}
|
|
|
|
// Get user info
|
|
const user = getUserByUsername(username)
|
|
if (!user || !user.email) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
message: 'User email not found'
|
|
})
|
|
}
|
|
|
|
// Get sermon info
|
|
const db = getDatabase()
|
|
const sermon = db.prepare('SELECT * FROM sermons WHERE id = ?').get(sermonId) as any
|
|
|
|
if (!sermon) {
|
|
throw createError({
|
|
statusCode: 404,
|
|
message: 'Sermon not found'
|
|
})
|
|
}
|
|
|
|
// Get user's notes (already stored as HTML from rich text editor)
|
|
const noteRecord = getSermonNote(user.id!, sermonId)
|
|
let userNotes = noteRecord?.notes || '<p>No notes taken</p>'
|
|
|
|
// Convert Tiptap HTML to email-friendly HTML with inline styles
|
|
// Email clients don't support <style> blocks well, so we need inline styles
|
|
userNotes = userNotes
|
|
// Convert <mark> to <span> with inline background color (email clients often don't support <mark>)
|
|
.replace(/<mark>/gi, '<span style="background-color: #fef08a; padding: 2px 4px; border-radius: 2px;">')
|
|
.replace(/<\/mark>/gi, '</span>')
|
|
// Add inline styles to other elements
|
|
.replace(/<strong>/gi, '<strong style="font-weight: 700;">')
|
|
.replace(/<em>/gi, '<em style="font-style: italic;">')
|
|
.replace(/<u>/gi, '<u style="text-decoration: underline;">')
|
|
.replace(/<s>/gi, '<s style="text-decoration: line-through;">')
|
|
.replace(/<h2>/gi, '<h2 style="font-size: 1.5em; font-weight: 700; margin: 1em 0 0.5em; color: #333;">')
|
|
.replace(/<h3>/gi, '<h3 style="font-size: 1.25em; font-weight: 600; margin: 0.75em 0 0.5em; color: #333;">')
|
|
.replace(/<ul>/gi, '<ul style="padding-left: 1.5em; margin: 0.5em 0;">')
|
|
.replace(/<ol>/gi, '<ol style="padding-left: 1.5em; margin: 0.5em 0;">')
|
|
.replace(/<li>/gi, '<li style="margin: 0.25em 0;">')
|
|
.replace(/<p>/gi, '<p style="margin: 0.5em 0;">')
|
|
|
|
// Format bible references for HTML email
|
|
let bibleReferencesText = ''
|
|
try {
|
|
const refs = JSON.parse(sermon.bible_references)
|
|
bibleReferencesText = refs.map((ref: any) =>
|
|
`<div style="margin-bottom: 15px;">
|
|
<div style="font-weight: bold; margin-bottom: 5px;">${ref.reference} (${ref.version})</div>
|
|
<div>${ref.text}</div>
|
|
</div>`
|
|
).join('')
|
|
} catch {
|
|
bibleReferencesText = sermon.bible_references
|
|
}
|
|
|
|
// Format date
|
|
const formatDate = (dateString: string) => {
|
|
const date = new Date(dateString + 'T00:00:00')
|
|
return date.toLocaleDateString('en-US', {
|
|
year: 'numeric',
|
|
month: 'long',
|
|
day: 'numeric'
|
|
})
|
|
}
|
|
|
|
const dates = [sermon.date]
|
|
if (sermon.dates) {
|
|
try {
|
|
const additionalDates = JSON.parse(sermon.dates)
|
|
dates.push(...additionalDates)
|
|
} catch {}
|
|
}
|
|
const sermonDate = dates.map(formatDate).join(' - ')
|
|
|
|
// Send email
|
|
try {
|
|
await sendSermonNotesEmail(
|
|
user.email,
|
|
user.first_name || user.username,
|
|
sermon.title,
|
|
sermonDate,
|
|
bibleReferencesText,
|
|
sermon.personal_appliance,
|
|
sermon.pastors_challenge,
|
|
userNotes,
|
|
event
|
|
)
|
|
|
|
return {
|
|
success: true,
|
|
message: 'Notes emailed successfully'
|
|
}
|
|
} catch (error) {
|
|
console.error('Failed to send email:', error)
|
|
throw createError({
|
|
statusCode: 500,
|
|
message: 'Failed to send email'
|
|
})
|
|
}
|
|
})
|