From 8bc9e566db746391520b7bf6a5bd616b914d1e84 Mon Sep 17 00:00:00 2001 From: Adrian Stephens Date: Mon, 29 Jun 2026 06:51:57 +0100 Subject: [PATCH] Improved password handling on profile page --- .../feca_mailshots_plugin.php | 2 +- .../src/Admin/AdminRequestHelpers.php | 3 + .../src/Admin/ProfileAdminPage.php | 100 +++++++++++++++++- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/feca_mailshots_plugin/feca_mailshots_plugin.php b/feca_mailshots_plugin/feca_mailshots_plugin.php index 115e1f3..5630078 100644 --- a/feca_mailshots_plugin/feca_mailshots_plugin.php +++ b/feca_mailshots_plugin/feca_mailshots_plugin.php @@ -3,7 +3,7 @@ * Plugin Name: FECA Mailshots * Plugin URI: https://fenedge.co.uk/ * Description: FECA mailshots plugin. - * Version: 1.1.8 + * Version: 1.1.10 * Requires at least: 6.0 * Requires PHP: 7.4 * Author: FECA diff --git a/feca_mailshots_plugin/src/Admin/AdminRequestHelpers.php b/feca_mailshots_plugin/src/Admin/AdminRequestHelpers.php index 944b7e9..12a827b 100644 --- a/feca_mailshots_plugin/src/Admin/AdminRequestHelpers.php +++ b/feca_mailshots_plugin/src/Admin/AdminRequestHelpers.php @@ -55,6 +55,9 @@ trait AdminRequestHelpers . '.feca-mailshots-admin .feca-form .form-table th,.feca-mailshots-admin .feca-form .form-table td{padding-top:12px;padding-bottom:12px;}' . '.feca-mailshots-admin .feca-form .form-table th{width:220px;}' . '.feca-mailshots-admin .feca-form .description{margin-top:var(--feca-space-1);}' + . '.feca-mailshots-admin .feca-password-control{display:flex;align-items:center;gap:8px;max-width:34rem;}' + . '.feca-mailshots-admin .feca-password-control .regular-text{flex:1;min-width:220px;margin:0;}' + . '.feca-mailshots-admin .feca-password-toggle{min-width:74px;text-align:center;}' . '.feca-mailshots-admin .feca-inline-form{display:inline;}' . '.feca-mailshots-admin .feca-hidden{display:none;}' . '.feca-mailshots-admin .feca-meta-line{margin:4px 0 var(--feca-space-3) 0;color:#6b7280;font-size:12px;}' diff --git a/feca_mailshots_plugin/src/Admin/ProfileAdminPage.php b/feca_mailshots_plugin/src/Admin/ProfileAdminPage.php index ea543ba..a0ef4c3 100644 --- a/feca_mailshots_plugin/src/Admin/ProfileAdminPage.php +++ b/feca_mailshots_plugin/src/Admin/ProfileAdminPage.php @@ -46,16 +46,39 @@ final class ProfileAdminPage } $uid = $this->wp->currentUserId(); - $saved = $uid > 0 ? ($this->repo()->findByUserId($uid) ?? []) : []; + $saved = []; + $loadError = ''; + if ($uid > 0) { + try { + $saved = $this->repo()->findByUserId($uid) ?? []; + } catch (\Throwable $e) { + $loadError = 'Unable to load stored profile credentials: ' . $e->getMessage(); + } + } $status = $this->wp->requestParam('saved', '') === '1' ? 'Profile credentials saved.' : ''; $test = $uid > 0 ? $this->testResult($uid) : null; $action = htmlspecialchars($this->wp->adminUrl('admin-post.php')); + $missingPasswords = $loadError === '' ? $this->missingPasswordLabels($saved) : []; echo '

Mailshot Profile

'; echo $this->renderAdminUiStyles(); + if ($loadError !== '') { + echo '
' . htmlspecialchars($loadError) . '
'; + } if ($status !== '') { echo '
' . htmlspecialchars($status) . '
'; } + if ($missingPasswords !== []) { + echo '
'; + echo '' . htmlspecialchars('Missing password configuration.') . ''; + echo '

