Skip to content

Commit

Permalink
Cancel ICS file corrupted on Office 365 PHPMailer#1780 (PHPMailer#1842)
Browse files Browse the repository at this point in the history
* Cancel ICS file corrupted on Office 365 PHPMailer#1780
  • Loading branch information
puhr-mde authored and Synchro committed Sep 26, 2019
1 parent 69a5403 commit de53537
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 2 deletions.
43 changes: 41 additions & 2 deletions src/PHPMailer.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ class PHPMailer
const ENCRYPTION_STARTTLS = 'tls';
const ENCRYPTION_SMTPS = 'ssl';

const ICAL_METHOD_REQUEST = 'REQUEST';
const ICAL_METHOD_PUBLISH = 'PUBLISH';
const ICAL_METHOD_REPLY = 'REPLY';
const ICAL_METHOD_ADD = 'ADD';
const ICAL_METHOD_CANCEL = 'CANCEL';
const ICAL_METHOD_REFRESH = 'REFRESH';
const ICAL_METHOD_COUNTER = 'COUNTER';
const ICAL_METHOD_DECLINECOUNTER = 'DECLINECOUNTER';

/**
* Email priority.
* Options: null (default), 1 = High, 3 = Normal, 5 = low.
Expand Down Expand Up @@ -149,6 +158,22 @@ class PHPMailer
*/
public $Ical = '';

/**
* Value-array of "method" in Contenttype header "text/calendar"
*
* @var string[]
*/
protected static $IcalMethods = [
self::ICAL_METHOD_REQUEST,
self::ICAL_METHOD_PUBLISH,
self::ICAL_METHOD_REPLY,
self::ICAL_METHOD_ADD,
self::ICAL_METHOD_CANCEL,
self::ICAL_METHOD_REFRESH,
self::ICAL_METHOD_COUNTER,
self::ICAL_METHOD_DECLINECOUNTER,
];

/**
* The complete compiled MIME message body.
*
Expand Down Expand Up @@ -2604,7 +2629,14 @@ public function createBody()
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
if (!empty($this->Ical)) {
$body .= $this->getBoundary($this->boundary[1], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=REQUEST', '');
$method = static::ICAL_METHOD_REQUEST;
foreach (static::$IcalMethods as $imethod) {
if (stripos($this->Ical, 'METHOD:' . $imethod) !== false) {
$method = $imethod;
break;
}
}
$body .= $this->getBoundary($this->boundary[1], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=' . $method, '');
$body .= $this->encodeString($this->Ical, $this->Encoding);
$body .= static::$LE;
}
Expand Down Expand Up @@ -2640,7 +2672,14 @@ public function createBody()
$body .= $this->encodeString($this->Body, $bodyEncoding);
$body .= static::$LE;
if (!empty($this->Ical)) {
$body .= $this->getBoundary($this->boundary[2], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=REQUEST', '');
$method = static::ICAL_METHOD_REQUEST;
foreach (static::$IcalMethods as $imethod) {
if (stripos($this->Ical, 'METHOD:' . $imethod) !== false) {
$method = $imethod;
break;
}
}
$body .= $this->getBoundary($this->boundary[2], '', static::CONTENT_TYPE_TEXT_CALENDAR . '; method=' . $method, '');
$body .= $this->encodeString($this->Ical, $this->Encoding);
}
$body .= $this->endBoundary($this->boundary[2]);
Expand Down
125 changes: 125 additions & 0 deletions test/PHPMailerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2686,6 +2686,131 @@ public function testOAuth()
$this->assertNull($subject);
$this->assertInstanceOf(OAuth::class, $PHPMailer->getOAuth());
}

/**
* Test ICal method
*/
public function testICalMethod()
{
$this->Mail->Subject .= ': ICal method';
$this->Mail->Body = '<h3>ICal method test.</h3>';
$this->Mail->AltBody = 'ICal method test.';
$this->Mail->Ical = 'BEGIN:VCALENDAR'
. "\r\nVERSION:2.0"
. "\r\nPRODID:-//PHPMailer//PHPMailer Calendar Plugin 1.0//EN"
. "\r\nMETHOD:CANCEL"
. "\r\nCALSCALE:GREGORIAN"
. "\r\nX-MICROSOFT-CALSCALE:GREGORIAN"
. "\r\nBEGIN:VEVENT"
. "\r\nUID:201909250755-42825@test"
. "\r\nDTSTART;20190930T080000Z"
. "\r\nSEQUENCE:2"
. "\r\nTRANSP:OPAQUE"
. "\r\nSTATUS:CONFIRMED"
. "\r\nDTEND:20190930T084500Z"
. "\r\nLOCATION:[London] London Eye"
. "\r\nSUMMARY:Test ICal method"
. "\r\nATTENDEE;CN=Attendee, Test;ROLE=OPT-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP="
. "\r\n TRUE:MAILTO:[email protected]"
. "\r\nCLASS:PUBLIC"
. "\r\nDESCRIPTION:Some plain text"
. "\r\nORGANIZER;CN=\"Example, Test\":MAILTO:[email protected]"
. "\r\nDTSTAMP:20190925T075546Z"
. "\r\nCREATED:20190925T075709Z"
. "\r\nLAST-MODIFIED:20190925T075546Z"
. "\r\nEND:VEVENT"
. "\r\nEND:VCALENDAR";
$this->buildBody();
$this->Mail->preSend();
$this->assertRegExp(
'/Content-Type: text\/calendar; method=CANCEL;/',
$this->Mail->getSentMIMEMessage(),
'Wrong ICal method in Content-Type header'
);
}

/**
* Test ICal missing method to use default (REQUEST)
*/
public function testICalInvalidMethod()
{
$this->Mail->Subject .= ': ICal method';
$this->Mail->Body = '<h3>ICal method test.</h3>';
$this->Mail->AltBody = 'ICal method test.';
$this->Mail->Ical = 'BEGIN:VCALENDAR'
. "\r\nVERSION:2.0"
. "\r\nPRODID:-//PHPMailer//PHPMailer Calendar Plugin 1.0//EN"
. "\r\nMETHOD:INVALID"
. "\r\nCALSCALE:GREGORIAN"
. "\r\nX-MICROSOFT-CALSCALE:GREGORIAN"
. "\r\nBEGIN:VEVENT"
. "\r\nUID:201909250755-42825@test"
. "\r\nDTSTART;20190930T080000Z"
. "\r\nSEQUENCE:2"
. "\r\nTRANSP:OPAQUE"
. "\r\nSTATUS:CONFIRMED"
. "\r\nDTEND:20190930T084500Z"
. "\r\nLOCATION:[London] London Eye"
. "\r\nSUMMARY:Test ICal method"
. "\r\nATTENDEE;CN=Attendee, Test;ROLE=OPT-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP="
. "\r\n TRUE:MAILTO:[email protected]"
. "\r\nCLASS:PUBLIC"
. "\r\nDESCRIPTION:Some plain text"
. "\r\nORGANIZER;CN=\"Example, Test\":MAILTO:[email protected]"
. "\r\nDTSTAMP:20190925T075546Z"
. "\r\nCREATED:20190925T075709Z"
. "\r\nLAST-MODIFIED:20190925T075546Z"
. "\r\nEND:VEVENT"
. "\r\nEND:VCALENDAR";
$this->buildBody();
$this->Mail->preSend();
$this->assertRegExp(
'/Content-Type: text\/calendar; method=REQUEST;/',
$this->Mail->getSentMIMEMessage(),
'Wrong ICal method in Content-Type header'
);
}

/**
* Test ICal invalid method to use default (REQUEST)
*/
public function testICalDefaultMethod()
{
$this->Mail->Subject .= ': ICal method';
$this->Mail->Body = '<h3>ICal method test.</h3>';
$this->Mail->AltBody = 'ICal method test.';
$this->Mail->Ical = 'BEGIN:VCALENDAR'
. "\r\nVERSION:2.0"
. "\r\nPRODID:-//PHPMailer//PHPMailer Calendar Plugin 1.0//EN"
. "\r\nCALSCALE:GREGORIAN"
. "\r\nX-MICROSOFT-CALSCALE:GREGORIAN"
. "\r\nBEGIN:VEVENT"
. "\r\nUID:201909250755-42825@test"
. "\r\nDTSTART;20190930T080000Z"
. "\r\nSEQUENCE:2"
. "\r\nTRANSP:OPAQUE"
. "\r\nSTATUS:CONFIRMED"
. "\r\nDTEND:20190930T084500Z"
. "\r\nLOCATION:[London] London Eye"
. "\r\nSUMMARY:Test ICal method"
. "\r\nATTENDEE;CN=Attendee, Test;ROLE=OPT-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP="
. "\r\n TRUE:MAILTO:[email protected]"
. "\r\nCLASS:PUBLIC"
. "\r\nDESCRIPTION:Some plain text"
. "\r\nORGANIZER;CN=\"Example, Test\":MAILTO:[email protected]"
. "\r\nDTSTAMP:20190925T075546Z"
. "\r\nCREATED:20190925T075709Z"
. "\r\nLAST-MODIFIED:20190925T075546Z"
. "\r\nEND:VEVENT"
. "\r\nEND:VCALENDAR";
$this->buildBody();
$this->Mail->preSend();
$this->assertRegExp(
'/Content-Type: text\/calendar; method=REQUEST;/',
$this->Mail->getSentMIMEMessage(),
'Wrong ICal method in Content-Type header'
);
}
}
/*
* This is a sample form for setting appropriate test values through a browser
Expand Down

0 comments on commit de53537

Please sign in to comment.