PageRenderTime 61ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/system/expressionengine/modules/email/mod.email.php

https://bitbucket.org/tdevonshire/hoolux
PHP | 946 lines | 617 code | 171 blank | 158 comment | 162 complexity | 2ffdad3fb653b4fbff6f1bb7f6a92ebd MD5 | raw file
  1. <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
  2. /**
  3. * ExpressionEngine - by EllisLab
  4. *
  5. * @package ExpressionEngine
  6. * @author EllisLab Dev Team
  7. * @copyright Copyright (c) 2003 - 2012, EllisLab, Inc.
  8. * @license http://ellislab.com/expressionengine/user-guide/license.html
  9. * @link http://ellislab.com
  10. * @since Version 2.0
  11. * @filesource
  12. */
  13. // ------------------------------------------------------------------------
  14. /**
  15. * ExpressionEngine Email Module
  16. *
  17. * @package ExpressionEngine
  18. * @subpackage Modules
  19. * @category Update File
  20. * @author EllisLab Dev Team
  21. * @link http://ellislab.com
  22. */
  23. class Email {
  24. var $email_time_interval = '20'; // In seconds
  25. var $email_max_emails = '50'; // Total recipients, not emails
  26. var $use_captchas = 'n';
  27. private $_user_recipients = '';
  28. /**
  29. * Constructor
  30. */
  31. public function __construct()
  32. {
  33. $this->EE =& get_instance();
  34. if ($this->EE->config->item('email_module_captchas') === FALSE OR
  35. $this->EE->config->item('email_module_captchas') == 'n')
  36. {
  37. $this->use_captchas = 'n';
  38. }
  39. elseif ($this->EE->config->item('email_module_captchas') == 'y')
  40. {
  41. $this->use_captchas = ($this->EE->config->item('captcha_require_members') == 'y' OR
  42. ($this->EE->config->item('captcha_require_members') == 'n' AND $this->EE->session->userdata('member_id') == 0)) ? 'y' : 'n';
  43. }
  44. }
  45. // --------------------------------------------------------------------
  46. /**
  47. * Contact Form
  48. */
  49. public function contact_form()
  50. {
  51. $tagdata = $this->EE->TMPL->tagdata;
  52. // Recipient Email Checking
  53. $user_recipients = $this->EE->TMPL->fetch_param('user_recipients', 'no');
  54. // Backwards compatible with previously documented "true/false" parameters (now "yes/no")
  55. $this->_user_recipients = ($user_recipients == 'true' OR $user_recipients == 'yes') ? 'yes' : 'no';
  56. $recipients = $this->EE->TMPL->fetch_param('recipients', '');
  57. $channel = $this->EE->TMPL->fetch_param('channel', '');
  58. // No email left behind act
  59. if ($this->_user_recipients == 'no' && $recipients == '')
  60. {
  61. $recipients = $this->EE->config->item('webmaster_email');
  62. }
  63. // Clean and check recipient emails, if any
  64. if ($recipients != '')
  65. {
  66. $array = $this->validate_recipients($recipients);
  67. // Put together into string again
  68. $recipients = implode(',',$array['approved']);
  69. }
  70. // Conditionals
  71. $cond = array();
  72. $cond['logged_in'] = ($this->EE->session->userdata('member_id') == 0) ? 'FALSE' : 'TRUE';
  73. $cond['logged_out'] = ($this->EE->session->userdata('member_id') != 0) ? 'FALSE' : 'TRUE';
  74. $cond['captcha'] = ($this->use_captchas == 'y') ? 'TRUE' : 'FALSE';
  75. $tagdata = $this->EE->functions->prep_conditionals($tagdata, $cond);
  76. // Load the form helper
  77. $this->EE->load->helper('form');
  78. // Parse "single" variables
  79. foreach ($this->EE->TMPL->var_single as $key => $val)
  80. {
  81. // parse {member_name}
  82. if ($key == 'member_name')
  83. {
  84. $name = ($this->EE->session->userdata['screen_name'] != '') ? $this->EE->session->userdata['screen_name'] : $this->EE->session->userdata['username'];
  85. $tagdata = $this->EE->TMPL->swap_var_single($key, form_prep($name), $tagdata);
  86. }
  87. // {member_email}
  88. if ($key == 'member_email')
  89. {
  90. $email = ($this->EE->session->userdata['email'] == '') ? '' : $this->EE->session->userdata['email'];
  91. $tagdata = $this->EE->TMPL->swap_var_single($key, form_prep($email), $tagdata);
  92. }
  93. // {current_time}
  94. if (strncmp($key, 'current_time', 12) == 0)
  95. {
  96. $now = $this->EE->localize->set_localized_time();
  97. $tagdata = $this->EE->TMPL->swap_var_single($key, $this->EE->localize->decode_date($val,$now), $tagdata);
  98. }
  99. if (($key == 'author_email' OR $key == 'author_name') && ! isset($$key))
  100. {
  101. if ($this->EE->uri->query_string != '')
  102. {
  103. $entry_id = $this->EE->uri->query_string;
  104. if ($channel != '')
  105. {
  106. $this->EE->db->join('channels c', 'c.channel_id = ct.channel_id', 'left');
  107. $this->EE->functions->ar_andor_string($channel, 'c.channel_name');
  108. }
  109. $table = ( ! is_numeric($entry_id)) ? 'ct.url_title' : 'ct.entry_id';
  110. $query = $this->EE->db->select('m.username, m.email, m.screen_name')
  111. ->from(array('channel_titles ct', 'members m'))
  112. ->where('m.member_id = ct.author_id', '', FALSE)
  113. ->where($table, $entry_id)
  114. ->get();
  115. if ($query->num_rows() == 0)
  116. {
  117. $author_name = '';
  118. }
  119. else
  120. {
  121. $author_name = ($query->row('screen_name') != '') ? $query->row('screen_name') : $query->row('username') ;
  122. }
  123. $author_email = ($query->num_rows() == 0) ? '' : $query->row('email') ;
  124. }
  125. else
  126. {
  127. $author_email = '';
  128. $author_name = '';
  129. }
  130. // Do them both now and save ourselves a query
  131. $tagdata = $this->EE->TMPL->swap_var_single('author_email', $author_email, $tagdata);
  132. $tagdata = $this->EE->TMPL->swap_var_single('author_name', $author_name, $tagdata);
  133. }
  134. }
  135. // Create form
  136. return $this->_setup_form($tagdata, $recipients, 'contact_form', FALSE);
  137. }
  138. // --------------------------------------------------------------------
  139. /**
  140. * Tell a friend form
  141. *
  142. * {exp:email:tell_a_friend charset="utf-8" allow_html='n'}
  143. * {exp:email:tell_a_friend charset="utf-8" allow_html='<p>,<a>' recipients='sales@ellislab.com'}
  144. * {member_email}, {member_name}, {current_time format="%Y %d %m"}
  145. */
  146. public function tell_a_friend()
  147. {
  148. if ($this->EE->uri->query_string == '')
  149. {
  150. return FALSE;
  151. }
  152. // Recipient Email Checking
  153. $this->_user_recipients = 'yes'; // By default
  154. $recipients = $this->EE->TMPL->fetch_param('recipients', '');
  155. $charset = $this->EE->TMPL->fetch_param('charset', '');
  156. $allow_html = $this->EE->TMPL->fetch_param('allow_html');
  157. // Equalize $allow_html value
  158. $allow_html = (is_string($allow_html) AND in_array($allow_html, array('yes', 'y', 'true'))) ? TRUE : $allow_html;
  159. $allow_html = (is_string($allow_html) AND in_array($allow_html, array('no', 'n', 'false'))) ? FALSE : $allow_html;
  160. if ( ! $this->EE->TMPL->fetch_param('status'))
  161. {
  162. $this->EE->TMPL->tagparams['status'] = 'open';
  163. }
  164. // Clean and check recipient emails, if any
  165. if ($recipients != '')
  166. {
  167. $array = $this->validate_recipients($recipients);
  168. // Put together into string again
  169. $recipients = implode(',',$array['approved']);
  170. }
  171. // Parse page number
  172. // We need to strip the page number from the URL for two reasons:
  173. // 1. So we can create pagination links
  174. // 2. So it won't confuse the query with an improper proper ID
  175. // Conditionally get query string based on whether or not the page
  176. // was accessed through the Pages module
  177. $qstring = (empty($this->EE->uri->page_query_string)) ? $this->EE->uri->query_string : $this->EE->uri->page_query_string;
  178. if (preg_match("#/P(\d+)#", $qstring, $match))
  179. {
  180. $current_page = $match['1'];
  181. $qstring = $this->EE->functions->remove_double_slashes(str_replace($match[0], '', $qstring));
  182. }
  183. // Remove "N"
  184. // The recent comments feature uses "N" as the URL indicator
  185. // It needs to be removed if presenst
  186. if (preg_match("#/N(\d+)#", $qstring, $match))
  187. {
  188. $qstring = $this->EE->functions->remove_double_slashes(str_replace($match[0], '', $qstring));
  189. }
  190. /* -------------------------------------
  191. /* 'email_module_tellafriend_override' hook.
  192. /* - Allow use of Tell-A-Friend for things besides channel entries
  193. /* - Added EE 1.5.1
  194. */
  195. if ($this->EE->extensions->active_hook('email_module_tellafriend_override') === TRUE)
  196. {
  197. $tagdata = $this->EE->extensions->call('email_module_tellafriend_override', $qstring, $this);
  198. if ($this->EE->extensions->end_script === TRUE) return $tagdata;
  199. }
  200. else // Else Do the Default Channel Processing
  201. {
  202. $entry_id = trim($qstring);
  203. // If there is a slash in the entry ID we'll kill everything after it.
  204. $entry_id = preg_replace("#/.+#", "", $entry_id);
  205. // Do we have a vaild channel and ID number?
  206. $timestamp = ($this->EE->TMPL->cache_timestamp != '') ? $this->EE->TMPL->cache_timestamp : $this->EE->localize->now;
  207. $channel = $this->EE->TMPL->fetch_param('channel', '');
  208. $this->EE->db->select('entry_id')
  209. ->from(array('channel_titles ct', 'channels c'))
  210. ->where('ct.channel_id = c.channel_id', '', FALSE)
  211. ->where('(ct.expiration_date = 0 OR expiration_date > '.$timestamp.')', '', FALSE)
  212. ->where('ct.status !=', 'closed');
  213. $table = ( ! is_numeric($entry_id)) ? 'ct.url_title' : 'ct.entry_id';
  214. $this->EE->db->where($table, $entry_id);
  215. if ($channel != '')
  216. {
  217. $this->EE->functions->ar_andor_string($channel, 'c.channel_name');
  218. }
  219. $query = $this->EE->db->get();
  220. // Bad ID? See ya!
  221. if ($query->num_rows() === 0)
  222. {
  223. return FALSE;
  224. }
  225. // Fetch the channel entry
  226. if ( ! class_exists('Channel'))
  227. {
  228. require PATH_MOD.'channel/mod.channel.php';
  229. }
  230. $channel = new Channel;
  231. $channel->fetch_custom_channel_fields();
  232. $channel->fetch_custom_member_fields();
  233. $channel->build_sql_query();
  234. if ($channel->sql == '')
  235. {
  236. return FALSE;
  237. }
  238. $channel->query = $this->EE->db->query($channel->sql);
  239. if ($channel->query->num_rows() === 0)
  240. {
  241. return FALSE;
  242. }
  243. $this->EE->load->library('typography');
  244. $this->EE->typography->initialize(array(
  245. 'encode_email' => FALSE,
  246. 'convert_curly' => FALSE
  247. ));
  248. $channel->fetch_categories();
  249. $channel->parse_channel_entries();
  250. $tagdata = $channel->return_data;
  251. }
  252. /*
  253. /* -------------------------------------*/
  254. // Parse conditionals
  255. $cond = array();
  256. $cond['captcha'] = ($this->use_captchas == 'y') ? 'TRUE' : 'FALSE';
  257. $tagdata = $this->EE->functions->prep_conditionals($tagdata, $cond);
  258. // Parse tell-a-friend variables
  259. // {member_name}
  260. $tagdata = $this->EE->TMPL->swap_var_single('member_name', $this->EE->session->userdata['screen_name'], $tagdata);
  261. // {member_email}
  262. $tagdata = $this->EE->TMPL->swap_var_single('member_email', $this->EE->session->userdata['email'], $tagdata);
  263. // A little work on the form field's values
  264. // Match values in input fields
  265. $tagdata = $this->_strip_field_html(
  266. $tagdata,
  267. "/<input(.*?)value=\"(.*?)\"/",
  268. $allow_html
  269. );
  270. // Remove line breaks
  271. $LB = 'snookums9loves4wookie';
  272. $tagdata = str_replace(array("\r\n", "\r", "\n"), $LB, $tagdata);
  273. // Match textarea content
  274. $tagdata = $this->_strip_field_html(
  275. $tagdata,
  276. "/<textarea(.*?)>(.*?)<\/textarea>/",
  277. $allow_html
  278. );
  279. $tagdata = str_replace($LB, "\n", $tagdata);
  280. $allow = ($allow_html !== FALSE) ? TRUE : FALSE;
  281. return $this->_setup_form($tagdata, $recipients, 'tellafriend_form', $allow);
  282. }
  283. // --------------------------------------------------------------------
  284. /**
  285. * Strips fields of HTML based on $allow_html
  286. *
  287. * @param string $template Template string to parse
  288. * @param string $field_regex Regular expression for the form field to
  289. * search for
  290. * @param bool|string $allow_html Either boolean if completely allowing or
  291. * disallowing html or a comma delimited string of html elements to
  292. * explicitly allow
  293. *
  294. * @return string $template with html parsed out of it
  295. */
  296. private function _strip_field_html($template, $field_regex, $allow_html)
  297. {
  298. // Make sure allow_html isn't true first, then run preg_match_all
  299. if ($allow_html !== TRUE
  300. AND preg_match_all($field_regex, $template, $matches))
  301. {
  302. foreach($matches['2'] as $value)
  303. {
  304. if ($allow_html === FALSE)
  305. {
  306. $new = strip_tags($value);
  307. }
  308. else
  309. {
  310. $new = strip_tags($value, $allow_html);
  311. }
  312. $template = str_replace($value, $new, $template);
  313. }
  314. }
  315. return $template;
  316. }
  317. // -------------------------------------------------------------------------
  318. /**
  319. * Send Email
  320. */
  321. public function send_email()
  322. {
  323. $error = array();
  324. // Blacklist/Whitelist Check
  325. if ($this->EE->blacklist->blacklisted == 'y' && $this->EE->blacklist->whitelisted == 'n')
  326. {
  327. return $this->EE->output->show_user_error('general', array(lang('not_authorized')));
  328. }
  329. // Is the nation of the user banend?
  330. $this->EE->session->nation_ban_check();
  331. // Check and Set
  332. $default = array(
  333. 'subject', 'message', 'from', 'user_recipients', 'to',
  334. 'recipients', 'name', 'required'
  335. );
  336. foreach ($default as $val)
  337. {
  338. if ( ! isset($_POST[$val]))
  339. {
  340. $_POST[$val] = '';
  341. }
  342. else
  343. {
  344. if (is_array($_POST[$val]) && ($val == 'message' OR $val == 'required'))
  345. {
  346. $temp = '';
  347. foreach($_POST[$val] as $post_value)
  348. {
  349. $temp .= $this->EE->input->_clean_input_data($post_value)."\n";
  350. }
  351. $_POST[$val] = $temp;
  352. }
  353. if ($val == 'recipients')
  354. {
  355. if ( function_exists('mcrypt_encrypt') )
  356. {
  357. $init_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
  358. $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
  359. $decoded_recipients = rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($this->EE->db->username.$this->EE->db->password), base64_decode($_POST[$val]), MCRYPT_MODE_ECB, $init_vect), "\0");
  360. }
  361. else
  362. {
  363. $raw = base64_decode($_POST[$val]);
  364. $hash = substr($raw, -32);
  365. $decoded_recipients = substr($raw, 0, -32);
  366. if ($hash != md5($this->EE->db->username.$this->EE->db->password.$decoded_recipients))
  367. {
  368. $decoded_recipients = '';
  369. }
  370. }
  371. $_POST[$val] = $decoded_recipients;
  372. }
  373. $_POST[$val] = $this->EE->security->xss_clean(trim(stripslashes($_POST[$val])));
  374. }
  375. }
  376. // Clean incoming
  377. $clean = array('subject', 'from', 'user_recipients', 'to', 'recipients', 'name');
  378. foreach ($clean as $val)
  379. {
  380. $_POST[$val] = strip_tags($_POST[$val]);
  381. }
  382. $this->EE->lang->loadfile('email');
  383. // Basic Security Check
  384. if ($this->EE->session->userdata('ip_address') == '' OR
  385. $this->EE->session->userdata('user_agent') == '')
  386. {
  387. return $this->EE->output->show_user_error('general', array(lang('em_unauthorized_request')));
  388. }
  389. // Return Variables
  390. $x = explode('|',$_POST['RET']);
  391. unset($_POST['RET']);
  392. if (is_numeric($x['0']))
  393. {
  394. $return_link = $this->EE->functions->form_backtrack($x['0']);
  395. }
  396. else
  397. {
  398. $return_link = $x[0];
  399. if ($x[0] == '' OR ! preg_match('{^http(s)?:\/\/}i', $x[0]))
  400. {
  401. $return_link = $this->EE->functions->form_backtrack(1);
  402. }
  403. }
  404. $site_name = ($this->EE->config->item('site_name') == '') ? lang('back') : stripslashes($this->EE->config->item('site_name'));
  405. $return_name = ( ! isset($x['1']) OR $x['1'] == '') ? $site_name : $x['1'];
  406. // ERROR Checking
  407. // If the message is empty, bounce them back
  408. if ($_POST['message'] == '')
  409. {
  410. return $this->EE->output->show_user_error('general', array(lang('message_required')));
  411. }
  412. // If the from field is empty, error
  413. $this->EE->load->helper('email');
  414. if ($_POST['from'] == '' OR ! valid_email($_POST['from']))
  415. {
  416. return $this->EE->output->show_user_error('general', array(lang('em_sender_required')));
  417. }
  418. // If no recipients, bounce them back
  419. if ($_POST['recipients'] == '' && $_POST['to'] == '')
  420. {
  421. return $this->EE->output->show_user_error('general', array(lang('em_no_valid_recipients')));
  422. }
  423. // Is the user banned?
  424. if ($this->EE->session->userdata['is_banned'] == TRUE)
  425. {
  426. return $this->EE->output->show_user_error('general', array(lang('not_authorized')));
  427. }
  428. // Check Form Hash
  429. if ( ! $this->EE->security->secure_forms_check($this->EE->input->post('XID')))
  430. {
  431. return $this->EE->output->show_user_error('general', array(lang('not_authorized')));
  432. }
  433. // Check Tracking Class
  434. $day_ago = $this->EE->localize->now - 60*60*24;
  435. $query = $this->EE->db->query("DELETE FROM exp_email_tracker WHERE email_date < '{$day_ago}'");
  436. if ($this->EE->session->userdata['username'] === false OR $this->EE->session->userdata['username'] == '')
  437. {
  438. $query = $this->EE->db->query("SELECT *
  439. FROM exp_email_tracker
  440. WHERE sender_ip = '".$this->EE->input->ip_address()."'
  441. ORDER BY email_date DESC");
  442. }
  443. else
  444. {
  445. $query = $this->EE->db->query("SELECT *
  446. FROM exp_email_tracker
  447. WHERE sender_username = '".$this->EE->db->escape_str($this->EE->session->userdata['username'])."'
  448. OR sender_ip = '".$this->EE->input->ip_address()."'
  449. ORDER BY email_date DESC");
  450. }
  451. if ($query->num_rows() > 0)
  452. {
  453. // Max Emails - Quick check
  454. if ($query->num_rows() >= $this->email_max_emails)
  455. {
  456. return $this->EE->output->show_user_error('general', array(lang('em_limit_exceeded')));
  457. }
  458. // Max Emails - Indepth check
  459. $total_sent = 0;
  460. foreach($query->result_array() as $row)
  461. {
  462. $total_sent = $total_sent + $row['number_recipients'];
  463. }
  464. if ($total_sent >= $this->email_max_emails)
  465. {
  466. return $this->EE->output->show_user_error('general', array(lang('em_limit_exceeded')));
  467. }
  468. // Interval check
  469. if ($query->row('email_date') > ($this->EE->localize->now - $this->email_time_interval))
  470. {
  471. $error[] = str_replace("%s", $this->email_time_interval, lang('em_interval_warning'));
  472. return $this->EE->output->show_user_error('general', $error);
  473. }
  474. }
  475. // Review Recipients
  476. $_POST['user_recipients'] = ($_POST['user_recipients'] == md5($this->EE->db->username.$this->EE->db->password.'y')) ? 'y' : 'n';
  477. if ($_POST['user_recipients'] == 'y' && trim($_POST['to']) != '')
  478. {
  479. $array = $this->validate_recipients($_POST['to']);
  480. $error = array_merge($error, $array['error']);
  481. $approved_tos = $array['approved'];
  482. }
  483. else
  484. {
  485. $approved_tos = array();
  486. }
  487. if (trim($_POST['recipients']) != '')
  488. {
  489. $array = $this->validate_recipients($_POST['recipients']);
  490. $approved_recipients = $array['approved'];
  491. }
  492. else
  493. {
  494. $approved_recipients = array();
  495. }
  496. // If we have no valid emails to send, back they go.
  497. if ($_POST['user_recipients'] == 'y' && count($approved_tos) == 0)
  498. {
  499. $error[] = lang('em_no_valid_recipients');
  500. }
  501. elseif ( count($approved_recipients) == 0 && count($approved_tos) == 0)
  502. {
  503. $error[] = lang('em_no_valid_recipients');
  504. }
  505. // Is from email banned?
  506. if ($this->EE->session->ban_check('email', $_POST['from']))
  507. {
  508. $error[] = lang('em_banned_from_email');
  509. }
  510. // Do we have errors to display?
  511. if (count($error) > 0)
  512. {
  513. return $this->EE->output->show_user_error('submission', $error);
  514. }
  515. // Check CAPTCHA
  516. if ($this->use_captchas == 'y')
  517. {
  518. if ( ! isset($_POST['captcha']) OR $_POST['captcha'] == '')
  519. {
  520. return $this->EE->output->show_user_error('general', array(lang('captcha_required')));
  521. }
  522. $query = $this->EE->db->query("SELECT COUNT(*) AS count FROM exp_captcha
  523. WHERE word='".$this->EE->db->escape_str($_POST['captcha'])."'
  524. AND ip_address = '".$this->EE->input->ip_address()."'
  525. AND date > UNIX_TIMESTAMP()-7200");
  526. if ($query->row('count') == 0)
  527. {
  528. return $this->EE->output->show_user_error('submission', array(lang('captcha_incorrect')));
  529. }
  530. $this->EE->db->query("DELETE FROM exp_captcha
  531. WHERE (word='".$this->EE->db->escape_str($_POST['captcha'])."'
  532. AND ip_address = '".$this->EE->input->ip_address()."')
  533. OR date < UNIX_TIMESTAMP()-7200");
  534. }
  535. // Censored Word Checking
  536. $this->EE->load->library('typography');
  537. $this->EE->typography->initialize();
  538. // Load the text helper
  539. $this->EE->load->helper('text');
  540. $subject = entities_to_ascii($_POST['subject']);
  541. $subject = $this->EE->typography->filter_censored_words($subject);
  542. $message = ($_POST['required'] != '') ? $_POST['required']."\n".$_POST['message'] : $_POST['message'];
  543. $message = $this->EE->security->xss_clean($message);
  544. if (isset($_POST['allow_html']) && $_POST['allow_html'] == 'y' &&
  545. strlen(strip_tags($message)) != strlen($message))
  546. {
  547. $mail_type = 'html';
  548. }
  549. else
  550. {
  551. $mail_type = 'plain';
  552. }
  553. $message = entities_to_ascii($message);
  554. $message = $this->EE->typography->filter_censored_words($message);
  555. // Send email
  556. $this->EE->load->library('email');
  557. $this->EE->email->wordwrap = true;
  558. $this->EE->email->mailtype = $mail_type;
  559. $this->EE->email->priority = '3';
  560. if (isset($_POST['charset']) && $_POST['charset'] != '')
  561. {
  562. $this->EE->email->charset = $_POST['charset'];
  563. }
  564. if ( count($approved_recipients) == 0 && count($approved_tos) > 0) // No Hidden Recipients
  565. {
  566. foreach ($approved_tos as $val)
  567. {
  568. $this->EE->email->EE_initialize();
  569. $this->EE->email->to($val);
  570. if (isset($_POST['replyto']) && $_POST['replyto'] == 'yes')
  571. {
  572. $this->EE->email->from($this->EE->config->item('webmaster_email'), $this->EE->config->item('webmaster_name'));
  573. $this->EE->email->reply_to($_POST['from'], $_POST['name']);
  574. }
  575. else
  576. {
  577. $this->EE->email->from($_POST['from'],$_POST['name']);
  578. }
  579. $this->EE->email->subject($subject);
  580. $this->EE->email->message($message);
  581. $this->EE->email->send();
  582. }
  583. }
  584. elseif ( count($approved_recipients) > 0 && count($approved_tos) == 0) // Hidden Recipients Only
  585. {
  586. foreach ($approved_recipients as $val)
  587. {
  588. $this->EE->email->EE_initialize();
  589. $this->EE->email->to($val);
  590. if (isset($_POST['replyto']) && $_POST['replyto'] == 'yes')
  591. {
  592. $this->EE->email->from($this->EE->config->item('webmaster_email'), $this->EE->config->item('webmaster_name'));
  593. $this->EE->email->reply_to($_POST['from'], $_POST['name']);
  594. }
  595. else
  596. {
  597. $this->EE->email->from($_POST['from'],$_POST['name']);
  598. }
  599. $this->EE->email->subject($subject);
  600. $this->EE->email->message($message);
  601. $this->EE->email->send();
  602. }
  603. }
  604. else // Combination of Hidden and Regular Recipients, BCC hidden on every regular recipient email
  605. {
  606. foreach ($approved_tos as $val)
  607. {
  608. $this->EE->email->EE_initialize();
  609. $this->EE->email->to($val);
  610. $this->EE->email->bcc(implode(',', $approved_recipients));
  611. if (isset($_POST['replyto']) && $_POST['replyto'] == 'yes')
  612. {
  613. $this->EE->email->from($this->EE->config->item('webmaster_email'), $this->EE->config->item('webmaster_name'));
  614. $this->EE->email->reply_to($_POST['from'], $_POST['name']);
  615. }
  616. else
  617. {
  618. $this->EE->email->from($_POST['from'], $_POST['name']);
  619. }
  620. $this->EE->email->subject($subject);
  621. $this->EE->email->message($message);
  622. $this->EE->email->send();
  623. }
  624. }
  625. // Store in tracking class
  626. $data = array(
  627. 'email_date' => $this->EE->localize->now,
  628. 'sender_ip' => $this->EE->input->ip_address(),
  629. 'sender_email' => $_POST['from'],
  630. 'sender_username' => $this->EE->session->userdata['username'],
  631. 'number_recipients' => count($approved_tos) + count($approved_recipients)
  632. );
  633. $this->EE->db->query($this->EE->db->insert_string('exp_email_tracker', $data));
  634. /* -------------------------------------
  635. /* 'email_module_send_email_end' hook.
  636. /* - After emails are sent, do some additional processing
  637. /* - Added EE 1.5.1
  638. */
  639. if ($this->EE->extensions->active_hook('email_module_send_email_end') === TRUE)
  640. {
  641. $edata = $this->EE->extensions->call('email_module_send_email_end', $subject, $message, $approved_tos, $approved_recipients);
  642. if ($this->EE->extensions->end_script === TRUE) return;
  643. }
  644. /*
  645. /* -------------------------------------*/
  646. // Thank you message
  647. $data = array(
  648. 'title' => lang('email_module_name'),
  649. 'heading' => lang('thank_you'),
  650. 'content' => lang('em_email_sent'),
  651. 'redirect' => $return_link,
  652. 'link' => array($return_link, $return_name)
  653. );
  654. if ($this->EE->input->get_post('redirect') !== FALSE)
  655. {
  656. if(is_numeric($this->EE->input->get_post('redirect')))
  657. {
  658. $data['rate'] = $this->EE->input->get_post('redirect');
  659. }
  660. elseif($this->EE->input->get_post('redirect') == 'none')
  661. {
  662. $data['redirect'] = '';
  663. }
  664. }
  665. $this->EE->output->show_message($data);
  666. }
  667. // --------------------------------------------------------------------
  668. /**
  669. * Validate List of Emails
  670. */
  671. function validate_recipients($str)
  672. {
  673. // Remove white space and replace with comma
  674. $recipients = preg_replace("/\s*(\S+)\s*/", "\\1,", $str);
  675. // Remove any existing doubles
  676. $recipients = str_replace(",,", ",", $recipients);
  677. // Remove any comma at the end
  678. if (substr($recipients, -1) == ",")
  679. {
  680. $recipients = substr($recipients, 0, -1);
  681. }
  682. // Break into an array via commas and remove duplicates
  683. $emails = preg_split('/[,]/', $recipients);
  684. $emails = array_unique($emails);
  685. // Emails to send email to...
  686. $error = array();
  687. $approved_emails = array();
  688. $this->EE->load->helper('email');
  689. foreach ($emails as $email)
  690. {
  691. if (trim($email) == '') continue;
  692. if (valid_email($email))
  693. {
  694. if ( ! $this->EE->session->ban_check('email', $email))
  695. {
  696. $approved_emails[] = $email;
  697. }
  698. else
  699. {
  700. $error['ban_recp'] = lang('em_banned_recipient');
  701. }
  702. }
  703. else
  704. {
  705. $error['bad_recp'] = lang('em_invalid_recipient');
  706. }
  707. }
  708. return array('approved' => $approved_emails, 'error' => $error);
  709. }
  710. // --------------------------------------------------------------------
  711. /**
  712. * Setup forms
  713. *
  714. * @param string $tagdata
  715. * @param string $recipients
  716. * @param string $form_id
  717. * @param boolean
  718. * @return string
  719. */
  720. private function _setup_form($tagdata, $recipients, $form_id = NULL, $allow_html = FALSE)
  721. {
  722. $charset = $this->EE->TMPL->fetch_param('charset', '');
  723. $recipients = $this->_encrypt_recipients($recipients);
  724. $data = array(
  725. 'id' => ($this->EE->TMPL->form_id == '') ? $form_id : $this->EE->TMPL->form_id,
  726. 'class' => $this->EE->TMPL->form_class,
  727. 'hidden_fields' => array(
  728. 'ACT' => $this->EE->functions->fetch_action_id('Email', 'send_email'),
  729. 'RET' => $this->EE->TMPL->fetch_param('return', ''),
  730. 'URI' => ($this->EE->uri->uri_string == '') ? 'index' : $this->EE->uri->uri_string,
  731. 'recipients' => base64_encode($recipients),
  732. 'user_recipients' => ($this->_user_recipients == 'yes') ? md5($this->EE->db->username.$this->EE->db->password.'y') : md5($this->EE->db->username.$this->EE->db->password.'n'),
  733. 'charset' => $charset,
  734. 'redirect' => $this->EE->TMPL->fetch_param('redirect', ''),
  735. 'replyto' => $this->EE->TMPL->fetch_param('replyto', '')
  736. )
  737. );
  738. if ($allow_html)
  739. {
  740. $data['hidden_fields']['allow_html'] = 'y';
  741. }
  742. $name = $this->EE->TMPL->fetch_param('name', FALSE);
  743. if ($name && preg_match("#^[a-zA-Z0-9_\-]+$#i", $name, $match))
  744. {
  745. $data['name'] = $name;
  746. }
  747. $res = $this->EE->functions->form_declaration($data);
  748. $res .= stripslashes($tagdata);
  749. $res .= "</form>";//echo $res; exit;
  750. return $res;
  751. }
  752. // --------------------------------------------------------------------
  753. /**
  754. * Encrypt Recipients list
  755. */
  756. private function _encrypt_recipients($recipients)
  757. {
  758. if (function_exists('mcrypt_encrypt'))
  759. {
  760. $init_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB);
  761. $init_vect = mcrypt_create_iv($init_size, MCRYPT_RAND);
  762. return mcrypt_encrypt(
  763. MCRYPT_RIJNDAEL_256,
  764. md5($this->EE->db->username.$this->EE->db->password),
  765. $recipients,
  766. MCRYPT_MODE_ECB,
  767. $init_vect
  768. );
  769. }
  770. return $recipients.md5($this->EE->db->username.$this->EE->db->password.$recipients);
  771. }
  772. }
  773. // END CLASS
  774. /* End of file mod.email.php */
  775. /* Location: ./system/expressionengine/modules/email/mod.email.php */