diff --git a/Engine/Modules/Core/Helper/Statics.php b/Engine/Modules/Core/Helper/Statics.php index 42e2e7d58..2ee5d49ab 100644 --- a/Engine/Modules/Core/Helper/Statics.php +++ b/Engine/Modules/Core/Helper/Statics.php @@ -36,7 +36,6 @@ class Statics { public const DB_CACHE_FILE = Statics::DB_CACHE_DIR . Statics::GLOBAL_SEPARATOR . "db.cache"; public const IMPORTS_DIR = Statics::GLOBAL_SEPARATOR . Statics::VAR_DIR . Statics::GLOBAL_SEPARATOR . "imports"; public const DEFAULT_THEME = "Base"; - //public const MAIL_TEMP_CACHE_DIR = Statics::CACHE_DIR . Statics::GLOBAL_SEPARATOR . 'mail'; /** * Relative path of logs folder. */ diff --git a/Engine/Modules/Cronjob/Commands/PingCommand.php b/Engine/Modules/Cronjob/Commands/PingCommand.php index c28747c4a..46bcf62b5 100644 --- a/Engine/Modules/Cronjob/Commands/PingCommand.php +++ b/Engine/Modules/Cronjob/Commands/PingCommand.php @@ -39,13 +39,13 @@ public function handle(Input $input, Logger $output) : void { $emailText = $configService->get("cronjob_ping_text"); if (!empty($email) && !empty($emailText)) { - $mailOptions = [ - 'from' => 'no_reply', + $mailConfig = [ + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), 'to' => [$email => $email], 'subject' => 'Ping ' . Oforge()->Settings()->get('host_url') , 'html' => $emailText, ]; - $mailService->send($mailOptions); + $mailService->send($mailConfig); } } diff --git a/Engine/Modules/Mailer/.meta/.phpstorm.meta.php b/Engine/Modules/Mailer/.meta/.phpstorm.meta.php new file mode 100644 index 000000000..d077d4a28 --- /dev/null +++ b/Engine/Modules/Mailer/.meta/.phpstorm.meta.php @@ -0,0 +1,20 @@ + \Oforge\Engine\Modules\Mailer\MailService::class, + // 'mail.list' => \Oforge\Engine\Modules\Mailer\MailingListService::class, + 'mail.inlineCss' => \Oforge\Engine\Modules\Mailer\InlineCssService::class, + ] + ) + ); + } +} diff --git a/Engine/Modules/Mailer/Bootstrap.php b/Engine/Modules/Mailer/Bootstrap.php index e2707c522..cc5f60c95 100644 --- a/Engine/Modules/Mailer/Bootstrap.php +++ b/Engine/Modules/Mailer/Bootstrap.php @@ -9,9 +9,6 @@ use Oforge\Engine\Modules\Core\Exceptions\ServiceNotFoundException; use Oforge\Engine\Modules\Core\Models\Config\ConfigType; use Oforge\Engine\Modules\Core\Services\ConfigService; -use Oforge\Engine\Modules\Mailer\Services\InlineCssService; -use Oforge\Engine\Modules\Mailer\Services\MailService; -use Oforge\Engine\Modules\Mailer\Services\MailingListService; use Oforge\Engine\Modules\I18n\Helper\I18N; /** @@ -19,13 +16,19 @@ * * @package Oforge\Engine\Modules\Mailer */ -class Bootstrap extends AbstractBootstrap { +class Bootstrap extends AbstractBootstrap +{ + + public function __construct() + { + // $this->models = [ + // Models\Mail::class, + // ]; - public function __construct() { $this->services = [ - 'mail' => MailService::class, - 'mailing.list' => MailingListService::class, - 'inline.css' => InlineCssService::class, + 'mail' => Services\MailService::class, + // 'mail.list' => Services\MailingListService::class, + 'mail.inlineCss' => Services\InlineCssService::class, ]; } @@ -35,196 +38,270 @@ public function __construct() { * @throws ConfigOptionKeyNotExistException * @throws ServiceNotFoundException */ - public function install() { - I18N::translate('config_mailer_host',[ - 'en' => 'Mailer Host', - 'de' => 'Mailer Host', - ]); - I18N::translate('config_mailer_port',[ - 'en' => 'Mailer Port', - 'de' => 'Mailer Port', - ]); - I18N::translate('config_mailer_smtp_username',[ - 'en' => 'SMTP Username', - 'de' => 'SMTP Benutzername', - ]); - I18N::translate('config_mailer_smtp_password',[ - 'en' => 'SMTP Password', - 'de' => 'SMTP Passwort', - ]); - I18N::translate('config_mailer_smtp_auth',[ - 'en' => 'Activate SMTP Authentication', - 'de' => 'Aktiviere SMTP Authentifizierung', - ]); - I18N::translate('config_mailer_smtp_secure',[ - 'en' => 'SMTP Encription (tls or ssl)', - 'de' => 'SMTP Verschlüsselung (tls oder ssl)', - ]); - I18N::translate('mailer_smtp_debug',[ - 'en' => 'SMTP Debug Level (0 - 4)', - 'de' => 'SMTP Debug Level (0 - 4)', - ]); - I18N::translate('config_mailer_exceptions',[ - 'en' => 'Mailer Exceptions', - 'de' => 'Mailer Exceptions', - ]); - I18N::translate('config_mailer_from_name',[ - 'en' => 'Sender Name', - 'de' => 'Absendername', - ]); - I18N::translate('config_mailer_from_host',[ - 'en' => 'Sender Hostname', - 'de' => 'Absender Hostname', - ]); - I18N::translate('config_mailer_from_host',[ - 'en' => 'Sender Hostname', - 'de' => 'Absender Hostname', - ]); - I18N::translate('config_mailer_from_info',[ - 'en' => 'Sender Prefix for Info Mails', - 'de' => 'Absender Präfix für Info-Mails', - ]); - I18N::translate('config_mailer_from_no_reply',[ - 'en' => 'Sender Prefix for No-Reply Mails', - 'de' => 'Absender Präfix für No-Reply Mails', - ]); - I18N::translate('config_mailer_redirect_outgoing_mail',[ - 'en' => 'redirect outgoing mail', - 'de' => 'Ausgehende Mails Umleiten', - ]); - I18N::translate('config_mailer_from_no_reply',[ - 'en' => 'recipient for outgoing mail', - 'de' => 'Empfänger für Umleitungen', - ]); + public function install() + { + I18N::translate( + 'config_mailer_smtp_host', + [ + 'en' => 'SMTP host', + 'de' => 'SMTP Host', + ] + ); + I18N::translate( + 'config_mailer_smtp_port', + [ + 'en' => 'SMTP port', + 'de' => 'SMTP Port', + ] + ); + I18N::translate( + 'config_mailer_smtp_username', + [ + 'en' => 'SMTP username', + 'de' => 'SMTP Benutzername', + ] + ); + I18N::translate( + 'config_mailer_smtp_password', + [ + 'en' => 'SMTP password', + 'de' => 'SMTP Passwort', + ] + ); + I18N::translate( + 'config_mailer_smtp_auth', + [ + 'en' => 'Activate SMTP authentication', + 'de' => 'Aktiviere SMTP Authentifizierung', + ] + ); + I18N::translate( + 'config_mailer_smtp_secure', + [ + 'en' => 'SMTP encryption (tls or ssl)', + 'de' => 'SMTP Verschlüsselung (tls oder ssl)', + ] + ); + I18N::translate( + 'config_mailer_smtp_debug', + [ + 'en' => 'SMTP Debug Level (0 - 4)', + 'de' => 'SMTP Debug Level (0 - 4)', + ] + ); + I18N::translate( + 'config_mailer_throw_exceptions', + [ + 'en' => 'Using exceptions', + 'de' => 'Verwenden von Exceptions', + ] + ); + I18N::translate( + 'config_mailer_from_builder_name', + [ + 'en' => 'From builder: Name', + 'de' => 'Absender-Builder: Name', + ] + ); + I18N::translate( + 'config_mailer_from_builder_mail_host', + [ + 'en' => 'From builder: Mail host', + 'de' => 'Absender-Builder: Mail-Host', + ] + ); + I18N::translate( + 'config_mailer_from_builder_mail_prefix_info', + [ + 'en' => 'From builder: Mail prefix for info mails', + 'de' => 'Absender-Builder: Mail-Prefix für Info-Mails', + ] + ); + I18N::translate( + 'config_mailer_from_builder_mail_prefix_no_reply', + [ + 'en' => 'From builder: Mail-Prefix for no-reply mails', + 'de' => 'Absender-Builder: Mail-Prefix für No-Reply Mails', + ] + ); + I18N::translate( + 'config_mailer_dev_redirect_enabled', + [ + 'en' => 'Dev: Redirect outgoing mail', + 'de' => 'Dev: Ausgehende Mails umleiten', + ] + ); + I18N::translate( + 'config_mailer_dev_redirect_to', + [ + 'en' => 'Dev: Recipient for mail redirects', + 'de' => 'Dev: Empfänger für Mail-Umleitungen', + ] + ); + I18N::translate( + 'config_mailer_dev_redirect_to', + [ + 'en' => 'recipient for outgoing mail', + 'de' => 'Dev: Empfänger für Mail-Umleitungen', + ] + ); /** @var ConfigService $configService */ $configService = Oforge()->Services()->get('config'); - - $configService->add([ - 'name' => 'redirect_outgoing_mail', - 'type' => ConfigType::BOOLEAN, - 'group' => 'mailer', - 'default' => false, - 'label' => 'config_redirect_outgoing_mail', - 'required' => true, - 'order' => 0, - ]); - $configService->add([ - 'name' => 'redirect_recipient', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => '', - 'label' => 'config_redirect_recipient', - 'required' => false, - 'order' => 1, - ]); - $configService->add([ - 'name' => 'mailer_host', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => '', - 'label' => 'config_mailer_host', - 'required' => true, - 'order' => 2, - ]); - $configService->add([ - 'name' => 'mailer_port', - 'type' => ConfigType::INTEGER, - 'group' => 'mailer', - 'default' => 25, - 'label' => 'config_mailer_port', - 'required' => true, - 'order' => 3, - ]); - $configService->add([ - 'name' => 'mailer_smtp_username', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => '', - 'label' => 'config_mailer_smtp_username', - 'required' => true, - 'order' => 4, - ]); - $configService->add([ - 'name' => 'mailer_smtp_password', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => '', - 'label' => 'config_mailer_smtp_password', - 'required' => true, - 'order' => 5, - ]); - $configService->add([ - 'name' => 'mailer_smtp_secure', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => 'tls', - 'label' => 'config_mailer_smtp_secure', - 'required' => true, - 'order' => 6, - ]); - $configService->add([ - 'name' => 'mailer_smtp_auth', - 'type' => ConfigType::BOOLEAN, - 'group' => 'mailer', - 'default' => true, - 'label' => 'config_mailer_smtp_auth', - 'required' => true, - 'order' => 7, - ]); - $configService->add([ - 'name' => 'mailer_smtp_debug', - 'type' => ConfigType::INTEGER, - 'group' => 'mailer', - 'default' => 2, - 'label' => 'config_mailer_smtp_debug', - 'required' => true, - 'order' => 8, - ]); - $configService->add([ - 'name' => 'mailer_exceptions', - 'type' => ConfigType::BOOLEAN, - 'group' => 'mailer', - 'default' => true, - 'label' => 'config_mailer_exceptions', - 'required' => true, - 'order' => 8, - ]); - $configService->add([ - 'name' => 'mailer_from_name', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => '', - 'label' => 'config_mailer_from_name', - 'required' => false, - 'order' => 9 - ]); - $configService->add([ - 'name' => 'mailer_from_host', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => '', - 'label' => 'config_mailer_from_host', - 'required' => true, - 'order' => 10, - ]); - $configService->add([ - 'name' => 'mailer_from_info', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => 'info', - 'label' => 'config_mailer_from_info', - 'required' => false, - 'order' => 11, - ]); - $configService->add([ - 'name' => 'mailer_from_no_reply', - 'type' => ConfigType::STRING, - 'group' => 'mailer', - 'default' => 'no-reply', - 'label' => 'config_mailer_from_no_reply', - 'required' => false, - 'order' => 12, - ]); + $configService->add( + [ + 'name' => 'mailer_dev_redirect_enabled', + 'type' => ConfigType::BOOLEAN, + 'group' => 'mailer', + 'default' => false, + 'label' => 'config_mailer_dev_redirect_enabled', + 'required' => false, + 'order' => 0, + ] + ); + $configService->add( + [ + 'name' => 'mailer_dev_redirect_to', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => '', + 'label' => 'config_mailer_dev_redirect_to', + 'required' => false, + 'order' => 1, + ] + ); + $configService->add( + [ + 'name' => 'mailer_smtp_host', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => '', + 'label' => 'config_mailer_smtp_host', + 'required' => true, + 'order' => 2, + ] + ); + $configService->add( + [ + 'name' => 'mailer_smtp_port', + 'type' => ConfigType::INTEGER, + 'group' => 'mailer', + 'default' => 25, + 'label' => 'config_mailer_smtp_port', + 'required' => true, + 'order' => 3, + ] + ); + $configService->add( + [ + 'name' => 'mailer_smtp_username', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => '', + 'label' => 'config_mailer_smtp_username', + 'required' => true, + 'order' => 4, + ] + ); + $configService->add( + [ + 'name' => 'mailer_smtp_password', + 'type' => ConfigType::STRING,#ConfigType::PASSWORD,# (sometimes) encryption problems + 'group' => 'mailer', + 'default' => '', + 'label' => 'config_mailer_smtp_password', + 'required' => true, + 'order' => 5, + ] + ); + $configService->add( + [ + 'name' => 'mailer_smtp_secure', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => 'tls', + 'label' => 'config_mailer_smtp_secure', + 'required' => true, + 'order' => 6, + ] + ); + $configService->add( + [ + 'name' => 'mailer_smtp_auth', + 'type' => ConfigType::BOOLEAN, + 'group' => 'mailer', + 'default' => true, + 'label' => 'config_mailer_smtp_auth', + 'required' => false, + 'order' => 7, + ] + ); + $configService->add(//TODO not used, usage? + [ + 'name' => 'mailer_smtp_debug', + 'type' => ConfigType::INTEGER, + 'group' => 'mailer', + 'default' => 2, + 'label' => 'config_mailer_smtp_debug', + 'required' => true, + 'order' => 8, + ] + ); + $configService->add( + [ + 'name' => 'mailer_throw_exceptions', + 'type' => ConfigType::BOOLEAN, + 'group' => 'mailer', + 'default' => true, + 'label' => 'config_mailer_throw_exceptions', + 'required' => false, + 'order' => 8, + ] + ); + $configService->add( + [ + 'name' => 'mailer_from_builder_name', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => '', + 'label' => 'config_mailer_from_builder_name', + 'required' => false, + 'order' => 9, + ] + ); + $configService->add( + [ + 'name' => 'mailer_from_builder_mail_host', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => '', + 'label' => 'config_mailer_from_builder_mail_host', + 'required' => true, + 'order' => 10, + ] + ); + $configService->add( + [ + 'name' => 'mailer_from_builder_mail_prefix_info', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => 'info', + 'label' => 'config_mailer_from_builder_mail_prefix_info', + 'required' => false, + 'order' => 11, + ] + ); + $configService->add( + [ + 'name' => 'mailer_from_builder_mail_prefix_no_reply', + 'type' => ConfigType::STRING, + 'group' => 'mailer', + 'default' => 'no-reply', + 'label' => 'config_mailer_from_builder_mail_prefix_no_reply', + 'required' => false, + 'order' => 12, + ] + ); } + } diff --git a/Engine/Modules/Mailer/Library/OforgePHPMailer.php b/Engine/Modules/Mailer/Library/OforgePHPMailer.php new file mode 100644 index 000000000..621768e5f --- /dev/null +++ b/Engine/Modules/Mailer/Library/OforgePHPMailer.php @@ -0,0 +1,36 @@ +Settings()->get('Modules.Mailer.mode', 'send'); + if ($sendMode === 'file') { + $message = $this->getSentMIMEMessage(); + $filepath = self::DIR_MAILS . Statics::GLOBAL_SEPARATOR . date('Y_m_d_H_i_s') . '.eml'; + FileSystemHelper::mkdir(self::DIR_MAILS); + file_put_contents($filepath, $message); + + return file_exists($filepath); + } else { + return parent::postSend(); + } + } + +} diff --git a/Engine/Modules/Mailer/Services/InlineCssService.php b/Engine/Modules/Mailer/Services/InlineCssService.php index 17f96850b..b3e35fb0c 100644 --- a/Engine/Modules/Mailer/Services/InlineCssService.php +++ b/Engine/Modules/Mailer/Services/InlineCssService.php @@ -4,24 +4,30 @@ use Pelago\Emogrifier; -class InlineCssService { +/** + * Class InlineCssService + * + * @package Oforge\Engine\Modules\Mailer\Services + */ +class InlineCssService +{ + /** * HTML / CSS input needs to be UTF-8 encoded. * - * @param $html - * @param $css + * @param string $html + * @param string|null $css * * @return string HTML with inline-CSS */ - public function renderInlineCss($html, $css = null) { - - /** @var $cssInliner */ - $cssInliner = new Emogrifier($html); - - if(isset($css)) { - $cssInliner->setCss($css); + public function inline(string $html, ?string $css = null) : string + { + $emogrifier = new Emogrifier($html); + if ($css !== null) { + $emogrifier->setCss($css); } - return $cssInliner->emogrify(); + return $emogrifier->emogrify(); } -} \ No newline at end of file + +} diff --git a/Engine/Modules/Mailer/Services/MailService.php b/Engine/Modules/Mailer/Services/MailService.php index e7da1e471..9131cbcab 100644 --- a/Engine/Modules/Mailer/Services/MailService.php +++ b/Engine/Modules/Mailer/Services/MailService.php @@ -2,446 +2,374 @@ namespace Oforge\Engine\Modules\Mailer\Services; +use Doctrine\ORM\OptimisticLockException; use Doctrine\ORM\ORMException; -use FrontendUserManagement\Models\User; -use FrontendUserManagement\Services\UserService; -use Insertion\Models\Insertion; -use Insertion\Services\InsertionService; +use Exception; use InvalidArgumentException; use Oforge\Engine\Modules\Core\Exceptions\ConfigElementNotFoundException; use Oforge\Engine\Modules\Core\Exceptions\ConfigOptionKeyNotExistException; use Oforge\Engine\Modules\Core\Exceptions\ServiceNotFoundException; -use Oforge\Engine\Modules\Core\Helper\ArrayHelper; +use Oforge\Engine\Modules\Core\Exceptions\Template\TemplateNotFoundException; use Oforge\Engine\Modules\Core\Helper\Statics; +use Oforge\Engine\Modules\Core\Models\Plugin\Plugin; use Oforge\Engine\Modules\Core\Services\ConfigService; -use Oforge\Engine\Modules\I18n\Helper\I18N; +use Oforge\Engine\Modules\Mailer\Library\OforgePHPMailer; use Oforge\Engine\Modules\Media\Twig\MediaExtension; +use Oforge\Engine\Modules\TemplateEngine\Core\Services\TemplateManagementService; use Oforge\Engine\Modules\TemplateEngine\Core\Twig\CustomTwig; use Oforge\Engine\Modules\TemplateEngine\Core\Twig\TwigOforgeDebugExtension; use Oforge\Engine\Modules\TemplateEngine\Extensions\Twig\AccessExtension; use Oforge\Engine\Modules\TemplateEngine\Extensions\Twig\SlimExtension; -use PHPMailer\PHPMailer\Exception; -use PHPMailer\PHPMailer\PHPMailer; use Twig_Error_Loader; use Twig_Error_Runtime; use Twig_Error_Syntax; +use Twig_Loader_Filesystem; /** * Class MailService * * @package Oforge\Engine\Modules\Mailer\Services */ -class MailService { +class MailService +{ + private $mailerTwig; + private $cacheBuildFrom = []; /** * Initialises PHP Mailer instance with specified mailer options and template data. - * Options = [ - * 'to' => ['user@host.de' => 'user_name', user2@host.de => 'user2_name, ...], - * 'cc' => [], - * 'bcc' => [], - * 'replyTo' => [], - * 'attachment' => [], - * 'subject' => string, - * 'template' => string, // Twig template file name (with extension) - * 'html' => string, // Html body - * 'body' => string, // Raw text mail - * ] + * Config = [ + * 'from' => ['mail' => '...', 'name' => '...'], + * 'to' => ['user@host.de' => 'user_name', user2@host.de => 'user2_name, ...], + * 'cc' => [], // like 'to' + * 'bcc' => [], // like 'to' + * 'replyTo' => [], // like 'to' + * 'attachment' => [path => filename], + * 'subject' => string, + * 'template' => string, // Twig template file name (with extension) + * 'html' => string, // Html body + * 'text' => string, // Raw text mail + * ] * TemplateData = ['key' = value, ... ] * - * @param array $options + * @param array $config * @param array $templateData * * @return bool - * @throws ConfigElementNotFoundException * @throws ConfigOptionKeyNotExistException - * @throws ServiceNotFoundException - * @throws Twig_Error_Loader - * @throws Twig_Error_Runtime - * @throws Twig_Error_Syntax */ - public function send(array $options, array $templateData = []) { - if ($this->isValid($options)) { - try { - /** @var $configService */ - $configService = Oforge()->Services()->get('config'); - $exceptions = $configService->get('mailer_exceptions'); - - /** @var PHPMailer $mail */ - $mail = new PHPMailer($exceptions); - - /** Mailer Settings */ - $mail->isSMTP(); - $mail->setFrom($this->getSenderAddress($options['from']), $configService->get('mailer_from_name')); - $mail->Host = $configService->get('mailer_host'); - $mail->Username = $configService->get('mailer_smtp_username'); - $mail->Port = $configService->get('mailer_port'); - $mail->SMTPAuth = $configService->get('mailer_smtp_auth'); - $mail->Password = $configService->get('mailer_smtp_password'); - $mail->SMTPSecure = $configService->get('mailer_smtp_secure'); - $mail->Encoding = 'base64'; - $mail->CharSet = 'UTF-8'; + public function send(array $config, array $templateData = []) : bool + { + $this->validateConfig($config); + try { + /** @var ConfigService $configService */ + $configService = Oforge()->Services()->get('config'); + $configThrowExceptions = $configService->get('mailer_throw_exceptions'); + $logger = Oforge()->Logger()->get('mailer'); + + $mailer = new OforgePHPMailer($configThrowExceptions); + $mailer->isSMTP(); + $mailer->SMTPDebug = $configService->get('mailer_smtp_debug'); + $mailer->Host = $configService->get('mailer_smtp_host'); + $mailer->Username = $configService->get('mailer_smtp_username'); + $mailer->Port = $configService->get('mailer_smtp_port'); + $mailer->SMTPAuth = $configService->get('mailer_smtp_auth'); + $mailer->Password = $configService->get('mailer_smtp_password'); + $mailer->SMTPSecure = $configService->get('mailer_smtp_secure'); + $mailer->Encoding = 'base64'; + $mailer->CharSet = 'UTF-8'; + if ($mailer->SMTPDebug > 0) { + $mailer->Debugoutput = function (string $string, int $level) use ($logger) { + $logger->debug("$level\t$string"); + }; + } - /** Add Recipients ({to,cc,bcc}Addresses) */ - $redirect = $configService->get('redirect_outgoing_mail'); - if ($redirect == true) { - $recipient = $configService->get('redirect_recipient'); - if (isset($recipient) && !empty($recipient)) { - $mail->addAddress($recipient, 'dev'); + //region # addresses + if (isset($config['from'])) { + $mailer->setFrom($config['from']['mail'], $config['from']['name'] ?? ''); + } - } else { - Oforge()->Logger()->get('mailer')->error('Could not redirect message, recipient not set in mailer backend options!'); - } + $devRedirectEnabled = $configService->get('mailer_dev_redirect_enabled'); + if ($devRedirectEnabled === true) { + $devRedirectTo = $configService->get('mailer_dev_redirect_to'); + if (empty($devRedirectTo)) { + Oforge()->Logger()->get('mailer')->error('Could not redirect message, recipient not set in mailer backend options!'); } else { - foreach ($options['to'] as $key => $value) { - $mail->addAddress($key, $value); - } + $mailer->addAddress($devRedirectTo, 'dev'); } - - if (isset($options['cc'])) { - foreach ($options['cc'] as $key => $value) { - $mail->addCC($key, $value); - } - } - if (isset($options['bcc'])) { - foreach ($options['bcc'] as $key => $value) { - $mail->addBCC($key, $value); - } + } else { + foreach ($config['to'] as $key => $value) { + $mailer->addAddress($key, $value); } - if (isset($options['replyTo'])) { - foreach ($options['replyTo'] as $key => $value) { - $mail->addReplyTo($key, $value); - } - } - - /** Add Attachments: */ - if (isset($options['attachment'])) { - foreach ($options['attachment'] as $key => $value) { - $mail->addAttachment($key, $value); + } + $headers = [ + 'cc' => 'addCC', + 'bcc' => 'addBCC', + 'replyTo' => 'addReplyTo', + ]; + foreach ($headers as $headerKey => $headerMethod) { + if (isset($config[$headerKey])) { + foreach ($config[$headerKey] as $key => $value) { + $mailer->$headerMethod($key, $value); + // $mailer->addCC($key, $value); + // $mailer->addBCC($key, $value); + // $mailer->addReplyTo($key, $value); } } - /** Generate Base-Url for Media */ - $conversationLink = 'http://'; - if (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') { - $conversationLink = 'https://'; - } - - if (isset($_SERVER['HTTP_HOST'])) { - $conversationLink .= $_SERVER['HTTP_HOST']; - $templateData['baseUrl'] = $conversationLink; - } + } + //endregion - if (isset($options['template'])) { - /** Render HTML */ - $renderedTemplate = $this->renderMail($options, $templateData); - $mail->isHTML(true); - } elseif (isset($options['html'])) { - $renderedTemplate = $options['html']; - $mail->isHTML(true); - } elseif (isset($options['text'])) { - $renderedTemplate = $options['text']; - $mail->isHTML(false); + // Attachments + if (isset($config['attachment'])) { + foreach ($config['attachment'] as $key => $value) { + $mailer->addAttachment($key, $value); } - - /** Add Content */ - $mail->Subject = $options['subject']; - $mail->Body = $renderedTemplate; - - $mail->send(); - - if ($redirect == true) { - Oforge()->Logger()->get('mailer')->info('Message has been redirected', [$mail->getToAddresses(), $options, $templateData]); + } + // BaseUrl for Media + if ( !isset($templateData['baseUrl'])) { + $baseUrl = Oforge()->View()->get('meta.route.baseUrl'); + if ($baseUrl === null) { + $conversationLink = 'http://'; + if ( !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') { + $conversationLink = 'https://'; + } + if (isset($_SERVER['HTTP_HOST'])) { + $conversationLink .= $_SERVER['HTTP_HOST']; + $templateData['baseUrl'] = $conversationLink; + } } else { - Oforge()->Logger()->get('mailer')->info('Message has been sent', [$options, $templateData]); + $templateData['baseUrl'] = $baseUrl; } - - return true; - - } catch (Exception $e) { - Oforge()->Logger()->get('mailer')->error('Message has not been sent', [$mail->ErrorInfo]); - - return false; } - } - - return false; - } - /** - * Loads minimal twig environment and returns rendered HTML-template with inlined CSS from active theme. - * If specified template does not exists in active theme -> fallback to base theme - * - * @param array $options - * @param array $templateData - * - * @return string - * @throws ServiceNotFoundException - * @throws Twig_Error_Loader - * @throws Twig_Error_Runtime - * @throws Twig_Error_Syntax - */ - public function renderMail(array $options, array $templateData) { - $templateManagementService = Oforge()->Services()->get('template.management'); - $templateName = $templateManagementService->getActiveTemplate()->getName(); - $templatePath = Statics::TEMPLATE_DIR . Statics::GLOBAL_SEPARATOR . $templateName . Statics::GLOBAL_SEPARATOR . 'MailTemplates'; + $mailer->isHTML(true); + if (isset($config['template'])) { + /** Render HTML */ + $body = $this->renderTemplate($config, $templateData); + } elseif (isset($config['html'])) { + //TODO templateData placeholder replacing + $body = $config['html']; + } elseif (isset($config['text'])) { + //TODO templateData placeholder replacing + $mailer->isHTML(false); + $body = $config['text']; + } else { + $body = ''; + } + $mailer->Body = $body; + $mailer->Subject = $config['subject']; - if (!file_exists($templatePath . Statics::GLOBAL_SEPARATOR . $options['template'])) { - $templatePath = Statics::TEMPLATE_DIR . Statics::GLOBAL_SEPARATOR . Statics::DEFAULT_THEME . Statics::GLOBAL_SEPARATOR . 'MailTemplates'; - } + $success = $mailer->send(); + if ($mailer->SMTPDebug > 0) { + $logger->debug("--------------------------------------------------------------------------------"); + } + if ($devRedirectEnabled == true) { + Oforge()->Logger()->get('mailer')->info('Message has been redirected', [$mailer->getToAddresses(), $config, $templateData]); + } else { + Oforge()->Logger()->get('mailer')->info('Message has been sent', [$config, $templateData]); + } - $twig = new CustomTwig($templatePath, ['cache' => ROOT_PATH . Statics::GLOBAL_SEPARATOR . Statics::CACHE_DIR . '/mailer']); - try { - Oforge()->Services()->get('cms'); - $cmsTwigExtension = '\CMS\Twig\CmsTwigExtension'; - $twig->addExtension(new $cmsTwigExtension()); + return $success; } catch (Exception $exception) { - // nothing to do - } - $twig->addExtension(new AccessExtension()); - $twig->addExtension(new MediaExtension()); - $twig->addExtension(new SlimExtension()); - $twig->addExtension(new TwigOforgeDebugExtension()); + Oforge()->Logger()->get('mailer')->error('Message has not been sent', [isset($mailer) ? $mailer->ErrorInfo : $exception->getMessage()]); - /** @var string $html */ - $html = $twig->fetch($template = $options['template'], $data = $templateData); - - /** @var $inlineCssService */ - $inlineCssService = Oforge()->Services()->get('inline.css'); - - return $inlineCssService->renderInlineCss($html); + return false; + } } /** * Looks up mailer backend options for custom sender and host information. * - * @param string $key + * @param string $configFromMailPrefix * - * @return string + * @return array * @throws ConfigElementNotFoundException * @throws ServiceNotFoundException */ - public function getSenderAddress($key = 'info') { + public function buildFromConfigByPrefix($configFromMailPrefix = 'info') : array + { $configService = Oforge()->Services()->get('config'); - $host = $configService->get('mailer_from_host'); - if (!$host) { - throw new InvalidArgumentException('Error: Host is not set'); - } - $sender = $configService->get('mailer_from_' . $key); - - $senderAddress = $sender . '@' . $host; - - return $senderAddress; - } - - /** - * @param $userId - * @param $conversationId - * - * @return bool - * @throws ConfigElementNotFoundException - * @throws ConfigOptionKeyNotExistException - * @throws ORMException - * @throws ServiceNotFoundException - * @throws Twig_Error_Loader - * @throws Twig_Error_Runtime - * @throws Twig_Error_Syntax - */ - public function sendNewMessageInfoMail($userId, $conversationId) { - /** @var UserService $userService */ - $userService = Oforge()->Services()->get('frontend.user.management.user'); - - /** @var User $user */ - $user = $userService->getUserById($userId); - - $userMail = $user->getEmail(); - $mailerOptions = [ - 'to' => [$userMail => $userMail], - 'from' => 'no_reply', - 'subject' => I18N::translate('mailer_subject_new_message'), - 'template' => 'NewMessage.twig', - ]; - $templateData = [ - 'conversationId' => $conversationId, - 'receiver_name' => $user->getDetail()->getNickName(), - 'sender_mail' => $this->getSenderAddress('no_reply'), + return [ + 'mail' => $this->buildFromMailByPrefix($configFromMailPrefix), + 'name' => $configService->get('mailer_from_builder_name') ?? '', ]; - - return $this->send($mailerOptions, $templateData); } /** - * @param $insertionId + * Looks up mailer backend options for custom sender and host information. * - * @return bool - * @throws ConfigElementNotFoundException - * @throws ConfigOptionKeyNotExistException - * @throws ORMException - * @throws ServiceNotFoundException - * @throws Twig_Error_Loader - * @throws Twig_Error_Runtime - * @throws Twig_Error_Syntax - */ - public function sendInsertionApprovedInfoMail($insertionId) { - /** @var InsertionService $insertionService */ - $insertionService = Oforge()->Services()->get('insertion'); - - /** @var Insertion $insertion */ - $insertion = $insertionService->getInsertionById($insertionId); - - /** @var User $user */ - $user = $insertion->getUser(); - $userMail = $user->getEmail(); - - $mailerOptions = [ - 'to' => [$userMail => $userMail], - 'from' => 'no_reply', - 'subject' => I18N::translate('mailer_subject_insertion_approved'), - 'template' => 'InsertionApproved.twig', - ]; - $templateData = [ - 'insertionId' => $insertionId, - // TODO: add title 'insertionTitle' => $insertion->getContent(), - 'receiver_name' => $user->getDetail()->getNickName(), - 'sender_mail' => $this->getSenderAddress('no_reply'), - ]; - - return $this->send($mailerOptions, $templateData); - } - - /** - * @param $userId - * @param $newResultsCount - * @param $searchLink + * @param string $configFromMailPrefix * - * @return bool + * @return string * @throws ConfigElementNotFoundException - * @throws ConfigOptionKeyNotExistException - * @throws ORMException * @throws ServiceNotFoundException - * @throws Twig_Error_Loader - * @throws Twig_Error_Runtime - * @throws Twig_Error_Syntax */ - public function sendNewSearchResultsInfoMail($userId, $newResultsCount, $searchLink) { - /** @var UserService $userService */ - $userService = Oforge()->Services()->get('frontend.user.management.user'); - - /** @var User $user */ - $user = $userService->getUserById($userId); - $userMail = $user->getEmail(); + public function buildFromMailByPrefix($configFromMailPrefix = 'info') : string + { + if ( !isset($this->cacheBuildFrom[$configFromMailPrefix])) { + $configService = Oforge()->Services()->get('config'); - $mailerOptions = [ - 'to' => [$userMail => $userMail], - 'from' => 'no_reply', - 'subject' => I18N::translate('mailer_subject_new_search_results'), - 'template' => 'NewSearchResults.twig', - ]; - $templateData = [ - 'resultCount' => $newResultsCount, - 'searchLink' => $searchLink, - 'sender_mail' => $this->getSenderAddress('no_reply'), - 'receiver_name' => $user->getDetail()->getNickName(), - ]; + $mailHost = $configService->get('mailer_from_builder_mail_host'); + if (empty($mailHost)) { + throw new InvalidArgumentException("Error: Builder value 'mailHost' is not set"); + } + $mailPrefix = $configService->get('mailer_from_builder_mail_prefix_' . $configFromMailPrefix); + if (empty($mailPrefix)) { + throw new InvalidArgumentException("Error: Builder value 'mailPrefix' is not set"); + } + $this->cacheBuildFrom[$configFromMailPrefix] = ($mailPrefix . '@' . $mailHost); + } - return $this->send($mailerOptions, $templateData); + return $this->cacheBuildFrom[$configFromMailPrefix]; } /** - * @param User $user - * @param Insertion $insertion + * Loads minimal twig environment and returns rendered HTML-template with inlined CSS from active theme. + * If specified template does not exists in active theme -> fallback to base theme * - * @throws ConfigElementNotFoundException - * @throws ConfigOptionKeyNotExistException + * @param array $config + * @param array $templateData + * + * @return string + * @throws ORMException * @throws ServiceNotFoundException * @throws Twig_Error_Loader * @throws Twig_Error_Runtime * @throws Twig_Error_Syntax + * @throws OptimisticLockException + * @throws TemplateNotFoundException */ - public function sendInsertionCreateInfoMail(User $user, Insertion $insertion) { - $userMail = $user->getEmail(); - $mailerOptions = [ - 'to' => [$userMail => $userMail], - 'from' => 'no_reply', - 'subject' => I18N::translate('mailer_subject_insertion_created', 'Insertion was created'), - 'template' => 'InsertionCreated.twig', - ]; - $templateData = [ - 'insertionId' => $insertion->getId(), - 'insertionTitle' => $insertion->getContent()[0]->getTitle(), - 'receiver_name' => $user->getDetail()->getNickName(), - 'sender_mail' => $this->getSenderAddress('no_reply'), - ]; - $this->send($mailerOptions, $templateData); - - try { - I18N::translate('mailer_insertion_waiting_for_moderating_btn', [ - 'en'=> 'moderate', - 'de' => 'moderieren', - ]); - /** @var ConfigService $configService */ - $configService = Oforge()->Services()->get('config'); - $moderatorMail = $configService->get('insertions_creation_moderator_mail'); - $moderatorName = $configService->get('insertions_creation_moderator_name'); - if (!empty($moderatorMail)) { - if (empty($moderatorName)) { - $moderatorName = $moderatorMail; + public function renderTemplate(array $config, array $templateData) : string + { + if ( !isset($this->mailerTwig)) { + /** @var TemplateManagementService $templateManagementService */ + $templateManagementService = Oforge()->Services()->get('template.management'); + $templateName = $templateManagementService->getActiveTemplate()->getName(); + // $templatePath = Statics::TEMPLATE_DIR . Statics::GLOBAL_SEPARATOR . $templateName . Statics::GLOBAL_SEPARATOR . 'MailTemplates'; + // + // if ( !file_exists($templatePath . Statics::GLOBAL_SEPARATOR . $config['template'])) { + // $templatePath = Statics::TEMPLATE_DIR . Statics::GLOBAL_SEPARATOR . Statics::DEFAULT_THEME . Statics::GLOBAL_SEPARATOR . 'MailTemplates'; + // } + // //TODO Problem: aktuell keine MailTemplates per Plugins möglich!!! + //TODO REFACTORING: Generic Twig Instance by TemplateRenderService method + + $paths = [ + Twig_Loader_Filesystem::MAIN_NAMESPACE => [], + ]; + $mainPaths = []; + $baseThemePath = join(Statics::GLOBAL_SEPARATOR, [ROOT_PATH, Statics::TEMPLATE_DIR, Statics::DEFAULT_THEME, 'MailTemplates']); + $currentThemePath = join(Statics::GLOBAL_SEPARATOR, [ROOT_PATH, Statics::TEMPLATE_DIR, $templateName, 'MailTemplates']); + if ($currentThemePath !== $baseThemePath) { + $mainPaths[] = $currentThemePath; + } + try { + /** @var Plugin[] $plugins */ + $plugins = Oforge()->Services()->get('plugin.access')->getActive(); + foreach ($plugins as $plugin) { + $pluginName = $plugin['name']; + $pluginPath = join( + Statics::GLOBAL_SEPARATOR, + [ROOT_PATH, Statics::PLUGIN_DIR, $pluginName, Statics::VIEW_DIR, $pluginName, 'MailTemplates'] + ); + if (file_exists($pluginPath)) { + $mainPaths[] = $pluginPath; + $tmp = $paths[$pluginName] ?? []; + $tmp[] = $pluginPath; + $paths[$pluginName] = $tmp; + } } - $mailerOptions = [ - 'to' => [$moderatorMail => $moderatorName], - 'from' => 'no_reply', - 'subject' => I18N::translate('mailer_subject_insertion_waiting_for_moderating', [ - 'en' => 'A new insertion is waiting for moderation', - 'de' => 'Ein neues Inserat wartet auf Moderation', - ]), - 'template' => 'InsertionWaitingForModerating.twig', - ]; - $templateData = [ - 'insertionID' => $insertion->getId(), - 'insertionTitle' => $insertion->getContent()[0]->getTitle(), - 'sender_mail' => $this->getSenderAddress('no_reply'), - ]; - $this->send($mailerOptions, $templateData); + } catch (Exception $exception) { + Oforge()->Logger()->logException($exception); + } + $mainPaths[] = $baseThemePath; + + $paths[Twig_Loader_Filesystem::MAIN_NAMESPACE] = $mainPaths; + + // $twig = new CustomTwig($templatePath, ['cache' => ROOT_PATH . Statics::GLOBAL_SEPARATOR . Statics::CACHE_DIR . '/mailer']); + $devMode = Oforge()->Settings()->isDevelopmentMode(); + $twig = new CustomTwig( + $paths,# + [ + 'cache' => join(Statics::GLOBAL_SEPARATOR, [ROOT_PATH, Statics::CACHE_DIR, 'mailer']), + 'auto_reload' => $devMode, + 'debug' => $devMode, + ] + ); + if ($devMode) { + $twig->getEnvironment()->enableDebug(); } - } catch (\Exception $exception) { - Oforge()->Logger()->logException($exception); + try { + Oforge()->Services()->get('cms'); + $cmsTwigExtension = '\CMS\Twig\CmsTwigExtension'; + $twig->addExtension(new $cmsTwigExtension()); + } catch (Exception $exception) { + // nothing to do + } + $twig->addExtension(new AccessExtension()); + $twig->addExtension(new MediaExtension()); + $twig->addExtension(new SlimExtension()); + $twig->addExtension(new TwigOforgeDebugExtension()); + + $this->mailerTwig = $twig; } + $html = $this->mailerTwig->fetch($config['template'], $templateData); + /** @var InlineCssService $inlineCssService */ + $inlineCssService = Oforge()->Services()->get('mail.inlineCss'); + + return $inlineCssService->inline($html); } /** - * @param array $options + * @param array $config * - * @return bool * @throws ConfigOptionKeyNotExistException */ - private function isValid(array $options) : bool { + protected function validateConfig(array &$config) + { + // required fields $keys = ['to', 'subject']; foreach ($keys as $key) { - if (!isset($options[$key])) { + if ( !isset($config[$key])) { throw new ConfigOptionKeyNotExistException($key); } } - /** Validate Mail Addresses */ - $emailKeys = ['to', 'cc', 'bcc', 'replyTo']; - foreach ($emailKeys as $key) { - if (array_key_exists($key, $options)) { - if (is_array($options[$key])) { - foreach ($options[$key] as $email => $name) { - if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - Oforge()->Logger()->logException(new InvalidArgumentException("$email is not a valid email.")); + if (isset($config['from'])) { + $tmp = $config['from']; + if (is_string($tmp)) { + $tmp = ['mail' => $tmp, 'name' => '']; + } + $tmp['name'] = $tmp['name'] ?? $tmp['mail']; + $keys = ['mail', 'name']; + foreach ($keys as $key) { + if ( !isset($tmp[$key])) { + throw new ConfigOptionKeyNotExistException($key); + } + } + if ( !filter_var($tmp['mail'], FILTER_VALIDATE_EMAIL)) { + throw new InvalidArgumentException( + sprintf("Value of config 'from.mail' is not valid valid email ('%s').", $tmp['mail']) + ); + } + $config['from'] = $tmp; + } - return false; - } + /** Validate Mail Addresses */ + $keys = ['to', 'cc', 'bcc', 'replyTo']; + foreach ($keys as $key) { + if (isset($config[$key])) { + if (is_string($config[$key])) { + $config[$key] = [ + $config[$key] => $config[$key], + ]; + } + foreach ($config[$key] as $email => $name) { + if ( !filter_var($email, FILTER_VALIDATE_EMAIL)) { + throw new InvalidArgumentException("Value of config '$key' has an not valid valid email ('$email')."); } - } else { - // Argument is not an Array - Oforge()->Logger()->logException(new InvalidArgumentException("Expected array for $key but get " . gettype($options[$key]))); - return false; } } } - - return true; } } diff --git a/Engine/Modules/Mailer/Models/Mail.php b/Engine/Modules/Mailer/backup/Mail.php similarity index 96% rename from Engine/Modules/Mailer/Models/Mail.php rename to Engine/Modules/Mailer/backup/Mail.php index 3fcbcfe05..05b4fcb9d 100644 --- a/Engine/Modules/Mailer/Models/Mail.php +++ b/Engine/Modules/Mailer/backup/Mail.php @@ -1,6 +1,6 @@ \Oforge\Engine\Modules\Mailer\MailingListService::class, +'mail.list' => MailingListService::class, diff --git a/Engine/Modules/Mailer/composer.json b/Engine/Modules/Mailer/composer.json new file mode 100644 index 000000000..d5a97ebd4 --- /dev/null +++ b/Engine/Modules/Mailer/composer.json @@ -0,0 +1,12 @@ +{ + "name": "oforge/mailer", + "type": "oforge-module", + "description": "Oforge Mailer", + "keywords": ["oforge", "module", "mail"], + "license": "MIT", + "require": { + "php": ">=7.2", + "phpmailer/phpmailer": "~6.0", + "pelago/emogrifier": "^2.1.0" + } +} diff --git a/Engine/Modules/TemplateEngine/Core/Services/TemplateRenderService.php b/Engine/Modules/TemplateEngine/Core/Services/TemplateRenderService.php index cb422de2b..bb348b652 100644 --- a/Engine/Modules/TemplateEngine/Core/Services/TemplateRenderService.php +++ b/Engine/Modules/TemplateEngine/Core/Services/TemplateRenderService.php @@ -134,6 +134,7 @@ public function render(Request $request, Response $response, $data) { * @throws DependencyNotResolvedException */ public function View() { + //TODO REFACTORING: Generic Twig Instance by TemplateRenderService method if (!$this->view) { /** @var TemplateManagementService $templateManagementService */ $templateManagementService = Oforge()->Services()->get('template.management'); diff --git a/Plugins/FrontendUserManagement/Controller/Frontend/RegistrationController.php b/Plugins/FrontendUserManagement/Controller/Frontend/RegistrationController.php index ed886fe70..fe4e2b028 100644 --- a/Plugins/FrontendUserManagement/Controller/Frontend/RegistrationController.php +++ b/Plugins/FrontendUserManagement/Controller/Frontend/RegistrationController.php @@ -233,9 +233,9 @@ public function processAction(Request $request, Response $response) { $mailService = Oforge()->Services()->get('mail'); - $mailOptions = [ + $mailConfig = [ 'to' => [$user['email'] => $user['email']], - 'from' => 'info', + 'from' => $mailService->buildFromConfigByPrefix('info'), 'subject' => I18N::translate('mailer_subject_registration', [ 'en' => 'Your Registration', 'de' => 'Deine Registrierung', @@ -246,14 +246,14 @@ public function processAction(Request $request, Response $response) { 'activationLink' => $activationLink, 'resendLink' => RouteHelper::getFullUrl(RouteHelper::getUrl('frontend_registration_resend_activation_link')), 'user_mail' => $user['email'], - 'sender_mail' => $mailService->getSenderAddress('info'), + 'sender_mail' => $mailService->buildFromMailByPrefix('info'), 'receiver_name' => $nickname, ]; /** * Registration Mail could not be sent */ - if (!$mailService->send($mailOptions, $templateData)) { + if (!$mailService->send($mailConfig, $templateData)) { Oforge()->View()->Flash()->addMessage('error', I18N::translate('registration_mail_error', [ 'en' => 'Your registration mail could not be sent', 'de' => 'Registrierungs-Mail konnte nicht gesendet werden.', @@ -355,15 +355,13 @@ public function activateAction(Request $request, Response $response) { /** @var MailService $mailService */ $mailService = Oforge()->Services()->get('mail'); - - $options = [ + $mailConfig = [ 'to' => [$user['email'] => $user['email']], - 'from' => 'info', + 'from' => $mailService->buildFromConfigByPrefix('info'), 'subject' => I18N::translate('mailer_subject_registration_gift_cert'), 'template' => 'RegistrationGiftCertificate.twig', ]; - - $mailService->send($options); + $mailService->send($mailConfig); if (isset($_SESSION['force_referrer'])) { $uri = $_SESSION['force_referrer']; @@ -429,9 +427,9 @@ public function resendActivationLinkAction(Request $request, Response $response) /** @var MailService $mailService */ $mailService = Oforge()->Services()->get('mail'); - $mailOptions = [ + $mailConfig = [ 'to' => [$userData['email'] => $userData['email']], - 'from' => 'info', + 'from' => $mailService->buildFromConfigByPrefix('info'), 'subject' => I18N::translate('mailer_subject_registration', [ 'en' => 'Your Registration', 'de' => 'Deine Registrierung', @@ -442,11 +440,11 @@ public function resendActivationLinkAction(Request $request, Response $response) 'activationLink' => $activationLink, 'resendLink' => RouteHelper::getFullUrl(RouteHelper::getUrl('frontend_registration_resend_activation_link')), 'user_mail' => $userData['email'], - 'sender_mail' => $mailService->getSenderAddress('info'), + 'sender_mail' => $mailService->buildFromMailByPrefix('info'), 'receiver_name' => ArrayHelper::dotGet($userData, 'detail.nickName') ?? $userData['email'] ?? '', ]; // Registration Mail could not be sent - if (!$mailService->send($mailOptions, $templateData)) { + if (!$mailService->send($mailConfig, $templateData)) { Oforge()->View()->Flash()->addMessage('error', I18N::translate('registration_mail_error', [ 'en' => 'Your registration mail could not be sent', 'de' => 'Registrierungs-Mail konnte nicht gesendet werden.', diff --git a/Plugins/Helpdesk/Controller/Backend/BackendHelpdeskController.php b/Plugins/Helpdesk/Controller/Backend/BackendHelpdeskController.php index 2c38d533a..00f05b18b 100644 --- a/Plugins/Helpdesk/Controller/Backend/BackendHelpdeskController.php +++ b/Plugins/Helpdesk/Controller/Backend/BackendHelpdeskController.php @@ -8,6 +8,7 @@ use Helpdesk\Models\Ticket; use Helpdesk\Services\HelpdeskMessengerService; use Helpdesk\Services\HelpdeskTicketService; +use Messenger\Helper\MessengerMail; use Messenger\Services\FrontendMessengerService; use Oforge\Engine\Modules\AdminBackend\Core\Abstracts\SecureBackendController; use Oforge\Engine\Modules\Auth\Models\User\BackendUser; @@ -17,7 +18,6 @@ use Oforge\Engine\Modules\Core\Exceptions\ConfigOptionKeyNotExistException; use Oforge\Engine\Modules\Core\Exceptions\ServiceNotFoundException; use Oforge\Engine\Modules\I18n\Helper\I18N; -use Oforge\Engine\Modules\Mailer\Services\MailService; use Slim\Http\Request; use Slim\Http\Response; use Slim\Router; @@ -139,16 +139,14 @@ public function messengerAction(Request $request, Response $response, array $arg $conversation = $helpdeskMessengerService->getConversationsByTarget($targetId, $senderId); - if (sizeof($conversation) > 0) { + if (!empty($conversation)) { $conversation = $conversation[0]; } - /** @var MailService $mailService - send notification to requester */ - $mailService = Oforge()->Services()->get('mail'); $messages = $helpdeskMessengerService->getMessagesOfConversation($conversation['id']); $lastMessage = end($messages)->toArray(1); if ($lastMessage["sender"] != 'helpdesk') { - $mailService->sendNewMessageInfoMail($conversation['requester'], $conversation['id']); + MessengerMail::sendNewMessageMail($conversation['requester'], $conversation['id']); Oforge()->View()->Flash()->addMessage('success', "Notification Mail has been sent"); } @@ -169,7 +167,7 @@ public function messengerAction(Request $request, Response $response, array $arg $conversation = $helpdeskMessengerService->getConversationsByTarget($ticketId, 'helpdesk'); - if (sizeof($conversation) > 0) { + if (!empty($conversation)) { $conversation = $conversation[0]; } diff --git a/Plugins/Insertion/Commands/InsertionBookmarkReminderCommand.php b/Plugins/Insertion/Commands/InsertionBookmarkReminderCommand.php index d1a2e50ad..659199a90 100644 --- a/Plugins/Insertion/Commands/InsertionBookmarkReminderCommand.php +++ b/Plugins/Insertion/Commands/InsertionBookmarkReminderCommand.php @@ -57,9 +57,9 @@ public function handle(Input $input, Logger $output) : void { continue; } - $mailerOptions = [ + $mailConfig = [ 'to' => [$userMail => $userMail], - 'from' => 'no_reply', + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), 'subject' => I18N::translate('mailer_subject_insertion_bookmark_reminder', 'Check mal wieder deine Merkliste | All Your Horses'), 'template' => 'InsertionBookmarkReminder.twig', ]; @@ -71,7 +71,7 @@ public function handle(Input $input, Logger $output) : void { 'baseUrl' => Oforge()->Settings()->get('host_url'), ]; - $mailService->send($mailerOptions, $templateData); + $mailService->send($mailConfig, $templateData); } } } diff --git a/Plugins/Insertion/Commands/ReminderCommand.php b/Plugins/Insertion/Commands/ReminderCommand.php index f61235abc..9e8ce870d 100644 --- a/Plugins/Insertion/Commands/ReminderCommand.php +++ b/Plugins/Insertion/Commands/ReminderCommand.php @@ -67,13 +67,13 @@ public function handle(Input $input, Logger $output) : void { /** @var User $user */ $user = $reminderInsertion->getUser(); - $mailOptions = [ - 'from' => 'no-reply', + $mailConfig = [ + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), 'to' => $user->getEmail(), 'Subject' => 'Reminder', 'template' => $template, ]; - $mailService->send($mailOptions); + $mailService->send($mailConfig); } } } diff --git a/Plugins/Insertion/Commands/SearchBookmarkCommand.php b/Plugins/Insertion/Commands/SearchBookmarkCommand.php index 6784c4ea2..9f583b46a 100644 --- a/Plugins/Insertion/Commands/SearchBookmarkCommand.php +++ b/Plugins/Insertion/Commands/SearchBookmarkCommand.php @@ -3,7 +3,11 @@ namespace Insertion\Commands; use DateTime; +use Doctrine\ORM\OptimisticLockException; +use Doctrine\ORM\ORMException; +use Exception; use FrontendUserManagement\Models\User; +use Insertion\Helper\InsertionMail; use Insertion\Models\InsertionUserSearchBookmark; use Insertion\Services\InsertionListService; use Insertion\Services\InsertionSearchBookmarkService; @@ -12,7 +16,6 @@ use Oforge\Engine\Modules\Console\Lib\Input; use Oforge\Engine\Modules\Core\Helper\RouteHelper; use Oforge\Engine\Modules\Core\Services\ConfigService; -use Oforge\Engine\Modules\Mailer\Services\MailService; use Oforge\Engine\Modules\Core\Exceptions; class SearchBookmarkCommand extends AbstractCommand { @@ -50,9 +53,6 @@ public function handle(Input $input, Logger $output) : void { /** @var InsertionListService $insertionListService */ $insertionListService = Oforge()->Services()->get('insertion.list'); - /** @var MailService $mailService */ - $mailService = Oforge()->Services()->get('mail'); - /** @var ConfigService $configService */ $configService = Oforge()->Services()->get('config'); @@ -72,12 +72,16 @@ public function handle(Input $input, Logger $output) : void { $baseUrl = $configService->get('system_project_domain_name'); $searchLink = $baseUrl . $searchBookmarkService->getUrl($bookmark->getInsertionType()->getId(), $params); - $newInsertionsCount = sizeof($insertionList["query"]["items"]); - if ($newInsertionsCount > 0) { - $mailService->sendNewSearchResultsInfoMail($user->getId(), $newInsertionsCount, $searchLink); - } + $newInsertionsCount = count($insertionList["query"]["items"]); - $searchBookmarkService->setLastChecked($bookmark); + try { + if ($newInsertionsCount > 0) { + InsertionMail::sendNewSearchResultsMail($user->getId(), $newInsertionsCount, $searchLink); + } + $searchBookmarkService->setLastChecked($bookmark); + } catch (Exception $exception) { + Oforge()->Logger()->logException($exception); + } } } diff --git a/Plugins/Insertion/Controller/Backend/BackendInsertionController.php b/Plugins/Insertion/Controller/Backend/BackendInsertionController.php index 35419e7ed..0fad320ac 100644 --- a/Plugins/Insertion/Controller/Backend/BackendInsertionController.php +++ b/Plugins/Insertion/Controller/Backend/BackendInsertionController.php @@ -4,7 +4,9 @@ use Doctrine\ORM\OptimisticLockException; use Doctrine\ORM\ORMException; +use Exception; use FrontendUserManagement\Services\UserService; +use Insertion\Helper\InsertionMail; use Insertion\Models\Insertion; use Insertion\Models\InsertionTypeAttribute; use Insertion\Services\InsertionCreatorService; @@ -18,6 +20,7 @@ use Oforge\Engine\Modules\Core\Exceptions\ConfigElementNotFoundException; use Oforge\Engine\Modules\Core\Exceptions\ConfigOptionKeyNotExistException; use Oforge\Engine\Modules\Core\Exceptions\ServiceNotFoundException; +use Oforge\Engine\Modules\Core\Exceptions\Template\TemplateNotFoundException; use Oforge\Engine\Modules\Core\Helper\RouteHelper; use Oforge\Engine\Modules\Core\Helper\SessionHelper; use Oforge\Engine\Modules\Core\Manager\Events\Event; @@ -26,7 +29,6 @@ use Oforge\Engine\Modules\CRUD\Enum\CrudFilterType; use Oforge\Engine\Modules\CRUD\Enum\CrudGroupByOrder; use Oforge\Engine\Modules\I18n\Helper\I18N; -use Oforge\Engine\Modules\Mailer\Services\MailService; use ReflectionException; use Slim\Http\Request; use Slim\Http\Response; @@ -427,8 +429,6 @@ public function updateAction(Request $request, Response $response, $args) { public function approveInsertionAction(Request $request, Response $response, $args) { $insertionId = $args['id']; - /** @var MailService $mailService */ - $mailService = Oforge()->Services()->get('mail'); /** @var InsertionService $insertionService */ $insertionService = Oforge()->Services()->get('insertion'); @@ -437,9 +437,13 @@ public function approveInsertionAction(Request $request, Response $response, $ar $insertion->setModeration(true); $insertionService->entityManager()->update($insertion); - if ($mailService->sendInsertionApprovedInfoMail($insertionId)) { - Oforge()->View()->Flash()->addMessage('success', sprintf('ID %s: Notification has been sent', $insertionId)); - } else { + try { + if (InsertionMail::sendInsertionApprovedMail($insertionId)) { + Oforge()->View()->Flash()->addMessage('success', sprintf('ID %s: Notification has been sent', $insertionId)); + } else { + Oforge()->View()->Flash()->addMessage('error', sprintf('ID %s: Notification could not be sent', $insertionId)); + } + } catch (Exception $exception) { Oforge()->View()->Flash()->addMessage('error', sprintf('ID %s: Notification could not be sent', $insertionId)); } diff --git a/Plugins/Insertion/Controller/Frontend/FrontendInsertionController.php b/Plugins/Insertion/Controller/Frontend/FrontendInsertionController.php index fd01f2d3f..18094af79 100644 --- a/Plugins/Insertion/Controller/Frontend/FrontendInsertionController.php +++ b/Plugins/Insertion/Controller/Frontend/FrontendInsertionController.php @@ -9,6 +9,7 @@ use FrontendUserManagement\Abstracts\SecureFrontendController; use FrontendUserManagement\Services\FrontendUserService; use Helpdesk\Services\HelpdeskTicketService; +use Insertion\Helper\InsertionMail; use Insertion\Models\AttributeKey; use Insertion\Models\Insertion; use Insertion\Models\InsertionType; @@ -24,6 +25,7 @@ use Insertion\Services\InsertionTypeService; use Insertion\Services\InsertionUpdaterService; use Insertion\Services\InsertionValidationService; +use Messenger\Helper\MessengerMail; use Messenger\Models\Conversation; use Messenger\Services\FrontendMessengerService; use Oforge\Engine\Modules\Auth\Models\User\BackendUser; @@ -35,7 +37,6 @@ use Oforge\Engine\Modules\I18n\Helper\I18N; use Oforge\Engine\Modules\I18n\Models\Language; use Oforge\Engine\Modules\I18n\Services\LanguageService; -use Oforge\Engine\Modules\Mailer\Services\MailService; use Oforge\Engine\Modules\TemplateEngine\Extensions\Services\UrlService; use ReflectionException; use Slim\Http\Request; @@ -235,9 +236,6 @@ public function processStepsAction(Request $request, Response $response, $args) /** @var InsertionFormsService $formsService */ $formsService = Oforge()->Services()->get('insertion.forms'); - /** @var MailService $mailService */ - $mailService = Oforge()->Services()->get('mail'); - if ($request->isPost() || $request->isGet() && $_GET['success'] === 'true') { Oforge()->Logger()->get('create')->info('process data ', $_POST); @@ -257,7 +255,7 @@ public function processStepsAction(Request $request, Response $response, $args) if (isset($insertion)) { try { - $mailService->sendInsertionCreateInfoMail($user, $insertion); + InsertionMail::sendInsertionCreateMail($user, $insertion); } catch (Exception $exception) { Oforge()->View()->Flash()->addMessage('warning', I18N::translate('confirmation_mail_not_sent', [ 'en' => 'Confirmation could not be sent.', @@ -753,11 +751,7 @@ public function contactAction(Request $request, Response $response, $args) { ]; $conversation = $messengerService->createNewConversation($data); - - /** @var MailService $mailService */ - $mailService = Oforge()->Services()->get('mail'); - - $mailService->sendNewMessageInfoMail($insertion->getUser()->getId(), $conversation->getId()); + MessengerMail::sendNewMessageMail($insertion->getUser()->getId(), $conversation->getId()); } $uri = $router->pathFor('frontend_account_messages', ['id' => $conversation->getId()]); diff --git a/Plugins/Insertion/Helper/InsertionMail.php b/Plugins/Insertion/Helper/InsertionMail.php new file mode 100644 index 000000000..22cac46f5 --- /dev/null +++ b/Plugins/Insertion/Helper/InsertionMail.php @@ -0,0 +1,197 @@ +getEmail(); + $detail = $user->getDetail(); + $nickName = $detail === null ? $userMail : $detail->getNickName(); + $mailConfig = [ + 'to' => [$userMail => $nickName], + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), + 'subject' => I18N::translate('mailer_subject_insertion_created', 'Insertion was created'), + 'template' => 'InsertionCreated.twig', + ]; + $templateData = [ + 'insertionId' => $insertion->getId(), + 'insertionTitle' => $insertion->getContent()[0]->getTitle(), + 'receiver_name' => $nickName, + 'sender_mail' => $mailService->buildFromMailByPrefix('no_reply'), + ]; + $mailService->send($mailConfig, $templateData); + + try { + I18N::translate( + 'mailer_insertion_waiting_for_moderating_btn', + [ + 'en' => 'moderate', + 'de' => 'moderieren', + ] + ); + /** @var ConfigService $configService */ + $configService = Oforge()->Services()->get('config'); + $moderatorMail = $configService->get('insertions_creation_moderator_mail'); + $moderatorName = $configService->get('insertions_creation_moderator_name'); + if ( !empty($moderatorMail)) { + if (empty($moderatorName)) { + $moderatorName = $moderatorMail; + } + $mailConfig = [ + 'to' => [$moderatorMail => $moderatorName], + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), + 'subject' => I18N::translate( + 'mailer_subject_insertion_waiting_for_moderating', + [ + 'en' => 'A new insertion is waiting for moderation', + 'de' => 'Ein neues Inserat wartet auf Moderation', + ] + ), + 'template' => 'InsertionWaitingForModerating.twig', + ]; + $templateData = [ + 'insertionID' => $insertion->getId(), + 'insertionTitle' => $insertion->getContent()[0]->getTitle(), + 'sender_mail' => $mailService->buildFromMailByPrefix('no_reply'), + ]; + $mailService->send($mailConfig, $templateData); + } + } catch (\Exception $exception) { + Oforge()->Logger()->logException($exception); + } + } + + /** + * @param $insertionId + * + * @return bool + * @throws ConfigElementNotFoundException + * @throws ConfigOptionKeyNotExistException + * @throws ORMException + * @throws OptimisticLockException + * @throws ServiceNotFoundException + * @throws TemplateNotFoundException + * @throws Twig_Error_Loader + * @throws Twig_Error_Runtime + * @throws Twig_Error_Syntax + */ + public static function sendInsertionApprovedMail($insertionId) : bool + { + $mailService = self::MailService(); + /** @var InsertionService $insertionService */ + $insertionService = Oforge()->Services()->get('insertion'); + /** @var Insertion|null $insertion */ + $insertion = $insertionService->getInsertionById($insertionId); + + /** @var User $user */ + $user = $insertion->getUser(); + $userMail = $user->getEmail(); + $detail = $user->getDetail(); + $nickName = $detail === null ? $userMail : $detail->getNickName(); + + $mailConfig = [ + 'to' => [$userMail => $nickName], + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), + 'subject' => I18N::translate('mailer_subject_insertion_approved'), + 'template' => 'InsertionApproved.twig', + ]; + $templateData = [ + 'insertionId' => $insertionId, + // TODO: add title 'insertionTitle' => $insertion->getContent()[0]->getTitle(), + 'receiver_name' => $nickName, + 'sender_mail' => $mailService->buildFromMailByPrefix('no_reply'), + ]; + + return $mailService->send($mailConfig, $templateData); + } + + /** + * @param $userId + * @param $newResultsCount + * @param $searchLink + * + * @return bool + * @throws ConfigElementNotFoundException + * @throws ConfigOptionKeyNotExistException + * @throws ORMException + * @throws OptimisticLockException + * @throws ServiceNotFoundException + * @throws TemplateNotFoundException + * @throws Twig_Error_Loader + * @throws Twig_Error_Runtime + * @throws Twig_Error_Syntax + */ + public static function sendNewSearchResultsMail($userId, $newResultsCount, $searchLink) : bool + { + $mailService = self::MailService(); + /** @var UserService $userService */ + $userService = Oforge()->Services()->get('frontend.user.management.user'); + /** @var User|null $user */ + $user = $userService->getUserById($userId); + $userMail = $user->getEmail(); + $detail = $user->getDetail(); + $nickName = $detail === null ? $userMail : $detail->getNickName(); + + $mailConfig = [ + 'to' => [$userMail => $nickName], + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), + 'subject' => I18N::translate('mailer_subject_new_search_results'), + 'template' => 'NewSearchResults.twig', + ]; + $templateData = [ + 'resultCount' => $newResultsCount, + 'searchLink' => $searchLink, + 'sender_mail' => $mailService->buildFromMailByPrefix('no_reply'), + 'receiver_name' => $nickName, + ]; + + return $mailService->send($mailConfig, $templateData); + } + + private static function MailService() : MailService + { + /** @noinspection PhpUnhandledExceptionInspection */ + return Oforge()->Services()->get('mail'); + } + +} diff --git a/Plugins/Messenger/Controller/Frontend/MessengerController.php b/Plugins/Messenger/Controller/Frontend/MessengerController.php index 4fa36a8be..dc2fe03ef 100644 --- a/Plugins/Messenger/Controller/Frontend/MessengerController.php +++ b/Plugins/Messenger/Controller/Frontend/MessengerController.php @@ -8,6 +8,7 @@ use FrontendUserManagement\Models\User; use FrontendUserManagement\Services\FrontendUserService; use FrontendUserManagement\Services\UserService; +use Messenger\Helper\MessengerMail; use Messenger\Models\Conversation; use Messenger\Services\FrontendMessengerService; use Oforge\Engine\Modules\Core\Annotation\Endpoint\EndpointAction; @@ -16,8 +17,6 @@ use Oforge\Engine\Modules\Core\Exceptions\ConfigOptionKeyNotExistException; use Oforge\Engine\Modules\Core\Exceptions\ServiceNotFoundException; use Oforge\Engine\Modules\Core\Helper\Statics; -use Oforge\Engine\Modules\I18n\Helper\I18N; -use Oforge\Engine\Modules\Mailer\Services\MailService; use Slim\Http\Request; use Slim\Http\Response; use Slim\Router; @@ -81,9 +80,7 @@ public function indexAction(Request $request, Response $response, array $args) { $message = $request->getParsedBody()['message']; /** @var FrontendMessengerService $frontendMessengerService */ - /** @var MailService $mailService */ $frontendMessengerService = Oforge()->Services()->get('frontend.messenger'); - $mailService = Oforge()->Services()->get('mail'); $frontendMessengerService->sendMessage($activeConversation['id'], $user['id'], $message); @@ -96,12 +93,12 @@ public function indexAction(Request $request, Response $response, array $args) { $lastMessage = end($activeConversation['messages']); /** send mail if posted message is first message */ if ($lastMessage == false) { - $mailService->sendNewMessageInfoMail($targetUserId, $activeConversation['id']); + MessengerMail::sendNewMessageMail($targetUserId, $activeConversation['id']); } else { $lastMessageUser = $lastMessage->toArray()['sender']; /** send mail if last message came from other chat user */ if ($lastMessageUser != $user['id']) { - $mailService->sendNewMessageInfoMail($targetUserId, $activeConversation['id']); + MessengerMail::sendNewMessageMail($targetUserId, $activeConversation['id']); } } } diff --git a/Plugins/Messenger/Helper/MessengerMail.php b/Plugins/Messenger/Helper/MessengerMail.php new file mode 100644 index 000000000..4cd05ffe9 --- /dev/null +++ b/Plugins/Messenger/Helper/MessengerMail.php @@ -0,0 +1,76 @@ +Services()->get('frontend.user.management.user'); + + /** @var User|null $user */ + $user = $userService->getUserById($userId); + + $userMail = $user->getEmail(); + $detail = $user->getDetail(); + $nickName = $detail === null ? $userMail : $detail->getNickName(); + $mailConfig = [ + 'to' => [$userMail => $nickName], + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), + 'subject' => I18N::translate('mailer_subject_new_message'), + 'template' => 'NewMessage.twig', + ]; + $templateData = [ + 'conversationId' => $conversationId, + 'receiver_name' => $nickName, + 'sender_mail' => $mailService->buildFromMailByPrefix('no_reply'), + ]; + + return $mailService->send($mailConfig, $templateData); + } + + private static function MailService() : MailService + { + /** @noinspection PhpUnhandledExceptionInspection */ + return Oforge()->Services()->get('mail'); + } + +} diff --git a/Plugins/PDFGenerator/Services/PDFGeneratorService.php b/Plugins/PDFGenerator/Services/PDFGeneratorService.php index 4e4828d16..7179d572d 100644 --- a/Plugins/PDFGenerator/Services/PDFGeneratorService.php +++ b/Plugins/PDFGenerator/Services/PDFGeneratorService.php @@ -98,6 +98,8 @@ public function generatePDF($options, $templateData = []) { $this->templateManagementService = Oforge()->Services()->get("template.management"); $this->templateName = $this->templateManagementService->getActiveTemplate()->getName(); $this->templatePath = Statics::TEMPLATE_DIR . Statics::GLOBAL_SEPARATOR . $this->templateName . Statics::GLOBAL_SEPARATOR . 'PDFTemplates'; + //TODO templatePath-Problem: aktuell keine MailTemplates per Plugins möglich!!! + //TODO REFACTORING: Generic Twig Instance by TemplateRenderService method $twig = new CustomTwig($this->templatePath); try { @@ -127,9 +129,9 @@ public function generatePDF($options, $templateData = []) { } /** @var InlineCssService $inlineCssService */ - $inlineCssService = Oforge()->Services()->get('inline.css'); + $inlineCssService = Oforge()->Services()->get('mail.inlineCss'); - $this->mpdf->WriteHTML($inlineCssService->renderInlineCss($html)); + $this->mpdf->WriteHTML($inlineCssService->inline($html)); if(isset($options["path"])) { return $this->mpdf->Output($options['path'] . $options['filename'], 'F'); } else { diff --git a/Plugins/ReportErrorForm/Controller/FormController.php b/Plugins/ReportErrorForm/Controller/FormController.php index e7ad74c77..4345a18b1 100644 --- a/Plugins/ReportErrorForm/Controller/FormController.php +++ b/Plugins/ReportErrorForm/Controller/FormController.php @@ -147,13 +147,13 @@ public function indexAction(Request $request, Response $response) : Response { $subject .= $issueTypeLabel; /** @var MailService $mailService */ $mailService = Oforge()->Services()->get('mail'); - $mailOptions = [ - 'from' => 'no_reply', + $mailConfig = [ + 'from' => $mailService->buildFromConfigByPrefix('no_reply'), 'to' => $receiver, 'subject' => $subject, 'text' => $message, ]; - $mailService->send($mailOptions); + $mailService->send($mailConfig); } /** @var HelpdeskTicketService $helpdeskTicketService */ $helpdeskTicketService = Oforge()->Services()->get('helpdesk.ticket'); diff --git a/Plugins/TestMail/.meta/.phpstorm.meta.php b/Plugins/TestMail/.meta/.phpstorm.meta.php new file mode 100644 index 000000000..45e572e9b --- /dev/null +++ b/Plugins/TestMail/.meta/.phpstorm.meta.php @@ -0,0 +1,28 @@ + 'List of mail ids', + 'mail.test.' => 'Mail config & testdata', + ] + ) + ); + override( + \Oforge\Engine\Modules\Core\Manager\Events\EventManager::attach(0), + map( + [ + 'mail.test.mailIds' => 'List of mail ids', + 'mail.test.' => 'Mail config & testdata', + ] + ) + ); + } +} diff --git a/Plugins/TestMail/.meta/events.txt b/Plugins/TestMail/.meta/events.txt new file mode 100644 index 000000000..9bbc60ed8 --- /dev/null +++ b/Plugins/TestMail/.meta/events.txt @@ -0,0 +1,29 @@ +Oforge()->Events()->attach( + 'mail.test.mailIds', + Event::SYNC, + function (Event $event) { + $mailIds = $event->getReturnValue(); + + $mailIds['newId'] = 'newDescription'; + + $event->setReturnValue($mailIds); + } +); + + + +Oforge()->Events()->attach( + 'mail.test.newId', + Event::SYNC, + function (Event $event) { + $mail = [ + 'config' => [ + 'template' => 'MyFolder/MyTemplateFile.twig', + ], + 'data' => [ + // Template data + ], + ]; + $event->setReturnValue($mail); + } +); diff --git a/Plugins/TestMail/.meta/ide-twig.json b/Plugins/TestMail/.meta/ide-twig.json new file mode 100644 index 000000000..17eea77cc --- /dev/null +++ b/Plugins/TestMail/.meta/ide-twig.json @@ -0,0 +1,7 @@ +{ + "namespaces": [ + { + "path": "../Views" + } + ] +} diff --git a/Plugins/TestMail/Bootstrap.php b/Plugins/TestMail/Bootstrap.php index b78087232..40289c260 100644 --- a/Plugins/TestMail/Bootstrap.php +++ b/Plugins/TestMail/Bootstrap.php @@ -4,37 +4,85 @@ use Oforge\Engine\Modules\AdminBackend\Core\Services\BackendNavigationService; use Oforge\Engine\Modules\Core\Abstracts\AbstractBootstrap; +use Oforge\Engine\Modules\Core\Manager\Events\Event; use Oforge\Engine\Modules\I18n\Helper\I18N; -use TestMail\Controller\Backend\SendMailController; -use TestMail\Controller\Backend\ShowMailController; -use TestMail\Controller\Backend\TestMailController; /** * Class Bootstrap * * @package TestMail */ -class Bootstrap extends AbstractBootstrap { +class Bootstrap extends AbstractBootstrap +{ - public function __construct() { + public function __construct() + { $this->endpoints = [ - TestMailController::class, - ShowMailController::class, - SendMailController::class, + Controller\BackendController::class, ]; } - public function activate() { - I18N::translate('backend_testmail', ['en' => 'TestMail', 'de' => 'TestMail']); + public function activate() + { + I18N::translate('backend_test_mail', ['en' => 'Test mail', 'de' => 'Test Mail']); $backendNavigationService = Oforge()->Services()->get('backend.navigation'); $backendNavigationService->add(BackendNavigationService::CONFIG_CONTENT); - $backendNavigationService->add([ - 'name' => 'backend_testmail', - 'order' => 5, - 'parent' => BackendNavigationService::KEY_CONTENT, - 'icon' => 'fa fa-envelope', - 'path' => 'backend_testmail', - 'position' => 'sidebar', - ]); + $backendNavigationService->add( + [ + 'name' => 'backend_test_mail', + 'order' => 5, + 'parent' => BackendNavigationService::KEY_CONTENT, + 'icon' => 'fa fa-envelope', + 'path' => 'backend_test_mail', + 'position' => 'sidebar', + ] + ); } + + public function load() + { + //TODO move to plugins/mailer module + $mailIds = [ + 'AutoDeactivationConfirm' => 'AutoDeactivationConfirm', + 'DeactivationConfirm' => 'DeactivationConfirm', + 'InsertionApproved' => 'InsertionApproved', + 'InsertionCreated' => 'InsertionCreated', + 'InsertionWaitingForModerating' => 'InsertionWaitingForModerating', + 'NewMessage' => 'NewMessage', + 'NewSearchResults' => 'NewSearchResults', + 'RegisterConfirm' => 'RegisterConfirm', + 'RegistrationGiftCertificate' => 'RegistrationGiftCertificate', + 'Reminder3Days' => 'Reminder3Days', + 'Reminder14Days' => 'Reminder14Days', + 'Reminder30Days' => 'Reminder30Days', + 'ResetPassword' => 'ResetPassword', + ]; + Oforge()->Events()->attach( + 'mail.test.mailIds', + Event::SYNC, + function (Event $event) use ($mailIds) { + $eventMailIds = $event->getReturnValue(); + + $eventMailIds = array_merge($eventMailIds, $mailIds); + + $event->setReturnValue($eventMailIds); + } + ); + foreach ($mailIds as $mailId => $mailDescription) { + Oforge()->Events()->attach( + 'mail.test.' . $mailId, + Event::SYNC, + function (Event $event) use ($mailId) { + $mail = [ + 'config' => [ + 'template' => $mailId . '.twig', + ], + 'data' => [], //TODO template based test data + ]; + $event->setReturnValue($mail); + } + ); + } + } + } diff --git a/Plugins/TestMail/Controller/Backend/SendMailController.php b/Plugins/TestMail/Controller/Backend/SendMailController.php deleted file mode 100644 index 18cde19a5..000000000 --- a/Plugins/TestMail/Controller/Backend/SendMailController.php +++ /dev/null @@ -1,46 +0,0 @@ -Services()->get('mail'); - $testOptions = [ - 'to' => [$request->getQueryParam('to') => $request->getQueryParam('to')], - 'cc' => [], - 'bcc' => [], - 'replyTo' => [], - 'subject' => $request->getQueryParam('template'), - 'attachment' => [], - 'template' => $request->getQueryParam('template'), - 'from' => 'info', - ]; - - $mailservice->send($testOptions, []); - Oforge()->View()->Flash()->addMessage('success', I18N::translate( 'mail_send_success')); - - /** @var Router $router */ - $router = Oforge()->App()->getContainer()->get('router'); - - $url = $router->pathFor('backend_testmail'); - - return $response->withRedirect($url, 301); - } - public function initPermissions() { - $this->ensurePermission('indexAction', BackendUser::ROLE_ADMINISTRATOR); - } -} diff --git a/Plugins/TestMail/Controller/Backend/ShowMailController.php b/Plugins/TestMail/Controller/Backend/ShowMailController.php deleted file mode 100644 index 31e7d9b10..000000000 --- a/Plugins/TestMail/Controller/Backend/ShowMailController.php +++ /dev/null @@ -1,28 +0,0 @@ -Services()->get('mail'); - $options['template'] = $request->getQueryParam('template'); - $renderedMail = $mailservice->renderMail($options, []); - $response->write($renderedMail); - return $response; - } - public function initPermissions() { - $this->ensurePermission('indexAction', BackendUser::ROLE_ADMINISTRATOR); - } -} diff --git a/Plugins/TestMail/Controller/Backend/TestMailController.php b/Plugins/TestMail/Controller/Backend/TestMailController.php deleted file mode 100644 index 1767234c0..000000000 --- a/Plugins/TestMail/Controller/Backend/TestMailController.php +++ /dev/null @@ -1,52 +0,0 @@ -Container()->get('router'); - $showMailLink = $router->pathFor('backend_showmail'); - $sendMailLink = $router->pathFor('backend_sendmail'); - // TODO: get all template files in active template - Oforge()->View()->assign(['showMailLink' => $showMailLink, 'sendMailLink' => $sendMailLink]); - - } - - public function sendAction(Request $request, Response $response) { - // - } - public function showAction(Request $request, Response $response) { - // - } - public function initPermissions() { - $this->ensurePermissions([ - 'indexAction', - 'sendAction', - 'showAction', - ], BackendUser::ROLE_ADMINISTRATOR); - } - -} diff --git a/Plugins/TestMail/Controller/BackendController.php b/Plugins/TestMail/Controller/BackendController.php new file mode 100644 index 000000000..fd684c6ec --- /dev/null +++ b/Plugins/TestMail/Controller/BackendController.php @@ -0,0 +1,170 @@ +ensurePermissions( + [ + 'indexAction', + 'sendAction', + 'showAction', + ], + BackendUser::ROLE_ADMINISTRATOR + ); + } + + /** + * @param Request $request + * @param Response $response + * @EndpointAction() + */ + public function indexAction(Request $request, Response $response) + { + $mailIds = Oforge()->Events()->trigger(Event::create('mail.test.mailIds', [], [])); + ksort($mailIds); + if (Oforge()->View()->Flash()->hasData(self::class)) { + $formData = Oforge()->View()->Flash()->getData(self::class); + } else { + $formData = []; + } + Oforge()->View()->assign( + [ + 'TestMailController' => [ + 'mailIds' => $mailIds, + 'formData' => $formData, + ], + ] + ); + } + + /** + * @param Request $request + * @param Response $response + * @param array $args + * + * @return Response + * @EndpointAction(path="/send", method=EndpointMethod::POST) + */ + public function sendAction(Request $request, Response $response, array $args) : Response + { + $postData = $request->getParsedBody(); + $mailId = $postData['id']; + /** @var MailService $mailservice */ + $mailservice = Oforge()->Services()->get('mail'); + $config = Oforge()->Events()->trigger(Event::create('mail.test.' . $mailId, [], ['config' => [], 'data' => []])); + $mailConfig = $config['config'] ?? []; + $mailData = $config['data'] ?? []; + + $mailConfig = array_merge( + $mailConfig, + [ + 'to' => $postData['to'], + 'subject' => 'Test-Mail: ' . ($mailConfig['subject'] ?? $mailId), + 'from' => $mailConfig['from'] ?? $mailservice->buildFromConfigByPrefix('info'), + ] + ); + Oforge()->View()->assign( + [ + 'TestMailController' => [ + 'mailConfig' => $mailConfig, + 'mailData' => $mailData, + ], + ] + ); + $success = $mailservice->send($mailConfig, $mailData); + if ($success) { + $formData = Oforge()->View()->Flash()->getData(self::class); + $formData['to'] = $postData['to']; + Oforge()->View()->Flash()->setData(self::class, $formData); + Oforge()->View()->Flash()->addMessage( + 'success', + I18N::translate( + 'mail_send_success', + [ + 'en' => 'Mail was sent', + 'de' => 'Mail wurde versendet', + ] + ) + ); + } else { + Oforge()->View()->Flash()->addMessage( + 'error', + I18N::translate( + 'mail_send_failed', + [ + 'en' => 'Mail could not be sent', + 'de' => 'Mail konnte nicht gesendet werden', + ] + ) + ); + } + + return RouteHelper::redirect($response, 'backend_test_mail'); + } + + /** + * @param Request $request + * @param Response $response + * @param array $args + * + * @return Response + * @throws ORMException + * @throws OptimisticLockException + * @throws ServiceNotFoundException + * @throws TemplateNotFoundException + * @throws Twig_Error_Loader + * @throws Twig_Error_Runtime + * @throws Twig_Error_Syntax + * @EndpointAction(path="/show/{id}") + */ + public function showAction(Request $request, Response $response, array $args) : Response + { + $mailId = $args['id']; + /** @var MailService $mailservice */ + $mailservice = Oforge()->Services()->get('mail'); + $config = Oforge()->Events()->trigger(Event::create('mail.test.' . $mailId, [], ['config' => [], 'data' => []])); + $mailConfig = $config['config'] ?? []; + $mailData = $config['data'] ?? []; + Oforge()->View()->assign( + [ + 'omitRendering' => true, + 'TestMailController' => [ + 'id' => $mailId, + 'mailConfig' => $mailConfig, + 'mailData' => $mailData, + ], + ] + ); + $rendered = $mailservice->renderTemplate($mailConfig, $mailData); + + return $response->write($rendered); + } + +} diff --git a/Plugins/TestMail/Controller/Frontend/TestController.php b/Plugins/TestMail/Controller/Frontend/TestController.php deleted file mode 100644 index 5cfce4209..000000000 --- a/Plugins/TestMail/Controller/Frontend/TestController.php +++ /dev/null @@ -1,40 +0,0 @@ -View()->assign(['tim' => "tim"]); - } - - - public function initPermissions() { - - } - -} diff --git a/Plugins/TestMail/Services/PayPalService.php b/Plugins/TestMail/Services/PayPalService.php deleted file mode 100644 index 4e01495cf..000000000 --- a/Plugins/TestMail/Services/PayPalService.php +++ /dev/null @@ -1,22 +0,0 @@ - -

{{ mail_preview }}

- - -
- -
- - -
-

{{ mail_send }}

- -
- -
-
- -
-
-{% endblock mail_form %} diff --git a/Plugins/TestMail/Views/Plugins/TestMail/Backend/Index.twig b/Plugins/TestMail/Views/Plugins/TestMail/Backend/Index.twig new file mode 100644 index 000000000..daa321c98 --- /dev/null +++ b/Plugins/TestMail/Views/Plugins/TestMail/Backend/Index.twig @@ -0,0 +1,38 @@ +{% extends "Backend/Master/Index.twig" %} + +{% block pagecontent %} +
+
+ + + + + + + + + + + {% for mailId,description in TestMailController.mailIds %} + + + + + + {% endfor %} + +
DescriptionPreviewSend
{{ description }} + Preview + +
+ + + +
+
+
{# end: box-body #} +
{# end: box #} +{% endblock pagecontent %} diff --git a/Plugins/TestMail/Views/Plugins/TestMail/Backend/ShowMail/Index.twig b/Plugins/TestMail/Views/Plugins/TestMail/Backend/ShowMail/Index.twig deleted file mode 100644 index e69de29bb..000000000 diff --git a/Plugins/TestMail/Views/Plugins/TestMail/Backend/TestMail/Index.twig b/Plugins/TestMail/Views/Plugins/TestMail/Backend/TestMail/Index.twig deleted file mode 100644 index b853cd113..000000000 --- a/Plugins/TestMail/Views/Plugins/TestMail/Backend/TestMail/Index.twig +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "Backend/Master/Index.twig" %} -{% block pagecontent %} -
- {% include 'Plugins/TestMail/Backend/Components/Forms/MailForm.twig' %} -
- -{% endblock pagecontent %} diff --git a/composer.json b/composer.json index b777aa126..ef1925c43 100644 --- a/composer.json +++ b/composer.json @@ -7,19 +7,17 @@ "ext-json": "*", "ext-openssl": "*", "ext-xml": "*", + "ext-fileinfo": "*", "slim/slim": "^3.0", "monolog/monolog": "^1.23", "twig/twig": "dev-environment-inheritance as 2.x-dev", "php-di/slim-bridge": "^2.0", "doctrine/orm":"^2.0", - "phpmailer/phpmailer": "~6.0", "scssphp/scssphp": "1.3", "matthiasmullie/minify": "^1.3", "firebase/php-jwt": "^5.0", "ulrichsg/getopt-php": "^3.0", "marcj/topsort": "^1.1", - "pelago/emogrifier": "^2.1.0", - "ext-fileinfo": "*", "vimeo/vimeo-api": "^3.0", "google/cloud-translate": "*", "wikimedia/composer-merge-plugin": "*" @@ -41,6 +39,7 @@ "extra": { "merge-plugin": { "include": [ + "Engine/Modules/*/composer.json", "Plugins/*/composer.json" ], "recurse": true, diff --git a/config.sample.php b/config.sample.php index b92f5f63f..6b036cb8c 100644 --- a/config.sample.php +++ b/config.sample.php @@ -1,11 +1,12 @@ 'development', // production|development // Monolog settings - 'logger' => [ + 'logger' => [# [ 'name' => 'system', 'level' => Logger::DEBUG, @@ -14,42 +15,48 @@ 'name' => 'plugins', 'level' => Logger::DEBUG, ], + [ + 'name' => 'mailer', + 'level' => Logger::DEBUG, + ], ], //Doctrine Settings - 'db' => [ + 'db' => [# // if true, metadata caching is forcefully disabled 'dev_mode' => true, // path where the compiled metadata info will be cached. make sure the path exists and it is writable - 'cache_dir' => ROOT_PATH . '/' . Statics::DB_CACHE_DIR, + 'cache_dir' => ROOT_PATH . Statics::DB_CACHE_DIR, // you should add any other path containing annotated entity classes 'metadata_dirs' => [ROOT_PATH . '/Engine', ROOT_PATH . '/Plugins'], - 'connection' => [ + 'connection' => [# 'driver' => 'pdo_mysql', 'host' => 'localhost', 'port' => 3306, 'dbname' => '', // your database name here 'user' => '', // your database user name here 'password' => '', // your database user password here - 'charset' => 'utf8mb4' // we expect to use utf8 charset everywhere (webserver, mysql, php, etc) + 'charset' => 'utf8mb4', // we expect to use utf8 charset everywhere (webserver, mysql, php, etc) + 'options' => [# + 'charset' => 'utf8mb4', + 'collate' => 'utf8mb4_unicode_ci', + ], ], ], 'jwt_salt' => 'my awesome salt', // Change this salt for security // config for db value encrypt/decrypt - 'encryption' => [ + 'encryption' => [# // 'method' => 'aes-128-gcm', // Default: aes-128-gcm 'key' => 'my awesome salt', ], - // host_url needed in specific cases (i.e. cronjobs generating domain specific links) 'host_url' => '', // your domain - // Configuration for detailed error reporting (in case of server error) via mail (over smtp) - 'error_mail_report' => [ + 'error_mail_report' => [# 'active' => false, // enable/disable error reporting - 'mailer_settings' => [ + 'mailer_settings' => [# 'smtp_host' => '', // set the SMTP server to send through 'smtp_port' => 587, 'smtp_user' => '', // SMTP username @@ -59,9 +66,16 @@ 'receiver_address' => '', // recipient address ], ], + // module configs + 'Modules' => [# + 'Mailer' => [# + // Send mail or save to disk as emv file (default = send). + 'mode' => 'send',// 'send|file' + ], + ], // plugin configs - 'Plugins' => [ - 'ReportErrorForm' => [ + 'Plugins' => [# + 'ReportErrorForm' => [# // '
' => '', ], ],