Add e-mail webhook.
This commit is contained in:
parent
92fbac4006
commit
ace826dae5
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -5,10 +5,13 @@ release channel, you can take advantage of these new features and fixes.
|
|||
|
||||
## New Features/Changes
|
||||
|
||||
- **Self-Service Password Reset**: If SMTP is configured properly in the system settings page, users can now request a
|
||||
password reset directly from the login page instead of requiring administrator intervention. The password reset
|
||||
functionality creates a single-time-use login token that can be used to reset the user's password and log them in
|
||||
once.
|
||||
- **E-mail Delivery**: System administrators can now configure SMTP for e-mail delivery via the system settings page. If
|
||||
SMTP is enabled for your installation, the following functionality is added:
|
||||
|
||||
- **Self-Service Password Reset**: Users can request a password recovery token to reset their own passwords.
|
||||
|
||||
- **E-mail Web Hook**: You can dispatch an e-mail to specified recipients as a web hook when specific triggers
|
||||
occur.
|
||||
|
||||
- Web Hooks can now be triggered to dispatch when a station goes offline or comes online.
|
||||
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
/**
|
||||
* @var array $triggers
|
||||
* @var App\Environment $environment
|
||||
* @var App\Http\Router $router
|
||||
*/
|
||||
|
||||
return [
|
||||
'method' => 'post',
|
||||
|
||||
'groups' => [
|
||||
|
||||
'message_grp' => [
|
||||
'use_grid' => true,
|
||||
'elements' => [
|
||||
|
||||
'name' => [
|
||||
'text',
|
||||
[
|
||||
'label' => __('Web Hook Name'),
|
||||
'description' => __(
|
||||
'Choose a name for this webhook that will help you distinguish it from others. This will only be shown on the administration page.'
|
||||
),
|
||||
'required' => true,
|
||||
'form_group_class' => 'col-md-6',
|
||||
],
|
||||
],
|
||||
|
||||
'triggers' => [
|
||||
'multiCheckbox',
|
||||
[
|
||||
'label' => __('Web Hook Triggers'),
|
||||
'options' => $triggers,
|
||||
'required' => true,
|
||||
'form_group_class' => 'col-sm-12',
|
||||
],
|
||||
],
|
||||
|
||||
'to' => [
|
||||
'text',
|
||||
[
|
||||
'label' => __('Message Recipient(s)'),
|
||||
'belongsTo' => 'config',
|
||||
'required' => true,
|
||||
'description' => __('E-mail addresses can be separated by commas.'),
|
||||
'form_group_class' => 'col-sm-6',
|
||||
],
|
||||
],
|
||||
|
||||
'subject' => [
|
||||
'text',
|
||||
[
|
||||
'label' => __('Message Subject'),
|
||||
'belongsTo' => 'config',
|
||||
'required' => true,
|
||||
'description' => __(
|
||||
'Variables are in the form of <code>{{ var.name }}</code>. All values in the <a href="%s" target="_blank">Now Playing API response</a> are avaliable for use. Any empty fields are ignored.',
|
||||
$router->named('api:nowplaying:index')
|
||||
),
|
||||
'form_group_class' => 'col-sm-6',
|
||||
],
|
||||
],
|
||||
|
||||
'message' => [
|
||||
'textarea',
|
||||
[
|
||||
'label' => __('Message Body'),
|
||||
'belongsTo' => 'config',
|
||||
'required' => true,
|
||||
'description' => __(
|
||||
'Variables are in the form of <code>{{ var.name }}</code>. All values in the <a href="%s" target="_blank">Now Playing API response</a> are avaliable for use. Any empty fields are ignored.',
|
||||
$router->named('api:nowplaying:index')
|
||||
),
|
||||
'form_group_class' => 'col-sm-12',
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
],
|
||||
|
||||
'submit_grp' => [
|
||||
'elements' => [
|
||||
|
||||
'submit' => [
|
||||
'submit',
|
||||
[
|
||||
'type' => 'submit',
|
||||
'label' => __('Save Changes'),
|
||||
'class' => 'ui-button btn-lg btn-primary',
|
||||
],
|
||||
],
|
||||
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
|
@ -13,6 +13,11 @@ return [
|
|||
'name' => __('Generic Web Hook'),
|
||||
'description' => __('Automatically send a message to any URL when your station data changes.'),
|
||||
],
|
||||
Connector\Email::NAME => [
|
||||
'class' => Connector\Email::class,
|
||||
'name' => __('Send E-mail'),
|
||||
'description' => __('Send an e-mail to specified address(es).'),
|
||||
],
|
||||
Connector\TuneIn::NAME => [
|
||||
'class' => Connector\TuneIn::class,
|
||||
'name' => __('TuneIn AIR'),
|
||||
|
|
|
@ -7,28 +7,24 @@ use App\Exception\RateLimitExceededException;
|
|||
use App\Http\Response;
|
||||
use App\Http\ServerRequest;
|
||||
use App\RateLimit;
|
||||
use App\Service\Mail;
|
||||
use App\Session\Flash;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
|
||||
class ForgotPasswordAction
|
||||
{
|
||||
public function __invoke(
|
||||
ServerRequest $request,
|
||||
Response $response,
|
||||
Entity\Repository\SettingsRepository $settingsRepo,
|
||||
Entity\Repository\UserRepository $userRepo,
|
||||
Entity\Repository\UserLoginTokenRepository $loginTokenRepo,
|
||||
RateLimit $rateLimit,
|
||||
MailerInterface $mailer
|
||||
Mail $mail
|
||||
): ResponseInterface {
|
||||
$flash = $request->getFlash();
|
||||
$view = $request->getView();
|
||||
|
||||
$settings = $settingsRepo->readSettings();
|
||||
if (!$settings->getMailEnabled()) {
|
||||
if (!$mail->isEnabled()) {
|
||||
return $view->renderToResponse($response, 'frontend/account/forgot_disabled');
|
||||
}
|
||||
|
||||
|
@ -55,8 +51,7 @@ class ForgotPasswordAction
|
|||
$user = $userRepo->findByEmail($email);
|
||||
|
||||
if ($user instanceof Entity\User) {
|
||||
$email = new Email();
|
||||
$email->from(new Address($settings->getMailSenderEmail(), $settings->getMailSenderName()));
|
||||
$email = $mail->createMessage();
|
||||
$email->to($user->getEmail());
|
||||
|
||||
$email->subject(__('Account Recovery Link'));
|
||||
|
@ -71,7 +66,7 @@ class ForgotPasswordAction
|
|||
)
|
||||
);
|
||||
|
||||
$mailer->send($email);
|
||||
$mail->send($email);
|
||||
}
|
||||
|
||||
$flash->addMessage(
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity;
|
||||
use Symfony\Component\Mailer\Envelope;
|
||||
use Symfony\Component\Mailer\MailerInterface;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Mime\RawMessage;
|
||||
|
||||
class Mail implements MailerInterface
|
||||
{
|
||||
protected Entity\Repository\SettingsRepository $settingsRepo;
|
||||
|
||||
protected MailerInterface $mailer;
|
||||
|
||||
public function __construct(Entity\Repository\SettingsRepository $settingsRepo, MailerInterface $mailer)
|
||||
{
|
||||
$this->settingsRepo = $settingsRepo;
|
||||
$this->mailer = $mailer;
|
||||
}
|
||||
|
||||
public function isEnabled(): bool
|
||||
{
|
||||
$settings = $this->settingsRepo->readSettings();
|
||||
return $settings->getMailEnabled();
|
||||
}
|
||||
|
||||
public function createMessage(): Email
|
||||
{
|
||||
$settings = $this->settingsRepo->readSettings();
|
||||
|
||||
$email = new Email();
|
||||
$email->from(new Address($settings->getMailSenderEmail(), $settings->getMailSenderName()));
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
public function send(RawMessage $message, Envelope $envelope = null): void
|
||||
{
|
||||
$this->mailer->send($message, $envelope);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace App\Webhook\Connector;
|
||||
|
||||
use App\Entity;
|
||||
use App\Service\Mail;
|
||||
use GuzzleHttp\Client;
|
||||
use Monolog\Logger;
|
||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||
|
||||
class Email extends AbstractConnector
|
||||
{
|
||||
public const NAME = 'email';
|
||||
|
||||
protected Mail $mail;
|
||||
|
||||
public function __construct(
|
||||
Logger $logger,
|
||||
Client $httpClient,
|
||||
Mail $mail
|
||||
) {
|
||||
parent::__construct($logger, $httpClient);
|
||||
|
||||
$this->mail = $mail;
|
||||
}
|
||||
|
||||
public function dispatch(
|
||||
Entity\Station $station,
|
||||
Entity\StationWebhook $webhook,
|
||||
Entity\Api\NowPlaying $np,
|
||||
array $triggers,
|
||||
bool $isStandalone
|
||||
): bool {
|
||||
if (!$this->mail->isEnabled()) {
|
||||
$this->logger->error('E-mail delivery is not currently enabled. Skipping webhook delivery...');
|
||||
return false;
|
||||
}
|
||||
|
||||
$config = $webhook->getConfig();
|
||||
$emailTo = $config['to'];
|
||||
$emailSubject = $config['subject'];
|
||||
$emailBody = $config['message'];
|
||||
|
||||
if (empty($emailTo) || empty($emailSubject) || empty($emailBody)) {
|
||||
$this->logger->error('Webhook ' . self::NAME . ' is missing necessary configuration. Skipping...');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$email = $this->mail->createMessage();
|
||||
|
||||
$emailToParts = explode(',', $emailTo);
|
||||
foreach ($emailToParts as $emailToPart) {
|
||||
$email->addTo(trim($emailToPart));
|
||||
}
|
||||
|
||||
$vars = [
|
||||
'subject' => $emailSubject,
|
||||
'body' => $emailBody,
|
||||
];
|
||||
$vars = $this->replaceVariables($vars, $np);
|
||||
|
||||
$email->subject($vars['subject']);
|
||||
$email->text($vars['body']);
|
||||
|
||||
$this->mail->send($email);
|
||||
} catch (TransportExceptionInterface $e) {
|
||||
$this->logger->error(sprintf('Error from e-mail (%d): %s', $e->getCode(), $e->getMessage()));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue