Page MenuHomePhorge

EmailTest.php
No OneTemporary

Authored By
Unknown
Size
21 KB
Referenced Files
None
Subscribers
None

EmailTest.php

<?php
namespace Tests\Sync\Sync;
class EmailTest extends \Tests\SyncTestCase
{
/**
* Test Sync command
*/
public function testSync()
{
$this->emptyTestFolder('INBOX', 'mail');
$this->registerDevice();
// Test invalid collection identifier
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync">
<Collections>
<Collection>
<SyncKey>0</SyncKey>
<CollectionId>1111111111</CollectionId>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$this->assertSame('12', $xpath->query("//ns:Sync/ns:Status")->item(0)->nodeValue);
// Test INBOX
$folderId = '38b950ebd62cd9a66929c89615d0fc04';
$syncKey = 0;
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync">
<Collections>
<Collection>
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$this->assertSame('1', $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:Status")->item(0)->nodeValue);
$this->assertSame(strval(++$syncKey), $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:SyncKey")->item(0)->nodeValue);
$this->assertSame('Email', $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:Class")->item(0)->nodeValue);
$this->assertSame($folderId, $xpath->query("//ns:Sync/ns:Collections/ns:Collection/ns:CollectionId")->item(0)->nodeValue);
// Test listing mail in INBOX, use WindowSize=1
// Append two mail messages
$this->appendMail('INBOX', 'mail.sync1');
$this->appendMail('INBOX', 'mail.sync2');
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
<Collections>
<Collection>
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
<DeletesAsMoves>1</DeletesAsMoves>
<GetChanges>1</GetChanges>
<WindowSize>1</WindowSize>
<Options>
<FilterType>0</FilterType>
<Conflict>1</Conflict>
<BodyPreference xmlns="uri:AirSyncBase">
<Type>2</Type>
<TruncationSize>51200</TruncationSize>
<AllOrNone>0</AllOrNone>
</BodyPreference>
</Options>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$root = "//ns:Sync/ns:Collections/ns:Collection";
$this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
$this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
$this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
$this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
// Note: We assume messages are in IMAP default order, it may change in future
$root .= "/ns:Commands/ns:Add";
$this->assertStringMatchesFormat("{$folderId}::%d", $xpath->query("{$root}/ns:ServerId")->item(0)->nodeValue);
$this->assertSame('test sync', $xpath->query("{$root}/ns:ApplicationData/Email:Subject")->item(0)->nodeValue);
// List the rest of the mail
$request = preg_replace('|<SyncKey>\d</SyncKey>|', "<SyncKey>{$syncKey}</SyncKey>", $request);
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$root = "//ns:Sync/ns:Collections/ns:Collection";
$this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
$this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
$this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
$this->assertSame(1, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
$this->assertSame('0', $xpath->query("{$root}/ns:Commands/ns:Add/ns:ApplicationData/Email:Read")->item(0)->nodeValue);
// Note: We assume messages are in IMAP default order, it may change in future
$root .= "/ns:Commands/ns:Add";
$this->assertStringMatchesFormat("{$folderId}::%d", $xpath->query("{$root}/ns:ServerId")->item(0)->nodeValue);
$this->assertSame('sync test with attachment', $xpath->query("{$root}/ns:ApplicationData/Email:Subject")->item(0)->nodeValue);
$this->assertSame(1, $xpath->query("{$root}/ns:ApplicationData/AirSyncBase:Body")->count());
$attachments = $xpath->query("{$root}/ns:ApplicationData/AirSyncBase:Attachments/AirSyncBase:Attachment");
$this->assertSame(3, $attachments->count());
$att = $attachments->item(0);
$this->assertSame('message.eml', $xpath->query('AirSyncBase:DisplayName', $att)->item(0)->nodeValue);
$this->assertSame('5', $xpath->query('AirSyncBase:Method', $att)->item(0)->nodeValue);
$this->assertSame('63', $xpath->query('AirSyncBase:EstimatedDataSize', $att)->item(0)->nodeValue);
$this->assertSame(0, $xpath->query('AirSyncBase:IsInline', $att)->count());
$att = $attachments->item(1);
$this->assertSame('logo1.gif', $xpath->query('AirSyncBase:DisplayName', $att)->item(0)->nodeValue);
$this->assertSame('1', $xpath->query('AirSyncBase:Method', $att)->item(0)->nodeValue);
$this->assertSame('76', $xpath->query('AirSyncBase:EstimatedDataSize', $att)->item(0)->nodeValue);
$this->assertSame(0, $xpath->query('AirSyncBase:IsInline', $att)->count());
$att = $attachments->item(2);
$this->assertSame('logo2.gif', $xpath->query('AirSyncBase:DisplayName', $att)->item(0)->nodeValue);
$this->assertSame('1', $xpath->query('AirSyncBase:Method', $att)->item(0)->nodeValue);
$this->assertSame('76', $xpath->query('AirSyncBase:EstimatedDataSize', $att)->item(0)->nodeValue);
$this->assertSame('1', $xpath->query('AirSyncBase:IsInline', $att)->item(0)->nodeValue);
$this->assertSame('foo4foo1@bar.net', $xpath->query('AirSyncBase:ContentId', $att)->item(0)->nodeValue);
$this->assertSame('fiction1/fiction2', $xpath->query('AirSyncBase:ContentLocation', $att)->item(0)->nodeValue);
// Test the empty Sync response
$request = preg_replace('|<SyncKey>\d</SyncKey>|', "<SyncKey>{$syncKey}</SyncKey>", $request);
$response = $this->request($request, 'Sync');
// According to https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-ascmd/b4b366a5-7dfb-45a9-a256-af8fa7c53400
// the empty response should look like this
//
// HTTP/1.1 200 OK
// Date: Fri, 10 Apr 2009 20:32:39 GMT
// Content-Length: 0
$this->assertSame(200, $response->getStatusCode());
$this->assertSame('', (string) $response->getBody());
$this->assertSame(['0'], $response->getHeader('Content-Length'));
return $syncKey;
}
/**
* Test empty sync response
*
* @depends testSync
*/
public function testEmptySync($syncKey)
{
$folderId = '38b950ebd62cd9a66929c89615d0fc04';
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
<Collections>
<Collection>
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
<DeletesAsMoves>1</DeletesAsMoves>
<GetChanges>1</GetChanges>
<Options>
<FilterType>0</FilterType>
<Conflict>1</Conflict>
<BodyPreference xmlns="uri:AirSyncBase">
<Type>2</Type>
<TruncationSize>51200</TruncationSize>
<AllOrNone>0</AllOrNone>
</BodyPreference>
</Options>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
// We expect an empty response without a change
$this->assertEquals(0, $response->getBody()->getSize());
return $syncKey;
}
/**
* Test flag change
*
* @depends testEmptySync
*/
public function testFlagChange($syncKey)
{
$this->assertTrue($this->markMailAsRead('INBOX', '*'));
$folderId = '38b950ebd62cd9a66929c89615d0fc04';
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
<Collections>
<Collection>
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
<DeletesAsMoves>1</DeletesAsMoves>
<GetChanges>1</GetChanges>
<Options>
<FilterType>0</FilterType>
<Conflict>1</Conflict>
<BodyPreference xmlns="uri:AirSyncBase">
<Type>2</Type>
<TruncationSize>51200</TruncationSize>
<AllOrNone>0</AllOrNone>
</BodyPreference>
</Options>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$root = "//ns:Sync/ns:Collections/ns:Collection";
$this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
$this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
$this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
$this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
$this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->count());
$this->assertSame('1', $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->item(0)->nodeValue);
$this->assertSame('1', $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/Email:Read")->item(1)->nodeValue);
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Change/ns:ApplicationData/AirSyncBase:Body")->count());
return $syncKey;
}
/**
* Retry flag change
* Resending the same syncKey should result in the same changes.
*
* @depends testFlagChange
*/
public function testRetryFlagChange($syncKey)
{
$syncKey--;
$folderId = '38b950ebd62cd9a66929c89615d0fc04';
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
<Collections>
<Collection>
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
<DeletesAsMoves>1</DeletesAsMoves>
<GetChanges>1</GetChanges>
<Options>
<FilterType>0</FilterType>
<Conflict>1</Conflict>
<BodyPreference xmlns="uri:AirSyncBase">
<Type>2</Type>
<TruncationSize>51200</TruncationSize>
<AllOrNone>0</AllOrNone>
</BodyPreference>
</Options>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$root = "//ns:Sync/ns:Collections/ns:Collection";
$this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
//FIXME I'm not sure why we get syncKey + 2, I suppose we just always increase the current synckey by one.
$this->assertSame(strval($syncKey += 2), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
$this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
$this->assertSame(2, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
$serverId1 = $xpath->query("{$root}/ns:Commands/ns:Change/ns:ServerId")->item(0)->nodeValue;
return [
'syncKey' => $syncKey,
'serverId' => $serverId1,
];
}
/**
* Test updating message properties from client
*
* @depends testRetryFlagChange
*/
public function testChangeFromClient($values)
{
$folderId = '38b950ebd62cd9a66929c89615d0fc04';
$syncKey = $values['syncKey'];
$serverId = $values['serverId'];
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync" xmlns:Syncroton="uri:Syncroton" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Email="uri:Email" xmlns:Email2="uri:Email2" xmlns:Tasks="uri:Tasks">
<Collections>
<Collection xmlns:default="uri:Email" xmlns:default1="uri:AirSyncBase">
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
<Commands xmlns:default="uri:Email" xmlns:default1="uri:AirSyncBase">
<Change xmlns:default="uri:Email" xmlns:default1="uri:AirSyncBase">
<ServerId>{$serverId}</ServerId>
<ApplicationData>
<Email:Read xmlns="uri:Email">0</Email:Read>
<Email:Flag xmlns="uri:Email"/>
</ApplicationData>
</Change>
</Commands>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$root = "//ns:Sync/ns:Collections/ns:Collection";
$this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
$this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
$this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
//The server doesn't have to report back successful changes
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
$emails = $this->listEmails('INBOX', '*');
$uid = explode("::", $serverId)[1];
$this->assertSame(2, count($emails));
$this->assertTrue(!array_key_exists('SEEN', $emails[$uid]));
return [
'syncKey' => $syncKey,
'serverId' => $serverId,
];
}
/**
* Test deleting messages from client
*
* @depends testChangeFromClient
*/
public function testDeleteFromClient($values)
{
$folderId = '38b950ebd62cd9a66929c89615d0fc04';
$syncKey = $values['syncKey'];
$serverId = $values['serverId'];
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync" xmlns:Syncroton="uri:Syncroton" xmlns:AirSyncBase="uri:AirSyncBase" xmlns:Email="uri:Email" xmlns:Email2="uri:Email2" xmlns:Tasks="uri:Tasks">
<Collections>
<Collection xmlns:default="uri:Email" xmlns:default1="uri:AirSyncBase">
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
<Commands xmlns:default="uri:Email" xmlns:default1="uri:AirSyncBase">
<Delete xmlns:default="uri:Email" xmlns:default1="uri:AirSyncBase">
<ServerId>{$serverId}</ServerId>
</Delete>
</Commands>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$root = "//ns:Sync/ns:Collections/ns:Collection";
$this->assertSame('1', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
$this->assertSame(strval(++$syncKey), $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
$this->assertSame($folderId, $xpath->query("{$root}/ns:CollectionId")->item(0)->nodeValue);
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Add")->count());
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Change")->count());
$this->assertSame(0, $xpath->query("{$root}/ns:Commands/ns:Delete")->count());
$emails = $this->listEmails('INBOX', '*');
$uid = explode("::", $serverId)[1];
$this->assertSame(2, count($emails));
$this->assertTrue($emails[$uid]['DELETED']);
return $syncKey;
}
/**
* Test a sync key that doesn't exist yet.
* @depends testDeleteFromClient
*/
public function testInvalidSyncKey($syncKey)
{
$syncKey++;
$folderId = '38b950ebd62cd9a66929c89615d0fc04';
$request = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
<Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
<Collections>
<Collection>
<SyncKey>{$syncKey}</SyncKey>
<CollectionId>{$folderId}</CollectionId>
<DeletesAsMoves>1</DeletesAsMoves>
<GetChanges>1</GetChanges>
<Options>
<FilterType>0</FilterType>
<Conflict>1</Conflict>
<BodyPreference xmlns="uri:AirSyncBase">
<Type>2</Type>
<TruncationSize>51200</TruncationSize>
<AllOrNone>0</AllOrNone>
</BodyPreference>
</Options>
</Collection>
</Collections>
</Sync>
EOF;
$response = $this->request($request, 'Sync');
$this->assertEquals(200, $response->getStatusCode());
$dom = $this->fromWbxml($response->getBody());
$xpath = $this->xpath($dom);
$root = "//ns:Sync/ns:Collections/ns:Collection";
$this->assertSame('3', $xpath->query("{$root}/ns:Status")->item(0)->nodeValue);
$this->assertSame('0', $xpath->query("{$root}/ns:SyncKey")->item(0)->nodeValue);
//We have to start over after this. The sync state was removed.
return 0;
}
}

File Metadata

Mime Type
text/x-php
Expires
Mon, Apr 6, 3:08 AM (2 w, 6 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18832144
Default Alt Text
EmailTest.php (21 KB)

Event Timeline