MediaWiki
REL1_23
|
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 ); 00118 00119 switch ( $error ) { 00120 case null: 00121 # Wahey! 00122 break; 00123 case 'badaccess': 00124 throw new PermissionsError( 'sendemail' ); 00125 case 'blockedemailuser': 00126 throw new UserBlockedError( $this->getUser()->mBlock ); 00127 case 'actionthrottledtext': 00128 throw new ThrottledError; 00129 case 'mailnologin': 00130 case 'usermaildisabled': 00131 throw new ErrorPageError( $error, "{$error}text" ); 00132 default: 00133 # It's a hook error 00134 list( $title, $msg, $params ) = $error; 00135 throw new ErrorPageError( $title, $msg, $params ); 00136 } 00137 // Got a valid target user name? Else ask for one. 00138 $ret = self::getTarget( $this->mTarget ); 00139 if ( !$ret instanceof User ) { 00140 if ( $this->mTarget != '' ) { 00141 // Messages used here: notargettext, noemailtext, nowikiemailtext 00142 $ret = ( $ret == 'notarget' ) ? 'emailnotarget' : ( $ret . 'text' ); 00143 $out->wrapWikiMsg( "<p class='error'>$1</p>", $ret ); 00144 } 00145 $out->addHTML( $this->userForm( $this->mTarget ) ); 00146 00147 return; 00148 } 00149 00150 $this->mTargetObj = $ret; 00151 00152 $context = new DerivativeContext( $this->getContext() ); 00153 $context->setTitle( $this->getPageTitle() ); // Remove subpage 00154 $form = new HTMLForm( $this->getFormFields(), $context ); 00155 // By now we are supposed to be sure that $this->mTarget is a user name 00156 $form->addPreText( $this->msg( 'emailpagetext', $this->mTarget )->parse() ); 00157 $form->setSubmitTextMsg( 'emailsend' ); 00158 $form->setSubmitCallback( array( __CLASS__, 'uiSubmit' ) ); 00159 $form->setWrapperLegendMsg( 'email-legend' ); 00160 $form->loadData(); 00161 00162 if ( !wfRunHooks( 'EmailUserForm', array( &$form ) ) ) { 00163 return; 00164 } 00165 00166 $result = $form->show(); 00167 00168 if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) { 00169 $out->setPageTitle( $this->msg( 'emailsent' ) ); 00170 $out->addWikiMsg( 'emailsenttext', $this->mTarget ); 00171 $out->returnToMain( false, $this->mTargetObj->getUserPage() ); 00172 } 00173 } 00174 00181 public static function getTarget( $target ) { 00182 if ( $target == '' ) { 00183 wfDebug( "Target is empty.\n" ); 00184 00185 return 'notarget'; 00186 } 00187 00188 $nu = User::newFromName( $target ); 00189 if ( !$nu instanceof User || !$nu->getId() ) { 00190 wfDebug( "Target is invalid user.\n" ); 00191 00192 return 'notarget'; 00193 } elseif ( !$nu->isEmailConfirmed() ) { 00194 wfDebug( "User has no valid email.\n" ); 00195 00196 return 'noemail'; 00197 } elseif ( !$nu->canReceiveEmail() ) { 00198 wfDebug( "User does not allow user emails.\n" ); 00199 00200 return 'nowikiemail'; 00201 } 00202 00203 return $nu; 00204 } 00205 00213 public static function getPermissionsError( $user, $editToken ) { 00214 global $wgEnableEmail, $wgEnableUserEmail; 00215 00216 if ( !$wgEnableEmail || !$wgEnableUserEmail ) { 00217 return 'usermaildisabled'; 00218 } 00219 00220 if ( !$user->isAllowed( 'sendemail' ) ) { 00221 return 'badaccess'; 00222 } 00223 00224 if ( !$user->isEmailConfirmed() ) { 00225 return 'mailnologin'; 00226 } 00227 00228 if ( $user->isBlockedFromEmailuser() ) { 00229 wfDebug( "User is blocked from sending e-mail.\n" ); 00230 00231 return "blockedemailuser"; 00232 } 00233 00234 if ( $user->pingLimiter( 'emailuser' ) ) { 00235 wfDebug( "Ping limiter triggered.\n" ); 00236 00237 return 'actionthrottledtext'; 00238 } 00239 00240 $hookErr = false; 00241 00242 wfRunHooks( 'UserCanSendEmail', array( &$user, &$hookErr ) ); 00243 wfRunHooks( 'EmailUserPermissionsErrors', array( $user, $editToken, &$hookErr ) ); 00244 00245 if ( $hookErr ) { 00246 return $hookErr; 00247 } 00248 00249 return null; 00250 } 00251 00258 protected function userForm( $name ) { 00259 global $wgScript; 00260 $string = Xml::openElement( 00261 'form', 00262 array( 'method' => 'get', 'action' => $wgScript, 'id' => 'askusername' ) 00263 ) . 00264 Html::hidden( 'title', $this->getPageTitle()->getPrefixedText() ) . 00265 Xml::openElement( 'fieldset' ) . 00266 Html::rawElement( 'legend', null, $this->msg( 'emailtarget' )->parse() ) . 00267 Xml::inputLabel( 00268 $this->msg( 'emailusername' )->text(), 00269 'target', 00270 'emailusertarget', 00271 30, 00272 $name 00273 ) . 00274 ' ' . 00275 Xml::submitButton( $this->msg( 'emailusernamesubmit' )->text() ) . 00276 Xml::closeElement( 'fieldset' ) . 00277 Xml::closeElement( 'form' ) . "\n"; 00278 00279 return $string; 00280 } 00281 00290 public static function uiSubmit( array $data, HTMLForm $form ) { 00291 return self::submit( $data, $form->getContext() ); 00292 } 00293 00304 public static function submit( array $data, IContextSource $context ) { 00305 global $wgUserEmailUseReplyTo; 00306 00307 $target = self::getTarget( $data['Target'] ); 00308 if ( !$target instanceof User ) { 00309 // Messages used here: notargettext, noemailtext, nowikiemailtext 00310 return $context->msg( $target . 'text' )->parseAsBlock(); 00311 } 00312 00313 $to = new MailAddress( $target ); 00314 $from = new MailAddress( $context->getUser() ); 00315 $subject = $data['Subject']; 00316 $text = $data['Text']; 00317 00318 // Add a standard footer and trim up trailing newlines 00319 $text = rtrim( $text ) . "\n\n-- \n"; 00320 $text .= $context->msg( 'emailuserfooter', 00321 $from->name, $to->name )->inContentLanguage()->text(); 00322 00323 $error = ''; 00324 if ( !wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) { 00325 return $error; 00326 } 00327 00328 if ( $wgUserEmailUseReplyTo ) { 00329 // Put the generic wiki autogenerated address in the From: 00330 // header and reserve the user for Reply-To. 00331 // 00332 // This is a bit ugly, but will serve to differentiate 00333 // wiki-borne mails from direct mails and protects against 00334 // SPF and bounce problems with some mailers (see below). 00335 global $wgPasswordSender; 00336 00337 $mailFrom = new MailAddress( $wgPasswordSender, 00338 wfMessage( 'emailsender' )->inContentLanguage()->text() ); 00339 $replyTo = $from; 00340 } else { 00341 // Put the sending user's e-mail address in the From: header. 00342 // 00343 // This is clean-looking and convenient, but has issues. 00344 // One is that it doesn't as clearly differentiate the wiki mail 00345 // from "directly" sent mails. 00346 // 00347 // Another is that some mailers (like sSMTP) will use the From 00348 // address as the envelope sender as well. For open sites this 00349 // can cause mails to be flunked for SPF violations (since the 00350 // wiki server isn't an authorized sender for various users' 00351 // domains) as well as creating a privacy issue as bounces 00352 // containing the recipient's e-mail address may get sent to 00353 // the sending user. 00354 $mailFrom = $from; 00355 $replyTo = null; 00356 } 00357 00358 $status = UserMailer::send( $to, $mailFrom, $subject, $text, $replyTo ); 00359 00360 if ( !$status->isGood() ) { 00361 return $status; 00362 } else { 00363 // if the user requested a copy of this mail, do this now, 00364 // unless they are emailing themselves, in which case one 00365 // copy of the message is sufficient. 00366 if ( $data['CCMe'] && $to != $from ) { 00367 $cc_subject = $context->msg( 'emailccsubject' )->rawParams( 00368 $target->getName(), $subject )->text(); 00369 wfRunHooks( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) ); 00370 $ccStatus = UserMailer::send( $from, $from, $cc_subject, $text ); 00371 $status->merge( $ccStatus ); 00372 } 00373 00374 wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $text ) ); 00375 00376 return $status; 00377 } 00378 } 00379 00380 protected function getGroupName() { 00381 return 'users'; 00382 } 00383 }