From b5980ab8669e0bfde89f14c66fc8f0cfbc289276 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Tue, 23 Oct 2012 14:55:41 +0200 Subject: [PATCH] First implementation --- lib/Alchemy/Phrasea/Application.php | 36 ++++++++- lib/Alchemy/Phrasea/Command/Setup/Install.php | 4 +- .../Phrasea/Controller/Admin/Dashboard.php | 15 +++- .../Phrasea/Controller/Admin/Users.php | 2 +- lib/Alchemy/Phrasea/Controller/Prod/Push.php | 2 +- .../Phrasea/Controller/Root/Account.php | 2 +- lib/Alchemy/Phrasea/Controller/Root/Login.php | 10 +-- .../NotificationDelivererServiceProvider.php | 21 +++++ lib/Alchemy/Phrasea/Helper/User/Edit.php | 2 +- lib/Alchemy/Phrasea/Helper/User/Manage.php | 2 +- .../Phrasea/Notification/Deliverer.php | 47 +++++++++++ lib/Alchemy/Phrasea/Notification/Emitter.php | 30 +++++++ .../Notification/Mail/AbstractMail.php | 78 +++++++++++++++++++ .../Notification/Mail/MailInterface.php | 23 ++++++ .../Phrasea/Notification/Mail/MailTest.php | 29 +++++++ lib/Alchemy/Phrasea/Notification/Receiver.php | 30 +++++++ lib/classes/mail.php | 7 +- templates/web/email-template.html.twig | 16 ++-- 18 files changed, 326 insertions(+), 30 deletions(-) create mode 100644 lib/Alchemy/Phrasea/Core/Provider/NotificationDelivererServiceProvider.php create mode 100644 lib/Alchemy/Phrasea/Notification/Deliverer.php create mode 100644 lib/Alchemy/Phrasea/Notification/Emitter.php create mode 100644 lib/Alchemy/Phrasea/Notification/Mail/AbstractMail.php create mode 100644 lib/Alchemy/Phrasea/Notification/Mail/MailInterface.php create mode 100644 lib/Alchemy/Phrasea/Notification/Mail/MailTest.php create mode 100644 lib/Alchemy/Phrasea/Notification/Receiver.php diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index 20bd4dbc6f..ef353ada56 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -20,6 +20,7 @@ use Alchemy\Phrasea\Core\Provider\ConfigurationServiceProvider; use Alchemy\Phrasea\Core\Provider\ConfigurationTesterServiceProvider; use Alchemy\Phrasea\Core\Provider\FtpServiceProvider; use Alchemy\Phrasea\Core\Provider\GeonamesServiceProvider; +use Alchemy\Phrasea\Core\Provider\NotificationDelivererServiceProvider; use Alchemy\Phrasea\Core\Provider\ORMServiceProvider; use Alchemy\Phrasea\Core\Provider\SearchEngineServiceProvider; use Alchemy\Phrasea\Core\Provider\TaskManagerServiceProvider; @@ -38,6 +39,7 @@ use Silex\Application as SilexApplication; use Silex\Provider\MonologServiceProvider; use Silex\Provider\SessionServiceProvider; use Silex\Provider\TwigServiceProvider; +use Silex\Provider\SwiftmailerServiceProvider; use Silex\Provider\UrlGeneratorServiceProvider; use Silex\Provider\ValidatorServiceProvider; use Unoconv\UnoconvServiceProvider; @@ -126,6 +128,7 @@ class Application extends SilexApplication $this->register(new MediaVorusServiceProvider()); $this->register(new MonologServiceProvider()); $this->register(new MP4BoxServiceProvider()); + $this->register(new NotificationDelivererServiceProvider()); $this->register(new ORMServiceProvider()); $this->register(new PhraseanetServiceProvider()); $this->register(new PHPExiftoolServiceProvider()); @@ -139,10 +142,41 @@ class Application extends SilexApplication $this->register(new UnicodeServiceProvider()); $this->register(new ValidatorServiceProvider()); $this->register(new XPDFServiceProvider()); + $this->register(new SwiftmailerServiceProvider()); + + $this['swiftmailer.transport'] = $this->share(function ($app) { + $transport = new \Swift_Transport_MailTransport( + new \Swift_Transport_SimpleMailInvoker(), + $app['swiftmailer.transport.eventdispatcher'] + ); +// $transport = new \Swift_Transport_EsmtpTransport( +// $app['swiftmailer.transport.buffer'], +// array($app['swiftmailer.transport.authhandler']), +// $app['swiftmailer.transport.eventdispatcher'] +// ); +// +// $options = $app['swiftmailer.options'] = array_replace(array( +// 'host' => 'localhost', +// 'port' => 25, +// 'username' => '', +// 'password' => '', +// 'encryption' => null, +// 'auth_mode' => null, +// ), $app['swiftmailer.options']); +// +// $transport->setHost($options['host']); +// $transport->setPort($options['port']); +// $transport->setEncryption($options['encryption']); +// $transport->setUsername($options['username']); +// $transport->setPassword($options['password']); +// $transport->setAuthMode($options['auth_mode']); + + return $transport; + }); + // $this->register(new \Silex\Provider\HttpCacheServiceProvider()); // $this->register(new \Silex\Provider\SecurityServiceProvider()); -// $this->register(new \Silex\Provider\SwiftmailerServiceProvider()); $this['imagine.factory'] = $this->share(function(Application $app) { if ($app['phraseanet.registry']->get('GV_imagine_driver') != '') { diff --git a/lib/Alchemy/Phrasea/Command/Setup/Install.php b/lib/Alchemy/Phrasea/Command/Setup/Install.php index b66b83fb0e..bdfadd963e 100644 --- a/lib/Alchemy/Phrasea/Command/Setup/Install.php +++ b/lib/Alchemy/Phrasea/Command/Setup/Install.php @@ -198,7 +198,7 @@ class Install extends Command do { $email = $dialog->ask($output, 'Please provide a valid e-mail address : '); - } while (!\mail::validateEmail($email)); + } while (!\Swift_Validate::email($email)); do { $password = $dialog->ask($output, 'Please provide a password (6 character min) : '); @@ -206,7 +206,7 @@ class Install extends Command $output->writeln("\n\tEmail / Password successfully set\n"); } elseif ($input->getOption('email') && $input->getOption('password')) { - if (!\mail::validateEmail($input->getOption('email'))) { + if (!\Swift_Validate::email($input->getOption('email'))) { throw new \RuntimeException('Invalid email addess'); } $email = $input->getOption('email'); diff --git a/lib/Alchemy/Phrasea/Controller/Admin/Dashboard.php b/lib/Alchemy/Phrasea/Controller/Admin/Dashboard.php index c7921e0517..529325ef0f 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/Dashboard.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/Dashboard.php @@ -11,6 +11,8 @@ namespace Alchemy\Phrasea\Controller\Admin; +use Alchemy\Phrasea\Notification\Receiver; +use Alchemy\Phrasea\Notification\Mail\MailTest; use Silex\Application; use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; @@ -29,8 +31,8 @@ class Dashboard implements ControllerProviderInterface $controllers = $app['controllers_factory']; $controllers->before(function(Request $request) use ($app) { - $app['firewall']->requireAdmin(); - }); + $app['firewall']->requireAdmin(); + }); /** * Get admin dashboard @@ -181,8 +183,15 @@ class Dashboard implements ControllerProviderInterface $app->abort(400, 'Bad request missing email parameter'); }; - if (\mail::mail_test($app, $mail)) { + try { + $receiver = new Receiver(null, $mail); + $mail = MailTest::create($app, $receiver); + $app['notification.deliverer']->deliver($mail); + $app['swiftmailer.spooltransport']->getSpool()->flushQueue($app['swiftmailer.transport']); + return $app->redirect('/admin/dashboard/?email=sent'); + } catch (\Exception $e) { +exit($e->getMessage()); } return $app->redirect('/admin/dashboard/?email=error'); diff --git a/lib/Alchemy/Phrasea/Controller/Admin/Users.php b/lib/Alchemy/Phrasea/Controller/Admin/Users.php index 34ee0fc4f9..bc6c32173a 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/Users.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/Users.php @@ -538,7 +538,7 @@ class Users implements ControllerProviderInterface if ($row) { - if (\PHPMailer::ValidateAddress($row['usr_mail'])) { + if (\Swift_Validate::email($row['usr_mail'])) { foreach ($bases as $bas => $isok) { if ($isok) { $accept .= '
  • ' . \phrasea::bas_names($bas, $app) . "
  • \n"; diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Push.php b/lib/Alchemy/Phrasea/Controller/Prod/Push.php index eb5e484559..2fd6c40c9a 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Push.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Push.php @@ -507,7 +507,7 @@ class Push implements ControllerProviderInterface if (!$request->request->get('email')) throw new ControllerException(_('Email is required')); - if (!\mail::validateEmail($request->request->get('email'))) + if (!\Swift_Validate::email($request->request->get('email'))) throw new ControllerException(_('Email is invalid')); } catch (ControllerException $e) { $result['message'] = $e->getMessage(); diff --git a/lib/Alchemy/Phrasea/Controller/Root/Account.php b/lib/Alchemy/Phrasea/Controller/Root/Account.php index 5ff7065f75..25a1a9609a 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Account.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Account.php @@ -285,7 +285,7 @@ class Account implements ControllerProviderInterface } catch (\Exception $e) { return $app->redirect('/account/reset-email/?notice=bad-password'); } - if (!\PHPMailer::ValidateAddress($email)) { + if (!\Swift_Validate::email($email)) { return $app->redirect('/account/reset-email/?notice=mail-invalid'); } diff --git a/lib/Alchemy/Phrasea/Controller/Root/Login.php b/lib/Alchemy/Phrasea/Controller/Root/Login.php index 6e4a610087..25a5cbe3f1 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Login.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Login.php @@ -275,7 +275,7 @@ class Login implements ControllerProviderInterface \random::removeToken($app, $code); - if (\PHPMailer::ValidateAddress($user->get_email())) { + if (\Swift_Validate::email($user->get_email())) { if (count($user->ACL()->get_granted_base()) > 0) { \mail::mail_confirm_registered($app, $user->get_email()); } @@ -313,7 +313,7 @@ class Login implements ControllerProviderInterface public function renewPassword(Application $app, Request $request) { if (null !== $mail = $request->request->get('mail')) { - if (!\PHPMailer::ValidateAddress($mail)) { + if (!\Swift_Validate::email($mail)) { return $app->redirect($app['url_generator']->generate('login_forgot_password', array('error' => 'invalidmail'))); } @@ -573,7 +573,7 @@ class Login implements ControllerProviderInterface $needed['form_password'] = 'pass-invalid'; } - if (false === \PHPMailer::ValidateAddress($email = $request->request->get('form_email'))) { + if (false === \Swift_Validate::email($email = $request->request->get('form_email'))) { $needed['form_email'] = 'mail-invalid'; } @@ -709,9 +709,9 @@ class Login implements ControllerProviderInterface $app['dispatcher']->dispatch(PhraseaEvents::LOGOUT, new LogoutEvent($app)); $app->closeAccount(); - + $appRedirect = $request->query->get("app"); - + $response = new RedirectResponse("/login/?logged_out=user" . ($appRedirect ? sprintf("&redirect=%s", ltrim($appRedirect, '/')) : "")); $response->headers->removeCookie('persistent'); diff --git a/lib/Alchemy/Phrasea/Core/Provider/NotificationDelivererServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/NotificationDelivererServiceProvider.php new file mode 100644 index 0000000000..c0ee4326af --- /dev/null +++ b/lib/Alchemy/Phrasea/Core/Provider/NotificationDelivererServiceProvider.php @@ -0,0 +1,21 @@ +share(function($app) { + return new Deliverer($app['mailer'], $app['phraseanet.registry']); + }); + } + + public function boot(Application $app) + { + } +} diff --git a/lib/Alchemy/Phrasea/Helper/User/Edit.php b/lib/Alchemy/Phrasea/Helper/User/Edit.php index e5c10b25b8..74902ee440 100644 --- a/lib/Alchemy/Phrasea/Helper/User/Edit.php +++ b/lib/Alchemy/Phrasea/Helper/User/Edit.php @@ -515,7 +515,7 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper $parm = $request->get_parms_from_serialized_datas($infos, 'user_infos'); - if ($parm['email'] && !\mail::validateEmail($parm['email'])) { + if ($parm['email'] && !\Swift_Validate::email($parm['email'])) { throw new \Exception_InvalidArgument(_('Email addess is not valid')); } diff --git a/lib/Alchemy/Phrasea/Helper/User/Manage.php b/lib/Alchemy/Phrasea/Helper/User/Manage.php index 6d0cd742c5..5cd0032aad 100644 --- a/lib/Alchemy/Phrasea/Helper/User/Manage.php +++ b/lib/Alchemy/Phrasea/Helper/User/Manage.php @@ -146,7 +146,7 @@ class Manage extends Helper { $email = $this->request->get('value'); - if (!\mail::validateEmail($email)) { + if ( ! \Swift_Validate::email($email)) { throw new \Exception_InvalidArgument(_('Invalid mail address')); } diff --git a/lib/Alchemy/Phrasea/Notification/Deliverer.php b/lib/Alchemy/Phrasea/Notification/Deliverer.php new file mode 100644 index 0000000000..9fa8fba811 --- /dev/null +++ b/lib/Alchemy/Phrasea/Notification/Deliverer.php @@ -0,0 +1,47 @@ +mailer = $mailer; + $this->registry = $registry; + } + + public function deliver(MailInterface $mail) + { + if (!$mail->receiver()) { + throw new \LogicException('You should provide a receiver for a mail notification'); + } + + $prefix = $this->registry->get('GV_mail_prefix') ? ($this->registry->get('GV_mail_prefix') . ' ') : null; + + $message = \Swift_Message::newInstance($prefix . $mail->subject(), $mail->renderHTML(), 'text/html', 'utf-8'); + $message->addPart($mail->message(), 'text/plain', 'utf-8'); + + $message->setFrom($this->registry->get('GV_defaulmailsenderaddr', 'no-reply@phraseanet.com'), $this->registry->get('GV_homeTitle', 'Phraseanet')); + $message->setTo($mail->receiver()->email(), $mail->receiver()->name()); + + if ($mail->emitter()) { + $message->setReplyTo($mail->emitter()->email(), $mail->emitter()->name()); + } + + + $this->mailer->send($message); + } +} diff --git a/lib/Alchemy/Phrasea/Notification/Emitter.php b/lib/Alchemy/Phrasea/Notification/Emitter.php new file mode 100644 index 0000000000..2e6e716bb5 --- /dev/null +++ b/lib/Alchemy/Phrasea/Notification/Emitter.php @@ -0,0 +1,30 @@ +name = $name; + $this->email = $email; + } + + public function name() + { + return $this->name; + } + + public function email() + { + return $this->email; + } + + public static function fromUser(\User_Adapter $user) + { + return new static($user->get_display_name(), $user->get_email()); + } +} \ No newline at end of file diff --git a/lib/Alchemy/Phrasea/Notification/Mail/AbstractMail.php b/lib/Alchemy/Phrasea/Notification/Mail/AbstractMail.php new file mode 100644 index 0000000000..a4e5621935 --- /dev/null +++ b/lib/Alchemy/Phrasea/Notification/Mail/AbstractMail.php @@ -0,0 +1,78 @@ +twig = $twig; + $this->registry = $registry; + $this->emitter = $emitter; + $this->receiver = $receiver; + $this->message = $message; + } + + public function renderHTML() + { + return $this->twig->render('email-template.html.twig', array( + 'phraseanetURL' => $this->phraseanetURL(), + 'logoUrl' => $this->logoUrl(), + 'logoText' => $this->logoText(), + 'subject' => $this->subject(), + 'senderName' => $this->emitter() ? $this->emitter()->getName() : null, + 'senderMail' => $this->emitter() ? $this->emitter()->getEmail() : null, + 'messageText' => $this->message(), + 'buttonUrl' => $this->buttonURL(), + 'buttonText' => $this->buttonText(), + )); + } + + public function phraseanetURL() + { + return $this->registry->get('GV_ServerName'); + } + + public function logoUrl() + { + return; + } + + public function logoText() + { + return $this->registry->get('GV_homeTitle'); + } + + public function emitter() + { + return $this->emitter; + } + + public function receiver() + { + return $this->receiver; + } + + abstract public function subject(); + + abstract public function message(); + + abstract public function buttonText(); + + abstract public function buttonURL(); + + public static function create(Application $app, Receiver $receiver, Emitter $emitter = null, $message = null) + { + return new static($app['twig'], $app['phraseanet.registry'], $receiver, $emitter, $message); + } +} diff --git a/lib/Alchemy/Phrasea/Notification/Mail/MailInterface.php b/lib/Alchemy/Phrasea/Notification/Mail/MailInterface.php new file mode 100644 index 0000000000..99f254befa --- /dev/null +++ b/lib/Alchemy/Phrasea/Notification/Mail/MailInterface.php @@ -0,0 +1,23 @@ +registry->get('GV_ServerName') + ); + } + + public function buttonText() + { + return _('Return to Phraseanet'); + } + + public function buttonURL() + { + return $this->registry->get('GV_ServerName'); + } +} diff --git a/lib/Alchemy/Phrasea/Notification/Receiver.php b/lib/Alchemy/Phrasea/Notification/Receiver.php new file mode 100644 index 0000000000..5d9b579359 --- /dev/null +++ b/lib/Alchemy/Phrasea/Notification/Receiver.php @@ -0,0 +1,30 @@ +name = $name; + $this->email = $email; + } + + public function name() + { + return $this->name; + } + + public function email() + { + return $this->email; + } + + public static function fromUser(\User_Adapter $user) + { + return new static($user->get_display_name(), $user->get_email()); + } +} \ No newline at end of file diff --git a/lib/classes/mail.php b/lib/classes/mail.php index 3e2e83fb18..549f1c95a7 100644 --- a/lib/classes/mail.php +++ b/lib/classes/mail.php @@ -188,14 +188,9 @@ class mail return self::send_mail($app, $subject, $body, $to); } - public static function validateEmail($email) - { - return PHPMailer::ValidateAddress($email); - } - public static function send_mail(Application $app, $subject, $body, $to, $from = false, $files = array(), $reading_confirm_to = false) { - if ( ! isset($to['email']) || ! PHPMailer::ValidateAddress($to['email'])) { + if ( ! isset($to['email']) || !\Swift_Validate::email($to['email'])) { return false; } diff --git a/templates/web/email-template.html.twig b/templates/web/email-template.html.twig index 06ae99523b..90df00e672 100644 --- a/templates/web/email-template.html.twig +++ b/templates/web/email-template.html.twig @@ -22,7 +22,7 @@ {% endif %} - {{ title }} + {{ subject }} @@ -40,12 +40,12 @@ - {% if senderName is defined and senderMail is defined %} - {{ senderName }} - - {{ senderMail }}
    - {% endif %} + {% if senderName is defined and senderMail is defined %} + {{ senderName }} - + {{ senderMail }}
    + {% endif %}
    - {{ messageText }} + {{ messageText | nl2br }}
    @@ -92,8 +92,8 @@ Si cet email contient des liens non cliquables, copiez/collez ces liens dans votre navigateur.
    Message automatique de Phraseanet - Pour gérer l'envoi d'email automatique, connectez-vous à - - {{ phraseanetUrl }} + + {{ phraseanetURL }}