ManageMail.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. <?php
  2. /**
  3. * Simple Machines Forum (SMF)
  4. *
  5. * @package SMF
  6. * @author Simple Machines http://www.simplemachines.org
  7. * @copyright 2011 Simple Machines
  8. * @license http://www.simplemachines.org/about/smf/license.php BSD
  9. *
  10. * @version 2.0
  11. */
  12. if (!defined('SMF'))
  13. die('Hacking attempt...');
  14. /* This file is all about mail, how we love it so. In particular it handles the admin side of
  15. mail configuration, as well as reviewing the mail queue - if enabled.
  16. void ManageMail()
  17. // !!
  18. void BrowseMailQueue()
  19. // !!
  20. void ModifyMailSettings()
  21. // !!
  22. void ClearMailQueue()
  23. // !!
  24. */
  25. // This function passes control through to the relevant section
  26. function ManageMail()
  27. {
  28. global $context, $txt, $scripturl, $modSettings, $sourcedir;
  29. // You need to be an admin to edit settings!
  30. isAllowedTo('admin_forum');
  31. loadLanguage('Help');
  32. loadLanguage('ManageMail');
  33. // We'll need the utility functions from here.
  34. require_once($sourcedir . '/ManageServer.php');
  35. $context['page_title'] = $txt['mailqueue_title'];
  36. $context['sub_template'] = 'show_settings';
  37. $subActions = array(
  38. 'browse' => 'BrowseMailQueue',
  39. 'clear' => 'ClearMailQueue',
  40. 'settings' => 'ModifyMailSettings',
  41. );
  42. // By default we want to browse
  43. $_REQUEST['sa'] = isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]) ? $_REQUEST['sa'] : 'browse';
  44. $context['sub_action'] = $_REQUEST['sa'];
  45. // Load up all the tabs...
  46. $context[$context['admin_menu_name']]['tab_data'] = array(
  47. 'title' => $txt['mailqueue_title'],
  48. 'help' => '',
  49. 'description' => $txt['mailqueue_desc'],
  50. );
  51. // Call the right function for this sub-acton.
  52. $subActions[$_REQUEST['sa']]();
  53. }
  54. // Display the mail queue...
  55. function BrowseMailQueue()
  56. {
  57. global $scripturl, $context, $modSettings, $txt, $smcFunc;
  58. global $sourcedir;
  59. // First, are we deleting something from the queue?
  60. if (isset($_REQUEST['delete']))
  61. {
  62. checkSession('post');
  63. $smcFunc['db_query']('', '
  64. DELETE FROM {db_prefix}mail_queue
  65. WHERE id_mail IN ({array_int:mail_ids})',
  66. array(
  67. 'mail_ids' => $_REQUEST['delete'],
  68. )
  69. );
  70. }
  71. // How many items do we have?
  72. $request = $smcFunc['db_query']('', '
  73. SELECT COUNT(*) AS queue_size, MIN(time_sent) AS oldest
  74. FROM {db_prefix}mail_queue',
  75. array(
  76. )
  77. );
  78. list ($mailQueueSize, $mailOldest) = $smcFunc['db_fetch_row']($request);
  79. $smcFunc['db_free_result']($request);
  80. $context['oldest_mail'] = empty($mailOldest) ? $txt['mailqueue_oldest_not_available'] : time_since(time() - $mailOldest);
  81. $context['mail_queue_size'] = comma_format($mailQueueSize);
  82. $listOptions = array(
  83. 'id' => 'mail_queue',
  84. 'title' => $txt['mailqueue_browse'],
  85. 'items_per_page' => 20,
  86. 'base_href' => $scripturl . '?action=admin;area=mailqueue',
  87. 'default_sort_col' => 'age',
  88. 'no_items_label' => $txt['mailqueue_no_items'],
  89. 'get_items' => array(
  90. 'function' => 'list_getMailQueue',
  91. ),
  92. 'get_count' => array(
  93. 'function' => 'list_getMailQueueSize',
  94. ),
  95. 'columns' => array(
  96. 'subject' => array(
  97. 'header' => array(
  98. 'value' => $txt['mailqueue_subject'],
  99. ),
  100. 'data' => array(
  101. 'function' => create_function('$rowData', '
  102. global $smcFunc;
  103. return $smcFunc[\'strlen\']($rowData[\'subject\']) > 50 ? sprintf(\'%1$s...\', htmlspecialchars($smcFunc[\'substr\']($rowData[\'subject\'], 0, 47))) : htmlspecialchars($rowData[\'subject\']);
  104. '),
  105. 'class' => 'smalltext',
  106. ),
  107. 'sort' => array(
  108. 'default' => 'subject',
  109. 'reverse' => 'subject DESC',
  110. ),
  111. ),
  112. 'recipient' => array(
  113. 'header' => array(
  114. 'value' => $txt['mailqueue_recipient'],
  115. ),
  116. 'data' => array(
  117. 'sprintf' => array(
  118. 'format' => '<a href="mailto:%1$s">%1$s</a>',
  119. 'params' => array(
  120. 'recipient' => true,
  121. ),
  122. ),
  123. 'class' => 'smalltext',
  124. ),
  125. 'sort' => array(
  126. 'default' => 'recipient',
  127. 'reverse' => 'recipient DESC',
  128. ),
  129. ),
  130. 'priority' => array(
  131. 'header' => array(
  132. 'value' => $txt['mailqueue_priority'],
  133. ),
  134. 'data' => array(
  135. 'function' => create_function('$rowData', '
  136. global $txt;
  137. // We probably have a text label with your priority.
  138. $txtKey = sprintf(\'mq_mpriority_%1$s\', $rowData[\'priority\']);
  139. // But if not, revert to priority 0.
  140. return isset($txt[$txtKey]) ? $txt[$txtKey] : $txt[\'mq_mpriority_1\'];
  141. '),
  142. 'class' => 'smalltext',
  143. ),
  144. 'sort' => array(
  145. 'default' => 'priority',
  146. 'reverse' => 'priority DESC',
  147. ),
  148. ),
  149. 'age' => array(
  150. 'header' => array(
  151. 'value' => $txt['mailqueue_age'],
  152. ),
  153. 'data' => array(
  154. 'function' => create_function('$rowData', '
  155. return time_since(time() - $rowData[\'time_sent\']);
  156. '),
  157. 'class' => 'smalltext',
  158. ),
  159. 'sort' => array(
  160. 'default' => 'time_sent',
  161. 'reverse' => 'time_sent DESC',
  162. ),
  163. ),
  164. 'check' => array(
  165. 'header' => array(
  166. 'value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check" />',
  167. ),
  168. 'data' => array(
  169. 'function' => create_function('$rowData', '
  170. return \'<input type="checkbox" name="delete[]" value="\' . $rowData[\'id_mail\'] . \'" class="input_check" />\';
  171. '),
  172. 'class' => 'smalltext',
  173. ),
  174. ),
  175. ),
  176. 'form' => array(
  177. 'href' => $scripturl . '?action=admin;area=mailqueue',
  178. 'include_start' => true,
  179. 'include_sort' => true,
  180. ),
  181. 'additional_rows' => array(
  182. array(
  183. 'position' => 'below_table_data',
  184. 'value' => '[<a href="' . $scripturl . '?action=admin;area=mailqueue;sa=clear;' . $context['session_var'] . '=' . $context['session_id'] . '" onclick="return confirm(\'' . $txt['mailqueue_clear_list_warning'] . '\');">' . $txt['mailqueue_clear_list'] . '</a>] <input type="submit" name="delete_redirects" value="' . $txt['delete'] . '" onclick="return confirm(\'' . $txt['quickmod_confirm'] . '\');" class="button_submit" />',
  185. ),
  186. ),
  187. );
  188. require_once($sourcedir . '/Subs-List.php');
  189. createList($listOptions);
  190. loadTemplate('ManageMail');
  191. $context['sub_template'] = 'browse';
  192. }
  193. function list_getMailQueue($start, $items_per_page, $sort)
  194. {
  195. global $smcFunc, $txt;
  196. $request = $smcFunc['db_query']('', '
  197. SELECT
  198. id_mail, time_sent, recipient, priority, private, subject
  199. FROM {db_prefix}mail_queue
  200. ORDER BY {raw:sort}
  201. LIMIT {int:start}, {int:items_per_page}',
  202. array(
  203. 'start' => $start,
  204. 'sort' => $sort,
  205. 'items_per_page' => $items_per_page,
  206. )
  207. );
  208. $mails = array();
  209. while ($row = $smcFunc['db_fetch_assoc']($request))
  210. {
  211. // Private PM/email subjects and similar shouldn't be shown in the mailbox area.
  212. if (!empty($row['private']))
  213. $row['subject'] = $txt['personal_message'];
  214. $mails[] = $row;
  215. }
  216. $smcFunc['db_free_result']($request);
  217. return $mails;
  218. }
  219. function list_getMailQueueSize()
  220. {
  221. global $smcFunc;
  222. // How many items do we have?
  223. $request = $smcFunc['db_query']('', '
  224. SELECT COUNT(*) AS queue_size
  225. FROM {db_prefix}mail_queue',
  226. array(
  227. )
  228. );
  229. list ($mailQueueSize) = $smcFunc['db_fetch_row']($request);
  230. $smcFunc['db_free_result']($request);
  231. return $mailQueueSize;
  232. }
  233. function ModifyMailSettings($return_config = false)
  234. {
  235. global $txt, $scripturl, $context, $settings, $birthdayEmails, $modSettings;
  236. loadLanguage('EmailTemplates');
  237. $body = $birthdayEmails[empty($modSettings['birthday_email']) ? 'happy_birthday' : $modSettings['birthday_email']]['body'];
  238. $subject = $birthdayEmails[empty($modSettings['birthday_email']) ? 'happy_birthday' : $modSettings['birthday_email']]['subject'];
  239. $emails = array();
  240. foreach ($birthdayEmails as $index => $dummy)
  241. $emails[$index] = $index;
  242. $config_vars = array(
  243. // Mail queue stuff, this rocks ;)
  244. array('check', 'mail_queue'),
  245. array('int', 'mail_limit'),
  246. array('int', 'mail_quantity'),
  247. '',
  248. // SMTP stuff.
  249. array('select', 'mail_type', array($txt['mail_type_default'], 'SMTP')),
  250. array('text', 'smtp_host'),
  251. array('text', 'smtp_port'),
  252. array('text', 'smtp_username'),
  253. array('password', 'smtp_password'),
  254. '',
  255. array('select', 'birthday_email', $emails, 'value' => empty($modSettings['birthday_email']) ? 'happy_birthday' : $modSettings['birthday_email'], 'javascript' => 'onchange="fetch_birthday_preview()"'),
  256. 'birthday_subject' => array('var_message', 'birthday_subject', 'var_message' => $birthdayEmails[empty($modSettings['birthday_email']) ? 'happy_birthday' : $modSettings['birthday_email']]['subject'], 'disabled' => true, 'size' => strlen($subject) + 3),
  257. 'birthday_body' => array('var_message', 'birthday_body', 'var_message' => nl2br($body), 'disabled' => true, 'size' => ceil(strlen($body) / 25)),
  258. );
  259. if ($return_config)
  260. return $config_vars;
  261. // Saving?
  262. if (isset($_GET['save']))
  263. {
  264. // Make the SMTP password a little harder to see in a backup etc.
  265. if (!empty($_POST['smtp_password'][1]))
  266. {
  267. $_POST['smtp_password'][0] = base64_encode($_POST['smtp_password'][0]);
  268. $_POST['smtp_password'][1] = base64_encode($_POST['smtp_password'][1]);
  269. }
  270. checkSession();
  271. // We don't want to save the subject and body previews.
  272. unset($config_vars['birthday_subject'], $config_vars['birthday_body']);
  273. saveDBSettings($config_vars);
  274. redirectexit('action=admin;area=mailqueue;sa=settings');
  275. }
  276. $context['post_url'] = $scripturl . '?action=admin;area=mailqueue;save;sa=settings';
  277. $context['settings_title'] = $txt['mailqueue_settings'];
  278. prepareDBSettingContext($config_vars);
  279. $context['settings_insert_above'] = '
  280. <script type="text/javascript"><!-- // --><![CDATA[
  281. var bDay = {';
  282. $i = 0;
  283. foreach ($birthdayEmails as $index => $email)
  284. {
  285. $is_last = ++$i == count($birthdayEmails);
  286. $context['settings_insert_above'] .= '
  287. ' . $index . ': {
  288. subject: ' . JavaScriptEscape($email['subject']) . ',
  289. body: ' . JavaScriptEscape(nl2br($email['body'])) . '
  290. }' . (!$is_last ? ',' : '');
  291. }
  292. $context['settings_insert_above'] .= '
  293. };
  294. function fetch_birthday_preview()
  295. {
  296. var index = document.getElementById(\'birthday_email\').value;
  297. document.getElementById(\'birthday_subject\').innerHTML = bDay[index].subject;
  298. document.getElementById(\'birthday_body\').innerHTML = bDay[index].body;
  299. }
  300. // ]]></script>';
  301. }
  302. // This function clears the mail queue of all emails, and at the end redirects to browse.
  303. function ClearMailQueue()
  304. {
  305. global $sourcedir, $smcFunc;
  306. checkSession('get');
  307. // This is certainly needed!
  308. require_once($sourcedir . '/ScheduledTasks.php');
  309. // If we don't yet have the total to clear, find it.
  310. if (!isset($_GET['te']))
  311. {
  312. // How many items do we have?
  313. $request = $smcFunc['db_query']('', '
  314. SELECT COUNT(*) AS queue_size
  315. FROM {db_prefix}mail_queue',
  316. array(
  317. )
  318. );
  319. list ($_GET['te']) = $smcFunc['db_fetch_row']($request);
  320. $smcFunc['db_free_result']($request);
  321. }
  322. else
  323. $_GET['te'] = (int) $_GET['te'];
  324. $_GET['sent'] = isset($_GET['sent']) ? (int) $_GET['sent'] : 0;
  325. // Send 50 at a time, then go for a break...
  326. while (ReduceMailQueue(50, true, true) === true)
  327. {
  328. // Sent another 50.
  329. $_GET['sent'] += 50;
  330. pauseMailQueueClear();
  331. }
  332. return BrowseMailQueue();
  333. }
  334. // Used for pausing the mail queue.
  335. function pauseMailQueueClear()
  336. {
  337. global $context, $txt, $time_start;
  338. // Try get more time...
  339. @set_time_limit(600);
  340. if (function_exists('apache_reset_timeout'))
  341. @apache_reset_timeout();
  342. // Have we already used our maximum time?
  343. if (time() - array_sum(explode(' ', $time_start)) < 5)
  344. return;
  345. $context['continue_get_data'] = '?action=admin;area=mailqueue;sa=clear;te=' . $_GET['te'] . ';sent=' . $_GET['sent'] . ';' . $context['session_var'] . '=' . $context['session_id'];
  346. $context['page_title'] = $txt['not_done_title'];
  347. $context['continue_post_data'] = '';
  348. $context['continue_countdown'] = '2';
  349. $context['sub_template'] = 'not_done';
  350. // Keep browse selected.
  351. $context['selected'] = 'browse';
  352. // What percent through are we?
  353. $context['continue_percent'] = round(($_GET['sent'] / $_GET['te']) * 100, 1);
  354. // Never more than 100%!
  355. $context['continue_percent'] = min($context['continue_percent'], 100);
  356. obExit();
  357. }
  358. // Little function to calculate how long ago a time was.
  359. function time_since($time_diff)
  360. {
  361. global $txt;
  362. if ($time_diff < 0)
  363. $time_diff = 0;
  364. // Just do a bit of an if fest...
  365. if ($time_diff > 86400)
  366. {
  367. $days = round($time_diff / 86400, 1);
  368. return sprintf($days == 1 ? $txt['mq_day'] : $txt['mq_days'], $time_diff / 86400);
  369. }
  370. // Hours?
  371. elseif ($time_diff > 3600)
  372. {
  373. $hours = round($time_diff / 3600, 1);
  374. return sprintf($hours == 1 ? $txt['mq_hour'] : $txt['mq_hours'], $hours);
  375. }
  376. // Minutes?
  377. elseif ($time_diff > 60)
  378. {
  379. $minutes = (int) ($time_diff / 60);
  380. return sprintf($minutes == 1 ? $txt['mq_minute'] : $txt['mq_minutes'], $minutes);
  381. }
  382. // Otherwise must be second
  383. else
  384. return sprintf($time_diff == 1 ? $txt['mq_second'] : $txt['mq_seconds'], $time_diff);
  385. }
  386. ?>