GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — integration (#2604)
by Brendan
04:52
created

SMTPGateway::send()   F

Complexity

Conditions 15
Paths 2472

Size

Total Lines 94
Code Lines 52

Duplication

Lines 15
Ratio 15.96 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 15
eloc 52
c 3
b 1
f 0
nc 2472
nop 0
dl 15
loc 94
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
    /**
3
     * @package email-gateways
4
     */
5
6
    /**
7
     * One of the two core email gateways.
8
     * Provides simple SMTP functionalities.
9
     * Supports AUTH LOGIN, SSL and TLS.
10
     *
11
     * @author Huib Keemink, Michael Eichelsdoerfer
12
     */
13
    class SMTPGateway extends EmailGateway
14
    {
15
        protected $_SMTP;
16
        protected $_helo_hostname;
17
        protected $_host;
18
        protected $_port;
19
        protected $_protocol = 'tcp';
20
        protected $_secure = 'no';
21
        protected $_auth = false;
22
        protected $_user;
23
        protected $_pass;
24
        protected $_envelope_from;
25
26
        /**
27
         * Constructor. Sets basic default values based on preferences.
28
         *
29
         * @throws EmailValidationException
30
         */
31
        public function __construct()
32
        {
33
            parent::__construct();
34
            $this->setConfiguration(Symphony::Configuration()->get('email_smtp'));
35
        }
36
37
        /**
38
         * Sets all configuration entries from an array.
39
         *
40
         * @param array $config
41
         *  All configuration entries stored in a single array.
42
         *  The array should have the format of the $_POST array created by the preferences HTML.
43
         * @throws EmailValidationException
44
         * @since 2.3.1
45
         * @return void
46
         */
47
        public function setConfiguration($config)
48
        {
49
            $this->setHeloHostname($config['helo_hostname']);
50
            $this->setFrom($config['from_address'], $config['from_name']);
51
            $this->setHost($config['host']);
52
            $this->setPort($config['port']);
53
            $this->setSecure($config['secure']);
54
55
            if ($config['auth'] === 1) {
56
                $this->setAuth(true);
57
                $this->setUser($config['username']);
58
                $this->setPass($config['password']);
59
            } else {
60
                $this->setAuth(false);
61
                $this->setUser('');
62
                $this->setPass('');
63
            }
64
        }
65
66
        /**
67
         * Sets the HELO/EHLO hostanme
68
         *
69
         * @param string $helo_hostname
70
         * @return void
71
         */
72
        public function setHeloHostname($helo_hostname = null)
73
        {
74
            $this->_helo_hostname = $helo_hostname;
75
        }
76
77
        /**
78
         * Sets the host to connect to.
79
         *
80
         * @param null|string $host (optional)
81
         * @return void
82
         */
83
        public function setHost($host = null)
84
        {
85
            if ($host === null) {
86
                $host = '127.0.0.1';
87
            }
88
89
            if (substr($host, 0, 6) === 'ssl://') {
90
                $this->_protocol = 'ssl';
91
                $this->_secure = 'ssl';
92
                $host = substr($host, 6);
93
            }
94
            $this->_host = $host;
95
        }
96
97
        /**
98
         * Sets the port, used in the connection.
99
         *
100
         * @param null|int $port
101
         * @return void
102
         */
103
        public function setPort($port = null)
104
        {
105
            if (is_null($port)) {
106
                $port = ($this->_protocol === 'ssl') ? 465 : 25;
107
            }
108
109
            $this->_port = $port;
110
        }
111
112
        /**
113
         * Sets the encryption used.
114
         *
115
         * @param string $secure
116
         *  The encryption used. Can be 'ssl', 'tls'. Anything else defaults to
117
         *  a non secure TCP connection
118
         * @return void
119
         */
120
        public function setSecure($secure = null)
121
        {
122
            if ($secure === 'tls') {
123
                $this->_protocol = 'tcp';
124
                $this->_secure = 'tls';
125
            } elseif ($secure === 'ssl') {
126
                $this->_protocol = 'ssl';
127
                $this->_secure = 'ssl';
128
            } else {
129
                $this->_protocol = 'tcp';
130
                $this->_secure = 'no';
131
            }
132
        }
133
134
        /**
135
         * Use AUTH login or no auth.
136
         *
137
         * @param boolean $auth
138
         * @return void
139
         */
140
        public function setAuth($auth = false)
141
        {
142
            $this->_auth = $auth;
143
        }
144
145
        /**
146
         * Sets the username to use with AUTH LOGIN
147
         *
148
         * @param string $user
149
         * @return void
150
         */
151
        public function setUser($user = null)
152
        {
153
            $this->_user = $user;
154
        }
155
156
        /**
157
         * Sets the password to use with AUTH LOGIN
158
         *
159
         * @param string $pass
160
         * @return void
161
         */
162
        public function setPass($pass = null)
163
        {
164
            $this->_pass = $pass;
165
        }
166
167
        /**
168
         * Returns the name, used in the dropdown menu in the preferences pane.
169
         *
170
         * @return array
171
         */
172
        public static function about()
173
        {
174
            return array(
175
                'name' => __('SMTP'),
176
            );
177
        }
178
179
        /**
180
         * Send an email using an SMTP server
181
         *
182
         * @throws EmailGatewayException
183
         * @throws EmailValidationException
184
         * @throws Exception
185
         * @return boolean
186
         */
187
        public function send()
188
        {
189
            $this->validate();
190
191
            $settings = array();
192
            $settings['helo_hostname'] = $this->_helo_hostname;
193
            if ($this->_auth) {
194
                $settings['username'] = $this->_user;
195
                $settings['password'] = $this->_pass;
196
            }
197
            $settings['secure'] = $this->_secure;
198
199
            try {
200
                if (!is_a($this->_SMTP, 'SMTP')) {
201
                    $this->_SMTP = new SMTP($this->_host, $this->_port, $settings);
202
                }
203
204
                // Encode recipient names (but not any numeric array indexes)
205
                $recipients = array();
206 View Code Duplication
                foreach ($this->_recipients as $name => $email) {
207
                    // Support Bcc header
208
                    if (isset($this->_header_fields['Bcc']) && $this->_header_fields['Bcc'] === $email) {
209
                        continue;
210
                    }
211
212
                    // if the key is not numeric, qEncode the key.
213
                    $name = General::intval($name) > -1 ? General::intval($name) : EmailHelper::qEncode($name);
214
                    $recipients[$name] = $email;
215
                }
216
217
                // Combine keys and values into a recipient list (name <email>, name <email>).
218
                $recipient_list = EmailHelper::arrayToList($recipients);
219
220
                // Encode the subject
221
                $subject = EmailHelper::qEncode((string)$this->_subject);
222
223
                // Build the 'From' header field body
224
                $from = empty($this->_sender_name)
225
                    ? $this->_sender_email_address
226
                    : EmailHelper::qEncode($this->_sender_name) . ' <' . $this->_sender_email_address . '>';
227
228
                // Build the 'Reply-To' header field body
229 View Code Duplication
                if (!empty($this->_reply_to_email_address)) {
230
                    $reply_to = empty($this->_reply_to_name)
231
                        ? $this->_reply_to_email_address
232
                        : EmailHelper::qEncode($this->_reply_to_name) . ' <' . $this->_reply_to_email_address . '>';
233
                }
234
235
                if (!empty($reply_to)) {
236
                    $this->_header_fields = array_merge(
237
                        $this->_header_fields,
238
                        array(
239
                            'Reply-To' => $reply_to,
240
                        )
241
                    );
242
                }
243
244
                // Build the body text using attachments, html-text and plain-text.
245
                $this->prepareMessageBody();
246
247
                // Build the header fields
248
                $this->_header_fields = array_merge(
249
                    $this->_header_fields,
250
                    array(
251
                        'Message-ID' => sprintf('<%s@%s>', md5(uniqid()), HTTP_HOST),
252
                        'Date' => date('r'),
253
                        'From' => $from,
254
                        'Subject' => $subject,
255
                        'To' => $recipient_list,
256
                        'X-Mailer' => 'Symphony Email Module',
257
                        'MIME-Version' => '1.0'
258
                    )
259
                );
260
261
                // Set header fields and fold header field bodies
262
                foreach ($this->_header_fields as $name => $body) {
263
                    $this->_SMTP->setHeader($name, EmailHelper::fold($body));
264
                }
265
266
                // Send the email command. If the envelope from variable is set, use that for the MAIL command. This improves bounce handling.
267
                $this->_SMTP->sendMail(is_null($this->_envelope_from) ? $this->_sender_email_address : $this->_envelope_from,
268
                    $this->_recipients, $this->_body);
269
270
                if ($this->_keepalive === false) {
271
                    $this->closeConnection();
272
                }
273
274
                $this->reset();
275
            } catch (SMTPException $e) {
276
                throw new EmailGatewayException($e->getMessage());
277
            }
278
279
            return true;
280
        }
281
282
        public function closeConnection()
283
        {
284
            if (is_a($this->_SMTP, 'SMTP')) {
285
                try {
286
                    $this->_SMTP->quit();
287
288
                    return parent::closeConnection();
289
                } catch (Exception $e) {
290
                }
291
            }
292
293
            parent::closeConnection();
294
295
            return false;
296
        }
297
298
        /**
299
         * Resets the headers, body, subject
300
         *
301
         * @return void
302
         */
303
        public function reset()
304
        {
305
            $this->_header_fields = array();
306
            $this->_envelope_from = null;
307
            $this->_recipients = array();
308
            $this->_subject = null;
309
            $this->_body = null;
310
        }
311
312
        public function openConnection()
313
        {
314
            return parent::openConnection();
315
        }
316
317
        /**
318
         * Sets the envelope_from address. This is only available via the API, as it is an expert-only feature.
319
         *
320
         * @since 2.3.1
321
         * @param null $envelope_from
322
         * @throws EmailValidationException
323
         * @return void
324
         */
325
        public function setEnvelopeFrom($envelope_from = null)
326
        {
327
            if (preg_match('%[\r\n]%', $envelope_from)) {
328
                throw new EmailValidationException(__('The Envelope From Address can not contain carriage return or newlines.'));
329
            }
330
331
            $this->_envelope_from = $envelope_from;
332
        }
333
334
        /**
335
         * Builds the preferences pane, shown in the Symphony backend.
336
         *
337
         * @throws InvalidArgumentException
338
         * @return XMLElement
339
         */
340
        public function getPreferencesPane()
341
        {
342
            parent::getPreferencesPane();
343
            $group = new XMLElement('fieldset');
344
            $group->setAttribute('class', 'settings condensed pickable');
345
            $group->setAttribute('id', 'smtp');
346
            $group->appendChild(new XMLElement('legend', __('Email: SMTP')));
347
348
            $div = new XMLElement('div');
349
350
            $label = Widget::Label(__('HELO Hostname'));
351
            $label->appendChild(Widget::Input('settings[email_smtp][helo_hostname]', $this->_helo_hostname));
352
            $div->appendChild($label);
353
354
            $group->appendChild($div);
355
            $group->appendChild(new XMLElement('p',
356
                __('A fully qualified domain name (FQDN) of your server, e.g. "www.example.com". If left empty, Symphony will attempt to find an IP address for the EHLO/HELO greeting.'),
357
                array('class' => 'help')));
358
359
            $div = new XMLElement('div');
360
            $div->setAttribute('class', 'two columns');
361
362
            $label = Widget::Label(__('From Name'));
363
            $label->setAttribute('class', 'column');
364
            $label->appendChild(Widget::Input('settings[email_smtp][from_name]', $this->_sender_name));
365
            $div->appendChild($label);
366
367
            $label = Widget::Label(__('From Email Address'));
368
            $label->setAttribute('class', 'column');
369
            $label->appendChild(Widget::Input('settings[email_smtp][from_address]', $this->_sender_email_address));
370
            $div->appendChild($label);
371
372
            $group->appendChild($div);
373
374
            $div = new XMLElement('div');
375
            $div->setAttribute('class', 'two columns');
376
377
            $label = Widget::Label(__('Host'));
378
            $label->setAttribute('class', 'column');
379
            $label->appendChild(Widget::Input('settings[email_smtp][host]', $this->_host));
380
            $div->appendChild($label);
381
382
            $label = Widget::Label(__('Port'));
383
            $label->setAttribute('class', 'column');
384
            $label->appendChild(Widget::Input('settings[email_smtp][port]', (string)$this->_port));
385
            $div->appendChild($label);
386
            $group->appendChild($div);
387
388
            $label = Widget::Label();
389
            $label->setAttribute('class', 'column');
390
            // To fix the issue with checkboxes that do not send a value when unchecked.
391
            $options = array(
392
                array('no', $this->_secure === 'no', __('No encryption')),
393
                array('ssl', $this->_secure === 'ssl', __('SSL encryption')),
394
                array('tls', $this->_secure === 'tls', __('TLS encryption')),
395
            );
396
            $select = Widget::Select('settings[email_smtp][secure]', $options);
397
            $label->appendChild($select);
398
            $group->appendChild($label);
399
400
            $group->appendChild(new XMLElement('p',
401
                __('For a secure connection, SSL and TLS are supported. Please check the manual of your email provider for more details.'),
402
                array('class' => 'help')));
403
404
            $label = Widget::Label();
405
            $label->setAttribute('class', 'column');
406
            // To fix the issue with checkboxes that do not send a value when unchecked.
407
            $group->appendChild(Widget::Input('settings[email_smtp][auth]', '0', 'hidden'));
408
            $input = Widget::Input('settings[email_smtp][auth]', '1', 'checkbox');
409
410
            if ($this->_auth === true) {
411
                $input->setAttribute('checked', 'checked');
412
            }
413
414
            $label->setValue(__('%s Requires authentication', array($input->generate())));
415
            $group->appendChild($label);
416
417
            $group->appendChild(new XMLElement('p',
418
                __('Some SMTP connections require authentication. If that is the case, enter the username/password combination below.'),
419
                array('class' => 'help')));
420
421
            $div = new XMLElement('div');
422
            $div->setAttribute('class', 'two columns');
423
424
            $label = Widget::Label(__('Username'));
425
            $label->setAttribute('class', 'column');
426
            $label->appendChild(Widget::Input('settings[email_smtp][username]', $this->_user, 'text',
427
                array('autocomplete' => 'off')));
428
            $div->appendChild($label);
429
430
            $label = Widget::Label(__('Password'));
431
            $label->setAttribute('class', 'column');
432
            $label->appendChild(Widget::Input('settings[email_smtp][password]', $this->_pass, 'password',
433
                array('autocomplete' => 'off')));
434
            $div->appendChild($label);
435
            $group->appendChild($div);
436
437
            return $group;
438
        }
439
    }
440