fix(email): derive SMTP auth from credentials

This commit is contained in:
2026-09-04 13:24:26 +08:00
parent 13fda31e37
commit dda343e398
4 changed files with 67 additions and 29 deletions
+4 -6
View File
@@ -176,13 +176,11 @@ class GlobalController extends ControllerBase {
return $this->error(__('请输入有效的邮箱地址', 'aksrt'));
}
$sent = class_exists('\\AKSRT\\Settings\\Mail')
? \AKSRT\Settings\Mail::send_test_email($to)
: false;
if ($sent) {
return $this->success(['message' => '测试邮件已发送']);
$result = \AKSRT\Settings\Mail::send_test_email($to);
if (is_wp_error($result)) {
return $this->error(__('邮件发送失败,详细原因已写入服务器错误日志', 'aksrt'));
}
return $this->error(__('邮件发送失败,请检查 SMTP 配置', 'aksrt'));
return $this->success(['message' => '测试邮件已发送']);
}
public function rest_homepage_tab_posts(\WP_REST_Request $request): \WP_REST_Response {
+45 -21
View File
@@ -10,24 +10,21 @@ namespace AKSRT\Settings;
defined('ABSPATH') || exit;
final class Mail {
/** @return list<string> */
public static function events(): array {
return array_keys(MailTemplates::definitions());
}
/** @return array<string, mixed> */
public static function get_smtp(): array {
$s = Settings::get_all();
$username = trim((string) ($s['mail_smtp_name'] ?? '')) ?: sanitize_email((string) ($s['mail_name'] ?? ''));
$password = (string) ($s['mail_passwd'] ?? '');
return [
'enabled' => !empty($s['mail_smtps']),
'host' => trim((string) ($s['mail_host'] ?? '')),
'port' => max(1, min(65535, (int) ($s['mail_port'] ?? 465))),
'username' => trim((string) ($s['mail_smtp_name'] ?? '')) ?: sanitize_email((string) ($s['mail_name'] ?? '')),
'password' => (string) ($s['mail_passwd'] ?? ''),
'username' => $username,
'password' => $password,
'encryption' => in_array(($s['mail_smtpsecure'] ?? 'ssl'), ['ssl', 'tls', ''], true) ? (string) ($s['mail_smtpsecure'] ?? 'ssl') : 'ssl',
'from_name' => trim((string) ($s['mail_showname'] ?? '')) ?: get_bloginfo('name'),
'from_address' => sanitize_email((string) ($s['mail_name'] ?? '')),
'auth' => !empty($s['mail_smtpauth']),
'auth' => $username !== '' && $password !== '',
];
}
@@ -88,16 +85,25 @@ final class Mail {
$definition = MailTemplates::definitions()[$event];
$subject = (string) ($cfg['subject'] ?? $default_subject ?: $definition['title']);
$content = (string) ($cfg['content'] ?? $default_content ?: $definition['content']);
$subject = self::replace_placeholders($subject, $placeholders, false);
$content = self::replace_placeholders($content, $placeholders, false);
$subject = self::replace_placeholders($subject, $placeholders);
$content = self::replace_placeholders($content, $placeholders);
$content = self::wrap_html($content, $cfg['global'] ?? []);
$headers = ['Content-Type: text/html; charset=UTF-8'];
return (bool) wp_mail($to, $subject, $content, $headers);
}
public static function send_test_email(string $to): bool {
public static function send_test_email(string $to): bool|\WP_Error {
$to = sanitize_email($to);
if ($to === '' || !is_email($to)) return false;
if ($to === '' || !is_email($to)) {
return new \WP_Error('aksrt_invalid_test_email', __('请输入有效的邮箱地址', 'aksrt'));
}
$failure = null;
$capture_failure = static function (\WP_Error $error) use (&$failure): void {
$failure = $error;
};
add_action('wp_mail_failed', $capture_failure);
$site = esc_html((string) get_bloginfo('name'));
$subject = '邮件配置测试';
$content = "您好,\n\n这是一封来自 {$site} 的邮件配置测试。";
@@ -105,7 +111,22 @@ final class Mail {
'description' => '此信为系统邮件,请不要直接回复。',
'more_content' => '',
]);
return (bool) wp_mail($to, $subject, $content, ['Content-Type: text/html; charset=UTF-8']);
try {
$sent = (bool) wp_mail($to, $subject, $content, ['Content-Type: text/html; charset=UTF-8']);
} finally {
remove_action('wp_mail_failed', $capture_failure);
}
if ($sent) {
return true;
}
$error = $failure instanceof \WP_Error
? $failure
: new \WP_Error('aksrt_mail_failed', __('wp_mail 返回失败,但未提供详细错误。', 'aksrt'));
self::log_test_failure($error);
return $error;
}
/** @return array<string, mixed> */
@@ -121,20 +142,23 @@ final class Mail {
];
}
private static function replace_placeholders(string $value, array $placeholders, bool $html): string {
private static function replace_placeholders(string $value, array $placeholders): string {
$replace = [];
foreach ($placeholders as $key => $replacement) {
$replacement = (string) $replacement;
if ($html) {
$replacement = str_contains($key, 'url') ? esc_url($replacement) : esc_html($replacement);
} else {
$replacement = wp_strip_all_tags($replacement);
}
$replace[$key] = $replacement;
$replace[$key] = wp_strip_all_tags((string) $replacement);
}
return strtr($value, $replace);
}
private static function log_test_failure(\WP_Error $error): void {
$message = sanitize_text_field($error->get_error_message());
$message = preg_replace('/[A-Z0-9._%+\-]+@[A-Z0-9.\-]+\.[A-Z]{2,}/i', '[email]', $message);
$message = preg_replace('/\b(?:[a-z0-9-]+\.)+[a-z]{2,}\b/i', '[host]', (string) $message);
$message = preg_replace('/\b(?:\d{1,3}\.){3}\d{1,3}\b/', '[ip]', (string) $message);
$message = preg_replace('/\b(?:password|passwd|username|user|login|credential)\s*[:=]\s*[^\s,;]+/i', '$1=[redacted]', (string) $message);
error_log('[AKSRT] SMTP 测试失败:' . substr((string) $message, 0, 500));
}
private static function wrap_html(string $content, array $global): string {
$logo = method_exists(Settings::class, 'logo_url') ? Settings::logo_url() : '';
$background = esc_url(AKSRT_URI . '/assets/img/mail-bg.png');
-2
View File
@@ -62,7 +62,6 @@ final class MailTemplates {
'mail_smtp_name' => '',
'mail_host' => '',
'mail_port' => 465,
'mail_smtpauth' => true,
'mail_smtpsecure' => 'ssl',
'mail_showname' => $site,
'mail_title_prefix' => '[' . $site . ']',
@@ -89,7 +88,6 @@ final class MailTemplates {
['key' => 'mail_smtp_name', 'label' => 'SMTP 用户名', 'type' => 'input', 'default' => $defaults['mail_smtp_name'], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_host', 'label' => '邮件服务器地址', 'type' => 'input', 'default' => $defaults['mail_host'], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_port', 'label' => 'SMTP 服务器端口', 'type' => 'number', 'default' => $defaults['mail_port'], 'min' => 1, 'max' => 65535, 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_smtpauth', 'label' => '启用 SMTPAuth', 'type' => 'switch', 'default' => $defaults['mail_smtpauth'], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
['key' => 'mail_smtpsecure', 'label' => '加密方式', 'type' => 'select', 'default' => $defaults['mail_smtpsecure'], 'options' => [['label' => 'SSL', 'value' => 'ssl'], ['label' => 'TLS', 'value' => 'tls'], ['label' => '不加密', 'value' => '']], 'dependsOn' => ['key' => 'mail_smtps', 'value' => true]],
]],
['key' => 'branding', 'title' => '邮件品牌', 'fields' => [