]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - includes/specials/SpecialEmailuser.php
MediaWiki 1.17.3-scripts
[autoinstallsdev/mediawiki.git] / includes / specials / SpecialEmailuser.php
1 <?php
2 /**
3  * Implements Special:Emailuser
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  * @file
21  * @ingroup SpecialPage
22  */
23
24 /**
25  * A special page that allows users to send e-mails to other users
26  *
27  * @ingroup SpecialPage
28  */
29 class SpecialEmailUser extends UnlistedSpecialPage {
30         protected $mTarget;
31         
32         public function __construct(){
33                 parent::__construct( 'Emailuser' );
34         }
35         
36         protected function getFormFields(){
37                 global $wgUser;
38                 return array(
39                         'From' => array(
40                                 'type' => 'info',
41                                 'raw' => 1,
42                                 'default' => $wgUser->getSkin()->link( 
43                                         $wgUser->getUserPage(), 
44                                         htmlspecialchars( $wgUser->getName() ) 
45                                 ),
46                                 'label-message' => 'emailfrom',
47                                 'id' => 'mw-emailuser-sender',
48                         ),
49                         'To' => array(
50                                 'type' => 'info',
51                                 'raw' => 1,
52                                 'default' => $wgUser->getSkin()->link( 
53                                         $this->mTargetObj->getUserPage(), 
54                                         htmlspecialchars( $this->mTargetObj->getName() )
55                                 ),
56                                 'label-message' => 'emailto',
57                                 'id' => 'mw-emailuser-recipient',
58                         ),
59                         'Target' => array(
60                                 'type' => 'hidden',
61                                 'default' => $this->mTargetObj->getName(),
62                         ),
63                         'Subject' => array(
64                                 'type' => 'text',
65                                 'default' => wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ) ),
66                                 'label-message' => 'emailsubject',
67                                 'maxlength' => 200,
68                                 'size' => 60,
69                                 'required' => 1,
70                         ),
71                         'Text' => array(
72                                 'type' => 'textarea',
73                                 'rows' => 20,
74                                 'cols' => 80,
75                                 'label-message' => 'emailmessage',
76                                 'required' => 1,
77                         ),
78                         'CCMe' => array(
79                                 'type' => 'check',
80                                 'label-message' => 'emailccme',
81                                 'default' => $wgUser->getBoolOption( 'ccmeonemails' ),
82                         ),
83                 );
84         }
85         
86         public function execute( $par ) {
87                 global $wgRequest, $wgOut, $wgUser;
88
89                 $this->setHeaders();
90                 $this->outputHeader();
91
92                 $this->mTarget = is_null( $par )
93                         ? $wgRequest->getVal( 'wpTarget', $wgRequest->getVal( 'target', '' ) )
94                         : $par;
95                         
96                 $ret = self::getTarget( $this->mTarget );
97                 if( $ret instanceof User ){
98                         $this->mTargetObj = $ret;
99                 } else {
100                         $wgOut->showErrorPage( "{$ret}title", "{$ret}text" );
101                         return false;
102                 }
103         
104                 $error = self::getPermissionsError( $wgUser, $wgRequest->getVal( 'wpEditToken' ) );
105                 switch ( $error ) {
106                         case null:
107                                 # Wahey!
108                                 break;
109                         case 'badaccess':
110                                 $wgOut->permissionRequired( 'sendemail' );
111                                 return;
112                         case 'blockedemailuser':
113                                 $wgOut->blockedPage();
114                                 return;
115                         case 'actionthrottledtext':
116                                 $wgOut->rateLimited();
117                                 return;
118                         case 'mailnologin':
119                         case 'usermaildisabled':
120                                 $wgOut->showErrorPage( $error, "{$error}text" );
121                                 return;
122                         default:
123                                 # It's a hook error
124                                 list( $title, $msg, $params ) = $error;
125                                 $wgOut->showErrorPage( $title, $msg, $params );
126                                 return;
127                 }
128                 
129                 $form = new HTMLForm( $this->getFormFields() );
130                 $form->addPreText( wfMsgExt( 'emailpagetext', 'parseinline' ) );
131                 $form->setSubmitText( wfMsg( 'emailsend' ) );
132                 $form->setTitle( $this->getTitle() );
133                 $form->setSubmitCallback( array( __CLASS__, 'submit' ) );
134                 $form->setWrapperLegend( wfMsgExt( 'email-legend', 'parsemag' ) );
135                 $form->loadData();
136                 
137                 if( !wfRunHooks( 'EmailUserForm', array( &$form ) ) ){
138                         return false;
139                 }
140                 
141                 $wgOut->setPagetitle( wfMsg( 'emailpage' ) );
142                 $result = $form->show();
143                 
144                 if( $result === true || ( $result instanceof Status && $result->isGood() ) ){
145                         $wgOut->setPagetitle( wfMsg( 'emailsent' ) );
146                         $wgOut->addWikiMsg( 'emailsenttext' );
147                         $wgOut->returnToMain( false, $this->mTargetObj->getUserPage() );
148                 }
149         }
150
151         /**
152          * Validate target User
153          *
154          * @param $target String: target user name
155          * @return User object on success or a string on error
156          */
157         public static function getTarget( $target ) {
158                 if ( $target == '' ) {
159                         wfDebug( "Target is empty.\n" );
160                         return 'notarget';
161                 }
162                 
163                 $nu = User::newFromName( $target );
164                 if( !$nu instanceof User || !$nu->getId() ) {
165                         wfDebug( "Target is invalid user.\n" );
166                         return 'notarget';
167                 } else if ( !$nu->isEmailConfirmed() ) {
168                         wfDebug( "User has no valid email.\n" );
169                         return 'noemail';
170                 } else if ( !$nu->canReceiveEmail() ) {
171                         wfDebug( "User does not allow user emails.\n" );
172                         return 'nowikiemail';
173                 }
174
175                 return $nu;
176         }
177
178         /**
179          * Check whether a user is allowed to send email
180          *
181          * @param $user User object
182          * @param $editToken String: edit token
183          * @return null on success or string on error
184          */
185         public static function getPermissionsError( $user, $editToken ) {
186                 global $wgEnableEmail, $wgEnableUserEmail;
187                 if( !$wgEnableEmail || !$wgEnableUserEmail ){
188                         return 'usermaildisabled';
189                 }
190                 
191                 if( !$user->isAllowed( 'sendemail' ) ) {
192                         return 'badaccess';
193                 }
194                 
195                 if( !$user->isEmailConfirmed() ){
196                         return 'mailnologin';
197                 }
198
199                 if( $user->isBlockedFromEmailuser() ) {
200                         wfDebug( "User is blocked from sending e-mail.\n" );
201                         return "blockedemailuser";
202                 }
203
204                 if( $user->pingLimiter( 'emailuser' ) ) {
205                         wfDebug( "Ping limiter triggered.\n" );
206                         return 'actionthrottledtext';
207                 }
208
209                 $hookErr = false;
210                 wfRunHooks( 'UserCanSendEmail', array( &$user, &$hookErr ) );
211                 wfRunHooks( 'EmailUserPermissionsErrors', array( $user, $editToken, &$hookErr ) );
212                 if ( $hookErr ) {
213                         return $hookErr;
214                 }
215
216                 return null;
217         }
218
219         /**
220          * Really send a mail. Permissions should have been checked using
221          * getPermissionsError(). It is probably also a good 
222          * idea to check the edit token and ping limiter in advance.
223          *
224          * @return Mixed: Status object, or potentially a String on error
225          * or maybe even true on success if anything uses the EmailUser hook.
226          */
227         public static function submit( $data ) {
228                 global $wgUser, $wgUserEmailUseReplyTo;
229
230                 $target = self::getTarget( $data['Target'] );
231                 if( !$target instanceof User ){
232                         return wfMsgExt( $target . 'text', 'parse' );
233                 }
234                 $to = new MailAddress( $target );
235                 $from = new MailAddress( $wgUser );
236                 $subject = $data['Subject'];
237                 $text = $data['Text'];
238
239                 // Add a standard footer and trim up trailing newlines
240                 $text = rtrim( $text ) . "\n\n-- \n";
241                 $text .= wfMsgExt( 
242                         'emailuserfooter',
243                         array( 'content', 'parsemag' ), 
244                         array( $from->name, $to->name ) 
245                 );
246
247                 $error = '';
248                 if( !wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) {
249                         return $error;
250                 }
251                 
252                 if( $wgUserEmailUseReplyTo ) {
253                         // Put the generic wiki autogenerated address in the From:
254                         // header and reserve the user for Reply-To.
255                         //
256                         // This is a bit ugly, but will serve to differentiate
257                         // wiki-borne mails from direct mails and protects against
258                         // SPF and bounce problems with some mailers (see below).
259                         global $wgPasswordSender, $wgPasswordSenderName;
260                         $mailFrom = new MailAddress( $wgPasswordSender, $wgPasswordSenderName );
261                         $replyTo = $from;
262                 } else {
263                         // Put the sending user's e-mail address in the From: header.
264                         //
265                         // This is clean-looking and convenient, but has issues.
266                         // One is that it doesn't as clearly differentiate the wiki mail
267                         // from "directly" sent mails.
268                         //
269                         // Another is that some mailers (like sSMTP) will use the From
270                         // address as the envelope sender as well. For open sites this
271                         // can cause mails to be flunked for SPF violations (since the
272                         // wiki server isn't an authorized sender for various users'
273                         // domains) as well as creating a privacy issue as bounces
274                         // containing the recipient's e-mail address may get sent to
275                         // the sending user.
276                         $mailFrom = $from;
277                         $replyTo = null;
278                 }
279
280                 $status = UserMailer::send( $to, $mailFrom, $subject, $text, $replyTo );
281
282                 if( !$status->isGood() ) {
283                         return $status;
284                 } else {
285                         // if the user requested a copy of this mail, do this now,
286                         // unless they are emailing themselves, in which case one 
287                         // copy of the message is sufficient.
288                         if ( $data['CCMe'] && $to != $from ) {
289                                 $cc_subject = wfMsg(
290                                         'emailccsubject', 
291                                         $target->getName(), 
292                                         $subject
293                                 );
294                                 wfRunHooks( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) );
295                                 $ccStatus = UserMailer::send( $from, $from, $cc_subject, $text );
296                                 $status->merge( $ccStatus );
297                         }
298
299                         wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $text ) );
300                         return $status;
301                 }
302         }
303 }