From 832ef7f411aa356aa5760df75b420abba54b0d48 Mon Sep 17 00:00:00 2001 From: Benjamin Palko Date: Mon, 26 Jan 2026 10:39:02 -0500 Subject: [PATCH] switch to discord hook for contact --- bun.lock | 6 --- package.json | 2 - src/lib/server/discord.ts | 26 ++++++++++++ src/routes/contact/+page.server.ts | 65 +++++++++--------------------- src/routes/contact/+page.svelte | 16 ++++---- 5 files changed, 53 insertions(+), 62 deletions(-) create mode 100644 src/lib/server/discord.ts diff --git a/bun.lock b/bun.lock index a96a76d..4577333 100644 --- a/bun.lock +++ b/bun.lock @@ -10,7 +10,6 @@ "@sveltejs/adapter-netlify": "^5.2.4", "clsx": "^2.1.1", "dayjs": "^1.11.13", - "nodemailer": "^6.10.1", "pino": "^9.6.0", "tailwind-merge": "^3.4.0", }, @@ -21,7 +20,6 @@ "@sveltejs/kit": "^2.20.7", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@tailwindcss/vite": "^4.1.4", - "@types/nodemailer": "^6.4.17", "autoprefixer": "^10.4.21", "daisyui": "^5.5.14", "eslint": "^9.25.1", @@ -252,8 +250,6 @@ "@types/node": ["@types/node@22.15.3", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-lX7HFZeHf4QG/J7tBZqrCAXwz9J5RD56Y6MpP0eJkka8p+K0RY/yBTW7CYFJ4VGCclxqOLKmiGP5juQc6MKgcw=="], - "@types/nodemailer": ["@types/nodemailer@6.4.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww=="], - "@types/resolve": ["@types/resolve@1.20.2", "", {}, "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="], "@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], @@ -574,8 +570,6 @@ "node-releases": ["node-releases@2.0.19", "", {}, "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw=="], - "nodemailer": ["nodemailer@6.10.1", "", {}, "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA=="], - "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], diff --git a/package.json b/package.json index 89be82a..7391ed4 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,6 @@ "@sveltejs/kit": "^2.20.7", "@sveltejs/vite-plugin-svelte": "^5.0.3", "@tailwindcss/vite": "^4.1.4", - "@types/nodemailer": "^6.4.17", "autoprefixer": "^10.4.21", "daisyui": "^5.5.14", "eslint": "^9.25.1", @@ -47,7 +46,6 @@ "@sveltejs/adapter-netlify": "^5.2.4", "clsx": "^2.1.1", "dayjs": "^1.11.13", - "nodemailer": "^6.10.1", "pino": "^9.6.0", "tailwind-merge": "^3.4.0" } diff --git a/src/lib/server/discord.ts b/src/lib/server/discord.ts new file mode 100644 index 0000000..90c2d53 --- /dev/null +++ b/src/lib/server/discord.ts @@ -0,0 +1,26 @@ +import { DISCORD_CONTACT_WEBHOOK } from '$env/static/private'; + +export async function sendContactMessage( + name: string, + email: string, + subject: string, + message: string +) { + const form = new FormData(); + + // We need a better way than this to format a string to markdown + const content = ` + # Someone is reaching out! + + From: ${name} - [${email}](mailto:${email}) + > **Subject: ${subject}** + > ${message} +` + .split('\n') + .map((str) => str.trim()) + .join('\n'); + + form.append('content', content); + + return await fetch(DISCORD_CONTACT_WEBHOOK, { method: 'POST', body: form }); +} diff --git a/src/routes/contact/+page.server.ts b/src/routes/contact/+page.server.ts index e604d9b..d81d8c1 100644 --- a/src/routes/contact/+page.server.ts +++ b/src/routes/contact/+page.server.ts @@ -1,84 +1,59 @@ -import { env } from "$env/dynamic/private"; -import { fail } from "@sveltejs/kit"; -import { createTransport } from "nodemailer"; -import type { Actions } from "./$types"; -import { logger } from "$lib/server/logger"; +import { sendContactMessage } from '$lib/server/discord'; +import { logger } from '$lib/server/logger'; +import { fail } from '@sveltejs/kit'; +import type { Actions } from './$types'; export const actions = { default: async ({ request }) => { const form = await request.formData(); - if (!form.has("name")) { + if (!form.has('name')) { return fail(400, { name: null, missing: true }); } - if (!form.has("email")) { + if (!form.has('email')) { return fail(400, { email: null, missing: true }); } - if (!form.has("subject")) { + if (!form.has('subject')) { return fail(400, { subject: null, missing: true }); } - if (!form.has("message")) { + if (!form.has('message')) { return fail(400, { message: null, missing: true }); } - const name = form.get("name"); - if (typeof name !== "string") { + const name = form.get('name'); + if (typeof name !== 'string') { return fail(400, { name, incorrect: true }); } - const email = form.get("email"); - if (typeof email !== "string") { + const email = form.get('email'); + if (typeof email !== 'string') { return fail(400, { email, incorrect: true }); } - const subject = form.get("subject"); - if (typeof subject !== "string") { + const subject = form.get('subject'); + if (typeof subject !== 'string') { return fail(400, { subject, incorrect: true }); } - const message = form.get("message"); - if (typeof message !== "string") { + const message = form.get('message'); + if (typeof message !== 'string') { return fail(400, { message, incorrect: true }); } - const transport = createTransport({ - host: env.MAIL_TRANSPORT_HOST, - port: isNaN(Number(env.MAIL_TRANSPORT_PORT)) - ? 587 - : Number(env.MAIL_TRANSPORT_PORT), - auth: { - user: env.MAIL_TRANSPORT_USER, - pass: env.MAIL_TRANSPORT_PASS, - }, - }); - try { - const info1 = await transport.sendMail({ - from: "no-reply@benjaminpalko.ca", - to: email, - subject: `Thank you for reaching out`, - text: `Hello ${name}!\n\nThank you for reaching out! I will be sure to get back to you ASAP.\n\nCheers,\nBenjamin`, - }); - - const info2 = await transport.sendMail({ - from: email, - to: "contact@benjaminpalko.ca", - subject: subject, - text: message, - }); + const response = await sendContactMessage(name, email, subject, message); return { response: { - accepted: [...info1.accepted, ...info2.accepted], - rejected: [...info1.rejected, ...info2.rejected], - }, + ok: response.ok + } }; } catch (error) { logger.error(error); fail(400, { incorrect: true }); } - }, + } } satisfies Actions; diff --git a/src/routes/contact/+page.svelte b/src/routes/contact/+page.svelte index 88036fd..898a1ff 100644 --- a/src/routes/contact/+page.svelte +++ b/src/routes/contact/+page.svelte @@ -14,8 +14,6 @@ let loading = $state(false); let { form }: PageProps = $props(); - - $inspect(form);
Reach out! 🤝
- {#if form?.response?.rejected.length ?? 0 > 0} -