diff --git a/worker.js b/worker.js index 7031556..4bfe4fe 100644 --- a/worker.js +++ b/worker.js @@ -1,13 +1,18 @@ +// @ts-check + // いじりやすいようにここに変数を集約させたい const BLOCKLIST = ["hacker@example.com", "spammer@example.com"]; const FORWARD_TO = "mymail@example.com"; const WEBHOOK_URL = "https://discord.com/api/webhooks/xxx/xxx"; // trendcreate icon -const WEBHOOK_ICON = "https://git.v-sli.me/HidemaruOwO/email-worker/raw/branch/main/assets/webhook_icon.jpg"; +const WEBHOOK_ICON = + "https://git.v-sli.me/HidemaruOwO/email-worker/raw/branch/main/assets/webhook_icon.jpg"; // mail letter icon -const AUTHOR_ICON = "https://git.v-sli.me/HidemaruOwO/email-worker/raw/branch/main/assets/email_icon.png"; +const AUTHOR_ICON = + "https://git.v-sli.me/HidemaruOwO/email-worker/raw/branch/main/assets/email_icon.png"; // cloudflare icon -const FOOTER_ICON = "https://git.v-sli.me/HidemaruOwO/email-worker/raw/branch/main/assets/cloudflare_icon.ico"; +const FOOTER_ICON = + "https://git.v-sli.me/HidemaruOwO/email-worker/raw/branch/main/assets/cloudflare_icon.ico"; export default { async email(message, env, ctx) { @@ -17,63 +22,67 @@ export default { } try { - const [text] = await Promise.all([ - getMailText(message), - message.forward(FORWARD_TO) + const [result] = await Promise.all([ + notify(message), + message.forward(FORWARD_TO), ]); - - const result = await notify(message.headers.get("from"), message.headers.get('subject'), text, message.headers.get("date")); - + if (!result.ok) { - console.log(await result.text()) - console.log(await result.json()) + console.log(await result.text()); + console.log(await result.json()); return; } } catch (err) { console.error("処理エラー:", err); } - } + }, }; -async function notify(from, subject, text, date) { +// async function notify(from, subject, text, date) { +async function notify(message) { + const from = message.headers.get("from"); + const subject = message.headers.get("subject"); + const date = message.headers.get("date"); + const text = await getMailText(message); + const payload = { username: "contact@trendcreate.net", avatar_url: WEBHOOK_ICON, content: `**${from}**からお問い合わせメールが届いております。`, - embeds: [{ - author: {name: from || "名前なし", icon_url: AUTHOR_ICON}, - title: `**${subject || "件名なし"}**`, - description: text || "本文はありません。", - timestamp: new Date(date).toISOString(), - footer: { - text: 'Powered by Cloudflare Worker and Email Routing', - icon_url: FOOTER_ICON - } - }], - + embeds: [ + { + author: { name: from || "名前なし", icon_url: AUTHOR_ICON }, + title: `**${subject || "件名なし"}**`, + description: text || "本文はありません。", + timestamp: new Date(date).toISOString(), + footer: { + text: "Powered by Cloudflare Worker and Email Routing", + icon_url: FOOTER_ICON, + }, + }, + ], }; // console.log(JSON.stringify(payload)) -try { - const result = await fetch(WEBHOOK_URL, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(payload) - }); - return result; -} catch (err) { - console.log(err) - throw new Error(err) -} -return; + try { + const result = await fetch(WEBHOOK_URL, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(payload), + }); + return result; + } catch (err) { + console.log(err); + throw new Error(err); + } } async function getMailText(message) { try { const buf = await readStream(message.raw); if (buf === "NO_CONTENT") { - return "" + return ""; } return parseEmail(buf); } catch (err) { @@ -83,56 +92,56 @@ async function getMailText(message) { async function readStream(stream) { if (typeof stream === "undefined") { - return "NO_CONTENT" + return "NO_CONTENT"; } const chunks = []; const reader = stream.getReader(); - + while (true) { const { done, value } = await reader.read(); if (done) break; chunks.push(value); } - + const size = chunks.reduce((sum, chunk) => sum + chunk.length, 0); const result = new Uint8Array(size); - + let pos = 0; for (const chunk of chunks) { result.set(chunk, pos); pos += chunk.length; } - + return result; } function parseEmail(buffer) { const text = new TextDecoder().decode(buffer); - const headerEnd = text.indexOf('\r\n\r\n'); - - if (headerEnd === -1) return ''; - + const headerEnd = text.indexOf("\r\n\r\n"); + + if (headerEnd === -1) return ""; + const header = text.substring(0, headerEnd); const body = text.substring(headerEnd + 4); - + const boundaryMatch = header.match(/boundary="?([^"\r\n]+)"?/i); - + if (!boundaryMatch) return body.trim(); - + const boundary = `--${boundaryMatch[1]}`; const parts = body.split(boundary); - + for (const part of parts) { - if (part.includes('Content-Type: text/plain')) { - const isBase64 = part.includes('Content-Transfer-Encoding: base64'); - const partBody = part.split('\r\n\r\n')[1]?.trim(); - + if (part.includes("Content-Type: text/plain")) { + const isBase64 = part.includes("Content-Transfer-Encoding: base64"); + const partBody = part.split("\r\n\r\n")[1]?.trim(); + if (!partBody) continue; - + if (isBase64) { try { - const cleanBase64 = partBody.replace(/[\r\n\s]/g, ''); + const cleanBase64 = partBody.replace(/[\r\n\s]/g, ""); return decodeBase64(cleanBase64); } catch { continue; @@ -142,17 +151,18 @@ function parseEmail(buffer) { } } } - - return ''; + + return ""; } function decodeBase64(base64) { const binary = atob(base64); const bytes = new Uint8Array(binary.length); - + for (let i = 0; i < binary.length; i++) { bytes[i] = binary.charCodeAt(i); } - + return new TextDecoder().decode(bytes); -} \ No newline at end of file +} +