From 23f0d518c5592619165397550897b6efd082611c Mon Sep 17 00:00:00 2001 From: vato007 Date: Mon, 3 Feb 2025 17:53:57 +1030 Subject: [PATCH] Rework email sending to be RFC5322 compliant by using mimetext package --- contact-email-worker/package-lock.json | 220 +++++++++++++++++++++---- contact-email-worker/package.json | 3 + contact-email-worker/src/index.ts | 39 ++++- functions/contact.ts | 38 ++--- 4 files changed, 248 insertions(+), 52 deletions(-) diff --git a/contact-email-worker/package-lock.json b/contact-email-worker/package-lock.json index a50b57e..696d073 100644 --- a/contact-email-worker/package-lock.json +++ b/contact-email-worker/package-lock.json @@ -7,14 +7,39 @@ "": { "name": "royal-leaf-c03c", "version": "0.0.0", + "dependencies": { + "mimetext": "^3.0.27" + }, "devDependencies": { "@cloudflare/vitest-pool-workers": "^0.6.4", "@cloudflare/workers-types": "^4.20250129.0", "typescript": "^5.5.2", - "vitest": "2.1.8", "wrangler": "^3.107.2" } }, + "node_modules/@babel/runtime": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.7.tgz", + "integrity": "sha512-AOPI3D+a8dXnja+iwsUqGRjr1BbZIe771sXdapOtYI531gSqpi92vXivKcq2asu/DFpdl1ceFAKZyRzK2PCVcQ==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.26.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.7.tgz", + "integrity": "sha512-55gRV8vGrCIYZnaQHQrD92Lo/hYE3Sj5tmbuf0hhHR7sj2CWhEhHU89hbq+UVDXvFG1zUVXJhUkEq1eAfqXtFw==", + "dependencies": { + "core-js-pure": "^3.30.2", + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@cloudflare/kv-asset-handler": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.3.4.tgz", @@ -180,6 +205,7 @@ "os": [ "aix" ], + "peer": true, "engines": { "node": ">=12" } @@ -581,7 +607,8 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-android-arm64": { "version": "4.34.0", @@ -594,7 +621,8 @@ "optional": true, "os": [ "android" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-darwin-arm64": { "version": "4.34.0", @@ -607,7 +635,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-darwin-x64": { "version": "4.34.0", @@ -620,7 +649,8 @@ "optional": true, "os": [ "darwin" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-freebsd-arm64": { "version": "4.34.0", @@ -633,7 +663,8 @@ "optional": true, "os": [ "freebsd" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-freebsd-x64": { "version": "4.34.0", @@ -646,7 +677,8 @@ "optional": true, "os": [ "freebsd" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { "version": "4.34.0", @@ -659,7 +691,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { "version": "4.34.0", @@ -672,7 +705,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm64-gnu": { "version": "4.34.0", @@ -685,7 +719,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-arm64-musl": { "version": "4.34.0", @@ -698,7 +733,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-loongarch64-gnu": { "version": "4.34.0", @@ -711,7 +747,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { "version": "4.34.0", @@ -724,7 +761,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { "version": "4.34.0", @@ -737,7 +775,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-s390x-gnu": { "version": "4.34.0", @@ -750,7 +789,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.34.0", @@ -763,7 +803,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-linux-x64-musl": { "version": "4.34.0", @@ -776,7 +817,8 @@ "optional": true, "os": [ "linux" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-arm64-msvc": { "version": "4.34.0", @@ -789,7 +831,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-ia32-msvc": { "version": "4.34.0", @@ -802,7 +845,8 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@rollup/rollup-win32-x64-msvc": { "version": "4.34.0", @@ -815,19 +859,22 @@ "optional": true, "os": [ "win32" - ] + ], + "peer": true }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/@vitest/expect": { "version": "2.1.8", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.8.tgz", "integrity": "sha512-8ytZ/fFHq2g4PJVAtDX57mayemKgDR6X3Oa2Foro+EygiOJHUXhCqBAAKQYYajZpFoIfvBCF1j6R6IYRSIUFuw==", "dev": true, + "peer": true, "dependencies": { "@vitest/spy": "2.1.8", "@vitest/utils": "2.1.8", @@ -843,6 +890,7 @@ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.8.tgz", "integrity": "sha512-7guJ/47I6uqfttp33mgo6ga5Gr1VnL58rcqYKyShoRK9ebu8T5Rs6HN3s1NABiBeVTdWNrwUMcHH54uXZBN4zA==", "dev": true, + "peer": true, "dependencies": { "@vitest/spy": "2.1.8", "estree-walker": "^3.0.3", @@ -869,6 +917,7 @@ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.8.tgz", "integrity": "sha512-9HiSZ9zpqNLKlbIDRWOnAWqgcA7xu+8YxXSekhr0Ykab7PAYFkhkwoqVArPOtJhPmYeE2YHgKZlj3CP36z2AJQ==", "dev": true, + "peer": true, "dependencies": { "tinyrainbow": "^1.2.0" }, @@ -881,6 +930,7 @@ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.8.tgz", "integrity": "sha512-17ub8vQstRnRlIU5k50bG+QOMLHRhYPAna5tw8tYbj+jzjcspnwnwtPtiOlkuKC4+ixDPTuLZiqiWWQ2PSXHVg==", "dev": true, + "peer": true, "dependencies": { "@vitest/utils": "2.1.8", "pathe": "^1.1.2" @@ -894,6 +944,7 @@ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.8.tgz", "integrity": "sha512-20T7xRFbmnkfcmgVEz+z3AU/3b0cEzZOt/zmnvZEctg64/QZbSDJEVm9fLnnlSi74KibmRsO9/Qabi+t0vCRPg==", "dev": true, + "peer": true, "dependencies": { "@vitest/pretty-format": "2.1.8", "magic-string": "^0.30.12", @@ -908,6 +959,7 @@ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.8.tgz", "integrity": "sha512-5swjf2q95gXeYPevtW0BLk6H8+bPlMb4Vw/9Em4hFxDcaOxS+e0LOX4yqNxoHzMR2akEB2xfpnWUzkZokmgWDg==", "dev": true, + "peer": true, "dependencies": { "tinyspy": "^3.0.2" }, @@ -920,6 +972,7 @@ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.8.tgz", "integrity": "sha512-dwSoui6djdwbfFmIgbIjX2ZhIoG7Ex/+xpxyiEgIGzjliY8xGkcpITKTlp6B4MgtGkF2ilvm97cPM96XZaAgcA==", "dev": true, + "peer": true, "dependencies": { "@vitest/pretty-format": "2.1.8", "loupe": "^3.1.2", @@ -967,6 +1020,7 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, + "peer": true, "engines": { "node": ">=12" } @@ -991,6 +1045,7 @@ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", "dev": true, + "peer": true, "engines": { "node": ">=8" } @@ -1000,6 +1055,7 @@ "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.2.tgz", "integrity": "sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==", "dev": true, + "peer": true, "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", @@ -1016,6 +1072,7 @@ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, + "peer": true, "engines": { "node": ">= 16" } @@ -1041,6 +1098,16 @@ "node": ">= 0.6" } }, + "node_modules/core-js-pure": { + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.40.0.tgz", + "integrity": "sha512-AtDzVIgRrmRKQai62yuSIN5vNiQjcJakJb4fbhVw3ehxx7Lohphvw9SGNWKhLFqSxC4ilD0g/L1huAYFQU3Q6A==", + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/data-uri-to-buffer": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-2.0.2.tgz", @@ -1052,6 +1119,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", "dev": true, + "peer": true, "dependencies": { "ms": "^2.1.3" }, @@ -1069,6 +1137,7 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, + "peer": true, "engines": { "node": ">=6" } @@ -1089,7 +1158,8 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/esbuild": { "version": "0.17.19", @@ -1145,6 +1215,7 @@ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, + "peer": true, "dependencies": { "@types/estree": "^1.0.0" } @@ -1166,6 +1237,7 @@ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.1.0.tgz", "integrity": "sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA==", "dev": true, + "peer": true, "engines": { "node": ">=12.0.0" } @@ -1200,17 +1272,24 @@ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "node_modules/js-base64": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.7.tgz", + "integrity": "sha512-7rCnleh0z2CkXhH67J8K1Ytz0b2Y+yxTPL+/KOJoa20hfnVQ/3/T6W/KflYI4bRHRagNeXeU2bkNGI3v1oS/lw==" + }, "node_modules/loupe": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "dev": true + "dev": true, + "peer": true }, "node_modules/magic-string": { "version": "0.30.17", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", "dev": true, + "peer": true, "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0" } @@ -1227,6 +1306,40 @@ "node": ">=10.0.0" } }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimetext": { + "version": "3.0.27", + "resolved": "https://registry.npmjs.org/mimetext/-/mimetext-3.0.27.tgz", + "integrity": "sha512-mUhWAsZD1N/K6dbN4+a5Yq78OPnYQw1ubOSMasBntsLQ2S7KVNlvDEA8dwpr4a7PszWMzeslKahAprtwYMgaBA==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@babel/runtime-corejs3": "^7.26.0", + "js-base64": "^3.7.7", + "mime-types": "^2.1.35" + }, + "funding": { + "type": "patreon", + "url": "https://patreon.com/muratgozel" + } + }, "node_modules/miniflare": { "version": "3.20250129.0", "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-3.20250129.0.tgz", @@ -1274,7 +1387,8 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/mustache": { "version": "4.2.0", @@ -1296,6 +1410,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1326,6 +1441,7 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", "dev": true, + "peer": true, "engines": { "node": ">= 14.16" } @@ -1334,7 +1450,8 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/pkg-types": { "version": "1.3.1", @@ -1372,6 +1489,7 @@ "url": "https://github.com/sponsors/ai" } ], + "peer": true, "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", @@ -1387,11 +1505,17 @@ "integrity": "sha512-dKp+C4iXWK4vVYZmYSd0KBH5F/h1HoZRsbJ82AVKRO3PEo8L4lBS/vLwhVtpwwuYcoIsVY+1JYKR268yn480uQ==", "dev": true }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, "node_modules/rollup": { "version": "4.34.0", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.0.tgz", "integrity": "sha512-+4C/cgJ9w6sudisA0nZz0+O7lTP9a3CzNLsoDwaRumM8QHwghUsu6tqHXiTmNUp/rqNiM14++7dkzHDyCRs0Jg==", "dev": true, + "peer": true, "dependencies": { "@types/estree": "1.0.6" }, @@ -1492,7 +1616,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true + "dev": true, + "peer": true }, "node_modules/source-map": { "version": "0.6.1", @@ -1508,6 +1633,7 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -1523,7 +1649,8 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/stacktracey": { "version": "2.1.8", @@ -1539,7 +1666,8 @@ "version": "3.8.0", "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz", "integrity": "sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==", - "dev": true + "dev": true, + "peer": true }, "node_modules/stoppable": { "version": "1.1.0", @@ -1555,19 +1683,22 @@ "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/tinyexec": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/tinypool": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", "dev": true, + "peer": true, "engines": { "node": "^18.0.0 || >=20.0.0" } @@ -1577,6 +1708,7 @@ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", "dev": true, + "peer": true, "engines": { "node": ">=14.0.0" } @@ -1586,6 +1718,7 @@ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", "dev": true, + "peer": true, "engines": { "node": ">=14.0.0" } @@ -1639,6 +1772,7 @@ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz", "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", "dev": true, + "peer": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -1698,6 +1832,7 @@ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.8.tgz", "integrity": "sha512-uPAwSr57kYjAUux+8E2j0q0Fxpn8M9VoyfGiRI8Kfktz9NcYMCenwY5RnZxnF1WTu3TGiYipirIzacLL3VVGFg==", "dev": true, + "peer": true, "dependencies": { "cac": "^6.7.14", "debug": "^4.3.7", @@ -1727,6 +1862,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } @@ -1743,6 +1879,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } @@ -1759,6 +1896,7 @@ "os": [ "android" ], + "peer": true, "engines": { "node": ">=12" } @@ -1775,6 +1913,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=12" } @@ -1791,6 +1930,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": ">=12" } @@ -1807,6 +1947,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -1823,6 +1964,7 @@ "os": [ "freebsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -1839,6 +1981,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1855,6 +1998,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1871,6 +2015,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1887,6 +2032,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1903,6 +2049,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1919,6 +2066,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1935,6 +2083,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1951,6 +2100,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1967,6 +2117,7 @@ "os": [ "linux" ], + "peer": true, "engines": { "node": ">=12" } @@ -1983,6 +2134,7 @@ "os": [ "netbsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -1999,6 +2151,7 @@ "os": [ "openbsd" ], + "peer": true, "engines": { "node": ">=12" } @@ -2015,6 +2168,7 @@ "os": [ "sunos" ], + "peer": true, "engines": { "node": ">=12" } @@ -2031,6 +2185,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } @@ -2047,6 +2202,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } @@ -2063,6 +2219,7 @@ "os": [ "win32" ], + "peer": true, "engines": { "node": ">=12" } @@ -2073,6 +2230,7 @@ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", "dev": true, "hasInstallScript": true, + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -2110,6 +2268,7 @@ "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.8.tgz", "integrity": "sha512-1vBKTZskHw/aosXqQUlVWWlGUxSJR8YtiyZDJAFeW2kPAeX6S3Sool0mjspO+kXLuxVWlEDDowBAeqeAQefqLQ==", "dev": true, + "peer": true, "dependencies": { "@vitest/expect": "2.1.8", "@vitest/mocker": "2.1.8", @@ -2175,6 +2334,7 @@ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", "dev": true, + "peer": true, "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" diff --git a/contact-email-worker/package.json b/contact-email-worker/package.json index e9c5922..e8c1581 100644 --- a/contact-email-worker/package.json +++ b/contact-email-worker/package.json @@ -13,5 +13,8 @@ "@cloudflare/workers-types": "^4.20250129.0", "typescript": "^5.5.2", "wrangler": "^3.107.2" + }, + "dependencies": { + "mimetext": "^3.0.27" } } diff --git a/contact-email-worker/src/index.ts b/contact-email-worker/src/index.ts index 401c786..5fba922 100644 --- a/contact-email-worker/src/index.ts +++ b/contact-email-worker/src/index.ts @@ -1,17 +1,52 @@ import { EmailMessage } from "cloudflare:email"; import { WorkerEntrypoint } from "cloudflare:workers"; +import { createMimeMessage } from "mimetext"; + +const formatEmptyString = (s: string) => s ?? "Not Specified"; + +interface EmailDetails { + fullName: string; + organisation: string; + email: string; + mobile: string; + message: string; +} export default class SendEmailWorker extends WorkerEntrypoint { async fetch() { return new Response("Unimplemented"); } - async sendEmail(rawMessage: string) { + async sendEmail({ + fullName, + organisation, + email, + mobile, + message, + }: EmailDetails) { + const msg = createMimeMessage(); + msg.setSender({ + name: "Michael Pivato Contact Form", + addr: "contact@michaelpivato.dev", + }); + msg.setRecipient("contact@michaelpivato.dev"); + msg.setSubject(`Message from ${fullName ?? email}`); + msg.addMessage({ + contentType: "text/plain", + data: `You've received a new message from ${fullName ?? email}. +Full Name: ${formatEmptyString(fullName)} +Organisation: ${formatEmptyString(organisation)} +Email: ${formatEmptyString(email)} +Mobile: ${formatEmptyString(mobile)} + +Message: +${message}`, + }); try { const cfMessage = new EmailMessage( "contact@michaelpivato.dev", "contact@michaelpivato.dev", - rawMessage + msg.asRaw() ); await this.env.SEB.send(cfMessage); } catch (e) { diff --git a/functions/contact.ts b/functions/contact.ts index c791e6c..6d8114b 100644 --- a/functions/contact.ts +++ b/functions/contact.ts @@ -1,43 +1,41 @@ import staticFormsPlugin from "@cloudflare/pages-plugin-static-forms"; +interface EmailDetails { + fullName: string; + organisation: string; + email: string; + mobile: string; + message: string; +} + interface SendEmailWorker { - sendEmail(rawMessage: string): Promise; + sendEmail(rawMessage: EmailDetails): Promise; } interface Env { SERVICE: SendEmailWorker; } -const formatEmptyString = (s: string) => s ?? "Not Specified"; - export const onRequest: PagesFunction = (context) => { // Wrap static forms plugin so we can extract the env to use email routing return staticFormsPlugin({ respondWith: async ({ formData }) => { const fullName = formData.get("name"); - const organisation = formData.get("org") ?? "Unknown Organisation"; + const organisation = formData.get("org"); const email = formData.get("email"); - const mobile = formData.get("mobile") ?? "Unknown Mobile"; + const mobile = formData.get("mobile"); const message = formData.get("message"); // Must have some kind of identifiable information for me to actually care about them. if ((fullName || email) && message) { try { - const rawEmailMessage = `---- -From: Michael Pivato Contact Form -To: Michael Pivato -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} -----`; - await context.env.SERVICE.sendEmail(rawEmailMessage); + await context.env.SERVICE.sendEmail({ + fullName, + organisation, + email, + mobile, + message, + }); } catch (e) { return new Response(e); }