Re: Adding support for Apple proprietary IMAP push notifications

2023-12-08 Thread Quan tran hong
Hello Benoit,

> JIRA please!

Yes, it should be JIRA: https://issues.apache.org/jira/projects/JAMES/issues
.

> That's a classic trick to have optional mavven dependencies and address
several architectures at once ;-)

This is truly a trick that would help write the extension more simple while
using the extension modular also. Thank you for adding up for me!

Quan


Vào Th 6, 8 thg 12, 2023 vào lúc 17:18 Benoit TELLIER 
đã viết:

> Hello,
>
>  > That is basically my idea on the topic. You can create a ticket at
> https://github.com/linagora/james-project/issues where we can discuss
> further details on implementing this if you want.
>
> JIRA please!
>
> https://issues.apache.org/jira/projects/JAMES/issues
>
>  > Also please do not hesitate to open a draft pull request so we can
> give you soon feedback.
>
> +1
>
> On a technical standpoint I mostly agree with pointers for Quan.
>
> Thinking more about it, we likely can make only a single extension with
> all storage implementations. And rely on advanced maven tricks for
> having just the right dependencies, while exposing a single maven module.
>
> The idea would be to, within a single APSN extension:
>
>   - Define a storage interface
>   - Define a standard junit 5 contract (with an interface
> APSNStoreContract)
>   - Implement a memory implementation of it (class MemoryAPSNStore
> implementd APSNStore) which passes the test (class MemoryAPSNStoreTest
> implements APSNStoreContract)
>   - Add provided dependency for cassandra, jpa storage backend. This
> mean we can compile with them but runtime deps will be provided by James
> server.
>   - We can then implement one JPAAPSNStore, CassandraAPSNStore and
> related tests
>   - We can write a guice module for each APSNSotre:
> MemoryAPSNStoreModule, JPAAPSNStoreModule, CassandraAPSNStoreModule
>
> Configuration of the storage backend can then be done by choosing the
> corresponding guice module within extensions.properties.
>
> That's a classic trick to have optional mavven dependencies and address
> several architectures at once ;-)
>
> Thoughts Quan?
>
> Best regards,
>
> On 08/12/2023 11:09, Quan tran hong wrote:
> > Hello Andre Borie,
> >
> > Your PoC work is very cool. I am happy that someone out there succeeded
> in
> > using our IMAP command extension mechanism.
> >
> >> however I have a question as to which pattern the storage & APNS
> > long-lived client should conform to. The IMAP extension & mailbox
> listeners
> > (which James has established patterns for) are only *part* of the entire
> > solution.
> >
> > FYI, we (Linagora) developed the JMAP Firebase Cloud Messaging extension.
> > The idea is basically as same as yours:
> > - Exposing application API so users can register their notifications.
> >In our case, it was JMAP FirebaseSubscription extension (
> >
> https://github.com/linagora/tmail-backend/blob/master/docs/modules/ROOT/pages/tmail-backend/jmap-extensions/pushWithFirebase.adoc
> ).
> > In your case it was the IMAP command extension.
> >For storing and managing the subscriptions, we wrote an interface for
> the
> > storage API called `FirebaseSubscriptionRepository` (
> >
> https://github.com/linagora/tmail-backend/blob/master/tmail-backend/jmap/extensions/src/main/java/com/linagora/tmail/james/jmap/firebase/FirebaseSubscriptionRepository.java
> ).
> > The idea is that we can have multiple implementations for the storage API
> > e.g. memory one (mostly for test), Cassandra one (using Cassandra
> > database), Postgres one (using Postgres database)...
> > - Pushing the users's data change to the Push gateway using a listener.
> >In our case it was `FirebasePushListener` (
> >
> https://github.com/linagora/tmail-backend/blob/master/tmail-backend/jmap/extensions/src/main/scala/com/linagora/tmail/james/jmap/firebase/FirebasePushListener.scala#L30
> ),
> > like your listener.
> >
> > I think your PoC is already good enough, the story is just about how to
> > contribute it to James in a proper way.
> >
> > As Benoit suggested, you can contribute your extension into a new module
> > let's say `apsn-imap`:
> >
> https://github.com/apache/james-project/tree/master/third-party/apsn-imap.
> > For the storage API, you can write a simple Java interface e.g.
> > `ApnsTokenRepository` in a child module:
> >
> https://github.com/apache/james-project/tree/master/third-party/apsn-imap/token-storage-api
> > Then you can implement a simple implementation for the storage using
> memory
> > in another child module:
> >
> https://github.com/apache/james-project/tree/master/third-party/apsn-imap/token-storage-memory
> .
> > Or whatever implementation you like IMO, other people who want to have a
> > Cassandra or Postgres implementation can just base on your
> > `ApnsTokenRepository` API.
> > After having the storage API, you can integrate your PushClient and the
> > listener.
> >
> > That is basically my idea on the topic. You can create a ticket at
> > 

