Index: trunk/phase3/includes/api/ApiEmailUser.php |
— | — | @@ -38,10 +38,6 @@ |
39 | 39 | |
40 | 40 | public function execute() { |
41 | 41 | global $wgUser; |
42 | | - // Check whether email is enabled |
43 | | - if ( !EmailUserForm::userEmailEnabled() ) { |
44 | | - $this->dieUsageMsg( array( 'usermaildisabled' ) ); |
45 | | - } |
46 | 42 | |
47 | 43 | $params = $this->extractRequestParams(); |
48 | 44 | // Check required parameters |
— | — | @@ -53,25 +49,30 @@ |
54 | 50 | } |
55 | 51 | |
56 | 52 | // Validate target |
57 | | - $targetUser = EmailUserForm::validateEmailTarget( $params['target'] ); |
| 53 | + $targetUser = SpecialEmailuser::getTarget( $params['target'] ); |
58 | 54 | if ( !( $targetUser instanceof User ) ) { |
59 | 55 | $this->dieUsageMsg( array( $targetUser ) ); |
60 | 56 | } |
61 | 57 | |
62 | | - // Check permissions |
63 | | - $error = EmailUserForm::getPermissionsError( $wgUser, $params['token'] ); |
| 58 | + // Check permissions and errors |
| 59 | + $error = SpecialEmailuser::getPermissionsError( $wgUser, $params['token'] ); |
64 | 60 | if ( $error ) { |
65 | 61 | $this->dieUsageMsg( array( $error ) ); |
66 | 62 | } |
67 | 63 | |
68 | | - $form = new EmailUserForm( $targetUser, $params['text'], $params['subject'], $params['ccme'] ); |
69 | | - $retval = $form->doSubmit(); |
70 | | - if ( is_null( $retval ) ) { |
| 64 | + $data = array( |
| 65 | + 'Target' => $targetUser->getName(), |
| 66 | + 'Text' => $params['text'], |
| 67 | + 'Subject' => $params['subject'], |
| 68 | + 'CCMe' => $params['ccme'], |
| 69 | + ); |
| 70 | + $retval = SpecialEmailuser::submit( $data ); |
| 71 | + if ( $retval === true ) { |
71 | 72 | $result = array( 'result' => 'Success' ); |
72 | 73 | } else { |
73 | 74 | $result = array( |
74 | 75 | 'result' => 'Failure', |
75 | | - 'message' => $retval->getMessage() |
| 76 | + 'message' => $retval |
76 | 77 | ); |
77 | 78 | } |
78 | 79 | |
Index: trunk/phase3/includes/AutoLoader.php |
— | — | @@ -512,7 +512,7 @@ |
513 | 513 | 'DoubleRedirectsPage' => 'includes/specials/SpecialDoubleRedirects.php', |
514 | 514 | 'EmailConfirmation' => 'includes/specials/SpecialConfirmemail.php', |
515 | 515 | 'EmailInvalidation' => 'includes/specials/SpecialConfirmemail.php', |
516 | | - 'EmailUserForm' => 'includes/specials/SpecialEmailuser.php', |
| 516 | + 'SpecialEmailUser' => 'includes/specials/SpecialEmailuser.php', |
517 | 517 | 'FakeResultWrapper' => 'includes/specials/SpecialAllmessages.php', |
518 | 518 | 'FewestrevisionsPage' => 'includes/specials/SpecialFewestrevisions.php', |
519 | 519 | 'FileDuplicateSearchPage' => 'includes/specials/SpecialFileDuplicateSearch.php', |
Index: trunk/phase3/includes/specials/SpecialEmailuser.php |
— | — | @@ -4,335 +4,177 @@ |
5 | 5 | * @ingroup SpecialPage |
6 | 6 | */ |
7 | 7 | |
8 | | -/** |
9 | | - * Constructor for Special:Emailuser. |
10 | | - */ |
11 | | -function wfSpecialEmailuser( $par ) { |
12 | | - global $wgRequest, $wgUser, $wgOut; |
13 | | - |
14 | | - if ( !EmailUserForm::userEmailEnabled() ) { |
15 | | - $wgOut->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' ); |
16 | | - return; |
| 8 | +class SpecialEmailUser extends UnlistedSpecialPage { |
| 9 | + protected $mTarget; |
| 10 | + |
| 11 | + public function __construct(){ |
| 12 | + parent::__construct( 'Emailuser' ); |
17 | 13 | } |
18 | | - |
19 | | - $action = $wgRequest->getVal( 'action' ); |
20 | | - $target = isset($par) ? $par : $wgRequest->getVal( 'target' ); |
21 | | - $targetUser = EmailUserForm::validateEmailTarget( $target ); |
22 | | - |
23 | | - if ( !( $targetUser instanceof User ) ) { |
24 | | - $wgOut->showErrorPage( $targetUser.'title', $targetUser.'text' ); |
25 | | - return; |
| 14 | + |
| 15 | + protected function getFormFields(){ |
| 16 | + global $wgUser; |
| 17 | + return array( |
| 18 | + 'From' => array( |
| 19 | + 'type' => 'info', |
| 20 | + 'raw' => 1, |
| 21 | + 'default' => $wgUser->getSkin()->link( |
| 22 | + $wgUser->getUserPage(), |
| 23 | + htmlspecialchars( $wgUser->getName() ) |
| 24 | + ), |
| 25 | + 'label-message' => 'emailfrom', |
| 26 | + 'id' => 'mw-emailuser-sender', |
| 27 | + ), |
| 28 | + 'To' => array( |
| 29 | + 'type' => 'info', |
| 30 | + 'raw' => 1, |
| 31 | + 'default' => $wgUser->getSkin()->link( |
| 32 | + $this->mTargetObj->getUserPage(), |
| 33 | + htmlspecialchars( $this->mTargetObj->getName() ) |
| 34 | + ), |
| 35 | + 'label-message' => 'emailto', |
| 36 | + 'id' => 'mw-emailuser-recipient', |
| 37 | + ), |
| 38 | + 'Target' => array( |
| 39 | + 'type' => 'hidden', |
| 40 | + 'default' => $this->mTargetObj->getName(), |
| 41 | + ), |
| 42 | + 'Subject' => array( |
| 43 | + 'type' => 'text', |
| 44 | + 'default' => wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ) ), |
| 45 | + 'label-message' => 'emailsubject', |
| 46 | + 'maxlength' => 200, |
| 47 | + 'size' => 60, |
| 48 | + 'required' => 1, |
| 49 | + ), |
| 50 | + 'Text' => array( |
| 51 | + 'type' => 'textarea', |
| 52 | + 'rows' => 20, |
| 53 | + 'cols' => 80, |
| 54 | + 'label-message' => 'emailmessage', |
| 55 | + 'required' => 1, |
| 56 | + ), |
| 57 | + 'CCMe' => array( |
| 58 | + 'type' => 'check', |
| 59 | + 'label-message' => 'emailccme', |
| 60 | + 'default' => $wgUser->getBoolOption( 'ccmeonemails' ), |
| 61 | + ), |
| 62 | + ); |
26 | 63 | } |
27 | | - |
28 | | - $form = new EmailUserForm( $targetUser, |
29 | | - $wgRequest->getText( 'wpText' ), |
30 | | - $wgRequest->getText( 'wpSubject' ), |
31 | | - $wgRequest->getBool( 'wpCCMe' ) ); |
32 | | - if ( $action == 'success' ) { |
33 | | - $form->showSuccess(); |
34 | | - return; |
35 | | - } |
36 | | - |
37 | | - $error = EmailUserForm::getPermissionsError( $wgUser, $wgRequest->getVal( 'wpEditToken' ) ); |
38 | | - if ( $error ) { |
| 64 | + |
| 65 | + public function execute( $par=null ) { |
| 66 | + global $wgRequest, $wgOut, $wgUser; |
| 67 | + $this->mTarget = is_null( $par ) |
| 68 | + ? $wgRequest->getVal( 'wpTarget', '' ) |
| 69 | + : $par; |
| 70 | + |
| 71 | + $ret = self::getTarget( $this->mTarget ); |
| 72 | + if( $ret instanceof User ){ |
| 73 | + $this->mTargetObj = $ret; |
| 74 | + } else { |
| 75 | + $wgOut->showErrorPage( "{$ret}title", "{$ret}text" ); |
| 76 | + return false; |
| 77 | + } |
| 78 | + |
| 79 | + $error = self::getPermissionsError( $wgUser, $wgRequest->getVal( 'wpEditToken' ) ); |
39 | 80 | switch ( $error ) { |
| 81 | + case null: |
| 82 | + # Wahey! |
| 83 | + break; |
| 84 | + case 'badaccess': |
| 85 | + $wgOut->permissionRequired( 'sendemail' ); |
| 86 | + return; |
40 | 87 | case 'blockedemailuser': |
41 | 88 | $wgOut->blockedPage(); |
42 | 89 | return; |
43 | 90 | case 'actionthrottledtext': |
44 | 91 | $wgOut->rateLimited(); |
45 | 92 | return; |
46 | | - case 'sessionfailure': |
47 | | - $form->showForm(); |
48 | | - return; |
49 | 93 | case 'mailnologin': |
50 | | - $wgOut->showErrorPage( 'mailnologin', 'mailnologintext' ); |
| 94 | + case 'usermaildisabled': |
| 95 | + $wgOut->showErrorPage( $error, "{$error}text" ); |
51 | 96 | return; |
52 | 97 | default: |
53 | | - // It's a hook error |
| 98 | + # It's a hook error |
54 | 99 | list( $title, $msg, $params ) = $error; |
55 | 100 | $wgOut->showErrorPage( $title, $msg, $params ); |
56 | 101 | return; |
57 | | - |
58 | 102 | } |
59 | | - } |
60 | | - |
61 | | - if ( "submit" == $action && $wgRequest->wasPosted() ) { |
62 | | - $result = $form->doSubmit(); |
63 | | - |
64 | | - if ( !is_null( $result ) ) { |
65 | | - $wgOut->addHTML( wfMsg( "usermailererror" ) . |
66 | | - ' ' . htmlspecialchars( $result->getMessage() ) ); |
67 | | - } else { |
68 | | - $titleObj = SpecialPage::getTitleFor( "Emailuser" ); |
69 | | - $encTarget = wfUrlencode( $form->getTarget()->getName() ); |
70 | | - $wgOut->redirect( $titleObj->getFullURL( "target={$encTarget}&action=success" ) ); |
| 103 | + |
| 104 | + $form = new HTMLForm( $this->getFormFields() ); |
| 105 | + $form->addPreText( wfMsgExt( 'emailpagetext', 'parseinline' ) ); |
| 106 | + $form->setSubmitText( wfMsg( 'emailsend' ) ); |
| 107 | + $form->setTitle( $this->getTitle() ); |
| 108 | + $form->setSubmitCallback( array( __CLASS__, 'submit' ) ); |
| 109 | + $form->setWrapperLegend( wfMsgExt( 'email-legend', 'parsemag' ) ); |
| 110 | + $form->loadData(); |
| 111 | + |
| 112 | + if( !wfRunHooks( 'EmailUserForm', array( &$form ) ) ){ |
| 113 | + return false; |
71 | 114 | } |
72 | | - } else { |
73 | | - $form->showForm(); |
74 | | - } |
75 | | -} |
76 | | - |
77 | | -/** |
78 | | - * Implements the Special:Emailuser web interface, and invokes |
79 | | - * UserMailer::send() for sending the email message. |
80 | | - * |
81 | | - * @ingroup SpecialPage |
82 | | - */ |
83 | | -class EmailUserForm { |
84 | | - |
85 | | - var $target; |
86 | | - var $text, $subject; |
87 | | - var $cc_me; // Whether user requested to be sent a separate copy of their email. |
88 | | - |
89 | | - /** |
90 | | - * Constructor |
91 | | - * |
92 | | - * @param $target User object |
93 | | - * @param $text String: message contents |
94 | | - * @param $subject String: message subject |
95 | | - * @param $cc_me Boolean: wheter to send a copy of the message to the sender user |
96 | | - */ |
97 | | - public function EmailUserForm( $target, $text, $subject, $cc_me ) { |
98 | | - $this->target = $target; |
99 | | - $this->text = $text; |
100 | | - $this->subject = $subject; |
101 | | - $this->cc_me = $cc_me; |
102 | | - } |
103 | | - |
104 | | - /** |
105 | | - * Display the form to send a email |
106 | | - */ |
107 | | - public function showForm() { |
108 | | - global $wgOut, $wgUser; |
109 | | - $skin = $wgUser->getSkin(); |
110 | | - |
111 | | - $wgOut->setPagetitle( wfMsg( "emailpage" ) ); |
112 | | - $wgOut->addWikiMsg( "emailpagetext" ); |
113 | | - |
114 | | - if ( $this->subject === "" ) { |
115 | | - $this->subject = wfMsgExt( 'defemailsubject', array( 'content', 'parsemag' ) ); |
| 115 | + |
| 116 | + $wgOut->setPagetitle( wfMsg( 'emailpage' ) ); |
| 117 | + $result = $form->show(); |
| 118 | + |
| 119 | + if( $result === true ){ |
| 120 | + $wgOut->setPagetitle( wfMsg( 'emailsent' ) ); |
| 121 | + $wgOut->addWikiMsg( 'emailsenttext' ); |
| 122 | + $wgOut->returnToMain( false, $this->mTargetObj->getUserPage() ); |
116 | 123 | } |
117 | | - |
118 | | - $titleObj = SpecialPage::getTitleFor( "Emailuser" ); |
119 | | - $action = $titleObj->getLocalURL( "target=" . |
120 | | - urlencode( $this->target->getName() ) . "&action=submit" ); |
121 | | - |
122 | | - $wgOut->addHTML( |
123 | | - Xml::openElement( 'form', array( 'method' => 'post', 'action' => $action, 'id' => 'emailuser' ) ) . |
124 | | - Xml::openElement( 'fieldset' ) . |
125 | | - Xml::element( 'legend', null, wfMsgExt( 'email-legend', 'parsemag' ) ) . |
126 | | - Xml::openElement( 'table', array( 'class' => 'mw-emailuser-table' ) ) . |
127 | | - "<tr> |
128 | | - <td class='mw-label'>" . |
129 | | - Xml::label( wfMsg( 'emailfrom' ), 'emailfrom' ) . |
130 | | - "</td> |
131 | | - <td class='mw-input' id='mw-emailuser-sender'>" . |
132 | | - $skin->link( $wgUser->getUserPage(), htmlspecialchars( $wgUser->getName() ) ) . |
133 | | - "</td> |
134 | | - </tr> |
135 | | - <tr> |
136 | | - <td class='mw-label'>" . |
137 | | - Xml::label( wfMsg( 'emailto' ), 'emailto' ) . |
138 | | - "</td> |
139 | | - <td class='mw-input' id='mw-emailuser-recipient'>" . |
140 | | - $skin->link( $this->target->getUserPage(), htmlspecialchars( $this->target->getName() ) ) . |
141 | | - "</td> |
142 | | - </tr> |
143 | | - <tr> |
144 | | - <td class='mw-label'>" . |
145 | | - Xml::label( wfMsg( 'emailsubject' ), 'wpSubject' ) . |
146 | | - "</td> |
147 | | - <td class='mw-input'>" . |
148 | | - Xml::input( 'wpSubject', 60, $this->subject, array( 'type' => 'text', 'maxlength' => 200 ) ) . |
149 | | - "</td> |
150 | | - </tr> |
151 | | - <tr> |
152 | | - <td class='mw-label'>" . |
153 | | - Xml::label( wfMsg( 'emailmessage' ), 'wpText' ) . |
154 | | - "</td> |
155 | | - <td class='mw-input'>" . |
156 | | - Xml::textarea( 'wpText', $this->text, 80, 20, array( 'id' => 'wpText' ) ) . |
157 | | - "</td> |
158 | | - </tr> |
159 | | - <tr> |
160 | | - <td></td> |
161 | | - <td class='mw-input'>" . |
162 | | - Xml::checkLabel( wfMsg( 'emailccme' ), 'wpCCMe', 'wpCCMe', $wgUser->getBoolOption( 'ccmeonemails' ) ) . |
163 | | - "</td> |
164 | | - </tr> |
165 | | - <tr> |
166 | | - <td></td> |
167 | | - <td class='mw-submit'>" . |
168 | | - Xml::submitButton( wfMsg( 'emailsend' ), array( 'name' => 'wpSend', 'accesskey' => 's' ) ) . |
169 | | - "</td> |
170 | | - </tr>" . |
171 | | - Xml::hidden( 'wpEditToken', $wgUser->editToken() ) . |
172 | | - Xml::closeElement( 'table' ) . |
173 | | - Xml::closeElement( 'fieldset' ) . |
174 | | - Xml::closeElement( 'form' ) |
175 | | - ); |
176 | 124 | } |
177 | 125 | |
178 | 126 | /** |
179 | | - * Really send a mail. Permissions should have been checked using |
180 | | - * EmailUserForm::getPermissionsError. It is probably also a good idea to |
181 | | - * check the edit token and ping limiter in advance. |
182 | | - * |
183 | | - * @return Mixed: WikiError on error or null |
184 | | - */ |
185 | | - public function doSubmit() { |
186 | | - global $wgUser, $wgUserEmailUseReplyTo, $wgSiteName; |
187 | | - |
188 | | - $to = new MailAddress( $this->target ); |
189 | | - $from = new MailAddress( $wgUser ); |
190 | | - $subject = $this->subject; |
191 | | - |
192 | | - // Add a standard footer and trim up trailing newlines |
193 | | - $this->text = rtrim($this->text) . "\n\n-- \n" . wfMsgExt( 'emailuserfooter', |
194 | | - array( 'content', 'parsemag' ), array( $from->name, $to->name ) ); |
195 | | - |
196 | | - if( wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$this->text ) ) ) { |
197 | | - |
198 | | - if( $wgUserEmailUseReplyTo ) { |
199 | | - // Put the generic wiki autogenerated address in the From: |
200 | | - // header and reserve the user for Reply-To. |
201 | | - // |
202 | | - // This is a bit ugly, but will serve to differentiate |
203 | | - // wiki-borne mails from direct mails and protects against |
204 | | - // SPF and bounce problems with some mailers (see below). |
205 | | - global $wgPasswordSender; |
206 | | - $mailFrom = new MailAddress( $wgPasswordSender ); |
207 | | - $replyTo = $from; |
208 | | - } else { |
209 | | - // Put the sending user's e-mail address in the From: header. |
210 | | - // |
211 | | - // This is clean-looking and convenient, but has issues. |
212 | | - // One is that it doesn't as clearly differentiate the wiki mail |
213 | | - // from "directly" sent mails. |
214 | | - // |
215 | | - // Another is that some mailers (like sSMTP) will use the From |
216 | | - // address as the envelope sender as well. For open sites this |
217 | | - // can cause mails to be flunked for SPF violations (since the |
218 | | - // wiki server isn't an authorized sender for various users' |
219 | | - // domains) as well as creating a privacy issue as bounces |
220 | | - // containing the recipient's e-mail address may get sent to |
221 | | - // the sending user. |
222 | | - $mailFrom = $from; |
223 | | - $replyTo = null; |
224 | | - } |
225 | | - |
226 | | - $mailResult = UserMailer::send( $to, $mailFrom, $subject, $this->text, $replyTo ); |
227 | | - |
228 | | - if( WikiError::isError( $mailResult ) ) { |
229 | | - return $mailResult; |
230 | | - } else { |
231 | | - // if the user requested a copy of this mail, do this now, |
232 | | - // unless they are emailing themselves, in which case one copy of the message is sufficient. |
233 | | - if ($this->cc_me && $to != $from) { |
234 | | - $cc_subject = wfMsg('emailccsubject', $this->target->getName(), $subject); |
235 | | - if( wfRunHooks( 'EmailUser', array( &$from, &$from, &$cc_subject, &$this->text ) ) ) { |
236 | | - $ccResult = UserMailer::send( $from, $from, $cc_subject, $this->text ); |
237 | | - if( WikiError::isError( $ccResult ) ) { |
238 | | - // At this stage, the user's CC mail has failed, but their |
239 | | - // original mail has succeeded. It's unlikely, but still, what to do? |
240 | | - // We can either show them an error, or we can say everything was fine, |
241 | | - // or we can say we sort of failed AND sort of succeeded. Of these options, |
242 | | - // simply saying there was an error is probably best. |
243 | | - return $ccResult; |
244 | | - } |
245 | | - } |
246 | | - } |
247 | | - |
248 | | - wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $this->text ) ); |
249 | | - return; |
250 | | - } |
251 | | - } |
252 | | - } |
253 | | - |
254 | | - /** |
255 | | - * Show "Your e-mail message has been sent." message |
256 | | - */ |
257 | | - public function showSuccess( &$user = null ) { |
258 | | - global $wgOut; |
259 | | - |
260 | | - if ( is_null($user) ) |
261 | | - $user = $this->target; |
262 | | - |
263 | | - $wgOut->setPagetitle( wfMsg( "emailsent" ) ); |
264 | | - $wgOut->addWikiMsg( 'emailsenttext' ); |
265 | | - |
266 | | - $wgOut->returnToMain( false, $user->getUserPage() ); |
267 | | - } |
268 | | - |
269 | | - /** |
270 | | - * Get target user |
271 | | - * |
272 | | - * @return User object |
273 | | - */ |
274 | | - public function getTarget() { |
275 | | - return $this->target; |
276 | | - } |
277 | | - |
278 | | - /** |
279 | | - * Check whether user-to-user emails are enabled |
280 | | - * |
281 | | - * @return Boolean |
282 | | - */ |
283 | | - public static function userEmailEnabled() { |
284 | | - global $wgEnableEmail, $wgEnableUserEmail; |
285 | | - return $wgEnableEmail && $wgEnableUserEmail; |
286 | | - } |
287 | | - |
288 | | - /** |
289 | 127 | * Validate target User |
290 | 128 | * |
291 | 129 | * @param $target String: target user name |
292 | 130 | * @return User object on success or a string on error |
293 | 131 | */ |
294 | | - public static function validateEmailTarget( $target ) { |
295 | | - if ( $target == "" ) { |
| 132 | + public static function getTarget( $target ) { |
| 133 | + if ( $target == '' ) { |
296 | 134 | wfDebug( "Target is empty.\n" ); |
297 | | - return "notarget"; |
| 135 | + return 'notarget'; |
298 | 136 | } |
299 | 137 | |
300 | 138 | $nt = Title::newFromURL( $target ); |
301 | | - if ( is_null( $nt ) ) { |
| 139 | + if ( !$nt instanceof Title ) { |
302 | 140 | wfDebug( "Target is invalid title.\n" ); |
303 | | - return "notarget"; |
| 141 | + return 'notarget'; |
304 | 142 | } |
305 | 143 | |
306 | 144 | $nu = User::newFromName( $nt->getText() ); |
307 | 145 | if( !$nu instanceof User || !$nu->getId() ) { |
308 | 146 | wfDebug( "Target is invalid user.\n" ); |
309 | | - return "notarget"; |
| 147 | + return 'notarget'; |
310 | 148 | } else if ( !$nu->isEmailConfirmed() ) { |
311 | 149 | wfDebug( "User has no valid email.\n" ); |
312 | | - return "noemail"; |
| 150 | + return 'noemail'; |
313 | 151 | } else if ( !$nu->canReceiveEmail() ) { |
314 | 152 | wfDebug( "User does not allow user emails.\n" ); |
315 | | - return "nowikiemail"; |
| 153 | + return 'nowikiemail'; |
316 | 154 | } |
317 | 155 | |
318 | 156 | return $nu; |
319 | 157 | } |
320 | 158 | |
321 | 159 | /** |
322 | | - * Check whether user is allowed to send email |
| 160 | + * Check whether a user is allowed to send email |
323 | 161 | * |
324 | 162 | * @param $user User object |
325 | 163 | * @param $editToken String: edit token |
326 | 164 | * @return null on success or string on error |
327 | 165 | */ |
328 | 166 | public static function getPermissionsError( $user, $editToken ) { |
329 | | - if( !$user->canSendEmail() ) { |
330 | | - wfDebug( "User can't send.\n" ); |
331 | | - // FIXME: this is also the error if user is in a group |
332 | | - // that is not allowed to send e-mail (no right |
333 | | - // 'sendemail'). Error messages should probably |
334 | | - // be more fine grained. |
335 | | - return "mailnologin"; |
| 167 | + global $wgEnableEmail, $wgEnableUserEmail; |
| 168 | + if( !$wgEnableEmail || !$wgEnableUserEmail ){ |
| 169 | + return 'usermaildisabled'; |
336 | 170 | } |
| 171 | + |
| 172 | + if( !$user->isAllowed( 'sendemail' ) ) { |
| 173 | + return 'badaccess'; |
| 174 | + } |
| 175 | + |
| 176 | + if( !$user->isEmailConfirmed() ){ |
| 177 | + return 'mailnologin'; |
| 178 | + } |
337 | 179 | |
338 | 180 | if( $user->isBlockedFromEmailuser() ) { |
339 | 181 | wfDebug( "User is blocked from sending e-mail.\n" ); |
— | — | @@ -344,31 +186,105 @@ |
345 | 187 | return 'actionthrottledtext'; |
346 | 188 | } |
347 | 189 | |
348 | | - $hookErr = null; |
| 190 | + $hookErr = false; |
| 191 | + wfRunHooks( 'UserCanSendEmail', array( &$user, &$hookErr ) ); |
349 | 192 | wfRunHooks( 'EmailUserPermissionsErrors', array( $user, $editToken, &$hookErr ) ); |
350 | | - |
351 | | - if ($hookErr) { |
| 193 | + if ( $hookErr ) { |
352 | 194 | return $hookErr; |
353 | 195 | } |
354 | | - |
355 | | - if( !$user->matchEditToken( $editToken ) ) { |
356 | | - wfDebug( "Matching edit token failed.\n" ); |
357 | | - return 'sessionfailure'; |
358 | | - } |
| 196 | + |
| 197 | + return null; |
359 | 198 | } |
360 | 199 | |
361 | 200 | /** |
362 | | - * Get a EmailUserForm object |
| 201 | + * Really send a mail. Permissions should have been checked using |
| 202 | + * getPermissionsError(). It is probably also a good |
| 203 | + * idea to check the edit token and ping limiter in advance. |
363 | 204 | * |
364 | | - * @param $target String: user name |
365 | | - * @param $text String: message contents |
366 | | - * @param $subject String: message subject |
367 | | - * @param $cc_me Boolean: wheter to send a copy of the message to the sender user |
368 | | - * @return EmailUserForm object |
| 205 | + * @return Mixed: True on success, String on error |
369 | 206 | */ |
370 | | - public static function newFromURL( $target, $text, $subject, $cc_me ) { |
371 | | - $nt = Title::newFromURL( $target ); |
372 | | - $nu = User::newFromName( $nt->getText() ); |
373 | | - return new EmailUserForm( $nu, $text, $subject, $cc_me ); |
| 207 | + public static function submit( $data ) { |
| 208 | + global $wgUser, $wgUserEmailUseReplyTo, $wgSiteName; |
| 209 | + |
| 210 | + $target = self::getTarget( $data['Target'] ); |
| 211 | + if( !$target instanceof User ){ |
| 212 | + return wfMsgExt( $to, 'parse' ); |
| 213 | + } |
| 214 | + $to = new MailAddress( $target ); |
| 215 | + $from = new MailAddress( $wgUser ); |
| 216 | + $subject = $data['Subject']; |
| 217 | + $text = $data['Text']; |
| 218 | + |
| 219 | + // Add a standard footer and trim up trailing newlines |
| 220 | + $text = rtrim( $text ) . "\n\n-- \n"; |
| 221 | + $text .= wfMsgExt( |
| 222 | + 'emailuserfooter', |
| 223 | + array( 'content', 'parsemag' ), |
| 224 | + array( $from->name, $to->name ) |
| 225 | + ); |
| 226 | + |
| 227 | + $error = ''; |
| 228 | + if( !wfRunHooks( 'EmailUser', array( &$to, &$from, &$subject, &$text, &$error ) ) ) { |
| 229 | + return $error; |
| 230 | + } |
| 231 | + |
| 232 | + if( $wgUserEmailUseReplyTo ) { |
| 233 | + // Put the generic wiki autogenerated address in the From: |
| 234 | + // header and reserve the user for Reply-To. |
| 235 | + // |
| 236 | + // This is a bit ugly, but will serve to differentiate |
| 237 | + // wiki-borne mails from direct mails and protects against |
| 238 | + // SPF and bounce problems with some mailers (see below). |
| 239 | + global $wgPasswordSender; |
| 240 | + $mailFrom = new MailAddress( $wgPasswordSender ); |
| 241 | + $replyTo = $from; |
| 242 | + } else { |
| 243 | + // Put the sending user's e-mail address in the From: header. |
| 244 | + // |
| 245 | + // This is clean-looking and convenient, but has issues. |
| 246 | + // One is that it doesn't as clearly differentiate the wiki mail |
| 247 | + // from "directly" sent mails. |
| 248 | + // |
| 249 | + // Another is that some mailers (like sSMTP) will use the From |
| 250 | + // address as the envelope sender as well. For open sites this |
| 251 | + // can cause mails to be flunked for SPF violations (since the |
| 252 | + // wiki server isn't an authorized sender for various users' |
| 253 | + // domains) as well as creating a privacy issue as bounces |
| 254 | + // containing the recipient's e-mail address may get sent to |
| 255 | + // the sending user. |
| 256 | + $mailFrom = $from; |
| 257 | + $replyTo = null; |
| 258 | + } |
| 259 | + |
| 260 | + $mailResult = UserMailer::send( $to, $mailFrom, $subject, $text, $replyTo ); |
| 261 | + |
| 262 | + if( WikiError::isError( $mailResult ) && false ) { |
| 263 | + return $mailResult->getMessage(); |
| 264 | + } else { |
| 265 | + // if the user requested a copy of this mail, do this now, |
| 266 | + // unless they are emailing themselves, in which case one |
| 267 | + // copy of the message is sufficient. |
| 268 | + if ( $data['CCMe'] && $to != $from ) { |
| 269 | + $cc_subject = wfMsg( |
| 270 | + 'emailccsubject', |
| 271 | + $target->getName(), |
| 272 | + $subject |
| 273 | + ); |
| 274 | + wfRunHooks( 'EmailUserCC', array( &$from, &$from, &$cc_subject, &$text ) ); |
| 275 | + $ccResult = UserMailer::send( $from, $from, $cc_subject, $text ); |
| 276 | + if( WikiError::isError( $ccResult ) ) { |
| 277 | + // At this stage, the user's CC mail has failed, but their |
| 278 | + // original mail has succeeded. It's unlikely, but still, |
| 279 | + // what to do? We can either show them an error, or we can |
| 280 | + // say everything was fine, or we can say we sort of failed |
| 281 | + // AND sort of succeeded. Of these options, simply saying |
| 282 | + // there was an error is probably best. |
| 283 | + return $ccResult->getMessage(); |
| 284 | + } |
| 285 | + } |
| 286 | + |
| 287 | + wfRunHooks( 'EmailUserComplete', array( $to, $from, $subject, $text ) ); |
| 288 | + return true; |
| 289 | + } |
374 | 290 | } |
375 | 291 | } |
Index: trunk/phase3/includes/SpecialPage.php |
— | — | @@ -181,7 +181,7 @@ |
182 | 182 | # Unlisted / redirects |
183 | 183 | 'Blankpage' => 'SpecialBlankpage', |
184 | 184 | 'Blockme' => array( 'UnlistedSpecialPage', 'Blockme' ), |
185 | | - 'Emailuser' => array( 'UnlistedSpecialPage', 'Emailuser' ), |
| 185 | + 'Emailuser' => 'SpecialEmailUser', |
186 | 186 | 'Listadmins' => array( 'SpecialRedirectToSpecial', 'Listadmins', 'Listusers', 'sysop' ), |
187 | 187 | 'Listbots' => array( 'SpecialRedirectToSpecial', 'Listbots', 'Listusers', 'bot' ), |
188 | 188 | 'Movepage' => array( 'UnlistedSpecialPage', 'Movepage' ), |