import {CalendarEvent} from "../calendarClient";
import {createEvent} from "ics";
import dayjs, {Dayjs} from "dayjs";
import {serverConfig} from "../serverConfig";
import nodemailer from 'nodemailer';
export default class EventOwnerMail {
calEvent: CalendarEvent;
/**
* An EventOwnerMail always consists of a CalendarEvent
* that stores the very basic data of the event (like date, title etc).
*
* @param calEvent
*/
constructor(calEvent: CalendarEvent) {
this.calEvent = calEvent;
}
/**
* Returns the instance's event as an iCal event in string representation.
* @protected
*/
protected getiCalEventAsString(): string {
const icsEvent = createEvent({
start: dayjs(this.calEvent.startTime).utc().toArray().slice(0, 6),
startInputType: 'utc',
productId: 'calendso/ics',
title: `${this.calEvent.type} with ${this.calEvent.attendees[0].name}`,
description: this.calEvent.description + this.stripHtml(this.getAdditionalBody()),
duration: {minutes: dayjs(this.calEvent.endTime).diff(dayjs(this.calEvent.startTime), 'minute')},
organizer: {name: this.calEvent.organizer.name, email: this.calEvent.organizer.email},
attendees: this.calEvent.attendees.map((attendee: any) => ({name: attendee.name, email: attendee.email})),
status: "CONFIRMED",
});
if (icsEvent.error) {
throw icsEvent.error;
}
return icsEvent.value;
}
/**
* Returns the email text as HTML representation.
*
* @protected
*/
protected getHtmlRepresentation(): string {
return `
Hi ${this.calEvent.organizer.name},
A new event has been scheduled.
Event Type:
${this.calEvent.type}
Invitee Email:
${this.calEvent.attendees[0].email}
` + this.getAdditionalBody() +
(
this.calEvent.location ? `
Location:
${this.calEvent.location}
` : ''
) +
`
Invitee Time Zone:
${this.calEvent.attendees[0].timeZone}
Additional notes:
${this.calEvent.description}
`;
}
/**
* Returns the email text in a plain text representation
* by stripping off the HTML tags.
*
* @protected
*/
protected getPlainTextRepresentation(): string {
return this.stripHtml(this.getHtmlRepresentation());
}
/**
* Strips off all HTML tags and leaves plain text.
*
* @param html
* @protected
*/
protected stripHtml(html: string): string {
return html
.replace('
', "\n")
.replace(/<[^>]+>/g, '');
}
/**
* Sends the email to the event attendant and returns a Promise.
*/
public sendEmail(): Promise {
const options = this.getMailerOptions();
const {transport, from} = options;
const organizerStart: Dayjs = dayjs(this.calEvent.startTime).tz(this.calEvent.organizer.timeZone);
return new Promise((resolve, reject) => nodemailer.createTransport(transport).sendMail(
{
icalEvent: {
filename: 'event.ics',
content: this.getiCalEventAsString(),
},
from: `Calendso <${from}>`,
to: this.calEvent.organizer.email,
subject: `New event: ${this.calEvent.attendees[0].name} - ${organizerStart.format('LT dddd, LL')} - ${this.calEvent.type}`,
html: this.getHtmlRepresentation(),
text: this.getPlainTextRepresentation(),
},
(error, info) => {
if (error) {
console.error("SEND_NEW_EVENT_NOTIFICATION_ERROR", this.calEvent.organizer.email, error);
reject(new Error(error));
} else {
resolve(info);
}
}));
}
/**
* Gathers the required provider information from the config.
*
* @protected
*/
protected getMailerOptions(): any {
return {
transport: serverConfig.transport,
from: serverConfig.from,
};
}
/**
* Can be used to include additional HTML or plain text
* content into the mail body and calendar event description.
* Leave it to an empty string if not desired.
*
* @protected
*/
protected getAdditionalBody(): string {
return "";
}
}