@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.

Add first unit test for mimemailparser headers

Summary:
Uploaded an example email with a lot of accents called 'test_accents.mbox' and
expected headers in the file 'test_accents.headers.txt'.

Better than nothing.

This change also includes a minor refactor in the library loading.

Ref T15960

Test Plan:
Manually run the new unit test and see green lights:

arc unit src/applications/metamta/externals/__tests__/PhabricatorExternalMimeMailParserTestCase.php

Double-check that the new class is already recorded:

arc liberate

Just as extra care, re-apply the same test plan of:

D25839

So, for example, run this, and see no exceptions:

./scripts/mail/mail_handler.php < src/applications/metamta/externals/__tests__/data/test_accents.mbox

Reviewers: aklapper, taavi, O1 Blessed Committers

Reviewed By: aklapper, O1 Blessed Committers

Subscribers: tobiaswiese, Matthew, Cigaryno

Maniphest Tasks: T15960

Differential Revision: https://we.phorge.it/D25844

+140 -9
+11
externals/mimemailparser/__init.php
··· 1 + <?php 2 + $root = __DIR__; 3 + require_once $root.'/Contracts/CharsetManager.php'; 4 + require_once $root.'/Contracts/Middleware.php'; 5 + require_once $root.'/Parser.php'; 6 + require_once $root.'/Charset.php'; 7 + require_once $root.'/Attachment.php'; 8 + require_once $root.'/Exception.php'; 9 + require_once $root.'/Middleware.php'; 10 + require_once $root.'/MiddlewareStack.php'; 11 + require_once $root.'/MimePart.php';
+1 -9
scripts/mail/mail_handler.php
··· 14 14 15 15 $root = dirname(dirname(dirname(__FILE__))); 16 16 require_once $root.'/scripts/__init_script__.php'; 17 - require_once $root.'/externals/mimemailparser/Contracts/CharsetManager.php'; 18 - require_once $root.'/externals/mimemailparser/Contracts/Middleware.php'; 19 - require_once $root.'/externals/mimemailparser/Parser.php'; 20 - require_once $root.'/externals/mimemailparser/Charset.php'; 21 - require_once $root.'/externals/mimemailparser/Attachment.php'; 22 - require_once $root.'/externals/mimemailparser/Exception.php'; 23 - require_once $root.'/externals/mimemailparser/Middleware.php'; 24 - require_once $root.'/externals/mimemailparser/MiddlewareStack.php'; 25 - require_once $root.'/externals/mimemailparser/MimePart.php'; 17 + require_once $root.'/externals/mimemailparser/__init.php'; 26 18 27 19 $args = new PhutilArgumentParser($argv); 28 20 $args->parseStandardArguments();
+2
src/__phutil_library_map__.php
··· 3386 3386 'PhabricatorExternalAccountQuery' => 'applications/auth/query/PhabricatorExternalAccountQuery.php', 3387 3387 'PhabricatorExternalAccountsSettingsPanel' => 'applications/settings/panel/PhabricatorExternalAccountsSettingsPanel.php', 3388 3388 'PhabricatorExternalEditorSettingsPanel' => 'applications/settings/panel/PhabricatorExternalEditorSettingsPanel.php', 3389 + 'PhabricatorExternalMimeMailParserTestCase' => 'applications/metamta/externals/__tests__/PhabricatorExternalMimeMailParserTestCase.php', 3389 3390 'PhabricatorExtraConfigSetupCheck' => 'applications/config/check/PhabricatorExtraConfigSetupCheck.php', 3390 3391 'PhabricatorFacebookAuthProvider' => 'applications/auth/provider/PhabricatorFacebookAuthProvider.php', 3391 3392 'PhabricatorFact' => 'applications/fact/fact/PhabricatorFact.php', ··· 9835 9836 'PhabricatorExternalAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 9836 9837 'PhabricatorExternalAccountsSettingsPanel' => 'PhabricatorSettingsPanel', 9837 9838 'PhabricatorExternalEditorSettingsPanel' => 'PhabricatorEditEngineSettingsPanel', 9839 + 'PhabricatorExternalMimeMailParserTestCase' => 'PhabricatorTestCase', 9838 9840 'PhabricatorExtraConfigSetupCheck' => 'PhabricatorSetupCheck', 9839 9841 'PhabricatorFacebookAuthProvider' => 'PhabricatorOAuth2AuthProvider', 9840 9842 'PhabricatorFact' => 'Phobject',
+84
src/applications/metamta/externals/__tests__/PhabricatorExternalMimeMailParserTestCase.php
··· 1 + <?php 2 + 3 + /** 4 + * @phutil-external-symbol class \PhpMimeMailParser\Parser 5 + */ 6 + final class PhabricatorExternalMimeMailParserTestCase 7 + extends PhabricatorTestCase { 8 + 9 + /** 10 + * Be sure to have mimemailparser classes. 11 + */ 12 + private function initMimemailparser() { 13 + // Not having this extension is probably a frequent error locally. 14 + if (!function_exists('mailparse_msg_create')) { 15 + $this->assertSkipped(pht('PHP mailparse extension is not installed')); 16 + } 17 + 18 + // Root of Phorge installation 19 + $root = dirname(dirname(dirname(dirname(dirname(__DIR__))))); 20 + 21 + // This is safe to be called multiple times. 22 + require_once $root.'/externals/mimemailparser/__init.php'; 23 + } 24 + 25 + public function testMailParse() { 26 + $this->initMimemailparser(); 27 + 28 + $tests = array( 29 + // Test case 0. 30 + // Check that no silly "ISO" things are in the headers, 31 + // even with esoteric accents. 32 + __DIR__.'/data/test_accents', 33 + ); 34 + 35 + foreach ($tests as $test) { 36 + $test_file = $test.'.mbox'; 37 + $test_file_basename = basename($test_file); 38 + $expected_headers_file = $test.'.headers.txt'; 39 + 40 + // Unpack the test. 41 + $mail_content = Filesystem::readFile($test_file); 42 + $expected_headers_raw = Filesystem::readFile($expected_headers_file); 43 + $expected_headers = $this->readAssociativeConf($expected_headers_raw); 44 + 45 + // Parse the email. 46 + $parser = new \PhpMimeMailParser\Parser(); 47 + $parser->setText($mail_content); 48 + 49 + // Check email fields headers from the corresponding txt file. 50 + $headers = $parser->getHeaders(); 51 + foreach ($expected_headers as $k => $v) { 52 + $this->assertEqual($v, $headers[$k], pht( 53 + "Read the header '%s' from the test email %s", 54 + $k, 55 + $test_file_basename)); 56 + } 57 + 58 + // If you are creative enough, you can do some tests on the body. 59 + // $content = array(); 60 + // foreach (array('text', 'html') as $part) { 61 + // $part_body = $parser->getMessageBody($part); 62 + // $content[$part] = $part_body; 63 + // } 64 + } 65 + } 66 + 67 + /** 68 + * Get an associative array from "key:value" lines. 69 + * @return array 70 + */ 71 + private function readAssociativeConf(string $conf_raw) { 72 + $conf = []; 73 + $lines = explode("\n", $conf_raw); 74 + foreach ($lines as $line) { 75 + $line = trim($line); 76 + if ($line !== '') { 77 + list($k, $v) = explode(':', $line, 2); 78 + $conf[$k] = $v; 79 + } 80 + } 81 + return $conf; 82 + } 83 + 84 + }
+3
src/applications/metamta/externals/__tests__/data/test_accents.headers.txt
··· 1 + from:Èxämplæ <myself-ääsdlääl@example.com> 2 + to:bossò-ääsdlääl@example.com 3 + subject:È ora di fare review! Aäällright
+39
src/applications/metamta/externals/__tests__/data/test_accents.mbox
··· 1 + From myself-ääsdlääl@example.com Tue Dec 3 15:07:14 2024 2 + Message-ID: <bb2f249a6e74b167d05b8c05977272c4fb78c0b7.camel@reyboz.it> 3 + Subject: =?ISO-8859-1?Q?=C8?= ora di fare review! 4 + =?ISO-8859-1?Q?A=E4=E4llright?= 5 + From: =?ISO-8859-1?Q?=C8x=E4mpl=E6?= <myself-ääsdlääl@example.com> 6 + X-Evolution-Identity: df6e2e1cbb42dd3e8553007ad64b060e663ba7d0 7 + X-Evolution-Fcc: folder://88d77e0e58a4c694494b49c0910f14f16d180d17/Sent 8 + X-Evolution-Transport: 034c5b726f93fae6b9b88dfdee67e7a519e3ac39 9 + To: bossò-ääsdlääl@example.com 10 + X-Evolution-Draft-Folder: 11 + folder://88d77e0e58a4c694494b49c0910f14f16d180d17/Drafts 12 + X-Evolution-Draft-Message: 1444 13 + X-Evolution-Format: text/html 14 + X-Evolution-Composer-Mode: text/plain 15 + Content-Type: multipart/alternative; boundary="=-ljePQpBKYtigz2UvrK3I" 16 + User-Agent: Evolution 3.46.4-2 17 + Date: Tue, 03 Dec 2024 15:07:14 +0100 18 + MIME-Version: 1.0 19 + X-Evolution-Source: 88d77e0e58a4c694494b49c0910f14f16d180d17 20 + 21 + --=-ljePQpBKYtigz2UvrK3I 22 + Content-Type: text/plain; charset="UTF-8" 23 + Content-Transfer-Encoding: 8bit 24 + 25 + Ottimo! È oraää di fare review. Bella zio. 26 + 27 + 28 + --=-ljePQpBKYtigz2UvrK3I 29 + Content-Type: text/html; charset="utf-8" 30 + Content-Transfer-Encoding: 8bit 31 + 32 + <html x-evo-bgcolor="#1b1e20" x-evo-text="#fcfcfc" x-evo-link="#1d99f3" x-evo-vlink="#fcfcfc"><head x-evo-selection="anchorElem=[3] anchorOffset=0 anchorIsElement=1"><style id="x-evo-theme-sheet">html { background-color : #1b1e20; } 33 + html { color : #fcfcfc; } 34 + a { color : #1d99f3; } 35 + a:visited { color : #fcfcfc; } 36 + </style></head><body data-evo-draft=""><div style="width: 71ch;">Ottimo! È oraää di fare review. Bella zio.</div><div style="width: 71ch;"><span class="-x-evo-signature" id="none"></span></div><div style="width: 71ch;"><span class="-x-evo-signature" id="none"></span></div><div style="width: 71ch;"><br></div><div style="width: 71ch;" class="-x-evo-signature-wrapper"><span class="-x-evo-signature" id="none"></span></div></body></html> 37 + 38 + --=-ljePQpBKYtigz2UvrK3I-- 39 +