Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E-mail semináře v configu #1074

Merged
merged 9 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/deploy-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
CONFIG_MAIL_SECURE:
CONFIG_MAIL_SMTP: false
CONFIG_MAIL_USERNAME:
CONFIG_MAILING_SENDER_EMAIL: ${{ secrets.CONFIG_MAILING_SENDER_EMAIL }}
CONFIG_SKAUTIS_APPLICATION_ID: ${{ secrets.CONFIG_SKAUTIS_APPLICATION_ID }}
CONFIG_SKAUTIS_TEST_MODE: ${{ secrets.CONFIG_SKAUTIS_TEST_MODE }}
CONFIG_RECAPTCHA_SITE_KEY: ${{ secrets.CONFIG_RECAPTCHA_SITE_KEY }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-manual.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ jobs:
CONFIG_MAIL_SECURE: ${{ secrets.CONFIG_MAIL_SECURE }}
CONFIG_MAIL_SMTP: ${{ secrets.CONFIG_MAIL_SMTP }}
CONFIG_MAIL_USERNAME: ${{ secrets.CONFIG_MAIL_USERNAME }}
CONFIG_MAILING_SENDER_EMAIL: ${{ secrets.CONFIG_MAILING_SENDER_EMAIL }}
CONFIG_SKAUTIS_APPLICATION_ID: ${{ secrets.CONFIG_SKAUTIS_APPLICATION_ID }}
CONFIG_SKAUTIS_TEST_MODE: ${{ secrets.CONFIG_SKAUTIS_TEST_MODE }}
CONFIG_RECAPTCHA_SITE_KEY: ${{ secrets.CONFIG_RECAPTCHA_SITE_KEY }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ jobs:
CONFIG_MAIL_SECURE:
CONFIG_MAIL_SMTP: false
CONFIG_MAIL_USERNAME:
CONFIG_MAILING_SENDER_EMAIL: ${{ secrets.CONFIG_MAILING_SENDER_EMAIL }}
CONFIG_SKAUTIS_APPLICATION_ID: ${{ secrets.CONFIG_SKAUTIS_APPLICATION_ID }}
CONFIG_SKAUTIS_TEST_MODE: ${{ secrets.CONFIG_SKAUTIS_TEST_MODE }}
CONFIG_RECAPTCHA_SITE_KEY: ${{ secrets.CONFIG_RECAPTCHA_SITE_KEY }}
Expand Down
36 changes: 0 additions & 36 deletions app/AdminModule/ConfigurationModule/Forms/MailingFormFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,15 @@
namespace App\AdminModule\ConfigurationModule\Forms;

use App\AdminModule\Forms\BaseFormFactory;
use App\Model\Mailing\Commands\CreateTemplateMail;
use App\Model\Mailing\Template;
use App\Model\Mailing\TemplateVariable;
use App\Model\Settings\Commands\SetSettingArrayValue;
use App\Model\Settings\Commands\SetSettingBoolValue;
use App\Model\Settings\Commands\SetSettingStringValue;
use App\Model\Settings\Queries\SettingArrayValueQuery;
use App\Model\Settings\Queries\SettingBoolValueQuery;
use App\Model\Settings\Queries\SettingStringValueQuery;
use App\Model\Settings\Settings;
use App\Services\CommandBus;
use App\Services\QueryBus;
use App\Utils\Validators;
use Doctrine\Common\Collections\ArrayCollection;
use Nette;
use Nette\Application\LinkGenerator;
use Nette\Application\UI\Form;
use Nette\Forms\Controls\TextInput;
use Nextras\FormsRendering\Renderers\Bs4FormRenderer;
Expand All @@ -31,11 +24,7 @@
use function assert;
use function explode;
use function implode;
use function md5;
use function mt_rand;
use function substr;
use function trim;
use function uniqid;

/**
* Formulář pro nastavení mailingu.
Expand All @@ -48,7 +37,6 @@ public function __construct(
private readonly BaseFormFactory $baseFormFactory,
private readonly CommandBus $commandBus,
private readonly QueryBus $queryBus,
private readonly LinkGenerator $linkGenerator,
private readonly Validators $validators,
) {
}
Expand All @@ -67,10 +55,6 @@ public function create(int $id): Form
$renderer->wrappers['control']['container'] = 'div class="col-7"';
$renderer->wrappers['label']['container'] = 'div class="col-5 col-form-label"';

$form->addText('seminarEmail', 'admin.configuration.mailing_email')
->addRule(Form::FILLED, 'admin.configuration.mailing_email_empty')
->addRule(Form::EMAIL, 'admin.configuration.mailing_email_format');

$form->addText('contactFormRecipients', 'admin.configuration.mailing_contact_form_recipients')
->addRule(Form::FILLED, 'admin.configuration.mailing_contact_form_recipients_empty')
->addRule([$this, 'validateEmails'], 'admin.configuration.mailing_contact_form_recipients_format');
Expand All @@ -80,7 +64,6 @@ public function create(int $id): Form
$form->addSubmit('submit', 'admin.common.save');

$form->setDefaults([
'seminarEmail' => $this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_EMAIL)),
'contactFormRecipients' => implode(', ', $this->queryBus->handle(new SettingArrayValueQuery(Settings::CONTACT_FORM_RECIPIENTS))),
'contactFormGuestsAllowed' => $this->queryBus->handle(new SettingBoolValueQuery(Settings::CONTACT_FORM_GUESTS_ALLOWED)),
]);
Expand All @@ -98,25 +81,6 @@ public function create(int $id): Form
*/
public function processForm(Form $form, stdClass $values): void
{
if ($this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_EMAIL)) !== $values->seminarEmail) {
$this->commandBus->handle(new SetSettingStringValue(Settings::SEMINAR_EMAIL_UNVERIFIED, $values->seminarEmail));

$verificationCode = substr(md5(uniqid((string) mt_rand(), true)), 0, 8);
$this->commandBus->handle(new SetSettingStringValue(Settings::SEMINAR_EMAIL_VERIFICATION_CODE, $verificationCode));

$link = $this->linkGenerator->link('Api:Mail:verify', ['code' => $verificationCode]);

$this->commandBus->handle(new CreateTemplateMail(
null,
new ArrayCollection([$values->seminarEmail]),
Template::EMAIL_VERIFICATION,
[
TemplateVariable::SEMINAR_NAME => $this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_NAME)),
TemplateVariable::EMAIL_VERIFICATION_LINK => $link,
],
));
}

