1<?php
2namespace TYPO3\CMS\Core\Mail;
3
4/*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17use Swift_Transport;
18use TYPO3\CMS\Core\Utility\GeneralUtility;
19use TYPO3\CMS\Extbase\Object\ObjectManager;
20use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
21
22/**
23 * Adapter for Swift_Mailer to be used by TYPO3 extensions.
24 *
25 * This will use the setting in TYPO3_CONF_VARS to choose the correct transport
26 * for it to work out-of-the-box.
27 */
28class Mailer extends \Swift_Mailer
29{
30    /**
31     * @var \Swift_Transport
32     */
33    protected $transport;
34
35    /**
36     * @var array
37     */
38    protected $mailSettings = [];
39
40    /**
41     * When constructing, also initializes the \Swift_Transport like configured
42     *
43     * @param \Swift_Transport|null $transport optionally pass a transport to the constructor.
44     * @throws \TYPO3\CMS\Core\Exception
45     */
46    public function __construct(\Swift_Transport $transport = null)
47    {
48        if ($transport !== null) {
49            $this->transport = $transport;
50        } else {
51            if (empty($this->mailSettings)) {
52                $this->injectMailSettings();
53            }
54            try {
55                $this->initializeTransport();
56            } catch (\Exception $e) {
57                throw new \TYPO3\CMS\Core\Exception($e->getMessage(), 1291068569);
58            }
59        }
60        parent::__construct($this->transport);
61
62        $this->emitPostInitializeMailerSignal();
63    }
64
65    /**
66     * Prepares a transport using the TYPO3_CONF_VARS configuration
67     *
68     * Used options:
69     * $TYPO3_CONF_VARS['MAIL']['transport'] = 'smtp' | 'sendmail' | 'mail' | 'mbox'
70     *
71     * $TYPO3_CONF_VARS['MAIL']['transport_smtp_server'] = 'smtp.example.org';
72     * $TYPO3_CONF_VARS['MAIL']['transport_smtp_port'] = '25';
73     * $TYPO3_CONF_VARS['MAIL']['transport_smtp_encrypt'] = FALSE; # requires openssl in PHP
74     * $TYPO3_CONF_VARS['MAIL']['transport_smtp_username'] = 'username';
75     * $TYPO3_CONF_VARS['MAIL']['transport_smtp_password'] = 'password';
76     *
77     * $TYPO3_CONF_VARS['MAIL']['transport_sendmail_command'] = '/usr/sbin/sendmail -bs'
78     *
79     * @throws \TYPO3\CMS\Core\Exception
80     * @throws \RuntimeException
81     */
82    private function initializeTransport()
83    {
84        $this->transport = $this->getTransportFactory()->get($this->mailSettings);
85    }
86
87    /**
88     * This method is only used in unit tests
89     *
90     * @param array $mailSettings
91     * @internal
92     */
93    public function injectMailSettings(array $mailSettings = null)
94    {
95        if (is_array($mailSettings)) {
96            $this->mailSettings = $mailSettings;
97        } else {
98            $this->mailSettings = (array)$GLOBALS['TYPO3_CONF_VARS']['MAIL'];
99        }
100    }
101
102    /**
103     * Returns the real transport (not a spool).
104     *
105     * @return \Swift_Transport
106     */
107    public function getRealTransport(): Swift_Transport
108    {
109        $mailSettings = !empty($this->mailSettings) ? $this->mailSettings : (array)$GLOBALS['TYPO3_CONF_VARS']['MAIL'];
110        unset($mailSettings['transport_spool_type']);
111        return $this->getTransportFactory()->get($mailSettings);
112    }
113
114    /**
115     * @return TransportFactory
116     */
117    protected function getTransportFactory(): TransportFactory
118    {
119        return GeneralUtility::makeInstance(TransportFactory::class);
120    }
121
122    /**
123     * Get the object manager
124     *
125     * @return \TYPO3\CMS\Extbase\Object\ObjectManager
126     */
127    protected function getObjectManager()
128    {
129        return GeneralUtility::makeInstance(ObjectManager::class);
130    }
131
132    /**
133     * Get the SignalSlot dispatcher
134     *
135     * @return \TYPO3\CMS\Extbase\SignalSlot\Dispatcher
136     */
137    protected function getSignalSlotDispatcher()
138    {
139        return $this->getObjectManager()->get(Dispatcher::class);
140    }
141
142    /**
143     * Emits a signal after mailer initialization
144     */
145    protected function emitPostInitializeMailerSignal()
146    {
147        $this->getSignalSlotDispatcher()->dispatch('TYPO3\\CMS\\Core\\Mail\\Mailer', 'postInitializeMailer', [$this]);
148    }
149}
150