Add email worker and use it to send email from pages function
Some checks failed
release / Publish to Cloudflare Pages (push) Failing after 1m17s
Some checks failed
release / Publish to Cloudflare Pages (push) Failing after 1m17s
This commit is contained in:
@@ -16,6 +16,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
lfs: true
|
lfs: true
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
|
||||||
- name: Install pico
|
- name: Install pico
|
||||||
run: npm ci
|
run: npm ci
|
||||||
@@ -30,6 +32,13 @@ jobs:
|
|||||||
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
command: pages deploy build --project-name=resume
|
command: pages deploy build --project-name=resume
|
||||||
|
|
||||||
|
- name: Publish Email Worker
|
||||||
|
uses: cloudflare/wrangler-action@v3
|
||||||
|
with:
|
||||||
|
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||||
|
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||||
|
workingDirectory: contact-email-worker
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v3
|
- uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: Website
|
name: Website
|
||||||
|
|||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
|||||||
/node_modules
|
node_modules
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.vscode
|
.vscode
|
||||||
build
|
build
|
||||||
|
|||||||
2286
contact-email-worker/package-lock.json
generated
Normal file
2286
contact-email-worker/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
17
contact-email-worker/package.json
Normal file
17
contact-email-worker/package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "royal-leaf-c03c",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"deploy": "wrangler deploy",
|
||||||
|
"dev": "wrangler dev",
|
||||||
|
"start": "wrangler dev",
|
||||||
|
"cf-typegen": "wrangler types"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@cloudflare/vitest-pool-workers": "^0.6.4",
|
||||||
|
"@cloudflare/workers-types": "^4.20250129.0",
|
||||||
|
"typescript": "^5.5.2",
|
||||||
|
"wrangler": "^3.107.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
18
contact-email-worker/src/index.ts
Normal file
18
contact-email-worker/src/index.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { EmailMessage } from "cloudflare:email";
|
||||||
|
import { WorkerEntrypoint } from "cloudflare:workers";
|
||||||
|
|
||||||
|
export default class SendEmailWorker extends WorkerEntrypoint<Env> {
|
||||||
|
async sendEmail(rawMessage: string): Promise<Response> {
|
||||||
|
try {
|
||||||
|
const cfMessage = new EmailMessage(
|
||||||
|
"contact@michaelpivato.dev",
|
||||||
|
"contact@michaelpivato.dev",
|
||||||
|
rawMessage
|
||||||
|
);
|
||||||
|
await this.env.SEB.send(cfMessage);
|
||||||
|
} catch (e) {
|
||||||
|
return new Response((e as Error).message);
|
||||||
|
}
|
||||||
|
return new Response();
|
||||||
|
}
|
||||||
|
}
|
||||||
46
contact-email-worker/tsconfig.json
Normal file
46
contact-email-worker/tsconfig.json
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
|
|
||||||
|
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||||
|
"target": "es2021",
|
||||||
|
/* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||||
|
"lib": ["es2021"],
|
||||||
|
/* Specify what JSX code is generated. */
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
|
||||||
|
/* Specify what module code is generated. */
|
||||||
|
"module": "es2022",
|
||||||
|
/* Specify how TypeScript looks up a file from a given module specifier. */
|
||||||
|
"moduleResolution": "Bundler",
|
||||||
|
/* Specify type package names to be included without being referenced in a source file. */
|
||||||
|
"types": [
|
||||||
|
"@cloudflare/workers-types/2023-07-01"
|
||||||
|
],
|
||||||
|
/* Enable importing .json files */
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
|
||||||
|
/* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
|
||||||
|
"allowJs": true,
|
||||||
|
/* Enable error reporting in type-checked JavaScript files. */
|
||||||
|
"checkJs": false,
|
||||||
|
|
||||||
|
/* Disable emitting files from a compilation. */
|
||||||
|
"noEmit": true,
|
||||||
|
|
||||||
|
/* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||||
|
"isolatedModules": true,
|
||||||
|
/* Allow 'import x from y' when a module doesn't have a default export. */
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
/* Ensure that casing is correct in imports. */
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
|
||||||
|
/* Enable all strict type-checking options. */
|
||||||
|
"strict": true,
|
||||||
|
|
||||||
|
/* Skip type checking all .d.ts files. */
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"exclude": ["test"],
|
||||||
|
"include": ["worker-configuration.d.ts", "src/**/*.ts"]
|
||||||
|
}
|
||||||
5
contact-email-worker/worker-configuration.d.ts
vendored
Normal file
5
contact-email-worker/worker-configuration.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// Generated by Wrangler
|
||||||
|
// After adding bindings to `wrangler.json`, regenerate this interface via `npm run cf-typegen`
|
||||||
|
interface Env {
|
||||||
|
SEB: SendEmail;
|
||||||
|
}
|
||||||
13
contact-email-worker/wrangler.json
Normal file
13
contact-email-worker/wrangler.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"$schema": "node_modules/wrangler/config-schema.json",
|
||||||
|
"name": "contact-email",
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"compatibility_date": "2025-01-29",
|
||||||
|
"observability": {
|
||||||
|
"enabled": true
|
||||||
|
},
|
||||||
|
"send_email": [
|
||||||
|
{ "name": "SEB", "destination_address": "contact@michaelpivato.dev" }
|
||||||
|
],
|
||||||
|
"workers_dev": false
|
||||||
|
}
|
||||||
@@ -1,9 +1,16 @@
|
|||||||
import staticFormsPlugin from "@cloudflare/pages-plugin-static-forms";
|
import staticFormsPlugin from "@cloudflare/pages-plugin-static-forms";
|
||||||
import { EmailMessage } from "cloudflare:email";
|
|
||||||
|
interface SendEmailWorker {
|
||||||
|
sendEmail(rawMessage: string): Promise<Response>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Env {
|
||||||
|
SERVICE: SendEmailWorker;
|
||||||
|
}
|
||||||
|
|
||||||
const formatEmptyString = (s: string) => s ?? "Not Specified";
|
const formatEmptyString = (s: string) => s ?? "Not Specified";
|
||||||
|
|
||||||
export const onRequest: PagesFunction = (context) => {
|
export const onRequest: PagesFunction<Env> = (context) => {
|
||||||
// Wrap static forms plugin so we can extract the env to use email routing
|
// Wrap static forms plugin so we can extract the env to use email routing
|
||||||
return staticFormsPlugin({
|
return staticFormsPlugin({
|
||||||
respondWith: async ({ formData }) => {
|
respondWith: async ({ formData }) => {
|
||||||
@@ -15,38 +22,25 @@ export const onRequest: PagesFunction = (context) => {
|
|||||||
|
|
||||||
// Must have some kind of identifiable information for me to actually care about them.
|
// Must have some kind of identifiable information for me to actually care about them.
|
||||||
if ((fullName || email) && message) {
|
if ((fullName || email) && message) {
|
||||||
const rawEmailMessage = `----
|
|
||||||
From: Michael Pivato Contact Form <contact@michaelpivato.dev>
|
|
||||||
To: Michael Pivato <contact@michaelpivato.dev
|
|
||||||
Subject: Message from ${fullName ?? email}
|
|
||||||
|
|
||||||
You've received a new message from ${fullName ?? email}.
|
|
||||||
Full Name: ${formatEmptyString(fullName)}
|
|
||||||
Organisation: ${formatEmptyString(organisation)}
|
|
||||||
Email: ${formatEmptyString(email)}
|
|
||||||
Mobile: ${formatEmptyString(mobile)}
|
|
||||||
|
|
||||||
Message:
|
|
||||||
${message}
|
|
||||||
----`;
|
|
||||||
|
|
||||||
const cfMessage = new EmailMessage(
|
|
||||||
"contact@michaelpivato.dev",
|
|
||||||
"contact@michaelpivato.dev",
|
|
||||||
rawEmailMessage
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await (context.env as any).SEB.send(cfMessage);
|
const rawEmailMessage = `----
|
||||||
} catch (e) {
|
From: Michael Pivato Contact Form <contact@michaelpivato.dev>
|
||||||
return new Response(e.message);
|
To: Michael Pivato <contact@michaelpivato.dev
|
||||||
}
|
Subject: Message from ${fullName ?? email}
|
||||||
|
|
||||||
console.log("Full Name: " + fullName ?? "fullname");
|
You've received a new message from ${fullName ?? email}.
|
||||||
console.log("Organisation: " + organisation);
|
Full Name: ${formatEmptyString(fullName)}
|
||||||
console.log("Email: " + email ?? "email");
|
Organisation: ${formatEmptyString(organisation)}
|
||||||
console.log("Mobile: " + mobile ?? "mobile");
|
Email: ${formatEmptyString(email)}
|
||||||
console.log("Message: " + message);
|
Mobile: ${formatEmptyString(mobile)}
|
||||||
|
|
||||||
|
Message:
|
||||||
|
${message}
|
||||||
|
----`;
|
||||||
|
await context.env.SERVICE.sendEmail(rawEmailMessage);
|
||||||
|
} catch (e) {
|
||||||
|
return new Response(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response.redirect("https://michaelpivato.dev");
|
return Response.redirect("https://michaelpivato.dev");
|
||||||
|
|||||||
6
wrangler.json
Normal file
6
wrangler.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"$schema": "node_modules/wrangler/config-schema.json",
|
||||||
|
"name": "resume",
|
||||||
|
"compatibility_date": "2025-01-29",
|
||||||
|
"services": [{ "binding": "SERVICE", "service": "contact-email" }]
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
send_email = [
|
|
||||||
{name = "SEB", destination_address = "contact@michaelpivato.dev"},
|
|
||||||
]
|
|
||||||
|
|
||||||
compatibility_flags = [ "nodejs_compat" ]
|
|
||||||
compatibility_date = "2024-09-23"
|
|
||||||
Reference in New Issue
Block a user