mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 11:09:18 +02:00
feat: extract MediaController, wire into Dispatcher, delete media.php
This commit is contained in:
181
app/src/SmtpRelay.php
Normal file
181
app/src/SmtpRelay.php
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* SMTP Relay — credentials stored in the DB, sending via PHP's built-in mail
|
||||
* wrappers (SMTP transport layer is wired later).
|
||||
*
|
||||
* Responsibilities:
|
||||
* 1. CRUD on the singleton smtp_settings row.
|
||||
* 2. Build MIME messages.
|
||||
* 3. Send via `mail()` now; swap transport later (e.g. PHPMailer / Symfony Mailer).
|
||||
*/
|
||||
class SmtpRelay {
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// DB operations
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Fetch current SMTP settings from the DB.
|
||||
*
|
||||
* @return array{host:string,port:int,encryption:string,username:string,password:string,from_email:string,from_name:string}
|
||||
*/
|
||||
public static function getSettings(Database $db): array {
|
||||
$stmt = $db->getPDO()->query(
|
||||
"SELECT host, port, encryption, username, password, from_email, from_name
|
||||
FROM v_smtp_active LIMIT 1"
|
||||
);
|
||||
$row = $stmt->fetch();
|
||||
|
||||
return $row ?: [
|
||||
'host' => '',
|
||||
'port' => 587,
|
||||
'encryption' => 'tls',
|
||||
'username' => '',
|
||||
'password' => '',
|
||||
'from_email' => '',
|
||||
'from_name' => 'Post-ERG',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Upsert SMTP settings.
|
||||
*
|
||||
* @param array $data Associative array with keys: host, port, encryption,
|
||||
* username, password, from_email, from_name.
|
||||
* Keys not present are left unchanged.
|
||||
*/
|
||||
public static function updateSettings(Database $db, array $data): void {
|
||||
// Read existing so we can merge partial updates
|
||||
$current = self::getSettings($db);
|
||||
$merged = array_merge($current, $data);
|
||||
|
||||
// Sanitize
|
||||
$port = max(1, min(65535, (int)$merged['port']));
|
||||
$encryption = in_array($merged['encryption'], ['tls', 'ssl', 'none'], true)
|
||||
? $merged['encryption'] : 'tls';
|
||||
|
||||
$stmt = $db->getPDO()->prepare(
|
||||
"UPDATE smtp_settings
|
||||
SET host = :host,
|
||||
port = :port,
|
||||
encryption = :encryption,
|
||||
username = :username,
|
||||
password = :password,
|
||||
from_email = :from_email,
|
||||
from_name = :from_name,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = 1"
|
||||
);
|
||||
|
||||
$stmt->execute([
|
||||
':host' => trim($merged['host']),
|
||||
':port' => $port,
|
||||
':encryption' => $encryption,
|
||||
':username' => trim($merged['username']),
|
||||
':password' => $merged['password'], // keep as-is
|
||||
':from_email' => trim($merged['from_email']),
|
||||
':from_name' => trim($merged['from_name']),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the SMTP relay is fully configured.
|
||||
*/
|
||||
public static function isConfigured(Database $db): bool {
|
||||
$s = self::getSettings($db);
|
||||
return $s['host'] !== '' && $s['username'] !== '' && $s['from_email'] !== '';
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Send helpers (transport wired later — stub implementation now)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Send an e-mail using the stored SMTP credentials.
|
||||
*
|
||||
* Currently uses PHP's `mail()` as a passthrough so the rest of the
|
||||
* application can call `SmtpRelay::send(…)` everywhere.
|
||||
* The actual SMTP transport layer will be wired in a later iteration
|
||||
* (e.g. replace this body with PHPMailer / Symfony Mailer).
|
||||
*
|
||||
* @param string $to Recipient e-mail address
|
||||
* @param string $subject Subject line
|
||||
* @param string $body HTML body
|
||||
* @param string $plain Plain-text alternative (optional)
|
||||
* @return bool True on send request acceptance; false on failure
|
||||
*/
|
||||
public static function send(
|
||||
Database $db,
|
||||
string $to,
|
||||
string $subject,
|
||||
string $body,
|
||||
string $plain = ''
|
||||
): bool {
|
||||
$settings = self::getSettings($db);
|
||||
if ($settings['from_email'] === '') {
|
||||
error_log('[SmtpRelay] send() aborted — no from_email configured');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build MIME multipart headers
|
||||
$boundary = 'posterg_' . md5((string) random_int(0, PHP_INT_MAX) . microtime(true));
|
||||
$headers = "From: {$settings['from_name']} <{$settings['from_email']}>\r\n";
|
||||
$headers .= "Reply-To: {$settings['from_email']}\r\n";
|
||||
$headers .= "MIME-Version: 1.0\r\n";
|
||||
|
||||
if ($plain !== '') {
|
||||
$headers .= "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n";
|
||||
$message = "--{$boundary}\r\n";
|
||||
$message .= "Content-Type: text/plain; charset=UTF-8\r\n\r\n";
|
||||
$message .= self::htmlToPlain($body) . "\r\n\r\n";
|
||||
$message .= "--{$boundary}\r\n";
|
||||
$message .= "Content-Type: text/html; charset=UTF-8\r\n\r\n";
|
||||
$message .= $body . "\r\n\r\n";
|
||||
$message .= "--{$boundary}--";
|
||||
} else {
|
||||
$headers .= "Content-Type: text/html; charset=UTF-8\r\n";
|
||||
$message = $body;
|
||||
}
|
||||
|
||||
// TODO: replace with real SMTP transport (PHPMailer / Symfony Mailer)
|
||||
// The stored credentials ($settings) will be passed to the mailer then.
|
||||
$ok = mail($to, $subject, $message, $headers);
|
||||
|
||||
if (!$ok) {
|
||||
error_log("[SmtpRelay] mail() returned false for {$to}");
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queue (persist) an e-mail for deferred sending.
|
||||
*
|
||||
* Stub — will create a `mail_queue` table in a future migration.
|
||||
*/
|
||||
public static function queue(
|
||||
Database $db,
|
||||
string $to,
|
||||
string $subject,
|
||||
string $body,
|
||||
string $plain = ''
|
||||
): void {
|
||||
// TODO: INSERT INTO mail_queue …
|
||||
// Placeholder so callers exist now and wire up later.
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Internal
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Strip HTML tags to produce a rough plain-text fallback.
|
||||
*/
|
||||
private static function htmlToPlain(string $html): string {
|
||||
$text = strip_tags($html);
|
||||
// Collapse multiple whitespace lines
|
||||
$text = preg_replace('/\n{3,}/', "\n\n", $text);
|
||||
return trim($text);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user