1<?php
2
3/*
4 * This file is part of the Silex framework.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Silex\Provider;
13
14use Pimple\Container;
15use Pimple\ServiceProviderInterface;
16use Silex\Api\EventListenerProviderInterface;
17use Symfony\Component\Console\ConsoleEvents;
18use Symfony\Component\EventDispatcher\EventDispatcherInterface;
19use Symfony\Component\HttpKernel\KernelEvents;
20use Symfony\Component\HttpKernel\Event\PostResponseEvent;
21
22/**
23 * Swiftmailer Provider.
24 *
25 * @author Fabien Potencier <fabien@symfony.com>
26 */
27class SwiftmailerServiceProvider implements ServiceProviderInterface, EventListenerProviderInterface
28{
29    public function register(Container $app)
30    {
31        $app['swiftmailer.options'] = array();
32        $app['swiftmailer.use_spool'] = true;
33
34        $app['mailer.initialized'] = false;
35
36        $app['mailer'] = function ($app) {
37            $app['mailer.initialized'] = true;
38            $transport = $app['swiftmailer.use_spool'] ? $app['swiftmailer.spooltransport'] : $app['swiftmailer.transport'];
39
40            return new \Swift_Mailer($transport);
41        };
42
43        $app['swiftmailer.spooltransport'] = function ($app) {
44            return new \Swift_Transport_SpoolTransport($app['swiftmailer.transport.eventdispatcher'], $app['swiftmailer.spool']);
45        };
46
47        $app['swiftmailer.spool'] = function ($app) {
48            return new \Swift_MemorySpool();
49        };
50
51        $app['swiftmailer.transport'] = function ($app) {
52            $transport = new \Swift_Transport_EsmtpTransport(
53                $app['swiftmailer.transport.buffer'],
54                array($app['swiftmailer.transport.authhandler']),
55                $app['swiftmailer.transport.eventdispatcher']
56            );
57
58            $options = $app['swiftmailer.options'] = array_replace(array(
59                'host' => 'localhost',
60                'port' => 25,
61                'username' => '',
62                'password' => '',
63                'encryption' => null,
64                'auth_mode' => null,
65                'stream_context_options' => [],
66            ), $app['swiftmailer.options']);
67
68            $transport->setHost($options['host']);
69            $transport->setPort($options['port']);
70            $transport->setEncryption($options['encryption']);
71            $transport->setUsername($options['username']);
72            $transport->setPassword($options['password']);
73            $transport->setAuthMode($options['auth_mode']);
74            $transport->setStreamOptions($options['stream_context_options']);
75
76            return $transport;
77        };
78
79        $app['swiftmailer.transport.buffer'] = function () {
80            return new \Swift_Transport_StreamBuffer(new \Swift_StreamFilters_StringReplacementFilterFactory());
81        };
82
83        $app['swiftmailer.transport.authhandler'] = function () {
84            return new \Swift_Transport_Esmtp_AuthHandler(array(
85                new \Swift_Transport_Esmtp_Auth_CramMd5Authenticator(),
86                new \Swift_Transport_Esmtp_Auth_LoginAuthenticator(),
87                new \Swift_Transport_Esmtp_Auth_PlainAuthenticator(),
88            ));
89        };
90
91        $app['swiftmailer.transport.eventdispatcher'] = function ($app) {
92            $dispatcher = new \Swift_Events_SimpleEventDispatcher();
93
94            $plugins = $app['swiftmailer.plugins'];
95
96            if (null !== $app['swiftmailer.sender_address']) {
97                $plugins[] = new \Swift_Plugins_ImpersonatePlugin($app['swiftmailer.sender_address']);
98            }
99
100            if (!empty($app['swiftmailer.delivery_addresses'])) {
101                $plugins[] = new \Swift_Plugins_RedirectingPlugin(
102                    $app['swiftmailer.delivery_addresses'],
103                    $app['swiftmailer.delivery_whitelist']
104                );
105            }
106
107            foreach ($plugins as $plugin) {
108                $dispatcher->bindEventListener($plugin);
109            }
110
111            return $dispatcher;
112        };
113
114        $app['swiftmailer.plugins'] = function ($app) {
115            return array();
116        };
117
118        $app['swiftmailer.sender_address'] = null;
119        $app['swiftmailer.delivery_addresses'] = array();
120        $app['swiftmailer.delivery_whitelist'] = array();
121    }
122
123    public function subscribe(Container $app, EventDispatcherInterface $dispatcher)
124    {
125        // Event has no typehint as it can be either a PostResponseEvent or a ConsoleTerminateEvent
126        $onTerminate = function ($event) use ($app) {
127            // To speed things up (by avoiding Swift Mailer initialization), flush
128            // messages only if our mailer has been created (potentially used)
129            if ($app['mailer.initialized'] && $app['swiftmailer.use_spool'] && $app['swiftmailer.spooltransport'] instanceof \Swift_Transport_SpoolTransport) {
130                $app['swiftmailer.spooltransport']->getSpool()->flushQueue($app['swiftmailer.transport']);
131            }
132        };
133
134        $dispatcher->addListener(KernelEvents::TERMINATE, $onTerminate);
135
136        if (class_exists('Symfony\Component\Console\ConsoleEvents')) {
137            $dispatcher->addListener(ConsoleEvents::TERMINATE, $onTerminate);
138        }
139    }
140}
141