🐛: JMAP references to previous method results are not working #1508
Replies: 5 comments 3 replies
-
|
To be able to continue with my implementation and not waiting for this to be fixed in Stalwart, I'm emulating multiple methodCalls now with a wrapper using single calls and resolving the references myself: /**
* Make a JMAP call - emulating multiple methodCalls with single calls and resolving references
*
* This fixes what seems to be a bug in Stalwart 0.11.x reference implementation
*
* @link https://github.com/stalwartlabs/mail-server/discussions/1508
* @param array $methodCalls [string $method, array $args][]
* @param string|array $using ='urn:ietf:params:jmap:mail'
* @return array response
*/
public function jmapCall(array $methodCalls, $using='urn:ietf:params:jmap:mail')
{
$responses = [];
foreach($methodCalls as $methodCall)
{
foreach($methodCall[1] as $name => $value)
{
if ($name[0] === '#')
{
unset($methodCall[1][$name]);
$name = substr($name, 1);
if (count($reference = array_filter($responses, function($response) use ($value) {
return $response[2] === $value['resultOf'];
})) !== 1 || $reference[0][0] !== $value['name'] ||
!isset($value['path']) || !is_array($reference[0][1] ?? null) ||
($methodCall[1][$name] = self::jsonPath($reference[0][1], $value['path'])) === null)
{
$responses[] = ['error', [
'type' => 'invalidResultReference',
'description' => 'Failed to evaluate '.json_encode($value).' result reference.',
], $methodCall[2]];
continue 2;
}
}
}
$responses[] = ($response = $this->_jmapCall([$methodCall], $using))['methodResponses'][0];
}
return [
'methodResponses' => $responses,
'sessionState' => $response['sessionState'] ?? null,
];
}Obviously performance and latency is not good, but I can continue with my implementation ... Ralf |
Beta Was this translation helpful? Give feedback.
-
|
@mdecimus I suggest to open that as bug report again ;) Ralf |
Beta Was this translation helpful? Give feedback.
-
|
Thanks, I will test this once JMAP for Calendars is implemented. This is because the JSON pointer eval function will be reimplemented as part of a refactoring that is planned. |
Beta Was this translation helpful? Give feedback.
-
|
Hi @ralfbecker , this has been fixed. However, the version in main is under development and not yet ready for testing. |
Beta Was this translation helpful? Give feedback.
-
|
Any rough idea when it will be released? Thx :) Ralf |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
What happened?
I'm using the Staying-in-sync example from jmap.io together with push subscription to implemented instant updates to our mail UI (www.egroupware.org), as we already have that for Dovecot.
Unfortunately references in JMAP calls with multiple method-calls always return a reference error.
How can we reproduce the problem?
I receive the following change in the push subscription, when I change e.g. the seen flag of a mail:
{"@type":"StateChange","changed":{"s":{"Email":"sr9qk0l2jzhgkyay","Mailbox":"sr9qk0l2jzhgkyay"}}}I know the previous states to be
{"Email":"srxqk071myhgkyay","Mailbox":"srxqk071myhgkyay"}So I send the following JMAP call:
{ "using":["urn:ietf:params:jmap:mail"], "methodCalls": [ ["Mailbox/changes",{ "accountId":"s", "sinceState":"srxqk071myhgkyay" },"0"], ["Mailbox/get",{ "accountId":"s", "#ids":{"name":"Mailbox/changes","path":"/created","resultOf":"0"} },"1"], ["Mailbox/get",{ "accountId":"s", "#ids":{"name":"Mailbox/changes","path":"/updated","resultOf":"0"}, "#properties":{"name":"Mailbox/changes","path":"/updatedProperties","resultOf":"0"} },"2"] ] }and receive this result:
{ "methodResponses":[ ["Mailbox/changes",{ "accountId":"s", "oldState":"srxqk071myhgkyay", "newState":"sr9qk0l2jzhgkyay", "hasMoreChanges":false, "created":[], "updated":["a"], "destroyed":[], "updatedProperties":["totalEmails","unreadEmails","totalThreads","unreadThreads"] },"0"], ["error",{ "type":"invalidResultReference", "description":"Failed to evaluate { resultOf: 0, name: Mailbox/changes, path: /created } result reference." },"1"], ["error",{ "type":"invalidResultReference", "description":"Failed to evaluate { resultOf: 0, name: Mailbox/changes, path: /updated } result reference." },"2"]], "sessionState":"b898b3b6" }While the first response is ok: folder "a" (Inbox) has been updated due to seen flag change the counters changed.
The second result is already wrong, instead of an empty list for no newly created folder it returns a reference error. I could probably live with it, thought it's not according to the spec or the above linked example.
The third result is also wrong, thought the reference should succeed here, as folder "a" (Inbox) was updated.
As it follows so closely the example, I don't think somethings wrong with the JMAP commands I send.
Is that a know problem in Stalwart and is there a workaround or a fix to be expected soon?
Ralf
Version
v0.11.x
What database are you using?
RocksDB
What blob storage are you using?
RocksDB
Where is your directory located?
SQL
What operating system are you using?
Docker
Relevant log output
Code of Conduct
Beta Was this translation helpful? Give feedback.
All reactions