death-notifier/src/main/php/com/fwdekker/deathnotifier/mailer/ProcessEmailQueueAction.php

108 lines
3.3 KiB
PHP

<?php
namespace com\fwdekker\deathnotifier\mailer;
use com\fwdekker\deathnotifier\Action;
use com\fwdekker\deathnotifier\Config;
use com\fwdekker\deathnotifier\UnexpectedException;
use com\fwdekker\deathnotifier\validation\EqualsCliPasswordRule;
use com\fwdekker\deathnotifier\validation\InvalidTypeException;
use com\fwdekker\deathnotifier\validation\InvalidValueException;
use com\fwdekker\deathnotifier\validation\RuleSet;
use PHPMailer\PHPMailer\Exception as PHPMailerException;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
/**
* Sends all emails in an {@see EmailQueue}.
*/
class ProcessEmailQueueAction extends Action
{
/**
* @var EmailQueue the `EmailQueue` of which all emails should be sent
*/
private readonly EmailQueue $email_queue;
/**
* Constructs a new `ProcessEmailQueueAction`.
*
* @param EmailQueue $email_queue the `EmailQueue` of which all emails should be sent
*/
public function __construct(EmailQueue $email_queue)
{
$this->email_queue = $email_queue;
}
/**
* Sends all emails in the {@see $email_queue}.
*
* @param array<int|string, mixed> $inputs `"password": string`: the CLI password
* @return null
* @throws InvalidTypeException if any of the inputs has the incorrect type
* @throws InvalidValueException if the CLI password is wrong
* @throws UnexpectedException if the mailer fails to send an email
*/
public function handle(array $inputs): mixed
{
(new RuleSet(["password" => [new EqualsCliPasswordRule()]]))->check($inputs);
$mailer = $this->create_mailer();
$emails = $this->email_queue->get_queue();
foreach ($emails as $email) {
$mailer->Subject = $email["subject"];
$mailer->Body = $email["body"];
try {
$mailer->addAddress($email["recipient"]);
$mailer->send();
} catch (PHPMailerException $exception) {
$mailer->getSMTPInstance()->reset();
throw new UnexpectedException("Failed to send email.", previous: $exception);
}
$mailer->clearAddresses();
}
$this->email_queue->unqueue($emails);
return null;
}
/**
* Creates a {@see PHPMailer} to send emails with.
*
* @throws UnexpectedException if the {@see PHPMailer} could not be created
*/
private function create_mailer(): PHPMailer
{
$config = Config::get("mail");
$mailer = new PHPMailer();
$mailer->IsSMTP();
$mailer->CharSet = "UTF-8";
$mailer->SMTPAuth = true;
$mailer->SMTPDebug = SMTP::DEBUG_OFF;
$mailer->SMTPKeepAlive = true;
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mailer->Host = $config["host"];
$mailer->Port = $config["port"];
$mailer->Username = $config["username"];
$mailer->Password = $config["password"];
try {
$mailer->setFrom($config["username"], $config["from_name"]);
} catch (PHPMailerException $exception) {
$mailer->smtpClose();
throw new UnexpectedException(
"Failed to set 'from' address while processing email queue.",
previous: $exception
);
}
return $mailer;
}
}