williamr@2: // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). williamr@2: // All rights reserved. williamr@2: // This component and the accompanying materials are made available williamr@4: // under the terms of "Eclipse Public License v1.0" williamr@2: // which accompanies this distribution, and is available williamr@4: // at the URL "http://www.eclipse.org/legal/epl-v10.html". williamr@2: // williamr@2: // Initial Contributors: williamr@2: // Nokia Corporation - initial contribution. williamr@2: // williamr@2: // Contributors: williamr@2: // williamr@2: // Description: williamr@2: // Client MTM for the IMAP4 protocol williamr@2: // williamr@2: // williamr@2: williamr@2: williamr@2: #if !defined (__IMPCMTM_H__) williamr@2: #define __IMPCMTM_H__ williamr@2: williamr@2: #if !defined (__MTCLBASE_H_) williamr@2: #include williamr@2: #endif williamr@2: williamr@2: #if !defined (__MIUTHDR_H_) williamr@2: #include williamr@2: #endif williamr@2: williamr@2: #if !defined (__MIUTPARS_H__) williamr@2: #include //TImMessageField williamr@2: #endif williamr@2: williamr@2: #if !defined (__IMAPSET_H__) williamr@2: #include williamr@2: #endif williamr@2: williamr@2: #if !defined (__IMAPCMDS_H__) williamr@2: #include williamr@2: #endif williamr@2: williamr@2: #if !defined(__OFFOP_H__) williamr@2: #include williamr@2: #endif williamr@2: williamr@2: #if !defined(__MIUTMSG_H__) williamr@2: #include williamr@2: #endif williamr@2: williamr@2: williamr@2: williamr@2: // Forward declarations. williamr@2: class CImap4ClientSessionObserver; williamr@2: class CImImap4GetMail; williamr@2: class CImEmailAutoSend; williamr@2: williamr@4: // williamr@2: // Imap4 Client MTM williamr@2: class CImap4ClientMtm : public CBaseMtm, public MImUndoOffLineOperation williamr@2: williamr@2: /** IMAP4 client MTM interface, providing access to the email services using the IMAP4 williamr@2: protocol. williamr@2: williamr@2: The class provides support for: williamr@2: williamr@2: - connecting to remote IMAP4 mail servers williamr@2: - synchronising message headers with mailboxes on these servers williamr@2: - getting message bodies and attachments williamr@2: - copying and moving messages williamr@2: - creating messages that forward or reply to IMAP4 messages williamr@2: - server notification of new messages using IMAP IDLE williamr@2: - queueing operations requested when there is no connection to a mail server, to be williamr@2: performed when a connection is made (offline operations). williamr@2: williamr@2: Note that CImap4ClientMtm does not support many of the generic functions defined by williamr@2: the @c CBaseMtm base class. In particular: williamr@2: williamr@2: - Message address information, body, subjects, and attachments are not manipulated williamr@2: through CImap4ClientMtm. Consequently, SaveMessageL() has an empty williamr@2: implementation, and is not used. Message access and manipulation is instead done williamr@2: through CImEmailMessage, which understands the email specific message formats, williamr@2: including MHTML (RFC 2557). The RFC 822 email header, which includes subject and williamr@2: address information, is encapsulated in a CImHeader object, which can be obtained from williamr@2: a CImEmailMessage object. IMAP also has its own specific flags, such as draft, williamr@2: answered, and deleted: this can be accessed through TMsvEmailEntry, which extends the williamr@2: message server's generic TMsvEntry to add email-specific information. williamr@2: williamr@2: - The idea of a default service used by base class functions DefaultServiceL(), williamr@2: ChangeDefaultServiceL(), and RemoveDefaultServiceL() is not supported. williamr@2: williamr@2: IMAP specific commands are issued through the InvokeAsyncFunctionL() function, with williamr@2: the commands defined in the #TImap4Cmds enumeration. Details of particular commands williamr@2: are given in the documentation for that enumeration, but the following describes some of williamr@2: the key concepts required to use those commands. Note that usually these commands do williamr@2: not correspond directly to the IMAP protocol commands described in RFC 3501. Instead, williamr@2: they are at a higher level, to simplify the logic required for an email client program. williamr@2: williamr@2: -------------------------------------- williamr@2: williamr@2: Connection and services williamr@2: williamr@2: Settings for connection to and use of an IMAP4 mail server and its mailboxes are williamr@2: encapsulated in an CImImap4Settings object, created and accessed through williamr@2: CEmailAccounts. Preferences for the network connection (e.g. the ISP to use) to be made williamr@2: to access an IMAP server are also accessed through CEmailAccounts. williamr@2: williamr@2: The settings are associated with a service-type entry in the Message Server's message williamr@2: store. Message and folder type entries under the service entry store a local copy of the williamr@2: mailboxes and messages that are present on an IMAP server. For this reason, the service williamr@2: is sometimes referred to as the local mirror of an IMAP server. williamr@2: williamr@2: By default, it is assumed that the user has a primary mailbox on the server called INBOX, williamr@2: though this can be changed if necessary using CImImap4Settings::SetFolderPathL(). (To williamr@2: avoid confusion, the term "Inbox" used in the IMAP MTM documentation refers to this williamr@2: mailbox, rather than the Message Server's standard local Inbox folder.) williamr@2: williamr@2: The settings store the user's log-in details required to access the IMAP server, and other williamr@2: settings not related to connection, but which affect the behaviour of commands, such as williamr@2: synchronisation, made to the service. williamr@2: williamr@2: -------------------------------------- williamr@2: williamr@2: Synchronisation williamr@2: williamr@2: The IMAP4 MTM provides the means to synchronise message headers on a remote williamr@2: IMAP mailboxes with the messages headers on the phone. Note that synchronisation only williamr@2: refers to message headers. Once headers are synchronised, populate operations (i.e. williamr@2: getting the message bodies) can be done. williamr@2: williamr@2: The basic steps involved in a full synchronisation are: williamr@2: williamr@2: - The headers of messages in the Inbox are synchronised. williamr@2: - The local list of folders is synchronised with those existing on the remote IMAP service. williamr@2: Depending on the service settings, the local or remote settings of subscribed mailboxes williamr@2: may be updated (see below for more information). williamr@2: - The headers of messages in subscribed folders are synchronised. williamr@2: williamr@2: Queued offline operations (see below) pending on the Inbox or subscribed folders are williamr@2: performed prior to the relevant folder being synchronised. williamr@2: williamr@2: Synchronisations can be performed in the background or the foreground. A foreground williamr@2: synchronisation means no other requests, such as message fetching, can be made to the williamr@2: MTM, until the synchronisation is complete. A background synchronisation allows some williamr@2: types of command to be given while it is in progress. Commands that write to the remote williamr@2: server are not allowed however while a background synchronisation is in progress. A williamr@2: client is informed of the state of a background synchronisation through the williamr@2: MMsvImapConnectionObserver callback interface. williamr@2: williamr@2: Synchronisations commands are made through williamr@2: CImap4ClientMtm::InvokeAsyncFunctionL(). There a variety of commands available williamr@2: that give different options for compounding synchronisation williamr@2: with other commands, such as connection, and synchronising only particular folders. See williamr@2: TImap4Cmds for details. Progress information for synchronisation commands can be williamr@2: obtained from the CMsvOperation object returned by the InvokeAsyncFunctionL(). williamr@2: Synchronisation progress information is encapsulated in a TImap4SyncProgress object. williamr@2: williamr@2: Settings that affect how a synchronisation is performed include: williamr@2: williamr@2: - Subscriptions: when an IMAP service had been synchronised, the Messaging server will williamr@2: contain entries for all folders on the remote server. These entries will be marked invisible williamr@2: within the TMsvEntry for the folder, implying that they should be invisible to the user. williamr@2: Messages in these folders are not synchronised unless the folder has been subscribed to. williamr@2: Note a folder subscription can be set either locally (i.e. just on the phone), using williamr@2: the #KIMAP4MTMLocalSubscribe command, or remotely (on the server), possibly through email williamr@2: clients on other devices. A service can be set to synchronise folders using either or both williamr@2: of these types of subscription (CImImap4Settings::SetSynchronise()). Local and remote williamr@2: subscriptions can themselves be synchronised in various ways (CImImap4Settings::SetSuscribe()). williamr@2: williamr@2: - Filters: a filter prevents certain e-mail messages from being synchronised onto the williamr@2: device when a client requests a synchronisation. Filters can include anything permitted by williamr@2: the IMAP Search command, including date, size, content, and message flags. williamr@2: williamr@2: - Limits: service settings can limit the number of emails synchronised to the inbox williamr@2: (CImImap4Settings::SetInboxSynchronisationLimit()), and to other folders williamr@2: (CImImap4Settings::SetMailboxSynchronisationLimit()). williamr@2: williamr@2: - Sync rate: one of the synchronisation commands williamr@2: (KIMAP4MTMConnectAndSyncCompleteAfterDisconnect) periodically resynchronises williamr@2: the Inbox until the service is disconnected. CImImap4Settings::SyncRate() sets the williamr@2: refresh period. williamr@2: williamr@2: -------------------------------------- williamr@2: williamr@2: Getting and copying messages williamr@2: williamr@2: After messages headers have been synchronised, message bodies and attachments can be williamr@2: fetched from the remote email server. Getting message parts and saving them in the williamr@2: mirror service is calling populating them. williamr@2: williamr@2: Commands for these actions can be made through williamr@2: CImap4ClientMtm::InvokeAsyncFunctionL(). There are a large number of commands, williamr@2: for different combinations of these options: williamr@2: williamr@2: - action type: whether to just populate messages, or to also copy or move them to a local williamr@2: folder williamr@2: - message selection: whether to get all, new, or selected messages williamr@2: - connection: whether to make a new connection or assume an existing connection williamr@2: - disconnect: whether to disconnect or stay online after operation is complete williamr@2: williamr@2: For the populate type commands, further options can be set that control the message williamr@2: getting behaviour. Basic options control, encapsulated in TImImap4GetMailInfo, specify williamr@2: whether body text and/or attachments are fetched, and a maximum message size. There williamr@2: are also options, encapsulated in TImImap4GetPartialMailInfo, that allow size limits to williamr@2: be separately specified for body text and/or attachments. If the the body is larger than the williamr@2: limit, then the body is partially downloaded up to the limit. Only attachments smaller williamr@2: than the specified size are downloaded. A partially downloaded message can later be williamr@2: fully downloaded. williamr@2: williamr@2: For the copy or move type commands, a TImImap4GetMailInfo parameter is supplied, in williamr@2: order to specify the destination folder for the messages, and a maximum message size. williamr@2: williamr@2: Progress information for getting commands can be obtained from the CMsvOperation williamr@2: object returned by the InvokeAsyncFunctionL(). Progress information is encapsulated in williamr@2: a TImap4GenericProgress object. williamr@2: williamr@2: Fetching and then copying or moving specified messages can also be performed by using williamr@2: the standard Messaging Framework @c CMsvEntry::CopyL() and @c williamr@2: CMsvEntry::MoveL() functions on entries under the remote service. If these functions are williamr@2: used, then the entire message is fetched without size limits. williamr@2: williamr@2: CMsvEntry functions can also be used to: williamr@2: williamr@2: - create a folder on a remote server williamr@2: - delete messages williamr@2: - copy or move messages from a local folder into a remote folder williamr@2: - copy or move messages between remote folders williamr@2: williamr@2: Note that changing an existing entry through CMsvEntry is not supported. An MTM- williamr@2: specific command #KIMAP4MTMRenameFolder is instead provided to rename a remote williamr@2: folder. williamr@2: williamr@2: The page "CMsvEntry functions for IMAP4 message entries", linked to in the "See also" williamr@2: section below, provides more details on using CMsvEntry. williamr@2: williamr@2: -------------------------------------- williamr@2: williamr@2: Offline operations williamr@2: williamr@2: Some operations can only be performed while online, while other commands may williamr@2: be stored while offline for processing when next connected. An attempt to perform a williamr@2: command while offline that requires the MTM to be connected results in immediate williamr@2: completion with the error code KErrDisconnected. williamr@2: williamr@2: Permitted offline operations include: williamr@2: williamr@2: - copy williamr@2: - move williamr@2: - delete williamr@2: williamr@2: Queued offline operations are usually performed when a connection is made, prior to the williamr@2: relevant folder being synchronised. Delete operations can alternatively be set to be done williamr@2: on disconnection using the service setting williamr@2: CImImap4Settings::SetDeleteEmailsWhenDisconnecting(). williamr@2: williamr@2: Note that: williamr@2: - Offline operations are only permitted if the service setting SetDisconnectedUserMode() williamr@2: is true. williamr@2: - It is possible to undo pending offline operations using the commands williamr@2: #KIMAP4MTMCancelOffLineOperations and #KIMAP4MTMUndeleteAll. williamr@2: williamr@2: -------------------------------------- williamr@2: williamr@2: IMAP IDLE support williamr@2: williamr@2: IMAP IDLE (RFC 2177) is an optional expansion of the IMAP email accessing protocol williamr@2: that allows the server to send updates to the client that messages have been created or williamr@2: deleted in real time. The IDLE command is sent from the client to the server when the williamr@2: client is ready to accept unsolicited mailbox update messages. Whether the client requests williamr@2: the server to provide IDLE support is set in the CImImap4Settings::SetImapIdle() service williamr@2: setting. When the IMAP MTM receives such a notification, it synchronises the changed williamr@2: folder. Email clients can be notified of such changes by setting a MMsvEntryObserver williamr@2: observer on a folder. williamr@2: williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: { williamr@2: public: williamr@2: IMPORT_C static CImap4ClientMtm* NewL(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aSession); williamr@2: williamr@2: ~CImap4ClientMtm(); williamr@2: void HandleEntryEvent(TMsvEntryEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3); williamr@2: void StoreL(); // uses a CMsvStore from the Session williamr@2: void RestoreL(); williamr@2: CMsvOperation* ReplyL(TMsvId aDestination, TMsvPartList aPartList, TRequestStatus& aCompletionStatus); williamr@2: CMsvOperation* ForwardL(TMsvId aDestination, TMsvPartList aPartList, TRequestStatus& aCompletionStatus); williamr@2: TUint ValidateMessage(TUint aPartList); williamr@2: TMsvPartList Find(const TDesC& aTextToFind, TMsvPartList aPartList); williamr@2: void SaveMessageL(); williamr@2: void LoadMessageL(); williamr@2: IMPORT_C void StoreSettingsL(); // uses a CMsvStore from the session williamr@2: IMPORT_C void RestoreSettingsL(); williamr@2: williamr@2: // --- RTTI functions --- williamr@2: TInt QueryCapability(TUid aCapability, TInt& aResponse); williamr@2: void InvokeSyncFunctionL(TInt aFunctionId, const CMsvEntrySelection& aSelection, TDes8& aParameter); williamr@2: CMsvOperation* InvokeAsyncFunctionL(TInt aFunctionId, const CMsvEntrySelection& aSelection, TDes8& aParameter, TRequestStatus& aCompletionStatus); williamr@2: // Addressees have no meaning in the text mtm. williamr@2: void AddAddresseeL(const TDesC& aRealAddress); williamr@2: void AddAddresseeL(const TDesC& aRealAddress, const TDesC& aAlias); williamr@2: void RemoveAddressee(TInt aIndex); williamr@2: williamr@2: // Attachment functions to support the SendAs API williamr@2: williamr@2: IMPORT_C virtual void AddAttachmentL(const TDesC& aFilePath, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus); williamr@2: IMPORT_C virtual void AddAttachmentL(RFile& aFile, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus); williamr@2: IMPORT_C virtual void AddLinkedAttachmentL(const TDesC& aFilePath, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus); williamr@2: IMPORT_C virtual void AddEntryAsAttachmentL(TMsvId aAttachmentId, TRequestStatus& aStatus); williamr@2: IMPORT_C virtual void CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus); williamr@2: IMPORT_C void CreateMessageL(TMsvId aServiceId); williamr@2: williamr@2: IMPORT_C virtual TMsvId DefaultServiceL() const; williamr@2: IMPORT_C virtual void RemoveDefaultServiceL(); williamr@2: IMPORT_C virtual void ChangeDefaultServiceL(const TMsvId& aService); williamr@2: williamr@2: public: // Returning a list of all the offline operations for a service entry. williamr@2: IMPORT_C CImOperationQueueList* QueueListL(CMsvEntry& aServiceEntry); williamr@2: public: // Wrapper to settings williamr@2: IMPORT_C const CImImap4Settings& Imap4Settings() const; williamr@2: IMPORT_C void SetImap4SettingsL(const CImImap4Settings& aSettings); williamr@2: public: // inherited from MUndoOffLine williamr@2: virtual void UndoOffLineChangesL(const CImOffLineOperation& aDeleted, TMsvId aFolderId); williamr@2: protected: williamr@2: CImap4ClientMtm(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aSession); williamr@2: void ConstructL(); williamr@2: void ContextEntrySwitched(); // called after the context of this instance has been changed to another entry williamr@2: williamr@2: private: williamr@2: TBool ValidateAddress(const TPtrC& anAddress); williamr@2: void SendOnNextConnectionL(); williamr@2: TMsvPartList DoFindL(const TDesC& aTextToFind, TMsvPartList aPartList); williamr@2: void FilterAllOrNewMailsL(TInt aFunctionId,const CMsvEntrySelection& aSelection,TDes8& aParameter); williamr@2: void FilterMailSelectionL(const CMsvEntrySelection& aSelection,TDes8& aParameter); williamr@2: CMsvOperation* CopyMoveOrPopulateL(TInt aFunctionId,TDes8& aParameter,TRequestStatus& aCompletionStatus); williamr@2: void ConvertToPartialPopulate(TDes8& aParameter); williamr@2: // To check whether a partial fetch or full fetch of message has to be done. williamr@2: TBool IsPartialPopulate(TDes8& aParameter); williamr@2: williamr@2: private: williamr@2: CImImap4Settings iImImap4Settings; williamr@2: TImMessageField iTImMessageField; williamr@2: CImap4ClientSessionObserver* iImap4ClientSessionObserver; williamr@2: HBufC* iEmailAddressFormatString; // defines format of email address used by "Send as" API eg _L("/"%S/" <%S>") williamr@2: CImHeader* iHeader; williamr@2: CMsvEntrySelection* iMsvEntrySelection; williamr@2: CImImap4GetMail* iImIMAP4GetMail; williamr@2: CImEmailOperation* iImEmailOperation; williamr@2: TPckgBuf iImap4GetPartialMailInfo; williamr@2: }; williamr@2: williamr@2: class CImImap4GetMail : public CMsvOperation williamr@2: /** Encapsulates an operation to copy, move, and populate (i.e. download the full williamr@2: message body) IMAP4 emails from the remote inbox to any local folder. williamr@2: williamr@2: Note that the same operations are available by calling CImap4ClientMtm::InvokeAsyncFunctionL() williamr@2: with a suitable command. williamr@2: williamr@2: @publishedAll williamr@2: @released williamr@2: */ williamr@2: { williamr@2: public: williamr@2: IMPORT_C CMsvOperation* GetMailL(TInt aFunctionId, CImap4ClientMtm& aImap4ClientMtm, const CMsvEntrySelection& aMsvEntrySelection, TDes8& aImap4GetMailInfo, TRequestStatus& aObserverRequestStatus); williamr@2: ~CImImap4GetMail(); williamr@2: void DoCancel(); williamr@2: void RunL(); williamr@2: const TDesC8& ProgressL(); williamr@2: const TDesC8& FinalProgress(); williamr@2: private: williamr@2: CImImap4GetMail(CMsvSession& aMsvSession, CImap4ClientMtm& aImap4ClientMtm, TRequestStatus& aObserverRequestStatus); williamr@2: void ConstructL(TInt aFunctionId, const CMsvEntrySelection& aMsvEntrySelection, TDes8& aImap4GetMailInfo); williamr@2: void SelectNextStateL(); // selects next state to go to williamr@2: void ChangeStateL(); // initiates the next state operation williamr@2: void SelectAndChangeToNextStateL(); williamr@2: void RequestComplete(TInt aError); williamr@2: void Complete(); williamr@2: void ConnectToMailboxL(); williamr@2: void CopyMoveNewMessagesL(TBool aCopy); williamr@2: void CopyMoveMessageSelectionL(TBool aCopy); williamr@2: void CopyMoveAllMessagesL(TBool aCopy); williamr@2: void PopulateNewMessagesL(); williamr@2: void PopulateAllMessagesL(); williamr@2: void PopulateMessageSelectionL(); williamr@2: void DisconnectFromMailboxL(); williamr@2: void ResetProgress(); williamr@2: void StoreProgressL(); williamr@2: private: williamr@2: enum TImImap4GetMailState williamr@2: { williamr@2: EConnectToMailbox, williamr@2: ECopyNewMessages, williamr@2: EMoveNewMessages, williamr@2: EPopulateNewMessages, williamr@2: ECopyMessageSelection, williamr@2: EMoveMessageSelection, williamr@2: EPopulateMessageSelection, williamr@2: ECopyAllMessages, williamr@2: EMoveAllMessages, williamr@2: EPopulateAllMessages, williamr@2: EDisconnectFromMailbox, williamr@2: EFinished williamr@2: }; williamr@2: williamr@2: CImap4ClientMtm& iImap4ClientMtm; williamr@2: CMsvEntrySelection* iMsvEntrySelection; williamr@2: CMsvOperation* iMsvOperation; williamr@2: williamr@2: TImap4GenericProgress iProgress; williamr@2: TImap4GenericProgress iErrorProgress; williamr@2: TImImap4GetMailState iState; williamr@2: TInt iCommand; williamr@2: TPckgBuf iProgressBuf; williamr@2: TPckgBuf iImap4GetPartialMailInfo; williamr@2: }; williamr@2: williamr@2: #endif // __IMPCMTM_H__