diff --git a/lib/calendarClient.ts b/lib/calendarClient.ts
index 8bded41027..1e7aab3653 100644
--- a/lib/calendarClient.ts
+++ b/lib/calendarClient.ts
@@ -1,5 +1,4 @@
import EventOrganizerMail from "./emails/EventOrganizerMail";
-import EventAttendeeMail from "./emails/EventAttendeeMail";
import EventOrganizerRescheduledMail from "./emails/EventOrganizerRescheduledMail";
import EventAttendeeRescheduledMail from "./emails/EventAttendeeRescheduledMail";
import prisma from "./prisma";
@@ -120,6 +119,10 @@ export interface CalendarEvent {
startTime: string;
endTime: string;
description?: string;
+ team?: {
+ name: string;
+ members: string[];
+ };
location?: string;
organizer: Person;
attendees: Person[];
@@ -574,25 +577,11 @@ const createEvent = async (
entryPoints: maybeEntryPoints,
});
- const attendeeMail = new EventAttendeeMail(calEvent, uid, {
- hangoutLink: maybeHangoutLink,
- conferenceData: maybeConferenceData,
- entryPoints: maybeEntryPoints,
- });
-
try {
await organizerMail.sendEmail();
} catch (e) {
console.error("organizerMail.sendEmail failed", e);
}
-
- if (!creationResult || !creationResult.disableConfirmationEmail) {
- try {
- await attendeeMail.sendEmail();
- } catch (e) {
- console.error("attendeeMail.sendEmail failed", e);
- }
- }
}
return {
diff --git a/lib/emails/EventAttendeeMail.ts b/lib/emails/EventAttendeeMail.ts
index f53fb6f9b8..cf9ea78f14 100644
--- a/lib/emails/EventAttendeeMail.ts
+++ b/lib/emails/EventAttendeeMail.ts
@@ -65,7 +65,13 @@ export default class EventAttendeeMail extends EventMail {
| Who |
- ${this.calEvent.organizer.name} ${this.calEvent.organizer.email} |
+
+ ${this.calEvent.team?.name || this.calEvent.organizer.name}
+
+ ${this.calEvent.organizer.email && !this.calEvent.team ? this.calEvent.organizer.email : ""}
+ ${this.calEvent.team ? this.calEvent.team.members.join(", ") : ""}
+
+ |
| Where |
@@ -122,6 +128,10 @@ export default class EventAttendeeMail extends EventMail {
return ``;
}
+ protected getAdditionalFooter(): string {
+ return this.parser.getChangeEventFooterHtml();
+ }
+
/**
* Returns the payload object for the nodemailer.
*
@@ -133,7 +143,7 @@ export default class EventAttendeeMail extends EventMail {
from: `${this.calEvent.organizer.name} <${this.getMailerOptions().from}>`,
replyTo: this.calEvent.organizer.email,
subject: `Confirmed: ${this.calEvent.type} with ${
- this.calEvent.organizer.name
+ this.calEvent.team?.name || this.calEvent.organizer.name
} on ${this.getInviteeStart().format("LT dddd, LL")}`,
html: this.getHtmlRepresentation(),
text: this.getPlainTextRepresentation(),
diff --git a/lib/emails/EventAttendeeRescheduledMail.ts b/lib/emails/EventAttendeeRescheduledMail.ts
index 1286c7ab7f..92592df3e2 100644
--- a/lib/emails/EventAttendeeRescheduledMail.ts
+++ b/lib/emails/EventAttendeeRescheduledMail.ts
@@ -13,8 +13,8 @@ export default class EventAttendeeRescheduledMail extends EventAttendeeMail {
Hi ${this.calEvent.attendees[0].name},
Your ${this.calEvent.type} with ${
- this.calEvent.organizer.name
- } has been rescheduled to ${this.getInviteeStart().format("h:mma")}
+ this.calEvent.team?.name || this.calEvent.organizer.name
+ } has been rescheduled to ${this.getInviteeStart().format("h:mma")}
(${this.calEvent.attendees[0].timeZone}) on ${this.getInviteeStart().format("dddd, LL")}.
` +
this.getAdditionalFooter() +
diff --git a/lib/emails/EventMail.ts b/lib/emails/EventMail.ts
index b3728872e6..3fa6eb5140 100644
--- a/lib/emails/EventMail.ts
+++ b/lib/emails/EventMail.ts
@@ -69,7 +69,7 @@ export default abstract class EventMail {
/**
* Sends the email to the event attendant and returns a Promise.
*/
- public sendEmail(): Promise {
+ public sendEmail() {
new Promise((resolve, reject) =>
nodemailer
.createTransport(this.getMailerOptions().transport)
@@ -90,7 +90,7 @@ export default abstract class EventMail {
*
* @protected
*/
- protected getMailerOptions(): any {
+ protected getMailerOptions() {
return {
transport: serverConfig.transport,
from: serverConfig.from,
@@ -135,12 +135,4 @@ export default abstract class EventMail {
protected getCancelLink(): string {
return this.parser.getCancelLink();
}
-
- /**
- * Defines a footer that will be appended to the email.
- * @protected
- */
- protected getAdditionalFooter(): string {
- return this.parser.getChangeEventFooterHtml();
- }
}
diff --git a/lib/emails/EventOrganizerMail.ts b/lib/emails/EventOrganizerMail.ts
index e5ee36b743..c24267895d 100644
--- a/lib/emails/EventOrganizerMail.ts
+++ b/lib/emails/EventOrganizerMail.ts
@@ -50,8 +50,10 @@ export default class EventOrganizerMail extends EventMail {
return "A new event has been scheduled.";
}
- protected getBodyText(): string {
- return "You and any other attendees have been emailed with this information.";
+ protected getAdditionalFooter(): string {
+ return `Need to make a change? Manage my bookings
`;
}
protected getImage(): string {
@@ -94,7 +96,6 @@ export default class EventOrganizerMail extends EventMail {
>
${this.getImage()}
${this.getBodyHeader()}
- ${this.getBodyText()}
diff --git a/lib/events/EventManager.ts b/lib/events/EventManager.ts
index f40fb49b87..f4af4217af 100644
--- a/lib/events/EventManager.ts
+++ b/lib/events/EventManager.ts
@@ -6,6 +6,7 @@ import prisma from "@lib/prisma";
import { LocationType } from "@lib/location";
import { v5 as uuidv5 } from "uuid";
import merge from "lodash.merge";
+import EventAttendeeMail from "@lib/emails/EventAttendeeMail";
export interface EventResult {
type: string;
@@ -65,10 +66,25 @@ export default class EventManager {
// First, create all calendar events. If this is a dedicated integration event, don't send a mail right here.
const results: Array = await this.createAllCalendarEvents(event, isDedicated, maybeUid);
-
// If and only if event type is a dedicated meeting, create a dedicated video meeting as well.
if (isDedicated) {
results.push(await this.createVideoEvent(event, maybeUid));
+ } else {
+ if (!results.length || !results.some((eRes) => eRes.createdEvent.disableConfirmationEmail)) {
+ const metadata: { hangoutLink?: string; conferenceData?: unknown; entryPoints?: unknown } = {};
+ if (results.length) {
+ // TODO: Handle created event metadata more elegantly
+ metadata.hangoutLink = results[0].createdEvent?.hangoutLink;
+ metadata.conferenceData = results[0].createdEvent?.conferenceData;
+ metadata.entryPoints = results[0].createdEvent?.entryPoints;
+ }
+ const attendeeMail = new EventAttendeeMail(event, maybeUid, metadata);
+ try {
+ await attendeeMail.sendEmail();
+ } catch (e) {
+ console.error("attendeeMail.sendEmail failed", e);
+ }
+ }
}
const referencesToCreate: Array = results.map((result) => {
diff --git a/pages/api/book/[user].ts b/pages/api/book/[user].ts
index 6950c76134..e509f1e739 100644
--- a/pages/api/book/[user].ts
+++ b/pages/api/book/[user].ts
@@ -5,7 +5,6 @@ import { CalendarEvent, getBusyCalendarTimes } from "@lib/calendarClient";
import { v5 as uuidv5 } from "uuid";
import short from "short-uuid";
import { getBusyVideoTimes } from "@lib/videoClient";
-import EventAttendeeMail from "../../../lib/emails/EventAttendeeMail";
import { getEventName } from "@lib/event";
import dayjs from "dayjs";
import logger from "../../../lib/logger";
@@ -15,7 +14,6 @@ import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
import isBetween from "dayjs/plugin/isBetween";
import dayjsBusinessDays from "dayjs-business-days";
-import { Exception } from "handlebars";
import EventOrganizerRequestMail from "@lib/emails/EventOrganizerRequestMail";
dayjs.extend(dayjsBusinessDays);
@@ -81,25 +79,6 @@ function isOutOfBounds(
}
}
-export async function handleLegacyConfirmationMail(
- results: Array,
- eventType: EventType,
- evt: CalendarEvent,
- hashUID: string
-): Promise<{ error: Exception; message: string | null }> {
- if (results.length === 0 && !eventType.requiresConfirmation) {
- // Legacy as well, as soon as we have a separate email integration class. Just used
- // to send an email even if there is no integration at all.
- try {
- const mail = new EventAttendeeMail(evt, hashUID);
- await mail.sendEmail();
- } catch (e) {
- return { error: e, message: "Booking failed" };
- }
- }
- return null;
-}
-
export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise {
const { user } = req.query;
log.debug(`Booking ${user} started`);
@@ -311,13 +290,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
results.length > 0 ? results[0].uid : translator.fromUUID(uuidv5(JSON.stringify(evt), uuidv5.URL));
// TODO Should just be set to the true case as soon as we have a "bare email" integration class.
// UID generation should happen in the integration itself, not here.
- const legacyMailError = await handleLegacyConfirmationMail(results, eventType, evt, hashUID);
- if (legacyMailError) {
- log.error("Sending legacy event mail failed", legacyMailError.error);
- log.error(`Booking ${user} failed`);
- res.status(500).json({ message: legacyMailError.message });
- return;
- }
try {
await prisma.booking.create({