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
Push — integration ( 45cc9f...98bc42 )
by Brendan
05:52
created

SMTPGateway::send()   F

Complexity

Conditions 15
Paths 2472

Size

Total Lines 93
Code Lines 51

Duplication

Lines 15
Ratio 16.13 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 15
eloc 51
c 2
b 1
f 0
nc 2472
nop 0
dl 15
loc 93
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
     * 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') targeting Configuration::get() can also be of type string; however, SMTPGateway::setConfiguration() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

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 View Code Duplication
            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 View Code Duplication
            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),
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);
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) {
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
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
        if ($config['auth'] === 1) {
321
            $this->setAuth(true);
322
            $this->setUser($config['username']);
323
            $this->setPass($config['password']);
324
        } else {
325
            $this->setAuth(false);
326
            $this->setUser('');
327
            $this->setPass('');
328
        }
329
    }
330
331
    /**
332
     * Builds the preferences pane, shown in the Symphony backend.
333
     *
334
     * @throws InvalidArgumentException
335
     * @return XMLElement
336
     */
337
    public function getPreferencesPane()
338
    {
339
        parent::getPreferencesPane();
340
        $group = new XMLElement('fieldset');
341
        $group->setAttribute('class', 'settings condensed pickable');
342
        $group->setAttribute('id', 'smtp');
343
        $group->appendChild(new XMLElement('legend', __('Email: SMTP')));
344
345
        $div = new XMLElement('div');
346
347
        $readonly = array('readonly' => 'readonly');
348
349
        $label = Widget::Label(__('HELO Hostname'));
350
        $label->appendChild(Widget::Input('settings[email_smtp][helo_hostname]', $this->_helo_hostname, 'text', $readonly));
351
        $div->appendChild($label);
352
353
        $group->appendChild($div);
354
        $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')));
355
356
        $div = new XMLElement('div');
357
        $div->setAttribute('class', 'two columns');
358
359
        $label = Widget::Label(__('From Name'));
360
        $label->setAttribute('class', 'column');
361
        $label->appendChild(Widget::Input('settings[email_smtp][from_name]', $this->_sender_name, 'text', $readonly));
362
        $div->appendChild($label);
363
364
        $label = Widget::Label(__('From Email Address'));
365
        $label->setAttribute('class', 'column');
366
        $label->appendChild(Widget::Input('settings[email_smtp][from_address]', $this->_sender_email_address, 'text', $readonly));
367
        $div->appendChild($label);
368
369
        $group->appendChild($div);
370
371
        $div = new XMLElement('div');
372
        $div->setAttribute('class', 'two columns');
373
374
        $label = Widget::Label(__('Host'));
375
        $label->setAttribute('class', 'column');
376
        $label->appendChild(Widget::Input('settings[email_smtp][host]', $this->_host, 'text', $readonly));
377
        $div->appendChild($label);
378
379
        $label = Widget::Label(__('Port'));
380
        $label->setAttribute('class', 'column');
381
        $label->appendChild(Widget::Input('settings[email_smtp][port]', (string)$this->_port, 'text', $readonly));
382
        $div->appendChild($label);
383
        $group->appendChild($div);
384
385
        $label = Widget::Label();
386
        $label->setAttribute('class', 'column');
387
        // To fix the issue with checkboxes that do not send a value when unchecked.
388
        $options = array(
389
            array('no',$this->_secure === 'no', __('No encryption')),
390
            array('ssl',$this->_secure === 'ssl', __('SSL encryption')),
391
            array('tls',$this->_secure === 'tls', __('TLS encryption')),
392
        );
393
        $select = Widget::Select('settings[email_smtp][secure]', $options, $readonly);
394
        $label->appendChild($select);
395
        $group->appendChild($label);
396
397
        $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')));
398
399
        $label = Widget::Label();
400
        $label->setAttribute('class', 'column');
401
        // To fix the issue with checkboxes that do not send a value when unchecked.
402
        $group->appendChild(Widget::Input('settings[email_smtp][auth]', '0', 'hidden'));
403
        $input = Widget::Input('settings[email_smtp][auth]', '1', 'checkbox', $readonly);
404
405
        if ($this->_auth === true) {
406
            $input->setAttribute('checked', 'checked');
407
        }
408
409
        $label->setValue(__('%s Requires authentication', array($input->generate())));
410
        $group->appendChild($label);
411
412
        $group->appendChild(new XMLElement('p', __('Some SMTP connections require authentication. If that is the case, enter the username/password combination below.'), array('class' => 'help')));
413
414
        $div = new XMLElement('div');
415
        $div->setAttribute('class', 'two columns');
416
417
        $label = Widget::Label(__('Username'));
418
        $label->setAttribute('class', 'column');
419
        $label->appendChild(Widget::Input('settings[email_smtp][username]', $this->_user, 'text', array_merge($readonly, array('autocomplete' => 'off'))));
420
        $div->appendChild($label);
421
422
        $label = Widget::Label(__('Password'));
423
        $label->setAttribute('class', 'column');
424
        $label->appendChild(Widget::Input('settings[email_smtp][password]', $this->_pass, 'password', array_merge($readonly, array('autocomplete' => 'off'))));
425
        $div->appendChild($label);
426
        $group->appendChild($div);
427
428
        return $group;
429
    }
430
}
431