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) <phpmailer@synchromedia.co.uk>
8 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
9 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
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) <phpmailer@synchromedia.co.uk>
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 * @throws phpmailerException
84 */
85 public function smtpConnect($options = array())
86 {
87 if (is_null($this->smtp)) {
88 $this->smtp = $this->getSMTPInstance();
89 }
90
91 if (is_null($this->oauth)) {
92 $this->oauth = $this->getOAUTHInstance();
93 }
94
95 // Already connected?
96 if ($this->smtp->connected()) {
97 return true;
98 }
99
100 $this->smtp->setTimeout($this->Timeout);
101 $this->smtp->setDebugLevel($this->SMTPDebug);
102 $this->smtp->setDebugOutput($this->Debugoutput);
103 $this->smtp->setVerp($this->do_verp);
104 $hosts = explode(';', $this->Host);
105 $lastexception = null;
106
107 foreach ($hosts as $hostentry) {
108 $hostinfo = array();
109 if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
110 // Not a valid host entry
111 continue;
112 }
113 // $hostinfo[2]: optional ssl or tls prefix
114 // $hostinfo[3]: the hostname
115 // $hostinfo[4]: optional port number
116 // The host string prefix can temporarily override the current setting for SMTPSecure
117 // If it's not specified, the default value is used
118 $prefix = '';
119 $secure = $this->SMTPSecure;
120 $tls = ($this->SMTPSecure == 'tls');
121 if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
122 $prefix = 'ssl://';
123 $tls = false; // Can't have SSL and TLS at the same time
124 $secure = 'ssl';
125 } elseif ($hostinfo[2] == 'tls') {
126 $tls = true;
127 // tls doesn't use a prefix
128 $secure = 'tls';
129 }
130 //Do we need the OpenSSL extension?
131 $sslext = defined('OPENSSL_ALGO_SHA1');
132 if ('tls' === $secure or 'ssl' === $secure) {
133 //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
134 if (!$sslext) {
135 throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
136 }
137 }
138 $host = $hostinfo[3];
139 $port = $this->Port;
140 $tport = (integer)$hostinfo[4];
141 if ($tport > 0 and $tport < 65536) {
142 $port = $tport;
143 }
144 if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
145 try {
146 if ($this->Helo) {
147 $hello = $this->Helo;
148 } else {
149 $hello = $this->serverHostname();
150 }
151 $this->smtp->hello($hello);
152 //Automatically enable TLS encryption if:
153 // * it's not disabled
154 // * we have openssl extension
155 // * we are not already using SSL
156 // * the server offers STARTTLS
157 if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
158 $tls = true;
159 }
160 if ($tls) {
161 if (!$this->smtp->startTLS()) {
162 throw new phpmailerException($this->lang('connect_host'));
163 }
164 // We must resend HELO after tls negotiation
165 $this->smtp->hello($hello);
166 }
167 if ($this->SMTPAuth) {
168 if (!$this->smtp->authenticate(
169 $this->Username,
170 $this->Password,
171 $this->AuthType,
172 $this->Realm,
173 $this->Workstation,
174 $this->oauth
175 )
176 ) {
177 throw new phpmailerException($this->lang('authenticate'));
178 }
179 }
180 return true;
181 } catch (phpmailerException $exc) {
182 $lastexception = $exc;
183 $this->edebug($exc->getMessage());
184 // We must have connected, but then failed TLS or Auth, so close connection nicely
185 $this->smtp->quit();
186 }
187 }
188 }
189 // If we get here, all connection attempts have failed, so close connection hard
190 $this->smtp->close();
191 // As we've caught all exceptions, just report whatever the last one was
192 if ($this->exceptions and !is_null($lastexception)) {
193 throw $lastexception;
194 }
195 return false;
196 }
197 }
198