ipsservices/ipssosplugin/src/ipsplgsmtpservice.cpp
author hgs
Fri, 23 Jul 2010 19:09:50 +0300
changeset 56 15bc1d5d6267
parent 43 99bcbff212ad
permissions -rw-r--r--
201029

/*
* Copyright (c) 2007 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: This file implements class CIpsPlgSmtpService.
*
*/


#include "emailtrace.h"
#include "ipsplgheaders.h"

#include <featmgr.h>
#include <bldvariant.hrh> // for feature definitions

// <cmail> const TInt KIpsSetUtilsCharAt = '@'; </cmail>
const TInt KIpsSetUtilsCharLessThan = '<';
const TInt KIpsSetUtilsCharMoreThan = '>';
const TInt KIpsSetUtilsCntrCharacters = 2;

// do we need smtp object instead set of static functions

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::CIpsPlgSmtpService
// ---------------------------------------------------------------------------
//
CIpsPlgSmtpService::CIpsPlgSmtpService(
    CMsvSession& aSession,
    CIpsPlgSosBasePlugin& aPlugin ) :
    iPlugin( aPlugin ),
    iSession( aSession), 
    iMsgMapper( NULL )
    {
    FUNC_LOG;
    }
  
// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::~CIpsPlgSmtpService
// ---------------------------------------------------------------------------
//    
CIpsPlgSmtpService::~CIpsPlgSmtpService() 
    {
    FUNC_LOG;
    delete iMsgMapper;
    
    if( iFeatureManagerInitialized )
    	{
    	FeatureManager::UnInitializeLib();  
    	}
    }    

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::NewL
// ---------------------------------------------------------------------------
//
EXPORT_C CIpsPlgSmtpService* CIpsPlgSmtpService::NewL(
    CMsvSession& aSession,
    CIpsPlgSosBasePlugin& aPlugin )
    {
    FUNC_LOG;
    CIpsPlgSmtpService* self = CIpsPlgSmtpService::NewLC( 
        aSession, aPlugin  );
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::NewLC
// ---------------------------------------------------------------------------
//
EXPORT_C CIpsPlgSmtpService* CIpsPlgSmtpService::NewLC(
    CMsvSession& aSession,
    CIpsPlgSosBasePlugin& aPlugin )
    {
    FUNC_LOG;
    CIpsPlgSmtpService* self = new( ELeave ) CIpsPlgSmtpService( 
        aSession, aPlugin );
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }
    
// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::ConstructL
// ---------------------------------------------------------------------------
//
void CIpsPlgSmtpService::ConstructL()
    {
    FUNC_LOG;
    iMsgMapper = CIpsPlgMsgMapper::NewL( iSession, iPlugin );
    
    FeatureManager::InitializeLibL();
    iFeatureManagerInitialized = ETrue;
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::CreateDisplayStringLC
// ---------------------------------------------------------------------------
//
HBufC* CIpsPlgSmtpService::CreateDisplayStringLC(
    const TDesC& aDisplayName,
    const TDesC& aEmailName )
    {
    FUNC_LOG;
    TInt length( aDisplayName.Length() );
    HBufC* fullName( NULL );
    
    length += aEmailName.Length() + KIpsSetUtilsCntrCharacters;
    fullName = HBufC::NewLC( length );
    fullName->Des().Append( aDisplayName );
    
    if ( fullName->Length() )
        {
        // We have display name, add angle brackets to address
        fullName->Des().Append( KIpsSetUtilsCharLessThan );
        fullName->Des().Append( aEmailName );
        fullName->Des().Append( KIpsSetUtilsCharMoreThan );
        }
    else
        {
        fullName->Des().Append( aEmailName );
        }
    return fullName;
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::StoreMessageL
// ---------------------------------------------------------------------------
//
void CIpsPlgSmtpService::StoreMessageL( 
    TFSMailMsgId /* aMailBoxId */, CFSMailMessage& aMessage )
    {
    FUNC_LOG;

    // Update flags i.e. Priority
    iMsgMapper->UpdateMessageFlagsL( aMessage.GetMessageId().Id(), aMessage );
    
    // get message from store
    CMsvEntry* cEntry = CMsvEntry::NewL(
        iSession, aMessage.GetMessageId().Id(), TMsvSelectionOrdering() );
    CleanupStack::PushL( cEntry );  // << cEntry
    TMsvEntry tEntry = cEntry->Entry();    
    
    // creating store object for editing message
    CMsvStore* store = cEntry->EditStoreL();
    CleanupStack::PushL( store );   // << store
    
    // create symbian email header object
    CImHeader* header = CImHeader::NewLC(); // << header
    header->RestoreL( *store );

    // From field, check that sender is set
    if ( aMessage.GetSender() )
        {
        header->SetFromL( aMessage.GetSender()->GetEmailAddress() );
        }
    
    // To Field
// <qmail> return by value, because Qt types are used for internal CFSMailAddress data storage
    RPointerArray<CFSMailAddress> toArray = aMessage.GetToRecipients();
// </qmail>
    // Reseting recipient list, because our client calls us many times
    // and we want to avoid duplicates
    header->ToRecipients().Reset();
    // build new 'to' header
    for( TInt i = 0; i < toArray.Count(); i++ )
        {
        TPtrC displayName = toArray[i]->GetDisplayName();
        TPtrC emailName = toArray[i]->GetEmailAddress();
        HBufC* fullName = CreateDisplayStringLC( displayName, emailName );  // << fullName
        header->ToRecipients().AppendL( *fullName ); // copy created
        // only first receiver 
        if( i == 0 && fullName )
            {
            tEntry.iDetails.Set( *fullName );
            cEntry->ChangeL( tEntry );
            // Load tEntry again
            // because old instance's iDetails member gets wiped
            // in PopAndDestroy below
            tEntry = cEntry->Entry();
            }
        CleanupStack::PopAndDestroy( fullName );    // >>> fullName
        }   
    
    // CC field
// <qmail> return by value, because Qt types are used for internal CFSMailAddress data storage
    RPointerArray<CFSMailAddress> ccArray 
        = aMessage.GetCCRecipients();
// </qmail>
    header->CcRecipients().Reset();
    for( TInt i = 0; i < ccArray.Count(); i++ )
        {
        TPtrC displayName = ccArray[i]->GetDisplayName();
        TPtrC emailName = ccArray[i]->GetEmailAddress();
        HBufC* fullName = CreateDisplayStringLC( displayName, emailName );  // << fullName
        header->CcRecipients().AppendL( *fullName );
        CleanupStack::PopAndDestroy( fullName );    // >>> fullName
        }
    
    // BCC field
// <qmail> return by value, because Qt types are used for internal CFSMailAddress data storage
    RPointerArray<CFSMailAddress> bccArray 
        = aMessage.GetBCCRecipients();
// </qmail>
    header->BccRecipients().Reset();
    for( TInt i = 0; i < bccArray.Count(); i++ )
        {
        TPtrC displayName = bccArray[i]->GetDisplayName();
        TPtrC emailName = bccArray[i]->GetEmailAddress();
        HBufC* fullName = CreateDisplayStringLC( displayName, emailName );  // << fullName
        header->BccRecipients().AppendL( *fullName ); // copy created
        CleanupStack::PopAndDestroy( fullName );    // >>> fullName
        }
    
    // Subject, check null pointer
    if ( &aMessage.GetSubject() )
        {
        header->SetSubjectL( aMessage.GetSubject() );
        }
        
    // store header in cEntry's store
    header->StoreWithoutCommitL(*store);
    // commit header to store
    store->CommitL();
    
    //change preparation state and set subject to description
    tEntry.SetInPreparation( EFalse );
    tEntry.iDescription.Set( aMessage.GetSubject() );
    
    cEntry->ChangeL( tEntry );
    
    // release store
    CleanupStack::PopAndDestroy( 3, cEntry );   // >>> cEntry, header, store
    }

// <qmail> removing unused functions
// CreateNewSmtpMessageL
// CreateForwardSmtpMessageL
// CreateReplySmtpMessageL
// </qmail>

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::ChangeServiceIdL
// ---------------------------------------------------------------------------
//
void CIpsPlgSmtpService::ChangeServiceIdL( TMsvEntry& aEntry )
    {
    FUNC_LOG;
    TMsvEntry serviceEntry;
    TMsvId service;
    CMsvEntry* cEntry = iSession.GetEntryL( aEntry.iServiceId );
    CleanupStack::PushL( cEntry );
    User::LeaveIfError( iSession.GetEntry( cEntry->EntryId(), service, serviceEntry ) );
    if( aEntry.iServiceId != serviceEntry.iRelatedId )
        {
        aEntry.iServiceId = serviceEntry.iRelatedId;
        cEntry->SetEntryL( aEntry.Id() );
        cEntry->ChangeL( aEntry );
        }
    CleanupStack::PopAndDestroy( cEntry );
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::ChangeServiceIdL
// ---------------------------------------------------------------------------
//
void CIpsPlgSmtpService::ChangeServiceIdL( TMsvEntry& aEntry, TMsvId aServiceId )
    {
    FUNC_LOG;
    CMsvEntry* cEntry = iSession.GetEntryL( aEntry.Id() );
    CleanupStack::PushL( cEntry );
    aEntry.iServiceId = aServiceId;
    cEntry->ChangeL( aEntry );
    CleanupStack::PopAndDestroy( cEntry );
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::CreateFSMessageAndSetFlagsL
// ---------------------------------------------------------------------------
//
CFSMailMessage* CIpsPlgSmtpService::CreateFSMessageAndSetFlagsL(
       TMsvId aMessageId,
       TMsvId aOriginalMsgId,
       TMsvId aMailboxId,
       TBool aCopyOriginalMsgProperties )
    {
    FUNC_LOG;

    
   
    // tp teleca change for korean specific email encoding
    // Default charset
    TUid charset;
    charset.iUid = KCharacterSetIdentifierUtf8;

      // korea specific charset
      if ( FeatureManager::FeatureSupported( KFeatureIdKorean ))
      {
      
      //const TUid KCRUidEMailCharsets = {0x20018441};    // korea needs different default charset
          const TInt KoreanMib = 38; // magic number to read from cen rep would be better
            
		  CCnvCharacterSetConverter* charConv = NULL;
		  TRAPD( err, charConv = CCnvCharacterSetConverter::NewL() );
		  if( err == KErrNone )
			  {
			  TUint characterSetId = KCharacterSetIdentifierUtf8;
			  RFs fs;
			  TInt err = fs.Connect();
			  
			  if( err == KErrNone )
				  {
				  TRAP( err, characterSetId = charConv->ConvertMibEnumOfCharacterSetToIdentifierL( KoreanMib, fs ));
				   if( err == KErrNone )
					   { // set korean specific charset
					   charset = TUid::Uid( characterSetId );
					   }
				   fs.Close();
				  }
			  }

         delete charConv; 
     
      }
      // tp teleca change END

    // set in preparation flag, altought 
    // not known where this affects
    TMsvId dummy;
    TMsvEmailEntry newEmailMsg;
    iSession.GetEntry( aMessageId, dummy, newEmailMsg );
    newEmailMsg.SetInPreparation( ETrue );
    
    // when creating new message from scratch theres no 
    // orginal message, so it is set to KErrNotFound
    if ( aOriginalMsgId != KErrNotFound )
        {
        TMsvEntry orgMsg;
        //get entry errors not handled
        iSession.GetEntry( aOriginalMsgId, dummy, orgMsg );
        const TMsvEmailEntry& orgEmailMsg(orgMsg);
        
        // symbian not mark same priority to reply / forward messages
// <qmail>
        if ( aCopyOriginalMsgProperties && orgEmailMsg.Priority() != newEmailMsg.Priority() )
// </qmail>
            {
            newEmailMsg.SetPriority( orgEmailMsg.Priority() );
            }
        //get charset from original message
        charset = GetOriginalCharsetL( aOriginalMsgId );
        }
    
    // set in preparation
    CMsvEntry* cEntry = iSession.GetEntryL( aMessageId );
    CleanupStack::PushL( cEntry );
    cEntry->ChangeL( newEmailMsg );

    //no need to set if we for some reason don't have it.
    //system default will be used.
    if ( KNullUidValue != charset.iUid )
        {
        SetCharactersetL( *cEntry, charset );
        }
    // delete operations we don't need anymore
    CleanupStack::PopAndDestroy( cEntry );
    
    // create a Freestyle mail message object and set to it all
    // needed data from just created symbian mail message
    CFSMailMessage* fsMsg = CFSMailMessage::NewL(
        TFSMailMsgId( iPlugin.PluginId(), aMessageId ) );
    fsMsg->SetMailBoxId( TFSMailMsgId( iPlugin.PluginId(), aMailboxId ) );
    fsMsg->SetFolderId( 
        TFSMailMsgId( iPlugin.PluginId(), KMsvDraftEntryId ) );

// <qmail>
    // update subject
    fsMsg->SetSubject( newEmailMsg.iDescription );
// </qmail>
    
    //update flags
    iMsgMapper->SetFSMessageFlagsL( newEmailMsg, *fsMsg );
    
    return fsMsg;
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::GetIdFromProgressL
// inline static
// ---------------------------------------------------------------------------
//
inline TMsvId CIpsPlgSmtpService::GetIdFromProgressL( const TDesC8& aProg )
    {
    FUNC_LOG;
    // Taken from symbian os help example code
    // Create and initialise a temporary TPckg object that 
    // can hold a message Id.
    TMsvId msgId;
    TPckg<TMsvId> param(msgId);
    
    // Copy the message Id returned from the ProgressL() call into the
    // temporary TPckg object.
    param.Copy( aProg ); 

    // Check the value of the returned message Id in the TPckg object.
    if ( msgId == KMsvNullIndexEntryId )
        {
        // Email is not correctly created, so leave
        User::Leave( KErrNotFound );
        }
    return msgId;
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::GetOriginalCharsetL
// ---------------------------------------------------------------------------
//
TUid CIpsPlgSmtpService::GetOriginalCharsetL( TMsvId aOriginalMsgId )
    {
    FUNC_LOG;
    TUid ret;
    CMsvEntry* oEntry = iSession.GetEntryL( aOriginalMsgId );
    CleanupStack::PushL( oEntry );
    
    CImEmailMessage* cMessage = CImEmailMessage::NewLC( *oEntry );
    
    // <cmail> Added check for body text because GetCharacterSetL will
    // hang if there is no body text
    CMsvStore* store = oEntry->EditStoreL();
    CleanupStack::PushL(store);

    TUint charId;
    
    if( store->HasBodyTextL() )
        {
        TBool override=EFalse;
        cMessage->GetCharacterSetL( aOriginalMsgId, charId, override );
        ret.iUid = charId;
        }
    else
        {
        ret.iUid = KCharacterSetIdentifierUtf8;
        }
    
    CleanupStack::PopAndDestroy( 3, oEntry );//oEntry, cMessage, store
    // </cmail>
      
    return ret;
    }

// ---------------------------------------------------------------------------
// CIpsPlgSmtpService::SetCharactersetL
// ---------------------------------------------------------------------------
//
void CIpsPlgSmtpService::SetCharactersetL( CMsvEntry& aEntry, TUid aCharset )
    {
    FUNC_LOG;
    //Set character set for outgoing message. We use the one 
    //that was in the original message.     
    CMsvStore* store = aEntry.EditStoreL();
    CleanupStack::PushL(store);

    CImHeader* header = CImHeader::NewLC();
    header->RestoreL( *store );
    
    TImEmailTransformingInfo info;
    info.SetToDefault(ESendAsMimeEmail);    
    info.SetHeaderAndBodyCharset( aCharset.iUid );
    info.StoreL( *store );
    
    header->StoreL( *store );
    store->CommitL();
    CleanupStack::PopAndDestroy( 2, store ); // store, header       
    }
// End of File