import nodemailer from 'nodemailer'; import dayjs, { Dayjs } from "dayjs"; import localizedFormat from 'dayjs/plugin/localizedFormat'; import utc from 'dayjs/plugin/utc'; import timezone from 'dayjs/plugin/timezone'; import toArray from 'dayjs/plugin/toArray'; import { createEvent } from 'ics'; import { CalendarEvent } from '../calendarClient'; import { serverConfig } from '../serverConfig'; dayjs.extend(localizedFormat); dayjs.extend(utc); dayjs.extend(timezone); dayjs.extend(toArray); export default function createNewEventEmail(calEvent: CalendarEvent, options: any = {}) { return sendEmail(calEvent, { provider: { transport: serverConfig.transport, from: serverConfig.from, }, ...options }); } const icalEventAsString = (calEvent: CalendarEvent): string => { const icsEvent = createEvent({ start: dayjs(calEvent.startTime).utc().toArray().slice(0, 6).map((v, i) => i === 1 ? v + 1 : v), startInputType: 'utc', productId: 'calendso/ics', title: `${calEvent.type} with ${calEvent.attendees[0].name}`, description: calEvent.description, duration: { minutes: dayjs(calEvent.endTime).diff(dayjs(calEvent.startTime), 'minute') }, organizer: { name: calEvent.organizer.name, email: calEvent.organizer.email }, attendees: calEvent.attendees.map( (attendee: any) => ({ name: attendee.name, email: attendee.email }) ), status: "CONFIRMED", }); if (icsEvent.error) { throw icsEvent.error; } return icsEvent.value; } const sendEmail = (calEvent: CalendarEvent, { provider, }) => new Promise( (resolve, reject) => { const { transport, from } = provider; const organizerStart: Dayjs = dayjs(calEvent.startTime).tz(calEvent.organizer.timeZone); nodemailer.createTransport(transport).sendMail( { icalEvent: { filename: 'event.ics', content: icalEventAsString(calEvent), }, from: `Calendso <${from}>`, to: calEvent.organizer.email, subject: `New event: ${calEvent.attendees[0].name} - ${organizerStart.format('LT dddd, LL')} - ${calEvent.type}`, html: html(calEvent), text: text(calEvent), }, (error) => { if (error) { console.error("SEND_NEW_EVENT_NOTIFICATION_ERROR", calEvent.organizer.email, error); return reject(new Error(error)); } return resolve(); }); }); const html = (evt: CalendarEvent) => `
Hi ${evt.organizer.name},

A new event has been scheduled.

Event Type:
${evt.type}

Invitee Email:
${evt.attendees[0].email}

` + ( evt.location ? ` Location:
${evt.location}

` : '' ) + `Invitee Time Zone:
${evt.attendees[0].timeZone}

Additional notes:
${evt.description}
`; // just strip all HTML and convert
to \n const text = (evt: CalendarEvent) => html(evt).replace('
', "\n").replace(/<[^>]+>/g, '');