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 <h...@rjevski.io.invalid>
đã 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 <btell...@apache.org> 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-xxxx 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&ab_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 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
> >>
> >>
> >
> > ---------------------------------------------------------------------
> > 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
>
>

Reply via email to