Remove product literal strings in "pht()", part 6
[phabricator.git] / src / applications / metamta / storage / __tests__ / PhabricatorMetaMTAMailTestCase.php
blobe66dd8c61bd95f4a54cb5c3514ab922135d4411d
1 <?php
3 final class PhabricatorMetaMTAMailTestCase extends PhabricatorTestCase {
5 protected function getPhabricatorTestCaseConfiguration() {
6 return array(
7 self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true,
8 );
11 public function testMailSendFailures() {
12 $user = $this->generateNewTestUser();
13 $phid = $user->getPHID();
16 // Normally, the send should succeed.
17 $mail = new PhabricatorMetaMTAMail();
18 $mail->addTos(array($phid));
20 $mailer = new PhabricatorMailTestAdapter();
21 $mail->sendWithMailers(array($mailer));
22 $this->assertEqual(
23 PhabricatorMailOutboundStatus::STATUS_SENT,
24 $mail->getStatus());
27 // When the mailer fails temporarily, the mail should remain queued.
28 $mail = new PhabricatorMetaMTAMail();
29 $mail->addTos(array($phid));
31 $mailer = new PhabricatorMailTestAdapter();
32 $mailer->setFailTemporarily(true);
33 try {
34 $mail->sendWithMailers(array($mailer));
35 } catch (Exception $ex) {
36 // Ignore.
38 $this->assertEqual(
39 PhabricatorMailOutboundStatus::STATUS_QUEUE,
40 $mail->getStatus());
43 // When the mailer fails permanently, the mail should be failed.
44 $mail = new PhabricatorMetaMTAMail();
45 $mail->addTos(array($phid));
47 $mailer = new PhabricatorMailTestAdapter();
48 $mailer->setFailPermanently(true);
49 try {
50 $mail->sendWithMailers(array($mailer));
51 } catch (Exception $ex) {
52 // Ignore.
54 $this->assertEqual(
55 PhabricatorMailOutboundStatus::STATUS_FAIL,
56 $mail->getStatus());
59 public function testRecipients() {
60 $user = $this->generateNewTestUser();
61 $phid = $user->getPHID();
63 $mailer = new PhabricatorMailTestAdapter();
65 $mail = new PhabricatorMetaMTAMail();
66 $mail->addTos(array($phid));
68 $this->assertTrue(
69 in_array($phid, $mail->buildRecipientList()),
70 pht('"To" is a recipient.'));
73 // Test that the "No Self Mail" and "No Mail" preferences work correctly.
74 $mail->setFrom($phid);
76 $this->assertTrue(
77 in_array($phid, $mail->buildRecipientList()),
78 pht('"From" does not exclude recipients by default.'));
80 $user = $this->writeSetting(
81 $user,
82 PhabricatorEmailSelfActionsSetting::SETTINGKEY,
83 true);
85 $this->assertFalse(
86 in_array($phid, $mail->buildRecipientList()),
87 pht('"From" excludes recipients with no-self-mail set.'));
89 $user = $this->writeSetting(
90 $user,
91 PhabricatorEmailSelfActionsSetting::SETTINGKEY,
92 null);
94 $this->assertTrue(
95 in_array($phid, $mail->buildRecipientList()),
96 pht('"From" does not exclude recipients by default.'));
98 $user = $this->writeSetting(
99 $user,
100 PhabricatorEmailNotificationsSetting::SETTINGKEY,
101 true);
103 $this->assertFalse(
104 in_array($phid, $mail->buildRecipientList()),
105 pht('"From" excludes recipients with no-mail set.'));
107 $mail->setForceDelivery(true);
109 $this->assertTrue(
110 in_array($phid, $mail->buildRecipientList()),
111 pht('"From" includes no-mail recipients when forced.'));
113 $mail->setForceDelivery(false);
115 $user = $this->writeSetting(
116 $user,
117 PhabricatorEmailNotificationsSetting::SETTINGKEY,
118 null);
120 $this->assertTrue(
121 in_array($phid, $mail->buildRecipientList()),
122 pht('"From" does not exclude recipients by default.'));
124 // Test that explicit exclusion works correctly.
125 $mail->setExcludeMailRecipientPHIDs(array($phid));
127 $this->assertFalse(
128 in_array($phid, $mail->buildRecipientList()),
129 pht('Explicit exclude excludes recipients.'));
131 $mail->setExcludeMailRecipientPHIDs(array());
134 // Test that mail tag preferences exclude recipients.
135 $user = $this->writeSetting(
136 $user,
137 PhabricatorEmailTagsSetting::SETTINGKEY,
138 array(
139 'test-tag' => false,
142 $mail->setMailTags(array('test-tag'));
144 $this->assertFalse(
145 in_array($phid, $mail->buildRecipientList()),
146 pht('Tag preference excludes recipients.'));
148 $user = $this->writeSetting(
149 $user,
150 PhabricatorEmailTagsSetting::SETTINGKEY,
151 null);
153 $this->assertTrue(
154 in_array($phid, $mail->buildRecipientList()),
155 'Recipients restored after tag preference removed.');
157 $email = id(new PhabricatorUserEmail())->loadOneWhere(
158 'userPHID = %s AND isPrimary = 1',
159 $phid);
161 $email->setIsVerified(0)->save();
163 $this->assertFalse(
164 in_array($phid, $mail->buildRecipientList()),
165 pht('Mail not sent to unverified address.'));
167 $email->setIsVerified(1)->save();
169 $this->assertTrue(
170 in_array($phid, $mail->buildRecipientList()),
171 pht('Mail sent to verified address.'));
174 public function testThreadIDHeaders() {
175 $this->runThreadIDHeadersWithConfiguration(true, true);
176 $this->runThreadIDHeadersWithConfiguration(true, false);
177 $this->runThreadIDHeadersWithConfiguration(false, true);
178 $this->runThreadIDHeadersWithConfiguration(false, false);
181 private function runThreadIDHeadersWithConfiguration(
182 $supports_message_id,
183 $is_first_mail) {
185 $user = $this->generateNewTestUser();
186 $phid = $user->getPHID();
188 $mailer = new PhabricatorMailTestAdapter();
190 $mailer->setSupportsMessageID($supports_message_id);
192 $thread_id = 'somethread-12345';
194 $mail = id(new PhabricatorMetaMTAMail())
195 ->setThreadID($thread_id, $is_first_mail)
196 ->addTos(array($phid))
197 ->sendWithMailers(array($mailer));
199 $guts = $mailer->getGuts();
201 $headers = idx($guts, 'headers', array());
203 $dict = array();
204 foreach ($headers as $header) {
205 list($name, $value) = $header;
206 $dict[$name] = $value;
209 if ($is_first_mail && $supports_message_id) {
210 $expect_message_id = true;
211 $expect_in_reply_to = false;
212 $expect_references = false;
213 } else {
214 $expect_message_id = false;
215 $expect_in_reply_to = true;
216 $expect_references = true;
219 $case = '<message-id = '.($supports_message_id ? 'Y' : 'N').', '.
220 'first = '.($is_first_mail ? 'Y' : 'N').'>';
222 $this->assertTrue(
223 isset($dict['Thread-Index']),
224 pht('Expect Thread-Index header for case %s.', $case));
225 $this->assertEqual(
226 $expect_message_id,
227 isset($dict['Message-ID']),
228 pht(
229 'Expectation about existence of Message-ID header for case %s.',
230 $case));
231 $this->assertEqual(
232 $expect_in_reply_to,
233 isset($dict['In-Reply-To']),
234 pht(
235 'Expectation about existence of In-Reply-To header for case %s.',
236 $case));
237 $this->assertEqual(
238 $expect_references,
239 isset($dict['References']),
240 pht(
241 'Expectation about existence of References header for case %s.',
242 $case));
245 private function writeSetting(PhabricatorUser $user, $key, $value) {
246 $preferences = PhabricatorUserPreferences::loadUserPreferences($user);
248 $editor = id(new PhabricatorUserPreferencesEditor())
249 ->setActor($user)
250 ->setContentSource($this->newContentSource())
251 ->setContinueOnNoEffect(true)
252 ->setContinueOnMissingFields(true);
254 $xactions = array();
255 $xactions[] = $preferences->newTransaction($key, $value);
256 $editor->applyTransactions($preferences, $xactions);
258 return id(new PhabricatorPeopleQuery())
259 ->setViewer($user)
260 ->withIDs(array($user->getID()))
261 ->executeOne();
264 public function testMailerFailover() {
265 $user = $this->generateNewTestUser();
266 $phid = $user->getPHID();
268 $status_sent = PhabricatorMailOutboundStatus::STATUS_SENT;
269 $status_queue = PhabricatorMailOutboundStatus::STATUS_QUEUE;
270 $status_fail = PhabricatorMailOutboundStatus::STATUS_FAIL;
272 $mailer1 = id(new PhabricatorMailTestAdapter())
273 ->setKey('mailer1');
275 $mailer2 = id(new PhabricatorMailTestAdapter())
276 ->setKey('mailer2');
278 $mailers = array(
279 $mailer1,
280 $mailer2,
283 // Send mail with both mailers active. The first mailer should be used.
284 $mail = id(new PhabricatorMetaMTAMail())
285 ->addTos(array($phid))
286 ->sendWithMailers($mailers);
287 $this->assertEqual($status_sent, $mail->getStatus());
288 $this->assertEqual('mailer1', $mail->getMailerKey());
291 // If the first mailer fails, the mail should be sent with the second
292 // mailer. Since we transmitted the mail, this doesn't raise an exception.
293 $mailer1->setFailTemporarily(true);
295 $mail = id(new PhabricatorMetaMTAMail())
296 ->addTos(array($phid))
297 ->sendWithMailers($mailers);
298 $this->assertEqual($status_sent, $mail->getStatus());
299 $this->assertEqual('mailer2', $mail->getMailerKey());
302 // If both mailers fail, the mail should remain in queue.
303 $mailer2->setFailTemporarily(true);
305 $mail = id(new PhabricatorMetaMTAMail())
306 ->addTos(array($phid));
308 $caught = null;
309 try {
310 $mail->sendWithMailers($mailers);
311 } catch (Exception $ex) {
312 $caught = $ex;
315 $this->assertTrue($caught instanceof Exception);
316 $this->assertEqual($status_queue, $mail->getStatus());
317 $this->assertEqual(null, $mail->getMailerKey());
319 $mailer1->setFailTemporarily(false);
320 $mailer2->setFailTemporarily(false);
323 // If the first mailer fails permanently, the mail should fail even though
324 // the second mailer isn't configured to fail.
325 $mailer1->setFailPermanently(true);
327 $mail = id(new PhabricatorMetaMTAMail())
328 ->addTos(array($phid));
330 $caught = null;
331 try {
332 $mail->sendWithMailers($mailers);
333 } catch (Exception $ex) {
334 $caught = $ex;
337 $this->assertTrue($caught instanceof Exception);
338 $this->assertEqual($status_fail, $mail->getStatus());
339 $this->assertEqual(null, $mail->getMailerKey());
342 public function testMailSizeLimits() {
343 $env = PhabricatorEnv::beginScopedEnv();
344 $env->overrideEnvConfig('metamta.email-body-limit', 1024 * 512);
346 $user = $this->generateNewTestUser();
347 $phid = $user->getPHID();
349 $string_1kb = str_repeat('x', 1024);
350 $html_1kb = str_repeat('y', 1024);
351 $string_1mb = str_repeat('x', 1024 * 1024);
352 $html_1mb = str_repeat('y', 1024 * 1024);
354 // First, send a mail with a small text body and a small HTML body to make
355 // sure the basics work properly.
356 $mail = id(new PhabricatorMetaMTAMail())
357 ->addTos(array($phid))
358 ->setBody($string_1kb)
359 ->setHTMLBody($html_1kb);
361 $mailer = new PhabricatorMailTestAdapter();
362 $mail->sendWithMailers(array($mailer));
363 $this->assertEqual(
364 PhabricatorMailOutboundStatus::STATUS_SENT,
365 $mail->getStatus());
367 $text_body = $mailer->getBody();
368 $html_body = $mailer->getHTMLBody();
370 $this->assertEqual($string_1kb, $text_body);
371 $this->assertEqual($html_1kb, $html_body);
374 // Now, send a mail with a large text body and a large HTML body. We expect
375 // the text body to be truncated and the HTML body to be dropped.
376 $mail = id(new PhabricatorMetaMTAMail())
377 ->addTos(array($phid))
378 ->setBody($string_1mb)
379 ->setHTMLBody($html_1mb);
381 $mailer = new PhabricatorMailTestAdapter();
382 $mail->sendWithMailers(array($mailer));
383 $this->assertEqual(
384 PhabricatorMailOutboundStatus::STATUS_SENT,
385 $mail->getStatus());
387 $text_body = $mailer->getBody();
388 $html_body = $mailer->getHTMLBody();
390 // We expect the body was truncated, because it exceeded the body limit.
391 $this->assertTrue(
392 (strlen($text_body) < strlen($string_1mb)),
393 pht('Text Body Truncated'));
395 // We expect the HTML body was dropped completely after the text body was
396 // truncated.
397 $this->assertTrue(
398 !phutil_nonempty_string($html_body),
399 pht('HTML Body Removed'));
402 // Next send a mail with a small text body and a large HTML body. We expect
403 // the text body to be intact and the HTML body to be dropped.
404 $mail = id(new PhabricatorMetaMTAMail())
405 ->addTos(array($phid))
406 ->setBody($string_1kb)
407 ->setHTMLBody($html_1mb);
409 $mailer = new PhabricatorMailTestAdapter();
410 $mail->sendWithMailers(array($mailer));
411 $this->assertEqual(
412 PhabricatorMailOutboundStatus::STATUS_SENT,
413 $mail->getStatus());
415 $text_body = $mailer->getBody();
416 $html_body = $mailer->getHTMLBody();
418 $this->assertEqual($string_1kb, $text_body);
419 $this->assertTrue(!phutil_nonempty_string($html_body));