mirror of
https://github.com/tomru/pfadi-bussle.git
synced 2026-03-03 06:27:11 +01:00
use nodemailer instead of sendgrid
This commit is contained in:
162
helpers/mail.ts
162
helpers/mail.ts
@@ -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
127
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user