Compare commits

..

28 Commits

Author SHA1 Message Date
a314136829 Merge branch 'rel_2.x' into rel_3.x
# Conflicts:
#	CHANGELOG.md
#	metadata.php
2024-07-10 08:30:11 +02:00
3362941449 complete documentation 2024-07-10 08:26:33 +02:00
132d618a06 set EHLO domain in SMTP check 2024-07-10 08:19:50 +02:00
37839b269c show communication protocol from shop
# Conflicts:
#	views/twig/admin/mailConfigCheck.html.twig
2024-07-10 08:19:50 +02:00
c3649a9e24
set EHLO domain in SMTP check 2024-07-09 23:36:11 +02:00
a154a9a243
show communication protocol from shop 2024-07-09 23:33:17 +02:00
116001f0fe Merge branch 'rel_2.x' into rel_3.x 2024-06-05 08:47:59 +02:00
2af6727797 fix composer.json syntax 2024-06-05 08:46:54 +02:00
1d7a47c048 align version information 2024-06-05 08:43:27 +02:00
99744ada70 Merge branch 'rel_2.x' into dev_3.x_OX7
# Conflicts:
#	Application/Controller/Admin/SpfChecker.php
#	Application/Model/DmarcResult.php
2024-06-05 08:38:43 +02:00
5352571623 align version information 2024-06-05 08:33:37 +02:00
d3e94b218a remove unnecessary migration 2024-06-05 08:33:14 +02:00
a119ae8687 add missing DMARC package 2024-06-04 16:21:56 +02:00
860de39a79 add DMARC check
# Conflicts:
#	Application/Controller/Admin/SpfChecker.php
#	Application/views/admin/tpl/mailTester.tpl
#	Application/views/admin/tpl/mailconfigcheck.tpl
#	Application/views/admin/tpl/mailinfopage.tpl
#	Application/views/admin/tpl/smtpCheck.tpl
#	Application/views/admin/tpl/spfCheck.tpl
2024-06-04 15:47:32 +02:00
d89b1a1848 add Twig templates 2024-06-04 15:38:19 +02:00
32d3b178f8 improve code 2024-06-04 14:37:41 +02:00
8900201ee8 add DMARC check 2024-06-04 14:20:20 +02:00
4e84b6940a align copyright notes 2024-06-03 07:57:58 +02:00
ab3c6e20a6 align Smarty template registration 2024-06-03 07:56:54 +02:00
46aeb7e6bd move assets 2024-05-31 16:30:51 +02:00
6bf8b0fb4c make installable in OXID 7 2024-05-31 16:02:53 +02:00
c414117143 fix md 2024-04-11 18:10:29 +02:00
541352a5c3 tag 2.0.0.1 2024-04-11 18:07:58 +02:00
e59efe83e7 add ownermail as "setfrom". Without this the email method ends always in status "phpmailer"and not "smtp" 2024-04-11 15:33:57 +02:00
f882c1383e
fix typo 2023-12-14 11:35:52 +01:00
73c5211c6d
cleanup dev dependencies 2023-12-14 11:06:27 +01:00
4f6605afd3
update module informations 2023-12-14 10:19:06 +01:00
86771ea2b1
make installable from OXID 6.4 2023-12-14 09:08:45 +01:00
43 changed files with 965 additions and 218 deletions

View File

@ -1,17 +1,13 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
*
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
@ -19,11 +15,12 @@ declare(strict_types=1);
namespace D3\MailConfigChecker\Application\Controller\Admin;
use D3\MailConfigChecker\Application\Model\Constants;
use OxidEsales\Eshop\Application\Controller\Admin\AdminController;
class MailCheckBase extends AdminController
{
protected $_sThisTemplate = 'mailCheckBase.tpl';
protected $_sThisTemplate = '@'.Constants::OXID_MODULE_ID.'/admin/mailCheckBase';
/**
* @return string

View File

@ -1,17 +1,13 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
*
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
@ -19,13 +15,14 @@ declare(strict_types=1);
namespace D3\MailConfigChecker\Application\Controller\Admin;
use D3\MailConfigChecker\Application\Model\Constants;
use OxidEsales\Eshop\Application\Controller\Admin\AdminListController;
class MailCheckMenu extends AdminListController
{
protected $_sThisTemplate = 'mailCheckMenu.tpl';
protected $_sThisTemplate = '@'.Constants::OXID_MODULE_ID.'/admin/mailCheckMenu';
public function render()
public function render(): string
{
$this->setEditObjectId('foo');
return parent::render();

View File

@ -1,24 +1,22 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
namespace D3\MailConfigChecker\Application\Controller\Admin;
use Assert\Assert;
use Assert\InvalidArgumentException;
use D3\MailConfigChecker\Application\Model\Constants;
use D3\MailConfigChecker\Application\Model\Exception\d3TranslatableLazyAssertionException;
use ErrorException;
use Exception;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
use OxidEsales\Eshop\Application\Model\Shop;
@ -27,18 +25,19 @@ use OxidEsales\Eshop\Core\Registry;
class MailConfigCheck extends AdminDetailsController
{
protected $_sThisTemplate = 'mailConfigCheck.tpl';
protected $testMailAddress = 'test@example.com';
protected $_sThisTemplate = '@'.Constants::OXID_MODULE_ID.'/admin/mailConfigCheck';
protected string $testMailAddress = 'test@example.com';
public function render()
public function render(): string
{
$this->checkDataAreSet();
$this->addTplParam('shop', Registry::getConfig()->getActiveShop());
$this->addTplParam('recipient', $this->testMailAddress);
return parent::render();
}
protected function checkDataAreSet()
protected function checkDataAreSet(): void
{
try {
/** @var Shop $shop */
@ -66,31 +65,42 @@ class MailConfigCheck extends AdminDetailsController
}
}
public function checkConfiguration()
public function checkConfiguration(): void
{
$this->getCurrentMailer();
}
function exceptions_error_handler($severity, $message, $filename, $lineno) {
throw new ErrorException($message, 0, $severity, $filename, $lineno);
}
protected function getCurrentMailer()
protected function getCurrentMailer(): void
{
try {
$shop = Registry::getConfig()->getActiveShop();
$config = Registry::getConfig();
$mail = oxNew(Email::class);
$mail->setRecipient($this->testMailAddress);
$mail->setRecipient(
trim(Registry::getRequest()->getRequestEscapedParameter('recipient')) ?: $this->testMailAddress
);
$mail->setBody('.');
$mail->setFrom($shop->getFieldData('oxowneremail'));
set_error_handler([$this, 'exceptions_error_handler']);
$currentDebug = $config->getConfigParam('iDebug');
$config->setConfigParam('iDebug', 6);
$mail->setSmtp();
ob_start();
$mail->send();
$communication = ob_get_contents();
ob_end_clean();
$re = '/(^|\<br\>)(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}\s)/m';
$subst = "$1";
$communication = preg_replace($re, $subst, $communication);
$config->setConfigParam('iDebug', $currentDebug);
$this->addTplParam('mailer', $mail->getMailer());
$this->addTplParam('communication', $communication);
} catch (Exception $e) {
Registry::getUtilsView()->addErrorToDisplay($e);
} finally {
restore_error_handler();
}
}
}

View File

@ -1,23 +1,22 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
namespace D3\MailConfigChecker\Application\Controller\Admin;
use D3\MailConfigChecker\Application\Model\Constants;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
class MailInfoPage extends AdminDetailsController
{
protected $_sThisTemplate = 'mailInfoPage.tpl';
protected $_sThisTemplate = '@'.Constants::OXID_MODULE_ID.'/admin/mailInfoPage';
}

View File

