From c1fcc4af4171d221def9e5925fec7a7d8fe7953c Mon Sep 17 00:00:00 2001 From: Mikayla Dobson Date: Mon, 2 Oct 2023 18:39:46 -0500 Subject: [PATCH] todo: mailer config --- app/contact/page.tsx | 21 ++++++++++---------- next.config.js | 2 +- package.json | 1 + server/actions/mailer.actions.ts | 34 ++++++++++++++++++++++++++++++++ server/services/sendgrid.ts | 28 ++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 server/actions/mailer.actions.ts create mode 100644 server/services/sendgrid.ts diff --git a/app/contact/page.tsx b/app/contact/page.tsx index 59b7165..ba219b8 100644 --- a/app/contact/page.tsx +++ b/app/contact/page.tsx @@ -1,40 +1,41 @@ 'use client'; -import { useState } from "react"; +import { contactFormSubmit, testMailerSDK } from "@/server/actions/mailer.actions" +import { useMemo, useState } from "react"; export default function ContactPage() { + const MESSAGE_LIMIT = 600; + const [name, setName] = useState(''); const [email, setEmail] = useState(''); const [message, setMessage] = useState(''); - function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - console.log(name, email, message); - } + const characterCount = useMemo(() => message.length.toString(), [message]); return (

Thanks for your interest! I'm looking forward to hearing from you.

-
+
- setName(e.target.value)} type="text" name="name" id="name" /> + setName(e.target.value)} type="text" name="name" id="name" />
- setEmail(e.target.value)} type="email" name="email" id="email" /> + setEmail(e.target.value)} type="email" name="email" id="email" />
- + +

MESSAGE_LIMIT ? "text-red-500" : "text-white")}>{characterCount}/{MESSAGE_LIMIT}

- +
diff --git a/next.config.js b/next.config.js index f257fac..8d1205f 100644 --- a/next.config.js +++ b/next.config.js @@ -19,7 +19,7 @@ const nextConfig = { reactStrictMode: true, experimental: { // mdxRs: true, - // serverActions: true, + serverActions: true, } } diff --git a/package.json b/package.json index 6dca4dd..7ea8b02 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@mdx-js/loader": "^2.3.0", "@mdx-js/react": "^2.3.0", "@next/mdx": "^13.4.4", + "@sendgrid/mail": "^7.7.0", "@supabase/supabase-js": "^2.26.0", "autoprefixer": "10.4.14", "eslint": "^8.46.0", diff --git a/server/actions/mailer.actions.ts b/server/actions/mailer.actions.ts new file mode 100644 index 0000000..e728c47 --- /dev/null +++ b/server/actions/mailer.actions.ts @@ -0,0 +1,34 @@ +'use server'; +import { Mailer } from "../services/sendgrid"; + +export async function contactFormSubmit(e: FormData) { + const data = [e.get('email'), e.get('message'), e.get('name')].map(each => each?.valueOf()); + const mailer = new Mailer(); + + data.forEach(item => { + if (typeof item !== 'string') throw new Error('Invalid form data') + }) + + const result = await mailer.send(...data as [string, string, string]); + return result; +} + +export async function testMailerSDK(e: FormData) { + const sgMail = require('@sendgrid/mail') + sgMail.setApiKey(process.env.SENDGRID_API_KEY) + const msg = { + to: 'mikaylaherself@gmail.com', // Change to your recipient + from: 'me@mikayla.dev', // Change to your verified sender + subject: 'Sending with SendGrid is Fun', + text: 'and easy to do anywhere, even with Node.js', + html: 'and easy to do anywhere, even with Node.js', + } + sgMail + .send(msg) + .then(() => { + console.log('Email sent') + }) + .catch((error: unknown) => { + console.error(error) + }) +} diff --git a/server/services/sendgrid.ts b/server/services/sendgrid.ts new file mode 100644 index 0000000..5df1818 --- /dev/null +++ b/server/services/sendgrid.ts @@ -0,0 +1,28 @@ +import mailer, { ClientResponse, MailDataRequired, MailService } from "@sendgrid/mail"; + +export class Mailer { + private mailer: MailService; + + constructor() { + const service = mailer; + const key = process.env.SENDGRID_API_KEY; + + if (!key) throw new Error("No SendGrid API key provided"); + + service.setApiKey(key); + + this.mailer = service; + } + + public async send(from: string, text: string, name: string) { + const data: MailDataRequired = { + text, from, + cc: from, + to: 'hello@mikayla.dev', + subject: `Contact form submission from ${name}` + } + const result = await this.mailer.send(data); + return result[0] as ClientResponse; + } +} +