3v4l.org

run code in 300+ PHP versions simultaneously
<?php class PlancakeEmailParser { const PLAINTEXT = 1; const HTML = 2; /** * * @var boolean */ private $isImapExtensionAvailable = false; /** * * @var string */ private $emailRawContent; /** * * @var associative array */ protected $rawFields; /** * * @var array of string (each element is a line) */ protected $rawBodyLines; /** * * @param string $emailRawContent */ public function __construct($emailRawContent) { $this->emailRawContent = $emailRawContent; $this->extractHeadersAndRawBody(); if (function_exists('imap_open')) { $this->isImapExtensionAvailable = true; } } private function extractHeadersAndRawBody() { $lines = preg_split("/(\r?\n|\r)/", $this->emailRawContent); $currentHeader = ''; $i = 0; foreach ($lines as $line) { if(self::isNewLine($line)) { // end of headers $this->rawBodyLines = array_slice($lines, $i); break; } if ($this->isLineStartingWithPrintableChar($line)) // start of new header { preg_match('/([^:]+): ?(.*)$/', $line, $matches); $newHeader = strtolower($matches[1]); $value = $matches[2]; $this->rawFields[$newHeader] = $value; $currentHeader = $newHeader; } else // more lines related to the current header { if ($currentHeader) { // to prevent notice from empty lines $this->rawFields[$currentHeader] .= substr($line, 1); } } $i++; } } /** * * @return string (in UTF-8 format) * @throws Exception if a subject header is not found */ public function getSubject() { if (!isset($this->rawFields['subject'])) { throw new Exception("Couldn't find the subject of the email"); } $ret = ''; if ($this->isImapExtensionAvailable) { foreach (imap_mime_header_decode($this->rawFields['subject']) as $h) { // subject can span into several lines $charset = ($h->charset == 'default') ? 'US-ASCII' : $h->charset; $ret .= iconv($charset, "UTF-8//TRANSLIT", $h->text); } } else { $ret = utf8_encode(iconv_mime_decode($this->rawFields['subject'])); } return $ret; } /** * * @return array */ public function getCc() { if (!isset($this->rawFields['cc'])) { return array(); } return explode(',', $this->rawFields['cc']); } /** * * @return array * @throws Exception if a to header is not found or if there are no recipient */ public function getTo() { if ( (!isset($this->rawFields['to'])) || (!count($this->rawFields['to']))) { throw new Exception("Couldn't find the recipients of the email"); } return explode(',', $this->rawFields['to']); } /** * return string - UTF8 encoded * * Example of an email body * --0016e65b5ec22721580487cb20fd Content-Type: text/plain; charset=ISO-8859-1 Hi all. I am new to Android development. Please help me. -- My signature email: myemail@gmail.com web: http://www.example.com --0016e65b5ec22721580487cb20fd Content-Type: text/html; charset=ISO-8859-1 */ public function getBody($returnType=self::PLAINTEXT) { $body = ''; $detectedContentType = false; $contentTransferEncoding = null; $charset = 'ASCII'; $waitingForContentStart = true; if ($returnType == self::HTML) $contentTypeRegex = '/^Content-Type: ?text\/html/i'; else $contentTypeRegex = '/^Content-Type: ?text\/plain/i'; // there could be more than one boundary preg_match_all('/boundary=(.*)/', $this->emailRawContent, $matches); $boundaries = $matches[1]; //preg_match('!boundary=(.*)$!mi', $this->emailRawContent, $matches); //*Removed 17Feb2017 MC //preg_match('/boundary=(.*)/', $this->emailRawContent, $matches); //Previous line was not catching boundaries properly //$boundary = str_replace(array("'", '"'), '', $matches[1]); // sometimes boundaries are delimited by quotes - we want to remove them foreach($boundaries as $i => $v) { $boundaries[$i] = str_replace(array("'", '"'), '', $v); } foreach ($this->rawBodyLines as $line) { if (!$detectedContentType) { if (preg_match($contentTypeRegex, $line, $matches)) { $detectedContentType = true; } if(preg_match('/charset=(.*)/i', $line, $matches)) { $charset = strtoupper(trim($matches[1], '"')); } } else if ($detectedContentType && $waitingForContentStart) { if(preg_match('/charset=(.*)/i', $line, $matches)) { $charset = strtoupper(trim($matches[1], '"')); } if ($contentTransferEncoding == null && preg_match('/^Content-Transfer-Encoding: ?(.*)/i', $line, $matches)) { $contentTransferEncoding = strtoupper($matches[1]); //MC 04Nov16: Added strtoupper } if (self::isNewLine($line)) { $waitingForContentStart = false; } } else { // ($detectedContentType && !$waitingForContentStart) // collecting the actual content until we find the delimiter // if the delimited is AAAAA, the line will be --AAAAA - that's why we use substr if (is_array($boundaries)) { if (in_array(substr($line, 2), $boundaries)) { // found the delimiter break; } } elseif (strpos($line, $boundary)) { break; } $body .= $line . "\n"; } } if (!$detectedContentType) { // if here, we missed the text/plain content-type (probably it was // in the header), thus we assume the whole body is what we are after $body = implode("\n", $this->rawBodyLines); } // removing trailing new lines $body = preg_replace('/((\r?\n)*)$/', '', $body); if ($contentTransferEncoding == 'BASE64') //MC 04Nov16: changed base64 to BASE64 $body = base64_decode($body, true); else if ($contentTransferEncoding == 'QUOTED-PRINTABLE') //MC 04Nov16: changed quoted-printable to QUOTED-PRINTABLE $body = quoted_printable_decode($body); if($charset != 'UTF-8') { // FORMAT=FLOWED, despite being popular in emails, it is not // supported by iconv $charset = str_replace("FORMAT=FLOWED", "", $charset); $body = iconv($charset, 'UTF-8//TRANSLIT', $body); if ($body === FALSE) { // iconv returns FALSE on failure $body = utf8_encode($body); } } return $body; } /** * @return string - UTF8 encoded * */ public function getPlainBody() { return $this->getBody(self::PLAINTEXT); } /** * return string - UTF8 encoded */ public function getHTMLBody() { return $this->getBody(self::HTML); } /** * N.B.: if the header doesn't exist an empty string is returned * * @param string $headerName - the header we want to retrieve * @return string - the value of the header */ public function getHeader($headerName) { $headerName = strtolower($headerName); if (isset($this->rawFields[$headerName])) { return $this->rawFields[$headerName]; } return ''; } /** * * @param string $line * @return boolean */ public static function isNewLine($line) { $line = str_replace("\r", '', $line); $line = str_replace("\n", '', $line); return (strlen($line) === 0); } /** * * @param string $line * @return boolean */ private function isLineStartingWithPrintableChar($line) { return preg_match('/^[A-Za-z]/', $line); } } $rawEmail = "From 8083199272@mms.att.net Tue Jul 03 19:10:49 2018\nReceived: from stcotaapp-apps-sfm1a.mobile.att.net ([166.216.152.37]:50252 helo=stcceg-mtmta01.wnsnet.attws.com)\n by gator3049.hostgator.com with esmtps (TLSv1:DHE-RSA-AES128-SHA:128)\n (Exim 4.91)\n (envelope-from <8083199272@mms.att.net>)\n id 1faVNh-002Xxu-GQ\n for bosque@firepage.org; Tue, 03 Jul 2018 19:10:49 -0500\nReceived: from alnnms01 ([107.79.70.30])\n by stcceg-mtmta01.wnsnet.attws.com with bizsmtp\n id 69421y01Y0fBW5X01QAe4c; Tue, 03 Jul 2018 19:10:38 -0500\nMessage-ID: <69421y01Y0fBW5X01QAe4c@txt.att.net>\nIn-Reply-To: 1383951446.40200251530663038311.JavaMail.nems@alnnms01\nX-Mms-Message-Type: m-send-req\nX-Mms-Transaction-Id: T16462a1a936\nX-Mms-MMS-Version: 1.2\nTo: bosque@firepage.org\nX-Mms-Message-Class: Personal\nX-Mms-Priority: Normal\nX-Mms-Delivery-Report: No\nX-Mms-Read-Reply: No\nFrom: 8083199272@mms.att.net\nDate: Tue, 3 Jul 2018 19:10:38 -0500 (CDT)\nX-Mms-Sender-Visibility: Show\nContent-Type: multipart/mixed; \n boundary=\"----=_Part_1669496_1731281007.1530663038311\"\nMIME-Version: 1.0\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=mms.att.net;\n s=EMG20171113; t=1530663038;\n bh=+kwzoNYvPgMRHfPJi5CwsNVIk5NlSAOY1AHbjrbjBAI=;\n h=In-Reply-To:To:From:Date;\n b=nMIh249YCq/Er2msND65RSC4HgQpbI3KtVOJ0CvZO3rud6mxY44a17RdeRpwLa3YT\n QPWxVW8QVZtD8/Bc4Tpf2DqGjOsR92pQRP9w79zXSssG1pZ0vgDeLldhF92hkj3n/5\n dG2/1jOaMqO4MvIhyX4U5+dp8EI/2xPbrkAu1Wm9LmJuMCJ3eGckyi7Zfk3x4+P1kx\n W5KEBEOi0FPyHIJD/pTmZJe5n179CUFToz+CKgjtNeFH+kkak8NUUx+GCHgL49030A\n jbw53rDN+Z2g9Ts4bYx63Ywf1zX0ZRo0gwXAFTeTY6KbGgJcXNVfWxVVVY27GGtRO6\n xExmhRGYpR6Tg==\n\n------=_Part_1669496_1731281007.1530663038311\nContent-Type: text/plain; charset=UTF-8\nContent-ID: <text_1530663119159.txt>\nContent-Location: text_1530663119159.txt\nContent-Transfer-Encoding: BASE64\n\nVGVzdCBwYWdlIGltIGRyaXZpbmcgdGVzdCBwYWdl\n------=_Part_1669496_1731281007.1530663038311--\n\n\n"; $emailParser = new PlancakeEmailParser($rawEmail); echo print_r($emailParser->getPlainBody()); ?>

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.40.0060.01019.25
8.3.30.0120.00319.01
8.3.20.0060.00319.40
8.3.10.0060.00323.52
8.3.00.0030.00523.65
8.2.170.0180.00322.96
8.2.160.0070.01019.52
8.2.150.0080.00024.18
8.2.140.0070.00024.66
8.2.130.0000.00822.33
8.2.120.0040.00426.35
8.2.110.0090.00921.23
8.2.100.0090.00318.14
8.2.90.0080.00019.34
8.2.80.0030.00517.97
8.2.70.0050.00518.15
8.2.60.0080.00018.17
8.2.50.0030.00618.10
8.2.40.0040.00419.24
8.2.30.0040.00819.35
8.2.20.0040.00418.11
8.2.10.0060.00318.23
8.2.00.0080.00019.45
8.1.270.0050.00321.95
8.1.260.0000.00826.35
8.1.250.0040.00428.09
8.1.240.0070.00322.54
8.1.230.0080.00319.23
8.1.220.0000.00817.79
8.1.210.0040.00418.77
8.1.200.0070.00317.60
8.1.190.0030.00717.50
8.1.180.0090.00018.10
8.1.170.0080.00018.91
8.1.160.0000.00819.00
8.1.150.0000.00819.05
8.1.140.0000.00917.82
8.1.130.0000.00719.11
8.1.120.0000.00817.63
8.1.110.0080.00017.66
8.1.100.0040.00417.63
8.1.90.0030.00617.65
8.1.80.0100.00017.60
8.1.70.0130.00017.64
8.1.60.0060.00317.66
8.1.50.0040.00417.75
8.1.40.0050.00317.64
8.1.30.0060.00317.90
8.1.20.0030.00617.88
8.1.10.0040.00417.76
8.1.00.0050.00317.71
8.0.300.0050.00318.90
8.0.290.0070.00217.00
8.0.280.0000.00718.55
8.0.270.0040.00417.30
8.0.260.0000.00717.27
8.0.250.0040.00417.24
8.0.240.0030.00717.29
8.0.230.0040.00417.25
8.0.220.0000.00717.16
8.0.210.0070.00017.11
8.0.200.0110.00017.18
8.0.190.0080.00017.22
8.0.180.0000.00817.17
8.0.170.0060.00317.22
8.0.160.0040.00417.23
8.0.150.0020.00517.16
8.0.140.0040.00417.11
8.0.130.0060.00013.70
8.0.120.0080.00017.20
8.0.110.0030.00617.13
8.0.100.0040.00416.98
8.0.90.0050.00316.97
8.0.80.0090.01117.21
8.0.70.0050.00317.22
8.0.60.0030.00517.04
8.0.50.0040.00417.04
8.0.30.0070.01217.37
8.0.20.0140.01117.40
8.0.10.0080.00017.19
8.0.00.0070.01416.97
7.4.330.0000.00515.55
7.4.320.0000.00716.80
7.4.300.0030.00316.71
7.4.290.0000.00816.89
7.4.280.0030.00516.75
7.4.270.0080.00016.89
7.4.260.0000.00816.78
7.4.250.0050.00216.79
7.4.240.0040.00416.90
7.4.230.0030.00516.65
7.4.220.0000.00816.93
7.4.210.0080.01116.85
7.4.200.0000.00716.61
7.4.160.0100.00716.89
7.4.140.0110.01217.86
7.4.130.0090.00916.83
7.4.120.0130.00816.88
7.4.110.0130.00416.80
7.4.100.0110.00716.96
7.4.90.0120.00916.70
7.4.80.0120.01219.39
7.4.70.0070.01516.85
7.4.60.0120.01116.73
7.4.50.0130.00816.82
7.4.40.0100.01016.75
7.4.30.0100.01416.79
7.4.20.0100.01416.73
7.4.10.0170.00315.74
7.4.00.0090.00915.65
7.3.330.0000.00513.62
7.3.320.0030.00313.64
7.3.310.0000.00716.70
7.3.300.0030.00316.65
7.3.290.0000.00816.65
7.3.280.0060.01516.70
7.3.260.0100.01016.80
7.3.240.0130.01016.84
7.3.230.0070.01016.53
7.3.210.0100.00716.58
7.3.200.0060.01916.55
7.3.190.0060.01616.63
7.3.180.0130.01016.73
7.3.170.0060.01416.67
7.3.160.0100.00916.73
7.3.150.0080.01616.54
7.3.140.0070.01516.61
7.3.130.0060.01415.67
7.3.120.0120.00815.89
7.3.110.0120.00815.86
7.3.100.0120.00615.81
7.3.90.0140.00715.90
7.3.80.0080.01015.97
7.3.70.0060.00715.97
7.3.60.0080.00815.96
7.3.50.0100.00515.90
7.3.40.0030.01415.77
7.3.30.0070.00815.79
7.3.20.0120.00516.75
7.3.10.0110.01016.69
7.3.00.0280.00816.76
7.2.330.0090.01317.08
7.2.320.0000.01716.83
7.2.310.0130.00616.99
7.2.300.0130.00716.93
7.2.290.0160.00417.06
7.2.280.0150.00917.02
7.2.270.0150.00716.95
7.2.260.0130.00816.06
7.2.250.0110.01016.24
7.2.240.0070.01216.31
7.2.230.0100.00916.17
7.2.220.0120.01016.19
7.2.210.0100.00716.33
7.2.200.0030.01416.14
7.2.190.0120.01016.09
7.2.180.0110.00616.20
7.2.170.0060.01216.27
7.2.160.0120.00616.15
7.2.150.0120.01217.09
7.2.140.0100.00917.15
7.2.130.0090.00916.98
7.2.120.0130.00717.07
7.2.110.0090.01017.10
7.2.100.0070.01017.09
7.2.90.0100.01117.15
7.2.80.0070.01117.15
7.2.70.0160.00916.55
7.2.60.0180.00516.54
7.2.50.0170.00816.50
7.2.40.0180.00616.59
7.2.30.0210.00716.53
7.2.20.0160.00816.41
7.2.10.0190.00916.43
7.2.00.0140.00616.52
7.1.330.0160.01115.89
7.1.320.0080.00815.94
7.1.310.0120.00616.10
7.1.300.0060.01215.97
7.1.290.0050.01215.88
7.1.280.0080.01115.89
7.1.270.0050.01115.96
7.1.260.0070.00915.86
7.1.250.0140.00815.80
7.1.240.0110.01115.83
7.1.230.0120.01115.89
7.1.220.0120.01115.91
7.1.210.0130.01215.98
7.1.200.0100.01116.02
7.1.190.0090.01315.85
7.1.180.0110.00915.90
7.1.170.0120.01115.37
7.1.160.0160.01315.33
7.1.150.0190.00815.48
7.1.140.0160.00815.29
7.1.130.0150.00915.25
7.1.120.0160.00815.31
7.1.110.0150.00815.29
7.1.100.0160.00915.44
7.1.90.0260.00915.41
7.1.80.0170.00815.32
7.1.70.0210.00515.42
7.1.60.0240.01021.31
7.1.50.0190.01621.51
7.1.40.0240.01121.36
7.1.30.0270.00821.36
7.1.20.0250.00821.34
7.1.10.0210.00715.30
7.1.00.0180.00415.32
7.0.330.0120.00915.54
7.0.320.0250.00715.65
7.0.310.0160.00615.60
7.0.300.0130.00515.52
7.0.290.0120.01115.49
7.0.280.0090.00815.40
7.0.270.0100.00715.38
7.0.260.0090.00915.62
7.0.250.0100.01015.66
7.0.240.0110.00915.54
7.0.230.0070.01415.53
7.0.220.0140.00615.66
7.0.210.0120.00815.55
7.0.200.0170.00615.53
7.0.190.0130.01115.61
7.0.180.0040.01815.49
7.0.170.0140.00515.63
7.0.160.0130.01015.59
7.0.150.0070.01115.58
7.0.140.0170.00215.67
7.0.130.0130.00515.45
7.0.120.0090.00915.58
7.0.110.0080.01215.54
7.0.100.0100.00815.62
7.0.90.0080.01015.68
7.0.80.0100.01415.65
7.0.70.0040.01415.54
7.0.60.0080.01215.68
7.0.50.0110.00615.69
7.0.40.0100.00814.62
7.0.30.0270.00914.67
7.0.20.0060.01114.65
7.0.10.0180.00614.70
7.0.00.0150.00914.75
5.6.400.0050.01115.55
5.6.390.0110.01315.64
5.6.380.0090.01315.30
5.6.370.0180.00715.36
5.6.360.0120.00815.35
5.6.350.0120.01015.33
5.6.340.0100.00915.56
5.6.330.0100.01015.34
5.6.320.0080.01615.42
5.6.310.0180.00415.55
5.6.300.0090.01315.35
5.6.290.0080.01915.38
5.6.280.0090.00715.54
5.6.270.0120.00915.48
5.6.260.0070.01415.53
5.6.250.0100.01015.45
5.6.240.0110.01115.35
5.6.230.0110.01015.29
5.6.220.0120.01415.49
5.6.210.0070.01415.36
5.6.200.0080.01215.38
5.6.190.0090.01115.35
5.6.180.0140.01215.28
5.6.170.0100.01215.44
5.6.160.0110.01015.36
5.6.150.0110.01215.35
5.6.140.0090.01415.29
5.6.130.0130.00915.58
5.6.120.0130.01015.36
5.6.110.0100.01315.54
5.6.100.0120.00815.37
5.6.90.0120.00915.70
5.6.80.0090.01115.23
5.6.70.0120.00615.39
5.6.60.0100.00915.40
5.6.50.0100.01015.45
5.6.40.0120.00715.27
5.6.30.0120.00915.31
5.6.20.0120.01115.37
5.6.10.0100.00915.50
5.6.00.0070.01215.44

preferences:
65.43 ms | 400 KiB | 5 Q