docfast/dist/services/email.js
OpenClaw Subagent 70eb6908e3
Some checks failed
Build & Deploy to Staging / Build & Deploy to Staging (push) Has been cancelled
Document rate limit headers in OpenAPI spec
- Add reusable header components (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After)
- Reference headers in 200 responses on all conversion and demo endpoints
- Add Retry-After header to 429 responses
- Update Rate Limits section in API description to mention response headers
- Add comprehensive tests for header documentation (21 new tests)
- All 809 tests passing
2026-03-18 11:06:22 +01:00

64 lines
3.1 KiB
JavaScript

import nodemailer from "nodemailer";
import logger from "./logger.js";
const smtpUser = process.env.SMTP_USER;
const smtpPass = process.env.SMTP_PASS;
const smtpHost = process.env.SMTP_HOST || "host.docker.internal";
const smtpPort = Number(process.env.SMTP_PORT || 25);
const smtpFrom = process.env.SMTP_FROM || "DocFast <noreply@docfast.dev>";
const smtpSecure = smtpPort === 465;
const transportConfig = {
host: smtpHost,
port: smtpPort,
secure: smtpSecure,
connectionTimeout: 5000,
greetingTimeout: 5000,
socketTimeout: 10000,
tls: { rejectUnauthorized: false },
...(smtpUser && smtpPass ? { auth: { user: smtpUser, pass: smtpPass } } : {}),
};
const transporter = nodemailer.createTransport(transportConfig);
export async function sendVerificationEmail(email, code) {
try {
const info = await transporter.sendMail({
from: smtpFrom,
to: email,
subject: "DocFast - Verify your email",
text: `Your DocFast verification code is: ${code}\n\nThis code expires in 15 minutes.\n\nIf you didn't request this, ignore this email.\n\n---\nDocFast — HTML to PDF API\nhttps://docfast.dev`,
html: `<!DOCTYPE html>
<html><body style="margin:0;padding:0;background:#0a0a0a;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;">
<table width="100%" cellpadding="0" cellspacing="0" style="background:#0a0a0a;padding:40px 0;">
<tr><td align="center">
<table width="480" cellpadding="0" cellspacing="0" style="background:#111;border-radius:12px;padding:40px;">
<tr><td align="center" style="padding-bottom:24px;">
<h1 style="margin:0;font-size:28px;font-weight:700;color:#44ff99;letter-spacing:-0.5px;">DocFast</h1>
</td></tr>
<tr><td align="center" style="padding-bottom:8px;">
<p style="margin:0;font-size:16px;color:#e8e8e8;">Your verification code</p>
</td></tr>
<tr><td align="center" style="padding-bottom:24px;">
<div style="display:inline-block;background:#0a0a0a;border:2px solid #44ff99;border-radius:8px;padding:16px 32px;font-family:monospace;font-size:32px;letter-spacing:8px;color:#44ff99;font-weight:700;">${code}</div>
</td></tr>
<tr><td align="center" style="padding-bottom:8px;">
<p style="margin:0;font-size:14px;color:#999;">This code expires in 15 minutes.</p>
</td></tr>
<tr><td align="center" style="padding-bottom:24px;">
<p style="margin:0;font-size:14px;color:#999;">If you didn't request this, ignore this email.</p>
</td></tr>
<tr><td align="center" style="border-top:1px solid #222;padding-top:20px;">
<p style="margin:0;font-size:12px;color:#666;">DocFast — HTML to PDF API<br><a href="https://docfast.dev" style="color:#44ff99;text-decoration:none;">docfast.dev</a></p>
</td></tr>
</table>
</td></tr>
</table>
</body></html>`,
});
logger.info({ email, messageId: info.messageId }, "Verification email sent");
return true;
}
catch (err) {
logger.error({ err, email }, "Failed to send verification email");
return false;
}
}
// NOTE: sendRecoveryEmail removed — API keys must NEVER be sent via email.
// Key recovery now shows the key in the browser after code verification.