/** * 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|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 or Array of two strings to be the text and html bodies * @param array $options: * 'replyTo' MailAddress * 'contentType' string default 'text/plain; charset=UTF-8' * 'headers' array Extra headers to set * * Previous versions of this function had $replyto as the 5th argument and $contentType * as the 6th. These are still supported for backwards compatability, but deprecated. * * @throws MWException * @throws Exception * @return Status */ public static function send($to, $from, $subject, $body, $options = array()) { global $wgAllowHTMLEmail; $contentType = 'text/plain; charset=UTF-8'; if (!is_array($options)) { // Old calling style wfDeprecated(__METHOD__ . ' with $replyto as 5th parameter', '1.26'); $options = array('replyTo' => $options); if (func_num_args() === 6) { $options['contentType'] = func_get_arg(5); } } if (!is_array($to)) { $to = array($to); } // mail body must have some content $minBodyLen = 10; // arbitrary but longer than Array or Object to detect casting error // body must either be a string or an array with text and body if (!(!is_array($body) && strlen($body) >= $minBodyLen) && !(is_array($body) && isset($body['text']) && isset($body['html']) && strlen($body['text']) >= $minBodyLen && strlen($body['html']) >= $minBodyLen)) { // if it is neither we have a problem return Status::newFatal('user-mail-no-body'); } if (!$wgAllowHTMLEmail && is_array($body)) { // HTML not wanted. Dump it. $body = $body['text']; } wfDebug(__METHOD__ . ': sending mail to ' . implode(', ', $to) . "\n"); // 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'); } // give a chance to UserMailerTransformContents subscribers who need to deal with each // target differently to split up the address list if (count($to) > 1) { $oldTo = $to; Hooks::run('UserMailerSplitTo', array(&$to)); if ($oldTo != $to) { $splitTo = array_diff($oldTo, $to); $to = array_diff($oldTo, $splitTo); // ignore new addresses added in the hook // first send to non-split address list, then to split addresses one by one $status = Status::newGood(); if ($to) { $status->merge(UserMailer::sendInternal($to, $from, $subject, $body, $options)); } foreach ($splitTo as $newTo) { $status->merge(UserMailer::sendInternal(array($newTo), $from, $subject, $body, $options)); } return $status; } } return UserMailer::sendInternal($to, $from, $subject, $body, $options); }