' . htmlspecialchars('Enter and save the missing password before running mailshot tests or sends.') . '

'; + echo '
    '; + foreach ($missingPasswords as $label) { + echo '
  • ' . htmlspecialchars($label) . '
  • '; + } + echo '
'; + echo '
'; + } if ($test !== null) { $ok = !empty($test['ok']); $kind = strtoupper((string) ($test['kind'] ?? 'CREDENTIAL')); @@ -92,7 +115,7 @@ final class ProfileAdminPage $this->field('SMTP Host', 'smtp_host', $saved['smtp_host'] ?? ''); $this->field('SMTP Port', 'smtp_port', (string) ($saved['smtp_port'] ?? '')); $this->field('SMTP User', 'smtp_user', $saved['smtp_user'] ?? ''); - $this->field('SMTP Password', 'smtp_password', '', 'password', 'Required on each save/test request'); + $this->field('SMTP Password', 'smtp_password', (string) ($saved['smtp_password'] ?? ''), 'password'); $this->field('From Email', 'smtp_from_email', $saved['smtp_from_email'] ?? ''); $this->field('From Name', 'smtp_from_name', $saved['smtp_from_name'] ?? ''); @@ -105,7 +128,7 @@ final class ProfileAdminPage $this->field('IMAP Host', 'imap_host', $saved['imap_host'] ?? ''); $this->field('IMAP Port', 'imap_port', (string) ($saved['imap_port'] ?? '')); $this->field('IMAP User', 'imap_user', $saved['imap_user'] ?? ''); - $this->field('IMAP Password', 'imap_password', '', 'password', 'Required on each save/test request'); + $this->field('IMAP Password', 'imap_password', (string) ($saved['imap_password'] ?? ''), 'password'); $this->field('IMAP Sent Folder', 'imap_sent_folder', $saved['imap_sent_folder'] ?? ''); $this->field('IMAP Mailbox Flags', 'imap_mailbox_flags', $saved['imap_mailbox_flags'] ?? ''); echo ''; @@ -116,7 +139,9 @@ final class ProfileAdminPage echo ''; echo ''; echo '

'; - echo '
'; + echo ''; + echo $this->renderPasswordToggleScript(); + echo ''; } public function handleSave(): void @@ -210,6 +235,8 @@ final class ProfileAdminPage 'imap_mailbox_flags' => trim((string) ($this->wp->requestParam('imap_mailbox_flags', '') ?? '')), ]; + $payload = $this->applyStoredPasswordsForTest($uid, $payload); + $result = $kind === 'smtp' ? $this->runSmtpTest($payload) : $this->runImapTest($payload); $this->wp->updateOption($this->testResultOptionKey($uid), $result); @@ -225,13 +252,76 @@ final class ProfileAdminPage { echo ''; echo ''; - echo ''; + echo ''; + if ($type === 'password') { + echo ''; + echo ''; + echo ''; + echo ''; + } else { + echo ''; + } if ($hint !== '') { echo '

' . htmlspecialchars($hint) . '

'; } echo ''; } + private function renderPasswordToggleScript(): string + { + return <<<'HTML' + +HTML; + } + + /** @param array $saved @return list */ + private function missingPasswordLabels(array $saved): array + { + $missing = []; + if (trim((string) ($saved['smtp_password'] ?? '')) === '') { + $missing[] = 'SMTP password is missing.'; + } + if (trim((string) ($saved['imap_password'] ?? '')) === '') { + $missing[] = 'IMAP password is missing.'; + } + return $missing; + } + + /** @param array $payload @return array */ + private function applyStoredPasswordsForTest(int $uid, array $payload): array + { + try { + $saved = $this->repo()->findByUserId($uid) ?? []; + } catch (\Throwable $e) { + return $payload; + } + + foreach (['smtp_password', 'imap_password'] as $key) { + if (trim((string) ($payload[$key] ?? '')) === '' && trim((string) ($saved[$key] ?? '')) !== '') { + $payload[$key] = (string) $saved[$key]; + } + } + + return $payload; + } + private function repo(): MailCredentialRepository { return ($this->repoFactory)();