use nodemailer instead of sendgrid

This commit is contained in:
Thomas Ruoff
2022-12-22 23:00:44 +01:00
parent e0fe762c80
commit 28b3b03279
5 changed files with 130 additions and 211 deletions

View File

@@ -1,32 +1,46 @@
import { Booking } from '../db/booking' import { Booking } from '../db/booking'
import { getBaseURL } from '../helpers/url' import { getBaseURL } from '../helpers/url'
import { log } from '../helpers/log'
import { daysFormatFrontend } from './date' import { daysFormatFrontend } from './date'
import { generateCalendarEntry } from './ical' import { generateCalendarEntry } from './ical'
import sgMail from '@sendgrid/mail' import nodemailer from 'nodemailer';
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY const smtpUser = process.env.SMTP_USER
const ADMIN_EMAIL = process.env.ADMIN_EMAIL const smtpPass = process.env.SMTP_PASS
const FROM_EMAIL = process.env.FROM_EMAIL const adminEmail = process.env.ADMIN_EMAIL
const fromEmail = process.env.FROM_EMAIL
if (!SENDGRID_API_KEY) { if (!smtpUser) {
throw new Error('NO SENDGRID_API_KEY set!') throw new Error('NO SMTP_USER set!')
} }
if (!ADMIN_EMAIL) { if (!smtpPass) {
throw new Error('NO SMTP_PASS set!')
}
if (!adminEmail) {
throw new Error('No ADMIN_EMAIL set!') throw new Error('No ADMIN_EMAIL set!')
} }
if (!FROM_EMAIL) { if (!fromEmail) {
throw new Error('No FROM_EMAIL set!') throw new Error('No FROM_EMAIL set!')
} }
sgMail.setApiKey(SENDGRID_API_KEY) let transporter = nodemailer.createTransport({
host: "wirtanen.uberspace.de",
port: 587,
secure: false,
auth: {
user: smtpUser,
pass: smtpPass,
},
logger: true,
});
const footer = ` const footer = `
Viele Grüße Viele Grüße
--
Thomas Ruoff Thomas Ruoff
Pfadi Bussle Wart Pfadi Bussle Wart
@@ -105,115 +119,85 @@ MfG`
export async function sendReceivedBookingAdminMail( export async function sendReceivedBookingAdminMail(
booking: Booking booking: Booking
): Promise<void> { ): Promise<void> {
try { await sendMail({
await sendMail({ to: [{ address: adminEmail, name: 'Pfadi-Bussle Wart' }],
to: [{ email: ADMIN_EMAIL }], from: { address: fromEmail, name: 'Pfadi-Bussle Wart' },
from: { email: FROM_EMAIL, name: 'Pfadi-Bussle Wart' }, subject: `Buchung für ${booking.days} eingegangen!`,
subject: `Buchung für ${booking.days} eingegangen!`, text: getReceivedBookingAdminText(booking),
textPlainContent: getReceivedBookingAdminText(booking), })
})
} catch (error) {
log.error(`Failed in sendReceivedBookingMail for ${booking.uuid}`, error)
}
} }
export async function sendReceivedBookingBookerMail( export async function sendReceivedBookingBookerMail(
booking: Booking booking: Booking
): Promise<void> { ): Promise<void> {
try { await sendMail({
await sendMail({ to: [{ address: booking.email, name: booking.name }],
to: [{ email: booking.email, name: booking.name }], from: { address: fromEmail, name: 'Pfadi-Bussle Wart' },
from: { email: FROM_EMAIL, name: 'Pfadi-Bussle Wart' }, subject: `Deine Pfadi-Bussle Buchung ist eingegangen!`,
subject: `Deine Pfadi-Bussle Buchung ist eingegangen!`, text: getReceivedBookingBookerText(booking),
textPlainContent: getReceivedBookingBookerText(booking), })
})
} catch (error) {
log.error(`Failed in sendReceivedBookingMail for ${booking.uuid}`, error)
}
} }
export async function sendBookingConfirmed(booking: Booking): Promise<void> { export async function sendBookingConfirmed(booking: Booking): Promise<void> {
try { await sendMail({
await sendMail({ to: [{ address: booking.email, name: booking.name }],
to: [{ email: booking.email, name: booking.name }], from: { address: fromEmail, name: 'Pfadi-Bussle Wart' },
from: { email: FROM_EMAIL, name: 'Pfadi-Bussle Wart' }, subject: `Deine Pfadi-Bussle Buchung wurde bestätigt!`,
subject: `Deine Pfadi-Bussle Buchung wurde bestätigt!`, text: getBookingConfirmedText(booking),
textPlainContent: getBookingConfirmedText(booking), attachments: [
attachments: [ {
{ content: Buffer.from(generateCalendarEntry(booking)).toString(
content: Buffer.from(generateCalendarEntry(booking)).toString( 'base64'
'base64' ),
), type: 'text/calendar',
type: 'text/calendar', filename: 'pfadibussle-buchung.ics',
filename: 'pfadibussle-buchung.ics', },
}, ],
], })
})
} catch (error) {
log.error(`Failed in sendBookingConfirmedMail for ${booking.uuid}`, error)
}
} }
export async function sendBookingRejected(booking: Booking): Promise<void> { export async function sendBookingRejected(booking: Booking): Promise<void> {
try { await sendMail({
await sendMail({ to: [{ address: booking.email, name: booking.name }],
to: [{ email: booking.email, name: booking.name }], from: { address: fromEmail, name: 'Pfadi-Bussle Wart' },
from: { email: FROM_EMAIL, name: 'Pfadi-Bussle Wart' }, subject: `Deine Pfadi-Bussle Buchung wurde abgelehnt!`,
subject: `Deine Pfadi-Bussle Buchung wurde abgelehnt!`, text: getBookingRejectedText(booking),
textPlainContent: getBookingRejectedText(booking), })
})
} catch (error) {
log.error(`Failed in sendBookingRejectedMail for ${booking.uuid}`, error)
}
} }
export async function sendBookingCanceled(booking: Booking): Promise<void> { export async function sendBookingCanceled(booking: Booking): Promise<void> {
try { await sendMail({
await sendMail({ to: [{ address: booking.email, name: booking.name }],
to: [{ email: booking.email, name: booking.name }], from: { address: fromEmail, name: 'Pfadi-Bussle Wart' },
from: { email: FROM_EMAIL, name: 'Pfadi-Bussle Wart' }, subject: `Deine Pfadi-Bussle Buchung wurde storniert!`,
subject: `Deine Pfadi-Bussle Buchung wurde storniert!`, text: getBookingCanceledText(booking),
textPlainContent: getBookingCanceledText(booking), })
})
} catch (error) {
log.error(`Failed in sendBookingCanceledMail for ${booking.uuid}`, error)
}
} }
async function sendMail({ async function sendMail({
to, to,
from, from,
subject, subject,
textPlainContent, text,
attachments, attachments,
}: { }: {
to: { email: string; name?: string }[] to: { address: string; name: string }[]
from: { email: string; name?: string } from: { address: string; name: string }
subject: string subject: string
textPlainContent: string text: string
attachments?: { attachments?: {
content: string content: string
type?: string type?: string
filename: string filename: string
}[] }[]
}): Promise<void> { }): Promise<void> {
const data = {
// send mail with defined transport object
await transporter.sendMail({
to, to,
from, from,
subject, subject,
text: textPlainContent, text,
attachments, attachments,
} });
}
try {
await sgMail.send(data)
} catch (error) {
log.error('Failed to send email', error)
if (error.response) {
log.error('Failed to send email', error.response.body)
}
// TODO: stuff into DB if failed and retry later
}
}

127
package-lock.json generated
View File

@@ -9,7 +9,6 @@
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@next-auth/mongodb-adapter": "1.1.1", "@next-auth/mongodb-adapter": "1.1.1",
"@sendgrid/mail": "7.7.0",
"@vercel/analytics": "^0.1.4", "@vercel/analytics": "^0.1.4",
"autoprefixer": "10.4.13", "autoprefixer": "10.4.13",
"classnames": "2.3.2", "classnames": "2.3.2",
@@ -22,13 +21,14 @@
"next-auth": "4.18.7", "next-auth": "4.18.7",
"next-axiom": "0.16.0", "next-axiom": "0.16.0",
"next-mdx-remote": "4.2.0", "next-mdx-remote": "4.2.0",
"nodemailer": "6.8.0", "nodemailer": "^6.8.0",
"react": "18.2.0", "react": "18.2.0",
"react-calendar": "4.0.0", "react-calendar": "4.0.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"uuid": "9.0.0" "uuid": "9.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/nodemailer": "^6.4.6",
"@types/react": "18.0.26", "@types/react": "18.0.26",
"@types/react-calendar": "3.9.0", "@types/react-calendar": "3.9.0",
"@types/uuid": "8.3.4", "@types/uuid": "8.3.4",
@@ -3047,41 +3047,6 @@
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==", "integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
"dev": true "dev": true
}, },
"node_modules/@sendgrid/client": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.7.0.tgz",
"integrity": "sha512-SxH+y8jeAQSnDavrTD0uGDXYIIkFylCo+eDofVmZLQ0f862nnqbC3Vd1ej6b7Le7lboyzQF6F7Fodv02rYspuA==",
"dependencies": {
"@sendgrid/helpers": "^7.7.0",
"axios": "^0.26.0"
},
"engines": {
"node": "6.* || 8.* || >=10.*"
}
},
"node_modules/@sendgrid/helpers": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-7.7.0.tgz",
"integrity": "sha512-3AsAxfN3GDBcXoZ/y1mzAAbKzTtUZ5+ZrHOmWQ279AuaFXUNCh9bPnRpN504bgveTqoW+11IzPg3I0WVgDINpw==",
"dependencies": {
"deepmerge": "^4.2.2"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/@sendgrid/mail": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-7.7.0.tgz",
"integrity": "sha512-5+nApPE9wINBvHSUxwOxkkQqM/IAAaBYoP9hw7WwgDNQPxraruVqHizeTitVtKGiqWCKm2mnjh4XGN3fvFLqaw==",
"dependencies": {
"@sendgrid/client": "^7.7.0",
"@sendgrid/helpers": "^7.7.0"
},
"engines": {
"node": "6.* || 8.* || >=10.*"
}
},
"node_modules/@sinclair/typebox": { "node_modules/@sinclair/typebox": {
"version": "0.24.19", "version": "0.24.19",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.19.tgz", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.19.tgz",
@@ -3274,6 +3239,15 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz",
"integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==" "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g=="
}, },
"node_modules/@types/nodemailer": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.6.tgz",
"integrity": "sha512-pD6fL5GQtUKvD2WnPmg5bC2e8kWCAPDwMPmHe/ohQbW+Dy0EcHgZ2oCSuPlWNqk74LS5BVMig1SymQbFMPPK3w==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/prettier": { "node_modules/@types/prettier": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz",
@@ -3755,14 +3729,6 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/axios": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"dependencies": {
"follow-redirects": "^1.14.8"
}
},
"node_modules/axobject-query": { "node_modules/axobject-query": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -4463,6 +4429,7 @@
"version": "4.2.2", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -5667,25 +5634,6 @@
"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
"dev": true "dev": true
}, },
"node_modules/follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/fraction.js": { "node_modules/fraction.js": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -13911,32 +13859,6 @@
"integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==", "integrity": "sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==",
"dev": true "dev": true
}, },
"@sendgrid/client": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-7.7.0.tgz",
"integrity": "sha512-SxH+y8jeAQSnDavrTD0uGDXYIIkFylCo+eDofVmZLQ0f862nnqbC3Vd1ej6b7Le7lboyzQF6F7Fodv02rYspuA==",
"requires": {
"@sendgrid/helpers": "^7.7.0",
"axios": "^0.26.0"
}
},
"@sendgrid/helpers": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-7.7.0.tgz",
"integrity": "sha512-3AsAxfN3GDBcXoZ/y1mzAAbKzTtUZ5+ZrHOmWQ279AuaFXUNCh9bPnRpN504bgveTqoW+11IzPg3I0WVgDINpw==",
"requires": {
"deepmerge": "^4.2.2"
}
},
"@sendgrid/mail": {
"version": "7.7.0",
"resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-7.7.0.tgz",
"integrity": "sha512-5+nApPE9wINBvHSUxwOxkkQqM/IAAaBYoP9hw7WwgDNQPxraruVqHizeTitVtKGiqWCKm2mnjh4XGN3fvFLqaw==",
"requires": {
"@sendgrid/client": "^7.7.0",
"@sendgrid/helpers": "^7.7.0"
}
},
"@sinclair/typebox": { "@sinclair/typebox": {
"version": "0.24.19", "version": "0.24.19",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.19.tgz", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.19.tgz",
@@ -14131,6 +14053,15 @@
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.27.tgz",
"integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g==" "integrity": "sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g=="
}, },
"@types/nodemailer": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.6.tgz",
"integrity": "sha512-pD6fL5GQtUKvD2WnPmg5bC2e8kWCAPDwMPmHe/ohQbW+Dy0EcHgZ2oCSuPlWNqk74LS5BVMig1SymQbFMPPK3w==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/prettier": { "@types/prettier": {
"version": "2.7.1", "version": "2.7.1",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.1.tgz",
@@ -14468,14 +14399,6 @@
"integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==", "integrity": "sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==",
"dev": true "dev": true
}, },
"axios": {
"version": "0.26.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz",
"integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==",
"requires": {
"follow-redirects": "^1.14.8"
}
},
"axobject-query": { "axobject-query": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",
@@ -14947,7 +14870,8 @@
"deepmerge": { "deepmerge": {
"version": "4.2.2", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz",
"integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==",
"dev": true
}, },
"define-lazy-prop": { "define-lazy-prop": {
"version": "2.0.0", "version": "2.0.0",
@@ -15855,11 +15779,6 @@
"integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==",
"dev": true "dev": true
}, },
"follow-redirects": {
"version": "1.15.1",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
"integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA=="
},
"fraction.js": { "fraction.js": {
"version": "4.2.0", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",

View File

@@ -12,7 +12,6 @@
}, },
"dependencies": { "dependencies": {
"@next-auth/mongodb-adapter": "1.1.1", "@next-auth/mongodb-adapter": "1.1.1",
"@sendgrid/mail": "7.7.0",
"@vercel/analytics": "^0.1.4", "@vercel/analytics": "^0.1.4",
"autoprefixer": "10.4.13", "autoprefixer": "10.4.13",
"classnames": "2.3.2", "classnames": "2.3.2",
@@ -25,13 +24,14 @@
"next-auth": "4.18.7", "next-auth": "4.18.7",
"next-axiom": "0.16.0", "next-axiom": "0.16.0",
"next-mdx-remote": "4.2.0", "next-mdx-remote": "4.2.0",
"nodemailer": "6.8.0", "nodemailer": "^6.8.0",
"react": "18.2.0", "react": "18.2.0",
"react-calendar": "4.0.0", "react-calendar": "4.0.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"uuid": "9.0.0" "uuid": "9.0.0"
}, },
"devDependencies": { "devDependencies": {
"@types/nodemailer": "^6.4.6",
"@types/react": "18.0.26", "@types/react": "18.0.26",
"@types/react-calendar": "3.9.0", "@types/react-calendar": "3.9.0",
"@types/uuid": "8.3.4", "@types/uuid": "8.3.4",
@@ -52,4 +52,4 @@
"^.+\\.(ts|tsx)$": "ts-jest" "^.+\\.(ts|tsx)$": "ts-jest"
} }
} }
} }

View File

@@ -63,12 +63,16 @@ export default async function userHandler(
const { current, previous } = await patchBooking(uuid, req.body) const { current, previous } = await patchBooking(uuid, req.body)
// TODO: this should really go into the schema // TODO: this should really go into the schema
if (wasRejected(previous, current)) { try {
sendBookingRejected(current) if (wasRejected(previous, current)) {
} else if (wasConfirmed(previous, current)) { sendBookingRejected(current)
sendBookingConfirmed(current) } else if (wasConfirmed(previous, current)) {
} else if (wasCanceled(previous, current)) { sendBookingConfirmed(current)
sendBookingCanceled(current) } else if (wasCanceled(previous, current)) {
sendBookingCanceled(current)
}
} catch (error) {
log.error(`Failed to send booking ${current} for booking ${uuid}`)
} }
res.status(200).json(current) res.status(200).json(current)
@@ -81,4 +85,4 @@ export default async function userHandler(
res.setHeader('Allow', ['PATCH']) res.setHeader('Allow', ['PATCH'])
res.status(405).end(`Method ${method} Not Allowed`) res.status(405).end(`Method ${method} Not Allowed`)
} }
} }

View File

@@ -34,17 +34,29 @@ export default async function userHandler(
`received booking ${booking.uuid} from ${booking.email}`, `received booking ${booking.uuid} from ${booking.email}`,
booking booking
) )
await sendReceivedBookingAdminMail(booking) try {
log.info(`send booking ${booking.uuid} received to admin`, booking) await sendReceivedBookingAdminMail(booking)
await sendReceivedBookingBookerMail(booking) log.info(`send booking ${booking.uuid} received to admin`, booking)
log.info( } catch (error) {
`send booking ${booking.uuid} received to {booking.email}`, log.error(`failed to send booking ${booking.uuid} received to admin`, booking)
booking }
) try {
await sendReceivedBookingBookerMail(booking)
log.info(
`send booking ${booking.uuid} received to {booking.email}`,
booking
)
} catch (error) {
log.error(
`failed to send booking ${booking.uuid} received to {booking.email}`,
booking
)
}
res.status(200).json(booking) res.status(200).json(booking)
break break
default: default:
res.setHeader('Allow', ['POST']) res.setHeader('Allow', ['POST'])
res.status(405).end(`Method ${method} Not Allowed`) res.status(405).end(`Method ${method} Not Allowed`)
} }
} }