Re: Adding support for Apple proprietary IMAP push notifications

2023-12-08 Thread Benoit TELLIER

Hello,

> That is basically my idea on the topic. You can create a ticket at 
https://github.com/linagora/james-project/issues where we can discuss 
further details on implementing this if you want.


JIRA please!

https://issues.apache.org/jira/projects/JAMES/issues

> Also please do not hesitate to open a draft pull request so we can 
give you soon feedback.


+1

On a technical standpoint I mostly agree with pointers for Quan.

Thinking more about it, we likely can make only a single extension with 
all storage implementations. And rely on advanced maven tricks for 
having just the right dependencies, while exposing a single maven module.


The idea would be to, within a single APSN extension:

 - Define a storage interface
 - Define a standard junit 5 contract (with an interface APSNStoreContract)
 - Implement a memory implementation of it (class MemoryAPSNStore 
implementd APSNStore) which passes the test (class MemoryAPSNStoreTest 
implements APSNStoreContract)
 - Add provided dependency for cassandra, jpa storage backend. This 
mean we can compile with them but runtime deps will be provided by James 
server.
 - We can then implement one JPAAPSNStore, CassandraAPSNStore and 
related tests
 - We can write a guice module for each APSNSotre: 
MemoryAPSNStoreModule, JPAAPSNStoreModule, CassandraAPSNStoreModule


Configuration of the storage backend can then be done by choosing the 
corresponding guice module within extensions.properties.


That's a classic trick to have optional mavven dependencies and address 
several architectures at once ;-)


Thoughts Quan?

Best regards,

On 08/12/2023 11:09, Quan tran hong wrote:

Hello Andre Borie,

Your PoC work is very cool. I am happy that someone out there succeeded in
using our IMAP command extension mechanism.


however I have a question as to which pattern the storage & APNS

long-lived client should conform to. The IMAP extension & mailbox listeners
(which James has established patterns for) are only *part* of the entire
solution.