@ -1,22 +1,22 @@
<?php
/**
* This Software is the property of Data Development and is protected
* by copyright law - it is NOT Freeware.
* Any unauthorized use of this software without a valid license
* is a violation of the license agreement and will be prosecuted by
* civil and criminal law.
* http://www.shopmodule.com
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <support@shopmodule.com>
* @link http://www.oxidmodule.com
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
namespace D3\MailConfigChecker\Application\Controller\Admin;
use Assert\Assert;
use D3\MailConfigChecker\Application\Model\Constants;
use D3\MailConfigChecker\Application\Model\Exception\d3TranslatableLazyAssertionException;
use Exception;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
use OxidEsales\Eshop\Application\Model\Shop;
use OxidEsales\Eshop\Core\Email;
@ -24,9 +24,9 @@ use OxidEsales\Eshop\Core\Registry;
class MailTester extends AdminDetailsController
{
protected $_sThisTemplate = 'mailTester.tpl';
protected $_sThisTemplate = '@'.Constants::OXID_MODULE_ID.'/admin/mailTester';
public function sendMail()
public function sendMail(): void
{
try {
$request = Registry::getRequest();
@ -46,12 +46,12 @@ class MailTester extends AdminDetailsController
$mail->setFrom($from);
$mail->sendEmail($to, $subject, $body);
$this->addTplParam('success', true);
} catch (\Exception $e) {
} catch ( Exception $e) {
Registry::getUtilsView()->addErrorToDisplay(nl2br($e->getMessage()));
}
}
protected function assertContent()
protected function assertContent(): void
{
$request = Registry::getRequest();
$lang = Registry::getLang();
@ -77,7 +77,7 @@ class MailTester extends AdminDetailsController
->verifyNow();
}
public function getMailAddressList()
public function getMailAddressList(): array
{
/** @var Shop $shop */
$shop = Registry::getConfig()->getActiveShop();

View File

