-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: update app to use email content templates
- Loading branch information
Anton Lilleby
authored and
Anton Lilleby
committed
Jan 15, 2025
1 parent
9aa4cd9
commit e7533eb
Showing
14 changed files
with
219 additions
and
348 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,18 +5,20 @@ import ical, { | |
ICalCalendarMethod, | ||
} from "ical-generator"; | ||
import { toHTML } from "@portabletext/to-html"; | ||
import { sendMail as sendEmail } from "../nodemailer"; | ||
import { composeEmail, sendEmail, wrapWithStyles } from "../nodemailer"; | ||
import { PUBLIC_APP_BASE_URL } from "$env/static/public"; | ||
import type { EventUpdatedProps } from "../../../routes/api/send-event-update/+server"; | ||
import type { EventUpdatedProps } from "../../../routes/api/send-event-updated/+server"; | ||
|
||
interface EventUpdatedExtendedProps extends EventUpdatedProps { | ||
interface EmailAcceptedProps extends EventUpdatedProps { | ||
to: string; | ||
} | ||
export const sendEmailUpdated = async (props: EventUpdatedExtendedProps) => { | ||
|
||
export const sendEmailAccepted = async (props: EmailAcceptedProps) => { | ||
const icsFile = createIcsFile(props); | ||
|
||
const emailTemplate = createEmailTemplate({ | ||
const emailTemplate = composeEmail({ | ||
...props, | ||
subject: `${props.subject} ${props.summary}`, | ||
icsFile, | ||
}); | ||
|
||
|
@@ -34,7 +36,7 @@ const createIcsFile = ({ | |
location, | ||
organiser, | ||
reminder, | ||
}: EventUpdatedExtendedProps) => { | ||
}: EmailAcceptedProps) => { | ||
const url = `${PUBLIC_APP_BASE_URL}/event/${id}`; | ||
const calendar = ical({ name: organiser, method: ICalCalendarMethod.REQUEST }); | ||
const alarms = []; | ||
|
@@ -43,7 +45,9 @@ const createIcsFile = ({ | |
alarms.push({ | ||
type: ICalAlarmType.email, | ||
summary: reminder.threeDaysSubject, | ||
description: reminder.threeDaysMessage ? toHTML(reminder.threeDaysMessage) : "", | ||
description: reminder.threeDaysMessage | ||
? wrapWithStyles(toHTML(reminder.threeDaysMessage)) | ||
: "", | ||
trigger: 259200, // ->3 days before event starts | ||
}); | ||
} | ||
|
@@ -52,7 +56,7 @@ const createIcsFile = ({ | |
alarms.push({ | ||
type: ICalAlarmType.email, | ||
summary: reminder.oneHourSubject, | ||
description: reminder.oneHourMessage ? toHTML(reminder.oneHourMessage) : "", | ||
description: reminder.oneHourMessage ? wrapWithStyles(toHTML(reminder.oneHourMessage)) : "", | ||
trigger: 3600, // -> 1 hour before event starts | ||
}); | ||
} | ||
|
@@ -81,21 +85,3 @@ const createIcsFile = ({ | |
|
||
return Buffer.from(calendar.toString()); | ||
}; | ||
|
||
interface EmailProps | ||
extends Pick<EventUpdatedExtendedProps, "to" | "subject" | "message" | "summary"> { | ||
icsFile: Buffer; | ||
} | ||
|
||
const createEmailTemplate = ({ to, subject, message, summary, icsFile }: EmailProps) => { | ||
return { | ||
to, | ||
from: "Skjer <[email protected]>", | ||
subject: `${subject} ${summary}`, | ||
html: toHTML(message), | ||
icalEvent: { | ||
method: "request", | ||
content: icsFile, | ||
}, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,22 @@ | ||
import { PUBLIC_APP_BASE_URL } from "$env/static/public"; | ||
import { sendMail as sendEmail } from "$lib/email/nodemailer"; | ||
import { toHTML } from "@portabletext/to-html"; | ||
import { composeEmail, sendEmail } from "$lib/email/nodemailer"; | ||
import ical, { ICalAttendeeRole, ICalAttendeeStatus, ICalCalendarMethod } from "ical-generator"; | ||
import type { EventCanceledProps } from "../../../routes/api/send-event-canceled/+server"; | ||
|
||
interface EventCanceledExtendedProps extends EventCanceledProps { | ||
interface EmailCanceledProps extends EventCanceledProps { | ||
to: string; | ||
} | ||
|
||
export const sendEmailCanceled = async (props: EventCanceledExtendedProps) => { | ||
export const sendEmailCanceled = async (props: EmailCanceledProps) => { | ||
const icsFile = createIcsFile(props); | ||
|
||
const emailTemplate = createEmailTemplate({ | ||
const email = composeEmail({ | ||
...props, | ||
subject: `${props.subject} ${props.summary}`, | ||
icsFile, | ||
}); | ||
|
||
const result = await sendEmail(emailTemplate); | ||
const result = await sendEmail(email); | ||
return result; | ||
}; | ||
|
||
|
@@ -29,7 +29,7 @@ const createIcsFile = ({ | |
end, | ||
location, | ||
organiser, | ||
}: EventCanceledExtendedProps) => { | ||
}: EmailCanceledProps) => { | ||
const url = `${PUBLIC_APP_BASE_URL}/event/${id}`; | ||
const calendar = ical({ name: organiser, method: ICalCalendarMethod.CANCEL }); | ||
calendar.createEvent({ | ||
|
@@ -55,21 +55,3 @@ const createIcsFile = ({ | |
|
||
return Buffer.from(calendar.toString()); | ||
}; | ||
|
||
interface EmailProps | ||
extends Pick<EventCanceledExtendedProps, "to" | "subject" | "message" | "summary"> { | ||
icsFile: Buffer; | ||
} | ||
|
||
const createEmailTemplate = ({ to, subject, message, summary, icsFile }: EmailProps) => { | ||
return { | ||
to, | ||
from: "Skjer <[email protected]>", | ||
subject: `${subject} ${summary}`, | ||
html: toHTML(message), | ||
icalEvent: { | ||
method: "request", | ||
content: icsFile, | ||
}, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { PUBLIC_APP_BASE_URL } from "$env/static/public"; | ||
import { sendEmail } from "$lib/email/nodemailer"; | ||
|
||
interface EmailConfirmDeclineProps { | ||
to: string; | ||
summary: string; | ||
organiser: string; | ||
token: string; | ||
} | ||
|
||
// TODO: Consider making this a function that takes a template from the Event Schema | ||
export const sendEmailConfirmDecline = async (props: EmailConfirmDeclineProps) => { | ||
const url = `${PUBLIC_APP_BASE_URL}/event/unregistration/${props.token}`; | ||
const html = `<span> | ||
<p>Hei,</p> | ||
<p>Vi har mottatt en forespørsel om å melde deg av «${props.summary}».</p> | ||
<p>For å bekrefte denne handlingen, vennligst klikk på følgende lenke:</p> | ||
<p><a href="${url}">Bekreft avregistrering</a></p> | ||
</span>`; | ||
|
||
const emailTemplate = { | ||
to: props.to, | ||
from: "Skjer <[email protected]>", | ||
subject: `Bekreft avregistrering: ${props.summary}`, | ||
html, | ||
}; | ||
|
||
const result = await sendEmail(emailTemplate); | ||
return result; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import ical, { ICalAttendeeRole, ICalAttendeeStatus, ICalCalendarMethod } from "ical-generator"; | ||
import { composeEmail, sendEmail } from "../nodemailer"; | ||
import { PUBLIC_APP_BASE_URL } from "$env/static/public"; | ||
import type { BlockContent } from "$models/sanity.model"; | ||
|
||
interface EmailDeclinedProps { | ||
id: string; | ||
to: string; | ||
summary: string; | ||
description?: string; | ||
start: string; | ||
end: string; | ||
location: string; | ||
organiser: string; | ||
subject: string; | ||
message: BlockContent; | ||
} | ||
|
||
export const sendEmailDeclined = async (props: EmailDeclinedProps) => { | ||
const icsFile = createIcsFile(props); | ||
|
||
const emailTemplate = composeEmail({ | ||
...props, | ||
subject: `${props.subject} ${props.summary}`, | ||
icsFile, | ||
}); | ||
|
||
const result = await sendEmail(emailTemplate); | ||
return result; | ||
}; | ||
|
||
const createIcsFile = ({ | ||
id, | ||
to, | ||
summary, | ||
description, | ||
start, | ||
end, | ||
location, | ||
organiser, | ||
}: EmailDeclinedProps) => { | ||
const url = `${PUBLIC_APP_BASE_URL}/event/${id}`; | ||
const calendar = ical({ name: organiser, method: ICalCalendarMethod.REQUEST }); | ||
|
||
calendar.createEvent({ | ||
id, | ||
summary, | ||
description, | ||
location, | ||
start, | ||
end, | ||
url, | ||
attendees: [ | ||
{ | ||
email: to, | ||
status: ICalAttendeeStatus.DECLINED, | ||
role: ICalAttendeeRole.REQ, | ||
}, | ||
], | ||
organizer: { | ||
name: organiser, | ||
email: "[email protected]", | ||
}, | ||
}); | ||
|
||
return Buffer.from(calendar.toString()); | ||
}; |
Oops, something went wrong.