Пример #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 The message 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
    antispam_block_ip();
    global $debug, $app_name, $app_version, $current_locale, $current_charset, $evo_charset, $locales, $Debuglog, $Settings, $demo_mode, $sendmail_additional_params;
    // 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');
    }
    $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 = '';
    reset($headers);
    while (list($lKey, $lValue) = each($headers)) {
        // Add additional headers
        $headerstring .= $lKey . ': ' . $lValue . $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 (!mail($to, $subject, $message, $headerstring, $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 (!@mail($to, $subject, $message, $headerstring, $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;
}
Пример #2
0
/**
 * Send account validation email with a permanent validation link
 *
 * @param array user ids to send validation email
 * @param boolean true if this email is an account activation reminder, false if the account status was changed right now
 * @return integer the number of successfully sent emails
 */
function send_easy_validate_emails($user_ids, $is_reminder = true, $email_changed = false)
{
    global $UserSettings, $servertimenow, $secure_htsrv_url;
    $UserCache =& get_UserCache();
    if (isset($GLOBALS['messaging_Module'])) {
        // Get already received messages for each recepient user
        $already_received_messages = get_users_unread_threads($user_ids);
    }
    $cache_by_locale = array();
    $email_sent = 0;
    foreach ($user_ids as $user_ID) {
        // Iterate through user ids and send account activation reminder to all user
        $User = $UserCache->get_by_ID($user_ID, false);
        if (!$User) {
            // user not exists
            continue;
        }
        if (!$User->check_status('can_be_validated')) {
            // User is validated or it is not allowed to be validated
            continue;
        }
        if ($is_reminder && !$UserSettings->get('send_activation_reminder')) {
            // This is an activation reminder, but user wouldn't like to receive this kind of emails
            continue;
        }
        if (mail_is_blocked($User->get('email'))) {
            // prevent trying to send an email to a blocked email address
            continue;
        }
        $notify_locale = $User->get('locale');
        $reminder_key = $UserSettings->get('last_activation_reminder_key', $User->ID);
        if (empty($reminder_key) || $email_changed) {
            // reminder key was not generated yet, or the user email address was changed and we need a new one, to invalidate old requests
            $reminder_key = generate_random_key(32);
            $UserSettings->set('last_activation_reminder_key', $reminder_key, $User->ID);
        }
        if (!isset($cache_by_locale[$notify_locale])) {
            // No subject for this locale generated yet:
            locale_temp_switch($notify_locale);
            $cache_by_locale[$notify_locale]['subject'] = T_('Activate your account: $login$');
            locale_restore_previous();
        }
        $email_template_params = array('locale' => $notify_locale, 'status' => $User->get('status'), 'reminder_key' => $reminder_key, 'is_reminder' => $is_reminder);
        if (!empty($already_received_messages[$User->ID])) {
            // add already received message list to email body
            $email_template_params['already_received_messages'] = $already_received_messages[$User->ID];
        }
        // Update notification sender's info from General settings
        $User->update_sender(true);
        if (send_mail_to_User($User->ID, $cache_by_locale[$notify_locale]['subject'], 'account_activate', $email_template_params, true)) {
            // save corresponding user settings right after the email was sent, to prevent not saving if an eroor occurs
            $email_sent++;
            // Set last remind activation email date and increase sent reminder emails number in UserSettings
            $UserSettings->set('last_activation_email', date2mysql($servertimenow), $User->ID);
            if ($is_reminder) {
                $reminder_sent_to_user = $UserSettings->get('activation_reminder_count', $User->ID);
                $UserSettings->set('activation_reminder_count', $reminder_sent_to_user + 1, $User->ID);
            }
            $UserSettings->dbupdate();
        }
    }
    return $email_sent;
}
Пример #3
0
 /**
  * Send an email to the user with a link to validate/confirm his email address.
  *
  * If the email could get sent, it saves the used "request_id" into the user's Session.
  *
  * @param string URL, where to redirect the user after he clicked the validation link (gets saved in Session).
  * @return boolean True, if the email could get sent; false if not
  */
 function send_validate_email($redirect_to_after, $blog = NULL, $email_changed = false)
 {
     global $app_name, $Session, $secure_htsrv_url, $baseurl, $servertimenow;
     global $Settings, $UserSettings;
     // Display messages depending on user email status
     display_user_email_status_message($this->ID);
     if ($Settings->get('validation_process') == 'easy') {
         // validation process is set to easy, send and easy activation email
         return send_easy_validate_emails(array($this->ID), false, $email_changed);
     }
     if (mail_is_blocked($this->email)) {
         // prevent trying to send an email to a blocked email address ( Note this is checked in the send_easy_validate_emails too )
         return false;
     }
     if (empty($redirect_to_after)) {
         // redirect to was not set
         $redirect_to_after = param('redirect_to', 'url', '');
         if (empty($redirect_to_after)) {
             if (is_admin_page()) {
                 $redirect_to_after = regenerate_url('action');
             } else {
                 $redirect_to_after = $this->get_userpage_url();
             }
         }
     }
     $request_id = generate_random_key(22);
     $blog_param = empty($blog) ? '' : '&inskin=1&blog=' . $blog;
     // Change locale here to localize the email subject and content
     locale_temp_switch($this->get('locale'));
     $email_template_params = array('status' => $this->status, 'blog_param' => $blog_param, 'request_id' => $request_id);
     $r = send_mail_to_User($this->ID, T_('Activate your account: $login$'), 'account_activate', $email_template_params, true);
     locale_restore_previous();
     if ($r) {
         // save request_id into Session
         $request_ids = $Session->get('core.validatemail.request_ids');
         if (!is_array($request_ids) || $email_changed) {
             // create new request ids array if it doesn't exist yet, or if user email changed ( this way the old request into the old email address won't be valid )
             $request_ids = array();
         }
         $request_ids[] = $request_id;
         $Session->set('core.validatemail.request_ids', $request_ids, 86400 * 2);
         // expires in two days (or when clicked)
         // set a redirect_to session variable because this way after the account will be activated we will know where to redirect
         $Session->set('core.validatemail.redirect_to', $redirect_to_after);
         $Session->dbsave();
         // save immediately
         // update last activation email timestamp
         $UserSettings->set('last_activation_email', date2mysql($servertimenow), $this->ID);
         $UserSettings->dbupdate();
     }
     return $r;
 }
Пример #4
0
/**
 * Memorize the blocked emails in cache array in order to display the message 
 * @see blocked_emails_display()
 *
 * @param string Email address
 */
function blocked_emails_memorize($email)
{
    global $current_User, $cache_blocked_emails;
    if (empty($email)) {
        // Empty email, Exit here
        return;
    }
    if (is_logged_in() && $current_User->check_perm('users', 'view')) {
        // User has permissions to view other users
        if (mail_is_blocked($email)) {
            // Check if the email address is blocked
            if (isset($cache_blocked_emails[$email])) {
                // Icrease a count of blocked email
                $cache_blocked_emails[$email]++;
            } else {
                $cache_blocked_emails[$email] = 1;
            }
        }
    }
}