blob: 566c9618f56e84718d07889b6352a80a767a8f1a [file] [log] [blame]
Copybara botbe50d492023-11-30 00:16:42 +01001<?php
2
3/**
4 * PHPMailer - PHP email creation and transport class.
5 * PHP Version 5.5.
6 *
7 * @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
8 *
9 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
10 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
11 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
12 * @author Brent R. Matzelle (original founder)
13 * @copyright 2012 - 2023 Marcus Bointon
14 * @copyright 2010 - 2012 Jim Jagielski
15 * @copyright 2004 - 2009 Andy Prevost
16 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
17 * @note This program is distributed in the hope that it will be useful - WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22namespace PHPMailer\PHPMailer;
23
24/**
25 * Configure PHPMailer with DSN string.
26 *
27 * @see https://en.wikipedia.org/wiki/Data_source_name
28 *
29 * @author Oleg Voronkovich <oleg-voronkovich@yandex.ru>
30 */
31class DSNConfigurator
32{
33 /**
34 * Create new PHPMailer instance configured by DSN.
35 *
36 * @param string $dsn DSN
37 * @param bool $exceptions Should we throw external exceptions?
38 *
39 * @return PHPMailer
40 */
41 public static function mailer($dsn, $exceptions = null)
42 {
43 static $configurator = null;
44
45 if (null === $configurator) {
46 $configurator = new DSNConfigurator();
47 }
48
49 return $configurator->configure(new PHPMailer($exceptions), $dsn);
50 }
51
52 /**
53 * Configure PHPMailer instance with DSN string.
54 *
55 * @param PHPMailer $mailer PHPMailer instance
56 * @param string $dsn DSN
57 *
58 * @return PHPMailer
59 */
60 public function configure(PHPMailer $mailer, $dsn)
61 {
62 $config = $this->parseDSN($dsn);
63
64 $this->applyConfig($mailer, $config);
65
66 return $mailer;
67 }
68
69 /**
70 * Parse DSN string.
71 *
72 * @param string $dsn DSN
73 *
74 * @throws Exception If DSN is malformed
75 *
76 * @return array Configuration
77 */
78 private function parseDSN($dsn)
79 {
80 $config = $this->parseUrl($dsn);
81
82 if (false === $config || !isset($config['scheme']) || !isset($config['host'])) {
83 throw new Exception('Malformed DSN');
84 }
85
86 if (isset($config['query'])) {
87 parse_str($config['query'], $config['query']);
88 }
89
90 return $config;
91 }
92
93 /**
94 * Apply configuration to mailer.
95 *
96 * @param PHPMailer $mailer PHPMailer instance
97 * @param array $config Configuration
98 *
99 * @throws Exception If scheme is invalid
100 */
101 private function applyConfig(PHPMailer $mailer, $config)
102 {
103 switch ($config['scheme']) {
104 case 'mail':
105 $mailer->isMail();
106 break;
107 case 'sendmail':
108 $mailer->isSendmail();
109 break;
110 case 'qmail':
111 $mailer->isQmail();
112 break;
113 case 'smtp':
114 case 'smtps':
115 $mailer->isSMTP();
116 $this->configureSMTP($mailer, $config);
117 break;
118 default:
119 throw new Exception(
120 sprintf(
121 'Invalid scheme: "%s". Allowed values: "mail", "sendmail", "qmail", "smtp", "smtps".',
122 $config['scheme']
123 )
124 );
125 }
126
127 if (isset($config['query'])) {
128 $this->configureOptions($mailer, $config['query']);
129 }
130 }
131
132 /**
133 * Configure SMTP.
134 *
135 * @param PHPMailer $mailer PHPMailer instance
136 * @param array $config Configuration
137 */
138 private function configureSMTP($mailer, $config)
139 {
140 $isSMTPS = 'smtps' === $config['scheme'];
141
142 if ($isSMTPS) {
143 $mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
144 }
145
146 $mailer->Host = $config['host'];
147
148 if (isset($config['port'])) {
149 $mailer->Port = $config['port'];
150 } elseif ($isSMTPS) {
151 $mailer->Port = SMTP::DEFAULT_SECURE_PORT;
152 }
153
154 $mailer->SMTPAuth = isset($config['user']) || isset($config['pass']);
155
156 if (isset($config['user'])) {
157 $mailer->Username = $config['user'];
158 }
159
160 if (isset($config['pass'])) {
161 $mailer->Password = $config['pass'];
162 }
163 }
164
165 /**
166 * Configure options.
167 *
168 * @param PHPMailer $mailer PHPMailer instance
169 * @param array $options Options
170 *
171 * @throws Exception If option is unknown
172 */
173 private function configureOptions(PHPMailer $mailer, $options)
174 {
175 $allowedOptions = get_object_vars($mailer);
176
177 unset($allowedOptions['Mailer']);
178 unset($allowedOptions['SMTPAuth']);
179 unset($allowedOptions['Username']);
180 unset($allowedOptions['Password']);
181 unset($allowedOptions['Hostname']);
182 unset($allowedOptions['Port']);
183 unset($allowedOptions['ErrorInfo']);
184
185 $allowedOptions = \array_keys($allowedOptions);
186
187 foreach ($options as $key => $value) {
188 if (!in_array($key, $allowedOptions)) {
189 throw new Exception(
190 sprintf(
191 'Unknown option: "%s". Allowed values: "%s"',
192 $key,
193 implode('", "', $allowedOptions)
194 )
195 );
196 }
197
198 switch ($key) {
199 case 'AllowEmpty':
200 case 'SMTPAutoTLS':
201 case 'SMTPKeepAlive':
202 case 'SingleTo':
203 case 'UseSendmailOptions':
204 case 'do_verp':
205 case 'DKIM_copyHeaderFields':
206 $mailer->$key = (bool) $value;
207 break;
208 case 'Priority':
209 case 'SMTPDebug':
210 case 'WordWrap':
211 $mailer->$key = (int) $value;
212 break;
213 default:
214 $mailer->$key = $value;
215 break;
216 }
217 }
218 }
219
220 /**
221 * Parse a URL.
222 * Wrapper for the built-in parse_url function to work around a bug in PHP 5.5.
223 *
224 * @param string $url URL
225 *
226 * @return array|false
227 */
228 protected function parseUrl($url)
229 {
230 if (\PHP_VERSION_ID >= 50600 || false === strpos($url, '?')) {
231 return parse_url($url);
232 }
233
234 $chunks = explode('?', $url);
235 if (is_array($chunks)) {
236 $result = parse_url($chunks[0]);
237 if (is_array($result)) {
238 $result['query'] = $chunks[1];
239 }
240 return $result;
241 }
242
243 return false;
244 }
245}