Korjaa captcha race condition + paranna SMTP-debuggausta

Captcha: loadBranding() ensin, sitten captcha+auth, jotta sessio-cookie
on luotu ennen captcha-latausta (estää eri sessiot rinnakkaisilla kutsuilla).

SMTP-testi: lisää salasanavihje (3 ensimmäistä + 2 viimeistä merkkiä),
override-kentät joilla voi testata eri tunnuksilla suoraan ilman DB:tä.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 00:01:52 +02:00
parent 1a41579e4b
commit 335ed540f1
3 changed files with 42 additions and 7 deletions

13
api.php
View File

@@ -2996,20 +2996,33 @@ switch ($action) {
'smtp_encryption' => $mailbox['smtp_encryption'] ?? '',
'smtp_from_email' => $mailbox['smtp_from_email'] ?? '',
];
// Override: käyttäjä voi antaa tunnukset suoraan testiin (ohittaa DB:n)
$overrideUser = trim($input['override_user'] ?? '');
$overridePass = $input['override_pass'] ?? '';
// Laske fallback-arvot
$effectiveUser = $mailbox['smtp_user'] ?? '';
if ($effectiveUser === '') $effectiveUser = $mailbox['imap_user'] ?? '';
if ($effectiveUser === '') $effectiveUser = $mailbox['smtp_from_email'] ?? '';
$effectivePass = $mailbox['smtp_password'] ?? '';
if ($effectivePass === '') $effectivePass = $mailbox['imap_password'] ?? '';
// Jos override annettu, käytä sitä
$usingOverride = false;
if ($overrideUser !== '') { $effectiveUser = $overrideUser; $usingOverride = true; }
if ($overridePass !== '') { $effectivePass = $overridePass; $usingOverride = true; }
$host = $mailbox['smtp_host'] ?? '';
$port = (int)($mailbox['smtp_port'] ?? 587);
$encryption = $mailbox['smtp_encryption'] ?? 'tls';
// Salasana-vihje: näytä ensimmäiset 3 ja viimeiset 2 merkkiä
$passHint = strlen($effectivePass) > 5
? substr($effectivePass, 0, 3) . '***' . substr($effectivePass, -2)
: (strlen($effectivePass) > 0 ? '***(' . strlen($effectivePass) . ' merkkiä)' : '(tyhjä)');
$result = [
'db_values' => $dbInfo,
'effective_user' => $effectiveUser,
'effective_pass_hint' => $passHint,
'effective_pass_len' => strlen($effectivePass),
'using_override' => $usingOverride,
'steps' => [],
];

View File

@@ -862,6 +862,14 @@
<button class="btn-secondary" id="btn-test-smtp" style="background:#2196F3;color:#fff;border:none;">🔌 Testaa SMTP</button>
<button class="btn-secondary" id="btn-cancel-mailbox">Peruuta</button>
</div>
<div id="smtp-test-override" style="display:none;margin-top:0.5rem;padding:0.75rem;background:#f0f4ff;border-radius:6px;">
<div style="font-size:0.8rem;color:#666;margin-bottom:0.4rem;">Testaa eri tunnuksilla (ohittaa tietokannan):</div>
<div style="display:flex;gap:0.5rem;align-items:center;flex-wrap:wrap;">
<input type="text" id="smtp-test-user" placeholder="Käyttäjä (tyhjä = DB)" style="flex:1;min-width:150px;padding:0.3rem 0.5rem;font-size:0.85rem;">
<input type="password" id="smtp-test-pass" placeholder="Salasana (tyhjä = DB)" style="flex:1;min-width:150px;padding:0.3rem 0.5rem;font-size:0.85rem;">
<button class="btn-secondary" id="btn-test-smtp-override" style="background:#FF9800;color:#fff;border:none;padding:0.3rem 0.7rem;font-size:0.85rem;">Testaa näillä</button>
</div>
</div>
<pre id="smtp-test-result" style="display:none;background:#1a1a2e;color:#0f0;padding:0.75rem;border-radius:6px;font-size:0.8rem;max-height:300px;overflow:auto;margin-top:0.5rem;white-space:pre-wrap;"></pre>
</div>
</div>

View File

@@ -2601,7 +2601,7 @@ document.getElementById('btn-cancel-mailbox').addEventListener('click', () => {
});
// SMTP-testaus
document.getElementById('btn-test-smtp').addEventListener('click', async () => {
async function runSmtpTest(overrideUser = '', overridePass = '') {
const mailboxId = document.getElementById('mailbox-form-id').value;
const resultEl = document.getElementById('smtp-test-result');
if (!mailboxId) {
@@ -2611,8 +2611,13 @@ document.getElementById('btn-test-smtp').addEventListener('click', async () => {
}
resultEl.style.display = '';
resultEl.textContent = '⏳ Testataan SMTP-yhteyttä...';
// Näytä override-kentät
document.getElementById('smtp-test-override').style.display = '';
try {
const res = await apiCall('smtp_test', 'POST', { mailbox_id: mailboxId });
const payload = { mailbox_id: mailboxId };
if (overrideUser) payload.override_user = overrideUser;
if (overridePass) payload.override_pass = overridePass;
const res = await apiCall('smtp_test', 'POST', payload);
let output = '=== TIETOKANNAN ARVOT ===\n';
if (res.db_values) {
for (const [k, v] of Object.entries(res.db_values)) {
@@ -2620,8 +2625,9 @@ document.getElementById('btn-test-smtp').addEventListener('click', async () => {
}
}
output += `\n=== KÄYTETTÄVÄT ARVOT ===\n`;
if (res.using_override) output += ` ⚠️ KÄYTETÄÄN OVERRIDE-TUNNUKSIA\n`;
output += ` Käyttäjä: ${res.effective_user || '(tyhjä)'}\n`;
output += ` Salasanan pituus: ${res.effective_pass_len}\n\n`;
output += ` Salasana: ${res.effective_pass_hint || '?'} (${res.effective_pass_len} merkkiä)\n\n`;
output += `=== TESTIN VAIHEET ===\n`;
if (res.steps) {
res.steps.forEach(s => { output += ` ${s}\n`; });
@@ -2633,6 +2639,13 @@ document.getElementById('btn-test-smtp').addEventListener('click', async () => {
} catch (e) {
resultEl.textContent = '❌ Virhe: ' + e.message;
}
}
document.getElementById('btn-test-smtp').addEventListener('click', () => runSmtpTest());
document.getElementById('btn-test-smtp-override').addEventListener('click', () => {
const user = document.getElementById('smtp-test-user').value;
const pass = document.getElementById('smtp-test-pass').value;
runSmtpTest(user, pass);
});
// ==================== YRITYKSEN KÄYTTÄJÄOIKEUDET ====================
@@ -3168,7 +3181,8 @@ async function loadBranding() {
}
}
// Init
loadBranding();
loadCaptcha();
checkAuth();
// Init — branding ensin (luo session-cookien), sitten captcha + auth
loadBranding().then(() => {
loadCaptcha();
checkAuth();
});