* @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
+ * @param array $options Keys:
+ * 'replyTo' MailAddress
+ * 'contentType' string default 'text/plain; charset=UTF-8'
+ * 'headers' array Extra headers to set
*
* @throws MWException
* @throws Exception
// first send to non-split address list, then to split addresses one by one
$status = Status::newGood();
if ( $to ) {
- $status->merge( UserMailer::sendInternal(
+ $status->merge( self::sendInternal(
$to, $from, $subject, $body, $options ) );
}
foreach ( $splitTo as $newTo ) {
- $status->merge( UserMailer::sendInternal(
+ $status->merge( self::sendInternal(
[ $newTo ], $from, $subject, $body, $options ) );
}
return $status;
}
}
- return UserMailer::sendInternal( $to, $from, $subject, $body, $options );
+ return self::sendInternal( $to, $from, $subject, $body, $options );
+ }
+
+ /**
+ * Whether the PEAR Mail_mime library is usable. This will
+ * try and load it if it is not already.
+ *
+ * @return bool
+ */
+ private static function isMailMimeUsable() {
+ static $usable = null;
+ if ( $usable === null ) {
+ $usable = class_exists( 'Mail_mime' );
+ }
+ return $usable;
+ }
+
+ /**
+ * Whether the PEAR Mail library is usable. This will
+ * try and load it if it is not already.
+ *
+ * @return bool
+ */
+ private static function isMailUsable() {
+ static $usable = null;
+ if ( $usable === null ) {
+ $usable = class_exists( 'Mail' );
+ }
+
+ return $usable;
}
/**
* @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
+ * @param array $options Keys:
+ * 'replyTo' MailAddress
+ * 'contentType' string default 'text/plain; charset=UTF-8'
+ * 'headers' array Extra headers to set
*
* @throws MWException
* @throws Exception
// Add the envelope sender address using the -f command line option when PHP mail() is used.
// Will default to the $from->address when the UserMailerChangeReturnPath hook fails and the
// generated VERP address when the hook runs effectively.
- $extraParams .= ' -f ' . $returnPath;
+
+ // PHP runs this through escapeshellcmd(). However that's not sufficient
+ // escaping (e.g. due to spaces). MediaWiki's email sanitizer should generally
+ // be good enough, but just in case, put in double quotes, and remove any
+ // double quotes present (" is not allowed in emails, so should have no
+ // effect, although this might cause apostrophees to be double escaped)
+ $returnPathCLI = '"' . str_replace( '"', '', $returnPath ) . '"';
+ $extraParams .= ' -f ' . $returnPathCLI;
$headers['Return-Path'] = $returnPath;
->getFullURL( '', false, PROTO_CANONICAL ) . '>';
// Line endings need to be different on Unix and Windows due to
- // the bug described at http://trac.wordpress.org/ticket/2603
+ // the bug described at https://core.trac.wordpress.org/ticket/2603
$endl = PHP_EOL;
if ( is_array( $body ) ) {
// we are sending a multipart message
wfDebug( "Assembling multipart mime email\n" );
- if ( !stream_resolve_include_path( 'Mail/mime.php' ) ) {
+ if ( !self::isMailMimeUsable() ) {
wfDebug( "PEAR Mail_Mime package is not installed. Falling back to text email.\n" );
// remove the html body for text email fall back
$body = $body['text'];
} else {
- // Check if pear/mail_mime is already loaded (via composer)
- if ( !class_exists( 'Mail_mime' ) ) {
- require_once 'Mail/mime.php';
- }
+ // pear/mail_mime is already loaded by this point
if ( wfIsWindows() ) {
$body['text'] = str_replace( "\n", "\r\n", $body['text'] );
$body['html'] = str_replace( "\n", "\r\n", $body['html'] );
if ( is_array( $wgSMTP ) ) {
// Check if pear/mail is already loaded (via composer)
- if ( !class_exists( 'Mail' ) ) {
- // PEAR MAILER
- if ( !stream_resolve_include_path( 'Mail.php' ) ) {
- throw new MWException( 'PEAR mail package is not installed' );
- }
- require_once 'Mail.php';
+ if ( !self::isMailUsable() ) {
+ throw new MWException( 'PEAR mail package is not installed' );
}
- MediaWiki\suppressWarnings();
+ Wikimedia\suppressWarnings();
// Create the mail object using the Mail::factory method
- $mail_object =& Mail::factory( 'smtp', $wgSMTP );
+ $mail_object = Mail::factory( 'smtp', $wgSMTP );
if ( PEAR::isError( $mail_object ) ) {
wfDebug( "PEAR::Mail factory failed: " . $mail_object->getMessage() . "\n" );
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
return Status::newFatal( 'pear-mail-error', $mail_object->getMessage() );
}
$status = self::sendWithPear( $mail_object, $chunk, $headers, $body );
// FIXME : some chunks might be sent while others are not!
if ( !$status->isOK() ) {
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
return $status;
}
}
- MediaWiki\restoreWarnings();
+ Wikimedia\restoreWarnings();
return Status::newGood();
} else {
// PHP mail()