mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-17 20:32:41 +01:00
Backport fix from php-mime-mail-parser to fix attachment parsing
Summary: - Allow proper parsing of attachments with missing Content-Disposition header Test Plan: - Create application email for Maniphest. - Send example broken email from Outlook 2007 to that address {F1842816} Reviewers: #blessed_reviewers, epriestley Reviewed By: #blessed_reviewers, epriestley Subscribers: epriestley Differential Revision: https://secure.phabricator.com/D16584
This commit is contained in:
parent
f8c2225268
commit
af218564e5
1 changed files with 62 additions and 40 deletions
102
externals/mimemailparser/MimeMailParser.class.php
vendored
102
externals/mimemailparser/MimeMailParser.class.php
vendored
|
@ -111,13 +111,13 @@ class MimeMailParser {
|
|||
* @param $data String
|
||||
*/
|
||||
public function setText($data) {
|
||||
// NOTE: This has been modified for Phabricator. If the input data does not
|
||||
// end in a newline, Mailparse fails to include the last line in the mail
|
||||
// body. This happens somewhere deep, deep inside the mailparse extension,
|
||||
// so adding a newline here seems like the most straightforward fix.
|
||||
if (!preg_match('/\n\z/', $data)) {
|
||||
$data = $data."\n";
|
||||
}
|
||||
// NOTE: This has been modified for Phabricator. If the input data does not
|
||||
// end in a newline, Mailparse fails to include the last line in the mail
|
||||
// body. This happens somewhere deep, deep inside the mailparse extension,
|
||||
// so adding a newline here seems like the most straightforward fix.
|
||||
if (!preg_match('/\n\z/', $data)) {
|
||||
$data = $data."\n";
|
||||
}
|
||||
|
||||
$this->resource = mailparse_msg_create();
|
||||
// does not parse incrementally, fast memory hog might explode
|
||||
|
@ -203,23 +203,23 @@ class MimeMailParser {
|
|||
);
|
||||
if (in_array($type, array_keys($mime_types))) {
|
||||
foreach($this->parts as $part) {
|
||||
$disposition = $this->getPartContentDisposition($part);
|
||||
if ($disposition == 'attachment') {
|
||||
// text/plain parts with "Content-Disposition: attachment" are
|
||||
// attachments, not part of the text body.
|
||||
continue;
|
||||
}
|
||||
$disposition = $this->getPartContentDisposition($part);
|
||||
if ($disposition == 'attachment') {
|
||||
// text/plain parts with "Content-Disposition: attachment" are
|
||||
// attachments, not part of the text body.
|
||||
continue;
|
||||
}
|
||||
if ($this->getPartContentType($part) == $mime_types[$type]) {
|
||||
$headers = $this->getPartHeaders($part);
|
||||
// Concatenate all the matching parts into the body text. For example,
|
||||
// if a user sends a message with some text, then an image, and then
|
||||
// some more text, the text body of the email gets split over several
|
||||
// attachments.
|
||||
$headers = $this->getPartHeaders($part);
|
||||
// Concatenate all the matching parts into the body text. For example,
|
||||
// if a user sends a message with some text, then an image, and then
|
||||
// some more text, the text body of the email gets split over several
|
||||
// attachments.
|
||||
$body .= $this->decode(
|
||||
$this->getPartBody($part),
|
||||
array_key_exists('content-transfer-encoding', $headers)
|
||||
? $headers['content-transfer-encoding']
|
||||
: '');
|
||||
? $headers['content-transfer-encoding']
|
||||
: '');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -251,20 +251,42 @@ class MimeMailParser {
|
|||
return $headers;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the attachments contents in order of appearance
|
||||
* @return Array
|
||||
* @param $type Object[optional]
|
||||
*/
|
||||
public function getAttachments() {
|
||||
// NOTE: This has been modified for Phabricator. Some mail clients do not
|
||||
// send attachments with "Content-Disposition" headers.
|
||||
$attachments = array();
|
||||
$dispositions = array("attachment","inline");
|
||||
foreach($this->parts as $part) {
|
||||
$non_attachment_types = array("text/plain", "text/html");
|
||||
$nonameIter = 0;
|
||||
foreach ($this->parts as $part) {
|
||||
$disposition = $this->getPartContentDisposition($part);
|
||||
if (in_array($disposition, $dispositions)) {
|
||||
$filename = 'noname';
|
||||
if (isset($part['disposition-filename'])) {
|
||||
$filename = $part['disposition-filename'];
|
||||
} elseif (isset($part['content-name'])) {
|
||||
// if we have no disposition but we have a content-name, it's a valid attachment.
|
||||
// we simulate the presence of an attachment disposition with a disposition filename
|
||||
$filename = $part['content-name'];
|
||||
$disposition = 'attachment';
|
||||
} elseif (!in_array($part['content-type'], $non_attachment_types, true)
|
||||
&& substr($part['content-type'], 0, 10) !== 'multipart/'
|
||||
) {
|
||||
// if we cannot get it with getMessageBody, we assume it is an attachment
|
||||
$disposition = 'attachment';
|
||||
}
|
||||
|
||||
if (in_array($disposition, $dispositions) && isset($filename) === true) {
|
||||
if ($filename == 'noname') {
|
||||
$nonameIter++;
|
||||
$filename = 'noname'.$nonameIter;
|
||||
}
|
||||
$attachments[] = new MimeMailParser_attachment(
|
||||
$part['disposition-filename'],
|
||||
$filename,
|
||||
$this->getPartContentType($part),
|
||||
$this->getAttachmentStream($part),
|
||||
$disposition,
|
||||
|
@ -413,7 +435,7 @@ class MimeMailParser {
|
|||
private function getAttachmentStream(&$part) {
|
||||
$temp_fp = tmpfile();
|
||||
|
||||
array_key_exists('content-transfer-encoding', $part['headers']) ? $encoding = $part['headers']['content-transfer-encoding'] : $encoding = '';
|
||||
array_key_exists('content-transfer-encoding', $part['headers']) ? $encoding = $part['headers']['content-transfer-encoding'] : $encoding = '';
|
||||
|
||||
if ($temp_fp) {
|
||||
if ($this->stream) {
|
||||
|
@ -445,21 +467,21 @@ class MimeMailParser {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decode the string depending on encoding type.
|
||||
* @return String the decoded string.
|
||||
* @param $encodedString The string in its original encoded state.
|
||||
* @param $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
|
||||
*/
|
||||
private function decode($encodedString, $encodingType) {
|
||||
if (strtolower($encodingType) == 'base64') {
|
||||
return base64_decode($encodedString);
|
||||
} else if (strtolower($encodingType) == 'quoted-printable') {
|
||||
return quoted_printable_decode($encodedString);
|
||||
} else {
|
||||
return $encodedString;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Decode the string depending on encoding type.
|
||||
* @return String the decoded string.
|
||||
* @param $encodedString The string in its original encoded state.
|
||||
* @param $encodingType The encoding type from the Content-Transfer-Encoding header of the part.
|
||||
*/
|
||||
private function decode($encodedString, $encodingType) {
|
||||
if (strtolower($encodingType) == 'base64') {
|
||||
return base64_decode($encodedString);
|
||||
} else if (strtolower($encodingType) == 'quoted-printable') {
|
||||
return quoted_printable_decode($encodedString);
|
||||
} else {
|
||||
return $encodedString;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue