blue-twilight/app/Console/Commands/SendEmailsCommand.php

142 lines
3.7 KiB
PHP

<?php
namespace App\Console\Commands;
use App\EmailLog;
use App\Facade\UserConfig;
use App\Http\Middleware\GlobalConfiguration;
use Illuminate\Console\Command;
use Illuminate\Mail\Mailer;
use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Mail;
class SendEmailsCommand extends Command
{
const MAX_EMAILS_PER_BATCH = 100;
const MAX_NUMBER_ATTEMPTS = 5;
const SECONDS_TO_SLEEP = 30;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'bt-queue:send-emails {--poll}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Sends e-mails queued in the database.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
GlobalConfiguration::updateMailConfig();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if (!UserConfig::get('queue_emails'))
{
$this->output->error('E-mail queueing is not enabled. E-mails are being sent immediately.');
}
$this->output->writeln('E-mail queue runner started');
while (true)
{
$emailsToSend = EmailLog::where([
['sent_at', null],
['number_attempts', '<', self::MAX_NUMBER_ATTEMPTS]
])->limit(self::MAX_EMAILS_PER_BATCH)->get();
$this->output->writeln(sprintf(
'%d e-mail%s to send',
$emailsToSend->count(),
$emailsToSend->count() == 1 ? '' : 's'
));
/** @var EmailLog $emailToSend */
foreach ($emailsToSend as $emailToSend)
{
$this->sendEmail($emailToSend);
}
if (!$this->option('poll'))
{
exit();
}
sleep(self::SECONDS_TO_SLEEP);
}
}
private function sendEmail(EmailLog $emailLog)
{
$this->output->writeln(sprintf('Sending message with subject \'%s\'', $emailLog->subject));
try
{
app('mailer')->send(
[],
[],
function (Message $message) use ($emailLog)
{
$message->setFrom($emailLog->sender_address, $emailLog->sender_name);
$message->setSubject($emailLog->subject);
$this->addAddresses($emailLog->to_addresses, $message, 'To');
$this->addAddresses($emailLog->cc_addresses, $message, 'Cc');
$this->addAddresses($emailLog->bcc_addresses, $message, 'Bcc');
$message->addPart($emailLog->body_plain, 'text/plain');
$message->setBody($emailLog->body_html, 'text/html');
}
);
$emailLog->sent_at = new \DateTime();
$this->output->writeln('Send completed');
}
catch (\Exception $ex)
{
$this->output->error(sprintf('Send failed: %s', $ex->getMessage()));
}
finally
{
$emailLog->number_attempts++;
$emailLog->save();
}
}
private function addAddresses($dbFieldData, Message $message, $property)
{
$decoded = json_decode($dbFieldData);
if (is_array($decoded))
{
foreach ($decoded as $addressInfo)
{
$this->output->writeln(sprintf('Adding %s address: \'"%s" <%s>\'', $property, $addressInfo->name, $addressInfo->address));
$message->{"set{$property}"}($addressInfo->address, $addressInfo->name);
}
}
}
}