diff options
| author | Elizabeth Hunt <me@liz.coffee> | 2025-12-15 20:17:22 -0800 |
|---|---|---|
| committer | Elizabeth Hunt <me@liz.coffee> | 2025-12-15 20:19:43 -0800 |
| commit | 2814d5520623efe5f48c26f639d3ed6cc5f0d8d2 (patch) | |
| tree | 3fc1af65dac5ed55aceaab7574b22fea32cad86a /src/integrations/email.ts | |
| parent | 2e41f030f02a336c2e9866d3d56b0494da5a622e (diff) | |
| download | posthook-2814d5520623efe5f48c26f639d3ed6cc5f0d8d2.tar.gz posthook-2814d5520623efe5f48c26f639d3ed6cc5f0d8d2.zip | |
Add email integration
Diffstat (limited to 'src/integrations/email.ts')
| -rw-r--r-- | src/integrations/email.ts | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/integrations/email.ts b/src/integrations/email.ts new file mode 100644 index 0000000..aa4c36c --- /dev/null +++ b/src/integrations/email.ts @@ -0,0 +1,69 @@ +import { Either, type IEither } from '@emprespresso/pengueno'; +import type { EmailConfig, StoredRequest } from '../types/index.js'; +import nodemailer from 'nodemailer'; + +export async function sendEmailNotification(config: EmailConfig, request: StoredRequest): Promise<IEither<Error, void>> { + if (!config.enabled || !config.to || !config.from) { + return Either.right(<void>undefined); + } + + return Either.fromFailableAsync(async () => { + // Create transporter based on configuration + const transporter = nodemailer.createTransport({ + host: config.host || 'localhost', + port: config.port || 25, + secure: config.secure ?? false, + auth: config.username && config.password + ? { + user: config.username, + pass: config.password, + } + : undefined, + }); + + const subject = config.subject || `Webhook received: ${request.routeName}`; + + // Build email body + let htmlBody = ` + <h2>Webhook Notification</h2> + <p><strong>Route:</strong> ${request.routeName}</p> + <p><strong>Method:</strong> ${request.method}</p> + <p><strong>Timestamp:</strong> ${new Date(request.timestamp).toISOString()}</p> + <p><strong>UUID:</strong> ${request.uuid}</p> + `; + + if (config.includeBody && request.body !== undefined) { + htmlBody += ` + <h3>Request Body:</h3> + <pre>${JSON.stringify(request.body, null, 2)}</pre> + `; + } + + if (config.includeHeaders && request.headers) { + htmlBody += ` + <h3>Headers:</h3> + <pre>${JSON.stringify(request.headers, null, 2)}</pre> + `; + } + + if (request.files && request.files.length > 0) { + htmlBody += ` + <h3>Uploaded Files:</h3> + <ul> + ${request.files.map(f => `<li>${f.originalFilename} (${f.contentType}, ${f.size} bytes)</li>`).join('')} + </ul> + `; + } + + const mailOptions = { + from: config.from, + to: config.to, + subject: subject, + html: htmlBody, + }; + + await transporter.sendMail(mailOptions); + + return <void>undefined; + }); +} |
