Changes of Revision 67
kolab-syncroton.spec
Changed
x
1
2
%global upstream_version 2.4.2
3
4
Name: kolab-syncroton
5
-Version: 2.4.2.39
6
+Version: 2.4.2.41
7
Release: 1%{?dist}
8
Summary: ActiveSync for Kolab Groupware
9
10
debian.changelog
Changed
7
1
2
-kolab-syncroton (2.4.2.39-0~kolab1) unstable; urgency=low
3
+kolab-syncroton (2.4.2.41-0~kolab1) unstable; urgency=low
4
5
* Release version 2.4.2
6
7
kolab-syncroton-2.4.2.tar.gz/bin/delete-device.php
Changed
18
1
2
}
3
$owner = $opts'owner';
4
5
+$host = $rcube->config->get('imap_host', $rcube->config->get('default_host'));
6
+$host = parse_url($host, PHP_URL_HOST) ?? $host;
7
$select = $db->query(
8
"SELECT `user_id` FROM `users`"
9
. " WHERE `username` = ?"
10
+ . " AND `mail_host` = ?"
11
. " ORDER BY `user_id` DESC",
12
- \strtolower($owner)
13
+ \strtolower($owner),
14
+ \strtolower($host)
15
);
16
17
if ($data = $db->fetch_assoc($select)) {
18
kolab-syncroton-2.4.2.tar.gz/bin/inspect.php
Changed
134
1
2
'e' => 'email',
3
'p' => 'adminpassword',
4
'd' => 'debug',
5
+ 'k' => 'dump'
6
);
7
8
if (empty($opts'email')) {
9
10
11
$rcube = rcube::get_instance();
12
$default_port = $rcube->config->get('default_port', 143);
13
-$default_host = $rcube->config->get('default_host');
14
+
15
+$host = $rcube->config->get('imap_host', $rcube->config->get('default_host'));
16
+
17
+// parse $host
18
+$a_host = parse_url($host);
19
+$port = null;
20
+$ssl = null;
21
+if (!empty($a_host'host')) {
22
+ $host = $a_host'host';
23
+ $ssl = (isset($a_host'scheme') && in_array($a_host'scheme', 'ssl','imaps','tls')) ? $a_host'scheme' : null;
24
+ if (!empty($a_host'port')) {
25
+ $port = $a_host'port';
26
+ } elseif ($ssl && $ssl != 'tls' && (!$default_port || $default_port == 143)) {
27
+ $port = 993;
28
+ }
29
+}
30
+
31
+if (!$port) {
32
+ $port = $default_port;
33
+}
34
+
35
$imap = new \rcube_imap_generic();
36
if ($proxyAuth) {
37
$options'auth_cid' = $user;
38
$options'auth_pw' = $password;
39
}
40
$options'auth_type' = 'PLAIN';
41
-$options'port' = $default_port;
42
+$options'port' = $port;
43
+
44
$options'socket_options' =
45
'ssl' =>
46
'verify_peer_name' => false,
47
48
$debug = !empty($opts'debug');
49
50
$imap->setDebug($debug);
51
-if (!$imap->connect($default_host, $email, $password, $options)) {
52
+if (!$imap->connect($host, $email, $password, $options)) {
53
rcube::raise_error("Failed to connect to imap.", false, true);
54
}
55
56
57
$select = $db->query(
58
"SELECT `user_id` FROM `users`"
59
. " WHERE `username` = ?"
60
+ . " AND `mail_host` = ?"
61
. " ORDER BY `user_id` DESC",
62
- \strtolower($email)
63
+ \strtolower($email),
64
+ \strtolower($host)
65
);
66
67
if ($data = $db->fetch_assoc($select)) {
68
69
return "Unknown value: $value";
70
}
71
72
+
73
+function getContentIds($db, $device_id, $folder_id)
74
+{
75
+ $contentSelect = $db->query(
76
+ "SELECT contentid FROM `syncroton_content`"
77
+ . " WHERE `device_id` = ? AND `folder_id` = ? AND `is_deleted` = 0",
78
+ $device_id,
79
+ $folder_id
80
+ );
81
+
82
+ $contentUids = ;
83
+ while ($content = $db->fetch_assoc($contentSelect)) {
84
+ $contentUids = $content'contentid';
85
+ }
86
+ return $contentUids;
87
+}
88
+
89
function getContentUids($db, $device_id, $folder_id)
90
{
91
$contentSelect = $db->query(
92
93
println(" Number of syncs: " . ($folder'counter' ?? "None"));
94
println(" Filter type: " . filterType($folder'lastfiltertype' ?? null));
95
96
+
97
+ if (!empty($opts'dump') && $opts'dump' == $folder'name') {
98
+ $contentUids = getContentUids($db, $deviceId, $folderId);
99
+ $imapUids = getImapUids($imap, $folder'name', $folder'lastfiltertype' ?? null);
100
+
101
+ $entries = array_diff($imapUids, $contentUids);
102
+ if (!empty($entries)) {
103
+ println(" The following messages are on the server, but not the device:");
104
+ foreach ($entries as $uid) {
105
+ println(" $uid");
106
+ //TODO get details from imap?
107
+ }
108
+ }
109
+
110
+ $entries = array_diff($contentUids, $imapUids);
111
+ if (!empty($entries)) {
112
+ println(" The following messages are on the device, but not the server:");
113
+ foreach ($entries as $uid) {
114
+ println(" $uid");
115
+ //TODO get details from the content part?
116
+ //TODO display creation_synckey?
117
+ }
118
+ }
119
+
120
+ $contentUids = getContentUids($db, $deviceId, $folderId);
121
+ foreach (array_slice($contentUids, -10, 10) as $uid) {
122
+ println($uid);
123
+ }
124
+
125
+ $contentIds = getContentIds($db, $deviceId, $folderId);
126
+ foreach (array_slice($contentIds, -10, 10) as $uid) {
127
+ println($uid);
128
+ }
129
+ }
130
+
131
if (($folder'class' == "Email") && ($folder'counter' ?? false) && $messageCount != $totalCount && ($modseq == "none" || $modseq == $imapModseq)) {
132
if (($folder'lastfiltertype' ?? false) && $messageCount > $totalCount) {
133
// This doesn't have to indicate an issue, since the timewindow of the filter wanders, so some messages that have been synchronized may no longer match the window.
134
kolab-syncroton-2.4.2.tar.gz/config/config.inc.php.dist
Changed
14
1
2
$config'activesync_log_file' = null;
3
4
// Type of ActiveSync cache. Supported values: 'db', 'apc' and 'memcache'.
5
-// Note: This is only for some additional data like timezones mapping.
6
$config'activesync_cache' = 'db';
7
8
-// lifetime of ActiveSync cache
9
-// possible units: s, m, h, d, w
10
+// Lifetime of the ActiveSync cache. Supported units: s, m, h, d, w
11
$config'activesync_cache_ttl' = '1d';
12
13
// Type of ActiveSync Auth cache. Supported values: 'db', 'apc' and 'memcache'.
14
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SendMail.php
Changed
25
1
2
protected $_defaultNameSpace = 'uri:ComposeMail';
3
protected $_documentElement = 'SendMail';
4
5
+ protected $_clientId;
6
protected $_mime;
7
protected $_saveInSent;
8
protected $_source;
9
10
} elseif ($this->_requestBody) {
11
$xml = simplexml_import_dom($this->_requestBody);
12
13
+ $this->_clientId = (string) $xml->ClientId;
14
$this->_mime = (string) $xml->Mime;
15
$this->_saveInSent = isset($xml->SaveInSentItems);
16
$this->_replaceMime = isset($xml->ReplaceMime);
17
18
*/
19
protected function sendMail($dataController)
20
{
21
- $dataController->sendEmail($this->_mime, $this->_saveInSent);
22
+ $dataController->sendEmail($this->_mime, $this->_saveInSent, $this->_clientId);
23
}
24
}
25
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SmartForward.php
Changed
15
1
2
*/
3
protected function sendMail($dataController)
4
{
5
- $dataController->forwardEmail($this->_source, $this->_mime, $this->_saveInSent, $this->_replaceMime);
6
+ $dataController->forwardEmail(
7
+ $this->_source,
8
+ $this->_mime,
9
+ $this->_saveInSent,
10
+ $this->_replaceMime,
11
+ $this->_clientId
12
+ );
13
}
14
}
15
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Command/SmartReply.php
Changed
9
1
2
*/
3
protected function sendMail($dataController)
4
{
5
- $dataController->replyEmail($this->_source, $this->_mime, $this->_saveInSent, $this->_replaceMime);
6
+ $dataController->replyEmail($this->_source, $this->_mime, $this->_saveInSent, $this->_replaceMime, $this->_clientId);
7
}
8
}
9
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/Email.php
Changed
28
1
2
* (non-PHPdoc)
3
* @see Syncroton_Data_IDataEmail::forwardEmail()
4
*/
5
- public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime)
6
+ public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime, $clientId)
7
{
8
if ($inputStream == 'triggerException') {
9
throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAILBOX_SERVER_OFFLINE);
10
11
* (non-PHPdoc)
12
* @see Syncroton_Data_IDataEmail::replyEmail()
13
*/
14
- public function replyEmail($source, $inputStream, $saveInSent, $replaceMime)
15
+ public function replyEmail($source, $inputStream, $saveInSent, $replaceMime, $clientId)
16
{
17
// forward email
18
}
19
20
* (non-PHPdoc)
21
* @see Syncroton_Data_IDataEmail::sendEmail()
22
*/
23
- public function sendEmail($inputStream, $saveInSent)
24
+ public function sendEmail($inputStream, $saveInSent, $clientId)
25
{
26
if ($inputStream == 'triggerException') {
27
throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAILBOX_SERVER_OFFLINE);
28
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Data/IDataEmail.php
Changed
44
1
2
/**
3
* send an email
4
*
5
- * @param resource $inputStream
6
- * @param boolean $saveInSent
7
+ * @param resource $inputStream
8
+ * @param bool $saveInSent
9
+ * @param ?string $clientId
10
*/
11
- public function sendEmail($inputStream, $saveInSent);
12
+ public function sendEmail($inputStream, $saveInSent, $clientId);
13
14
/**
15
* forward an email
16
*
17
- * @param string|array $source is either a string(LongId) or an array with following properties collectionId, itemId and instanceId
18
- * @param string $inputStream
19
- * @param string $saveInSent
20
+ * @param string|array $source is either a string(LongId) or an array with following properties collectionId, itemId and instanceId
21
+ * @param string $inputStream
22
+ * @param string $saveInSent
23
+ * @param bool $replaceMime
24
+ * @param ?string $clientId
25
*/
26
- public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime);
27
+ public function forwardEmail($source, $inputStream, $saveInSent, $replaceMime, $clientId);
28
29
/**
30
* reply to an email
31
*
32
- * @param string|array $source is either a string(LongId) or an array with following properties collectionId, itemId and instanceId
33
- * @param string $inputStream
34
- * @param string $saveInSent
35
+ * @param string|array $source is either a string(LongId) or an array with following properties collectionId, itemId and instanceId
36
+ * @param string $inputStream
37
+ * @param string $saveInSent
38
+ * @param bool $replaceMime
39
+ * @param ?string $clientId
40
*/
41
- public function replyEmail($source, $inputStream, $saveInSent, $replaceMime);
42
+ public function replyEmail($source, $inputStream, $saveInSent, $replaceMime, $clientId);
43
}
44
kolab-syncroton-2.4.2.tar.gz/lib/ext/Syncroton/Server.php
Changed
13
1
2
if (!$response) {
3
$response = $command->getResponse();
4
}
5
+
6
+ if ($response === null) {
7
+ // FIXME: Is this really needed? It is for PHP cli-server, but not really for a real http server
8
+ header('Content-Length: 0');
9
+ }
10
} catch (Syncroton_Exception_ProvisioningNeeded $sepn) {
11
if ($this->_logger instanceof Zend_Log) {
12
$this->_logger->info(__METHOD__ . '::' . __LINE__ . " provisioning needed");
13
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_data_email.php
Changed
211
1
2
{
3
public const MAX_SEARCH_RESULT = 200;
4
5
+ protected const MAIL_SUBMITTED = 1;
6
+ protected const MAIL_DONE = 2;
7
+
8
/**
9
* Mapping from ActiveSync Email namespace fields
10
*/
11
12
$is_ios = preg_match('/(iphone|ipad)/i', $this->device->devicetype);
13
14
// attachments
15
- $attachments = array_merge($message->attachments, $message->inline_parts);
16
+ $attachments = $message->attachments;
17
+ if (isset($message->inline_parts)) {
18
+ $attachments = array_merge($attachments, $message->inline_parts);
19
+ }
20
if (!empty($attachments)) {
21
$result'attachments' = ;
22
+ $attachment_ids = ;
23
24
foreach ($attachments as $attachment) {
25
$att = ;
26
27
continue;
28
}
29
30
+ // Eliminate possible duplicates in $attachments
31
+ if (in_array($attachment->mime_id, $attachment_ids)) {
32
+ continue;
33
+ }
34
+
35
$filename = rcube_charset::clean($attachment->filename);
36
if (empty($filename) && $attachment->mimetype == 'text/html') {
37
$filename = 'HTML Part';
38
}
39
40
- $att'displayName' = $filename;
41
+ $att'displayName' = $filename;
42
$att'fileReference' = $serverId . '::' . $attachment->mime_id;
43
- $att'method' = 1;
44
+ // Message/rfc822 parts have Method=5, anything else Method=1
45
+ // FIXME: Method=6 is for OLE objects, but is it inline images or sth else?
46
+ $att'method' = strcasecmp($attachment->mimetype, 'message/rfc822') === 0 ? 5 : 1;
47
$att'estimatedDataSize' = $attachment->size;
48
49
if (!empty($attachment->content_id)) {
50
$att'contentId' = rcube_charset::clean($attachment->content_id);
51
}
52
+
53
if (!empty($attachment->content_location)) {
54
$att'contentLocation' = rcube_charset::clean($attachment->content_location);
55
}
56
57
- if (in_array($attachment, $message->inline_parts)) {
58
+ if (strcasecmp($attachment->disposition, 'inline') === 0) {
59
$att'isInline' = 1;
60
}
61
62
$result'attachments' = new Syncroton_Model_EmailAttachment($att);
63
+ $attachment_ids = $attachment->mime_id;
64
}
65
}
66
67
68
* Send an email
69
*
70
* @param mixed $message MIME message
71
- * @param boolean $saveInSent Enables saving the sent message in Sent folder
72
+ * @param bool $saveInSent Enables saving the sent message in Sent folder
73
+ * @param ?string $clientId Message client-id
74
*
75
* @throws Syncroton_Exception_Status
76
*/
77
- public function sendEmail($message, $saveInSent)
78
+ public function sendEmail($message, $saveInSent, $clientId)
79
{
80
+ if (($status = $this->sentMailStatus($clientId, $cache, $cache_key)) === self::MAIL_DONE) {
81
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MESSAGE_PREVIOUSLY_SENT);
82
+ }
83
+
84
if (!($message instanceof kolab_sync_message)) {
85
$message = new kolab_sync_message($message);
86
}
87
88
- $sent = $message->send($smtp_error);
89
+ // Snet the message (if not sent previously)
90
+ if (!$status) {
91
+ $sent = $message->send($smtp_error);
92
93
- if (!$sent) {
94
- throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAIL_SUBMISSION_FAILED);
95
+ if (!$sent) {
96
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MAIL_SUBMISSION_FAILED);
97
+ }
98
+
99
+ if (!empty($cache)) {
100
+ $cache->set($cache_key, self::MAIL_SUBMITTED);
101
+ }
102
}
103
104
// Save sent message in Sent folder
105
if ($saveInSent) {
106
- $sent_folder = kolab_sync::get_instance()->config->get('sent_mbox');
107
-
108
- if (strlen($sent_folder) && $this->storage->folder_exists($sent_folder)) {
109
- return $this->storage->save_message($sent_folder, $message->source(), '', false, 'SEEN');
110
+ if (!$message->saveInSent()) {
111
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::SERVER_ERROR);
112
}
113
}
114
+
115
+ if (!empty($cache)) {
116
+ $cache->set($cache_key, self::MAIL_DONE);
117
+ }
118
}
119
120
/**
121
122
* @param array|string $itemId A string LongId or an array with following properties:
123
* collectionId, itemId and instanceId
124
* @param resource|string $body MIME message
125
- * @param boolean $saveInSent Enables saving the sent message in Sent folder
126
- * @param boolean $replaceMime If enabled, original message would be appended
127
+ * @param bool $saveInSent Enables saving the sent message in Sent folder
128
+ * @param bool $replaceMime If enabled, original message would be appended
129
+ * @param ?string $clientId Message client-id
130
*
131
* @throws Syncroton_Exception_Status
132
*/
133
- public function forwardEmail($itemId, $body, $saveInSent, $replaceMime)
134
+ public function forwardEmail($itemId, $body, $saveInSent, $replaceMime, $clientId)
135
{
136
+ if ($this->sentMailStatus($clientId) === self::MAIL_DONE) {
137
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MESSAGE_PREVIOUSLY_SENT);
138
+ }
139
+
140
/*
141
@TODO:
142
The SmartForward command can be applied to a meeting. When SmartForward is applied to a recurring meeting,
143
144
}
145
146
// Send message
147
- $this->sendEmail($sync_msg, $saveInSent);
148
+ $this->sendEmail($sync_msg, $saveInSent, $clientId);
149
150
// Set FORWARDED flag on the replied message
151
if (empty($message->headers->flags'FORWARDED')) {
152
153
* @param array|string $itemId A string LongId or an array with following properties:
154
* collectionId, itemId and instanceId
155
* @param resource|string $body MIME message
156
- * @param boolean $saveInSent Enables saving the sent message in Sent folder
157
- * @param boolean $replaceMime If enabled, original message would be appended
158
+ * @param bool $saveInSent Enables saving the sent message in Sent folder
159
+ * @param bool $replaceMime If enabled, original message would be appended
160
+ * @param ?string $clientId Message client-id
161
*
162
* @throws Syncroton_Exception_Status
163
*/
164
- public function replyEmail($itemId, $body, $saveInSent, $replaceMime)
165
+ public function replyEmail($itemId, $body, $saveInSent, $replaceMime, $clientId)
166
{
167
+ if ($this->sentMailStatus($clientId) === self::MAIL_DONE) {
168
+ throw new Syncroton_Exception_Status(Syncroton_Exception_Status::MESSAGE_PREVIOUSLY_SENT);
169
+ }
170
+
171
$msg = $this->parseMessageId($itemId);
172
$message = $this->getObject($itemId);
173
174
175
}
176
177
// Send message
178
- $this->sendEmail($sync_msg, $saveInSent);
179
+ $this->sendEmail($sync_msg, $saveInSent, $clientId);
180
181
// Set ANSWERED flag on the replied message
182
if (empty($message->headers->flags'ANSWERED')) {
183
184
return kolab_sync_message::fake_message($headers, $msg);
185
}
186
}
187
+
188
+ /**
189
+ * Check in the cache if specified message (client-id) has been previously processed
190
+ * and with what result. It's used to prevent a duplicate submission.
191
+ */
192
+ protected function sentMailStatus($clientId, &$cache = null, &$cache_key = null)
193
+ {
194
+ // Note: ClientId is set with ActiveSync version >= 14.0
195
+ if ($clientId === null || $clientId === '') {
196
+ return 0;
197
+ }
198
+
199
+ $engine = kolab_sync::get_instance();
200
+ $status = null;
201
+ $cache_key = "ClientId:{$clientId}";
202
+
203
+ if ($cache_type = $engine->config->get('activesync_cache', 'db')) {
204
+ $cache = $engine->get_cache('activesync_cache', $cache_type, '1d', false);
205
+ $status = $cache->get($cache_key);
206
+ }
207
+
208
+ return (int) $status;
209
+ }
210
}
211
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_message.php
Changed
68
1
2
unset($smtp_headers'Bcc');
3
4
// send message
5
- if (!is_object($rcube->smtp)) {
6
- $rcube->smtp_init(true);
7
- }
8
+ if (isset($headers'X-Syncroton-Test')
9
+ && preg_match('/smtp=(true|false)/i', $headers'X-Syncroton-Test', $m)
10
+ ) {
11
+ $sent = $m1 == 'true';
12
+ $smtp_response = ;
13
+ $smtp_error = 999;
14
+ } else {
15
+ if (!is_object($rcube->smtp)) {
16
+ $rcube->smtp_init(true);
17
+ }
18
19
- $sent = $rcube->smtp->send_mail($headers'From', $recipients, $smtp_headers, $this->body, $smtp_opts);
20
- $smtp_response = $rcube->smtp->get_response();
21
- $smtp_error = $rcube->smtp->get_error();
22
+ $sent = $rcube->smtp->send_mail($headers'From', $recipients, $smtp_headers, $this->body, $smtp_opts);
23
+ $smtp_response = $rcube->smtp->get_response();
24
+ $smtp_error = $rcube->smtp->get_error();
25
+ }
26
27
// log error
28
if (!$sent) {
29
30
}
31
32
/**
33
+ * Save message in Sent folder
34
+ *
35
+ * @return bool True on success (or when the folder does not exist), False otherwise
36
+ */
37
+ public function saveInSent()
38
+ {
39
+ $engine = kolab_sync::get_instance();
40
+ $storage = $engine->get_storage();
41
+ $sent_folder = $engine->config->get('sent_mbox');
42
+
43
+ if (isset($this->headers'X-Syncroton-Test')
44
+ && preg_match('/imap=(true|false)/i', $this->headers'X-Syncroton-Test', $m)
45
+ ) {
46
+ return $m1 == 'true';
47
+ }
48
+
49
+ if (strlen($sent_folder) && $storage->folder_exists($sent_folder)) {
50
+ $source = $this->source();
51
+ $uid = $storage->save_message($sent_folder, $source, '', false, 'SEEN');
52
+
53
+ if (empty($uid)) {
54
+ rcube::raise_error('code' => 500, 'type' => 'imap',
55
+ 'line' => __LINE__, 'file' => __FILE__,
56
+ 'message' => "Failed to save message in {$sent_folder}", true, false);
57
+ return false;
58
+ }
59
+ }
60
+
61
+ return true;
62
+ }
63
+
64
+ /**
65
* Parses the message source and fixes 8bit data for ActiveSync.
66
* This way any not UTF8 characters will be encoded before
67
* sending to the device.
68
kolab-syncroton-2.4.2.tar.gz/lib/kolab_sync_timezone_converter.php
Changed
18
1
2
protected $_startDate = ;
3
4
/**
5
- * If set then the timezone guessing results will be cached.
6
- * This is strongly recommended for performance reasons.
7
- *
8
- * @var rcube_cache
9
- */
10
- protected $cache = null;
11
-
12
- /**
13
* array of offsets known by ActiceSync clients, but unknown by php
14
+ *
15
* @var array
16
*/
17
protected $_knownTimezones =
18
kolab-syncroton-2.4.2.tar.gz/tests/Sync/SendMailTest.php
Added
114
1
2
+<?php
3
+
4
+class SendMailTest extends Tests\SyncTestCase
5
+{
6
+ /**
7
+ * Test SendMail command
8
+ */
9
+ public function testSendMail()
10
+ {
11
+ $this->emptyTestFolder('Sent', 'mail');
12
+
13
+ $clientId = microtime();
14
+
15
+ $request = <<<EOF
16
+ <?xml version="1.0" encoding="utf-8"?>
17
+ <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
18
+ <SendMail xmlns="uri:ComposeMail">
19
+ <ClientId>{$clientId}</ClientId>
20
+ <SaveInSentItems />
21
+ <Mime>From: testuser1@kolab.org
22
+ To: testuser2@kolab.org
23
+ Subject: Test
24
+ MIME-Version: 1.0
25
+ Content-Type: text/plain; charset="iso-8859-1"
26
+ Message-ID: <msg1@kolab.org>
27
+ X-Syncroton-Test: smtp=true
28
+
29
+ This is the email body content.</Mime>
30
+ </SendMail>
31
+ EOF;
32
+
33
+ $response = $this->request($request, 'SendMail');
34
+
35
+ $this->assertEquals(200, $response->getStatusCode());
36
+ $this->assertSame('', (string) $response->getBody());
37
+ $emails = $this->listEmails('Sent', '*');
38
+ $this->assertCount(1, $emails);
39
+ // TODO: Assert mail content
40
+ }
41
+
42
+ /**
43
+ * Test SendMail command
44
+ */
45
+ public function testSendMailErrorHandling()
46
+ {
47
+ $this->emptyTestFolder('Sent', 'mail');
48
+
49
+ $clientId = microtime();
50
+
51
+ $request = <<<EOF
52
+ <?xml version="1.0" encoding="utf-8"?>
53
+ <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
54
+ <SendMail xmlns="uri:ComposeMail">
55
+ <ClientId>{$clientId}</ClientId>
56
+ <SaveInSentItems />
57
+ <Mime>From: testuser1@kolab.org
58
+ To: testuser2@kolab.org
59
+ Subject: Test
60
+ MIME-Version: 1.0
61
+ Content-Type: text/plain; charset="iso-8859-1"
62
+ Message-ID: <msg1@kolab.org>
63
+ X-Syncroton-Test: smtp=false imap=true
64
+
65
+ This is the email body content.</Mime>
66
+ </SendMail>
67
+ EOF;
68
+
69
+ // Expect a SMTP error
70
+ $response = $this->request($request, 'SendMail');
71
+
72
+ $dom = $this->fromWbxml($response->getBody());
73
+ $xpath = $this->xpath($dom);
74
+
75
+ $this->assertEquals(200, $response->getStatusCode());
76
+ $this->assertSame('120', $xpath->query("//ns:SendMail/ns:Status")->item(0)->nodeValue);
77
+ $this->assertCount(0, $this->listEmails('Sent', '*'));
78
+
79
+ // Test IMAP error handling
80
+ $request = str_replace('smtp=false', 'smtp=true', $request);
81
+ $request = str_replace('imap=true', 'imap=false', $request);
82
+
83
+ $response = $this->request($request, 'SendMail');
84
+
85
+ $dom = $this->fromWbxml($response->getBody());
86
+ $xpath = $this->xpath($dom);
87
+
88
+ $this->assertEquals(200, $response->getStatusCode());
89
+ $this->assertSame('110', $xpath->query("//ns:SendMail/ns:Status")->item(0)->nodeValue);
90
+ $this->assertCount(0, $this->listEmails('Sent', '*'));
91
+
92
+ // Test no error
93
+ // smtp=false would cause error, but the submission should get skipped now
94
+ $request = str_replace('smtp=true', 'smtp=false', $request);
95
+ $request = str_replace('imap=false', '', $request);
96
+
97
+ $response = $this->request($request, 'SendMail');
98
+
99
+ $this->assertEquals(200, $response->getStatusCode());
100
+ $this->assertSame('', (string) $response->getBody());
101
+ $this->assertCount(1, $this->listEmails('Sent', '*'));
102
+
103
+ // Send the same mail again, expect an error
104
+ $response = $this->request($request, 'SendMail');
105
+
106
+ $dom = $this->fromWbxml($response->getBody());
107
+ $xpath = $this->xpath($dom);
108
+
109
+ $this->assertEquals(200, $response->getStatusCode());
110
+ $this->assertSame('118', $xpath->query("//ns:SendMail/ns:Status")->item(0)->nodeValue);
111
+ $this->assertCount(1, $this->listEmails('Sent', '*'));
112
+ }
113
+}
114
kolab-syncroton-2.4.2.tar.gz/tests/Sync/Sync/EmailTest.php
Changed
74
1
2
$this->assertSame('test sync', $xpath->query("{$root}/ns:ApplicationData/Email:Subject")->item(0)->nodeValue);
3
4
// List the rest of the mail
5
- $request = <<<EOF
6
- <?xml version="1.0" encoding="utf-8"?>
7
- <!DOCTYPE AirSync PUBLIC "-//AIRSYNC//DTD AirSync//EN" "http://www.microsoft.com/">
8
- <Sync xmlns="uri:AirSync" xmlns:AirSyncBase="uri:AirSyncBase">
9
- <Collections>
10
- <Collection>
11
- <SyncKey>{$syncKey}</SyncKey>
12
- <CollectionId>{$folderId}</CollectionId>
13
- <DeletesAsMoves>1</DeletesAsMoves>
14
- <GetChanges>1</GetChanges>
15
- <Options>
16
- <FilterType>0</FilterType>
17
- <Conflict>1</Conflict>
18
- <BodyPreference xmlns="uri:AirSyncBase">
19
- <Type>2</Type>
20
- <TruncationSize>51200</TruncationSize>
21
- <AllOrNone>0</AllOrNone>
22
- </BodyPreference>
23
- </Options>
24
- </Collection>
25
- </Collections>
26
- </Sync>
27
- EOF;
28
+ $request = preg_replace('|<SyncKey>\d</SyncKey>|', "<SyncKey>{$syncKey}</SyncKey>", $request);
29
30
$response = $this->request($request, 'Sync');
31
32
33
$this->assertStringMatchesFormat("{$folderId}::%d", $xpath->query("{$root}/ns:ServerId")->item(0)->nodeValue);
34
$this->assertSame('sync test with attachment', $xpath->query("{$root}/ns:ApplicationData/Email:Subject")->item(0)->nodeValue);
35
$this->assertSame(1, $xpath->query("{$root}/ns:ApplicationData/AirSyncBase:Body")->count());
36
+ $attachments = $xpath->query("{$root}/ns:ApplicationData/AirSyncBase:Attachments/AirSyncBase:Attachment");
37
+ $this->assertSame(3, $attachments->count());
38
+ $att = $attachments->item(0);
39
+ $this->assertSame('message.eml', $xpath->query('AirSyncBase:DisplayName', $att)->item(0)->nodeValue);
40
+ $this->assertSame('5', $xpath->query('AirSyncBase:Method', $att)->item(0)->nodeValue);
41
+ $this->assertSame('63', $xpath->query('AirSyncBase:EstimatedDataSize', $att)->item(0)->nodeValue);
42
+ $this->assertSame(0, $xpath->query('AirSyncBase:IsInline', $att)->count());
43
+ $att = $attachments->item(1);
44
+ $this->assertSame('logo1.gif', $xpath->query('AirSyncBase:DisplayName', $att)->item(0)->nodeValue);
45
+ $this->assertSame('1', $xpath->query('AirSyncBase:Method', $att)->item(0)->nodeValue);
46
+ $this->assertSame('76', $xpath->query('AirSyncBase:EstimatedDataSize', $att)->item(0)->nodeValue);
47
+ $this->assertSame(0, $xpath->query('AirSyncBase:IsInline', $att)->count());
48
+ $att = $attachments->item(2);
49
+ $this->assertSame('logo2.gif', $xpath->query('AirSyncBase:DisplayName', $att)->item(0)->nodeValue);
50
+ $this->assertSame('1', $xpath->query('AirSyncBase:Method', $att)->item(0)->nodeValue);
51
+ $this->assertSame('76', $xpath->query('AirSyncBase:EstimatedDataSize', $att)->item(0)->nodeValue);
52
+ $this->assertSame('1', $xpath->query('AirSyncBase:IsInline', $att)->item(0)->nodeValue);
53
+ $this->assertSame('foo4foo1@bar.net', $xpath->query('AirSyncBase:ContentId', $att)->item(0)->nodeValue);
54
+ $this->assertSame('fiction1/fiction2', $xpath->query('AirSyncBase:ContentLocation', $att)->item(0)->nodeValue);
55
+
56
+ // Test the empty Sync response
57
+ $request = preg_replace('|<SyncKey>\d</SyncKey>|', "<SyncKey>{$syncKey}</SyncKey>", $request);
58
+
59
+ $response = $this->request($request, 'Sync');
60
+
61
+ // According to https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-ascmd/b4b366a5-7dfb-45a9-a256-af8fa7c53400
62
+ // the empty response should look like this
63
+ //
64
+ // HTTP/1.1 200 OK
65
+ // Date: Fri, 10 Apr 2009 20:32:39 GMT
66
+ // Content-Length: 0
67
+
68
+ $this->assertSame(200, $response->getStatusCode());
69
+ $this->assertSame('', (string) $response->getBody());
70
+ $this->assertSame('0', $response->getHeader('Content-Length'));
71
72
return $syncKey;
73
}
74
kolab-syncroton-2.4.2.tar.gz/tests/SyncTestCase.php
Changed
27
1
2
3
// Make sure user is authenticated
4
$this->getImapStorage();
5
- if (!empty($sync->user)) {
6
+ if ($sync->user) {
7
// required e.g. for DAV client cache use
8
\rcube::get_instance()->user = $sync->user;
9
}
10
11
$xpath->registerNamespace("AirSyncBase", "uri:AirSyncBase");
12
$xpath->registerNamespace("Calendar", "uri:Calendar");
13
$xpath->registerNamespace("Contacts", "uri:Contacts");
14
+ $xpath->registerNamespace("ComposeMail", "uri:ComposeMail");
15
$xpath->registerNamespace("Email", "uri:Email");
16
$xpath->registerNamespace("Email2", "uri:Email2");
17
$xpath->registerNamespace("Settings", "uri:Settings");
18
19
if (method_exists("PHPUnit\Framework\TestCase", "assertMatchesRegularExpression")) {
20
parent::assertMatchesRegularExpression($arg1, $arg2, $message);
21
} else {
22
- parent::assertRegExp($arg1, $arg2);
23
+ parent::assertRegExp($arg1, $arg2, $message);
24
}
25
}
26
}
27
kolab-syncroton-2.4.2.tar.gz/tests/src/mail.sync2
Changed
29
1
2
3
ZWVl
4
--BOUNDARY
5
+Content-Type: message/rfc822
6
+Content-Disposition: attachment; filename=message.eml
7
+
8
+Subject: Forwarded
9
+From: kolab@domain.tld
10
+
11
+Forwarded message
12
+--BOUNDARY
13
+Content-Transfer-Encoding: base64
14
+Content-Type: image/gif; name=logo1.gif
15
+Content-Disposition: attachment; filename=logo1.gif; size=2574
16
+
17
+/9j/4AAQSkZJRgABAgEASABIAAD/4QqARXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA
18
+--BOUNDARY
19
Content-Transfer-Encoding: base64
20
-Content-Type: image/jpeg; name=logo.gif
21
-Content-Disposition: inline; filename=logo.gif; size=2574
22
+Content-Type: image/gif; name=logo2.gif
23
+Content-Disposition: inline; filename=logo2.gif; size=2574
24
+Content-ID: <foo4foo1@bar.net>
25
+Content-Location: fiction1/fiction2
26
27
/9j/4AAQSkZJRgABAgEASABIAAD/4QqARXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA
28
--BOUNDARY--
29
kolab-syncroton.dsc
Changed
10
1
2
Source: kolab-syncroton
3
Binary: kolab-syncroton
4
Architecture: all
5
-Version: 1:2.4.2.39-1~kolab1
6
+Version: 1:2.4.2.41-1~kolab1
7
Maintainer: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
8
Uploaders: Jeroen van Meeuwen <vanmeeuwen@kolabsys.com>
9
Homepage: http://www.kolab.org/
10