-
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Budget;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
final class Mailgun
|
||||
{
|
||||
public function __construct(private Settings $settings)
|
||||
{
|
||||
}
|
||||
|
||||
public function configured(): bool
|
||||
{
|
||||
return $this->settings->get('mailgun.api_key', '') !== ''
|
||||
&& $this->settings->get('mailgun.domain', '') !== ''
|
||||
&& $this->settings->get('alerts.email', '') !== '';
|
||||
}
|
||||
|
||||
public function send(string $recipient, string $subject, string $html): array
|
||||
{
|
||||
if (!$this->configured()) {
|
||||
throw new RuntimeException('Mailgun settings are incomplete.');
|
||||
}
|
||||
$region = (string) $this->settings->get('mailgun.region', 'us');
|
||||
$host = $region === 'eu' ? 'api.eu.mailgun.net' : 'api.mailgun.net';
|
||||
$domain = (string) $this->settings->get('mailgun.domain', '');
|
||||
$endpoint = sprintf('https://%s/v3/%s/messages', $host, rawurlencode($domain));
|
||||
$body = http_build_query([
|
||||
'from' => (string) $this->settings->get('mailgun.from', ''),
|
||||
'to' => $recipient,
|
||||
'subject' => $subject,
|
||||
'html' => $html,
|
||||
]);
|
||||
$context = stream_context_create([
|
||||
'http' => [
|
||||
'method' => 'POST',
|
||||
'header' => [
|
||||
'Authorization: Basic ' . base64_encode('api:' . $this->settings->get('mailgun.api_key', '')),
|
||||
'Content-Type: application/x-www-form-urlencoded',
|
||||
'Content-Length: ' . strlen($body),
|
||||
],
|
||||
'content' => $body,
|
||||
'ignore_errors' => true,
|
||||
'timeout' => 15,
|
||||
],
|
||||
]);
|
||||
$response = @file_get_contents($endpoint, false, $context);
|
||||
$statusLine = $http_response_header[0] ?? 'HTTP/1.1 500 Unknown response';
|
||||
preg_match('/\s(\d{3})\s/', $statusLine, $matches);
|
||||
$status = (int) ($matches[1] ?? 500);
|
||||
if ($response === false || $status >= 400) {
|
||||
throw new RuntimeException('Mailgun rejected the reminder: ' . ($response ?: $statusLine));
|
||||
}
|
||||
return ['status' => $status, 'body' => $response];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user