/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" #include "nsIArray.idl" #include "nsISupportsPrimitives.idl" #include "MailNewsTypes2.idl" interface nsIMsgDBHdr; interface nsIRequest; interface nsIStreamListener; interface nsIMsgIncomingServer; interface nsIInputStream; interface nsIMsgCopyServiceListener; interface nsIURI; interface nsIUrlListener; // Forward declarations of callback classes defined later in this file. interface IEwsFolderListener; interface IEwsMessageSyncListener; interface IEwsMessageCreateListener; interface IEwsMessageFetchListener; interface IEwsSimpleOperationListener; interface IEwsFallibleOperationListener; /** * A client for communicating with a Microsoft Exchange server via Exchange Web * Services. * * This interface is intended to provide an abstraction of EWS operations to * bridge the foreign function interface between the components of a Thunderbird * mail protocol implementation and a single implementation of those EWS ops. * * With the exception of initialization, all client operations are intended to * be asynchronous, with implementations of the callback interfaces used to * handle the results of the operations or handle errors. */ [scriptable, uuid(4a117361-653b-48a5-9ddb-588482ef9dbb)] interface IEwsClient : nsISupports { /** * Initializes a new client with the necessary host address and authentication * details to communicate with an Exchange server. * * @param endpoint - The HTTP(S) address of an Exchange server's EWS endpoint. * @param server - An incoming server entity corresponding to an EWS-capable * account. */ void initialize( in AUTF8String endpoint, in nsIMsgIncomingServer server); /** * Checks that the current client configuration is able to connect and * authenticate against an EWS server. * * EWS does not have a dedicated endpoint that can be queried for this, so * instead we test this by attempting to look up the account's root mail * folder, since it results in a fairly small request and represents the first * operation performed when adding the account to Thunderbird. * * @param listener - Listener to communicate the success or failure of the * check. * @returns The client's EWS endpoint's URL. */ nsIURI checkConnectivity(in nsIUrlListener listener); /** * Synchronizes the local folder listing with changes made on the remote * Exchange server. * * @param listener - Listener for communicating changes to the folder list and * to the recorded synchronization state. * @param syncStateToken - A synchronization state token provided by a prior * sync request, or an empty string to indicate that this is the initial * sync. */ void syncFolderHierarchy(in IEwsFolderListener listener, in AUTF8String syncStateToken); /** * Creates a new folder on the Exchange server as a child of the specified * parent. * * @param listener - Listener that propagates the success or failure of the * folder creation operation to the consumer. * @param parentId - The EWS ID of the folder under which to create the new * folder. * @param name - The name to use for the new folder. */ void createFolder(in IEwsSimpleOperationListener listener, in AUTF8String parentId, in AUTF8String name); /** * Synchronizes the local message listing for the given folder with changes * made on the remote Exchange server. * * @param listener - Listener for communicating changes to the message list * and to the recorded synchronization state. * @param folderId - The EWS ID of the folder which message list to * synchronize. * @param syncStateToken - A synchronization state token provided by a prior * sync request, or an empty string to indicate that this is the initial * sync. */ void syncMessagesForFolder(in IEwsMessageSyncListener listener, in AUTF8String folderId, in AUTF8String syncStateToken); /** * Retrieves the content of a message on the Exchange server. * * @param listener - Listener to communicate the operation's state and status, * as well as the message's content, to the consumer. * @param id - The EWS ID of the message to fetch. */ void getMessage(in IEwsMessageFetchListener listener, in AUTF8String id); /** * Changes the read/unread status of one or more messages on the Exchange * server. * * @param messageIds - The EWS IDs of the messages which read/unread status to * change. * @param isRead - The new read/unread state for the message, indicating * whether the message should be marked as read. */ void changeReadStatus(in IEwsSimpleOperationListener listener, in Array messageIds, in boolean isRead); /** * Creates a new message on the server using the data read from the stream. * * @param listener - Listener to indicate operation state and status. * @param folderId - The EWS ID of the folder. * @param isDraft - Whether the message being created is an unsent draft. * @param isRead - Whether the message has already been read. * @param messageStream - The input stream to read the message from. */ void createMessage(in IEwsMessageCreateListener listener, in AUTF8String folderId, in boolean isDraft, in boolean isRead, in nsIInputStream messageStream); /** * Deletes the messages with the given EWS IDs from the server. * * @param listener - Listener to indicate the success or failure of the * message deletion operation. * @param messageEwsIds - The EWS IDs of the messages to delete. */ void deleteMessages(in IEwsSimpleOperationListener listener, in Array messageEwsIds); /** * Deletes the folders with the given EWS IDs from the server. * * @param listener - Listener to indicate the success or failure of the * folder deletion operation. * @param folderIds - The EWS IDs of the folders to delete. */ void deleteFolder(in IEwsSimpleOperationListener listener, in Array folderIds); /** * Renames a folder on the Exchange server. * * @param listener - Listener to indicate the success or failure of the * folder update operation to rename the folder. * @param folderId - The EWS ID of the folder to rename. */ void updateFolder(in IEwsSimpleOperationListener listener, in AUTF8String folderId, in AUTF8String folderName); /** * Moves items on the Exchange server. * * @param listener - Listener to indicate the success or failure of the move * operation. * @param destinationFolderId - The EWS ID of the destination folder. * @param itemIds - A list of the EWS IDs of the items to be moved. */ void moveItems(in IEwsSimpleOperationListener listener, in AUTF8String destinationFolderId, in Array itemIds); /** * Copies items on the Exchange server. * * @param listener - Listener to indicate the success or failure of the copy * operation. * @param destinationFolderId - The EWS ID of the destination folder. * @param itemIds - A list of the EWS IDs of the items to be copied. */ void copyItems(in IEwsSimpleOperationListener listener, in AUTF8String destinationFolderId, in Array itemIds); /** * Moves folders on the Exchange server. * * @param listener - Listener to indicate the success or failure of the move * operation. * @param destinationFolderId - The EWS ID of the destination folder. * @param itemIds - A list of the EWS IDs of the folders to be moved. */ void moveFolders(in IEwsSimpleOperationListener listener, in AUTF8String destinationFolderId, in Array folderIds); /** * Copies folders on the Exchange server. * * @param listener - Listener to indicate the success or failure of the copy * operation. * @param destinationFolderId - The EWS ID of the destination folder. * @param itemIds - A list of the EWS IDs of the folders to be copied. */ void copyFolders(in IEwsSimpleOperationListener listener, in AUTF8String destinationFolderId, in Array folderIds); /** * Mark an item as Junk or not junk. * * @param listener - Callbacks to indicate the success or failure of the operation. * @param itemIds - The EWS IDs for the items to mark as junk or not junk. * @param isJunk - Whether to mark as junk or not junk. * @param legacyDestinationFolderId - The EWS ID as the folder to use as the junk folder for * older versions of Exchange that do not support the `MarkAsJunk` operation. */ void markItemsAsJunk( in IEwsSimpleOperationListener listener, in Array itemIds, in boolean isJunk, in AUTF8String legacyDestinationFolderId); }; [scriptable, uuid(5dacc994-30e0-42f7-94c8-52756638add5)] interface IEwsFolderListener : nsISupports { /** * Called on the first sync when we have requested and received the EWS ID for * the account's root folder. * * The EWS client is responsible for ensuring this is only called in the first * sync. * * @param id - The root folder's EWS ID. */ void onNewRootFolder(in AUTF8String id); /** * Called if a folder has been created on the server. * * This may be called multiple times in a single sync if multiple folders * have been created since the last sync. * * @param id - The new folder's EWS ID. * @param parentId - The EWS ID for the new folder's parent folder. * @param name - The new folder's name. * @param flags - The `nsMsgFolderFlags` for the new folder. */ void onFolderCreated(in AUTF8String id, in AUTF8String parentId, in AUTF8String name, in unsigned long flags); /** * Called if an existing folder has been updated on the server. * * An update can mean the folder has been either renamed or moved to a new * parent. * * This may be called multiple times in a single sync if multiple folders * have been created since the last sync. * * @param id - The folder's EWS ID. * @param parentId - The EWS ID for the folder's parent folder. * @param name - The folder's name. */ void onFolderUpdated(in AUTF8String id, in AUTF8String parentId, in AUTF8String name); /** * Called if an existing folder has been deleted on the server. * * This may be called multiple times in a single sync if multiple folders * have been created since the last sync. * * @param id - The folder's EWS ID. */ void onFolderDeleted(in AUTF8String id); /** * Called after a sync has completed. * * In this context, a sync having completed does not necessarily mean the * client has stopped syncing, because the server might have told it there is * more data to sync than what could be included in one sync. In this case, * the client will sync again (and call this method again). * * @param syncStateToken - The new sync state token to use in future syncs. */ void onSyncStateTokenChanged(in AUTF8String syncStateToken); /** * Called after processing everything there was to sync from the server. * * Unlike `onSyncStateTokenChanged`, this will only be called after all the * necessary sync operations have completed (rather than at the end of each * one). */ void onSuccess(); }; /** * Callbacks used when interacting with an EWS server via an `IEwsClient` in the * context of synchronizing changes to the message list. * * These callbacks allow the `IEwsClient` instance to perform local operation on * the folder that is being synchronized. */ [scriptable, uuid(dec2ddd5-b5a2-4724-bfc7-e5de31840f76)] interface IEwsMessageSyncListener : nsISupports { /** * Called when a new message has been created on the server. * * Implementations are expected to check if a database entry already exists * for the given EWS ID, and return `NS_ERROR_ILLEGAL_VALUE` if so. * * @param ewsId - The EWS ID for the new message. * @returns A detached database entry for the new message. */ nsIMsgDBHdr onMessageCreated(in AUTF8String ewsId); /** * Called when an existing message has been updated on the server. * * Implementations are expected to return `NS_ERROR_NOT_AVAILABLE` if no * database entry exists for the given EWS ID. * * @param ewsId - The EWS ID for the updated message. * @returns An existing (non-detached) database entry for the message. */ nsIMsgDBHdr onMessageUpdated(in AUTF8String ewsId); /** * Called when the read/unread flag was changed for a specific message. * * When a message is marked as read/unread on the EWS server, the EWS server * will represent this either as an `Update` element or `ReadFlagChange` * element (presumably for older versions of Exchange Server) when syncing the * message list. * * If the server represents changes to read/unread flags as `ReadFlagChange`, * then this method will be called, otherwise only `onMessageUpdated` will be * called. * * @param ewsId - The EWS ID for the updated message. * @param IsRead - The new read/unread status for the message. */ void onReadStatusChanged(in AUTF8String ewsId, in boolean isRead); /** * Called when an existing message has been deleted on the server. * * @param ewsId - The EWS ID for the deleted message. */ void onMessageDeleted(in AUTF8String ewsId); /** * Called when a detached database entry has been populated for a new message * and is ready to be persisted. * * @param hdr - The database entry that was populated. */ void onDetachedHdrPopulated(in nsIMsgDBHdr hdr); /** * Called when an existing (non-detached) database entry has been changed, and * the changes are ready to be persisted (i.e. committed). * * Since the database entry is already attached to the relevant message * database, no argument is necessary here. */ void onExistingHdrChanged(); /** * Called after a sync has completed. * * In this context, a sync having completed does not necessarily mean the * client has stopped syncing, because the server might have told it there is * more data to sync than what could be included in one sync. In this case, * the client will sync again (and call this method again). * * @param syncStateToken - The new sync state token to use in future syncs. */ void onSyncStateTokenChanged(in AUTF8String syncStateToken); /** * Called after processing everything there was to sync from the server. * * Unlike `onSyncStateTokenChanged`, this will only be called after all the * necessary sync operations have completed (rather than at the end of each * one). */ void onSyncComplete(); }; /** * A set of callbacks called during the creation of a new message on an Exchange * server. */ [scriptable, uuid(ff45569f-d618-4bb0-9686-6cb24b92b02b)] interface IEwsMessageCreateListener : nsISupports { /** * Inform consumers that the message creation has finished, both on the server * and the relevant local database and message store, with the provided * status. * * This will still be called if `onRemoteCreateSuccessful` is. * * @param status - The status describing the operation's outcome. */ void onStopCreate(in nsresult status); /** * Inform consumers of the key for the newly-created message in the local * message database. * * @param msgKey - The key for the new message. */ void onNewMessageKey(in nsMsgKey msgKey); /** * Signal that the message was correctly created on the server. * * This does not signal the end of the message creation operation (as the * client still has some processing to work through at this point), just the * remote part. * * `nsIMsgDBHdr` is a type quite strongly associated with the message database * and storage, and, going forwards, we'll want to decouple these interfaces * from local storage management. We use currently use it because we don't * have a better way to represent structured headers over the XPCOM boundary, * and parsing RFC822 messages is easier in Rust than using the C++ message * parser. We should revisit our use of `nsIMsgDBHdr` in client code when the * situation improves. * * @param ewsId - The EWS ID of the new message. * @returns A new `nsIMsgDBHdr` object to update with the message's metadata * and to commit to the message database */ nsIMsgDBHdr onRemoteCreateSuccessful(in AUTF8String ewsId); /** * Inform consumers that the provided `nsIMsgDBHdr` has been fully populated * and is ready to be persisted. * * @param hdr - The `nsIMsgDBHdr` that has been populated. */ void onHdrPopulated(in nsIMsgDBHdr hdr); }; /** * A listener used when downloading message content. * * Its shape is loosely based on `nsIStreamListener`, which cannot be used in * this instance because we don't always have a request/channel that can be used * in method calls when fetching a message's content (and using `nullptr` * everywhere is quite ugly and potentially unsafe). */ [scriptable, uuid(027150b1-d127-41a9-8945-18f9374755b3)] interface IEwsMessageFetchListener : nsISupports { void onFetchStart(); void onFetchedDataAvailable(in nsIInputStream inputStream); void onFetchStop(in nsresult status); }; /** * A listener for "simple" operations, which only report a success to the * consumer. */ [scriptable, uuid(0217030b-dcad-4289-914f-48bad6693f2e)] interface IEwsSimpleOperationListener : nsISupports { /** * Signals a successful completion of the EWS operation. * * @param newIds - If the operation involves generating new EWS identifiers * for one or several entities, they are included in this array. Otherwise, * this is an empty array. * @param useLegacyFallback - Whether the client has decided the Exchange * server is too old to perform the operation the "normal" way and we need * to fall back to a "legacy" behaviour. What the normal and legacy * behaviours are, and whether there's even a difference in behaviour * depending on the server version, depends on the specific operation. */ void onOperationSuccess(in Array newIds, in boolean useLegacyFallback); }; /** * A listener for operations which failures we want to report to the consumer. * * This interface will likely not be implemented on its own but be QI'd from an * object of a different type (e.g. `IEwsSimpleOperationListener`). */ [scriptable, uuid(50b04351-609c-4650-b915-81e2b8e209c0)] interface IEwsFallibleOperationListener : nsISupports { /** * Signals an error causing the operation to be aborted. * * @param status - The status describing the error. */ void onOperationFailure(in nsresult status); };