diff --git a/api.php b/api.php index ac98c5e..18aba7f 100644 --- a/api.php +++ b/api.php @@ -2975,26 +2975,149 @@ switch ($action) { echo json_encode($mbs); break; - case 'mailbox_debug': + case 'smtp_test': requireAdmin(); $companyId = requireCompany(); - $mailboxes = dbLoadMailboxes($companyId); - $debug = array_map(function($mb) { - return [ - 'id' => $mb['id'], - 'nimi' => $mb['nimi'], - 'imap_host' => $mb['imap_host'] ?? '', - 'imap_user' => $mb['imap_user'] ?? '', - 'imap_pass_len' => strlen($mb['imap_password'] ?? ''), - 'smtp_host' => $mb['smtp_host'] ?? '', - 'smtp_port' => $mb['smtp_port'] ?? '', - 'smtp_user' => $mb['smtp_user'] ?? '', - 'smtp_pass_len' => strlen($mb['smtp_password'] ?? ''), - 'smtp_encryption' => $mb['smtp_encryption'] ?? '', - 'smtp_from_email' => $mb['smtp_from_email'] ?? '', - ]; - }, $mailboxes); - echo json_encode($debug, JSON_PRETTY_PRINT); + $input = json_decode(file_get_contents('php://input'), true); + $mailboxId = $input['mailbox_id'] ?? ''; + $mailbox = dbGetMailbox($mailboxId); + if (!$mailbox) { + echo json_encode(['error' => 'Postilaatikkoa ei löydy']); + break; + } + // Näytä tietokannan raakatiedot + $dbInfo = [ + 'imap_user' => $mailbox['imap_user'] ?? '', + 'imap_pass_len' => strlen($mailbox['imap_password'] ?? ''), + 'smtp_host' => $mailbox['smtp_host'] ?? '', + 'smtp_port' => $mailbox['smtp_port'] ?? '', + 'smtp_user' => $mailbox['smtp_user'] ?? '', + 'smtp_pass_len' => strlen($mailbox['smtp_password'] ?? ''), + 'smtp_encryption' => $mailbox['smtp_encryption'] ?? '', + 'smtp_from_email' => $mailbox['smtp_from_email'] ?? '', + ]; + // 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'] ?? ''; + $host = $mailbox['smtp_host'] ?? ''; + $port = (int)($mailbox['smtp_port'] ?? 587); + $encryption = $mailbox['smtp_encryption'] ?? 'tls'; + + $result = [ + 'db_values' => $dbInfo, + 'effective_user' => $effectiveUser, + 'effective_pass_len' => strlen($effectivePass), + 'steps' => [], + ]; + + if (empty($host)) { + $result['steps'][] = '❌ SMTP-palvelin puuttuu'; + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + if (empty($effectivePass)) { + $result['steps'][] = '❌ Salasana puuttuu (tietokannassa ei SMTP- eikä IMAP-salasanaa)'; + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + + // Testaa yhteys + $connStr = ($encryption === 'ssl' ? 'ssl' : 'tcp') . "://{$host}:{$port}"; + $result['steps'][] = "🔌 Yhdistetään: {$connStr}"; + $ctx = stream_context_create(['ssl' => ['verify_peer' => false, 'verify_peer_name' => false, 'allow_self_signed' => true]]); + $fp = @stream_socket_client($connStr, $errno, $errstr, 15, STREAM_CLIENT_CONNECT, $ctx); + if (!$fp) { + $result['steps'][] = "❌ Yhteys epäonnistui: {$errstr} ({$errno})"; + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + stream_set_timeout($fp, 15); + $result['steps'][] = '✅ Yhteys muodostettu'; + + // Banner + $resp = smtpReadResponse($fp); + $result['steps'][] = '📨 Banner: ' . trim($resp); + if (smtpCode($resp) !== '220') { + $result['steps'][] = '❌ Virheellinen banner'; + fclose($fp); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + + // EHLO + $ehlo = smtpCommand($fp, "EHLO " . gethostname()); + $result['steps'][] = '📨 EHLO: ' . smtpCode($ehlo); + $result['ehlo_capabilities'] = trim($ehlo); + if (smtpCode($ehlo) !== '250') { + $result['steps'][] = '❌ EHLO hylätty'; + fclose($fp); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + + // STARTTLS + if ($encryption === 'tls') { + $resp = smtpCommand($fp, "STARTTLS"); + $result['steps'][] = '🔒 STARTTLS: ' . smtpCode($resp); + if (smtpCode($resp) !== '220') { + $result['steps'][] = '❌ STARTTLS hylätty: ' . trim($resp); + fclose($fp); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + $crypto = @stream_socket_enable_crypto($fp, true, + STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT | STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT); + if (!$crypto) { + $result['steps'][] = '❌ TLS-neuvottelu epäonnistui'; + fclose($fp); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + $result['steps'][] = '✅ TLS OK'; + // Re-EHLO + $ehlo = smtpCommand($fp, "EHLO " . gethostname()); + $result['steps'][] = '📨 EHLO2: ' . smtpCode($ehlo); + $result['ehlo_capabilities_tls'] = trim($ehlo); + } + + // AUTH PLAIN + $cred = base64_encode("\0{$effectiveUser}\0{$effectivePass}"); + $resp = smtpCommand($fp, "AUTH PLAIN {$cred}"); + $result['steps'][] = '🔑 AUTH PLAIN: ' . trim($resp); + if (smtpCode($resp) === '235') { + $result['steps'][] = '✅ Kirjautuminen onnistui (AUTH PLAIN)!'; + smtpCommand($fp, "QUIT"); + fclose($fp); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + + // AUTH LOGIN fallback + $resp = smtpCommand($fp, "AUTH LOGIN"); + $result['steps'][] = '🔑 AUTH LOGIN: ' . smtpCode($resp); + if (smtpCode($resp) === '334') { + $resp = smtpCommand($fp, base64_encode($effectiveUser)); + $result['steps'][] = '🔑 Käyttäjä: ' . smtpCode($resp); + if (smtpCode($resp) === '334') { + $resp = smtpCommand($fp, base64_encode($effectivePass)); + $result['steps'][] = '🔑 Salasana: ' . trim($resp); + if (smtpCode($resp) === '235') { + $result['steps'][] = '✅ Kirjautuminen onnistui (AUTH LOGIN)!'; + smtpCommand($fp, "QUIT"); + fclose($fp); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + break; + } + } + } + + $result['steps'][] = "❌ Kirjautuminen epäonnistui (käyttäjä: {$effectiveUser}, salasanan pituus: " . strlen($effectivePass) . ")"; + smtpCommand($fp, "QUIT"); + fclose($fp); + echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); break; case 'mailbox_save': diff --git a/index.html b/index.html index 5dc2c56..d7fcb18 100644 --- a/index.html +++ b/index.html @@ -859,8 +859,10 @@
+
+ diff --git a/script.js b/script.js index f1866ff..c1b5a9c 100644 --- a/script.js +++ b/script.js @@ -2600,6 +2600,41 @@ document.getElementById('btn-cancel-mailbox').addEventListener('click', () => { document.getElementById('mailbox-form-container').style.display = 'none'; }); +// SMTP-testaus +document.getElementById('btn-test-smtp').addEventListener('click', async () => { + const mailboxId = document.getElementById('mailbox-form-id').value; + const resultEl = document.getElementById('smtp-test-result'); + if (!mailboxId) { + resultEl.style.display = ''; + resultEl.textContent = '⚠️ Tallenna postilaatikko ensin, sitten testaa.'; + return; + } + resultEl.style.display = ''; + resultEl.textContent = '⏳ Testataan SMTP-yhteyttä...'; + try { + const res = await apiCall('smtp_test', 'POST', { mailbox_id: mailboxId }); + let output = '=== TIETOKANNAN ARVOT ===\n'; + if (res.db_values) { + for (const [k, v] of Object.entries(res.db_values)) { + output += ` ${k}: ${v === '' ? '(tyhjä)' : v}\n`; + } + } + output += `\n=== KÄYTETTÄVÄT ARVOT ===\n`; + output += ` Käyttäjä: ${res.effective_user || '(tyhjä)'}\n`; + output += ` Salasanan pituus: ${res.effective_pass_len}\n\n`; + output += `=== TESTIN VAIHEET ===\n`; + if (res.steps) { + res.steps.forEach(s => { output += ` ${s}\n`; }); + } + if (res.ehlo_capabilities_tls) { + output += `\n=== EHLO (TLS jälkeen) ===\n${res.ehlo_capabilities_tls}\n`; + } + resultEl.textContent = output; + } catch (e) { + resultEl.textContent = '❌ Virhe: ' + e.message; + } +}); + // ==================== YRITYKSEN KÄYTTÄJÄOIKEUDET ==================== async function loadCompanyUsers(companyId) {