Skip to content

Commit

Permalink
Improved function to parse datetimes
Browse files Browse the repository at this point in the history
- Updated formatting of class DataPartInfo to make it more human-readable
- Issue #310: Fixed issue with unparseable datetimes and updated/added PHPUnit tests
  • Loading branch information
Sebbo94BY authored May 7, 2019
2 parents 983799e + 855f122 commit 4f953db
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 58 deletions.
82 changes: 42 additions & 40 deletions src/PhpImap/DataPartInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,56 @@
* @author nickl- http://github.com/nickl-
*/
class DataPartInfo {

const TEXT_PLAIN = 0;
const TEXT_HTML = 1;
const TEXT_PLAIN = 0;
const TEXT_HTML = 1;

public $id;
public $encoding;
public $charset;
public $id;
public $encoding;
public $charset;
public $part;
public $mail;
public $options;
private $data;

public function __construct($mail, $id, $part, $encoding, $options) {
$this->mail = $mail;
$this->id = $id;
$this->part = $part;
$this->encoding = $encoding;
$this->options = $options;
$this->mail = $mail;
$this->id = $id;
$this->part = $part;
$this->encoding = $encoding;
$this->options = $options;
}

function fetch() {
if(isset($this->data)) {
return $this->data;
}
if($this->part == 0) {
$this->data = $this->mail->imap('body', [$this->id, $this->options]);
}
else {
$this->data = $this->mail->imap('fetchbody', [$this->id, $this->part, $this->options]);
}
switch($this->encoding) {
case ENC8BIT:
$this->data = imap_utf8($this->data);
break;
case ENCBINARY:
$this->data = imap_binary($this->data);
break;
case ENCBASE64:
$this->data = preg_replace('~[^a-zA-Z0-9+=/]+~s', '', $this->data); // https://github.com/barbushin/php-imap/issues/88
$this->data = imap_base64($this->data);
break;
case ENCQUOTEDPRINTABLE:
$this->data = quoted_printable_decode($this->data);
break;
}
if(isset($this->charset)) {
$this->data = $this->mail->convertStringEncoding($this->data, $this->charset, $this->mail->getServerEncoding());
}
return $this->data;
if(isset($this->data)) {
return $this->data;
}

if($this->part == 0) {
$this->data = $this->mail->imap('body', [$this->id, $this->options]);
} else {
$this->data = $this->mail->imap('fetchbody', [$this->id, $this->part, $this->options]);
}

switch($this->encoding) {
case ENC8BIT:
$this->data = imap_utf8($this->data);
break;
case ENCBINARY:
$this->data = imap_binary($this->data);
break;
case ENCBASE64:
$this->data = preg_replace('~[^a-zA-Z0-9+=/]+~s', '', $this->data); // https://github.com/barbushin/php-imap/issues/88
$this->data = imap_base64($this->data);
break;
case ENCQUOTEDPRINTABLE:
$this->data = quoted_printable_decode($this->data);
break;
}

if(isset($this->charset)) {
$this->data = $this->mail->convertStringEncoding($this->data, $this->charset, $this->mail->getServerEncoding());
}

return $this->data;
}
}
24 changes: 15 additions & 9 deletions src/PhpImap/Mailbox.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

use stdClass;
use Exception;
use DateTime;
use PhpImap\IncomingMail;
use PhpImap\IncomingMailHeader;
use PhpImap\IncomingMailAttachment;
Expand Down Expand Up @@ -935,17 +936,22 @@ protected function decodeRFC2231($string, $charset = 'utf-8') {

/**
* Converts the datetime to a normalized datetime
* @param string header datetime
* @return datetime Normalized datetime
* @param string header datetime
* @return datetime Normalized datetime
*/
public function parseDateTime($dateHeader){
if(!empty($dateHeader)) {
$dateRegex = '/\\s*\\(.*?\\)/';
$dateFormatted = \DateTime::createFromFormat(\DateTime::RFC2822, preg_replace($dateRegex, '', $dateHeader));
return $dateFormatted->format('Y-m-d H:i:s');
} else {
$now = new \DateTime;
public function parseDateTime($dateHeader) {
if(empty($dateHeader)) {
throw new InvalidParameterException('parseDateTime() expects parameter 1 to be a parsable string datetime');
}

$dateRegex = '/\\s*\\(.*?\\)/';
$dateFormatted = DateTime::createFromFormat(DateTime::RFC2822, preg_replace($dateRegex, '', $dateHeader));

if(is_bool($dateFormatted)) {
$now = new DateTime;
return $now->format('Y-m-d H:i:s');
} else {
return $dateFormatted->format('Y-m-d H:i:s');
}
}

Expand Down
35 changes: 26 additions & 9 deletions tests/unit/MailboxTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* @author Sebastian Kraetzig <sebastian-kraetzig@gmx.de>
*/

use DateTime;
use PhpImap\Mailbox;
use PhpImap\Exceptions\ConnectionException;
use PhpImap\Exceptions\InvalidParameterException;
Expand Down Expand Up @@ -318,9 +319,8 @@ public function testEncodingReturnsCorrectValues()

/**
* Test, different datetimes conversions using differents timezones
*/

public function testParsedDateDifferentTimeZones(){
*/
public function testParsedDateDifferentTimeZones() {
$test_datetimes = array (
array('Sun, 14 Aug 2005 16:13:03 +0000 (CEST)' ,'1124035983'),
array('Sun, 14 Aug 2005 16:13:03 +0000','1124035983'),
Expand Down Expand Up @@ -371,7 +371,6 @@ public function testParsedDateDifferentTimeZones(){

array('Sun, 14 Aug 2005 16:13:03 +1200 (CEST)','1124035983'),
array('Sun, 14 Aug 2005 16:13:03 +1200','1124035983'),

);

foreach($test_datetimes as $datetime) {
Expand All @@ -383,19 +382,37 @@ public function testParsedDateDifferentTimeZones(){
$parsedDateTime = new DateTime($parsedDt);

$this->assertEquals($parsedDateTime->format('U'), $epochToCompare);

}

}

/**
* Test, different invalid / unparseable datetimes conversions
*/
public function testParsedDateWithUnparseableDateTime() {
$test_unparseable_datetimes = array (
array('14 Aug 2005 16:13:03 +1200 (CEST)','1124035983'),
array('14 Aug 2005 16:13:03 +1200','1124035983'),
array('14 Aug 2005 16:13:03 -0500','1124035983'),
);

foreach($test_unparseable_datetimes as $datetime) {
$dateToParse = $datetime["0"];
$epochToCompare = $datetime["1"];

$parsedDt = $this->mailbox->parseDateTime($dateToParse);

$parsedDateTime = new DateTime($parsedDt);

$this->assertNotEquals($parsedDateTime->format('U'), $epochToCompare);
}
}

/**
* Test, parsed datetime being emtpy the header date
*/
public function testParsedDateTimeWithEmptyHeaderDate() {
$parsedDt = $this->mailbox->parseDateTime('');
$now = new DateTime;
$this->assertEquals($parsedDt, $now->format('Y-m-d H:i:s'));
$this->expectException(InvalidParameterException::class);
$this->mailbox->parseDateTime('');

}

Expand Down

0 comments on commit 4f953db

Please sign in to comment.