feat: mailer with magic link email (allegiance pattern, MorseQuest branding)
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
'use strict'
|
||||
const nodemailer = require('nodemailer')
|
||||
|
||||
const SMTP_HOST = process.env.SMTP_HOST || ''
|
||||
const SMTP_PORT = parseInt(process.env.SMTP_PORT || '587', 10)
|
||||
const SMTP_USER = process.env.SMTP_USER || ''
|
||||
const SMTP_PASS = process.env.SMTP_PASS || ''
|
||||
const APP_URL = (process.env.APP_URL || 'http://localhost:3001').replace(/\/$/, '')
|
||||
const FROM_ADDR = SMTP_USER
|
||||
? `"MorseQuest" <${SMTP_USER}>`
|
||||
: '"MorseQuest" <noreply@morsequest.keylinkit.net>'
|
||||
|
||||
let transport = null
|
||||
if (SMTP_HOST && SMTP_USER && SMTP_PASS) {
|
||||
transport = nodemailer.createTransport({
|
||||
host: SMTP_HOST,
|
||||
port: SMTP_PORT,
|
||||
secure: SMTP_PORT === 465,
|
||||
auth: { user: SMTP_USER, pass: SMTP_PASS },
|
||||
})
|
||||
console.log(`[mailer] SMTP configured: ${SMTP_HOST}:${SMTP_PORT}`)
|
||||
} else {
|
||||
console.warn('[mailer] SMTP not configured — magic links will be logged only')
|
||||
}
|
||||
|
||||
async function send(to, subject, html) {
|
||||
if (!transport) {
|
||||
console.log(`[mailer] Would send to ${to}: ${subject}`)
|
||||
return
|
||||
}
|
||||
await transport.sendMail({ from: FROM_ADDR, to, subject, html })
|
||||
}
|
||||
|
||||
async function sendMagicLink(email, token) {
|
||||
const link = `${APP_URL}/api/auth/verify?token=${token}`
|
||||
const subject = 'Your MorseQuest Login Link'
|
||||
const html = `
|
||||
<div style="font-family:'Open Sans',sans-serif;max-width:480px;margin:0 auto;
|
||||
padding:2rem;background:#F5E6D3;border:2px solid #D4AF37">
|
||||
<h1 style="font-family:'Cinzel',serif;color:#3C2415;font-size:1.4rem;margin-bottom:1rem">
|
||||
⚡ MorseQuest Login
|
||||
</h1>
|
||||
<p style="color:#3C2415;line-height:1.6">
|
||||
Click the button below to log in to MorseQuest. This link is valid for 24 hours
|
||||
and can only be used once.
|
||||
</p>
|
||||
<div style="text-align:center;margin:2rem 0">
|
||||
<a href="${link}"
|
||||
style="display:inline-block;padding:0.8rem 2rem;background:#D4AF37;
|
||||
color:#3C2415;text-decoration:none;font-family:'Cinzel',serif;
|
||||
font-size:1rem;font-weight:600;border:2px solid #3C2415">
|
||||
Begin Your Quest ›
|
||||
</a>
|
||||
</div>
|
||||
<p style="color:#654321;font-size:0.85rem;line-height:1.5">
|
||||
If you didn't request this link, you can ignore this email safely.
|
||||
</p>
|
||||
</div>`
|
||||
await send(email, subject, html)
|
||||
}
|
||||
|
||||
module.exports = { sendMagicLink }
|
||||
Reference in New Issue
Block a user