@ -17,6 +17,7 @@ namespace D3\MailConfigChecker\Application\Controller\Admin;
use Assert\Assert;
use Assert\InvalidArgumentException;
use D3\MailConfigChecker\Application\Model\Constants;
use Net_SMTP;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
use OxidEsales\Eshop\Application\Model\Shop;
@ -26,18 +27,18 @@ use PEAR_Error;
class SmtpChecker extends AdminDetailsController
{
protected $debug = true;
protected bool $debug = true;
protected $host;
protected $port;
protected $user;
protected $pwd;
protected $from;
protected $to;
protected string $host;
protected int $port;
protected string $user;
protected string $pwd;
protected string $from;
protected ?string $to = null;
protected $smtp;
protected $action;
protected $log = [];
protected Net_SMTP $smtp;
protected string $action = '';
protected array $log = [];
public function __construct()
{
@ -68,19 +69,19 @@ class SmtpChecker extends AdminDetailsController
$this->addTplParam('smtpLog', $this->log);
}
public function getTemplateName()
public function getTemplateName(): string
{
return 'smtpCheck.tpl';
return '@'.Constants::OXID_MODULE_ID.'/admin/smtpCheck';
}
public function render()
public function render(): ?string
{
$this->addTplParam('shop', Registry::getConfig()->getActiveShop());
return parent::render();
}
public function getMailAddressList()
public function getMailAddressList(): array
{
/** @var Shop $shop */
$shop = Registry::getConfig()->getActiveShop();
@ -96,7 +97,7 @@ class SmtpChecker extends AdminDetailsController
);
}
public function sendMail()
public function sendMail(): void
{
try {
$this->hostIsAvailable();
@ -119,11 +120,11 @@ class SmtpChecker extends AdminDetailsController
* @throws InvalidArgumentException
* @return void
*/
protected function hostIsAvailable()
protected function hostIsAvailable(): void
{
$this->action = __FUNCTION__;
Assert::that(
($this->smtp = new Net_SMTP($this->host, $this->port)),
($this->smtp = new Net_SMTP($this->host, $this->port, $_SERVER['HTTP_HOST'])),
Registry::getLang()->translateString('D3_MAILCHECKER_SMTPCHECK_INSTANCE')
)->isInstanceOf(
Net_SMTP::class,
@ -132,7 +133,7 @@ class SmtpChecker extends AdminDetailsController
$this->smtp->setDebug($this->debug, [$this, 'dumpDebug']);
}
protected function connect()
protected function connect(): void
{
$this->action = __FUNCTION__;
Assert::that(
@ -149,7 +150,7 @@ class SmtpChecker extends AdminDetailsController
* @throws InvalidArgumentException
* @return void
*/
protected function auth()
protected function auth(): void
{
$this->action = __FUNCTION__;
Assert::that(
@ -162,7 +163,7 @@ class SmtpChecker extends AdminDetailsController
);
}
protected function setFrom()
protected function setFrom(): void
{
$this->action = __FUNCTION__;
Assert::that(
@ -175,8 +176,12 @@ class SmtpChecker extends AdminDetailsController
);
}
protected function setRecipient()
protected function setRecipient(): void
{
if (!$this->to) {
return;
}
$this->action = __FUNCTION__;
Assert::that(
$this->smtp->rcptTo($this->to),
@ -188,7 +193,7 @@ class SmtpChecker extends AdminDetailsController
);
}
protected function sendContent()
protected function sendContent(): void
{
if (!Registry::getRequest()->getRequestEscapedParameter('sendmail')) {
return;
@ -207,13 +212,13 @@ class SmtpChecker extends AdminDetailsController
);
}
protected function disconnect()
protected function disconnect(): void
{
$this->action = __FUNCTION__;
$this->smtp->disconnect();
}
public function dumpDebug($smtp, $message)
public function dumpDebug($smtp, $message): void
{
unset($smtp);
@ -223,7 +228,7 @@ class SmtpChecker extends AdminDetailsController
$this->log[$this->action][] = trim(htmlentities($message));
}
public function formatMessage(array $arguments)
public function formatMessage(array $arguments): ?string
{
/** @var PEAR_Error|true $response */
$response = $arguments['value'];

View File

@ -16,8 +16,15 @@ declare(strict_types=1);
namespace D3\MailConfigChecker\Application\Controller\Admin;
use Assert\InvalidArgumentException;
use D3\MailAuthenticationCheck\DMARCCheck;
use D3\MailAuthenticationCheck\Model\DMARCResult;
use D3\MailConfigChecker\Application\Model\Constants;
use D3\MailConfigChecker\Application\Model\DmarcResult as OxDmarcResult;
use D3\MailConfigChecker\Application\Model\SpfResult;
use Mika56\SPFCheck\DNSRecordGetter;
use LogicException;
use Mika56\SPFCheck\DNS\DNSRecordGetter;
use Mika56\SPFCheck\Model\Query;
use Mika56\SPFCheck\Model\Result;
use Mika56\SPFCheck\SPFCheck;
use OxidEsales\Eshop\Application\Controller\Admin\AdminDetailsController;
use OxidEsales\Eshop\Application\Model\Shop;
@ -25,15 +32,16 @@ use OxidEsales\Eshop\Core\Registry;
class SpfChecker extends AdminDetailsController
{
protected $_sThisTemplate = 'spfCheck.tpl';
protected $_sThisTemplate = '@'.Constants::OXID_MODULE_ID.'/admin/spfCheck';
public function render()
public function render(): ?string
{
$this->checkSpf();
$this->checkDmarc();
return parent::render();
}
protected function checkSpf()
protected function checkSpf(): void
{
$result = [];
$mailDomains = $this->getMailDomains();
@ -44,10 +52,24 @@ class SpfChecker extends AdminDetailsController
}
);
$this->addTplParam('result', $result);
$this->addTplParam('spf_result', $result);
}
protected function getMailDomains()
protected function checkDmarc(): void
{
$result = [];
$mailDomains = $this->getMailDomains();
array_walk(
$mailDomains,
function ($domain) use (&$result) {
$this->checkDmarcByDomain($domain, $result);
}
);
$this->addTplParam('dmarc_result', $result);
}
protected function getMailDomains(): array
{
/** @var Shop $shop */
$shop = Registry::getConfig()->getActiveShop();
@ -59,13 +81,13 @@ class SpfChecker extends AdminDetailsController
function ($mailAddress) {
$mailAddress = trim($mailAddress);
try {
if (! strstr($mailAddress, '@')) {
if ( ! str_contains( $mailAddress, '@' ) ) {
throw oxNew(InvalidArgumentException::class);
}
$addressChunks = explode('@', $mailAddress);
return array_pop($addressChunks);
} catch (InvalidArgumentException $e) {
} catch (InvalidArgumentException) {
return '';
}
},
@ -79,40 +101,59 @@ class SpfChecker extends AdminDetailsController
);
}
protected function checkSpfByDomain($domain, &$summarize)
protected function checkSpfByDomain($domain, &$summarize): void
{
$checker = new SPFCheck(new DNSRecordGetter());
$query = new Query('', $domain);
switch ($checker->isIPAllowed(gethostbyname($domain), $domain)) {
case SPFCheck::RESULT_FAIL:
case SPFCheck::RESULT_NEUTRAL:
case SPFCheck::RESULT_PASS:
case SPFCheck::RESULT_SOFTFAIL:
$status = SpfResult::SET;
break;
case SPFCheck::RESULT_NONE:
$status = SpfResult::MISSING;
break;
default:
$status = SpfResult::ERROR;
}
$result = $checker->getResult($query);
$status = match ( $result->getResult() ) {
Result::FAIL, Result::NEUTRAL, Result::PASS, Result::SOFTFAIL => SpfResult::SET,
Result::NONE => SpfResult::MISSING,
default => SpfResult::ERROR,
};
$rawRecord = ($record = (new DNSRecordGetter())->getSPFRecordForDomain($domain)) ?
implode(', ', $record) :
$rawRecord = ($record = $result->getRecord()) ?
$record->getRawRecord() :
null;
$summarize[$domain] = oxNew(SpfResult::class, $status, $rawRecord);
}
public function getSpfStatusColor(SpfResult $result)
public function getSpfStatusColor(SpfResult $result): string
{
switch ($result->getStatus()) {
case SpfResult::SET:
return 'success';
case SpfResult::ERROR:
return 'warning';
default:
return 'danger';
return match ( $result->getStatus() ) {
SpfResult::SET => 'success',
SpfResult::ERROR => 'warning',
default => 'danger',
};
}
public function checkDmarcByDomain($domain, &$summarize): void
{
try {
$check = new DMARCCheck(new DNSRecordGetter());
$query = new Query('', $domain);
$record = $check->getResult($query)->getRecord();
$status = match ( $record->getRejectPolicy()->getValue() ) {
DMARCResult::REJECT_QUARANTINE, DMARCResult::REJECT_REJECT => OxDmarcResult::SET,
DMARCResult::REJECT_NONE => OxDmarcResult::MISSING,
default => OxDmarcResult::ERROR,
};
$summarize[$domain] = oxNew( OxDmarcResult::class, $status, $record->getRawRecord());
} catch ( LogicException) {
$summarize[$domain] = oxNew( OxDmarcResult::class, OxDmarcResult::MISSING, '');
}
}
public function getDmarcStatusColor(OxDmarcResult $result): string
{
return match ( $result->getStatus() ) {
SpfResult::SET => 'success',
SpfResult::ERROR => 'warning',
default => 'danger',
};
}
}

View File

@ -0,0 +1,21 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\MailConfigChecker\Application\Model;
class Constants
{
public const OXID_MODULE_ID = 'd3mailconfigchecker';
}

View File

@ -0,0 +1,42 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
namespace D3\MailConfigChecker\Application\Model;
class DmarcResult
{
public const SET = 'set';
public const MISSING = 'missing';
public const ERROR = 'error';
protected $status;
protected $record;
public function __construct(string $status, ?string $record = null)
{
$this->status = $status;
$this->record = $record;
}
public function getStatus(): string
{
return $this->status;
}
public function getRecord(): ?string
{
return $this->record;
}
}

View File

@ -17,12 +17,12 @@ namespace D3\MailConfigChecker\Application\Model;
class SpfResult
{
public const SET = 'set';
public const SET = 'set';
public const MISSING = 'missing';
public const ERROR = 'error';
protected $status;
protected $record;
protected string $status;
protected ?string $record;
public function __construct(string $status, ?string $record = null)
{
@ -30,12 +30,12 @@ class SpfResult
$this->record = $record;
}
public function getStatus()
public function getStatus(): string
{
return $this->status;
}
public function getRecord()
public function getRecord(): ?string
{
return $this->record;
}

View File

@ -1,3 +0,0 @@
<?php
$aLang = include __DIR__."/../../de/translations.php";

View File

@ -1,3 +0,0 @@
<?php
$aLang = include __DIR__."/../../en/translations.php";

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
// @codeCoverageIgnoreStart
$sLangName = 'Deutsch';
$aLang = include __DIR__."/../../de/translations.php";
// @codeCoverageIgnoreEnd

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
// @codeCoverageIgnoreStart
$sLangName = 'English';
$aLang = include __DIR__."/../../en/translations.php";
// @codeCoverageIgnoreEnd

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
// @codeCoverageIgnoreStart
$sLangName = 'Deutsch';
$aLang = include __DIR__."/../../de/translations.php";
// @codeCoverageIgnoreEnd

View File

@ -0,0 +1,22 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
// @codeCoverageIgnoreStart
$sLangName = 'English';
$aLang = include __DIR__."/../../en/translations.php";
// @codeCoverageIgnoreEnd

View File

@ -1,12 +1,25 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
return [
'charset' => 'UTF-8',
'D3_MENU_MAILCHECKER' => 'E-Mail Prüfung',
'D3_TAB_MAILCHECKER_MODULEDESCRIPTION' => 'Beschreibung',
'D3_TAB_MAILCHECKER_CONFIGCHECK' => 'Konfigurationsprüfung',
'D3_TAB_MAILCHECKER_SMTPCHECK' => 'SMTP Check',
'D3_TAB_MAILCHECKER_SPFCHECK' => 'SPF Check',
'D3_TAB_MAILCHECKER_SPFCHECK' => 'Authentisierung Check',
'D3_TAB_MAILCHECKER_TESTMAIL' => 'Testmail',
'D3_MAILCHECKER_INFO_1' => 'Dieses Modul kann Ihnen helfen, um Schwierigkeiten beim Versand von Mails oder bei nicht zugestellten Mails zu identifizieren. Gehen Sie bitte die folgenden Tabs durch. Nötige Nacharbeiten werden Ihnen dort angezeigt.',
@ -20,7 +33,7 @@ return [
'D3_MAILCHECKER_CFGCHECK_SHOPSEND_PHPMAILER' => 'PhpMailer',
'D3_MAILCHECKER_CFGCHECK_SHOPSEND_PHPMAILER_DESC' => 'Der Versand über den PhpMailer sollte dringend vermieden werden, da solche Mails meist als Spam eingestuft werden. Wenn Sie alle SMTP-Daten eingegeben haben, prüfen Sie mögliche Anmeldeprobleme im SMTP-Check.',
'D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP' => 'SMTP',
'D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP_DESC' => 'Alles in bester Ordnung. Bitte prüfen Sie noch die nötigen SPF-Einträge für Ihre Domain(s).',
'D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP_DESC' => 'Alles in bester Ordnung. Bitte prüfen Sie noch die nötigen Einstellungen im Tab "Authorisierung Check" für Ihre Domain(s).',
'D3_MAILCHECKER_CFGCHECK_STARTCHECK' => 'Konfiguration testen',
'D3_MAILCHECKER_SMTPCHECK_DESC1' => 'Wenn trotz passend eingegebenen Daten kein Mailversand über SMTP erfolgt, kann hier der Anmeldeversuch am Postausgangsserver nachvollzogen werden. Eventuell auftretende Meldungen werden gezeigt.',
@ -41,6 +54,9 @@ return [
'D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT' => 'Datenübertragung nicht erfolgreich',
'D3_MAILCHECKER_SMTPCHECK_SUCCESS' => 'Die SMTP-Kommunikation wurde erfolgreich abgeschlossen.',
'D3_MAILCHECKER_RECORD' => 'Eintrag',
'D3_MAILCHECKER_SPFRESULT_HL' => 'SPF (Herkunftsprüfung)',
'D3_MAILCHECKER_SPFRESULT_DESC' => 'Mit dem Sender Policy Framework (SPF) definiert der Domaininhaber, welcher Server E-Mails mit dem Domainabsender versenden darf. Diese Angabe wird vom Empfangsserver geprüft. Fehlt der SPF-Eintrag, werden E-Mails üblicherweise als Spam klassifiziert.',
'D3_MAILCHECKER_SPFRESULT_SET' => 'Es ist ein SPF-Eintrag gesetzt',
'D3_MAILCHECKER_SPFRESULT_MISSING' => 'Es ist kein SPF-Eintrag gesetzt, dieser sollte dringend nachgetragen werden',
@ -50,6 +66,15 @@ return [
'D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR' => 'SPF Generator',
'D3_MAILCHECKER_SPFRESULT_LINK_BLACKLISTCHECK' => 'Blacklist Check',
'D3_MAILCHECKER_DMARCRESULT_HL' => 'DMARC (Ablehnungsrichtlinien und Berichterstattung)',
'D3_MAILCHECKER_DMARCRESULT_DESC' => 'Der DMARC-Eintrag definiert, wie mit Mails umgegangen wird, bei denen die Authentisierungsprüfungen fehlgeschlagen sind. Dort können auch Mailadressen für Reporte angegeben werden.',
'D3_MAILCHECKER_DMARCRESULT_SET' => 'Es ist ein DMARC-Eintrag gesetzt, das Verhalten ist nicht auf "ignorieren" gestellt.',
'D3_MAILCHECKER_DMARCRESULT_MISSING' => 'Es ist kein DMARC-Eintrag gesetzt oder mit "ignorieren" konfiguriert. Dies sollte dringend geändert werden.',
'D3_MAILCHECKER_DMARCRESULT_ERROR' => 'Der DMARC-Eintrag kann nicht geprüft werden',
'D3_MAILCHECKER_DMARCRESULT_LINKS' => 'weiterführende Links',
'D3_MAILCHECKER_DMARCRESULT_LINK_ANALYSIS' => 'DMARC Analyse',
'D3_MAILCHECKER_DMARCRESULT_LINK_GENERATOR' => 'DMARC Generator',
'D3_MAILCHECKER_TESTMAIL_DESC' => 'Die Testmail wird auf identischem Weg geschickt, den auch alle regulären Mails aus dem Shop nehmen (z.B. Bestellbestätigungen, ...) und kann z.B. zur Headeranalyse dienen.',
'D3_MAILCHECKER_TESTMAIL_HEADERANALYSIS' => 'Email Header Analyzer',
'D3_MAILCHECKER_TESTMAIL_SUBJECT' => 'Betreff',

View File

@ -1,12 +1,25 @@
<?php
/**
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* https://www.d3data.de
*
* @copyright (C) D3 Data Development (Inh. Thomas Dartsch)
* @author D3 Data Development - Daniel Seifert <info@shopmodule.com>
* @link https://www.oxidmodule.com
*/
declare(strict_types=1);
return [
"charset" => "UTF-8",
"D3_MENU_MAILCHECKER" => "Email checking",
"D3_TAB_MAILCHECKER_MODULEDESCRIPTION" => "Description",
"D3_TAB_MAILCHECKER_CONFIGCHECK" => "Configuration check",
"D3_TAB_MAILCHECKER_SMTPCHECK" => "SMTP check",
"D3_TAB_MAILCHECKER_SPFCHECK" => "SPF check",
"D3_TAB_MAILCHECKER_SPFCHECK" => "Authentication check",
"D3_TAB_MAILCHECKER_TESTMAIL" => "Test email",
"D3_MAILCHECKER_ASSERTIONS_FAILED" => "The following %d checks failed:",
"D3_MAILCHECKER_ASSERTIONS_NOTSET" => "is not (correctly) set",
@ -15,7 +28,7 @@ return [
"D3_MAILCHECKER_CFGCHECK_SHOPSEND_PHPMAILER" => "PhpMailer",
"D3_MAILCHECKER_CFGCHECK_SHOPSEND_PHPMAILER_DESC" => "Sending via PhpMailer should be avoided as such emails are usually classified as spam. Once you have entered all SMTP data, check possible login problems in the SMTP check.",
"D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP" => "SMTP",
"D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP_DESC" => "Everything is fine. Please check the necessary SPF entries for your domain(s).",
"D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP_DESC" => "Everything is fine. Please check the necessary settings for your domain(s) in the \"Authentication Check\" tab .",
"D3_MAILCHECKER_CFGCHECK_STARTCHECK" => "Test configuration",
"D3_MAILCHECKER_SMTPCHECK_DESC1" => "If no mail is sent via SMTP despite the appropriate data entered, the attempt to log in to the outgoing mail server can be repeated here. Any messages that may occur are shown.",
"D3_MAILCHECKER_SMTPCHECK_DESC2" => "New connections can also be tested here in advance.",
@ -34,6 +47,10 @@ return [
"D3_MAILCHECKER_SMTPCHECK_TRANSMIT" => "Data transfer",
"D3_MAILCHECKER_SMTPCHECK_NOTRANSMIT" => "Data transfer not successful",
"D3_MAILCHECKER_SMTPCHECK_SUCCESS" => "SMTP communication was completed successfully.",
'D3_MAILCHECKER_RECORD' => 'Record',
'D3_MAILCHECKER_SPFRESULT_HL' => 'SPF (Origin verification)',
"D3_MAILCHECKER_SPFRESULT_DESC" => "With the Sender Policy Framework (SPF), the domain owner defines which server is allowed to send emails with the domain sender. This information is checked by the receiving server. If the SPF entry is missing, emails are usually sent as ",
"D3_MAILCHECKER_SPFRESULT_SET" => "An SPF entry is set",
"D3_MAILCHECKER_SPFRESULT_MISSING" => "There is no SPF entry set, this should be added urgently",
@ -42,6 +59,16 @@ return [
"D3_MAILCHECKER_SPFRESULT_LINK_ANALYSIS" => "SPF analysis",
"D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR" => "SPF generator",
"D3_MAILCHECKER_SPFRESULT_LINK_BLACKLISTCHECK" => "Blacklist check",
'D3_MAILCHECKER_DMARCRESULT_HL' => 'DMARC (Reject policy and reporting)',
'D3_MAILCHECKER_DMARCRESULT_DESC' => 'The DMARC entry defines how to deal with mails for which the authentication checks have failed. Mail addresses for reports can also be specified there.',
'D3_MAILCHECKER_DMARCRESULT_SET' => 'A DMARC entry is set, the behaviour is not set to ignore.',
'D3_MAILCHECKER_DMARCRESULT_MISSING' => 'No DMARC entry is set or configured with ignore. This should be changed urgently.',
'D3_MAILCHECKER_DMARCRESULT_ERROR' => 'The DMARC record cannot be checked',
'D3_MAILCHECKER_DMARCRESULT_LINKS' => 'Related Links',
'D3_MAILCHECKER_DMARCRESULT_LINK_ANALYSIS' => 'DMARC analysis',
'D3_MAILCHECKER_DMARCRESULT_LINK_GENERATOR' => 'DMARC generator',
"D3_MAILCHECKER_TESTMAIL_DESC" => "The test email is sent in the same way as all regular emails from the shop (e.g..B. order confirmations, ...) and can ",
"D3_MAILCHECKER_TESTMAIL_HEADERANALYSIS" => "Email Header Analyzer",
"D3_MAILCHECKER_TESTMAIL_SUBJECT" => "Regarding",

View File

@ -4,13 +4,41 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased](https://git.d3data.de/D3Public/MyModule/compare/1.0.0.0...rel_1.x)
## [Unreleased](https://git.d3data.de/D3Public/MyModule/compare/3.0.1.0...rel_3.x)
## [1.0.0.1](https://git.d3data.de/D3Public/MailConfigChecker/releases/tag/1.0.0.1) - 2024-04-11
## [3.0.1.0](https://git.d3data.de/D3Public/MailConfigChecker/compare/3.0.0.0...3.0.1.0) - 2024-07-10
### Added
- get mailer check shows PHPMailer communication with the mail server (can be different from the SMTP check)
- recipient for get mailer check can modified in hidden form element
### Changed
- SMTP check uses shop domain for EHLO
## [3.0.0.0](https://git.d3data.de/D3Public/MailConfigChecker/compare/2.1.0.0...3.0.0.0) - 2024-06-05
### Added
- OXID 7.x support
- Twig templates (alongside to Smarty)
### Removed
- OXID 6.x support
## [2.1.1.0](https://git.d3data.de/D3Public/MailConfigChecker/compare/2.1.0.0...2.1.1.0) - 2024-07-10
### Added
- get mailer check shows PHPMailer communication with the mail server (can be different from the SMTP check)
- recipient for get mailer check can modified in hidden form element
### Changed
- SMTP check uses shop domain for EHLO
## [2.1.0.0](https://git.d3data.de/D3Public/MailConfigChecker/compare/2.0.0.1...2.1.0.0) - 2024-06-05
### Added
- check for DMARC DNS record
## [2.0.0.1](https://git.d3data.de/D3Public/MailConfigChecker/compare/2.0.0.0...2.0.0.1) - 2024-04-11
### Fixed
- MailConfigCheck need a valid "from" mailadress to check smtp correctly
## [1.0.0.0](https://git.d3data.de/D3Public/MailConfigChecker/releases/tag/1.0.0.0) - 2023-12-13
## [2.0.0.0](https://git.d3data.de/D3Public/MailConfigChecker/releases/tag/2.0.0.0) - 2023-12-13
### Added
- Checking the mail configuration
- Checking the transmission path used

View File

@ -18,7 +18,7 @@ This package requires an OXID eShop installed with Composer in a version defined
Open a command line and navigate to the root directory of the shop (parent directory of source and vendor). Execute the following commands. Adapt the path details to your installation environment.
```bash
composer require d3/mailconfigchecker:^1.0
composer require d3/mailconfigchecker:^2.0
```
Activate the module in Shopadmin under "Extensions -> Modules".

View File

@ -19,7 +19,7 @@ Dieses Paket erfordert einen mit Composer installierten OXID eShop in einer in d
```bash
composer require d3/mailconfigchecker:^1.0
composer require d3/mailconfigchecker:^3.0
```
Aktivieren Sie das Modul im Shopadmin unter "Erweiterungen -> Module".

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -12,6 +12,7 @@
"SMTP",
"phpMailer",
"SPF",
"DMARC",
"testing"
],
"authors": [
@ -30,26 +31,22 @@
"GPL-3.0-or-later"
],
"require": {
"php": ">=7.1",
"oxid-esales/oxideshop-ce": "6.3 - 6.9",
"php": "^8",
"oxid-esales/oxideshop-ce": "7.0 - 7.1",
"pear/net_smtp": "^1.11",
"mika56/spfcheck": "^1.1.7",
"mika56/spfcheck": "^2.1.1",
"d3/mailauthenticationcheck": "^0.1.0",
"beberlei/assert": "^3.3"
},
"extra": {
"oxideshop": {
"blacklist-filter": [
"*.md",
"composer.json",
".php-cs-fixer.php",
"*.neon"
],
"target-directory": "d3/mailconfigchecker"
}
"require-dev": {
"php": "^8",
"friendsofphp/php-cs-fixer": "^3.9",
"phpstan/phpstan": "^1.8",
"boxblinkracer/phpunuhi": "^1.12"
},
"autoload": {
"psr-4": {
"D3\\MailConfigChecker\\": "../../../source/modules/d3/mailconfigchecker"
"D3\\MailConfigChecker\\": ""
}
},
"scripts": {

View File

@ -20,17 +20,17 @@ use D3\MailConfigChecker\Application\Controller\Admin\MailInfoPage;
use D3\MailConfigChecker\Application\Controller\Admin\MailTester;
use D3\MailConfigChecker\Application\Controller\Admin\SpfChecker;
use D3\MailConfigChecker\Application\Controller\Admin\SmtpChecker;
use D3\MailConfigChecker\Application\Model\Constants;
$sMetadataVersion = '2.1';
$sModuleId = 'd3mailconfigchecker';
$logo = '<img src="https://logos.oxidmodule.com/d3logo.svg" alt="(D3)" style="height:1em;width:1em">';
/**
* Module information
*/
$aModule = [
'id' => $sModuleId,
'id' => Constants::OXID_MODULE_ID,
'title' => [
'de' => $logo.' E-Mail Konfigurationspr&uuml;fung',
'en' => $logo.' Mail Configuration Check Tool',
@ -40,7 +40,7 @@ $aModule = [
'en' => '',
],
'thumbnail' => 'picture.svg',
'version' => '1.0.0.1',
'version' => '3.0.1.0',
'author' => 'D&sup3; Data Development (Inh.: Thomas Dartsch)',
'email' => 'support@shopmodule.com',
'url' => 'https://www.oxidmodule.com/',
@ -54,13 +54,13 @@ $aModule = [
'd3mailtester' => MailTester::class,
],
'templates' => [
'mailCheckBase.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/mailcheckbase.tpl',
'mailCheckMenu.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/mailcheckmenu.tpl',
'mailInfoPage.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/mailinfopage.tpl',
'mailConfigCheck.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/mailconfigcheck.tpl',
'smtpCheck.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/smtpCheck.tpl',
'spfCheck.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/spfCheck.tpl',
'mailTester.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/mailTester.tpl',
'inc_bootstrap.tpl' => 'd3/mailconfigchecker/Application/views/admin/tpl/inc/bootstrap.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/mailCheckBase.tpl' => 'views/smarty/admin/mailcheckbase.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/mailCheckMenu.tpl' => 'views/smarty/admin/mailcheckmenu.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/mailInfoPage.tpl' => 'views/smarty/admin/mailinfopage.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/mailConfigCheck.tpl' => 'views/smarty/admin/mailconfigcheck.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/smtpCheck.tpl' => 'views/smarty/admin/smtpCheck.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/spfCheck.tpl' => 'views/smarty/admin/spfCheck.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/mailTester.tpl' => 'views/smarty/admin/mailTester.tpl',
'@' . Constants::OXID_MODULE_ID . '/admin/inc_bootstrap.tpl' => 'views/smarty/admin/inc/bootstrap.tpl',
],
];

View File

@ -1,38 +0,0 @@
# Arbeiten mit [Doctrine Migrations](https://www.doctrine-project.org/projects/doctrine-migrations/en/3.6/reference/introduction.html)
Migrations bilden die Veränderung der Datenbankstruktur in programmierter Form ab. Jede Strukturänderung wird in einer einzelnen (jeweils neuen) Migrationsdatei abgelegt, die Teil des Moduls ist.
Passe die `migrations.yml` an Dein Modul an.
## Erstellen eines Skeletons für die erste oder zusätzliche Migrationen
```
./vendor/bin/oe-eshop-doctrine_migration migrations:generate d3moduleid
```
Arbeite die angelegte Datei entsprechend Deinen Anforderungen um.
## Ausführen der noch nicht ausgeführten Migrations
Doctrine überwacht selbst, welche Migrationen schon ausgeführt wurden und verhindert damit mehrfache Ausführungen der selben Migration.
Im OXID-Shop werden Migrations mit folgendem Befehl ausgeführt:
```
./vendor/bin/oe-eshop-db_migrate migrations:migrate
```
Als Argument kann noch die Suite mitgegeben werden, wenn nur bestimmte Migrations ausgeführt werden sollen. Mögliche Angaben sind:
- CE - für alle CE-Migrations
- PE - für alle PE-Migrations
- EE - für alle EE-Migrations
- PR - für alle Projekt-Migrations
- ModuleId - für alle Migrations des jeweiligen Moduls
- ohne Angabe - werden die Migrations aller Suiten nacheinander ausgeführt
## Abweichungen zwischen Doctrine Migrations und dem OXID Migration Wrapper
In den originalen Doctrine Migrations können keine Suiten angegeben werden. Dafür gibt es die Möglichkeit, die Richtung (up / down) und eine Zielversion anzugeben.
Bei OXID können Migrations ausschließlich aufwärts (up) und immer fix bis zur aktuellsten Version ausgeführt werden.

View File

@ -1,4 +0,0 @@
name: D3 module name
migrations_namespace: D3\ThisModule\Migrations
table_name: d3migrations_modulename
migrations_directory: data

View File

@ -1,5 +1,5 @@
[{include file="headitem.tpl" title="d3mxd3cleartmp"|oxmultilangassign}]
[{include file="inc_bootstrap.tpl"}]
[{include file="@d3mailconfigchecker/admin/inc_bootstrap.tpl"}]
[{if $readonly}]
[{assign var="readonly" value="readonly disabled"}]

View File

@ -1,10 +1,18 @@
[{include file="headitem.tpl" title="d3mxd3cleartmp"|oxmultilangassign}]
[{include file="inc_bootstrap.tpl"}]
[{include file="@d3mailconfigchecker/admin/inc_bootstrap.tpl"}]
<style>
span.btn {
cursor: default;
}
.communicationoutput {
background-color: black;
color: white;
max-height: 500px;
overflow: auto;
margin-top: 30px;
}
</style>
[{assign var="readonly" value="readonly disabled"}]
@ -52,11 +60,16 @@
[{oxmultilang ident="D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP_DESC"}]
[{/if}]
</div>
<div class="col-12 communicationoutput">
[{$communication}]
</div>
[{else}]
<form name="myedit" id="myedit" action="[{$oViewConf->getSelfLink()}]" method="post">
[{$oViewConf->getHiddenSid()}]
<input type="hidden" name="cl" value="[{$oViewConf->getActiveClassName()}]">
<input type="hidden" name="fnc" value="checkConfiguration">
<input type="hidden" name="recipient" value="[{$recipient}]">
<button type="submit" class="btn btn-primary">[{oxmultilang ident="D3_MAILCHECKER_CFGCHECK_STARTCHECK"}]</button>
</form>
[{/if}]

View File

@ -1,5 +1,5 @@
[{include file="headitem.tpl" title="d3mxd3cleartmp"|oxmultilangassign}]
[{include file="inc_bootstrap.tpl"}]
[{include file="@d3mailconfigchecker/admin/inc_bootstrap.tpl"}]
<style>
span.btn {

View File

@ -1,5 +1,5 @@
[{include file="headitem.tpl" title="GENERAL_ADMIN_TITLE"|oxmultilangassign}]
[{include file="inc_bootstrap.tpl"}]
[{include file="@d3mailconfigchecker/admin/inc_bootstrap.tpl"}]
<style>
.communicationoutput,

View File

@ -1,5 +1,5 @@
[{include file="headitem.tpl" title="GENERAL_ADMIN_TITLE"|oxmultilangassign}]
[{include file="inc_bootstrap.tpl"}]
[{include file="@d3mailconfigchecker/admin/inc_bootstrap.tpl"}]
<form name="transfer" id="transfer" action="[{$oViewConf->getSelfLink()}]" method="post">
[{$oViewConf->getHiddenSid()}]
@ -10,15 +10,16 @@
</form>
<div class="row">
<div class="col-12 col-md-10 col-lg-8 mb-4">
<div class="col-12 mb-4">
<h4>[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_HL"}]</h4>
[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_DESC"}]
</div>
</div>
<div class="row">
<div class="col-12 col-md-10 col-lg-8 mb-4">
<div class="col-12 mb-4">
<div class="row">
[{foreach from=$result key="domain" item="spf"}]
<div class="col-12 col-md-6 col-lg-4">
[{foreach from=$spf_result key="domain" item="spf"}]
<div class="col-12 col-md-6 col-lg-3">
<div class="card mb-3">
<div class="card-header text-white bg-[{$oView->getSpfStatusColor($spf)}]">
[{$domain}]
@ -27,8 +28,8 @@
<p>[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_"|cat:$spf->getStatus()|upper}]</p>
[{if $spf->getRecord()}]
<p>
<label for="[{$domain}]_record">Eintrag:</label>
<input type="text" id="[{$domain}]_record" value="[{$spf->getRecord()}]" readonly disabled>
<label for="[{$domain}]_record">[{oxmultilang ident="D3_MAILCHECKER_RECORD" suffix="COLON"}]</label>
<input type="text" id="[{$domain}]_record" value="[{$spf->getRecord()}]" style="width: 50%;" readonly disabled>
</p>
[{/if}]
@ -45,7 +46,6 @@
<a href="https://mxtoolbox.com/SPFRecordGenerator.aspx?domain=[{$domain}]&prefill=true">
[{oxmultilang ident="D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR"}]
</a>
</li>
[{/if}]
<li>
@ -62,6 +62,51 @@
</div>
</div>
<div class="row">
<div class="col-12 mb-4">
<h4>[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_HL"}]</h4>
[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_DESC"}]
</div>
</div>
<div class="row">
<div class="col-12 mb-4">
<div class="row">
[{foreach from=$dmarc_result key="domain" item="dmarc"}]
<div class="col-12 col-md-6 col-lg-3">
<div class="card mb-3">
<div class="card-header text-white bg-[{$oView->getDmarcStatusColor($dmarc)}]">
[{$domain}]
</div>
<div class="card-body">
<p>[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_"|cat:$dmarc->getStatus()|upper}]</p>
[{if $dmarc->getRecord()}]
<p>
<label for="[{$domain}]_record">[{oxmultilang ident="D3_MAILCHECKER_RECORD" suffix="COLON"}]</label>
<input type="text" id="[{$domain}]_record" value="[{$dmarc->getRecord()}]" style="width: 50%;" readonly disabled>
</p>
[{/if}]
<h5>[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_LINKS"}]</h5>
<ul>
<li>
<a href="https://mxtoolbox.com/SuperTool.aspx?action=dmarc%3a[{$domain}]&run=toolpage">
[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_LINK_ANALYSIS"}]
</a>
</li>
<li>
<a href="https://mxtoolbox.com/DMARCRecordGenerator.aspx?domain=[{$domain}]&prefill=true">
[{oxmultilang ident="D3_MAILCHECKER_DMARCRESULT_LINK_GENERATOR"}]
</a>
</li>
</ul>
</div>
</div>
</div>
[{/foreach}]
</div>
</div>
</div>
[{include file="bottomnaviitem.tpl"}]
[{include file="bottomitem.tpl"}]

View File

@ -0,0 +1,14 @@
<link rel="stylesheet" href="{{ oViewConf.getModuleUrl('d3mailconfigchecker', 'out/src/css/bootstrap.min.css') }}">
<style>
* {
font-size: 12px;
box-sizing: initial;
}
a {
color: inherit;
text-decoration: inherit;
}
select {
box-sizing: border-box;
}
</style>

View File

@ -0,0 +1,14 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>{{ translate({ ident: "GENERAL_ADMIN_TITLE" }) }}</title>
</head>
<!-- frames -->
<frameset rows="10%,*" style="border: none" onload="top.loadEditFrame('{{ oViewConf.getSelfLink()|raw }}&{{ editurl }}{% if oxid %}&oxid={{ oxid }}{% endif %}');">
<frame src="{{ oViewConf.getSelfLink()|raw }}&{{ listurl }}{% if oxid %}&oxid={{ oxid }}{% endif %}" name="list" id="list" style="border: none" frameborder="0" scrolling="Auto" noresize marginwidth="0" marginheight="0">
<frame src="" name="edit" id="edit" style="border: none" frameborder="0" scrolling="Auto" noresize marginwidth="0" marginheight="0">
</frameset>
</html>

View File

@ -0,0 +1,39 @@
{% include "headitem.html.twig" with {title: "GENERAL_ADMIN_TITLE"|translate, box: "list"} %}
{% if readonly %}
{% set readonly = "readonly disabled" %}
{% else %}
{% set readonly = "" %}
{% endif %}
<script type="text/javascript">
<!--
window.onload = function ()
{
{% if updatenav %}
var oTransfer = top.basefrm.edit.document.getElementById( "transfer" );
oTransfer.updatenav.value = 1;
oTransfer.cl.value = '{{ default_edit }}';
{% endif %}
top.reloadEditFrame();
}
//-->
</script>
<form name="search" id="search" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{% include "_formparams.html.twig" with {cl: oViewConf.getActiveClassName()|raw, lstrt: lstrt, actedit: actedit, oxid: oxid, fnc: "", language: actlang, editlanguage: actlang} %}
</form>
{% include "pagetabsnippet.html.twig" %}
<script type="text/javascript">
if (parent.parent != null && parent.parent.setTitle )
{ parent.parent.sShopTitle = "{{ actshopobj.oxshops__oxname.getRawValue()|addslashes }}";
parent.parent.sMenuItem = "{{ translate({ ident: "SHOP_LIST_MENUITEM" }) }}";
parent.parent.sMenuSubItem = "{{ translate({ ident: "SHOP_LIST_MENUSUBITEM" }) }}";
parent.parent.sWorkArea = "{{ _act }}";
parent.parent.setTitle();
}
</script>
</body>
</html>

View File

@ -0,0 +1,80 @@
{% include "headitem.html.twig" with {title: "d3mxd3cleartmp"|translate} %}
{% include "@d3mailconfigchecker/admin/inc/bootstrap.html.twig" %}
<style>
span.btn {
cursor: default;
}
.communicationoutput {
background-color: black;
color: white;
max-height: 500px;
overflow: auto;
margin-top: 30px;
}
</style>
{% set readonly = "readonly disabled" %}
<form name="transfer" id="transfer" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="oxid" value="{{ oxid }}">
<input type="hidden" name="oxidCopy" value="{{ oxid }}">
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
</form>
<div class="row">
<div class="col-12 col-md-6 col-lg-4 mb-4">
<div>
<label class="col-4 form-label" for="oxshops__oxsmtp">{{ translate({ ident: "SHOP_MAIN_SMTPSERVER" }) }}</label>
<input type="text" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxsmtp.fldmax_length }}" id="oxshops__oxsmtp" value="{{ shop.getFieldData('oxsmtp') }}" {{ readonly }}>
</div>
<div>
<label class="col-4 form-label" for="oxshops__oxsmtpuser">{{ translate({ ident: "SHOP_MAIN_SMTPUSER" }) }}</label>
<input type="text" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxsmtpuser.fldmax_length }}" id="oxshops__oxsmtpuser" value="{{ shop.getFieldData('oxsmtpuser') }}" {{ readonly }}>
</div>
<div>
<label class="col-4 form-label" for="oxshops__oxinfoemail">{{ translate({ ident: "SHOP_MAIN_INFOEMAIL" }) }}</label>
<input type="text" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxinfoemail.fldmax_length }}" id="oxshops__oxinfoemail" value="{{ shop.getFieldData('oxinfoemail') }}" {{ readonly }}>
</div>
<div>
<label class="col-4 form-label" for="oxshops__oxorderemail">{{ translate({ ident: "SHOP_MAIN_ORDEREMAIL" }) }}</label>
<input type="text" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxorderemail.fldmax_length }}" id="oxshops__oxorderemail" value="{{ shop.getFieldData('oxorderemail') }}" {{ readonly }}>
</div>
<div>
<label class="col-4 form-label" for="oxshops__oxowneremail">{{ translate({ ident: "SHOP_MAIN_OWNEREMAIL" }) }}</label>
<input type="text" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxowneremail.fldmax_length }}" id="oxshops__oxowneremail" value="{{ shop.getFieldData('oxowneremail') }}" {{ readonly }}>
</div>
</div>
<div class="col-12 col-md-6 col-lg-4">
{% if mailer %}
<div>
{{ translate({ ident: "D3_MAILCHECKER_CFGCHECK_SHOPSEND", suffix: "COLON" }) }}
{% if mailer == 'mail' %}
<button type="button" class="btn btn-danger">{{ translate({ ident: "D3_MAILCHECKER_CFGCHECK_SHOPSEND_PHPMAILER" }) }}</button><br>
{{ translate({ ident: "D3_MAILCHECKER_CFGCHECK_SHOPSEND_PHPMAILER_DESC" }) }}
{% else %}
<span class="btn btn-success">{{ translate({ ident: "D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP" }) }}</span><br>
{{ translate({ ident: "D3_MAILCHECKER_CFGCHECK_SHOPSEND_SMTP_DESC" }) }}
{% endif %}
</div>
<div class="col-12 communicationoutput">
{{ communication|raw }}
</div>
{% else %}
<form name="myedit" id="myedit" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
<input type="hidden" name="fnc" value="checkConfiguration">
<input type="hidden" name="recipient" value="{{ recipient }}">
<button type="submit" class="btn btn-primary">{{ translate({ ident: "D3_MAILCHECKER_CFGCHECK_STARTCHECK" }) }}</button>
</form>
{% endif %}
</div>
</div>
{% include "bottomnaviitem.html.twig" %}
{% include "bottomitem.html.twig" %}

View File

@ -0,0 +1,34 @@
{% include "headitem.html.twig" with {title: "d3mxd3cleartmp"|translate} %}
{% include "@d3mailconfigchecker/admin/inc/bootstrap.html.twig" %}
<style>
span.btn {
cursor: default;
}
</style>
{% set readonly = "readonly disabled" %}
<form name="transfer" id="transfer" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="oxid" value="{{ oxid }}">
<input type="hidden" name="oxidCopy" value="{{ oxid }}">
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
</form>
<div class="row">
<div class="col-12 col-md-10 col-lg-8 mb-4">
<p>
{{ translate({ ident: "D3_MAILCHECKER_INFO_1" }) }}
</p>
<p>
{{ translate({ ident: "D3_MAILCHECKER_INFO_2" }) }}
</p>
<p>
{{ translate({ ident: "D3_MAILCHECKER_INFO_3" }) }}
</p>
</div>
</div>
{% include "bottomnaviitem.html.twig" %}
{% include "bottomitem.html.twig" %}

View File

@ -0,0 +1,71 @@
{% include "headitem.html.twig" with {title: "d3mxd3cleartmp"|translate} %}
{% include "@d3mailconfigchecker/admin/inc/bootstrap.html.twig" %}
{% if readonly %}
{% set readonly = "readonly disabled" %}
{% else %}
{% set readonly = "" %}
{% endif %}
<form name="transfer" id="transfer" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="oxid" value="{{ oxid }}">
<input type="hidden" name="oxidCopy" value="{{ oxid }}">
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
</form>
{% if success %}
<div class="alert alert-success">{{ translate({ ident: "D3_MAILCHECKER_TESTMAIL_SUCCESS" }) }}</div>
{% endif %}
<div class="col-12 col-md-10 col-lg-8 mb-4">
{{ translate({ ident: "D3_MAILCHECKER_TESTMAIL_DESC" }) }}
</div>
<h5>{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_LINKS" }) }}</h5>
<ul>
<li>
<a href="https://mxtoolbox.com/EmailHeaders.aspx">
{{ translate({ ident: "D3_MAILCHECKER_TESTMAIL_HEADERANALYSIS" }) }}
</a>
</li>
</ul>
<div class="row">
<div class="col-12 col-md-6 col-lg-4 mb-4">
<form name="myedit" id="myedit" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
<input type="hidden" name="fnc" value="sendMail">
<div>
<label class="col-4 form-label" for="sender">{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_SENDER" }) }}</label>
<select name="from" class="col-7 editinput" id="sender">
{% for address in oView.getMailAddressList() %}
<option value="{{ address }}" {% if sender == address %}selected{% endif %}>{{ address }}</option>
{% endfor %}
</select>
</div>
<div>
<label class="col-4 form-label" for="recipient">{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_RECIPIENT" }) }}</label>
<input name="to" type="text" class="col-7 editinput" size="35" maxlength="255" id="recipient" value="{{ recipient }}">
</div>
<div>
<label class="col-4 form-label" for="subject">{{ translate({ ident: "D3_MAILCHECKER_TESTMAIL_SUBJECT" }) }}</label>
<input type="text" class="col-7 editinput" id="subject" maxlength="255" name="subject" value="{{ subject }}">
</div>
<div>
<label class="col-4 form-label" for="body">{{ translate({ ident: "D3_MAILCHECKER_TESTMAIL_BODY" }) }}</label>
<textarea name="body" class="col-7 editinput" id="body" maxlength="255" style="height: 100px">{% apply spaceless %}
{{ body }}
{% endapply %}</textarea>
</div>
<div>
<button type="submit" class="btn btn-primary offset-4">{{ translate({ ident: "D3_MAILCHECKER_TESTMAIL_SENDMAIL" }) }}</button>
</div>
</form>
</div>
</div>
{% include "bottomnaviitem.html.twig" %}
{% include "bottomitem.html.twig" %}

View File

@ -0,0 +1,96 @@
{% include "headitem.html.twig" with {title: "GENERAL_ADMIN_TITLE"|translate} %}
{% include "@d3mailconfigchecker/admin/inc/bootstrap.html.twig" %}
<style>
.communicationoutput,
.communicationoutput dl dt,
.communicationoutput dl dd {
background-color: black;
color: white;
}
</style>
<form name="transfer" id="transfer" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="oxid" value="{{ oxid }}">
<input type="hidden" name="oxidCopy" value="{{ oxid }}">
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
<input type="hidden" name="editlanguage" value="{{ editlanguage }}">
</form>
{% if success %}
<div class="alert alert-success">{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_SUCCESS" }) }}</div>
{% endif %}
<div class="row">
<div class="col-12 col-md-6 col-lg-4 mb-4">
<p>
{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_DESC1" }) }}
</p>
<p>
{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_DESC2" }) }}
</p>
<p>
{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_DESC3" }) }}
</p>
<form name="myedit" id="myedit" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
<input type="hidden" name="fnc" value="sendMail">
<div>
<label class="col-4 form-label" for="oxshops__oxsmtp">{{ translate({ ident: "SHOP_MAIN_SMTPSERVER" }) }}</label>
<input type="text" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxsmtp.fldmax_length }}" id="oxshops__oxsmtp" name="smtpHost" value="{% if smtpHost %}{{ smtpHost }}{% else %}{{ shop.getFieldData('oxsmtp') }}{% endif %}">
</div>
<div>
<label class="col-4 form-label" for="oxshops__oxsmtpuser">{{ translate({ ident: "SHOP_MAIN_SMTPUSER" }) }}</label>
<input type="text" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxsmtpuser.fldmax_length }}" id="oxshops__oxsmtpuser" name="smtpUser" value="{% if smtpUser %}{{ smtpUser }}{% else %}{{ shop.getFieldData('oxsmtpuser') }}{% endif %}">
</div>
<div>
<label class="col-4 form-label" for="oxshops__oxsmtppwd">{{ translate({ ident: "SHOP_MAIN_SMTPPASSWORD" }) }}</label>
<input type="password" class="col-7 editinput" size="35" maxlength="{{ shop.oxshops__oxsmtppwd.fldmax_length }}" id="oxshops__oxsmtppwd" name="smtpPwd" value="{% if smtpPwd %}{{ smtpPwd }}{% else %}{{ shop.getFieldData('oxsmtppwd') }}{% endif %}">
</div>
<div>
<label class="col-4 form-label" for="sender">{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_SENDER" }) }}</label>
<select name="from" class="col-7 editinput" id="sender">
{% for address in oView.getMailAddressList() %}
<option value="{{ address }}">{{ address }}</option>
{% endfor %}
</select>
</div>
<div>
<label class="col-4 form-label" for="recipient">{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_RECIPIENT" }) }}</label>
<input name="to" type="text" class="col-7 editinput" size="35" maxlength="255" id="recipient" value="{{ recipient }}">
</div>
<div>
<label class="col-4 form-label" for="sendmail">{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_TESTSENDMAIL" }) }}</label>
<input type="checkbox" class="col-7 editinput" id="sendmail" name="sendmail" value="1" {% if sendMail %}checked{% endif %}>
</div>
<div>
<button type="submit" class="btn btn-primary offset-4">{{ translate({ ident: "D3_MAILCHECKER_SMTPCHECK_STARTTEST" }) }}</button>
</div>
</form>
</div>
<div class="col-12 col-md-6 col-lg-4 mb-4 {% if smtpLog %}communicationoutput{% endif %}">
{% for action, logItems in smtpLog %}
<dl>
<dt>{{ loop.index }} - {{ action }}</dt>
<dd>
<ul>
{% for logItem in logItems %}
<li>
{{ logItem }}
</li>
{% endfor %}
</ul>
</dd>
</dl>
{% endfor %}
</div>
</div>
{% include "bottomnaviitem.html.twig" %}
{% include "bottomitem.html.twig" %}

View File

@ -0,0 +1,112 @@
{% include "headitem.html.twig" with {title: "GENERAL_ADMIN_TITLE"|translate} %}
{% include "@d3mailconfigchecker/admin/inc/bootstrap.html.twig" %}
<form name="transfer" id="transfer" action="{{ oViewConf.getSelfLink()|raw }}" method="post">
{{ oViewConf.getHiddenSid()|raw }}
<input type="hidden" name="oxid" value="{{ oxid }}">
<input type="hidden" name="oxidCopy" value="{{ oxid }}">
<input type="hidden" name="cl" value="{{ oViewConf.getActiveClassName() }}">
<input type="hidden" name="editlanguage" value="{{ editlanguage }}">
</form>
<div class="row">
<div class="col-12 mb-4">
<h4>{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_HL" }) }}</h4>
{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_DESC" }) }}
</div>
</div>
<div class="row">
<div class="col-12 mb-4">
<div class="row">
{% for domain, spf in spf_result %}
<div class="col-12 col-md-6 col-lg-3">
<div class="card mb-3">
<div class="card-header text-white bg-{{ oView.getSpfStatusColor(spf) }}">
{{ domain }}
</div>
<div class="card-body">
<p>{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_"|cat(spf.getStatus())|upper }) }}</p>
{% if spf.getRecord() %}
<p>
<label for="{{ domain }}_record">{{ translate({ ident: "D3_MAILCHECKER_RECORD", suffix: "COLON" }) }}</label>
<input type="text" id="{{ domain }}_record" value="{{ spf.getRecord() }}" style="width: 50%;" readonly disabled>
</p>
{% endif %}
<h5>{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_LINKS" }) }}</h5>
<ul>
{% if spf.getRecord() %}
<li>
<a href="https://mxtoolbox.com/SuperTool.aspx?action=spf%3a{{ domain }}&run=toolpage">
{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_LINK_ANALYSIS" }) }}
</a>
</li>
{% else %}
<li>
<a href="https://mxtoolbox.com/SPFRecordGenerator.aspx?domain={{ domain }}&prefill=true">
{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_LINK_GENERATOR" }) }}
</a>
</li>
{% endif %}
<li>
<a href="https://mxtoolbox.com/SuperTool.aspx?action=blacklist%3a{{ domain }}&run=toolpage">
{{ translate({ ident: "D3_MAILCHECKER_SPFRESULT_LINK_BLACKLISTCHECK" }) }}
</a>
</li>
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="row">
<div class="col-12 mb-4">
<h4>{{ translate({ ident: "D3_MAILCHECKER_DMARCRESULT_HL" }) }}</h4>
{{ translate({ ident: "D3_MAILCHECKER_DMARCRESULT_DESC" }) }}
</div>
</div>
<div class="row">
<div class="col-12 mb-4">
<div class="row">
{% for domain, dmarc in dmarc_result %}
<div class="col-12 col-md-6 col-lg-3">
<div class="card mb-3">
<div class="card-header text-white bg-{{ oView.getDmarcStatusColor(dmarc) }}">
{{ domain }}
</div>
<div class="card-body">
<p>{{ translate({ ident: "D3_MAILCHECKER_DMARCRESULT_"|cat(dmarc.getStatus())|upper }) }}</p>
{% if dmarc.getRecord() %}
<p>
<label for="{{ domain }}_record">{{ translate({ ident: "D3_MAILCHECKER_RECORD", suffix: "COLON" }) }}</label>
<input type="text" id="{{ domain }}_record" value="{{ dmarc.getRecord() }}" style="width: 50%;" readonly disabled>
</p>
{% endif %}
<h5>{{ translate({ ident: "D3_MAILCHECKER_DMARCRESULT_LINKS" }) }}</h5>
<ul>
<li>
<a href="https://mxtoolbox.com/SuperTool.aspx?action=dmarc%3a{{ domain }}&run=toolpage">
{{ translate({ ident: "D3_MAILCHECKER_DMARCRESULT_LINK_ANALYSIS" }) }}
</a>
</li>
<li>
<a href="https://mxtoolbox.com/DMARCRecordGenerator.aspx?domain={{ domain }}&prefill=true">
{{ translate({ ident: "D3_MAILCHECKER_DMARCRESULT_LINK_GENERATOR" }) }}
</a>
</li>
</ul>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% include "bottomnaviitem.html.twig" %}
{% include "bottomitem.html.twig" %}