/** * Set the mail error message in self::$mErrorString * * @param int $code Error number * @param string $string Error message */ static function errorHandler($code, $string) { self::$mErrorString = preg_replace('/^mail\\(\\)(\\s*\\[.*?\\])?: /', '', $string); }
/** * This function will perform a direct (authenticated) login to * a SMTP Server to use for mail relaying if 'wgSMTP' specifies an * array of parameters. It requires PEAR:Mail to do that. * Otherwise it just uses the standard PHP 'mail' function. * * @param MailAddress $to : recipient's email (or an array of them) * @param MailAddress $from : sender's email * @param String $subject : email's subject. * @param String $body : email's text. * $body can be array with text and html version of email message, and also can contain attachements * $body = array('text' => 'Email text', 'html' => '<b>Email text</b>') * @param MailAddress $replyTo : optional reply-to email (default: null). * @param String $contentType : optional custom Content-Type * @param String $category : optional category for statistic * @param int $priority : optional priority for email * @param Array $attachments : optional list of files to send as attachments * * @return Status object * @throws MWException */ public static function send(MailAddress $to, MailAddress $from, $subject, $body, MailAddress $replyTo = null, $contentType = null, $category = 'UserMailer', $priority = 0, $attachments = []) { if (!is_array($to)) { $to = [$to]; } # Make sure we have at least one address $has_address = false; foreach ($to as $u) { if ($u->address) { $has_address = true; break; } } if (!$has_address) { return Status::newFatal('user-mail-no-addy'); } wfRunHooks('UserMailerSend', [&$to]); # Forge email headers # ------------------- # # WARNING # # DO NOT add To: or Subject: headers at this step. They need to be # handled differently depending upon the mailer we are going to use. # # To: # PHP mail() first argument is the mail receiver. The argument is # used as a recipient destination and as a To header. # # PEAR mailer has a recipient argument which is only used to # send the mail. If no To header is given, PEAR will set it to # to 'undisclosed-recipients:'. # # NOTE: To: is for presentation, the actual recipient is specified # by the mailer using the Rcpt-To: header. # # Subject: # PHP mail() second argument to pass the subject, passing a Subject # as an additional header will result in a duplicate header. # # PEAR mailer should be passed a Subject header. # # -- hashar 20120218 $headers['From'] = $from->toString(); $headers['Return-Path'] = $from->address; if ($replyTo && $replyTo instanceof MailAddress) { $headers['Reply-To'] = $replyTo->toString(); } $headers['Date'] = date('r'); $headers['MIME-Version'] = '1.0'; if (empty($attachments)) { $headers['Content-Type'] = is_null($contentType) ? 'text/plain; charset=UTF-8' : $contentType; $headers['Content-Transfer-Encoding'] = '8bit'; } $headers['Message-ID'] = self::makeMsgId(); $headers['X-Mailer'] = 'MediaWiki mailer'; $headers['X-Msg-Category'] = $category; if ($priority) { $headers['X-Priority'] = $priority; } $ret = wfRunHooks('AlternateUserMailer', [$headers, $to, $from, $subject, $body, $priority, $attachments]); if ($ret === false) { return Status::newGood(); } elseif ($ret !== true) { return Status::newFatal('php-mail-error', $ret); } # MoLi: body can be an array with text and html message # MW core uses only text version of email message, so $body as array should be used only with AlternateUserMailer hook if (is_array($body) && isset($body['text'])) { $body = $body['text']; } if (is_array(F::app()->wg->SMTP)) { # # PEAR MAILER # if (function_exists('stream_resolve_include_path')) { $found = stream_resolve_include_path('Mail.php'); } else { $found = Fallback::stream_resolve_include_path('Mail.php'); } if (!$found) { throw new MWException('PEAR mail package is not installed'); } require_once 'Mail.php'; wfSuppressWarnings(); // Create the mail object using the Mail::factory method $mail_object =& Mail::factory('smtp', F::app()->wg->SMTP); if (PEAR::isError($mail_object)) { wfDebug("PEAR::Mail factory failed: " . $mail_object->getMessage() . "\n"); wfRestoreWarnings(); return Status::newFatal('pear-mail-error', $mail_object->getMessage()); } wfDebug("Sending mail via PEAR::Mail\n"); $headers['Subject'] = self::quotedPrintable($subject); # When sending only to one recipient, shows it its email using To: if (count($to) == 1) { $headers['To'] = $to[0]->toString(); } # Split jobs since SMTP servers tends to limit the maximum # number of possible recipients. $chunks = array_chunk($to, F::app()->wg->EnotifMaxRecips); foreach ($chunks as $chunk) { if (!wfRunHooks('ComposeMail', [$chunk, &$body, &$headers])) { continue; } $status = self::sendWithPear($mail_object, $chunk, $headers, $body); # FIXME : some chunks might be sent while others are not! if (!$status->isOK()) { wfRestoreWarnings(); return $status; } } wfRestoreWarnings(); return Status::newGood(); } else { # # PHP mail() # # Line endings need to be different on Unix and Windows due to # the bug described at http://trac.wordpress.org/ticket/2603 if (wfIsWindows()) { $body = str_replace("\n", "\r\n", $body); $endl = "\r\n"; } else { $endl = "\n"; } if (count($to) > 1) { $headers['To'] = 'undisclosed-recipients:;'; } $headers = self::arrayToHeaderString($headers, $endl); wfDebug("Sending mail via internal mail() function\n"); self::$mErrorString = ''; $html_errors = ini_get('html_errors'); ini_set('html_errors', '0'); $safeMode = wfIniGetBool('safe_mode'); foreach ($to as $recip) { if (!wfRunHooks('ComposeMail', array($recip, &$body, &$headers))) { continue; } if ($safeMode) { $sent = mail($recip, self::quotedPrintable($subject), $body, $headers); } else { $sent = mail($recip, self::quotedPrintable($subject), $body, $headers, F::app()->wg->AdditionalMailParams); } } ini_set('html_errors', $html_errors); if (self::$mErrorString) { wfDebug("Error sending mail: " . self::$mErrorString . "\n"); return Status::newFatal('php-mail-error', self::$mErrorString); } elseif (!$sent) { // mail function only tells if there's an error wfDebug("Unknown error sending mail\n"); return Status::newFatal('php-mail-error-unknown'); } else { return Status::newGood(); } } }