diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml
new file mode 100644
index 0000000..61365be
--- /dev/null
+++ b/.github/workflows/check.yml
@@ -0,0 +1,38 @@
+name: Check
+on:
+ schedule:
+ - cron: "5 15 * * *"
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches:
+ - main
+
+jobs:
+ cs:
+ if: github.event_name != 'schedule'
+ runs-on: ubuntu-24.04
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Run CS
+ uses: shopware/github-actions/extension-verifier@main
+ with:
+ action: format
+
+ check:
+ runs-on: ubuntu-24.04
+ strategy:
+ fail-fast: false
+ matrix:
+ version-selection: [ 'lowest', 'highest']
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v6
+
+ - name: Run Check
+ uses: shopware/github-actions/extension-verifier@main
+ with:
+ action: check
+ check-against: ${{ matrix.version-selection }}
\ No newline at end of file
diff --git a/README.md b/README.md
index 41fcfd9..a20fff4 100644
--- a/README.md
+++ b/README.md
@@ -1,24 +1,24 @@
-# FroshMailValidation
+# FroshMailAddressTester
-This plugin for Shopware 6 validates email addresses during customer registration and checkout processes to ensure the mailbox is accessible and potentially valid.
+This plugin for Shopware 6 tests email address during customer registration and checkout processes to ensure the mailbox is accessible and potentially valid.
## Installation
### Via Composer
```bash
-composer require frosh/mail-validation
+composer require frosh/mail-address-tester
```
```bash
bin/console plugin:refresh
-bin/console plugin:install --activate FroshMailValidation
+bin/console plugin:install --activate FroshMailAddressTester
bin/console cache:clear
```
## Support
-- **GitHub Issues**: [https://github.com/FriendsOfShopware/FroshMailValidation/issues](https://github.com/FriendsOfShopware/FroshMailValidation/issues)
+- **GitHub Issues**: [https://github.com/FriendsOfShopware/FroshMailAddressTester/issues](https://github.com/FriendsOfShopware/FroshMailAddressTester/issues)
## License
diff --git a/composer.json b/composer.json
index 3041c7a..81bb8ca 100644
--- a/composer.json
+++ b/composer.json
@@ -1,5 +1,5 @@
{
- "name": "frosh/mail-validation",
+ "name": "frosh/mail-address-tester",
"description": "Validates email addresses by checking their actual existence on the target mail server. Reduces bounces, fake addresses, and sustainably improves deliverability.",
"type": "shopware-platform-plugin",
"version": "1.0.0",
@@ -10,32 +10,32 @@
],
"require": {
"shopware/core": "~6.7",
- "shyim/check-if-email-exists": "^1.0"
+ "shyim/check-if-email-exists": "^1.0.2"
},
"license": "MIT",
"autoload": {
"psr-4": {
- "Frosh\\MailValidation\\": "src/"
+ "Frosh\\MailAddressTester\\": "src/"
}
},
"extra": {
- "shopware-plugin-class": "Frosh\\MailValidation\\FroshMailValidation",
+ "shopware-plugin-class": "Frosh\\MailAddressTester\\FroshMailAddressTester",
"copyright": "FriendsOfShopware",
"label": {
- "de-DE": "E-Mail-Validierung durch Überprüfung der Existenz",
- "en-GB": "MailValidation by checking existence"
+ "de-DE": "E-Mail-Adressen-Tester",
+ "en-GB": "Mail address tester"
},
"description": {
"de-DE": "Validiert E-Mail-Adressen durch Prüfung der tatsächlichen Existenz beim Zielserver. Reduziert Bounces, Fake-Adressen und verbessert nachhaltig die Zustellbarkeit.",
"en-GB": "Validates email addresses by checking their actual existence on the target mail server. Reduces bounces, fake addresses, and sustainably improves deliverability."
},
"manufacturerLink": {
- "de-DE": "https://github.com/FriendsOfShopware/FroshMailValidation/",
- "en-GB": "https://github.com/FriendsOfShopware/FroshMailValidation/"
+ "de-DE": "https://github.com/FriendsOfShopware/FroshMailAddressTester/",
+ "en-GB": "https://github.com/FriendsOfShopware/FroshMailAddressTester/"
},
"supportLink": {
- "de-DE": "https://github.com/FriendsOfShopware/FroshMailValidation/",
- "en-GB": "https://github.com/FriendsOfShopware/FroshMailValidation/"
+ "de-DE": "https://github.com/FriendsOfShopware/FroshMailAddressTester/",
+ "en-GB": "https://github.com/FriendsOfShopware/FroshMailAddressTester/"
}
},
"scripts": {
diff --git a/src/Constraint/TestEmail.php b/src/Constraint/TestEmail.php
index 1b0e732..013cb3d 100644
--- a/src/Constraint/TestEmail.php
+++ b/src/Constraint/TestEmail.php
@@ -1,6 +1,6 @@
'frosh-mail-validation'])]
+#[AutoconfigureTag('monolog.logger', ['channel' => 'frosh_mail_tester'])]
#[AutoconfigureTag(name: 'validator.constraint_validator')]
class TestEmailValidator extends ConstraintValidator
{
public function __construct(
- private readonly Validator $emailValidator,
+ private readonly Tester $emailAddressTester,
) {
}
@@ -26,7 +26,7 @@ public function validate(mixed $value, Constraint $constraint): void
return;
}
- if ($this->emailValidator->validateEmail($value)) {
+ if ($this->emailAddressTester->validateEmail($value)) {
return;
}
diff --git a/src/FroshMailAddressTester.php b/src/FroshMailAddressTester.php
new file mode 100644
index 0000000..afdb87e
--- /dev/null
+++ b/src/FroshMailAddressTester.php
@@ -0,0 +1,39 @@
+getPath(), '/') . '/Resources/config';
+
+ $configLoader->load($confDir . '/{packages}/*.yaml', 'glob');
+ }
+
+ public function executeComposerCommands(): bool
+ {
+ return true;
+ }
+}
diff --git a/src/FroshMailValidation.php b/src/FroshMailValidation.php
deleted file mode 100644
index cd58e19..0000000
--- a/src/FroshMailValidation.php
+++ /dev/null
@@ -1,13 +0,0 @@
-Basic Configuration
Grundeinstellungen
+
+ level
+
+
+ simple
+ simple: just checks if the domain has an announced mail server (MX record)
+
+ SMTP: checks if an email would be deliverable by connecting to the mail server and simulating a mail delivery without really sending. Diese Prüfung dauert länger. Make sure the email address provided in the next field is valid, otherwise, some checks will be false-negative.
+ ]]>
+ Einfach: Es wird lediglich geprüft, ob für die Domain ein bekanntgegebener Mailserver (MX-Eintrag) existiert.
+
+ SMTP: Diese Option prüft die Zustellbarkeit einer E-Mail, indem sie eine Verbindung zum Mailserver herstellt und die Zustellung simuliert, ohne die E-Mail tatsächlich zu senden. Diese Prüfung dauert länger. Stellen Sie sicher, dass die im nächsten Feld angegebene E-Mail-Adresse gültig ist, da es sonst zu Fehlalarmen kommen kann.
+ ]]>
+
+
+
+
+
+
verifyEmail
-
+
verify@example.com
- This is important to be a valid mail domain. Otherwise, some checks will be false-positive.
- Es ist wichtig, dass es sich um eine gültige E-Mail-Domain handelt. Andernfalls liefern einige Prüfungen falsch-positive Ergebnisse.
+ This is important to be a valid mail domain. Otherwise, some checks will be false-negative.
+ Es ist wichtig, dass es sich um eine gültige E-Mail-Domain handelt. Andernfalls liefern einige Prüfungen falsch-negative Ergebnisse.
\ No newline at end of file
diff --git a/src/Resources/config/packages/monolog.yaml b/src/Resources/config/packages/monolog.yaml
new file mode 100644
index 0000000..71cec37
--- /dev/null
+++ b/src/Resources/config/packages/monolog.yaml
@@ -0,0 +1,10 @@
+monolog:
+ channels: ['frosh_mail_tester']
+
+ handlers:
+ FroshMailTesterHandler:
+ type: rotating_file
+ max_files: 14
+ path: '%kernel.logs_dir%/frosh_mail_tester_%kernel.environment%.log'
+ level: error
+ channels: ['frosh_mail_tester']
diff --git a/src/Resources/config/services.yaml b/src/Resources/config/services.yaml
index 52c2d08..0ea7360 100644
--- a/src/Resources/config/services.yaml
+++ b/src/Resources/config/services.yaml
@@ -2,6 +2,6 @@ services:
_defaults:
autowire: true
autoconfigure: true
- Frosh\MailValidation\:
+ Frosh\MailAddressTester\:
resource: '../../*'
- exclude: '../../{Resources,FroshMailValidation.php}'
+ exclude: '../../{Resources,FroshMailAddressTester.php}'
diff --git a/src/Service/Tester.php b/src/Service/Tester.php
new file mode 100644
index 0000000..80b513e
--- /dev/null
+++ b/src/Service/Tester.php
@@ -0,0 +1,111 @@
+getCacheItem($email);
+ $mailValidCacheResult = $mailValidCache->get();
+ if (\is_bool($mailValidCacheResult)) {
+ return $mailValidCacheResult;
+ }
+
+ $syntaxResult = new Syntax($email);
+ if ($syntaxResult->isValid() === false) {
+ return false;
+ }
+
+ $domain = $syntaxResult->domain;
+
+ $domainValidCache = $this->getCacheItem($domain);
+ // first check if the domain is already marked as invalid
+ if ($domainValidCache->get() === false) {
+ return false;
+ }
+
+ $mxRecords = (new DNS())->getMxRecords($domain);
+
+ if (empty($mxRecords)) {
+ $this->saveCache($domainValidCache, false);
+
+ $this->froshMailAddressTesterLogger->error(\sprintf('Domain %s has no mx records', $domain));
+
+ return false;
+ }
+
+ if ($this->systemConfigService->getString('FroshMailAddressTester.config.level') !== 'smtp') {
+ return true;
+ }
+
+ $verifyEmail = $this->systemConfigService->getString('FroshMailAddressTester.config.verifyEmail');
+ if ($verifyEmail !== '') {
+ $smtpCheck = new SMTP($verifyEmail);
+ } else {
+ $smtpCheck = new SMTP();
+ }
+
+ $smtpResult = $smtpCheck->check($domain, $mxRecords, $email);
+ $this->saveCache($domainValidCache, $smtpResult->canConnect);
+
+ if ($smtpResult->canConnect === false) {
+ $this->froshMailAddressTesterLogger->error($smtpResult->error);
+
+ return false;
+ }
+
+ $isValid = $smtpResult->isDeliverable === true && $smtpResult->isDisabled === false && $smtpResult->hasFullInbox === false;
+
+ $this->saveCache($mailValidCache, $isValid);
+
+ if ($isValid === false) {
+ $this->froshMailAddressTesterLogger->error(
+ \sprintf('Email address "%s" test failed', $email),
+ json_decode(json_encode($smtpResult, \JSON_THROW_ON_ERROR), true, 1, \JSON_THROW_ON_ERROR)
+ );
+ }
+
+ return $isValid;
+ }
+
+ private function getCacheItem(string $value): CacheItemInterface
+ {
+ $cacheKey = 'frosh_mail_tester_' . Hasher::hash($value);
+
+ return $this->cache->getItem($cacheKey);
+ }
+
+ private function saveCache(CacheItemInterface $item, bool $value): void
+ {
+ $cacheTime = 3600;
+
+ if ($value === true) {
+ $cacheTime = 86400; // one day for valid emails
+ }
+
+ $item->expiresAfter($cacheTime);
+ $item->set($value);
+ $this->cache->save($item);
+ }
+}
diff --git a/src/Service/Validator.php b/src/Service/Validator.php
deleted file mode 100644
index 7e855d3..0000000
--- a/src/Service/Validator.php
+++ /dev/null
@@ -1,70 +0,0 @@
-systemConfigService->getString('FroshMailValidation.config.verifyEmail');
-
- $syntax = new Syntax($email);
- if ($syntax->isValid() === false) {
- return false;
- }
-
- $domain = $syntax->domain;
-
- $domainCacheKey = 'frosh_mail_validation_domain_' . Hasher::hash($domain);
-
- \assert($this->cache instanceof AdapterInterface);
- $domainValidCache = $this->cache->getItem($domainCacheKey);
-
- // first check if the domain is already marked as invalid
- if ($domainValidCache->get() === false) {
- return false;
- }
-
- $checker = new EmailChecker(smtp: new SMTP($verifyEmail));
-
- $emailCacheKey = 'frosh_mail_validation_email_' . Hasher::hash($email);
-
- return $this->cache->get($emailCacheKey, function (ItemInterface $cacheItem) use ($email, $checker, $domainValidCache) {
- $result = $checker->check($email);
-
- $domainValid = $result->hasMxRecords && $result->isReachable;
- $domainValidCache->set($domainValid);
- $domainValidCache->expiresAfter($domainValid ? 86400 : 3600);
- $this->cache->save($domainValidCache);
-
- $cacheItem->expiresAfter(3600);
-
- if ($domainValid && $result->isDisabled === false && $result->hasFullInbox === false) {
- return true;
- }
-
- $this->froshMailValidationLogger->error('Email validation failed', $result->toArray());
-
- return false;
- });
- }
-}
diff --git a/src/Subscriber/BuildValidationEventListener.php b/src/Subscriber/BuildValidationEventListener.php
index 15c0a5e..989a41a 100644
--- a/src/Subscriber/BuildValidationEventListener.php
+++ b/src/Subscriber/BuildValidationEventListener.php
@@ -1,8 +1,8 @@