/** * Main email posting controller, reads, parses, checks and posts an email message or PM * * What it does: * - Allows a user to reply to a topic on the board by emailing a reply to a * notification message. * - It must have the security key in the email or it will be rejected * - It must be from the email of a registered user * - The key must have been sent to that user * - Keys are used once and then discarded * - Accessed by email imap cron script, and ManageMaillist.controller.php. * * @param string|null $data used to supply a full headers+body email * @param boolean $force used to override common failure errors * @param string|null $key used to supply a lost key */ public function action_pbe_post($data = null, $force = false, $key = null) { global $txt, $modSettings, $language, $user_info, $maintenance; // The function is not even on ... if (empty($modSettings['maillist_enabled'])) { return; } // Our mail parser and our main subs require_once SUBSDIR . '/EmailParse.class.php'; require_once SUBSDIR . '/Emailpost.subs.php'; // Init loadLanguage('Maillist'); setMemoryLimit('128M'); // Load the email parser and get some data to work with $email_message = new Email_Parse(); $email_message->read_data($data, BOARDDIR); if (!$email_message->raw_message) { return false; } // Ask for an html version (if available) and some needed details $email_message->read_email(true, $email_message->raw_message); $email_message->load_address(); $email_message->load_key($key); // If the feature is on but the post/pm function is not enabled, just log the message. if (empty($modSettings['pbe_post_enabled']) && empty($modSettings['pbe_pm_enabled'])) { return pbe_emailError('error_email_notenabled', $email_message); } // Spam I am? if ($email_message->load_spam() && !$force) { return pbe_emailError('error_found_spam', $email_message); } // Load the user from the database based on the sending email address $email_message->email['from'] = !empty($email_message->email['from']) ? strtolower($email_message->email['from']) : ''; $pbe = query_load_user_info($email_message->email['from']); // Can't find this email in our database, a non-user, a spammer, a looser, a poser or even worse? if (empty($pbe)) { return pbe_emailError('error_not_find_member', $email_message); } // Find the message security key, without it we are not going anywhere ever if (empty($email_message->message_key_id)) { return pbe_emailError('error_missing_key', $email_message); } // Good we have a key, who was it sent to? $key_owner = query_key_owner($email_message->message_key_id); // Can't find this key in the database, either // a) spam attempt or b) replying with an expired/consumed key if (empty($key_owner) && !$force) { return pbe_emailError('error_' . ($email_message->message_type === 'p' ? 'pm_' : '') . 'not_find_entry', $email_message); } // The key received was not sent to this member ... how we love those email aggregators if (strtolower($key_owner) !== $email_message->email['from'] && !$force) { return pbe_emailError('error_key_sender_match', $email_message); } // In maintenance mode, just log it for now if (!empty($maintenance) && $maintenance !== 2 && !$pbe['user_info']['is_admin'] && !$user_info['is_admin']) { return pbe_emailError('error_in_maintenance_mode', $email_message); } // The email looks valid, now on to check the actual user trying to make the post/pm // lets load the topic/message info and any additional permissions we need if ($email_message->message_type === 't' || $email_message->message_type === 'm') { // Load the message/topic details $topic_info = query_load_message($email_message->message_type, $email_message->message_id, $pbe); if (empty($topic_info)) { return pbe_emailError('error_topic_gone', $email_message); } // Load board permissions query_load_permissions('board', $pbe, $topic_info); } else { // Load the PM details $pm_info = query_load_message($email_message->message_type, $email_message->message_id, $pbe); if (empty($pm_info)) { // Duh oh ... likely they deleted the PM on the site and are now // replying to the PM by email, the agony! return pbe_emailError('error_pm_not_found', $email_message); } } // Account for moderation actions pbe_check_moderation($pbe); // Maybe they want to do additional spam / security checking call_integration_hook('integrate_mailist_checks_before', array($email_message, $pbe)); // Load in the correct Re: for the language if ($language === $pbe['user_info']['language']) { $pbe['response_prefix'] = $txt['response_prefix']; } else { loadLanguage('index', $language, false); $pbe['response_prefix'] = $txt['response_prefix']; loadLanguage('index'); } // Allow for new topics to be started via a email subject change if (!empty($modSettings['maillist_newtopic_change']) && $email_message->message_type === 'm') { $subject = str_replace($pbe['response_prefix'], '', pbe_clean_email_subject($email_message->subject)); $current_subject = str_replace($pbe['response_prefix'], '', $topic_info['subject']); // If it does not match, then we go to make a new topic instead if (trim($subject) != trim($current_subject)) { $board_info = query_load_board_details($topic_info['id_board'], $pbe); return pbe_create_topic($pbe, $email_message, $board_info); } } // Time to make a Post or a PM, first up topic and message replies if ($email_message->message_type === 't' || $email_message->message_type === 'm') { $result = pbe_create_post($pbe, $email_message, $topic_info); } elseif ($email_message->message_type === 'p') { $result = pbe_create_pm($pbe, $email_message, $pm_info); } if (!empty($result)) { // We have now posted or PM'ed .. lets do some database maintenance cause maintenance is fun :'( query_key_maintenance($email_message); // Update this user so the log shows they were/are active, no luking in the email ether query_update_member_stats($pbe, $email_message, $email_message->message_type === 'p' ? $pm_info : $topic_info); } return !empty($result); }
/** * For a given type, t m or p, query the appropriate table for a given message id * * - If found returns the message subject * * @package Maillist * @param int $message_id * @param string $message_type * @param string $email */ function query_load_subject($message_id, $message_type, $email) { $db = database(); $subject = ''; // Load up the core topic details, if ($message_type === 't') { $request = $db->query('', ' SELECT t.id_topic, m.subject FROM {db_prefix}topics AS t INNER JOIN {db_prefix}messages AS m ON (m.id_msg = t.id_first_msg) WHERE t.id_topic = {int:id_topic}', array('id_topic' => $message_id)); } elseif ($message_type === 'm') { $request = $db->query('', ' SELECT m.id_topic, m.subject FROM {db_prefix}messages AS m INNER JOIN {db_prefix}topics AS t ON (t.id_topic = m.id_topic) WHERE m.id_msg = {int:message_id}', array('message_id' => $message_id)); } elseif ($message_type === 'p') { // With PM's ... first get the member id based on the email $request = $db->query('', ' SELECT id_member FROM {db_prefix}members WHERE email_address = {string:email} AND is_activated = {int:act} LIMIT 1', array('email' => $email, 'act' => 1)); // Found them, now we find the PM to them with this ID if ($db->num_rows($request) !== 0) { list($id_member) = $db->fetch_row($request); $db->free_result($request); // Now find this PM ID and make sure it was sent to this member $request = $db->query('', ' SELECT p.subject FROM {db_prefix}pm_recipients AS pmr, {db_prefix}personal_messages AS p WHERE pmr.id_pm = {int:id_pm} AND pmr.id_member = {int:id_member} AND p.id_pm = pmr.id_pm', array('id_member' => $id_member, 'id_pm' => $message_id)); } } // If we found the message, topic or PM, return the subject if ($db->num_rows($request) != 0) { list($subject) = $db->fetch_row($request); $subject = pbe_clean_email_subject($subject); } $db->free_result($request); return $subject; }