diff --git a/lib/CalEventParser.ts b/lib/CalEventParser.ts
new file mode 100644
index 00000000..4668fb77
--- /dev/null
+++ b/lib/CalEventParser.ts
@@ -0,0 +1,108 @@
+import { CalendarEvent } from "./calendarClient";
+import { v5 as uuidv5 } from "uuid";
+import short from "short-uuid";
+import { stripHtml } from "./emails/helpers";
+
+const translator = short();
+
+export default class CalEventParser {
+ calEvent: CalendarEvent;
+
+ constructor(calEvent: CalendarEvent) {
+ this.calEvent = calEvent;
+ }
+
+ /**
+ * Returns a link to reschedule the given booking.
+ */
+ public getRescheduleLink(): string {
+ return process.env.BASE_URL + "/reschedule/" + this.getUid();
+ }
+
+ /**
+ * Returns a link to cancel the given booking.
+ */
+ public getCancelLink(): string {
+ return process.env.BASE_URL + "/cancel/" + this.getUid();
+ }
+
+ /**
+ * Returns a unique identifier for the given calendar event.
+ */
+ public getUid(): string {
+ return translator.fromUUID(uuidv5(JSON.stringify(this.calEvent), uuidv5.URL));
+ }
+
+ /**
+ * Returns a footer section with links to change the event (as HTML).
+ */
+ public getChangeEventFooterHtml(): string {
+ return `
+
+
+ Need to change this event?
+ Cancel: ${this.getCancelLink()}
+ Reschedule: ${this.getRescheduleLink()}
+ `;
+ }
+
+ /**
+ * Returns a footer section with links to change the event (as plain text).
+ */
+ public getChangeEventFooter(): string {
+ return stripHtml(this.getChangeEventFooterHtml());
+ }
+
+ /**
+ * Returns an extended description with all important information (as HTML).
+ *
+ * @protected
+ */
+ public getRichDescriptionHtml(): string {
+ return (
+ `
+