1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-18 04:42:40 +01:00

Skip attaching 'inline' text attachments

Summary:
Mail clients can send messages where the body is represented as 'inline'
attachments. Don't treat any such text attachments as actual attachments.

Test Plan:
toulouse, can you verify this fixes the issue?

Reviewed By: toulouse
Reviewers: toulouse
CC: aran, toulouse, epriestley
Differential Revision: 441
This commit is contained in:
epriestley 2011-06-12 21:09:55 -07:00
parent 93773495d1
commit 8ca5581a9c
2 changed files with 61 additions and 32 deletions

View file

@ -10,35 +10,35 @@ require_once('attachment.class.php');
* @version $Id$ * @version $Id$
*/ */
class MimeMailParser { class MimeMailParser {
/** /**
* PHP MimeParser Resource ID * PHP MimeParser Resource ID
*/ */
public $resource; public $resource;
/** /**
* A file pointer to email * A file pointer to email
*/ */
public $stream; public $stream;
/** /**
* A text of an email * A text of an email
*/ */
public $data; public $data;
/** /**
* Stream Resources for Attachments * Stream Resources for Attachments
*/ */
public $attachment_streams; public $attachment_streams;
/** /**
* Inialize some stuff * Inialize some stuff
* @return * @return
*/ */
public function __construct() { public function __construct() {
$this->attachment_streams = array(); $this->attachment_streams = array();
} }
/** /**
* Free the held resouces * Free the held resouces
* @return void * @return void
@ -57,7 +57,7 @@ class MimeMailParser {
fclose($stream); fclose($stream);
} }
} }
/** /**
* Set the file path we use to get the email text * Set the file path we use to get the email text
* @return Object MimeMailParser Instance * @return Object MimeMailParser Instance
@ -70,7 +70,7 @@ class MimeMailParser {
$this->parse(); $this->parse();
return $this; return $this;
} }
/** /**
* Set the Stream resource we use to get the email text * Set the Stream resource we use to get the email text
* @return Object MimeMailParser Instance * @return Object MimeMailParser Instance
@ -95,7 +95,7 @@ class MimeMailParser {
} else { } else {
$this->stream = $stream; $this->stream = $stream;
} }
$this->resource = mailparse_msg_create(); $this->resource = mailparse_msg_create();
// parses the message incrementally low memory usage but slower // parses the message incrementally low memory usage but slower
while(!feof($this->stream)) { while(!feof($this->stream)) {
@ -104,10 +104,10 @@ class MimeMailParser {
$this->parse(); $this->parse();
return $this; return $this;
} }
/** /**
* Set the email text * Set the email text
* @return Object MimeMailParser Instance * @return Object MimeMailParser Instance
* @param $data String * @param $data String
*/ */
public function setText($data) { public function setText($data) {
@ -118,7 +118,7 @@ class MimeMailParser {
$this->parse(); $this->parse();
return $this; return $this;
} }
/** /**
* Parse the Message into parts * Parse the Message into parts
* @return void * @return void
@ -132,7 +132,7 @@ class MimeMailParser {
$this->parts[$part_id] = mailparse_msg_get_part_data($part); $this->parts[$part_id] = mailparse_msg_get_part_data($part);
} }
} }
/** /**
* Retrieve the Email Headers * Retrieve the Email Headers
* @return Array * @return Array
@ -157,7 +157,7 @@ class MimeMailParser {
} }
return false; return false;
} }
/** /**
* Retrieve a specific Email Header * Retrieve a specific Email Header
* @return String * @return String
@ -174,13 +174,20 @@ class MimeMailParser {
} }
return false; return false;
} }
/** /**
* Returns the email message body in the specified format * Returns the email message body in the specified format
* @return Mixed String Body or False if not found * @return Mixed String Body or False if not found
* @param $type Object[optional] * @param $type Object[optional]
*/ */
public function getMessageBody($type = 'text') { public function getMessageBody($type = 'text') {
// NOTE: This function has been modified for Phabricator. The default
// implementation returns the last matching part, which throws away text
// for many emails. Instead, we concatenate all matching parts. See
// issue 22 for discussion:
// http://code.google.com/p/php-mime-mail-parser/issues/detail?id=22
$body = false; $body = false;
$mime_types = array( $mime_types = array(
'text'=> 'text/plain', 'text'=> 'text/plain',
@ -188,10 +195,23 @@ class MimeMailParser {
); );
if (in_array($type, array_keys($mime_types))) { if (in_array($type, array_keys($mime_types))) {
foreach($this->parts as $part) { 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;
}
if ($this->getPartContentType($part) == $mime_types[$type]) { if ($this->getPartContentType($part) == $mime_types[$type]) {
$headers = $this->getPartHeaders($part); $headers = $this->getPartHeaders($part);
$body = $this->decode($this->getPartBody($part), array_key_exists('content-transfer-encoding', $headers) ? // Concatenate all the matching parts into the body text. For example,
$headers['content-transfer-encoding'] : ''); // 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']
: '');
} }
} }
} else { } else {
@ -223,7 +243,7 @@ $headers['content-transfer-encoding'] : '');
return $headers; return $headers;
} }
/** /**
* Returns the attachments contents in order of appearance * Returns the attachments contents in order of appearance
* @return Array * @return Array
@ -236,8 +256,8 @@ $headers['content-transfer-encoding'] : '');
$disposition = $this->getPartContentDisposition($part); $disposition = $this->getPartContentDisposition($part);
if (in_array($disposition, $dispositions)) { if (in_array($disposition, $dispositions)) {
$attachments[] = new MimeMailParser_attachment( $attachments[] = new MimeMailParser_attachment(
$part['disposition-filename'], $part['disposition-filename'],
$this->getPartContentType($part), $this->getPartContentType($part),
$this->getAttachmentStream($part), $this->getAttachmentStream($part),
$disposition, $disposition,
$this->getPartHeaders($part) $this->getPartHeaders($part)
@ -246,7 +266,7 @@ $headers['content-transfer-encoding'] : '');
} }
return $attachments; return $attachments;
} }
/** /**
* Return the Headers for a MIME part * Return the Headers for a MIME part
* @return Array * @return Array
@ -258,7 +278,7 @@ $headers['content-transfer-encoding'] : '');
} }
return false; return false;
} }
/** /**
* Return a Specific Header for a MIME part * Return a Specific Header for a MIME part
* @return Array * @return Array
@ -271,7 +291,7 @@ $headers['content-transfer-encoding'] : '');
} }
return false; return false;
} }
/** /**
* Return the ContentType of the MIME part * Return the ContentType of the MIME part
* @return String * @return String
@ -283,7 +303,7 @@ $headers['content-transfer-encoding'] : '');
} }
return false; return false;
} }
/** /**
* Return the Content Disposition * Return the Content Disposition
* @return String * @return String
@ -295,7 +315,7 @@ $headers['content-transfer-encoding'] : '');
} }
return false; return false;
} }
/** /**
* Retrieve the raw Header of a MIME part * Retrieve the raw Header of a MIME part
* @return String * @return String
@ -328,7 +348,7 @@ $headers['content-transfer-encoding'] : '');
} }
return $body; return $body;
} }
/** /**
* Retrieve the Header from a MIME part from file * Retrieve the Header from a MIME part from file
* @return String Mime Header Part * @return String Mime Header Part
@ -353,7 +373,7 @@ $headers['content-transfer-encoding'] : '');
$body = fread($this->stream, $end-$start); $body = fread($this->stream, $end-$start);
return $body; return $body;
} }
/** /**
* Retrieve the Header from a MIME part from text * Retrieve the Header from a MIME part from text
* @return String Mime Header Part * @return String Mime Header Part
@ -376,14 +396,14 @@ $headers['content-transfer-encoding'] : '');
$body = substr($this->data, $start, $end-$start); $body = substr($this->data, $start, $end-$start);
return $body; return $body;
} }
/** /**
* Read the attachment Body and save temporary file resource * Read the attachment Body and save temporary file resource
* @return String Mime Body Part * @return String Mime Body Part
* @param $part Array * @param $part Array
*/ */
private function getAttachmentStream(&$part) { private function getAttachmentStream(&$part) {
$temp_fp = tmpfile(); $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 = '';
@ -416,7 +436,7 @@ $headers['content-transfer-encoding'] : '');
return $temp_fp; return $temp_fp;
} }
/** /**
* Decode the string depending on encoding type. * Decode the string depending on encoding type.
* @return String the decoded string. * @return String the decoded string.

View file

@ -45,6 +45,15 @@ $received->setBodies(array(
$attachments = array(); $attachments = array();
foreach ($parser->getAttachments() as $attachment) { foreach ($parser->getAttachments() as $attachment) {
if (preg_match('@text/(plain|html)@', $attachment->getContentType()) &&
$attachment->getContentDisposition() == 'inline') {
// If this is an "inline" attachment with some sort of text content-type,
// do not treat it as a file for attachment. MimeMailParser already picked
// it up in the getMessageBody() call above. We still want to treat 'inline'
// attachments with other content types (e.g., images) as attachments.
continue;
}
$file = PhabricatorFile::newFromFileData( $file = PhabricatorFile::newFromFileData(
$attachment->getContent(), $attachment->getContent(),
array( array(