Example #1
0
/**
 * Sends an email, wrapping PHP's mail() function.
 * ALL emails sent by b2evolution must be sent through this function (for consistency and for logging)
 *
 * {@link $current_locale} will be used to set the charset.
 *
 * Note: we use a single \n as line ending, though it does not comply to {@link http://www.faqs.org/rfcs/rfc2822 RFC2822}, but seems to be safer,
 * because some mail transfer agents replace \n by \r\n automatically.
 *
 * @todo Unit testing with "nice addresses" This gets broken over and over again.
 *
 * @param string Recipient email address.
 * @param string Recipient name.
 * @param string Subject of the mail
 * @param string|array The message text OR Array: 'charset', 'full', 'html', 'text'
 * @param string From address, being added to headers (we'll prevent injections); see {@link http://securephp.damonkohler.com/index.php/Email_Injection}.
 *               Defaults to {@link GeneralSettings::get('notification_sender_email') } if NULL.
 * @param string From name.
 * @param array Additional headers ( headername => value ). Take care of injection!
 * @param integer User ID
 * @return boolean True if mail could be sent (not necessarily delivered!), false if not - (return value of {@link mail()})
 */
function send_mail($to, $to_name, $subject, $message, $from = NULL, $from_name = NULL, $headers = array(), $user_ID = NULL)
{
    global $servertimenow;
    // Stop a request from the blocked IP addresses or Domains
    antispam_block_request();
    global $debug, $app_name, $app_version, $current_locale, $current_charset, $evo_charset, $locales, $Debuglog, $Settings, $demo_mode, $sendmail_additional_params;
    $message_data = $message;
    if (is_array($message_data) && isset($message_data['full'])) {
        // If content is multipart
        $message = $message_data['full'];
    } elseif (is_string($message_data)) {
        // Convert $message_data to array
        $message_data = array('full' => $message);
    }
    // Replace secret content in the mail logs message body
    $message = preg_replace('~\\$secret_content_start\\$.*\\$secret_content_end\\$~', '***secret-content-removed***', $message);
    // Remove secret content marks from the message
    $message_data = str_replace(array('$secret_content_start$', '$secret_content_end$'), '', $message_data);
    // Memorize email address
    $to_email_address = $to;
    $NL = "\r\n";
    if ($demo_mode) {
        // Debug mode restriction: Sending email in debug mode is not allowed
        return false;
    }
    if (!is_array($headers)) {
        // Make sure $headers is an array
        $headers = array($headers);
    }
    if (empty($from)) {
        $from = user_get_notification_sender($user_ID, 'email');
    }
    if (empty($from_name)) {
        $from_name = user_get_notification_sender($user_ID, 'name');
    }
    // Pass these data for SMTP mailer
    $message_data['to_email'] = $to;
    $message_data['to_name'] = empty($to_name) ? NULL : $to_name;
    $message_data['from_email'] = $from;
    $message_data['from_name'] = empty($from_name) ? NULL : $from_name;
    $return_path = $Settings->get('notification_return_path');
    // Add real name into $from...
    if (!is_windows()) {
        // fplanque: Windows XP, Apache 1.3, PHP 4.4, MS SMTP : will not accept "nice" addresses.
        if (!empty($to_name)) {
            $to = '"' . mail_encode_header_string($to_name) . '" <' . $to . '>';
        }
        if (!empty($from_name)) {
            $from = '"' . mail_encode_header_string($from_name) . '" <' . $from . '>';
        }
    }
    $from = mail_sanitize_header_string($from, true);
    // From has to go into headers
    $headers['From'] = $from;
    if (!empty($return_path)) {
        // Set a return path
        $headers['Return-Path'] = $return_path;
    }
    // echo 'sending email to: ['.htmlspecialchars($to).'] from ['.htmlspecialchars($from).']';
    $clear_subject = $subject;
    $subject = mail_encode_header_string($subject);
    $message = str_replace(array("\r\n", "\r"), $NL, $message);
    // Convert encoding of message (from internal encoding to the one of the message):
    // fp> why do we actually convert to $current_charset?
    // dh> I do not remember. Appears to make sense sending it unconverted in $evo_charset.
    // asimo> converting the message creates wrong output, no need for conversion, however this needs further investigation
    // $message = convert_charset( $message, $current_charset, $evo_charset );
    if (!isset($headers['Content-Type'])) {
        // Specify charset and content-type of email
        $headers['Content-Type'] = 'text/plain; charset=' . $current_charset;
    }
    $headers['MIME-Version'] = '1.0';
    $headers['Date'] = gmdate('r', $servertimenow);
    // ADDITIONAL HEADERS:
    $headers['X-Mailer'] = $app_name . ' ' . $app_version . ' - PHP/' . phpversion();
    $ip_list = implode(',', get_ip_list());
    if (!empty($ip_list)) {
        // Add X-Remote_Addr param only if its value is not empty
        $headers['X-Remote-Addr'] = $ip_list;
    }
    // COMPACT HEADERS:
    $headerstring = get_mail_headers($headers, $NL);
    // Set an additional parameter for the return path:
    if (!empty($sendmail_additional_params)) {
        $additional_parameters = str_replace(array('$from-address$', '$return-address$'), array($from, empty($return_path) ? $from : $return_path), $sendmail_additional_params);
    } else {
        $additional_parameters = '';
    }
    if (mail_is_blocked($to_email_address)) {
        // Check if the email address is blocked
        $Debuglog->add('Sending mail to &laquo;' . htmlspecialchars($to_email_address) . '&raquo; FAILED, because this email marked with spam or permanent errors.', 'error');
        mail_log($user_ID, $to_email_address, $clear_subject, $message, $headerstring, 'blocked');
        return false;
    }
    // SEND MESSAGE:
    if ($debug > 1) {
        // We agree to die for debugging...
        if (!evo_mail($to, $subject, $message_data, $headers, $additional_parameters)) {
            mail_log($user_ID, $to_email_address, $clear_subject, $message, $headerstring, 'error');
            debug_die('Sending mail from &laquo;' . htmlspecialchars($from) . '&raquo; to &laquo;' . htmlspecialchars($to) . '&raquo;, Subject &laquo;' . htmlspecialchars($subject) . '&raquo; FAILED.');
        }
    } else {
        // Soft debugging only....
        if (!evo_mail($to, $subject, $message_data, $headers, $additional_parameters)) {
            $Debuglog->add('Sending mail from &laquo;' . htmlspecialchars($from) . '&raquo; to &laquo;' . htmlspecialchars($to) . '&raquo;, Subject &laquo;' . htmlspecialchars($subject) . '&raquo; FAILED.', 'error');
            mail_log($user_ID, $to_email_address, $clear_subject, $message, $headerstring, 'error');
            return false;
        }
    }
    $Debuglog->add('Sent mail from &laquo;' . htmlspecialchars($from) . '&raquo; to &laquo;' . htmlspecialchars($to) . '&raquo;, Subject &laquo;' . htmlspecialchars($subject) . '&raquo;.');
    mail_log($user_ID, $to_email_address, $clear_subject, $message, $headerstring, 'ok');
    return true;
}
Example #2
0
         $Messages->add(T_('Invalid account activation request!'), 'error');
         $action = 'req_validatemail';
         break;
     }
     // log in with user
     $Session->set_user_ID($userID);
     // activate user account
     $User->activate_from_Request();
     $Messages->add(T_('Your account is now activated.'), 'success');
     header_redirect(redirect_after_account_activation());
     /* exited */
     break;
 case 'validatemail':
     // Clicked "Validate email" link from a mail
     // Stop a request from the blocked IP addresses or Domains
     antispam_block_request();
     param('reqID', 'string', '');
     param('sessID', 'integer', '');
     if (check_user_status('is_validated')) {
         // Already validated, e.g. clicked on an obsolete email link:
         $Messages->add(T_('Your email address has already been validated.'), 'note');
         // no break: cleanup & redirect below
     } else {
         // Check valid format:
         if (empty($reqID)) {
             // This was not requested
             $Messages->add(T_('Invalid email address validation request!'), 'error');
             $action = 'req_validatemail';
             break;
         }
         // Check valid session (format only, meant as help for the user):
Example #3
0
 /**
  * Handle messaging module htsrv actions
  */
 function handle_htsrv_action()
 {
     global $current_User, $Blog, $Session, $Messages, $samedomain_htsrv_url;
     // Init objects we want to work on.
     $action = param_action(true, true);
     $disp = param('disp', '/^[a-z0-9\\-_]+$/', 'threads');
     // Check that this action request is not a CSRF hacked request:
     $Session->assert_received_crumb('messaging_' . $disp);
     // Load classes
     load_class('messaging/model/_thread.class.php', 'Thread');
     load_class('messaging/model/_message.class.php', 'Message');
     if (!is_logged_in()) {
         // user must be logged in
         debug_die('User must be logged in to proceed with messaging updates!');
     }
     // Check permission:
     $current_User->check_perm('perm_messaging', 'reply', true);
     // set where to redirect
     $redirect_to = param('redirect_to', 'url', NULL);
     if (empty($redirect_to)) {
         if (isset($Blog)) {
             $redirect_to = url_add_param($Blog->gen_baseurl(), 'disp=' . $disp);
         } else {
             $redirect_to = url_add_param($baseurl, 'disp=' . $disp);
         }
     }
     if ($disp != 'contacts' && ($thrd_ID = param('thrd_ID', 'integer', '', true))) {
         // Load thread from cache:
         $ThreadCache =& get_ThreadCache();
         if (($edited_Thread =& $ThreadCache->get_by_ID($thrd_ID, false)) === false) {
             // Thread doesn't exists with this ID
             unset($edited_Thread);
             forget_param('thrd_ID');
             $Messages->add(T_('The requested thread does not exist any longer.'), 'error');
             $action = 'nil';
         }
     }
     switch ($disp) {
         // threads action
         case 'threads':
             if ($action != 'create' && $action != 'preview') {
                 // Make sure we got a thrd_ID:
                 param('thrd_ID', 'integer', true);
             }
             switch ($action) {
                 case 'create':
                     // create thread
                 // create thread
                 case 'preview':
                     // preview message
                     // Stop a request from the blocked IP addresses or Domains
                     antispam_block_request();
                     // check if create new thread is allowed
                     if (check_create_thread_limit()) {
                         // max new threads limit reached, don't allow to create new thread
                         debug_die('Invalid request, new conversation limit already reached!');
                     }
                     $creating_success = create_new_thread();
                     if (!$creating_success || $action == 'preview') {
                         // unsuccessful new thread creation OR preview mode
                         global $edited_Thread, $edited_Message, $thrd_recipients, $thrd_recipients_array;
                         $redirect_to .= '&action=new';
                         // save new message and thread params into the Session to not lose the content
                         $unsaved_message_params = array();
                         $unsaved_message_params['action'] = $action;
                         $unsaved_message_params['subject'] = $edited_Thread->title;
                         $unsaved_message_params['message'] = $edited_Message->text;
                         $unsaved_message_params['message_original'] = $edited_Message->original_text;
                         $unsaved_message_params['renderers'] = $edited_Message->get_renderers_validated();
                         $unsaved_message_params['thrdtype'] = param('thrdtype', 'string', 'individual');
                         // alternative: discussion
                         $unsaved_message_params['thrd_recipients'] = $thrd_recipients;
                         $unsaved_message_params['thrd_recipients_array'] = $thrd_recipients_array;
                         $unsaved_message_params['creating_success'] = $creating_success;
                         save_message_params_to_session($unsaved_message_params);
                     }
                     break;
                 case 'delete':
                     // delete thread
                     // Check permission:
                     $current_User->check_perm('perm_messaging', 'delete', true);
                     $confirmed = param('confirmed', 'integer', 0);
                     if ($confirmed) {
                         $msg = sprintf(T_('Thread &laquo;%s&raquo; deleted.'), $edited_Thread->dget('title'));
                         $edited_Thread->dbdelete();
                         unset($edited_Thread);
                         forget_param('thrd_ID');
                         $Messages->add($msg, 'success');
                     } else {
                         $delete_url = $samedomain_htsrv_url . 'action.php?mname=messaging&thrd_ID=' . $edited_Thread->ID . '&action=delete&confirmed=1&redirect_to=' . $redirect_to . '&' . url_crumb('messaging_threads');
                         $ok_button = '<a href="' . $delete_url . '" class="btn btn-danger">' . T_('I am sure!') . '</a>';
                         $cancel_button = '<a href="' . $redirect_to . '" class="btn btn-default">CANCEL</a>';
                         $msg = sprintf(T_('You are about to delete all messages in the conversation &laquo;%s&raquo;.'), $edited_Thread->dget('title'));
                         $msg .= '<br />' . T_('This CANNOT be undone!') . '<br />' . T_('Are you sure?') . '<br /><br />' . $ok_button . "\t" . $cancel_button;
                         $Messages->add($msg, 'error');
                     }
                     break;
                 case 'leave':
                     // user wants to leave the thread
                     leave_thread($edited_Thread->ID, $current_User->ID, false);
                     $Messages->add(sprintf(T_('You have successfuly left the &laquo;%s&raquo; conversation!'), $edited_Thread->get('title')), 'success');
                     break;
                 case 'close':
                     // close the thread
                 // close the thread
                 case 'close_and_block':
                     // close the thread and block contact
                     leave_thread($edited_Thread->ID, $current_User->ID, true);
                     // user has closed this conversation because there was only one other user involved
                     $Messages->add(sprintf(T_('You have successfuly closed the &laquo;%s&raquo; conversation!'), $edited_Thread->get('title')), 'success');
                     if ($action == 'close_and_block') {
                         // user also wants to block contact with the other user involved in this thread
                         $block_user_ID = param('block_ID', 'integer', true);
                         $UserCache =& get_UserCache();
                         $blocked_User = $UserCache->get_by_ID($block_user_ID);
                         set_contact_blocked($block_user_ID, true);
                         $Messages->add(sprintf(T_('&laquo;%s&raquo; was blocked.'), $blocked_User->get('login')), 'success');
                     }
                     break;
             }
             break;
             // break from threads action switch
             // contacts action
         // break from threads action switch
         // contacts action
         case 'contacts':
             $user_ID = param('user_ID', 'string', true);
             if ($action != 'block' && $action != 'unblock') {
                 // only block or unblock is valid
                 debug_die("Invalid action param");
             }
             if (set_contact_blocked($user_ID, $action == 'block' ? 1 : 0)) {
                 if ($action == 'block') {
                     $Messages->add(T_('You have blocked this user from contacting you.'), 'success');
                 } else {
                     $Messages->add(T_('You have unblocked this user so he can contact you again.'), 'success');
                 }
             }
             $redirect_to = str_replace('&amp;', '&', $redirect_to);
             break;
             // messages action
         // messages action
         case 'messages':
             switch ($action) {
                 case 'create':
                     // create new message
                     // Stop a request from the blocked IP addresses or Domains
                     antispam_block_request();
                     create_new_message($thrd_ID);
                     break;
                 case 'preview':
                     // create new message
                     // Stop a request from the blocked IP addresses or Domains
                     antispam_block_request();
                     global $edited_Message;
                     $creating_success = create_new_message($thrd_ID, 'preview');
                     // save new message and thread params into the Session to not lose the content
                     $unsaved_message_params = array();
                     $unsaved_message_params['action'] = $action;
                     $unsaved_message_params['message'] = $edited_Message->text;
                     $unsaved_message_params['message_original'] = $edited_Message->original_text;
                     $unsaved_message_params['renderers'] = $edited_Message->get_renderers_validated();
                     $unsaved_message_params['creating_success'] = $creating_success;
                     save_message_params_to_session($unsaved_message_params);
                     break;
                 case 'delete':
                     // delete message
                     // Check permission:
                     $current_User->check_perm('perm_messaging', 'delete', true);
                     $msg_ID = param('msg_ID', 'integer', true);
                     $MessageCache =& get_MessageCache();
                     if (($edited_Message =& $MessageCache->get_by_ID($msg_ID, false)) === false) {
                         $Messages->add(sprintf(T_('Requested &laquo;%s&raquo; object does not exist any longer.'), T_('Message')), 'error');
                         break;
                     }
                     $confirmed = param('confirmed', 'integer', 0);
                     if ($confirmed) {
                         // delete message
                         $edited_Message->dbdelete();
                         unset($edited_Message);
                         $Messages->add(T_('Message deleted.'), 'success');
                     } else {
                         $delete_url = $samedomain_htsrv_url . 'action.php?mname=messaging&disp=messages&thrd_ID=' . $thrd_ID . '&msg_ID=' . $msg_ID . '&action=delete&confirmed=1';
                         if (!empty($Blog)) {
                             // Add blog ID to correctly redirect after deleting:
                             $delete_url .= '&blog=' . $Blog->ID;
                         }
                         $delete_url = url_add_param($delete_url, 'redirect_to=' . rawurlencode($redirect_to), '&') . '&' . url_crumb('messaging_messages');
                         $ok_button = '<a href="' . $delete_url . '" class="btn btn-danger">' . T_('I am sure!') . '</a>';
                         $cancel_button = '<a href="' . $redirect_to . '" class="btn btn-default">' . T_('CANCEL') . '</a>';
                         $msg = T_('You are about to delete this message. ') . '<br /> ' . T_('This CANNOT be undone!') . '<br />' . T_('Are you sure?') . '<br /><br />' . $ok_button . "\t" . $cancel_button;
                         $Messages->add($msg, 'error');
                     }
                     break;
             }
             break;
     }
     header_redirect($redirect_to);
     // Will save $Messages into Session
 }