setDescription('Sends queued emails in a batch')
->addOption(
'limit',
[
'short' => 'l',
'help' => 'How many emails should be sent in this batch?',
'default' => 50,
]
)
->addOption(
'template',
[
'short' => 't',
'help' => 'Name of the template to be used to render email',
'default' => 'default',
]
)
->addOption(
'layout',
[
'short' => 'w',
'help' => 'Name of the layout to be used to wrap template',
'default' => 'default',
]
)
->addOption(
'stagger',
[
'short' => 's',
'help' => 'Seconds to maximum wait randomly before proceeding (useful for parallel executions)',
'default' => false,
]
)
->addOption(
'config',
[
'short' => 'c',
'help' => 'Name of email settings to use as defined in email.php',
'default' => 'default',
]
)
->addSubCommand(
'clearLocks',
[
'help' => 'Clears all locked emails in the queue, useful for recovering from crashes',
]
);
return $parser;
}
/**
* Sends queued emails.
*
* @return void
*/
public function main()
{
if ($this->params['stagger']) {
sleep(rand(0, $this->params['stagger']));
}
Configure::write('App.baseUrl', '/');
$emailQueue = TableRegistry::getTableLocator()->get('EmailQueue', ['className' => EmailQueueTable::class]);
$emails = $emailQueue->getBatch($this->params['limit']);
$count = count($emails);
foreach ($emails as $e) {
$configName = $e->config === 'default' ? $this->params['config'] : $e->config;
$template = $e->template === 'default' ? $this->params['template'] : $e->template;
$layout = $e->layout === 'default' ? $this->params['layout'] : $e->layout;
$headers = empty($e->headers) ? [] : (array)$e->headers;
$theme = empty($e->theme) ? '' : (string)$e->theme;
$viewVars = empty($e->template_vars) ? [] : $e->template_vars;
$errorMessage = null;
try {
$email = $this->_newEmail($configName);
if (!empty($e->from_email) && !empty($e->from_name)) {
$email->setFrom($e->from_email, $e->from_name);
}
$transport = $email->getTransport();
if ($transport && $transport->getConfig('additionalParameters')) {
$from = key($email->getFrom());
$transport->setConfig(['additionalParameters' => "-f $from"]);
}
if (!empty($e->attachments)) {
$email->setAttachments($e->attachments);
}
$sent = $email
->setTo($e->email)
->setSubject($e->subject)
->setEmailFormat($e->format)
->addHeaders($headers)
->setViewVars($viewVars)
->setMessageId(false)
->setReturnPath($email->getFrom());
$email->viewBuilder()
->setLayout($layout)
->setTheme($theme)
->setTemplate($template);
$email->send();
} catch (SocketException $exception) {
$this->err($exception->getMessage());
$errorMessage = $exception->getMessage();
$sent = false;
}
if ($sent) {
$emailQueue->success($e->id);
$this->out('Email ' . $e->id . ' was sent');
} else {
$emailQueue->fail($e->id, $errorMessage);
$this->out('Email ' . $e->id . ' was not sent');
}
}
if ($count > 0) {
$locks = collection($emails)->extract('id')->toList();
$emailQueue->releaseLocks($locks);
}
}
/**
* Clears all locked emails in the queue, useful for recovering from crashes.
*
* @return void
*/
public function clearLocks()
{
TableRegistry::getTableLocator()
->get('EmailQueue', ['className' => EmailQueueTable::class])
->clearLocks();
}
/**
* Returns a new instance of CakeEmail.
*
* @param array $config array of configs, or string to load configs from app.php
* @return Email
*/
protected function _newEmail($config)
{
return new Email($config);
}
}