@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Respect "metamta.email-body-limit" when building mail HTML bodies

Summary:
Ref T13151. See T11767. See PHI686. Although we limit outbound mail text bodies, the limit doesn't currently apply to attachments, HTML bodies, or headers. T11767 discusses improving this in the general case.

In the wild, an install hit an issue (see PHI686) where edits to Phriction pages generate very large HTML bodies. Check and respect the limit when building HTML bodies.

If we don't have enough room for the HTML body, we just drop it. We have the text body to fall back to, and HTML is difficult to truncate safely.

Test Plan: Added unit tests and made them pass.

Reviewers: amckinley

Reviewed By: amckinley

Maniphest Tasks: T13151

Differential Revision: https://secure.phabricator.com/D19489

+103 -6
+8
src/applications/metamta/adapter/PhabricatorMailImplementationTestAdapter.php
··· 123 123 return $this; 124 124 } 125 125 126 + public function getBody() { 127 + return idx($this->guts, 'body'); 128 + } 129 + 130 + public function getHTMLBody() { 131 + return idx($this->guts, 'html-body'); 132 + } 133 + 126 134 }
+15 -6
src/applications/metamta/storage/PhabricatorMetaMTAMail.php
··· 892 892 $body = $raw_body; 893 893 } 894 894 895 - $max = PhabricatorEnv::getEnvConfig('metamta.email-body-limit'); 896 - if (strlen($body) > $max) { 895 + $body_limit = PhabricatorEnv::getEnvConfig('metamta.email-body-limit'); 896 + if (strlen($body) > $body_limit) { 897 897 $body = id(new PhutilUTF8StringTruncator()) 898 - ->setMaximumBytes($max) 898 + ->setMaximumBytes($body_limit) 899 899 ->truncateString($body); 900 900 $body .= "\n"; 901 - $body .= pht('(This email was truncated at %d bytes.)', $max); 901 + $body .= pht('(This email was truncated at %d bytes.)', $body_limit); 902 902 } 903 903 $mailer->setBody($body); 904 + $body_limit -= strlen($body); 904 905 905 906 // If we sent a different message body than we were asked to, record 906 907 // what we actually sent to make debugging and diagnostics easier. ··· 914 915 $send_html = $this->shouldSendHTML($preferences); 915 916 } 916 917 917 - if ($send_html && isset($params['html-body'])) { 918 - $mailer->setHTMLBody($params['html-body']); 918 + if ($send_html) { 919 + $html_body = idx($params, 'html-body'); 920 + 921 + // NOTE: We just drop the entire HTML body if it won't fit. Safely 922 + // truncating HTML is hard, and we already have the text body to fall 923 + // back to. 924 + if (strlen($html_body) <= $body_limit) { 925 + $mailer->setHTMLBody($html_body); 926 + $body_limit -= strlen($html_body); 927 + } 919 928 } 920 929 921 930 // Pass the headers to the mailer, then save the state so we can show
+80
src/applications/metamta/storage/__tests__/PhabricatorMetaMTAMailTestCase.php
··· 331 331 $this->assertEqual(null, $mail->getMailerKey()); 332 332 } 333 333 334 + public function testMailSizeLimits() { 335 + $env = PhabricatorEnv::beginScopedEnv(); 336 + $env->overrideEnvConfig('metamta.email-body-limit', 1024 * 512); 337 + 338 + $user = $this->generateNewTestUser(); 339 + $phid = $user->getPHID(); 340 + 341 + $string_1kb = str_repeat('x', 1024); 342 + $html_1kb = str_repeat('y', 1024); 343 + $string_1mb = str_repeat('x', 1024 * 1024); 344 + $html_1mb = str_repeat('y', 1024 * 1024); 345 + 346 + // First, send a mail with a small text body and a small HTML body to make 347 + // sure the basics work properly. 348 + $mail = id(new PhabricatorMetaMTAMail()) 349 + ->addTos(array($phid)) 350 + ->setBody($string_1kb) 351 + ->setHTMLBody($html_1kb); 352 + 353 + $mailer = new PhabricatorMailImplementationTestAdapter(); 354 + $mail->sendWithMailers(array($mailer)); 355 + $this->assertEqual( 356 + PhabricatorMailOutboundStatus::STATUS_SENT, 357 + $mail->getStatus()); 358 + 359 + $text_body = $mailer->getBody(); 360 + $html_body = $mailer->getHTMLBody(); 361 + 362 + $this->assertEqual($string_1kb, $text_body); 363 + $this->assertEqual($html_1kb, $html_body); 364 + 365 + 366 + // Now, send a mail with a large text body and a large HTML body. We expect 367 + // the text body to be truncated and the HTML body to be dropped. 368 + $mail = id(new PhabricatorMetaMTAMail()) 369 + ->addTos(array($phid)) 370 + ->setBody($string_1mb) 371 + ->setHTMLBody($html_1mb); 372 + 373 + $mailer = new PhabricatorMailImplementationTestAdapter(); 374 + $mail->sendWithMailers(array($mailer)); 375 + $this->assertEqual( 376 + PhabricatorMailOutboundStatus::STATUS_SENT, 377 + $mail->getStatus()); 378 + 379 + $text_body = $mailer->getBody(); 380 + $html_body = $mailer->getHTMLBody(); 381 + 382 + // We expect the body was truncated, because it exceeded the body limit. 383 + $this->assertTrue( 384 + (strlen($text_body) < strlen($string_1mb)), 385 + pht('Text Body Truncated')); 386 + 387 + // We expect the HTML body was dropped completely after the text body was 388 + // truncated. 389 + $this->assertTrue( 390 + !strlen($html_body), 391 + pht('HTML Body Removed')); 392 + 393 + 394 + // Next send a mail with a small text body and a large HTML body. We expect 395 + // the text body to be intact and the HTML body to be dropped. 396 + $mail = id(new PhabricatorMetaMTAMail()) 397 + ->addTos(array($phid)) 398 + ->setBody($string_1kb) 399 + ->setHTMLBody($html_1mb); 400 + 401 + $mailer = new PhabricatorMailImplementationTestAdapter(); 402 + $mail->sendWithMailers(array($mailer)); 403 + $this->assertEqual( 404 + PhabricatorMailOutboundStatus::STATUS_SENT, 405 + $mail->getStatus()); 406 + 407 + $text_body = $mailer->getBody(); 408 + $html_body = $mailer->getHTMLBody(); 409 + 410 + $this->assertEqual($string_1kb, $text_body); 411 + $this->assertTrue(!strlen($html_body)); 412 + } 413 + 334 414 }