$contactFormRecipients = array_map(
static fn (string $o) => trim($o),
explode(',', $values->contactFormRecipients),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

use App\AdminModule\ConfigurationModule\Forms\MailingFormFactory;
use App\Model\Settings\Exceptions\SettingsItemNotFoundException;
use App\Model\Settings\Queries\SettingStringValueQuery;
use App\Model\Settings\Settings;
use Nette\Application\UI\Form;
use Nette\DI\Attributes\Inject;
use stdClass;
Expand All @@ -21,12 +19,6 @@ class MailingPresenter extends ConfigurationBasePresenter
#[Inject]
public MailingFormFactory $mailingFormFactory;

/** @throws Throwable */
public function renderDefault(): void
{
$this->template->waiting = $this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_EMAIL_VERIFICATION_CODE)) !== null;
}

/**
* @throws SettingsItemNotFoundException
* @throws Throwable
Expand Down
34 changes: 0 additions & 34 deletions app/ApiModule/Presenters/MailPresenter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,11 @@

namespace App\ApiModule\Presenters;

use App\Model\Acl\Permission;
use App\Model\Acl\SrsResource;
use App\Model\Mailing\Commands\SendMails;
use App\Model\Settings\Commands\SetSettingStringValue;
use App\Model\Settings\Queries\SettingStringValueQuery;
use App\Model\Settings\Settings;
use App\Services\CommandBus;
use App\Services\QueryBus;
use Nette\Application\AbortException;
use Nette\Application\Responses\TextResponse;
use Nette\DI\Attributes\Inject;
use Throwable;

/**
* Presenter obsluhující potvrzení změny e-mailu.
Expand All @@ -38,31 +31,4 @@ public function actionSend(): void
$response = new TextResponse(null);
$this->sendResponse($response);
}

/**
* Ověří e-mail semináře.
*
* @throws AbortException
* @throws Throwable
*/
public function actionVerify(string $code): void
{
if ($code === $this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_EMAIL_VERIFICATION_CODE))) {
$newEmail = $this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_EMAIL_UNVERIFIED));
$this->commandBus->handle(new SetSettingStringValue(Settings::SEMINAR_EMAIL, $newEmail));

$this->commandBus->handle(new SetSettingStringValue(Settings::SEMINAR_EMAIL_UNVERIFIED, null));
$this->commandBus->handle(new SetSettingStringValue(Settings::SEMINAR_EMAIL_VERIFICATION_CODE, null));

