9a0f3bb03a
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q8t9GEyyLZbUQu26na1JQg
118 lines
6.9 KiB
PHP
118 lines
6.9 KiB
PHP
<?php
|
|
/**
|
|
* Batch 59 — FluentSMTP tools. Net-new, GPL-2.0-or-later. See NOTICE.md.
|
|
* Inert unless FluentSMTP (FLUENTMAIL_PLUGIN_VERSION) is active.
|
|
* Reads the plugin's own log table ({prefix}fsmpt_email_logs) and the
|
|
* 'fluentmail-settings' option. Credentials (username/password/keys) are NEVER returned.
|
|
*/
|
|
|
|
namespace AskTamMCP\Extensions;
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class Batch59 {
|
|
|
|
public static function register($registry): void {
|
|
if (!defined('FLUENTMAIL_PLUGIN_VERSION')) return;
|
|
|
|
$def = function (string $name, string $desc, array $props, array $required, string $scope, string $method) {
|
|
$schema = ['type' => 'object', 'properties' => $props ?: new \stdClass()];
|
|
if ($required) $schema['required'] = $required;
|
|
return ['name' => $name, 'description' => $desc, 'scope' => $scope,
|
|
'handler' => 'AskTamMCP\\Extensions\\Batch59::' . $method, 'inputSchema' => $schema];
|
|
};
|
|
|
|
$registry->register($def('fluentsmtp_detect', 'Report whether FluentSMTP is active and its version.', [], [], 'read', 'detect'));
|
|
$registry->register($def('fluentsmtp_list_connections', 'List configured FluentSMTP sender connections (provider, sender name/email, host/port/encryption). Credentials are redacted.', [], [], 'read', 'listConnections'));
|
|
$registry->register($def('fluentsmtp_list_logs', 'List recent FluentSMTP email-log rows (id, to, subject, status, source, time). Body is not returned. Optionally filter by status (sent/failed/resent).',
|
|
['status' => ['type' => 'string'], 'per_page' => ['type' => 'integer', 'default' => 50]], [], 'read', 'listLogs'));
|
|
$registry->register($def('fluentsmtp_stats', 'FluentSMTP email counts grouped by status, plus total.', [], [], 'read', 'stats'));
|
|
$registry->register($def('fluentsmtp_send_test', 'Send a test email through the active FluentSMTP connection (routes via wp_mail). Returns whether wp_mail accepted it.',
|
|
['to' => ['type' => 'string'], 'subject' => ['type' => 'string'], 'body' => ['type' => 'string']], ['to'], 'write', 'sendTest'));
|
|
}
|
|
|
|
public static function detect(array $args): array {
|
|
return ['active' => defined('FLUENTMAIL_PLUGIN_VERSION'), 'version' => defined('FLUENTMAIL_PLUGIN_VERSION') ? FLUENTMAIL_PLUGIN_VERSION : null];
|
|
}
|
|
|
|
private static function logTable(): string { global $wpdb; return $wpdb->prefix . 'fsmpt_email_logs'; }
|
|
private static function hasLog(): bool { global $wpdb; $t = self::logTable(); return $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $t)) === $t; }
|
|
|
|
/** FluentSMTP stores recipient fields PHP-serialized (sometimes JSON). Normalise to a comma list. */
|
|
private static function emails($raw): string {
|
|
if (is_string($raw) && $raw !== '') {
|
|
$dec = @unserialize($raw);
|
|
if ($dec === false && $raw !== 'b:0;') $dec = json_decode($raw, true);
|
|
if (is_array($dec)) $raw = $dec;
|
|
}
|
|
if (!is_array($raw)) return (string) $raw;
|
|
$out = [];
|
|
foreach ($raw as $x) {
|
|
if (is_array($x)) $out[] = $x['email'] ?? (is_scalar(reset($x)) ? reset($x) : '');
|
|
else $out[] = (string) $x;
|
|
}
|
|
return implode(', ', array_filter($out));
|
|
}
|
|
|
|
public static function listConnections(array $args): array {
|
|
$s = get_option('fluentmail-settings');
|
|
if (!is_array($s) || empty($s['connections']) || !is_array($s['connections'])) {
|
|
return ['supported' => false, 'note' => 'No FluentSMTP connections configured.', 'connections' => []];
|
|
}
|
|
$maps = (isset($s['mappings']) && is_array($s['mappings'])) ? $s['mappings'] : [];
|
|
$byKey = [];
|
|
foreach ($maps as $email => $key) { $byKey[$key][] = $email; }
|
|
$out = [];
|
|
foreach ($s['connections'] as $key => $c) {
|
|
$ps = (is_array($c) && isset($c['provider_settings']) && is_array($c['provider_settings'])) ? $c['provider_settings'] : [];
|
|
$out[] = [
|
|
'id' => $key,
|
|
'title' => is_array($c) ? ($c['title'] ?? '') : '',
|
|
'provider' => $ps['provider'] ?? '',
|
|
'sender_name' => $ps['sender_name'] ?? '',
|
|
'sender_email' => $ps['sender_email'] ?? '',
|
|
'host' => $ps['host'] ?? '',
|
|
'port' => $ps['port'] ?? '',
|
|
'encryption' => $ps['encryption'] ?? '',
|
|
'maps_from' => $byKey[$key] ?? [],
|
|
];
|
|
}
|
|
return ['supported' => true, 'count' => count($out), 'connections' => $out];
|
|
}
|
|
|
|
public static function listLogs(array $args): array {
|
|
global $wpdb;
|
|
if (!self::hasLog()) return ['supported' => false, 'note' => 'fsmpt_email_logs table not found (logging may be off).', 'logs' => []];
|
|
$t = self::logTable();
|
|
$per = max(1, min(500, (int) ($args['per_page'] ?? 50)));
|
|
$where = '';
|
|
if (!empty($args['status'])) $where = $wpdb->prepare('WHERE status = %s', (string) $args['status']);
|
|
$rows = $wpdb->get_results("SELECT id, `to`, subject, status, source, retries, created_at FROM `{$t}` {$where} ORDER BY id DESC LIMIT {$per}", ARRAY_A);
|
|
$out = [];
|
|
foreach ((array) $rows as $r) {
|
|
$out[] = ['id' => (int) $r['id'], 'to' => self::emails($r['to']), 'subject' => $r['subject'], 'status' => $r['status'],
|
|
'source' => $r['source'], 'retries' => (int) $r['retries'], 'created_at' => $r['created_at']];
|
|
}
|
|
return ['supported' => true, 'count' => count($out), 'logs' => $out];
|
|
}
|
|
|
|
public static function stats(array $args): array {
|
|
global $wpdb;
|
|
if (!self::hasLog()) return ['supported' => false, 'note' => 'fsmpt_email_logs table not found (logging may be off).', 'by_status' => [], 'total' => 0];
|
|
$t = self::logTable();
|
|
$rows = $wpdb->get_results("SELECT status, COUNT(*) AS c FROM `{$t}` GROUP BY status", ARRAY_A);
|
|
$by = []; $total = 0;
|
|
foreach ((array) $rows as $r) { $by[$r['status']] = (int) $r['c']; $total += (int) $r['c']; }
|
|
return ['supported' => true, 'by_status' => $by, 'total' => $total];
|
|
}
|
|
|
|
public static function sendTest(array $args): array {
|
|
$to = isset($args['to']) ? sanitize_email((string) $args['to']) : '';
|
|
if (!$to || !is_email($to)) return ['sent' => false, 'error' => 'A valid "to" email address is required.'];
|
|
$subject = isset($args['subject']) && $args['subject'] !== '' ? (string) $args['subject'] : 'FluentSMTP test — Advanced MCP';
|
|
$body = isset($args['body']) && $args['body'] !== '' ? (string) $args['body'] : 'This is a test email sent via FluentSMTP by the Advanced MCP plugin.';
|
|
$sent = wp_mail($to, $subject, $body);
|
|
return ['sent' => (bool) $sent, 'to' => $to, 'subject' => $subject, 'note' => $sent ? 'wp_mail accepted the message (routed through FluentSMTP). Check fluentsmtp_list_logs for delivery status.' : 'wp_mail returned false.'];
|
|
}
|
|
}
|