FYI, we (Linagora) developed the JMAP Firebase Cloud Messaging extension.
The idea is basically as same as yours:
- Exposing application API so users can register their notifications.
   In our case, it was JMAP FirebaseSubscription extension (
https://github.com/linagora/tmail-backend/blob/master/docs/modules/ROOT/pages/tmail-backend/jmap-extensions/pushWithFirebase.adoc).
In your case it was the IMAP command extension.
   For storing and managing the subscriptions, we wrote an interface for the
storage API called `FirebaseSubscriptionRepository` (
https://github.com/linagora/tmail-backend/blob/master/tmail-backend/jmap/extensions/src/main/java/com/linagora/tmail/james/jmap/firebase/FirebaseSubscriptionRepository.java).
The idea is that we can have multiple implementations for the storage API
e.g. memory one (mostly for test), Cassandra one (using Cassandra
database), Postgres one (using Postgres database)...
- Pushing the users's data change to the Push gateway using a listener.
   In our case it was `FirebasePushListener` (
https://github.com/linagora/tmail-backend/blob/master/tmail-backend/jmap/extensions/src/main/scala/com/linagora/tmail/james/jmap/firebase/FirebasePushListener.scala#L30),
like your listener.

I think your PoC is already good enough, the story is just about how to
contribute it to James in a proper way.

As Benoit suggested, you can contribute your extension into a new module
let's say `apsn-imap`:
https://github.com/apache/james-project/tree/master/third-party/apsn-imap.
For the storage API, you can write a simple Java interface e.g.
`ApnsTokenRepository` in a child module:
https://github.com/apache/james-project/tree/master/third-party/apsn-imap/token-storage-api
Then you can implement a simple implementation for the storage using memory
in another child module:
https://github.com/apache/james-project/tree/master/third-party/apsn-imap/token-storage-memory.
Or whatever implementation you like IMO, other people who want to have a
Cassandra or Postgres implementation can just base on your
`ApnsTokenRepository` API.
After having the storage API, you can integrate your PushClient and the
listener.

That is basically my idea on the topic. You can create a ticket at
https://github.com/linagora/james-project/issues
where we can discuss further details on implementing this if you want. Also
please do not hesitate to open a draft pull request so we can give you soon
feedback.

Thanks for your enthusiasm.

Regards,

Quan






Vào Th 6, 8 thg 12, 2023 vào lúc 08:47 Andre Borie
đã viết:


Hello,


is there a public document specifying this

No explicit public specification; the closest we have are patches
published against Dovecot (which was part of macOS Server, their
discontinued server product).

Other open-source mail server projects have used that as a specification
to develop their own solutions:

*https://github.com/freswa/dovecot-xaps-plugin
*

Re: Adding support for Apple proprietary IMAP push notifications

2023-12-08 Thread Quan tran hong
Hello Andre Borie,

Your PoC work is very cool. I am happy that someone out there succeeded in
using our IMAP command extension mechanism.

> however I have a question as to which pattern the storage & APNS
long-lived client should conform to. The IMAP extension & mailbox listeners
(which James has established patterns for) are only *part* of the entire
solution.

FYI, we (Linagora) developed the JMAP Firebase Cloud Messaging extension.
The idea is basically as same as yours:
- Exposing application API so users can register their notifications.
  In our case, it was JMAP FirebaseSubscription extension (
https://github.com/linagora/tmail-backend/blob/master/docs/modules/ROOT/pages/tmail-backend/jmap-extensions/pushWithFirebase.adoc).
In your case it was the IMAP command extension.
  For storing and managing the subscriptions, we wrote an interface for the
storage API called `FirebaseSubscriptionRepository` (
https://github.com/linagora/tmail-backend/blob/master/tmail-backend/jmap/extensions/src/main/java/com/linagora/tmail/james/jmap/firebase/FirebaseSubscriptionRepository.java).
The idea is that we can have multiple implementations for the storage API
e.g. memory one (mostly for test), Cassandra one (using Cassandra
database), Postgres one (using Postgres database)...
- Pushing the users's data change to the Push gateway using a listener.
  In our case it was `FirebasePushListener` (
https://github.com/linagora/tmail-backend/blob/master/tmail-backend/jmap/extensions/src/main/scala/com/linagora/tmail/james/jmap/firebase/FirebasePushListener.scala#L30),
like your listener.

I think your PoC is already good enough, the story is just about how to
contribute it to James in a proper way.

As Benoit suggested, you can contribute your extension into a new module
let's say `apsn-imap`:
https://github.com/apache/james-project/tree/master/third-party/apsn-imap.
For the storage API, you can write a simple Java interface e.g.
`ApnsTokenRepository` in a child module:
https://github.com/apache/james-project/tree/master/third-party/apsn-imap/token-storage-api
Then you can implement a simple implementation for the storage using memory
in another child module:
https://github.com/apache/james-project/tree/master/third-party/apsn-imap/token-storage-memory.
Or whatever implementation you like IMO, other people who want to have a
Cassandra or Postgres implementation can just base on your
`ApnsTokenRepository` API.
After having the storage API, you can integrate your PushClient and the
listener.

That is basically my idea on the topic. You can create a ticket at
https://github.com/linagora/james-project/issues
where we can discuss further details on implementing this if you want. Also
please do not hesitate to open a draft pull request so we can give you soon
feedback.

Thanks for your enthusiasm.

Regards,

Quan






Vào Th 6, 8 thg 12, 2023 vào lúc 08:47 Andre Borie 
đã viết:

> Hello,
>
> > is there a public document specifying this
>
> No explicit public specification; the closest we have are patches
> published against Dovecot (which was part of macOS Server, their
> discontinued server product).
>
> Other open-source mail server projects have used that as a specification
> to develop their own solutions:
>
> * https://github.com/freswa/dovecot-xaps-plugin
> *
> https://github.com/cyrusimap/cyrus-imapd/commit/a4470bf0f79de49030b3d66d2b385a1345c1a040
>
> > we added exactly one year ago support for IMAP extension
>
> As you saw previously I am already doing this in my proof-of-concept,
> however I have a question as to which pattern the storage & APNS long-lived
> client should conform to. The IMAP extension & mailbox listeners (which
> James has established patterns for) are only *part* of the entire solution.
>
> I am very new to this project (and Java in general) so I would appreciate
> if someone with more experience could stub out a general layout of the
> classes I should implement and which base classes to inherit from for the
> storage & long-lived APNS client. I will check out that Firebase extension
> you linked but I'd appreciate any other help/opinions.
>
>
> > all code landing in ASF james needs t be ASFV2
>
> I'm open to licensing this under whatever license - the PoC I linked to
> previously is licensed under whatever James is, I've copied the LICENSE
> file verbatim.
>
> > we can not rely on a proprietary custom external APSN bridge (external
> bridge is OK to me though, if FOSS and easy to run...).
>
> T bridge I used in my PoC is FOSS (MIT-licensed), however I am looking to
> remove the dependency on it as I find its data storage model inadequate and
> unable to support mailbox delegation, therefore this mailing list thread on
> how to reimplement the full functionality within James itself.
>
> Regards.
>
>
> > On 7 Dec 2023, at 20:13, Benoit TELLIER  wrote:
> >
> > Hello Andre.
> >
> > Thanks for letting me discover about this Apple feature. Out of
> curiosity, is there a public document specifying 

Re: Adding support for Apple proprietary IMAP push notifications

2023-12-07 Thread Andre Borie
Hello,

> is there a public document specifying this

No explicit public specification; the closest we have are patches published 
against Dovecot (which was part of macOS Server, their discontinued server 
product).

Other open-source mail server projects have used that as a specification to 
develop their own solutions:

* https://github.com/freswa/dovecot-xaps-plugin
* 
https://github.com/cyrusimap/cyrus-imapd/commit/a4470bf0f79de49030b3d66d2b385a1345c1a040

> we added exactly one year ago support for IMAP extension

As you saw previously I am already doing this in my proof-of-concept, however I 
have a question as to which pattern the storage & APNS long-lived client should 
conform to. The IMAP extension & mailbox listeners (which James has established 
patterns for) are only *part* of the entire solution.

I am very new to this project (and Java in general) so I would appreciate if 
someone with more experience could stub out a general layout of the classes I 
should implement and which base classes to inherit from for the storage & 
long-lived APNS client. I will check out that Firebase extension you linked but 
I'd appreciate any other help/opinions.


> all code landing in ASF james needs t be ASFV2

I'm open to licensing this under whatever license - the PoC I linked to 
previously is licensed under whatever James is, I've copied the LICENSE file 
verbatim.

> we can not rely on a proprietary custom external APSN bridge (external bridge 
> is OK to me though, if FOSS and easy to run...).

T bridge I used in my PoC is FOSS (MIT-licensed), however I am looking to 
remove the dependency on it as I find its data storage model inadequate and 
unable to support mailbox delegation, therefore this mailing list thread on how 
to reimplement the full functionality within James itself.

Regards.


> On 7 Dec 2023, at 20:13, Benoit TELLIER  wrote:
> 
> Hello Andre.
> 
> Thanks for letting me discover about this Apple feature. Out of curiosity, is 
> there a public document specifying this? If so could you share this link?
> 
> Are you aware of other free and OpenSource mail servers implementing this?
> 
> Second, we added exactly one year ago support for IMAP extension: 
> implementing support for XAPPLEPUSHSERVICE can thus always be done in an 
> extension. Here is an example of how to do so: 
> https://github.com/apache/james-project/tree/master/examples/custom-imap
> 
> 
> 
> I speak for myself - this is not something I would contribute by myself for 
> pleasure
> 
> > First question would be whether you'd be interested in including this in 
> > James core, or if this should remain a separate extension?
> 
> If there is a publicly available specification and other FOSS mail server 
> implementation for this, I personnally could welcome such a  effort as a 
> third party module that could be embedded into the IMAP stack.
> Definitvely not in James core.
> 
> > If interested in upstreaming, would you be able to outline a high-level 
> > overview of what the code should look like, especially where to put the 
> > APNS client?
> 
> https://github.com/apache/james-project/tree/master/third-party/apsn-imap ?
> 
> We coukld define core concepts there, apsn driver, storage api, imap module. 
> Then separate maven modules for token storage?
> 
> Like 
> https://github.com/apache/james-project/tree/master/third-party/apsn-memory
> https://github.com/apache/james-project/tree/master/third-party/apsn-cassandra
> 
> Somebody willing to enable the extension in James would...
> ...1 Drop the apsn-imap- jar on the classpath
> ...2 Register the guice module into extensions.properties to select his 
> device store.
> ...3 Register the APSN IMAP extension.
> 
> > I want to know whether James has a way for extensions to attach arbitrary 
> > data to a mailbox
> 
> James extension can store data. Talk speaking about this [1] and (old) code 
> example [2]
> [1] https://www.youtube.com/watch?v=zr8qpNkL6U4_channel=TheASF
> [2] https://github.com/chibenwa/james-blacklist
> 
> > Also, where to put the long-lived APNS client?
> 
> Dedicated storage for the extension
> 
> > Does James have an existing extension pattern that accounts for long-lived 
> > services like this?
> 
> Yes as Tung mentionned with JMAP we did implement WebPush and a Linagora 
> specific firebase extension.
> We also do have websockets and eventsource up and running with JMAP.
> 
> > https://github.com/Rjevski/apache-james-xapsd-registration-extension
> 
> So cool!
> 
> Congrats!
> 
> Definitly happy to welcome this in James (as third-party), and happy to see 
> you did succeed to set up an IMAP extension by yourself!
> 
> Last question: all code landing in ASF james needs t be ASFV2 and we can not 
> rely on a proprietary custom external APSN bridge (external bridge is OK to 
> me though, if FOSS and easy to run...).
> 
> Best regards,
> 
> Benoit
> 
> On 07/12/2023 10:33, Tran Tung wrote:
>> Hello,
>> 
>> I'm unable to answer all your questions.
>> As I 

Re: Adding support for Apple proprietary IMAP push notifications

2023-12-07 Thread Benoit TELLIER

Hello Andre.

Thanks for letting me discover about this Apple feature. Out of 
curiosity, is there a public document specifying this? If so could you 
share this link?


Are you aware of other free and OpenSource mail servers implementing this?

Second, we added exactly one year ago support for IMAP extension: 
implementing support for XAPPLEPUSHSERVICE can thus always be done in an 
extension. Here is an example of how to do so: 
https://github.com/apache/james-project/tree/master/examples/custom-imap




I speak for myself - this is not something I would contribute by myself 
for pleasure


> First question would be whether you'd be interested in including this 
in James core, or if this should remain a separate extension?


If there is a publicly available specification and other FOSS mail 
server implementation for this, I personnally could welcome such a  
effort as a third party module that could be embedded into the IMAP stack.

Definitvely not in James core.

> If interested in upstreaming, would you be able to outline a 
high-level overview of what the code should look like, especially where 
to put the APNS client?


https://github.com/apache/james-project/tree/master/third-party/apsn-imap ?

We coukld define core concepts there, apsn driver, storage api, imap 
module. Then separate maven modules for token storage?


Like 
https://github.com/apache/james-project/tree/master/third-party/apsn-memory

https://github.com/apache/james-project/tree/master/third-party/apsn-cassandra

Somebody willing to enable the extension in James would...
...1 Drop the apsn-imap- jar on the classpath
...2 Register the guice module into extensions.properties to select his 
device store.

...3 Register the APSN IMAP extension.

> I want to know whether James has a way for extensions to attach 
arbitrary data to a mailbox


James extension can store data. Talk speaking about this [1] and (old) 
code example [2]

[1] https://www.youtube.com/watch?v=zr8qpNkL6U4_channel=TheASF
[2] https://github.com/chibenwa/james-blacklist

> Also, where to put the long-lived APNS client?

Dedicated storage for the extension

> Does James have an existing extension pattern that accounts for 
long-lived services like this?


Yes as Tung mentionned with JMAP we did implement WebPush and a Linagora 
specific firebase extension.

We also do have websockets and eventsource up and running with JMAP.

> https://github.com/Rjevski/apache-james-xapsd-registration-extension

So cool!

Congrats!

Definitly happy to welcome this in James (as third-party), and happy to 
see you did succeed to set up an IMAP extension by yourself!


Last question: all code landing in ASF james needs t be ASFV2 and we can 
not rely on a proprietary custom external APSN bridge (external bridge 
is OK to me though, if FOSS and easy to run...).


Best regards,

Benoit

On 07/12/2023 10:33, Tran Tung wrote:

Hello,

I'm unable to answer all your questions.
As I know, James doesn't have a backend repository to store data 
similar to your use case.
At Linagora, we encountered a similar situation when implementing 
Firebase. Consequently, we opted to develop a dedicated repository for 
storage.
If you want to reference the code, you can visit 
https://github.com/linagora/tmail-backend/tree/master/tmail-backend/jmap/extensions/src/main/java/com/linagora/tmail/james/jmap/firebase


Hope that help you a bit


On 07/12/2023 15:36, Andre Borie wrote:
Hello and hope everyone is well. I would like your help as to how 
best to implement Apple Push notification support.


For a bit of context, Apple iOS does not use IMAP IDLE - instead it 
uses a proprietary IMAP command "XAPPLEPUSHSERVICE" combined with 
Apple's hosted push notifications service "APNS".


When an iOS device connects to a supported server advertising the 
"XAPPLEPUSHSERVICE" capability, the device issues an 
XAPPLEPUSHSERVICE IMAP command with the following contents:


* account-id: opaque blob that must be quoted in subsequent 
notifications
* subtopic: APNS subtopic, must be used when sending subsequent 
notifications
* device token: the APNS identifier of the device, must be used to 
send subsequent notifications
* list of mailboxes: list of IMAP mailbox names (from the perspective 
of the iOS IMAP client) to monitor and send notifications upon changes


The IMAP server replies with an APNS topic (mostly static value, 
derived from the certificate it uses to talk to APNS). Then, when 
changes occur in the aforementioned mailboxes, the server must send a 
notification via APNS (a persistent connection to an Apple server 
authenticated by a client certificate) towards the aforementioned 
device token & subtopic, quoting the account ID & client-facing 
mailbox name. The notification is relayed by Apple to the target 
device which prompts it to wake up and fetch the new messages via IMAP.


This would require us to:

* store (device_token, account_id, subtopic, client-specific IMAP 
mailbox name) tuples against a 

Re: Adding support for Apple proprietary IMAP push notifications

2023-12-07 Thread Tran Tung

Hello,

I'm unable to answer all your questions.
As I know, James doesn't have a backend repository to store data similar 
to your use case.
At Linagora, we encountered a similar situation when implementing 
Firebase. Consequently, we opted to develop a dedicated repository for 
storage.
If you want to reference the code, you can visit 
https://github.com/linagora/tmail-backend/tree/master/tmail-backend/jmap/extensions/src/main/java/com/linagora/tmail/james/jmap/firebase


Hope that help you a bit


On 07/12/2023 15:36, Andre Borie wrote:

Hello and hope everyone is well. I would like your help as to how best to 
implement Apple Push notification support.

For a bit of context, Apple iOS does not use IMAP IDLE - instead it uses a proprietary IMAP command 
"XAPPLEPUSHSERVICE" combined with Apple's hosted push notifications service 
"APNS".

When an iOS device connects to a supported server advertising the 
"XAPPLEPUSHSERVICE" capability, the device issues an XAPPLEPUSHSERVICE IMAP 
command with the following contents:

* account-id: opaque blob that must be quoted in subsequent notifications
* subtopic: APNS subtopic, must be used when sending subsequent notifications
* device token: the APNS identifier of the device, must be used to send 
subsequent notifications
* list of mailboxes: list of IMAP mailbox names (from the perspective of the 
iOS IMAP client) to monitor and send notifications upon changes

The IMAP server replies with an APNS topic (mostly static value, derived from the 
certificate it uses to talk to APNS). Then, when changes occur in the aforementioned 
mailboxes, the server must send a notification via APNS (a persistent connection to an 
Apple server authenticated by a client certificate) towards the aforementioned device 
token & subtopic, quoting the account ID & client-facing mailbox name. The 
notification is relayed by Apple to the target device which prompts it to wake up and 
fetch the new messages via IMAP.

This would require us to:

* store (device_token, account_id, subtopic, client-specific IMAP mailbox name) 
tuples against a given Mailbox
* react to mailbox events and enqueue notifications for each of the above tuples
* maintain a persistent connection to APNS to dequeue & forward those 
notifications to

First question would be whether you'd be interested in including this in James 
core, or if this should remain a separate extension? If included in core, it 
would require James to be able to accept another keystore (with the APNS 
certificate, created by a helper program) and be able to reload it on the fly 
to enable zero-downtime certificate rotations.

If interested in upstreaming, would you be able to outline a high-level 
overview of what the code should look like, especially where to put the APNS 
client?

On the other hand, if it's better to keep it as an extension, I want to know 
whether James has a way for extensions to attach arbitrary data to a mailbox 
(so I can store the device tokens) without changing the storage backends? Also, 
where to put the long-lived APNS client? Does James have an existing extension 
pattern that accounts for long-lived services like this?

For reference, I currently have a proof of concept extension at 
https://github.com/Rjevski/apache-james-xapsd-registration-extension which is 
an IMAP extension (implementing the custom command) and mailbox listener - 
however, the storage of mailbox to device token mappings and APNS communication 
is delegated to an external service called over HTTP.

Regards.
-
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org




-
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org



Adding support for Apple proprietary IMAP push notifications

2023-12-07 Thread Andre Borie
Hello and hope everyone is well. I would like your help as to how best to 
implement Apple Push notification support.

For a bit of context, Apple iOS does not use IMAP IDLE - instead it uses a 
proprietary IMAP command "XAPPLEPUSHSERVICE" combined with Apple's hosted push 
notifications service "APNS".

When an iOS device connects to a supported server advertising the 
"XAPPLEPUSHSERVICE" capability, the device issues an XAPPLEPUSHSERVICE IMAP 
command with the following contents:

* account-id: opaque blob that must be quoted in subsequent notifications
* subtopic: APNS subtopic, must be used when sending subsequent notifications
* device token: the APNS identifier of the device, must be used to send 
subsequent notifications
* list of mailboxes: list of IMAP mailbox names (from the perspective of the 
iOS IMAP client) to monitor and send notifications upon changes

The IMAP server replies with an APNS topic (mostly static value, derived from 
the certificate it uses to talk to APNS). Then, when changes occur in the 
aforementioned mailboxes, the server must send a notification via APNS (a 
persistent connection to an Apple server authenticated by a client certificate) 
towards the aforementioned device token & subtopic, quoting the account ID & 
client-facing mailbox name. The notification is relayed by Apple to the target 
device which prompts it to wake up and fetch the new messages via IMAP.

This would require us to:

* store (device_token, account_id, subtopic, client-specific IMAP mailbox name) 
tuples against a given Mailbox
* react to mailbox events and enqueue notifications for each of the above tuples
* maintain a persistent connection to APNS to dequeue & forward those 
notifications to

First question would be whether you'd be interested in including this in James 
core, or if this should remain a separate extension? If included in core, it 
would require James to be able to accept another keystore (with the APNS 
certificate, created by a helper program) and be able to reload it on the fly 
to enable zero-downtime certificate rotations.

If interested in upstreaming, would you be able to outline a high-level 
overview of what the code should look like, especially where to put the APNS 
client?

On the other hand, if it's better to keep it as an extension, I want to know 
whether James has a way for extensions to attach arbitrary data to a mailbox 
(so I can store the device tokens) without changing the storage backends? Also, 
where to put the long-lived APNS client? Does James have an existing extension 
pattern that accounts for long-lived services like this?

For reference, I currently have a proof of concept extension at 
https://github.com/Rjevski/apache-james-xapsd-registration-extension which is 
an IMAP extension (implementing the custom command) and mailbox listener - 
however, the storage of mailbox to device token mappings and APNS communication 
is delegated to an external service called over HTTP.

Regards.
-
To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org
For additional commands, e-mail: server-dev-h...@james.apache.org