Completed
Pull Request — master (#133)
by Goffy
16:45
created

PHPMailerOAuth   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 171
Duplicated Lines 47.95 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 82
loc 171
rs 10
c 0
b 0
f 0
wmc 30
lcom 1
cbo 4

2 Methods

Rating   Name   Duplication   Size   Complexity  
A getOAUTHInstance() 0 12 2
F smtpConnect() 82 112 28

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
/**
3
 * PHPMailer - PHP email creation and transport class.
4
 * PHP Version 5.4
5
 * @package PHPMailer
6
 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
7
 * @author Marcus Bointon (Synchro/coolbru) <[email protected]>
8
 * @author Jim Jagielski (jimjag) <[email protected]>
9
 * @author Andy Prevost (codeworxtech) <[email protected]>
10
 * @author Brent R. Matzelle (original founder)
11
 * @copyright 2012 - 2014 Marcus Bointon
12
 * @copyright 2010 - 2012 Jim Jagielski
13
 * @copyright 2004 - 2009 Andy Prevost
14
 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
15
 * @note This program is distributed in the hope that it will be useful - WITHOUT
16
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
 * FITNESS FOR A PARTICULAR PURPOSE.
18
 */
19
20
/**
21
 * PHPMailerOAuth - PHPMailer subclass adding OAuth support.
22
 * @package PHPMailer
23
 * @author @sherryl4george
24
 * @author Marcus Bointon (@Synchro) <[email protected]>
25
 */
26
class PHPMailerOAuth extends PHPMailer
27
{
28
    /**
29
     * The OAuth user's email address
30
     * @var string
31
     */
32
    public $oauthUserEmail = '';
33
34
    /**
35
     * The OAuth refresh token
36
     * @var string
37
     */
38
    public $oauthRefreshToken = '';
39
40
    /**
41
     * The OAuth client ID
42
     * @var string
43
     */
44
    public $oauthClientId = '';
45
46
    /**
47
     * The OAuth client secret
48
     * @var string
49
     */
50
    public $oauthClientSecret = '';
51
52
    /**
53
     * An instance of the PHPMailerOAuthGoogle class.
54
     * @var PHPMailerOAuthGoogle
55
     * @access protected
56
     */
57
    protected $oauth = null;
58
59
    /**
60
     * Get a PHPMailerOAuthGoogle instance to use.
61
     * @return PHPMailerOAuthGoogle
62
     */
63
    public function getOAUTHInstance()
64
    {
65
        if (!is_object($this->oauth)) {
66
            $this->oauth = new PHPMailerOAuthGoogle(
67
                $this->oauthUserEmail,
68
                $this->oauthClientSecret,
69
                $this->oauthClientId,
70
                $this->oauthRefreshToken
71
            );
72
        }
73
        return $this->oauth;
74
    }
75
76
    /**
77
     * Initiate a connection to an SMTP server.
78
     * Overrides the original smtpConnect method to add support for OAuth.
79
     * @param array $options An array of options compatible with stream_context_create()
80
     * @uses SMTP
81
     * @access public
82
     * @return bool
83
     */
84
    public function smtpConnect($options = array())
85
    {
86
        if (is_null($this->smtp)) {
87
            $this->smtp = $this->getSMTPInstance();
88
        }
89
90
        if (is_null($this->oauth)) {
91
            $this->oauth = $this->getOAUTHInstance();
92
        }
93
94
        // Already connected?
95
        if ($this->smtp->connected()) {
96
            return true;
97
        }
98
99
        $this->smtp->setTimeout($this->Timeout);
100
        $this->smtp->setDebugLevel($this->SMTPDebug);
101
        $this->smtp->setDebugOutput($this->Debugoutput);
102
        $this->smtp->setVerp($this->do_verp);
103
        $hosts = explode(';', $this->Host);
104
        $lastexception = null;
105
106 View Code Duplication
        foreach ($hosts as $hostentry) {
107
            $hostinfo = array();
108
            if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
109
                // Not a valid host entry
110
                continue;
111
            }
112
            // $hostinfo[2]: optional ssl or tls prefix
113
            // $hostinfo[3]: the hostname
114
            // $hostinfo[4]: optional port number
115
            // The host string prefix can temporarily override the current setting for SMTPSecure
116
            // If it's not specified, the default value is used
117
            $prefix = '';
118
            $secure = $this->SMTPSecure;
119
            $tls = ($this->SMTPSecure == 'tls');
120
            if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
121
                $prefix = 'ssl://';
122
                $tls = false; // Can't have SSL and TLS at the same time
123
                $secure = 'ssl';
124
            } elseif ($hostinfo[2] == 'tls') {
125
                $tls = true;
126
                // tls doesn't use a prefix
127
                $secure = 'tls';
128
            }
129
            //Do we need the OpenSSL extension?
130
            $sslext = defined('OPENSSL_ALGO_SHA1');
131
            if ('tls' === $secure or 'ssl' === $secure) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as or instead of || is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
132
                //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
133
                if (!$sslext) {
134
                    throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
135
                }
136
            }
137
            $host = $hostinfo[3];
138
            $port = $this->Port;
139
            $tport = (integer)$hostinfo[4];
140
            if ($tport > 0 and $tport < 65536) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
141
                $port = $tport;
142
            }
143
            if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
144
                try {
145
                    if ($this->Helo) {
146
                        $hello = $this->Helo;
147
                    } else {
148
                        $hello = $this->serverHostname();
149
                    }
150
                    $this->smtp->hello($hello);
151
                    //Automatically enable TLS encryption if:
152
                    // * it's not disabled
153
                    // * we have openssl extension
154
                    // * we are not already using SSL
155
                    // * the server offers STARTTLS
156
                    if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
157
                        $tls = true;
158
                    }
159
                    if ($tls) {
160
                        if (!$this->smtp->startTLS()) {
161
                            throw new phpmailerException($this->lang('connect_host'));
162
                        }
163
                        // We must resend HELO after tls negotiation
164
                        $this->smtp->hello($hello);
165
                    }
166
                    if ($this->SMTPAuth) {
167
                        if (!$this->smtp->authenticate(
168
                            $this->Username,
169
                            $this->Password,
170
                            $this->AuthType,
171
                            $this->Realm,
172
                            $this->Workstation,
173
                            $this->oauth
174
                        )
175
                        ) {
176
                            throw new phpmailerException($this->lang('authenticate'));
177
                        }
178
                    }
179
                    return true;
180
                } catch (phpmailerException $exc) {
181
                    $lastexception = $exc;
182
                    $this->edebug($exc->getMessage());
183
                    // We must have connected, but then failed TLS or Auth, so close connection nicely
184
                    $this->smtp->quit();
185
                }
186
            }
187
        }
188
        // If we get here, all connection attempts have failed, so close connection hard
189
        $this->smtp->close();
190
        // As we've caught all exceptions, just report whatever the last one was
191
        if ($this->exceptions and !is_null($lastexception)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
192
            throw $lastexception;
193
        }
194
        return false;
195
    }
196
}
197