45 private $userNameUtils;
48 private $userNamePrefixSearch;
51 private $userOptionsLookup;
63 parent::__construct(
'Emailuser' );
64 $this->userNameUtils = $userNameUtils;
65 $this->userNamePrefixSearch = $userNamePrefixSearch;
66 $this->userOptionsLookup = $userOptionsLookup;
75 if ( !$target instanceof
User ) {
76 return $this->
msg(
'emailuser-title-notarget' )->text();
79 return $this->
msg(
'emailuser-title-target', $target->getName() )->text();
89 'default' => $linkRenderer->makeLink(
93 'label-message' =>
'emailfrom',
94 'id' =>
'mw-emailuser-sender',
99 'default' => $linkRenderer->makeLink(
100 $this->mTargetObj->getUserPage(),
101 $this->mTargetObj->getName()
103 'label-message' =>
'emailto',
104 'id' =>
'mw-emailuser-recipient',
108 'default' => $this->mTargetObj->getName(),
112 'default' => $this->
msg(
'defemailsubject', $user->getName() )->inContentLanguage()->text(),
113 'label-message' =>
'emailsubject',
119 'type' =>
'textarea',
121 'label-message' =>
'emailmessage',
126 'label-message' =>
'emailccme',
127 'default' => $this->userOptionsLookup->getBoolOption( $user,
'ccmeonemails' ),
135 $out->addModuleStyles(
'mediawiki.special' );
137 $this->mTarget = $par ?? $request->getVal(
'wpTarget', $request->getVal(
'target',
'' ) );
157 case 'blockedemailuser':
160 case 'actionthrottledtext':
163 case 'usermaildisabled':
167 list(
$title, $msg, $params ) = $error;
177 if ( !$this->mTargetObj instanceof
User ) {
193 if ( $target ==
'' ) {
202 return $error ?: $nu;
214 if ( !$target instanceof
User || !$target->
getId() ) {
215 wfDebug(
"Target is invalid user." );
220 if ( !$target->isEmailConfirmed() ) {
221 wfDebug(
"User has no valid email." );
226 if ( !$target->canReceiveEmail() ) {
227 wfDebug(
"User does not allow user emails." );
229 return 'nowikiemail';
232 $userOptionsLookup = MediaWikiServices::getInstance()
233 ->getUserOptionsLookup();
236 'email-allow-new-users'
239 wfDebug(
"User does not allow user emails from new users." );
241 return 'nowikiemail';
244 $muteList = $userOptionsLookup->
getOption(
250 $muteList = MultiUsernameFilter::splitIds( $muteList );
251 $senderId = MediaWikiServices::getInstance()
252 ->getCentralIdLookup()
253 ->centralIdFromLocalUser( $sender );
254 if ( $senderId !== 0 && in_array( $senderId, $muteList ) ) {
255 wfDebug(
"User does not allow user emails from this user." );
257 return 'nowikiemail';
274 if ( $config ===
null ) {
275 wfDebug( __METHOD__ .
' called without a Config instance passed to it' );
276 $config = MediaWikiServices::getInstance()->getMainConfig();
278 if ( !$config->get( MainConfigNames::EnableEmail ) ||
279 !$config->get( MainConfigNames::EnableUserEmail ) ) {
280 return 'usermaildisabled';
285 if ( !$user->isEmailConfirmed() ) {
286 return 'mailnologin';
289 if ( !MediaWikiServices::getInstance()
290 ->getPermissionManager()
291 ->userHasRight( $user,
'sendemail' )
296 if ( $user->isBlockedFromEmailuser() ) {
297 wfDebug(
"User is blocked from sending e-mail." );
299 return "blockedemailuser";
304 if ( $user->pingLimiter(
'emailuser', 0 ) ) {
305 wfDebug(
"Ping limiter triggered." );
307 return 'actionthrottledtext';
312 Hooks::runner()->onUserCanSendEmail( $user, $hookErr );
313 Hooks::runner()->onEmailUserPermissionsErrors( $user, $editToken, $hookErr );
328 $htmlForm = HTMLForm::factory(
'ooui', [
333 'label' => $this->
msg(
'emailusername' )->text(),
334 'id' =>
'emailusertarget',
342 ->setSubmitCallback( [ $this,
'sendEmailForm' ] )
343 ->setFormIdentifier(
'userForm' )
344 ->setId(
'askusername' )
345 ->setWrapperLegendMsg(
'emailtarget' )
346 ->setSubmitTextMsg(
'emailusernamesubmit' )
354 if ( !$ret instanceof
User ) {
355 if ( $this->mTarget !=
'' ) {
357 $ret = ( $ret ==
'notarget' ) ?
'emailnotarget' : ( $ret .
'text' );
358 return Status::newFatal( $ret );
367 ->addPreText( $this->
msg(
'emailpagetext', $this->mTarget )->parse() )
368 ->setSubmitTextMsg(
'emailsend' )
369 ->setSubmitCallback( [ __CLASS__,
'submit' ] )
370 ->setFormIdentifier(
'sendEmailForm' )
371 ->setWrapperLegendMsg(
'email-legend' )
374 if ( !$this->
getHookRunner()->onEmailUserForm( $htmlForm ) ) {
378 $result = $htmlForm->show();
380 if ( $result ===
true || ( $result instanceof
Status && $result->
isGood() ) ) {
381 $out->setPageTitle( $this->
msg(
'emailsent' ) );
382 $out->addWikiMsg(
'emailsenttext', $this->mTarget );
383 $out->returnToMain(
false, $ret->getUserPage() );
403 if ( !$target instanceof
User ) {
405 return Status::newFatal( $target .
'text' );
408 $toAddress = MailAddress::newFromUser( $target );
409 $fromAddress = MailAddress::newFromUser( $sender );
410 $subject = $data[
'Subject'];
411 $text = $data[
'Text'];
414 $text = rtrim( $text ) .
"\n\n-- \n";
415 $text .= $context->
msg(
419 )->inContentLanguage()->text();
421 if ( $config->get( MainConfigNames::EnableSpecialMute ) ) {
423 $text .=
"\n" . $context->
msg(
424 'specialmute-email-footer',
425 $specialMutePage->getCanonicalURL(),
427 )->inContentLanguage()->text();
431 if ( $sender->pingLimiter(
'emailuser' ) ) {
437 $hookRunner = Hooks::runner();
438 $emailer = MediaWikiServices::getInstance()->getEmailer();
441 if ( !$hookRunner->onEmailUser( $toAddress, $fromAddress, $subject, $text, $error ) ) {
442 if ( $error instanceof
Status ) {
444 } elseif ( $error ===
false || $error ===
'' || $error === [] ) {
447 } elseif ( $error ===
true ) {
449 return Status::newGood();
450 } elseif ( is_array( $error ) ) {
451 $status = Status::newGood();
452 foreach ( $error as $e ) {
453 $status->fatal( $e );
457 return Status::newFatal( $error );
461 $type = is_object( $error ) ? get_class( $error ) : gettype( $error );
463 'EmailUser hook set $error to unsupported type ' .
$type
468 if ( $config->get( MainConfigNames::UserEmailUseReplyTo ) ) {
478 $config->get( MainConfigNames::PasswordSender ),
479 $context->
msg(
'emailsender' )->inContentLanguage()->text()
481 $replyTo = $fromAddress;
498 $mailFrom = $fromAddress;
502 $status = Status::wrap( $emailer->send(
508 [
'replyTo' => $replyTo ]
511 if ( !$status->isGood() ) {
518 if ( $data[
'CCMe'] && $toAddress != $fromAddress ) {
519 $ccTo = $fromAddress;
520 $ccFrom = $fromAddress;
521 $ccSubject = $context->
msg(
'emailccsubject' )->plaintextParams(
527 $hookRunner->onEmailUserCC( $ccTo, $ccFrom, $ccSubject, $ccText );
529 if ( $config->get( MainConfigNames::UserEmailUseReplyTo ) ) {
531 $config->get( MainConfigNames::PasswordSender ),
532 $context->
msg(
'emailsender' )->inContentLanguage()->text()
540 $ccStatus = $emailer->send(
546 [
'replyTo' => $replyTo ]
548 $status->merge( $ccStatus );
551 $hookRunner->onEmailUserComplete( $toAddress, $fromAddress, $subject, $text );
565 $search = $this->userNameUtils->getCanonical( $search );
571 return $this->userNamePrefixSearch
572 ->search( UserNamePrefixSearch::AUDIENCE_PUBLIC, $search, $limit, $offset );
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
An error page which can definitely be safely rendered using the OutputPage.
Stores a single person's name and email address.
A class containing constants representing the names of configuration variables.
Show an error when a user tries to do something they do not have the necessary permissions for.
A special page that allows users to send e-mails to other users.
static getTarget( $target, User $sender)
Validate target User.
userForm( $name)
Form to ask for target user name.
static getPermissionsError( $user, $editToken, Config $config=null)
Check whether a user is allowed to send email.
static validateTarget( $target, User $sender)
Validate target User.
static submit(array $data, IContextSource $context)
Really send a mail.
prefixSearchSubpages( $search, $limit, $offset)
Return an array of subpages beginning with $search that this special page will accept.
doesWrites()
Indicates whether this special page may perform database writes.
__construct(UserNameUtils $userNameUtils, UserNamePrefixSearch $userNamePrefixSearch, UserOptionsLookup $userOptionsLookup)
getDescription()
Returns the name that goes in the <h1> in the special page itself, and also the name that will be l...
execute( $par)
Default execute method Checks user permissions.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
outputHeader( $summaryMessageKey='')
Outputs a summary message on top of special pages Per default the message key is the canonical name o...
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getRequest()
Get the WebRequest being used for this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
isGood()
Returns whether the operation completed and didn't have any error or warnings.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Show an error when the user hits a rate limit.
Shortcut to construct a special page which is unlisted by default.
Show an error when the user tries to do something whilst blocked.
static newFromName( $name, $validate='valid')
isNewbie()
Determine whether the user is a newbie.
getId( $wikiId=self::LOCAL)
Get the user's ID.
Interface for configuration instances.
Interface for objects which can provide a MediaWiki context on request.
getConfig()
Get the site configuration.
msg( $key,... $params)
This is the method for getting translated interface messages.