emailservices/emailstore/base_plugin/src/BasePlugin.cpp
changeset 0 8466d47a6819
child 8 e1b6206813b4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/base_plugin/src/BasePlugin.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,1592 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Email interface implementation.
+*
+*/
+
+
+//MsgStore.
+//<cmail>
+#include "MsgStore.h"
+#include "MsgStoreAccount.h"
+#include "MsgStoreMailBox.h"
+#include "MsgStoreMessage.h"
+#include "MsgStoreFolder.h"
+#include "MsgStorePropertyContainer.h"
+#include "MsgStorePropertyKeys.h"
+#include "MsgStoreSortCriteria.h"
+#include "MsgStoreSortResultIterator.h"
+//Freestyle.
+#include "CFSMailCommon.h"
+#include "CFSMailMessage.h"
+//</cmail>
+//Base plugin.
+#include "BasePlugin.h"
+#include "BasePluginPanic.h"
+#include "baseplugincommonutils.h"
+#include "MailIterator.h"
+#include "baseplugindelayedopsprivate.h"
+// Other
+#include <e32base.h>
+#include <utf.h>
+
+//<cmail>
+#include "FreestyleEmailUiConstants.h"
+//</cmail>
+
+//size of the read buffer when reading body content from the quoted
+//message when replying/forwarding.
+const TInt KQuotedReadBufferSize = 1024*64;
+
+
+/**
+ *
+ */
+CBasePlugin* CBasePlugin::NewLC()
+    {
+    CBasePlugin* api = new (ELeave) CBasePlugin();
+    CleanupStack::PushL( api );
+    api->ConstructL();
+    return api;
+    } 
+
+/**
+ *
+ */
+CBasePlugin* CBasePlugin::NewL()
+   {
+   CBasePlugin* api =  CBasePlugin::NewLC();
+   CleanupStack:: Pop(api);
+   return api;
+   }
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::ConstructL()
+    {
+    __LOG_CONSTRUCT( "baseplugin", "CBasePlugin" )
+
+    __LOG_ENTER( "ConstructL" )
+    iMsgStore = CMsgStore::NewL( EFalse );
+    
+    iDelayedOpsManager = CDelayedOpsManager::NewL( *this );
+
+    __LOG_EXIT
+    }
+
+
+/**
+ *
+ */
+EXPORT_C CBasePlugin::CBasePlugin()
+: iMailboxes( RMap<TInt, CMailboxInfo>::CompareInt )
+   {
+   }
+
+
+/**
+ *
+ */
+EXPORT_C CBasePlugin::~CBasePlugin()
+    {
+    //needs to be first thing to do as it might force execution of operations
+    //that depend on the plugin's current state.
+    delete iDelayedOpsManager;
+    
+    iMailboxes.ResetAndDestroy();
+    iMailboxes.Close();
+
+    if ( iObservers.Count() > 0 )
+        {
+        TRAP_IGNORE( iMsgStore->RemoveObserverL( this ) );
+        }
+    iObservers.Close();
+
+    delete iMsgStore;
+
+    iReqs.ResetAndDestroy();
+    iReqs.Close();
+    
+    ResetCache();
+
+    __LOG_DESTRUCT
+    }
+    
+
+#pragma mark --- "MFSMAILPLUGIN - MAILBOX RELATED" ---
+
+
+/**
+ * Note that as the msgstore performs the delete immediately the observer will get
+ * called from within this method.
+ */
+EXPORT_C void CBasePlugin::DeleteMailBoxByUidL(
+    const TFSMailMsgId& aMailBoxId,
+    MFSMailRequestObserver& aOperationObserver,
+	const TInt aRequestId )
+    {
+    __LOG_ENTER( "DeleteMailBoxByUidL" )
+
+    RPointerArray< CMsgStoreAccount > accounts;
+    iMsgStore->AccountsL( accounts );
+    CleanupResetAndDestroyClosePushL( accounts );
+
+    TFSProgress progress = { TFSProgress::EFSStatus_RequestCancelled, 0, 0, 0 };
+    progress.iError = KErrNotFound;
+
+    TInt count = accounts.Count();
+    for( TInt i = 0; i < count; i++ )
+        {
+        CMsgStoreMailBox* msbox = iMsgStore->OpenAccountL( *accounts[i] );
+        CleanupStack::PushL( msbox );
+      
+        if( aMailBoxId.Id() == msbox->Id() )
+            {
+            __LOG_WRITE_INFO( "Found, about to start the delete.." )
+
+            //remove from the cache.
+            if ( KErrNotFound != iMailboxes.Find( msbox->Id() ) )
+                {
+                iMailboxes.RemoveL( msbox->Id() );
+                }
+            
+            iMsgStore->DeleteAccountL( *accounts[i] );
+            CleanupStack::PopAndDestroy( msbox );
+            
+            progress.iError = KErrNone;
+            progress.iProgressStatus = TFSProgress::EFSStatus_RequestComplete;
+            
+            __LOG_WRITE_INFO( "Delete complete." )
+            break;
+            }
+      
+        CleanupStack::PopAndDestroy( msbox );
+        }
+
+    CleanupStack::PopAndDestroy( &accounts );
+
+    aOperationObserver.RequestResponseL( progress, aRequestId );
+    __LOG_EXIT
+    }
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::ListMailBoxesL( RArray<TFSMailMsgId>& aMailboxes )
+    {
+    __LOG_ENTER( "ListMailBoxesL" )
+    
+    RPointerArray< CMsgStoreAccount > accounts;
+    iMsgStore->AccountsL( accounts );
+    CleanupResetAndDestroyClosePushL( accounts );
+
+    TFSMailMsgId fsid;
+    fsid.SetPluginId( TUid::Uid( GetPluginId() ) );
+    
+    __LOG_WRITE_FORMAT1_INFO( "Plugin id: 0x%X,", GetPluginId() )
+    
+    TInt count = accounts.Count();
+    for ( TInt i = 0; i < count; i++ )
+        {
+        __LOG_WRITE_FORMAT1_INFO( "Owner id: 0x%X,", accounts[i]->Owner() )
+        
+        if ( accounts[i]->Owner() == GetPluginId() )
+            {
+            CMsgStoreMailBox* msbox = iMsgStore->OpenAccountL( *accounts[i] );
+            CleanupStack::PushL( msbox );
+
+            fsid.SetId( msbox->Id() );
+            aMailboxes.AppendL( fsid );
+        
+            __LOG_WRITE_FORMAT1_INFO( "Found mailbox with id of 0x%X,", msbox->Id() )
+            __LOG_WRITE_FORMAT1_INFO( "and account name of %S.", &accounts[i]->Name() )
+
+            CleanupStack::PopAndDestroy( msbox );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( &accounts );
+    __LOG_EXIT
+    }
+
+
+/**
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C CFSMailBox* CBasePlugin::GetMailBoxByUidL( const TFSMailMsgId& aMailBox )
+    {
+    __LOG_ENTER( "GetMailBoxByUidL" )
+
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBox.Id() );
+    
+    CFSMailBox* result = CFSMailBox::NewL( aMailBox );
+    CleanupStack::PushL( result ); 
+
+    CFSMailAddress* ownMailBox = CFSMailAddress::NewLC();
+    ownMailBox->SetEmailAddress( *mailBox.iMailBoxName );
+    
+    if ( !( mailBox.iMailBoxDisplayName->Length() ) )
+        {
+        ownMailBox->SetDisplayName( KNullDesC );
+        result->SetName( *mailBox.iMailBoxName );
+        }
+    else
+        {
+        ownMailBox->SetDisplayName( *(mailBox.iMailBoxDisplayName) );
+        result->SetName( *(mailBox.iMailBoxDisplayName) );
+        }
+        
+    result->SetOwnMailAddressL( ownMailBox );
+    
+    CleanupStack::Pop( ownMailBox );
+
+    MMRInfoProcessor* infoProcessor = CBaseMrInfoProcessor::NewL( *this );
+    result->SetMRInfoProcessorL( infoProcessor );
+    
+    CleanupStack::Pop( result );
+    
+    __LOG_EXIT
+    return result;
+    }
+
+
+#pragma mark --- "MFSMAILPLUGIN - FOLDER RELATED" ---
+
+/**
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C TFSMailMsgId CBasePlugin::GetStandardFolderIdL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSFolderType aFolderType )
+    
+    {
+    __LOG_ENTER( "GetStandardFolderIdL" )
+    
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId.Id() );
+    
+    TFSMailMsgId result;
+    result.SetPluginId( TUid::Uid( GetPluginId() ) );
+    
+    if( EFSInbox <= aFolderType && aFolderType <= EFSDeleted )
+        {
+        result.SetId( mailBox.iRootFolders.iFolders[ aFolderType ] );
+        }
+
+    __LOG_EXIT
+    return result;
+    }
+
+
+/**
+ * Note that the unseen count is not set by the plugin as this information is not
+ * readily available.
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C CFSMailFolder* CBasePlugin::GetFolderByUidL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& aFolderId )
+
+    {
+    __LOG_ENTER( "GetFolderByUidL" )
+    
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId.Id() );
+
+    TUint totalCount, unreadCount;
+    mailBox().MessageCountsL( aFolderId.Id(), totalCount, unreadCount );
+
+    //prepare the fsfw folder.
+    CFSMailFolder* result = CFSMailFolder::NewLC( aFolderId );
+
+    result->SetMailBoxId( aMailBoxId );
+    result->SetMessageCount( totalCount );
+    result->SetUnreadCount( unreadCount );
+
+    //get the folder name from the msgstore folder object.
+    __LOG_WRITE_INFO( "About to get the folder's name." )
+    CMsgStoreFolder* msgStoreFolder = mailBox().FolderL( aFolderId.Id() );
+    CleanupStack::PushL( msgStoreFolder );
+
+    TUint idx;
+    if ( msgStoreFolder->FindProperty( KMsgStorePropertyFolderDisplayName, idx ) )
+        {
+        const TDesC& name = msgStoreFolder->PropertyValueDesL( idx );
+        result->SetFolderName( const_cast<TDesC&>( name ) );
+        }
+    else
+        {
+        //the root folders will get names from the UI. the base plugin should not
+        //deal with any localization.
+        result->SetFolderName( KNullDesC() );
+        }
+
+    TFSFolderType folderType = EFSOther;
+    TUint i = 0;
+    if ( msgStoreFolder->FindProperty( KMsgStorePropertyFolderType, i ) )
+        {
+        __LOG_WRITE_INFO( "Getting the folder's type." )
+        folderType = (TFSFolderType)( msgStoreFolder->PropertyValueUint32L( i ) );
+        result->SetFolderType( folderType );
+        }
+
+    TFSMailMsgId parentId( GetPluginId(), msgStoreFolder->ParentId() );
+    result->SetParentFolderId( parentId );
+    CleanupStack::PopAndDestroy( msgStoreFolder );
+
+    RPointerArray<CMsgStoreFolder> folders;
+    CleanupResetAndDestroyClosePushL( folders );
+    
+    mailBox().FoldersL( aFolderId.Id(), folders );
+    result->SetSubFolderCount( folders.Count() );
+    
+    BlockCopyMoveFromFoldersL( aFolderId, folderType, *result );
+
+    CleanupStack::PopAndDestroy( &folders );
+    CleanupStack::Pop( result );
+
+    __LOG_EXIT
+    return result;
+    } //GetFolderByUidL.
+
+
+/**
+ * @param aFolderId parent folder id.
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ * @return if the folder already exists returns the existing one.
+ */
+EXPORT_C CFSMailFolder* CBasePlugin::CreateFolderL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& aParentFolderId,
+    const TDesC& aFolderName,
+    const TBool aSync )
+
+    {
+    __LOG_ENTER( "CreateFolderL" )
+    
+    CMailboxInfo& mailboxInfo = GetMailboxInfoL( aMailBoxId.Id() );
+
+    CMsgStorePropertyContainer* props = CMsgStorePropertyContainer::NewL();
+    CleanupStack::PushL( props );
+
+    props->AddPropertyL( KMsgStorePropertyName, aFolderName );
+    props->AddPropertyL( KMsgStorePropertyFolderType, EMsgStoreOther );
+
+    TMsgStoreId parent = aParentFolderId.Id();
+    TMsgStoreId folderId =
+        mailboxInfo().CreateFolderL( parent, *props, aSync );
+    CleanupStack::PopAndDestroy( props );
+
+    //return the FS folder.
+    TFSMailMsgId fid( GetPluginId(), folderId );
+
+    CFSMailFolder* result = CFSMailFolder::NewLC( fid );
+
+    result->SetParentFolderId( aParentFolderId );
+    result->SetFolderName( aFolderName );
+
+    result->SetMailBoxId( aMailBoxId );
+    result->SetMessageCount( 0 );
+    result->SetUnreadCount( 0 );
+
+    BlockCopyMoveFromFoldersL( fid, EFSOther, *result );
+    
+    CleanupStack::Pop( result );
+    __LOG_EXIT
+    return result;
+    }
+
+
+/**
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C void CBasePlugin::DeleteFolderByUidL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& aFolder )
+    
+    {
+    __LOG_ENTER( "DeleteFolderByUidL" )
+
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId.Id() );
+    mailBox().DeleteFolderL( aFolder.Id() );
+    
+    __LOG_EXIT
+    }
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::ListFoldersL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& aFolderId,
+    RPointerArray<CFSMailFolder>& aFolderList )
+    
+    {
+    __LOG_ENTER( "ListFoldersL, aFolderId" )
+    
+    TMsgStoreId folderId;
+    if ( 0 == aFolderId.Id() )
+    	{
+    	folderId = aMailBoxId.Id();
+    	}
+    else
+    	{
+    	folderId = aFolderId.Id();
+    	}
+    
+	DoListFoldersL( aMailBoxId, folderId, EFalse, aFolderList );
+    __LOG_EXIT 
+    }
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::ListFoldersL(
+    const TFSMailMsgId& aMailBoxId,
+    RPointerArray<CFSMailFolder>& aFolderList )
+    
+    {
+    __LOG_ENTER( "ListFoldersL" )
+    DoListFoldersL( aMailBoxId, KMsgStoreInvalidId, ETrue, aFolderList );
+    __LOG_EXIT
+    }
+
+
+#pragma mark --- "MFSMAILPLUGIN - MESSAGE RELATED" ---
+
+
+/**
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C MFSMailIterator* CBasePlugin::ListMessagesL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& aFolderId,
+    const TFSMailDetails aDetails,
+    const RArray<TFSMailSortCriteria>& aSorting )
+   
+    {
+    __LOG_ENTER( "ListMessagesL" )
+    
+    CMailboxInfo& mailbox = GetMailboxInfoL( aMailBoxId.Id() );
+    
+    RMsgStoreSortCriteria criteria;
+    CleanupClosePushL( criteria );
+ 
+    criteria.iFolderId = aFolderId.Id();
+    if( aSorting.Count() > 0 )
+        {
+        criteria.iSortBy = static_cast<TMsgStoreSortByField>( aSorting[0].iField - 1);
+        criteria.iSortOrder = static_cast<TMsgStoreSortOrder>( aSorting[0].iOrder );
+        criteria.iSecondarySortOrder = EMsgStoreSortDescending;
+        }
+    else
+        {
+        __LOG_WRITE_INFO( "No sorting criteria supplied, falling back to the default." )
+        criteria.iSortBy = EMsgStoreSortByReceivedDate;
+        criteria.iSortOrder = EMsgStoreSortDescending;
+        }
+    
+    //determine the details to request from the msgstore.
+    if ( EFSMsgDataStructure & aDetails || EFSMsgDataEnvelope & aDetails
+        || EFSMsgDataSubject & aDetails )
+        {
+        criteria.AddResultPropertyL( KMsgStorePropertySubject );
+        }
+
+    if ( EFSMsgDataStructure & aDetails || EFSMsgDataEnvelope & aDetails
+        || EFSMsgDataDate & aDetails )
+        {
+        criteria.AddResultPropertyL( KMsgStorePropertyReceivedAt );
+        criteria.AddResultPropertyL( KMsgStorePropertySent );
+        }
+
+    if ( EFSMsgDataStructure & aDetails || EFSMsgDataEnvelope & aDetails
+        || EFSMsgDataSender & aDetails )
+        {
+        criteria.AddResultPropertyL( KMsgStorePropertyFrom );
+        }
+    
+    if ( EFSMsgDataStructure & aDetails || EFSMsgDataEnvelope & aDetails
+        || EFSMsgDataIdOnly & aDetails )
+        {
+        /**@ no result properties added means the msgstore leaves with -6; ask
+        about it because EFSMsgDataIdOnly means id-only.*/
+        criteria.AddResultPropertyL( KMsgStorePropertyTo );
+        }
+
+    if ( EFSMsgDataStructure & aDetails || EFSMsgDataEnvelope & aDetails )
+        {
+        criteria.AddResultPropertyL( KMsgStorePropertyFlags );
+        criteria.AddResultPropertyL( KMsgStorePropertySize );
+        criteria.AddResultPropertyL( KMsgStorePropertyCc );
+        criteria.AddResultPropertyL( KMsgStorePropertyBcc );
+        }
+
+    CMsgStoreSortResultIterator* msIter = mailbox().SortL( criteria );
+    CleanupStack::PopAndDestroy( &criteria );
+
+    CleanupStack::PushL( msIter );
+    HMailIterator* result = new (ELeave) HMailIterator( *this, msIter, aMailBoxId );
+    CleanupStack::Pop( msIter );
+    
+    __LOG_EXIT
+    return result;
+    }
+
+/**
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C CFSMailMessage* CBasePlugin::GetMessageByUidL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& /*aFolderId*/,
+    const TFSMailMsgId& aMessageId,
+    const TFSMailDetails aDetails )
+    
+    {
+    __LOG_ENTER( "GetMessageByUidL" )
+    
+    CMsgStoreMessage* message = GetCachedMsgL( aMailBoxId.Id(), aMessageId.Id() );
+
+    CFSMailMessage* result = CFSMailMessage::NewLC( aMessageId );
+    TranslateMsgStorePropsL( aMailBoxId, *message, *result, aDetails );
+    result->SetMailBoxId( aMailBoxId );
+    CleanupStack::Pop( result );
+
+    __LOG_EXIT
+    return result;
+    }
+
+
+/**
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C void CBasePlugin::DeleteMessagesByUidL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& aFolderId,
+    const RArray<TFSMailMsgId>& aMessages )
+    
+    {
+    __LOG_ENTER( "DeleteMessagesByUidL" )
+
+    CDelayedDeleteMessagesOp* delayedOp = CDelayedDeleteMessagesOp::NewLC(
+        aMailBoxId.Id(), aFolderId.Id(), aMessages );
+    iDelayedOpsManager->EnqueueOpL( delayedOp );
+    CleanupStack::Pop( delayedOp );
+
+    __LOG_EXIT
+    }
+
+
+/**
+ * Drafts folder assumed.
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C CFSMailMessage* CBasePlugin::CreateMessageToSendL(
+    const TFSMailMsgId& aMailBox )
+    
+    {
+    __LOG_ENTER( "CreateMessageToSendL" )
+    
+    CMailboxInfo& mailboxInfo = GetMailboxInfoL( aMailBox.Id() );
+
+    CMsgStorePropertyContainer* props = CMsgStorePropertyContainer::NewL();
+    CleanupStack::PushL( props );
+    props->AddOrUpdatePropertyL( KMsgStorePropertyContentType, KFSMailContentTypeMultipartMixed );
+
+    // Set reply-to address, if it exists
+    HBufC* replyToAddressString = GetReplyToAddressL( aMailBox );
+    
+    if ( NULL != replyToAddressString )
+        {
+        CleanupStack::PushL( replyToAddressString );
+        
+        if ( replyToAddressString->Length() > 0 )
+            {
+            RMsgStoreAddress replyToAddress;
+            CleanupClosePushL( replyToAddress );
+            
+            replyToAddress.iEmailAddress.Create( *replyToAddressString );
+            replyToAddress.iDisplayName.Create( KNullDesC );
+            
+            props->AddOrUpdatePropertyL( KMsgStorePropertyReplyTo, replyToAddress );
+            
+            CleanupStack::PopAndDestroy( &replyToAddress );
+            }        
+        CleanupStack::PopAndDestroy( replyToAddressString );
+        }
+    
+    CMsgStoreMessage* message = mailboxInfo().CreateMessageL(
+        mailboxInfo.iRootFolders.iFolders[EFSDraftsFolder], *props );
+
+    CleanupStack::PopAndDestroy( props );
+    CleanupStack::PushL( message );
+    
+    //create the body part.
+    props = CMsgStorePropertyContainer::NewL();
+    CleanupStack::PushL( props );
+    
+    props->AddOrUpdatePropertyL(
+        KMsgStorePropertyContentType, KFSMailContentTypeMultipartAlternative );
+    CMsgStoreMessagePart* bodyPart = message->AddChildPartL( *props );
+    
+    CleanupStack::PopAndDestroy( props );
+    CleanupStack::PushL( bodyPart );
+    
+    //create the plain text part.
+    props = CMsgStorePropertyContainer::NewL();
+    CleanupStack::PushL( props );
+
+    props->AddPropertyL(
+        KMsgStorePropertyContentType, KFSMailContentTypeTextPlain );
+
+    _LIT(KMessageBodyCharset, "UTF-8");
+    props->AddPropertyL( KMsgStorePropertyCharset, KMessageBodyCharset );
+
+    _LIT(KMessageBodyDisposition, "inline");
+    props->AddPropertyL(
+        KMsgStorePropertyContentDisposition, KMessageBodyDisposition );
+
+    HBufC* signature = GetSignatureL( aMailBox );
+    if ( signature )
+        {
+        CleanupStack::PushL( signature );       
+
+        props->AddPropertyL(
+            KMsgStorePropertySize, static_cast<TUint32>( signature->Length() ) );
+        props->AddPropertyL(
+            KMsgStorePropertyRetrievedSize,
+            static_cast<TUint32>( signature->Length() ) );
+        }
+    
+    CMsgStoreMessagePart* textPlain = bodyPart->AddChildPartL( *props );
+    if ( signature )
+        {
+        CleanupStack::Pop( signature );
+        }
+    CleanupStack::PopAndDestroy( props );           
+    if ( signature )
+        {
+        CleanupStack::PushL( signature );
+        }
+    CleanupStack::PushL( textPlain );
+    
+    //add signature, if it exists
+	if ( NULL != signature && signature->Length() )
+        {
+        TPtrC8 ptr8(
+            reinterpret_cast<const TUint8*>( signature->Ptr() ),
+            signature->Size() );
+        
+        textPlain->ReplaceContentL( ptr8 );
+		}
+
+	CleanupStack::PopAndDestroy( textPlain );
+    if ( signature )
+        {
+        CleanupStack::PopAndDestroy( signature );
+        }
+    CleanupStack::PopAndDestroy( bodyPart );
+	
+	//done.
+    message->CommitL();
+    
+    TFSMailMsgId folderId( GetPluginId(), message->ParentId() );
+    TFSMailMsgId msgId( GetPluginId(), message->Id() );
+    CleanupStack::PopAndDestroy( message );
+
+    CFSMailMessage* result = CFSMailMessage::NewL( msgId );    
+    
+    result->SetMailBoxId( aMailBox );
+    result->SetFolderId( folderId );
+    result->SetContentType( KFSMailContentTypeMultipartMixed );
+    
+    __LOG_EXIT
+    return result;
+    }
+
+
+/**
+ *
+ */
+EXPORT_C CFSMailMessage* CBasePlugin::CreateForwardMessageL(
+    const TFSMailMsgId& aMailBox,
+    const TFSMailMsgId& aOriginal,
+    const TDesC& aHeaderDescriptor )
+    {
+    return CreateForwardReplyMessageL( aMailBox, aOriginal, EFalse, aHeaderDescriptor, ETrue );
+    }
+
+
+/**
+ * Relying on the UI for the subject and recipients.
+ */
+EXPORT_C CFSMailMessage* CBasePlugin::CreateReplyMessageL(
+    const TFSMailMsgId& aMailBoxId,
+    const TFSMailMsgId& aOriginalMessageId,
+    const TBool aReplyToAll,
+    const TDesC& aHeaderDescriptor )
+    {
+    return CreateForwardReplyMessageL( aMailBoxId, aOriginalMessageId, aReplyToAll, aHeaderDescriptor, EFalse );
+    }
+
+
+/**
+ *
+ */
+EXPORT_C CFSMailMessage* CBasePlugin::CreateMrReplyMessageL(
+    const TFSMailMsgId& aMailBoxId,
+    MMRInfoObject& /*aMeetingRequest*/,
+    const TFSMailMsgId& aOriginalMessageId )
+    {
+    return CreateReplyMessageL( aMailBoxId, aOriginalMessageId, EFalse, KNullDesC );
+    }
+
+
+/**
+ *
+ * @param aMailBoxId if not found leaves with KErrNotFound.
+ */
+EXPORT_C void CBasePlugin::StoreMessageL(
+    const TFSMailMsgId& aMailBoxId,
+    CFSMailMessage& aMessage )
+    
+    {
+    __LOG_ENTER( "StoreMessageL" )
+    
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId.Id() );
+
+    CMsgStoreMessage* message = mailBox().FetchMessageL(
+        aMessage.GetMessageId().Id(), KMsgStoreInvalidId );
+    CleanupStack::PushL( message );
+
+    //determine whether the message is in the inbox folder or some of its
+    //children; the translation is different for inbox and all the other folders.
+    TBool inInbox = EFalse;
+    TMsgStoreId parentId = message->ParentId();
+    while ( KMsgStoreInvalidId != parentId
+    	&& EMsgStoreFolderContainer == mailBox().ContainerTypeById( parentId ) )
+    	{
+    	if ( parentId == mailBox.iRootFolders.iFolders[EFSInbox] )
+    		{
+    		inInbox = ETrue;
+    		break;
+    		}
+    	else
+    		{
+    		CMsgStoreFolder* parent = mailBox().FolderL( parentId );
+    		parentId = parent->ParentId();
+    		delete parent;
+    		}
+    	}
+    
+    TranslateEmailFwMessageL( aMessage, *message, inInbox );
+    message->StorePropertiesL();
+    
+    CleanupStack::PopAndDestroy( message );
+    
+    ResetCache();
+    __LOG_EXIT
+    }
+
+
+/**
+ * Async operation, starts fetching.
+ * @param aRequestId
+ */
+EXPORT_C void CBasePlugin::FetchMessagesL(
+    const TFSMailMsgId& /*aMailBox*/,
+    const TFSMailMsgId& /*aFolder*/,
+    const RArray<TFSMailMsgId>& /*aMessageIds*/,
+    TFSMailDetails /*aDetails*/,
+    MFSMailRequestObserver& /*aObserver*/,
+    TInt /*aRequestId*/ )
+
+    {
+    /**@ is this really necessary for the base plugin ?*/
+    }
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::GetMessagesL(
+    const TFSMailMsgId& /*aMailBoxId*/,
+    const TFSMailMsgId& /*aParentFolderId*/,
+    const RArray<TFSMailMsgId>& /*aMessageIds*/,
+    RPointerArray<CFSMailMessage>& /*aMessageList*/,
+    const TFSMailDetails /*aDetails*/ )
+    
+    {
+    /**@ is this really necessary for the base plugin ?*/
+    }
+
+
+/**
+ * CFSMailPlugin::SendMessageL
+ */
+EXPORT_C void CBasePlugin::SendMessageL( CFSMailMessage& aMessage )    
+    {
+    __LOG_ENTER( "SendMessageL1" )
+
+    TMsgStoreId mailBoxId = aMessage.GetMailBoxId().Id();
+    TMsgStoreId msgId = aMessage.GetMessageId().Id();
+    
+    CMsgStoreMessage* message = GetCachedMsgL( mailBoxId, msgId );
+    __LOG_WRITE8_FORMAT1_INFO( "Fetched message : 0x%X.", msgId )
+
+    TranslateEmailFwMessageL( aMessage, *message, EFalse );
+    //the sendmessagel will store the message's properties!
+
+    TTime sentTime;
+    sentTime.UniversalTime();
+    aMessage.SetDate( sentTime );
+
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMessage.GetMailBoxId().Id() );
+    SendMessageL( mailBox(), *message, sentTime );
+
+    __LOG_EXIT
+    }
+
+
+/**
+ * Plugin could use this method to "send" a message if the CFSMailPlugin's is
+ * not necessary. The method also stores the message properties before doing so.
+ * This allows for optimizing away of unnecessary writes to the msgstore.
+ * @param aSentTime the sent time you want set for the message.
+ */
+EXPORT_C void CBasePlugin::SendMessageL(
+    CMsgStoreMailBox& aMailBox,
+    CMsgStoreMessage& aMsg,
+    const TTime& aSentTime )    
+    {
+    __LOG_ENTER( "SendMessageL2" )
+
+    //set the sent stamp.
+    aMsg.AddOrUpdatePropertyL( KMsgStorePropertySent, aSentTime );
+    // Due to no Received Time in the sent messages, it caused sorting problem
+    // from MsgStore
+    aMsg.AddOrUpdatePropertyL( KMsgStorePropertyReceivedAt, aSentTime );
+    aMsg.StorePropertiesL();
+
+    // move the msg to the outbox.
+    TFSMailMsgId id( GetPluginId(), aMailBox.Id() );
+    TFSMailMsgId drafts = GetStandardFolderIdL( id, EFSDraftsFolder );
+    TFSMailMsgId outbox = GetStandardFolderIdL( id, EFSOutbox );
+
+    aMailBox.CopyMessageL( aMsg.Id(), drafts.Id(), outbox.Id() );
+    
+    CDelayedDeleteMessagesOp* delayedOp = CDelayedDeleteMessagesOp::NewLC(
+        aMailBox.Id(), KMsgStoreInvalidId, aMsg.Id() );
+    iDelayedOpsManager->EnqueueOpL( delayedOp );
+    CleanupStack::Pop( delayedOp );
+
+    __LOG_EXIT
+    }
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::MoveMessagesL(
+    const TFSMailMsgId& aMailBoxId,
+    const RArray<TFSMailMsgId>& aMessageIds,
+    const TFSMailMsgId& aSourceFolderId,
+    const TFSMailMsgId& aDestinationFolderId )
+
+    {
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId.Id() );
+
+    TInt count = aMessageIds.Count();
+    for ( TUint i = 0; i < count; i++ )
+        {
+        mailBox().MoveMessageL(
+            aMessageIds[i].Id(),
+            aSourceFolderId.Id(),
+            aDestinationFolderId.Id() );
+        }    
+    }
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::CopyMessagesL(
+    const TFSMailMsgId& aMailBoxId,
+    const RArray<TFSMailMsgId>& aMessageIds,
+    RArray<TFSMailMsgId>& aNewMessages,
+    const TFSMailMsgId& aSourceFolderId,
+    const TFSMailMsgId& aDestinationFolderId )
+
+    {
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId.Id() );
+
+    TFSMailMsgId newId( GetPluginId(), KMsgStoreInvalidId );
+    
+    TInt count = aMessageIds.Count();
+    for ( TUint i = 0; i < count; i++ )
+        {
+        TMsgStoreId msgStoreId = mailBox().CopyMessageL(
+            aMessageIds[i].Id(),
+            aSourceFolderId.Id(),
+            aDestinationFolderId.Id() );
+        
+        newId.SetId( msgStoreId );
+        aNewMessages.AppendL( newId );
+        }
+    }
+
+
+#pragma mark --- "Plugin Helpers" ---
+
+
+/**
+ * Get the MsgStore mailbox instance for the specified FSEF mailbox id.
+ *
+ * @param aId mailbox id, if none can be found leaves with KErrNotFound.
+ */
+EXPORT_C CMailboxInfo& CBasePlugin::GetMailboxInfoL(
+    TMsgStoreId aId )
+    {
+    
+    __ASSERT_DEBUG( NULL != iMsgStore, ::BasePluginPanic( ENoMsgStoreSessionAssert ) );
+    
+    //if not present in the cache, add it.
+    if ( !iMailboxes.ContainsKey(aId) )
+        {
+        RPointerArray< CMsgStoreAccount > accounts;
+        iMsgStore->AccountsL( accounts );
+        CleanupResetAndDestroyClosePushL( accounts );
+
+        TBool found = EFalse;
+
+        TInt count = accounts.Count();
+        for ( TInt i = 0; i < count; i++ )
+            {
+            CMsgStoreMailBox* msbox = iMsgStore->OpenAccountL( *accounts[i] );
+            CleanupStack::PushL( msbox );
+
+            if ( aId == msbox->Id() )
+                {
+                CMailboxInfo* mailBox = new (ELeave) CMailboxInfo( this );
+                CleanupStack::PushL( mailBox );
+                mailBox->iMailBox = msbox;
+                //always observe for mailbox changes to keep the cache
+                //up-to-date.
+                mailBox->iMailBox->AddObserverL( this );
+
+                mailBox->iMailBoxName = accounts[i]->Name().AllocL();
+                mailBox->iBrandingId = KNullDesC().AllocL();
+                
+                RBuf mailboxDisplayName;
+                mailboxDisplayName.CleanupClosePushL();
+                GetMailboxDisplayNameL( aId, mailboxDisplayName );
+                mailBox->iMailBoxDisplayName = mailboxDisplayName.AllocL();
+                CleanupStack::PopAndDestroy( &mailboxDisplayName );
+                
+                MsgStoreFolderUtils::GetRootFoldersL( *msbox, mailBox->iRootFolders );
+
+                TInt64* key = new (ELeave) TInt64( msbox->Id() );
+                CleanupDeletePushL( key );
+                iMailboxes.InsertL( key, mailBox );   //the map owns the memory.
+
+                CleanupStack::Pop( key );
+                CleanupStack::Pop( mailBox );
+                CleanupStack::Pop( msbox );
+                
+                found = ETrue;
+                break;
+                }
+
+            CleanupStack::PopAndDestroy( msbox );
+            }
+
+        CleanupStack::PopAndDestroy( &accounts );
+        
+        if( !found )
+            {
+            User::Leave( KErrNotFound );
+            }
+        }
+    
+    return iMailboxes.GetValueL( aId );
+    } //GetMailboxInfoL.
+
+
+/**
+ * Get the MsgStore mailbox instance for the specified FSEF mailbox id.
+ *
+ * @param aId mailbox id, if none can be found leaves with KErrNotFound.
+ */
+void CBasePlugin::GetMailboxDisplayNameL(
+    TMsgStoreId aId,
+    RBuf& aDisplayName )
+    {
+    
+    __ASSERT_DEBUG( NULL != iMsgStore, ::BasePluginPanic( ENoMsgStoreSessionAssert ) );
+    
+    RPointerArray< CMsgStoreAccount > accounts;
+    iMsgStore->AccountsL( accounts );
+    CleanupResetAndDestroyClosePushL( accounts );
+
+    TInt count = accounts.Count();
+    for ( TInt i = 0; i < count; i++ )
+        {
+        CMsgStoreMailBox* msbox = iMsgStore->OpenAccountL( *accounts[i] );
+        CleanupStack::PushL( msbox );
+
+        if( aId == msbox->Id() )
+            {
+            TUint index = 0;
+            if ( msbox->FindProperty( KMsgStorePropertyName, index ) )
+                {
+                    const TDesC& string = msbox->PropertyValueDesL( index );
+                    if (string.Length() > 0)
+                        {
+                        aDisplayName.Close();
+                        aDisplayName.CreateL( string );
+                        }
+                }
+                CleanupStack::PopAndDestroy( msbox );
+                break;
+            }
+        else
+            {
+	             CleanupStack::PopAndDestroy( msbox );
+	        }
+        }
+
+        CleanupStack::PopAndDestroy( &accounts );
+    } //GetMailboxDisplayNameL.
+
+/**
+ * @param aFolderId if set to KMsgStoreInvalidId makes a recursive list.
+ */
+void CBasePlugin::DoListFoldersL(
+    TFSMailMsgId aMailBoxId,
+    TMsgStoreId aFolderId,
+    TBool aRecursive,
+    RPointerArray<CFSMailFolder>& aFolderList )
+    
+    {
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId.Id() );
+    
+    RPointerArray<CMsgStoreFolder> folders;
+    CleanupResetAndDestroyClosePushL( folders );
+    
+    if ( aRecursive )
+        {
+        mailBox().FoldersL( folders );
+        }
+    else
+        {
+        mailBox().FoldersL( aFolderId, folders );
+        }
+    
+    TFSMailMsgId folderId;
+    folderId.SetPluginId( TUid::Uid( GetPluginId() ) );
+    
+    TInt count = folders.Count();
+    for( TInt i = 0; i < count; i++ )
+        {
+        folderId.SetId( folders[i]->Id() );
+        
+        CFSMailFolder* folder = GetFolderByUidL( aMailBoxId, folderId );
+
+        CleanupStack::PushL( folder );
+        aFolderList.AppendL( folder );
+        CleanupStack::Pop( folder );
+        }
+    
+    CleanupStack::PopAndDestroy( &folders );
+    }
+
+
+/**
+ *
+ */
+CFSMailAddress* CBasePlugin::FetchEmailAddressL(
+    CMsgStorePropertyContainer& aMessage,
+    TUint aIdx )
+
+    {
+    RMsgStoreAddress value;
+    CleanupClosePushL( value );
+
+    aMessage.PropertyValueAddressL( aIdx, value );
+
+    CFSMailAddress* result = CFSMailAddress::NewL();
+    result->SetEmailAddress( value.iEmailAddress );
+    if ( KNullDesC() != value.iDisplayName )
+        {
+        result->SetDisplayName( value.iDisplayName );
+        }
+    else
+        {
+        /**@ the UI would crash if there was no display name.*/
+        result->SetDisplayName( value.iEmailAddress );
+        }
+
+    CleanupStack::PopAndDestroy( &value );
+    
+    return result;
+    }
+
+
+/**
+ *
+ */
+EXPORT_C CMsgStoreMessagePart* CBasePlugin::GetBodyPartL(
+    CMsgStoreMessage& aMessage,
+    const TDesC& aContentType )
+    {
+    CMsgStoreMessagePart* result = NULL;
+    
+    RPointerArray<CMsgStoreMessagePart> parts;
+    CleanupResetAndDestroyClosePushL( parts );
+
+    aMessage.ChildPartsL( parts );
+    if ( 0 < parts.Count() )
+        {
+        RPointerArray<CMsgStoreMessagePart> childParts;
+        CleanupResetAndDestroyClosePushL( childParts );
+        parts[0]->ChildPartsL( childParts );
+        
+        TInt count = childParts.Count();
+        if ( 0 < count )
+            {
+            for ( TInt i = 0; i < count; i++ )
+                {
+                TUint idx = 0;
+                if ( childParts[i]->FindProperty( KMsgStorePropertyContentType, idx, idx ) )
+                    {
+                    const TDesC& contentType = childParts[i]->PropertyValueDesL( idx );
+                    if ( contentType == aContentType )
+                        {
+                        result = childParts[i];
+                        childParts.Remove( i );
+                        break;
+                        }
+                    }
+                }
+            
+            }
+        else
+            {
+            TUint idx = 0;
+            if ( parts[0]->FindProperty( KMsgStorePropertyContentType, idx, idx ) )
+                {
+                const TDesC& contentType = parts[0]->PropertyValueDesL( idx );
+                if ( contentType == aContentType )
+                    {
+                    result = parts[0];
+                    parts.Remove( 0 );
+                    }
+                }
+            }
+            
+        CleanupStack::PopAndDestroy( &childParts );
+        }
+        
+    CleanupStack::PopAndDestroy( &parts );
+
+    return result;
+    } //GetBodyPartL.
+
+/**
+ *
+ */
+EXPORT_C CFSMailMessage* CBasePlugin::CreateForwardReplyMessageL(
+    const TFSMailMsgId& aMailBox,
+    const TFSMailMsgId& aOriginal,
+    const TBool aReplyToAll,
+    const TDesC& aHeaderDescriptor,
+    TBool aKeepAttachments,
+    TBool aKeepMeetingRequestInfo )
+    {
+    __LOG_ENTER( "CreateForwardReplyMessageL" )
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBox.Id() );
+
+    CMsgStoreMessage* message = mailBox().FetchMessageL(
+        aOriginal.Id(), KMsgStoreInvalidId );
+    CleanupStack::PushL( message );
+
+    TMsgStoreId newMsgId = mailBox().CopyMessageL(
+        aOriginal.Id(), message->ParentId(),
+        mailBox.iRootFolders.iFolders[EFSDraftsFolder] );
+    
+    CMsgStoreMessage* newMsg = mailBox().FetchMessageL( newMsgId, KMsgStoreInvalidId );
+    CleanupStack::PushL( newMsg );
+
+    if ( !aReplyToAll )
+        {
+        //Clear all To, Cc addresses for Reply, Forward
+        RemoveAllPropertiesL( *newMsg, KMsgStorePropertyTo );
+        RemoveAllPropertiesL( *newMsg, KMsgStorePropertyCc );
+        }
+    else
+        {
+        //Remove the mailbox address from the reply to addresses
+        HBufC* mailBoxAdd = GetMailBoxAddressL( aMailBox );
+        CleanupStack::PushL( mailBoxAdd );
+        
+        if ( NULL != mailBoxAdd )
+            {           
+            TUint idx1 = 0;
+            while (newMsg->FindProperty( KMsgStorePropertyTo, idx1, idx1 ) )
+                {
+                RMsgStoreAddress tempAdd;
+                CleanupClosePushL( tempAdd );
+                
+                newMsg->PropertyValueAddressL( idx1, tempAdd );
+                if ( tempAdd.iEmailAddress == *mailBoxAdd )
+                    {
+                    newMsg->RemovePropertyL( idx1 );
+                    CleanupStack::PopAndDestroy( &tempAdd );
+                    break;
+                    }
+                CleanupStack::PopAndDestroy( &tempAdd );
+                ++idx1;
+                }
+        
+            idx1 = 0;
+            while (newMsg->FindProperty( KMsgStorePropertyCc, idx1, idx1 ) )
+                {
+                RMsgStoreAddress tempAdd;
+                CleanupClosePushL( tempAdd );
+                        
+                newMsg->PropertyValueAddressL( idx1, tempAdd );
+                if ( tempAdd.iEmailAddress == *mailBoxAdd )
+                    {
+                    newMsg->RemovePropertyL( idx1 );
+                    CleanupStack::PopAndDestroy( &tempAdd );
+                    break;
+                    }
+                CleanupStack::PopAndDestroy( &tempAdd );
+                ++idx1;
+                } 
+            }
+        
+        CleanupStack::PopAndDestroy( mailBoxAdd );
+        }
+    
+	SetReplyOrForwardToFieldL( *newMsg );
+
+    //Clear the response flag.
+	TUint idx = 0;
+    if ( newMsg->FindProperty( KMsgStorePropertyFlags, idx ) )
+        {
+        TUint32 flags = newMsg->PropertyValueUint32L( idx );
+        flags &= ~EFSMsgFlag_Answered;
+        newMsg->AddOrUpdatePropertyL( KMsgStorePropertyFlags, flags );
+        }
+
+    //Clear the From field, ReplyTo field
+    RemoveAllPropertiesL( *newMsg, KMsgStorePropertyFrom );
+    RemoveAllPropertiesL( *newMsg, KMsgStorePropertyReplyTo );
+    
+    //Use reply-to address, if it exists
+    HBufC* replyToAddressString = GetReplyToAddressL( aMailBox );
+       
+    if ( NULL != replyToAddressString )
+        {
+        CleanupStack::PushL( replyToAddressString );
+           
+        if ( replyToAddressString->Length() > 0 )
+            {
+            RMsgStoreAddress replyToAddress;
+            CleanupClosePushL( replyToAddress );
+               
+            replyToAddress.iEmailAddress.Create( *replyToAddressString );
+            replyToAddress.iDisplayName.Create( KNullDesC );
+               
+            newMsg->AddOrUpdatePropertyL( KMsgStorePropertyReplyTo, replyToAddress );
+               
+            CleanupStack::PopAndDestroy( &replyToAddress );
+            }
+        CleanupStack::PopAndDestroy( replyToAddressString );
+       }
+          
+    newMsg->StorePropertiesL();
+
+    //deal with the attachments accordingly.
+    /**@ the case where the attachments haven't been downloaded but some smart
+     * reply/fw tag is present in the msg body needs to be dealt with in the specific
+     * plugins.*/
+    if ( aKeepAttachments == EFalse )
+        {
+        RPointerArray<CMsgStoreMessagePart> parts;
+        CleanupResetAndDestroyClosePushL( parts );
+
+        newMsg->ChildPartsL( parts );
+        TInt count = parts.Count();
+
+        for ( TInt i = 1; i < count; i++ )
+            {
+            newMsg->RemoveChildPartL( parts[i]->Id() );
+            }
+            
+        CleanupStack::PopAndDestroy( &parts );
+        }
+
+    if ( aKeepMeetingRequestInfo == EFalse )
+    	{
+    	idx = 0;
+    	if ( newMsg->FindProperty( KMsgStorePropertyMeetingRequest, idx ) )
+    		{
+    		CBasePlugin::RemoveAllPropertiesL( *newMsg, KMsgStorePropertyMeetingRequest );
+    		}
+    	}
+    
+    CFSMailMessage* result = CFSMailMessage::NewL(
+        TFSMailMsgId( GetPluginId(), newMsgId ) );
+    CleanupStack::PushL( result );
+    
+    TranslateMsgStorePropsL( aMailBox, *newMsg, *result );
+    result->SetMailBoxId( aMailBox );
+
+    /**@ candidate for refactoring out to a separate body dealing method.*/
+    CMsgStoreMessagePart* srcPart = GetBodyPartL( *message );
+    if ( NULL != srcPart )
+        {
+        CleanupStack::PushL( srcPart );
+        CMsgStoreMessagePart* dstPart = GetBodyPartL( *newMsg );
+
+        if ( NULL != dstPart )
+            {
+            CleanupStack::PushL( dstPart );
+            
+            HBufC* signature = GetSignatureL( aMailBox );
+            if ( NULL != signature )
+                {
+                CleanupStack::PushL( signature );
+                TPtrC8 ptr8(
+                    reinterpret_cast<const TUint8*>( signature->Ptr() ),
+                    signature->Size() );
+                dstPart->ReplaceContentL( ptr8 );
+                CleanupStack::PopAndDestroy( signature );
+
+                __LOG_WRITE_INFO( "Set the email signature." )
+                }
+
+            //the quoted message header.
+            if ( aHeaderDescriptor != KNullDesC )
+                {
+                TPckgBuf<TReplyForwardParams> rfParsPckg;
+                rfParsPckg.Copy( aHeaderDescriptor );
+                
+                TPtrC8 ptrHeader8(
+                    reinterpret_cast<const TUint8*>( rfParsPckg().iHeader->Ptr() ),
+                    rfParsPckg().iHeader->Size() );
+                NULL != signature ? dstPart->AppendToContentL( ptrHeader8 )
+                    : dstPart->ReplaceContentL( ptrHeader8 );
+
+                __LOG_WRITE8_FORMAT1_INFO(
+                    "Original body content length: %d.", srcPart->ContentLengthL() )
+
+                //copy the body content from the original.
+                TInt startOffset = 0;
+                RBuf8 buf;
+                buf.Create( KQuotedReadBufferSize );
+                CleanupClosePushL( buf );
+
+                do
+                    {
+                    srcPart->FetchContentToBufferL( buf, startOffset );
+                    dstPart->AppendToContentL( buf );
+                    
+                    startOffset += buf.Size();
+                    }
+                while ( buf.Size() == KQuotedReadBufferSize );
+
+                CleanupStack::PopAndDestroy( &buf );
+
+                TInt newFetchedSize = dstPart->ContentLengthL();
+                __LOG_WRITE8_FORMAT1_INFO(
+                    "Reply/fw body content length: %d.", newFetchedSize )
+
+                TInt idx = dstPart->AddOrUpdatePropertyL(
+                    KMsgStorePropertySize, static_cast<TUint32>( newFetchedSize ) );
+                dstPart->StorePropertyL( idx );
+                idx = dstPart->AddOrUpdatePropertyL(
+                    KMsgStorePropertyRetrievedSize, static_cast<TUint32>( newFetchedSize ) );
+                dstPart->StorePropertyL( idx );
+                
+                result->SetContentSize( newFetchedSize );
+                result->SetFetchedContentSize( newFetchedSize );
+
+                //determine whether the original msg was truncated.
+                TBool wasTruncated = EFalse;
+                TUint srcIdx = 0;
+                if ( srcPart->FindProperty( KMsgStorePropertySize, srcIdx ) )
+                    {
+                    TUint size = srcPart->PropertyValueUint32L( srcIdx );
+
+                    srcIdx = 0;
+                    if ( srcPart->FindProperty( KMsgStorePropertyRetrievedSize, srcIdx ) )
+                        {
+                        TUint retrievedSize = srcPart->PropertyValueUint32L( srcIdx );
+                        
+                        if ( retrievedSize < size )
+                            {
+                            wasTruncated = ETrue;
+                            }
+                        }
+                    }
+                    
+                //if truncated append msg that the whole msg is available server-side.
+                if ( wasTruncated )
+                    {
+                    _LIT( KTwoLineFeeds, "\n\n" );
+                    TPtrC8 ptrTwoLineFeeds8(
+                        reinterpret_cast<const TUint8*>( KTwoLineFeeds().Ptr() ),
+                        KTwoLineFeeds().Size() );
+                    dstPart->AppendToContentL( ptrTwoLineFeeds8 );
+
+                    TPtrC8 ptrSmartTag8(
+                        reinterpret_cast<const TUint8*>( rfParsPckg().iSmartTag->Ptr() ),
+                        rfParsPckg().iSmartTag->Size() );
+                    dstPart->AppendToContentL( ptrSmartTag8 );
+                    }
+                }
+
+            /**@ incorrect but per activesync request - the base plugin doesn't know anything about how the unicode characters
+            are being encoded by the specific implementations when they talk to their backends.*/
+            _LIT(KMessageBodyCharset, "UTF-8");
+            dstPart->AddPropertyL( KMsgStorePropertyCharset, KMessageBodyCharset );
+
+            CleanupStack::PopAndDestroy( dstPart );
+            }
+        CleanupStack::PopAndDestroy( srcPart );
+        }
+    
+    CleanupStack::Pop( result );
+    CleanupStack::PopAndDestroy( newMsg );
+    CleanupStack::PopAndDestroy( message );
+    
+    __LOG_EXIT
+    return result;
+    } //CreateForwardReplyMessageL.
+
+
+/**
+ * If there is a reply to address, add it to the TO list
+ * else add the FROM address to the TO address list   
+ */
+/*private*/ void CBasePlugin::SetReplyOrForwardToFieldL( CMsgStoreMessage& aMsg )
+	{
+    RMsgStoreAddress toAddr;
+    CleanupClosePushL( toAddr );
+    
+    TBool usingReplyTo = EFalse;
+    
+    TUint idx = 0;
+    if( aMsg.FindProperty( KMsgStorePropertyReplyTo, idx ) )
+    	{
+    	//if both address and name are null strings no memory will be allocated.
+        aMsg.PropertyValueAddressL( idx, toAddr );
+        
+        if ( toAddr.iEmailAddress.Length() || toAddr.iDisplayName.Length() )
+        	{
+        	usingReplyTo = ETrue;
+        	}
+    	}
+
+    if ( EFalse == usingReplyTo )
+		{
+        idx = 0;
+        if ( aMsg.FindProperty( KMsgStorePropertyFrom, idx ) )
+        	{
+            aMsg.PropertyValueAddressL( idx, toAddr );
+        	}
+		}
+
+    aMsg.AddPropertyL( KMsgStorePropertyTo, toAddr );
+    CleanupStack::PopAndDestroy( &toAddr );
+	}
+
+
+/**
+ * RefreshMailboxCacheL - This will refresh the mailbox instance cache maintained within the base plugin.  
+ *
+ */
+EXPORT_C CMailboxInfo& CBasePlugin::RefreshMailboxCacheL( TMsgStoreId aMailBoxId )
+    {
+    //save the observers
+    CMailboxInfo& oldMailBox = GetMailboxInfoL( aMailBoxId );
+    
+    RPointerArray<MFSMailEventObserver> observers;
+    // the elements are not owned by the base plugin, so just close the array
+    CleanupClosePushL( observers );
+
+    TUint count = oldMailBox.iObservers.Count();
+    for ( TUint i = 0; i < count; i++ )
+    	{
+    	observers.AppendL( oldMailBox.iObservers[i] );
+    	}
+    
+    //remove from the cache
+    if ( KErrNotFound != iMailboxes.Find( aMailBoxId ) )
+        {
+        iMailboxes.RemoveL( aMailBoxId );
+        }
+
+    //force the refresh and restore the observes
+    CMailboxInfo& newMailBox = GetMailboxInfoL( aMailBoxId );
+    
+    for ( TUint i = 0; i < count; i++ )
+    	{
+    	newMailBox.iObservers.AppendL( observers[i] );
+    	}
+    
+    CleanupStack::PopAndDestroy( &observers );
+    return newMailBox;
+    }
+
+
+/**
+ * RefreshCachedMailBoxDisplayNameL -   This will check to see if the mailbox display name has changed.  If so it will
+ *                                      update the cached mailbox display name and set mailBoxNameHasChanged to ETrue 
+ *
+ */
+void CBasePlugin::RefreshCachedMailBoxDisplayNameL( TBool& aMailBoxNameHasChanged, const TMsgStoreId& aMailBoxId )
+    {
+    aMailBoxNameHasChanged = EFalse;
+    
+    RBuf currentDisplayName;
+    currentDisplayName.CleanupClosePushL();
+    GetMailboxDisplayNameL( aMailBoxId, currentDisplayName );
+    
+    CMailboxInfo& mailboxInfo = GetMailboxInfoL( aMailBoxId );
+    TDesC* cachedDisplayName( mailboxInfo.iMailBoxDisplayName );
+
+    if ( ( cachedDisplayName && currentDisplayName != *cachedDisplayName ) ||
+         ( !cachedDisplayName && currentDisplayName.Length() ) )
+        {
+        aMailBoxNameHasChanged = ETrue;
+        delete mailboxInfo.iMailBoxDisplayName;
+        mailboxInfo.iMailBoxDisplayName = NULL;
+        mailboxInfo.iMailBoxDisplayName = currentDisplayName.AllocL();
+        }
+    
+    CleanupStack::PopAndDestroy( &currentDisplayName );
+    }
+