MediaWiki
REL1_24
|
00001 <?php 00029 class SpecialEmailUser extends UnlistedSpecialPage { 00030 protected $mTarget; 00031 00035 protected $mTargetObj; 00036 00037 public function __construct() { 00038 parent::__construct( 'Emailuser' ); 00039 } 00040 00041 public function getDescription() { 00042 $target = self::getTarget( $this->mTarget ); 00043 if ( !$target instanceof User ) { 00044 return $this->msg( 'emailuser-title-notarget' )->text(); 00045 } 00046 00047 return $this->msg( 'emailuser-title-target', $target->getName() )->text(); 00048 } 00049 00050 protected function getFormFields() { 00051 return array( 00052 'From' => array( 00053 'type' => 'info', 00054 'raw' => 1, 00055 'default' => Linker::link( 00056 $this->getUser()->getUserPage(), 00057 htmlspecialchars( $this->getUser()->getName() ) 00058 ), 00059 'label-message' => 'emailfrom', 00060 'id' => 'mw-emailuser-sender', 00061 ), 00062 'To' => array( 00063 'type' => 'info', 00064 'raw' => 1, 00065 'default' => Linker::link( 00066 $this->mTargetObj->getUserPage(), 00067 htmlspecialchars( $this->mTargetObj->getName() ) 00068 ), 00069 'label-message' => 'emailto', 00070 'id' => 'mw-emailuser-recipient', 00071 ), 00072 'Target' => array( 00073 'type' => 'hidden', 00074 'default' => $this->mTargetObj->getName(), 00075 ), 00076 'Subject' => array( 00077 'type' => 'text', 00078 'default' => $this->msg( 'defemailsubject', 00079 $this->getUser()->getName() )->inContentLanguage()->text(), 00080 'label-message' => 'emailsubject', 00081 'maxlength' => 200, 00082 'size' => 60, 00083 'required' => true, 00084 ), 00085 'Text' => array( 00086 'type' => 'textarea', 00087 'rows' => 20, 00088 'cols' => 80, 00089 'label-message' => 'emailmessage', 00090 'required' => true, 00091 ), 00092 'CCMe' => array( 00093 'type' => 'check', 00094 'label-message' => 'emailccme', 00095 'default' => $this->getUser()->getBoolOption( 'ccmeonemails' ), 00096 ), 00097 ); 00098 } 00099 00100 public function execute( $par ) { 00101 $out = $this->getOutput(); 00102 $out->addModuleStyles( 'mediawiki.special' ); 00103 00104 $this->mTarget = is_null( $par ) 00105 ? $this->getRequest()->getVal( 'wpTarget', $this->getRequest()->getVal( 'target', '' ) ) 00106 : $par; 00107 00108 // This needs to be below assignment of $this->mTarget because 00109 // getDescription() needs it to determine the correct page title. 00110 $this->setHeaders(); 00111 $this->outputHeader(); 00112 00113 // error out if sending user cannot do this 00114 $error = self::getPermissionsError( 00115 $this->getUser(), 00116 $this->getRequest()->getVal( 'wpEditToken' ), 00117 $this->getConfig() 00118 ); 00119 00120 switch ( $error ) { 00121 case null: 00122 # Wahey! 00123 break; 00124 case 'badaccess': 00125 throw new PermissionsError( 'sendemail' ); 00126 case 'blockedemailuser': 00127 throw new UserBlockedError( $this->getUser()->mBlock ); 00128 case 'actionthrottledtext': 00129 throw new ThrottledError; 00130 case 'mailnologin': 00131 case 'usermaildisabled': 00132 throw new ErrorPageError( $error, "{$error}text" ); 00133 default: 00134 # It's a hook error 00135 list( $title, $msg, $params ) = $error; 00136 throw new ErrorPageError( $title, $msg, $params ); 00137 } 00138 // Got a valid target user name? Else ask for one. 00139 $ret = self::getTarget( $this->mTarget ); 00140 if ( !$ret instanceof User ) { 00141 if ( $this->mTarget != '' ) { 00142 // Messages used here: notargettext, noemailtext, nowikiemailtext 00143 $ret = ( $ret == 'notarget' ) ? 'emailnotarget' : ( $ret . 'text' ); 00144 $out->wrapWikiMsg( "<p class='error'>$1</p>", $ret ); 00145 } 00146 $out->addHTML( $this->userForm( $this->mTarget ) ); 00147 00148 return; 00149 } 00150 00151 $this->mTargetObj = $ret; 00152 00153 $context = new DerivativeContext( $this->getContext() ); 00154 $context->setTitle( $this->getPageTitle() ); // Remove subpage 00155 $form = new HTMLForm( $this->getFormFields(), $context ); 00156 // By now we are supposed to be sure that $this->mTarget is a user name 00157 $form->addPreText( $this->msg( 'emailpagetext', $this->mTarget )->parse() ); 00158 $form->setSubmitTextMsg( 'emailsend' ); 00159 $form->setSubmitCallback( array( __CLASS__, 'uiSubmit' ) ); 00160 $form->setWrapperLegendMsg( 'email-legend' ); 00161 $form->loadData(); 00162 00163 if ( !wfRunHooks( 'EmailUserForm', array( &$form ) ) ) { 00164 return; 00165 } 00166 00167 $result = $form->show(); 00168 00169 if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) { 00170 $out->setPageTitle( $this->msg( 'emailsent' ) ); 00171 $out->addWikiMsg( 'emailsenttext', $this->mTarget ); 00172 $out->returnToMain( false, $this->mTargetObj->getUserPage() ); 00173 } 00174 } 00175 00182 public static function getTarget( $target ) { 00183 if ( $target == '' ) { 00184 wfDebug( "Target is empty.\n" ); 00185 00186 return 'notarget'; 00187 } 00188 00189 $nu = User::newFromName( $target ); 00190 if ( !$nu instanceof User || !$nu->getId() ) { 00191 wfDebug( "Target is invalid user.\n" ); 00192 00193 return 'notarget'; 00194 } elseif ( !$nu->isEmailConfirmed() ) { 00195 wfDebug( "User has no valid email.\n" ); 00196 00197 return 'noemail'; 00198 } elseif ( !$nu->canReceiveEmail() ) { 00199 wfDebug( "User does not allow user emails.\n" ); 00200 00201 return 'nowikiemail'; 00202 } 00203 00204 return $nu; 00205 } 00206 00215 public static function getPermissionsError( $user, $editToken, Config $config = null ) { 00216 if ( $config === null ) { 00217 wfDebug( __METHOD__ . ' called without a Config instance passed to it' ); 00218 $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' ); 00219 } 00220 if ( !$config->get( 'EnableEmail' ) || !$config->get( 'EnableUserEmail' ) ) { 00221 return 'usermaildisabled'; 00222 } 00223 00224 if ( !$user->isAllowed( 'sendemail' ) ) { 00225 return 'badaccess'; 00226 } 00227 00228 if ( !$user->isEmailConfirmed() ) { 00229 return 'mailnologin'; 00230 } 00231 00232 if ( $user->isBlockedFromEmailuser() ) { 00233 wfDebug( "User is blocked from sending e-mail.\n" ); 00234 00235 return "blockedemailuser"; 00236 } 00237 00238 if ( $user->pingLimiter( 'emailuser' ) ) { 00239 wfDebug( "Ping limiter triggered.\n" ); 00240 00241 return 'actionthrottledtext'; 00242 } 00243 00244 $hookErr = false; 00245 00246 wfRunHooks( 'UserCanSendEmail', array( &$user, &$hookErr ) ); 00247 wfRunHooks( 'EmailUserPermissionsErrors', array( $user, $editToken, &$hookErr ) ); 00248 00249 if ( $hookErr ) { 00250 return $hookErr; 00251 } 00252 00253 return null; 00254 } 00255 00262 protected function userForm( $name ) { 00263 $string = Xml::openElement( 00264 'form', 00265 array( 'method' => 'get', 'action' => wfScript(), 'id' => 'askusername' ) 00266 ) . 00267 Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) . 00268 Xml::openElement( 'fieldset' ) . 00269 Html::rawElement( 'legend', null, $this->msg( 'emailtarget' )->parse() ) . 00270 Xml::inputLabel( 00271 $this->msg( 'emailusername' )->text(), 00272 'target', 00273 'emailusertarget', 00274 30, 00275 $name 00276 ) . 00277 ' ' . 00278 Xml::submitButton( $this->msg( 'emailusernamesubmit' )->text() ) . 00279 Xml::closeElement( 'fieldset' ) . 00280 Xml::closeElement( 'form' ) . "\n"; 00281 00282 return $string; 00283 } 00284 00293 public static function uiSubmit( array $data, HTMLForm $form ) { 00294 return self::submit( $data, $form->getContext() ); 00295 } 00296 00307 public static function submit( array $data, IContextSource $context ) { 00308 $config = $context->getConfig(); 00309 00310 $target = self::getTarget( $data['Target'] ); 00311 if ( !$target instanceof User ) { 00312 // Messages used here: notargettext, noemailtext, nowikiemailtext 00313 return $context->msg( $target . 'text' )->parseAsBlock(); 00314 } 00315 00316 $to = MailAddress::newFromUser( $target ); 00317 $from = MailAddress::newFromUser( $context->getUser() ); 00318 $subject = $data['Subject']; 00319 $text = $data['Text']; 00320 00321 // Add a standard footer and trim up trailing newlines 00322 $text = rtrim( $text ) . "\n\n-- \n"; 00323 $text .= $context->msg( 'emailuserfooter', 00324 $from->name, $to->name )->inContentLanguage()->text(); 00325 00326 $error = ''; 00327 if ( !wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) { 00328 return $error; 00329 } 00330 00331 if ( $config->get( 'UserEmailUseReplyTo' ) ) { 00332 // Put the generic wiki autogenerated address in the From: 00333 // header and reserve the user for Reply-To. 00334 // 00335 // This is a bit ugly, but will serve to differentiate 00336 // wiki-borne mails from direct mails and protects against 00337 // SPF and bounce problems with some mailers (see below). 00338 $mailFrom = new MailAddress( $config->get( 'PasswordSender' ), 00339 wfMessage( 'emailsender' )->inContentLanguage()->text() ); 00340 $replyTo = $from; 00341 } else { 00342 // Put the sending user's e-mail address in the From: header. 00343 // 00344 // This is clean-looking and convenient, but has issues. 00345 // One is that it doesn't as clearly differentiate the wiki mail 00346 // from "directly" sent mails. 00347 // 00348 // Another is that some mailers (like sSMTP) will use the From 00349 // address as the envelope sender as well. For open sites this 00350 // can cause mails to be flunked for SPF violations (since the 00351 // wiki server isn't an authorized sender for various users' 00352 // domains) as well as creating a privacy issue as bounces 00353 // containing the recipient's e-mail address may get sent to 00354 // the sending user. 00355 $mailFrom = $from; 00356 $replyTo = null; 00357 } 00358 00359 $status = UserMailer::send( $to, $mailFrom, $subject, $text, $replyTo ); 00360 00361 if ( !$status->isGood() ) { 00362 return $status; 00363 } else { 00364 // if the user requested a copy of this mail, do this now, 00365 // unless they are emailing themselves, in which case one 00366 // copy of the message is sufficient. 00367 if ( $data['CCMe'] && $to != $from ) { 00368 $cc_subject = $context->msg( 'emailccsubject' )->rawParams( 00369 $target->getName(), $subject )->text(); 00370 wfRunHooks( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) ); 00371 $ccStatus = UserMailer::send( $from, $from, $cc_subject, $text ); 00372 $status->merge( $ccStatus ); 00373 } 00374 00375 wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $text ) ); 00376 00377 return $status; 00378 } 00379 } 00380 00381 protected function getGroupName() { 00382 return 'users'; 00383 } 00384 }