Changeset ca507ef in Klonkt
- Timestamp:
- 06/19/2026 08:29:28 AM (3 months ago)
- Branches:
- main
- Children:
- 7eb35ae
- Parents:
- 977f65d
- Location:
- src
- Files:
-
- 3 edited
-
config/mailer.js (modified) (2 diffs)
-
routes/admin-settings.js (modified) (3 diffs)
-
views/pages/admin-settings.ejs (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/config/mailer.js
r977f65d rca507ef 1 // E-mail versturen (wachtwoord-reset). Optioneel: alleen actief als de self-hoster 2 // SMTP heeft ingesteld. Niet ingesteld? Dan valt de reset terug op de CLI 3 // (`npm run reset-admin`) — zie README. 1 // E-mail versturen (wachtwoord-reset, nieuwsbrief, notify). Optioneel: alleen actief 2 // als SMTP is ingesteld — via Beheer → Instellingen (app_settings) OF env-vars. 4 3 // 5 // Config viaenv:6 // SMTP_HOST, SMTP_PORT (default 587), SMTP_USER, SMTP_PASS 7 // SMTP_FROM (afzender; default = SMTP_USER)4 // Config-bron (in deze volgorde): app_settings (ingesteld in de UI), anders env: 5 // SMTP_HOST, SMTP_PORT (default 587), SMTP_USER, SMTP_PASS, SMTP_FROM (default = USER) 6 // Niet ingesteld → versturen valt terug op CLI (reset-admin) / wordt overgeslagen. 8 7 9 8 import nodemailer from 'nodemailer'; 9 import { getSetting } from '../services/SettingsService.js'; 10 10 11 const HOST = process.env.SMTP_HOST || ''; 12 const PORT = parseInt(process.env.SMTP_PORT || '587', 10); 13 const USER = process.env.SMTP_USER || ''; 14 const PASS = process.env.SMTP_PASS || ''; 15 const FROM = process.env.SMTP_FROM || USER; 11 function cfg() { 12 const host = getSetting('smtp_host', '') || process.env.SMTP_HOST || ''; 13 const port = parseInt(getSetting('smtp_port', '') || process.env.SMTP_PORT || '587', 10) || 587; 14 const user = getSetting('smtp_user', '') || process.env.SMTP_USER || ''; 15 const pass = getSetting('smtp_pass', '') || process.env.SMTP_PASS || ''; 16 const from = getSetting('smtp_from', '') || process.env.SMTP_FROM || user; 17 return { host, port, user, pass, from }; 18 } 16 19 17 20 export function mailerConfigured() { 18 return !!(HOST && USER && PASS); 21 const c = cfg(); 22 return !!(c.host && c.user && c.pass); 19 23 } 20 24 21 let _transport = null; 25 // Status voor de UI (zonder het wachtwoord te lekken). 26 export function mailerStatus() { 27 const c = cfg(); 28 return { 29 configured: mailerConfigured(), 30 host: c.host, 31 port: c.port, 32 user: c.user, 33 from: c.from, 34 passSet: !!c.pass, 35 // bron: handig om te tonen dat env nog actief is 36 fromEnv: !getSetting('smtp_host', '') && !!process.env.SMTP_HOST, 37 }; 38 } 39 40 // Transport cachen, maar herbouwen zodra de config wijzigt (UI-edit zonder herstart). 41 let _transport = null, _key = null; 22 42 function transport() { 23 if (!_transport) { 43 const c = cfg(); 44 const key = [c.host, c.port, c.user, c.pass].join('|'); 45 if (!_transport || _key !== key) { 24 46 _transport = nodemailer.createTransport({ 25 host: HOST,26 port: PORT,27 secure: PORT=== 465, // 465 = impliciete TLS; 587 = STARTTLS28 auth: { user: USER, pass: PASS},47 host: c.host, 48 port: c.port, 49 secure: c.port === 465, // 465 = impliciete TLS; 587 = STARTTLS 50 auth: { user: c.user, pass: c.pass }, 29 51 }); 52 _key = key; 30 53 } 31 54 return _transport; … … 34 57 export async function sendMail({ to, subject, text, html }) { 35 58 if (!mailerConfigured()) throw new Error('SMTP niet geconfigureerd'); 36 return transport().sendMail({ from: FROM, to, subject, text, html }); 59 const c = cfg(); 60 return transport().sendMail({ from: c.from, to, subject, text, html }); 37 61 } -
src/routes/admin-settings.js
r977f65d rca507ef 22 22 import { requireGod } from '../middleware/auth.js'; 23 23 import { getTenancy, setTenancy, getSetting, setSetting } from '../services/SettingsService.js'; 24 import { mailerStatus, sendMail } from '../config/mailer.js'; 24 25 import { entitlementStatus, premiumUnlocked } from '../services/PatreonService.js'; 25 26 import { googleConfigured, redirectUri, currentClientId, clientSecretSet } from '../config/google.js'; … … 83 84 secretSet: clientSecretSet(), 84 85 }, 86 smtp: mailerStatus(), 85 87 success: req.query.success || null, 86 88 error: req.query.error || null, … … 151 153 }); 152 154 155 // ── SMTP / e-mail-instellingen ──────────────────────────────────── 156 router.post('/smtp', requireGod, (req, res) => { 157 const b = req.body || {}; 158 if (b.clear === '1') { 159 ['smtp_host', 'smtp_port', 'smtp_user', 'smtp_pass', 'smtp_from'].forEach((k) => setSetting(k, '')); 160 return res.redirect('/admin/settings?success=' + encodeURIComponent('SMTP-instellingen gewist')); 161 } 162 setSetting('smtp_host', (b.smtp_host || '').toString().trim()); 163 setSetting('smtp_port', (b.smtp_port || '').toString().trim()); 164 setSetting('smtp_user', (b.smtp_user || '').toString().trim()); 165 setSetting('smtp_from', (b.smtp_from || '').toString().trim()); 166 // Wachtwoord alleen overschrijven als er een nieuwe waarde is ingevoerd. 167 const pass = (b.smtp_pass || '').toString(); 168 if (pass) setSetting('smtp_pass', pass); 169 res.redirect('/admin/settings?success=' + encodeURIComponent('SMTP-instellingen opgeslagen')); 170 }); 171 172 // Testmail sturen naar een opgegeven adres (of de ingelogde gebruiker). 173 router.post('/smtp/test', requireGod, async (req, res) => { 174 const to = ((req.body && req.body.to) || (req.session.user && req.session.user.email) || '').toString().trim(); 175 if (!to || to.indexOf('@') === -1) { 176 return res.redirect('/admin/settings?error=' + encodeURIComponent('Geef een geldig test-e-mailadres op.')); 177 } 178 try { 179 await sendMail({ 180 to, 181 subject: 'Klonkt — SMTP-test', 182 text: 'Gelukt! Je SMTP-instellingen werken. Dit is een testbericht van je Klonkt-site.', 183 html: '<p>Gelukt! Je <strong>SMTP-instellingen werken</strong>. Dit is een testbericht van je Klonkt-site.</p>', 184 }); 185 res.redirect('/admin/settings?success=' + encodeURIComponent('Testmail verstuurd naar ' + to)); 186 } catch (e) { 187 res.redirect('/admin/settings?error=' + encodeURIComponent('Testmail mislukt: ' + (e.message || e))); 188 } 189 }); 190 153 191 export default router; -
src/views/pages/admin-settings.ejs
r977f65d rca507ef 110 110 <% if (typeof premiumEnabled !== 'undefined' && premiumEnabled && !(premium && premium.premium)) { %> 111 111 <p class="set-help" style="margin-top:.7rem; color:var(--accent)">Premium-laag staat aan zonder Patreon — de Google-knop blijft verborgen tot premium ontgrendeld is.</p> 112 <% } %> 113 </section> 114 115 <%# E-mail / SMTP — nodig voor nieuwsbrief versturen, notify-mails en wachtwoord-reset. %> 116 <section class="set-card" style="margin-top:1rem"> 117 <h2>E-mail (SMTP)</h2> 118 <p class="set-help">Nodig om de <strong>nieuwsbrief te versturen</strong>, <strong>show-notify</strong>-mails te sturen en wachtwoord-reset per mail te laten werken. Vul de gegevens van je mailprovider in (bv. je hostingmail, Gmail-app-wachtwoord, Brevo, Mailgun…). 119 <% if (smtp && smtp.configured) { %><br><strong>Status: ingesteld ✓</strong><% if (smtp.fromEnv) { %> <small>(via .env)</small><% } %><% } else { %><br>Nog niet ingesteld — versturen werkt nog niet.<% } %></p> 120 121 <form method="post" action="/admin/settings/smtp" class="set-form"> 122 <label><span>SMTP-host</span> 123 <input type="text" name="smtp_host" value="<%= smtp ? smtp.host : '' %>" placeholder="smtp.jouwprovider.nl" autocomplete="off"> 124 </label> 125 <label><span>Poort <small style="font-weight:400">— 587 (STARTTLS) of 465 (SSL)</small></span> 126 <input type="text" name="smtp_port" value="<%= (smtp && smtp.port) ? smtp.port : '' %>" placeholder="587" autocomplete="off" inputmode="numeric"> 127 </label> 128 <label><span>Gebruikersnaam</span> 129 <input type="text" name="smtp_user" value="<%= smtp ? smtp.user : '' %>" placeholder="jij@jouwprovider.nl" autocomplete="off"> 130 </label> 131 <label><span>Wachtwoord <% if (smtp && smtp.passSet) { %><small style="font-weight:400">— ingesteld; leeg laten = ongewijzigd</small><% } %></span> 132 <input type="password" name="smtp_pass" placeholder="<%= (smtp && smtp.passSet) ? '•••••••• (ingesteld)' : 'app-wachtwoord' %>" autocomplete="off"> 133 </label> 134 <label><span>Afzender <small style="font-weight:400">— optioneel; standaard = gebruikersnaam</small></span> 135 <input type="text" name="smtp_from" value="<%= smtp ? smtp.from : '' %>" placeholder="Jouw Naam <jij@jouwprovider.nl>" autocomplete="off"> 136 </label> 137 <div class="set-actions"> 138 <button type="submit" class="btn btn-primary">SMTP opslaan</button> 139 <% if (smtp && (smtp.host || smtp.passSet)) { %> 140 <button type="submit" name="clear" value="1" class="btn" formnovalidate>Wissen</button> 141 <% } %> 142 </div> 143 </form> 144 145 <% if (smtp && smtp.configured) { %> 146 <form method="post" action="/admin/settings/smtp/test" class="set-form" style="margin-top:.8rem"> 147 <label><span>Testmail sturen naar</span> 148 <input type="email" name="to" placeholder="jij@email.nl" autocomplete="off"> 149 </label> 150 <div class="set-actions"><button type="submit" class="btn">✉ Testmail sturen</button></div> 151 </form> 112 152 <% } %> 113 153 </section>
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)