diff --git a/.env b/.env
index e438f74731..aebb5d16cc 100644
--- a/.env
+++ b/.env
@@ -107,10 +107,9 @@ GOOGLE_CLOUD_PROJECT=''
MAILER_DSN='null://null'
###< symfony/mailer ###
-###> symfony/brevo-mailer ###
-# MAILER_DSN=brevo+api://KEY@default
-# MAILER_DSN=brevo+smtp://USERNAME:PASSWORD@default
-###< symfony/brevo-mailer ###
+###> symfony/amazon-mailer ###
+# MAILER_DSN=ses+smtp://ACCESS_KEY:SECRET_KEY@default?region=eu-central-1
+###< symfony/amazon-mailer ###
###> bugsnag/bugsnag-symfony ###
BUGSNAG_API_KEY=''
diff --git a/composer.json b/composer.json
index 7097e10098..1234263009 100644
--- a/composer.json
+++ b/composer.json
@@ -38,7 +38,7 @@
"sonata-project/exporter": "3.4.*",
"sonata-project/twig-extensions": "2.6.*",
"symfony/asset": "7.4.*",
- "symfony/brevo-mailer": "7.4.*",
+ "symfony/amazon-mailer": "7.4.*",
"symfony/cache": "7.4.*",
"symfony/config": "7.4.*",
"symfony/console": "7.4.*",
diff --git a/composer.lock b/composer.lock
index 926f4d4a18..b1cc722aed 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,141 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "cc659d8045d12437f5948afb3987c198",
+ "content-hash": "357fba43de72a6eef12bb2b472d85d5e",
"packages": [
+ {
+ "name": "async-aws/core",
+ "version": "1.29.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/async-aws/core.git",
+ "reference": "70899695fcc7b23a9247926ff8b581668583b993"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/async-aws/core/zipball/70899695fcc7b23a9247926ff8b581668583b993",
+ "reference": "70899695fcc7b23a9247926ff8b581668583b993",
+ "shasum": ""
+ },
+ "require": {
+ "ext-hash": "*",
+ "ext-simplexml": "*",
+ "php": "^8.2",
+ "psr/cache": "^1.0 || ^2.0 || ^3.0",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
+ "symfony/deprecation-contracts": "^2.1 || ^3.0",
+ "symfony/http-client": "^4.4.16 || ^5.1.7 || ^6.0 || ^7.0 || ^8.0",
+ "symfony/http-client-contracts": "^1.1.8 || ^2.0 || ^3.0",
+ "symfony/service-contracts": "^1.0 || ^2.0 || ^3.0"
+ },
+ "conflict": {
+ "async-aws/s3": "<1.1",
+ "symfony/http-client": "5.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5.42",
+ "symfony/error-handler": "^7.3.2 || ^8.0",
+ "symfony/phpunit-bridge": "^7.3.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.29-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "AsyncAws\\Core\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Core package to integrate with AWS. This is a lightweight AWS SDK provider by AsyncAws.",
+ "keywords": [
+ "amazon",
+ "async-aws",
+ "aws",
+ "sdk",
+ "sts"
+ ],
+ "support": {
+ "source": "https://github.com/async-aws/core/tree/1.29.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/jderusse",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nyholm",
+ "type": "github"
+ }
+ ],
+ "time": "2026-04-18T17:06:10+00:00"
+ },
+ {
+ "name": "async-aws/ses",
+ "version": "1.14.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/async-aws/ses.git",
+ "reference": "ab3bceb3380e971a5619fbd27d921a5352e644f4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/async-aws/ses/zipball/ab3bceb3380e971a5619fbd27d921a5352e644f4",
+ "reference": "ab3bceb3380e971a5619fbd27d921a5352e644f4",
+ "shasum": ""
+ },
+ "require": {
+ "async-aws/core": "^1.9",
+ "php": "^8.2"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^11.5.42",
+ "symfony/error-handler": "^7.3.2 || ^8.0",
+ "symfony/phpunit-bridge": "^7.3.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.14-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "AsyncAws\\Ses\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "SES client, part of the AWS SDK provided by AsyncAws.",
+ "keywords": [
+ "amazon",
+ "async-aws",
+ "aws",
+ "sdk",
+ "ses"
+ ],
+ "support": {
+ "source": "https://github.com/async-aws/ses/tree/1.14.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/jderusse",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/nyholm",
+ "type": "github"
+ }
+ ],
+ "time": "2026-04-18T17:06:10+00:00"
+ },
{
"name": "beberlei/doctrineextensions",
"version": "v1.5.0",
@@ -7023,34 +7156,31 @@
"time": "2025-11-23T16:41:45+00:00"
},
{
- "name": "symfony/asset",
+ "name": "symfony/amazon-mailer",
"version": "v7.4.6",
"source": {
"type": "git",
- "url": "https://github.com/symfony/asset.git",
- "reference": "d944ae87e4697af05aadeacfc5e603c3c18ef4fb"
+ "url": "https://github.com/symfony/amazon-mailer.git",
+ "reference": "6fedfa970a1b5b2c93fd32c598df7db7d03070b4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/asset/zipball/d944ae87e4697af05aadeacfc5e603c3c18ef4fb",
- "reference": "d944ae87e4697af05aadeacfc5e603c3c18ef4fb",
+ "url": "https://api.github.com/repos/symfony/amazon-mailer/zipball/6fedfa970a1b5b2c93fd32c598df7db7d03070b4",
+ "reference": "6fedfa970a1b5b2c93fd32c598df7db7d03070b4",
"shasum": ""
},
"require": {
- "php": ">=8.2"
- },
- "conflict": {
- "symfony/http-foundation": "<6.4"
+ "async-aws/ses": "^1.8",
+ "php": ">=8.2",
+ "symfony/mailer": "^7.2|^8.0"
},
"require-dev": {
- "symfony/http-client": "^6.4|^7.0|^8.0",
- "symfony/http-foundation": "^6.4|^7.0|^8.0",
- "symfony/http-kernel": "^6.4|^7.0|^8.0"
+ "symfony/http-client": "^6.4|^7.0|^8.0"
},
- "type": "library",
+ "type": "symfony-mailer-bridge",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Asset\\": ""
+ "Symfony\\Component\\Mailer\\Bridge\\Amazon\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -7070,10 +7200,10 @@
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files",
+ "description": "Symfony Amazon Mailer Bridge",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/asset/tree/v7.4.6"
+ "source": "https://github.com/symfony/amazon-mailer/tree/v7.4.6"
},
"funding": [
{
@@ -7093,37 +7223,37 @@
"type": "tidelift"
}
],
- "time": "2026-02-09T09:33:46+00:00"
+ "time": "2026-02-11T15:05:50+00:00"
},
{
- "name": "symfony/brevo-mailer",
- "version": "v7.4.0",
+ "name": "symfony/asset",
+ "version": "v7.4.6",
"source": {
"type": "git",
- "url": "https://github.com/symfony/brevo-mailer.git",
- "reference": "f1ef26ffe147e9185531030fc1503ed7b63fa0ef"
+ "url": "https://github.com/symfony/asset.git",
+ "reference": "d944ae87e4697af05aadeacfc5e603c3c18ef4fb"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/brevo-mailer/zipball/f1ef26ffe147e9185531030fc1503ed7b63fa0ef",
- "reference": "f1ef26ffe147e9185531030fc1503ed7b63fa0ef",
+ "url": "https://api.github.com/repos/symfony/asset/zipball/d944ae87e4697af05aadeacfc5e603c3c18ef4fb",
+ "reference": "d944ae87e4697af05aadeacfc5e603c3c18ef4fb",
"shasum": ""
},
"require": {
- "php": ">=8.2",
- "symfony/mailer": "^7.2|^8.0"
+ "php": ">=8.2"
},
"conflict": {
- "symfony/mime": "<6.2"
+ "symfony/http-foundation": "<6.4"
},
"require-dev": {
- "symfony/http-client": "^6.3|^7.0|^8.0",
- "symfony/webhook": "^6.3|^7.0|^8.0"
+ "symfony/http-client": "^6.4|^7.0|^8.0",
+ "symfony/http-foundation": "^6.4|^7.0|^8.0",
+ "symfony/http-kernel": "^6.4|^7.0|^8.0"
},
- "type": "symfony-mailer-bridge",
+ "type": "library",
"autoload": {
"psr-4": {
- "Symfony\\Component\\Mailer\\Bridge\\Brevo\\": ""
+ "Symfony\\Component\\Asset\\": ""
},
"exclude-from-classmap": [
"/Tests/"
@@ -7135,18 +7265,18 @@
],
"authors": [
{
- "name": "Pierre Tanguy",
- "homepage": "https://github.com/petanguy"
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
- "description": "Symfony Brevo Mailer Bridge",
+ "description": "Manages URL generation and versioning of web assets such as CSS stylesheets, JavaScript files and image files",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/brevo-mailer/tree/v7.4.0"
+ "source": "https://github.com/symfony/asset/tree/v7.4.6"
},
"funding": [
{
@@ -7166,7 +7296,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-04T08:00:56+00:00"
+ "time": "2026-02-09T09:33:46+00:00"
},
{
"name": "symfony/cache",
@@ -8729,16 +8859,16 @@
},
{
"name": "symfony/http-client",
- "version": "v7.4.7",
+ "version": "v7.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-client.git",
- "reference": "1010624285470eb60e88ed10035102c75b4ea6af"
+ "reference": "01933e626c3de76bea1e22641e205e78f6a34342"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/http-client/zipball/1010624285470eb60e88ed10035102c75b4ea6af",
- "reference": "1010624285470eb60e88ed10035102c75b4ea6af",
+ "url": "https://api.github.com/repos/symfony/http-client/zipball/01933e626c3de76bea1e22641e205e78f6a34342",
+ "reference": "01933e626c3de76bea1e22641e205e78f6a34342",
"shasum": ""
},
"require": {
@@ -8806,7 +8936,7 @@
"http"
],
"support": {
- "source": "https://github.com/symfony/http-client/tree/v7.4.7"
+ "source": "https://github.com/symfony/http-client/tree/v7.4.8"
},
"funding": [
{
@@ -8826,7 +8956,7 @@
"type": "tidelift"
}
],
- "time": "2026-03-05T11:16:58+00:00"
+ "time": "2026-03-30T12:55:43+00:00"
},
{
"name": "symfony/http-client-contracts",
@@ -9199,16 +9329,16 @@
},
{
"name": "symfony/mailer",
- "version": "v7.4.6",
+ "version": "v7.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/mailer.git",
- "reference": "b02726f39a20bc65e30364f5c750c4ddbf1f58e9"
+ "reference": "f6ea532250b476bfc1b56699b388a1bdbf168f62"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mailer/zipball/b02726f39a20bc65e30364f5c750c4ddbf1f58e9",
- "reference": "b02726f39a20bc65e30364f5c750c4ddbf1f58e9",
+ "url": "https://api.github.com/repos/symfony/mailer/zipball/f6ea532250b476bfc1b56699b388a1bdbf168f62",
+ "reference": "f6ea532250b476bfc1b56699b388a1bdbf168f62",
"shasum": ""
},
"require": {
@@ -9259,7 +9389,7 @@
"description": "Helps sending emails",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/mailer/tree/v7.4.6"
+ "source": "https://github.com/symfony/mailer/tree/v7.4.8"
},
"funding": [
{
@@ -9279,20 +9409,20 @@
"type": "tidelift"
}
],
- "time": "2026-02-25T16:50:00+00:00"
+ "time": "2026-03-24T13:12:05+00:00"
},
{
"name": "symfony/mime",
- "version": "v7.4.7",
+ "version": "v7.4.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
- "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1"
+ "reference": "6df02f99998081032da3407a8d6c4e1dcb5d4379"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/mime/zipball/da5ab4fde3f6c88ab06e96185b9922f48b677cd1",
- "reference": "da5ab4fde3f6c88ab06e96185b9922f48b677cd1",
+ "url": "https://api.github.com/repos/symfony/mime/zipball/6df02f99998081032da3407a8d6c4e1dcb5d4379",
+ "reference": "6df02f99998081032da3407a8d6c4e1dcb5d4379",
"shasum": ""
},
"require": {
@@ -9348,7 +9478,7 @@
"mime-type"
],
"support": {
- "source": "https://github.com/symfony/mime/tree/v7.4.7"
+ "source": "https://github.com/symfony/mime/tree/v7.4.8"
},
"funding": [
{
@@ -9368,7 +9498,7 @@
"type": "tidelift"
}
],
- "time": "2026-03-05T15:24:09+00:00"
+ "time": "2026-03-30T14:11:46+00:00"
},
{
"name": "symfony/monolog-bridge",
@@ -10018,7 +10148,7 @@
},
{
"name": "symfony/polyfill-intl-idn",
- "version": "v1.33.0",
+ "version": "v1.36.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
@@ -10081,7 +10211,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.36.0"
},
"funding": [
{
@@ -10105,7 +10235,7 @@
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.34.0",
+ "version": "v1.36.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
@@ -10166,7 +10296,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.34.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.36.0"
},
"funding": [
{
@@ -10190,7 +10320,7 @@
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.34.0",
+ "version": "v1.36.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
@@ -10251,7 +10381,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.34.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.36.0"
},
"funding": [
{
@@ -10275,7 +10405,7 @@
},
{
"name": "symfony/polyfill-php80",
- "version": "v1.34.0",
+ "version": "v1.36.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php80.git",
@@ -10335,7 +10465,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.34.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.36.0"
},
"funding": [
{
@@ -10439,16 +10569,16 @@
},
{
"name": "symfony/polyfill-php83",
- "version": "v1.33.0",
+ "version": "v1.36.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php83.git",
- "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5"
+ "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/17f6f9a6b1735c0f163024d959f700cfbc5155e5",
- "reference": "17f6f9a6b1735c0f163024d959f700cfbc5155e5",
+ "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149",
+ "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149",
"shasum": ""
},
"require": {
@@ -10495,7 +10625,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php83/tree/v1.33.0"
+ "source": "https://github.com/symfony/polyfill-php83/tree/v1.36.0"
},
"funding": [
{
@@ -10515,7 +10645,7 @@
"type": "tidelift"
}
],
- "time": "2025-07-08T02:45:35+00:00"
+ "time": "2026-04-10T17:25:58+00:00"
},
{
"name": "symfony/polyfill-php84",
diff --git a/config/services.php b/config/services.php
index 97860ff2b2..3686745b79 100644
--- a/config/services.php
+++ b/config/services.php
@@ -141,7 +141,7 @@
$parameters->set('catrobat.translations.project_cache_threshold', 15);
$parameters->set('catrobat.upload.temp.dir', '%catrobat.pubdir%resources/tmp/uploads/');
$parameters->set('catrobat.upload.temp.path', 'resources/tmp/uploads/');
- $parameters->set('dkim.private.key', '%kernel.project_dir%/.dkim/private.key');
+
$parameters->set('.container.dumper.inline_class_loader', true);
$parameters->set('reset_password.throttle_limit', 86400);
diff --git a/deploy.php b/deploy.php
index eaaa31e0cf..1162ae45ef 100644
--- a/deploy.php
+++ b/deploy.php
@@ -44,7 +44,6 @@
add('shared_files', [
'.env.prod.local', // keep only production .env
'google_cloud_key.json',
- '.dkim/private.key',
]);
// Writable directories
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 0a617747d8..3ef9748672 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -475,11 +475,7 @@
-
-
-
-
-
+
getContent()]]>
diff --git a/src/System/Mail/EmailBudgetManager.php b/src/System/Mail/EmailBudgetManager.php
index 231a88cdb5..2dd4e81c0a 100644
--- a/src/System/Mail/EmailBudgetManager.php
+++ b/src/System/Mail/EmailBudgetManager.php
@@ -11,14 +11,14 @@
class EmailBudgetManager
{
- public const int DAILY_LIMIT = 300;
+ public const int DAILY_LIMIT = 5000;
public const array TYPE_RESERVES = [
- 'verification' => 150,
- 'reset' => 30,
- 'consent' => 30,
- 'admin' => 50,
- 'management' => 40,
+ 'verification' => 2500,
+ 'reset' => 500,
+ 'consent' => 500,
+ 'admin' => 750,
+ 'management' => 750,
];
public function __construct(
diff --git a/src/System/Mail/MailerAdapter.php b/src/System/Mail/MailerAdapter.php
index 78a163cb92..32b1f13b88 100644
--- a/src/System/Mail/MailerAdapter.php
+++ b/src/System/Mail/MailerAdapter.php
@@ -6,12 +6,9 @@
use Psr\Log\LoggerInterface;
use Symfony\Bridge\Twig\Mime\TemplatedEmail;
-use Symfony\Component\DependencyInjection\Attribute\Autowire;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Address;
-use Symfony\Component\Mime\Crypto\DkimSigner;
-use Symfony\Component\Mime\Exception\InvalidArgumentException;
use Symfony\Component\Mime\Message;
use Twig\Environment;
@@ -21,8 +18,6 @@ public function __construct(
protected MailerInterface $mailer,
protected LoggerInterface $logger,
protected Environment $templateWrapper,
- #[Autowire('%dkim.private.key%')]
- protected string $dkim_private_key_path,
protected EmailBudgetManager $budgetManager,
) {
}
@@ -36,7 +31,6 @@ public function send(string $to, string $subject, string $template, array $conte
}
$email = $this->buildEmail($to, $subject, $template, $context);
- // $email = $this->signEmail($email); // Signing is currently disabled due to breveo
$this->sendEmail($email, $to);
$this->budgetManager->recordSend($emailType);
@@ -62,19 +56,6 @@ protected function buildEmail(string $to, string $subject, string $template, arr
;
}
- protected function signEmail(Message $email): Message
- {
- try {
- return new DkimSigner('file://'.$this->dkim_private_key_path, 'share.catrob.at', 'sf')->sign($email);
- } catch (InvalidArgumentException $invalidArgumentException) {
- if ('prod' === $_ENV['APP_ENV']) {
- $this->logger->error(sprintf('Private dkim key is missing (%s): ', $this->dkim_private_key_path).$invalidArgumentException->getMessage());
- }
-
- return $email;
- }
- }
-
protected function sendEmail(Message $email, string $to): void
{
try {
diff --git a/symfony.lock b/symfony.lock
index b5f4411257..32d745882e 100644
--- a/symfony.lock
+++ b/symfony.lock
@@ -597,18 +597,18 @@
"stella-maris/clock": {
"version": "0.1.4"
},
- "symfony/asset": {
- "version": "v4.4.5"
- },
- "symfony/brevo-mailer": {
- "version": "6.4",
+ "symfony/amazon-mailer": {
+ "version": "7.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
- "version": "6.4",
- "ref": "7c1038ceb733175f610a913a885a7c8b552b703a"
+ "version": "4.4",
+ "ref": "9648db3ecae5c8a6b1a5f74715d3907124348815"
}
},
+ "symfony/asset": {
+ "version": "v4.4.5"
+ },
"symfony/browser-kit": {
"version": "v5.0.5"
},
diff --git a/tests/PhpUnit/Admin/System/Maintenance/SystemHealthServiceTest.php b/tests/PhpUnit/Admin/System/Maintenance/SystemHealthServiceTest.php
index 57a0e318b6..479f104266 100644
--- a/tests/PhpUnit/Admin/System/Maintenance/SystemHealthServiceTest.php
+++ b/tests/PhpUnit/Admin/System/Maintenance/SystemHealthServiceTest.php
@@ -69,15 +69,15 @@ public function testGetEmailBudgetReturnsCorrectStructure(): void
{
$email = $this->service->getEmailBudget();
- self::assertSame(300, $email['daily_limit']);
+ self::assertSame(EmailBudgetManager::DAILY_LIMIT, $email['daily_limit']);
self::assertSame(25, $email['sent_today']);
- self::assertSame(275, $email['remaining']);
+ self::assertSame(EmailBudgetManager::DAILY_LIMIT - 25, $email['remaining']);
self::assertArrayHasKey('breakdown', $email);
self::assertArrayHasKey('verification', $email['breakdown']);
self::assertArrayHasKey('reset', $email['breakdown']);
self::assertSame(10, $email['breakdown']['verification']['sent']);
- self::assertSame(150, $email['breakdown']['verification']['reserve']);
- self::assertSame(140, $email['breakdown']['verification']['remaining']);
+ self::assertSame(EmailBudgetManager::TYPE_RESERVES['verification'], $email['breakdown']['verification']['reserve']);
+ self::assertSame(EmailBudgetManager::TYPE_RESERVES['verification'] - 10, $email['breakdown']['verification']['remaining']);
}
public function testGetProjectCountsReturnsAllCategories(): void
diff --git a/tests/PhpUnit/System/Mail/EmailBudgetManagerTest.php b/tests/PhpUnit/System/Mail/EmailBudgetManagerTest.php
index 4bcae1c325..9a88cc7479 100644
--- a/tests/PhpUnit/System/Mail/EmailBudgetManagerTest.php
+++ b/tests/PhpUnit/System/Mail/EmailBudgetManagerTest.php
@@ -53,12 +53,11 @@ public function testCanSendReturnsFalseWhenDailyLimitReached(): void
public function testCanSendRespectsTypeReserve(): void
{
- // Fill up verification reserve (150)
- $this->budget->setVerificationSent(150);
- $this->budget->setTotalSent(150);
+ // Fill up verification reserve (2500)
+ $this->budget->setVerificationSent(2500);
+ $this->budget->setTotalSent(2500);
- // Verification can still send from shared pool (300 - 300 reserves = 0 shared)
- // Total reserved = 150 + 30 + 30 + 50 + 40 = 300, shared pool = 0
+ // Total reserved = 2500 + 500 + 500 + 750 + 750 = 5000, shared pool = 0
self::assertFalse($this->manager->canSend('verification'));
// Other types are still within their reserves
@@ -67,10 +66,10 @@ public function testCanSendRespectsTypeReserve(): void
public function testCanSendAllowsOverflowIntoSharedPool(): void
{
- // With total reserves = 300 and daily limit = 300, shared pool = 0
+ // With total reserves = 5000 and daily limit = 5000, shared pool = 0
// So overflowing a reserve is NOT possible when reserves sum to daily limit
- $this->budget->setVerificationSent(150);
- $this->budget->setTotalSent(150);
+ $this->budget->setVerificationSent(2500);
+ $this->budget->setTotalSent(2500);
self::assertFalse($this->manager->canSend('verification'));
}
@@ -107,23 +106,23 @@ public function testGetRemainingBudget(): void
$remaining = $this->manager->getRemainingBudget();
- self::assertSame(148, $remaining['verification']);
- self::assertSame(29, $remaining['reset']);
- self::assertSame(30, $remaining['consent']);
- self::assertSame(50, $remaining['admin']);
- self::assertSame(40, $remaining['management']);
- self::assertSame(297, $remaining['total']);
+ self::assertSame(2498, $remaining['verification']);
+ self::assertSame(499, $remaining['reset']);
+ self::assertSame(500, $remaining['consent']);
+ self::assertSame(750, $remaining['admin']);
+ self::assertSame(750, $remaining['management']);
+ self::assertSame(4997, $remaining['total']);
}
public function testGetRemainingBudgetNeverNegative(): void
{
- $this->budget->setResetSent(100);
- $this->budget->setTotalSent(100);
+ $this->budget->setResetSent(1000);
+ $this->budget->setTotalSent(1000);
$remaining = $this->manager->getRemainingBudget();
self::assertSame(0, $remaining['reset']);
- self::assertSame(200, $remaining['total']);
+ self::assertSame(4000, $remaining['total']);
}
public function testCanSendThrowsOnInvalidType(): void
@@ -143,12 +142,12 @@ public function testRecordSendThrowsOnInvalidType(): void
public function testBudgetExhaustionByType(): void
{
// Fill reset reserve completely
- for ($i = 0; $i < 30; ++$i) {
+ for ($i = 0; $i < 500; ++$i) {
self::assertTrue($this->manager->canSend('reset'));
$this->manager->recordSend('reset');
}
- // Reset reserve exhausted, shared pool = 0 (reserves sum to 300 = daily limit)
+ // Reset reserve exhausted, shared pool = 0 (reserves sum to 5000 = daily limit)
self::assertFalse($this->manager->canSend('reset'));
// Other types still have budget within their reserves
@@ -158,7 +157,7 @@ public function testBudgetExhaustionByType(): void
public function testTotalLimitPreventsAllSending(): void
{
- $this->budget->setTotalSent(300);
+ $this->budget->setTotalSent(5000);
$this->budget->setVerificationSent(0);
self::assertFalse($this->manager->canSend('verification'));