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.
Passed
Pull Request — master (#2843)
by Brendan
04:11
created

SMTPGateway::send()   F

Complexity

Conditions 15
Paths 2472

Size

Total Lines 93
Code Lines 51

Duplication

Lines 15
Ratio 16.13 %

Importance

Changes 0
Metric Value
cc 15
eloc 51
nc 2472
nop 0
dl 15
loc 93
rs 2
c 0
b 0
f 0

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
     * Returns the name, used in the dropdown menu in the preferences pane.
28
     *
29
     * @return array
30
     */
31
    public static function about()
32
    {
33
        return array(
34
            'name' => __('SMTP'),
35
        );
36
    }
37
38
    /**
39
     * Constructor. Sets basic default values based on preferences.
40
     *
41
     * @throws EmailValidationException
42
     */
43
    public function __construct()
44
    {
45
        parent::__construct();
46
        $this->setConfiguration(Symphony::Configuration()->get('email_smtp'));
0 ignored issues
show
Bug introduced by
It seems like Symphony::Configuration()->get('email_smtp') can also be of type integer and string and boolean and double; however, parameter $config of SMTPGateway::setConfiguration() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

46
        $this->setConfiguration(/** @scrutinizer ignore-type */ Symphony::Configuration()->get('email_smtp'));
Loading history...
47
    }
48
49
    /**
50
     * Send an email using an SMTP server
51
     *
52
     * @throws EmailGatewayException
53
     * @throws EmailValidationException
54
     * @throws Exception
55
     * @return boolean
56
     */
57
    public function send()
58
    {
59
        $this->validate();
60
61
        $settings = array();
62
        $settings['helo_hostname'] = $this->_helo_hostname;
63
        if ($this->_auth) {
64
            $settings['username'] = $this->_user;
65
            $settings['password'] = $this->_pass;
66
        }
67
        $settings['secure'] = $this->_secure;
68
69
        try {
70
            if (!is_a($this->_SMTP, 'SMTP')) {
71
                $this->_SMTP = new SMTP($this->_host, $this->_port, $settings);
72
            }
73
74
            // Encode recipient names (but not any numeric array indexes)
75
            $recipients = array();
76
            foreach ($this->_recipients as $name => $email) {
77
                // Support Bcc header
78
                if (isset($this->_header_fields['Bcc']) && $this->_header_fields['Bcc'] == $email) {
79
                    continue;
80
                }
81
82
                // if the key is not numeric, qEncode the key.
83
                $name = General::intval($name) > -1 ? General::intval($name) : EmailHelper::qEncode($name);
84
                $recipients[$name] = $email;
85
            }
86
87
            // Combine keys and values into a recipient list (name <email>, name <email>).
88
            $recipient_list = EmailHelper::arrayToList($recipients);
89
90
            // Encode the subject
91
            $subject = EmailHelper::qEncode((string)$this->_subject);
92
93
            // Build the 'From' header field body
94
            $from = empty($this->_sender_name)
95
                    ? $this->_sender_email_address
96
                    : EmailHelper::qEncode($this->_sender_name) . ' <' . $this->_sender_email_address . '>';
97
98
            // Build the 'Reply-To' header field body
99
            if (!empty($this->_reply_to_email_address)) {
100
                $reply_to = empty($this->_reply_to_name)
101
                            ? $this->_reply_to_email_address
102
                            : EmailHelper::qEncode($this->_reply_to_name) . ' <'.$this->_reply_to_email_address.'>';
103
            }
104
105
            if (!empty($reply_to)) {
106
                $this->_header_fields = array_merge(
107
                    $this->_header_fields,
108
                    array(
109
                        'Reply-To' => $reply_to,
110
                    )
111
                );
112
            }
113
114
            // Build the body text using attachments, html-text and plain-text.
115
            $this->prepareMessageBody();
116
117
            // Build the header fields
118
            $this->_header_fields = array_merge(
119
                $this->_header_fields,
120
                array(
121
                    'Message-ID'   => sprintf('<%s@%s>', md5(uniqid()), HTTP_HOST),
0 ignored issues
show
Bug introduced by
The constant HTTP_HOST was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
122
                    'Date'         => date('r'),
123
                    'From'         => $from,
124
                    'Subject'      => $subject,
125
                    'To'           => $recipient_list,
126
                    'X-Mailer'     => 'Symphony Email Module',
127
                    'MIME-Version' => '1.0'
128
                )
129
            );
130
131
            // Set header fields and fold header field bodies
132
            foreach ($this->_header_fields as $name => $body) {
133
                $this->_SMTP->setHeader($name, EmailHelper::fold($body));
134
            }
135
136
            // Send the email command. If the envelope from variable is set, use that for the MAIL command. This improves bounce handling.
137
            $this->_SMTP->sendMail(is_null($this->_envelope_from)?$this->_sender_email_address:$this->_envelope_from, $this->_recipients, $this->_body);
0 ignored issues
show
Bug introduced by
$this->_recipients of type array is incompatible with the type string expected by parameter $to of SMTP::sendMail(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

137
            $this->_SMTP->sendMail(is_null($this->_envelope_from)?$this->_sender_email_address:$this->_envelope_from, /** @scrutinizer ignore-type */ $this->_recipients, $this->_body);
Loading history...
138
139
            if ($this->_keepalive === false) {
140
                $this->closeConnection();
141
            }
142
143
            $this->reset();
144
        } catch (SMTPException $e) {
145
            throw new EmailGatewayException($e->getMessage());
146
        }
147
148
        return true;
149
    }
150
151
    /**
152
     * Resets the headers, body, subject
153
     *
154
     * @return void
155
     */
156
    public function reset()
157
    {
158
        $this->_header_fields = array();
159
        $this->_envelope_from = null;
160
        $this->_recipients = array();
161
        $this->_subject = null;
162
        $this->_body = null;
163
    }
164
165
    public function openConnection()
166
    {
167
        return parent::openConnection();
168
    }
169
170
    public function closeConnection()
171
    {
172
        if (is_a($this->_SMTP, 'SMTP')) {
173
            try {
174
                $this->_SMTP->quit();
175
                return parent::closeConnection();
176
            } catch (Exception $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
177
            }
178
        }
179
180
        parent::closeConnection();
181
        return false;
182
    }
183
184
    /**
185
     * Sets the HELO/EHLO hostanme
186
     *
187
     * @param string $helo_hostname
188
     * @return void
189
     */
190
    public function setHeloHostname($helo_hostname = null)
191
    {
192
        $this->_helo_hostname = $helo_hostname;
193
    }
194
195
    /**
196
     * Sets the host to connect to.
197
     *
198
     * @param null|string $host (optional)
199
     * @return void
200
     */
201
    public function setHost($host = null)
202
    {
203
        if ($host === null) {
204
            $host = '127.0.0.1';
205
        }
206
207
        if (substr($host, 0, 6) == 'ssl://') {
208
            $this->_protocol = 'ssl';
209
            $this->_secure = 'ssl';
210
            $host = substr($host, 6);
211
        }
212
        $this->_host = $host;
213
    }
214
215
    /**
216
     * Sets the port, used in the connection.
217
     *
218
     * @param null|int $port
219
     * @return void
220
     */
221
    public function setPort($port = null)
222
    {
223
        if (is_null($port)) {
224
            $port = ($this->_protocol == 'ssl') ? 465 : 25;
225
        }
226
227
        $this->_port = $port;
228
    }
229
230
    /**
231
     * Sets the username to use with AUTH LOGIN
232
     *
233
     * @param string $user
234
     * @return void
235
     */
236
    public function setUser($user = null)
237
    {
238
        $this->_user = $user;
239
    }
240
241
    /**
242
     * Sets the password to use with AUTH LOGIN
243
     *
244
     * @param string $pass
245
     * @return void
246
     */
247
    public function setPass($pass = null)
248
    {
249
        $this->_pass = $pass;
250
    }
251
252
    /**
253
     * Use AUTH login or no auth.
254
     *
255
     * @param boolean $auth
256
     * @return void
257
     */
258
    public function setAuth($auth = false)
259
    {
260
        $this->_auth = $auth;
261
    }
262
263
    /**
264
     * Sets the encryption used.
265
     *
266
     * @param string $secure
267
     *  The encryption used. Can be 'ssl', 'tls'. Anything else defaults to
268
     *  a non secure TCP connection
269
     * @return void
270
     */
271
    public function setSecure($secure = null)
272
    {
273
        if ($secure == 'tls') {
274
            $this->_protocol = 'tcp';
275
            $this->_secure = 'tls';
276
        } elseif ($secure == 'ssl') {
277
            $this->_protocol = 'ssl';
278
            $this->_secure = 'ssl';
279
        } else {
280
            $this->_protocol = 'tcp';
281
            $this->_secure = 'no';
282
        }
283
    }
284
285
    /**
286
     * Sets the envelope_from address. This is only available via the API, as it is an expert-only feature.
287
     *
288
     * @since 2.3.1
289
     * @param null $envelope_from
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $envelope_from is correct as it would always require null to be passed?
Loading history...
290
     * @throws EmailValidationException
291
     * @return void
292
     */
293
    public function setEnvelopeFrom($envelope_from = null)
294
    {
295
        if (preg_match('%[\r\n]%', $envelope_from)) {
296
            throw new EmailValidationException(__('The Envelope From Address can not contain carriage return or newlines.'));
297
        }
298
299
        $this->_envelope_from = $envelope_from;
300
    }
301
302
    /**
303
     * Sets all configuration entries from an array.
304
     *
305
     * @param array $config
306
     *  All configuration entries stored in a single array.
307
     *  The array should have the format of the $_POST array created by the preferences HTML.
308
     * @throws EmailValidationException
309
     * @since 2.3.1
310
     * @return void
311
     */
312
    public function setConfiguration($config)
313
    {
314
        $this->setHeloHostname($config['helo_hostname']);
315
        $this->setFrom($config['from_address'], $config['from_name']);
316
        $this->setHost($config['host']);
317
        $this->setPort($config['port']);
318
        $this->setSecure($config['secure']);
319
320
        $this->setAuth((int)$config['auth'] === 1);
321
        $this->setUser($config['username']);
322
        $this->setPass($config['password']);
323
    }
324
325
    /**
326
     * Builds the preferences pane, shown in the Symphony backend.
327
     *
328
     * @throws InvalidArgumentException
329
     * @return XMLElement
330
     */
331
    public function getPreferencesPane()
332
    {
333
        parent::getPreferencesPane();
334
        $group = new XMLElement('fieldset');
335
        $group->setAttribute('class', 'settings condensed pickable');
336
        $group->setAttribute('id', 'smtp');
337
        $group->appendChild(new XMLElement('legend', __('Email: SMTP')));
338
339
        $div = new XMLElement('div');
340
341
        $readonly = array('readonly' => 'readonly');
342
343
        $label = Widget::Label(__('HELO Hostname'));
344
        $label->appendChild(Widget::Input('settings[email_smtp][helo_hostname]', General::sanitize($this->_helo_hostname), 'text', $readonly));
345
        $div->appendChild($label);
346
347
        $group->appendChild($div);
348
        $group->appendChild(new XMLElement('p', __('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.'), array('class' => 'help')));
349
350
        $div = new XMLElement('div');
351
        $div->setAttribute('class', 'two columns');
352
353
        $label = Widget::Label(__('From Name'));
354
        $label->setAttribute('class', 'column');
355
        $label->appendChild(Widget::Input('settings[email_smtp][from_name]', General::sanitize($this->_sender_name), 'text', $readonly));
356
        $div->appendChild($label);
357
358
        $label = Widget::Label(__('From Email Address'));
359
        $label->setAttribute('class', 'column');
360
        $label->appendChild(Widget::Input('settings[email_smtp][from_address]', General::sanitize($this->_sender_email_address), 'text', $readonly));
361
        $div->appendChild($label);
362
363
        $group->appendChild($div);
364
365
        $div = new XMLElement('div');
366
        $div->setAttribute('class', 'two columns');
367
368
        $label = Widget::Label(__('Host'));
369
        $label->setAttribute('class', 'column');
370
        $label->appendChild(Widget::Input('settings[email_smtp][host]', General::sanitize($this->_host), 'text', $readonly));
371
        $div->appendChild($label);
372
373
        $label = Widget::Label(__('Port'));
374
        $label->setAttribute('class', 'column');
375
        $label->appendChild(Widget::Input('settings[email_smtp][port]', General::sanitize((string) $this->_port), 'text', $readonly));
376
        $div->appendChild($label);
377
        $group->appendChild($div);
378
379
        $label = Widget::Label();
380
        $label->setAttribute('class', 'column');
381
        // To fix the issue with checkboxes that do not send a value when unchecked.
382
        $options = array(
383
            array('no',$this->_secure == 'no', __('No encryption')),
384
            array('ssl',$this->_secure == 'ssl', __('SSL encryption')),
385
            array('tls',$this->_secure == 'tls', __('TLS encryption')),
386
        );
387
        $select = Widget::Select('settings[email_smtp][secure]', $options, $readonly);
388
        $label->appendChild($select);
389
        $group->appendChild($label);
390
391
        $group->appendChild(new XMLElement('p', __('For a secure connection, SSL and TLS are supported. Please check the manual of your email provider for more details.'), array('class' => 'help')));
392
393
        $label = Widget::Label();
394
        $label->setAttribute('class', 'column');
395
        // To fix the issue with checkboxes that do not send a value when unchecked.
396
        $group->appendChild(Widget::Input('settings[email_smtp][auth]', '0', 'hidden'));
397
        $input = Widget::Input('settings[email_smtp][auth]', '1', 'checkbox', $readonly);
398
399
        if ($this->_auth === true) {
400
            $input->setAttribute('checked', 'checked');
401
        }
402
403
        $label->setValue(__('%s Requires authentication', array($input->generate())));
404
        $group->appendChild($label);
405
406
        $group->appendChild(new XMLElement('p', __('Some SMTP connections require authentication. If that is the case, enter the username/password combination below.'), array('class' => 'help')));
407
408
        $div = new XMLElement('div');
409
        $div->setAttribute('class', 'two columns');
410
411
        $label = Widget::Label(__('Username'));
412
        $label->setAttribute('class', 'column');
413
        $label->appendChild(Widget::Input('settings[email_smtp][username]', General::sanitize($this->_user), 'text', array_merge($readonly, array('autocomplete' => 'off'))));
414
        $div->appendChild($label);
415
416
        $label = Widget::Label(__('Password'));
417
        $label->setAttribute('class', 'column');
418
        $label->appendChild(Widget::Input('settings[email_smtp][password]', General::sanitize($this->_pass), 'password', array_merge($readonly, array('autocomplete' => 'off'))));
419
        $div->appendChild($label);
420
        $group->appendChild($div);
421
422
        return $group;
423
    }
424
}
425