$this->flashMessage('admin.configuration.mailing_email_verification_successful', 'success');
} else {
$this->flashMessage('admin.configuration.mailing_email_verification_error', 'danger');
}

if ($this->user->isAllowed(SrsResource::CONFIGURATION, Permission::MANAGE)) {
$this->redirect(':Admin:Configuration:Mailing:default');
} else {
$this->redirect(':Web:Page:default');
}
}
}
2 changes: 1 addition & 1 deletion app/Mailing/SrsMail.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class SrsMail extends AbstractMail implements IComposableMail
/** @param SrsMailData|null $mailData */
public function compose(Message $message, IMessageData|null $mailData = null): void
{
$message->setFrom($mailData->getFrom()->getEmail(), $mailData->getFrom()->getName());
$message->setFrom($this->mailAddresses['senderEmail'], $mailData->getSenderName());
$message->addTo($mailData->getTo()->getEmail(), $mailData->getTo()->getName());
$message->setSubject($mailData->getSubject());

Expand Down
14 changes: 7 additions & 7 deletions app/Mailing/SrsMailData.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,22 @@
class SrsMailData implements IMessageData
{
/**
* @param Recipient $from Odesilatel mailu.
* @param Recipient $to Příjemce mailu.
* @param string $subject Předmět mailu.
* @param string $text Text mailu.
* @param string $senderName Jméno odesilatele mailu.
* @param Recipient $to Příjemce mailu.
* @param string $subject Předmět mailu.
* @param string $text Text mailu.
*/
public function __construct(
private readonly Recipient $from,
private readonly string $senderName,
private readonly Recipient $to,
private readonly string $subject,
private readonly string $text,
) {
}

public function getFrom(): Recipient
public function getSenderName(): string
{
return $this->from;
return $this->senderName;
}

public function getTo(): Recipient
Expand Down
22 changes: 14 additions & 8 deletions app/Model/Mailing/Commands/Handlers/SendMailsHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@

class SendMailsHandler implements MessageHandlerInterface
{
/** Limit počtu e-mailů odeslaných v rámci jednoho volání. */
private const BATCH_LIMIT = 100;

/** Počet e-mailů, po jejichž odeslání se čeká. */
private const BATCH_WAIT_LIMIT = 10;

/** Počet sekund čekání před odesláním dalších e-mailů. */
private const BATCH_WAIT_SECONDS = 2;

public function __construct(
private readonly QueryBus $queryBus,
private readonly MailQueueRepository $mailQueueRepository,
Expand All @@ -29,21 +38,18 @@ public function __construct(

public function __invoke(SendMails $command): void
{
$mailsToSend = $this->mailQueueRepository->findMailsToSend(50);
$mailsToSend = $this->mailQueueRepository->findMailsToSend(self::BATCH_LIMIT);

if ($mailsToSend->isEmpty()) {
return;
}

$from = new Recipient(
$this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_EMAIL)),
$this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_NAME)),
);
$senderName = $this->queryBus->handle(new SettingStringValueQuery(Settings::SEMINAR_NAME));

$i = 0;
foreach ($mailsToSend as $mailToSend) {
$to = new Recipient($mailToSend->getRecipientEmail(), $mailToSend->getRecipientName());
$messageData = new SrsMailData($from, $to, $mailToSend->getMail()->getSubject(), $mailToSend->getMail()->getText());
$messageData = new SrsMailData($senderName, $to, $mailToSend->getMail()->getSubject(), $mailToSend->getMail()->getText());
$mail = $this->mailFactory->createByType(SrsMail::class, $messageData);
$mail->send();

Expand All @@ -52,8 +58,8 @@ public function __invoke(SendMails $command): void
$this->mailQueueRepository->save($mailToSend);

$i++;
if ($i % 10 === 0) {
sleep(2);
if ($i % self::BATCH_WAIT_LIMIT === 0) {
sleep(self::BATCH_WAIT_SECONDS);
}
}
}
Expand Down
5 changes: 0 additions & 5 deletions app/Model/Mailing/TemplateVariable.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,6 @@ class TemplateVariable
*/
public const BANK_ACCOUNT = 'bank_account';

/**
* Odkaz pro potvrzení změny e-mailu.
*/
public const EMAIL_VERIFICATION_LINK = 'email_verification_link';

/**
* Jméno uživatele.
*/
Expand Down
15 changes: 0 additions & 15 deletions app/Model/Settings/Settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,6 @@ class Settings
*/
public const SEMINAR_NAME = 'seminar_name';

/**
* E-mail semináře.
*/
public const SEMINAR_EMAIL = 'seminar_email';

/**
* Neověřený změněný e-mail semináře.
*/
public const SEMINAR_EMAIL_UNVERIFIED = 'seminar_email_unverified';

/**
* Ověřovací kód pro změnu e-mailu.
*/
public const SEMINAR_EMAIL_VERIFICATION_CODE = 'seminar_email_verification_code';

/**
* Začátek semináře.
*/
Expand Down
5 changes: 5 additions & 0 deletions app/config/ci.local.neon
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ mail:
smtp: true
host: smtp-srs.loc

mailing:
mails: [
senderEmail: [email protected]
]

recaptcha:
siteKey: 6LdUAuMZAAAAALl3JDqMpjZpmhjwtOjGwRfuW7y7
secretKey: 6LdUAuMZAAAAAJcLosipAZ1vw9o3voIzjvQwaPMX
5 changes: 5 additions & 0 deletions app/config/production.local.neon
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ mail:
password: "__CONFIG_MAIL_PASSWORD__"
secure: __CONFIG_MAIL_SECURE__

mailing:
mails: [
senderEmail: "__CONFIG_MAILING_SENDER_EMAIL__"
]

recaptcha:
siteKey: "__CONFIG_RECAPTCHA_SITE_KEY__"
secretKey: "__CONFIG_RECAPTCHA_SECRET_KEY__"
5 changes: 5 additions & 0 deletions app/config/sample.local.neon
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ mail:
password: ""
secure:

mailing:
mails: [
senderEmail: [email protected]
]

recaptcha:
siteKey: ""
secretKey: ""
6 changes: 0 additions & 6 deletions app/lang/admin.cs_CZ.neon
Original file line number Diff line number Diff line change
Expand Up @@ -818,16 +818,10 @@ configuration:
place_points_saved: "Mapový bod byl úspěšně uložen."

mailing_heading: "Mailing"
mailing_email: "E-mail pro mailing"
mailing_email_empty: "Zadejte e-mail."
mailing_email_format: "Zadejte e-mail ve správném formátu."
mailing_contact_form_recipients: "E-maily pro zaslání zpráv z kontaktního formuláře"
mailing_contact_form_recipients_empty: "Zadete alespoň jeden e-mail."
mailing_contact_form_recipients_format: "Zadejte e-mailové adresy oddělené čárkou."
mailing_contact_form_guests_allowed: "povolit kontaktní formulář pro nepřihlášené uživatele"
mailing_email_verification_needed: "Změna e-mailu čeká na ověření. Ověřit ji můžete pomocí odkazu zaslaného na nový e-mail."
mailing_email_verification_successful: "E-mail byl úspěšně ověřen."
mailing_email_verification_error: "E-mail se nepodařilo ověřit."

skautis_event_heading: "Propojení s akcí ve skautIS"
skautis_event_type: "Typ skautIS akce"
Expand Down
1 change: 1 addition & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<token key="CONFIG_MAIL_USERNAME" value="${env.CONFIG_MAIL_USERNAME}"/>
<token key="CONFIG_MAIL_PASSWORD" value="${env.CONFIG_MAIL_PASSWORD}"/>
<token key="CONFIG_MAIL_SECURE" value="${env.CONFIG_MAIL_SECURE}"/>
<token key="CONFIG_MAILING_SENDER_EMAIL" value="${env.CONFIG_MAILING_SENDER_EMAIL}"/>
<token key="CONFIG_RECAPTCHA_SITE_KEY" value="${env.CONFIG_RECAPTCHA_SITE_KEY}"/>
<token key="CONFIG_RECAPTCHA_SECRET_KEY" value="${env.CONFIG_RECAPTCHA_SECRET_KEY}"/>
</replacetokens>
Expand Down
27 changes: 27 additions & 0 deletions migrations/Version20231025195652.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace Migrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20231025195652 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}

public function up(Schema $schema): void
{
$this->addSql('DELETE FROM `settings` WHERE `item`=\'seminar_email\'');
$this->addSql('DELETE FROM `settings` WHERE `item`=\'seminar_email_unverified\'');
$this->addSql('DELETE FROM `settings` WHERE `item`=\'seminar_email_verification_code\'');
}

public function down(Schema $schema): void
{
}
}