email/pop3andsmtpmtm/clientmtms/src/MIUTMSG.CPP
changeset 0 72b543305e3a
child 9 1d7827e39b52
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // MIUTMSG.CPP
       
    15 //
       
    16 
       
    17 #include <e32def.h>
       
    18 #include "MIUTMSG.H"
       
    19 #include "MIUT_ERR.H"
       
    20 #include "IMCMMAIN.H"
       
    21 #include "SMTPSET.H"	// CImSmtpSettings
       
    22 #include "MIUTRSLV.H"
       
    23 #include "MIUTCONV.H"
       
    24 #include "POP3SET.H"
       
    25 #include "IMAPSET.H"
       
    26 #include <msventry.h>
       
    27 #include <msvuids.h>
       
    28 #include <bautils.h>	// BaflUtils
       
    29 #include <barsread.h>	// TResourceReader
       
    30 #include <imcm.rsg>
       
    31 #include <cntdb.h>
       
    32 #include <vcard.h>
       
    33 #include <s32mem.h>
       
    34 #include <f32file.h>
       
    35 #include <apgcli.h> // for recognizeData
       
    36 #include <eikenv.h>
       
    37 #include <txtrich.h>
       
    38 #include <cmsvbodytext.h>
       
    39 #include <imcvcodc.h>
       
    40 #include <tz.h> //Converting from UTC to local time
       
    41 #include <tzconverter.h>
       
    42 #include <cmsvplainbodytext.h>
       
    43 #include <cmsvattachment.h>
       
    44 #include <cmsvmimeheaders.h>
       
    45 #include "cimattachmentmanager.h"
       
    46 #include <mmsvattachmentmanagersync.h>
       
    47 #include <cemailaccounts.h>
       
    48 #include "CIMPLAINBODYTEXT.H"
       
    49 #include <numberconversion.h>
       
    50 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
       
    51 #include "cimmessagepart.h"
       
    52 #include "miut_errconsts.h"
       
    53 #include "cimconvertcharconv.h"
       
    54 #include "cimconvertheader.h"
       
    55 #include <mtmuidsdef.hrh>
       
    56 #include "msvconsts.h"
       
    57 #endif
       
    58 
       
    59 const TInt KMaxChunkLength = 1000;
       
    60 const TInt KMiutAttachmentListGranularity=8;
       
    61 const TInt KVCardFilenameLength=25;
       
    62 const TUid KUidMsgTypePCMail = {0x1000412A};
       
    63 const TUid KMessageCharSetStreamUid = {0x101FD0E4};
       
    64 const TUint8 KMessageCharSetStreamVersion = 1;
       
    65 const TInt KRFC2231Encoded = 2;
       
    66 _LIT(KEllipsesString,",...");
       
    67 _LIT(KSeparatorString,", ");
       
    68 _LIT(KMhtmlUrlAmpersand, "&amp;");
       
    69 
       
    70 
       
    71 //
       
    72 //CImEmailMessage
       
    73 //
       
    74 
       
    75 /**
       
    76 Allocates and creates a new CImEmailMessage object.
       
    77 
       
    78 @param aEntry
       
    79 A CMsvEntry object that relates to a message server entry.
       
    80 This object is used by CImEmailMessage to perform operations on particular
       
    81 message server entries.  It does not matter what context aEntry happens to
       
    82 be focused on.
       
    83 
       
    84 @return
       
    85 A CImEmailMessage message object.
       
    86 
       
    87 @see CMsvEntry
       
    88 */
       
    89 EXPORT_C CImEmailMessage* CImEmailMessage::NewL(CMsvEntry& aEntry)
       
    90 	{
       
    91 	CImEmailMessage* self = CImEmailMessage::NewLC(aEntry);
       
    92 	CleanupStack::Pop();
       
    93 	return self;
       
    94 	}
       
    95 
       
    96 
       
    97 /**
       
    98 Allocates and creates a new CImEmailMessage object, leaving the object on the 
       
    99 cleanup stack.
       
   100 
       
   101 @param aEntry
       
   102 A CMsvEntry object that relates to a message server entry.
       
   103 This object is used by CImEmailMessage to perform operations on particular
       
   104 message server entries.  It does not matter what context aEntry happens to
       
   105 be focused on.
       
   106 
       
   107 @return
       
   108 A CImEmailMessage object.
       
   109 
       
   110 @see CMsvEntry
       
   111 */
       
   112 EXPORT_C CImEmailMessage* CImEmailMessage::NewLC(CMsvEntry& aEntry)
       
   113 	{
       
   114 	CImEmailMessage* self = new (ELeave) CImEmailMessage(aEntry);
       
   115 	CleanupStack::PushL(self);
       
   116 	self->ConstructL();
       
   117 	return self;
       
   118 	}
       
   119 
       
   120 
       
   121 /** 
       
   122 Destructor.
       
   123 */
       
   124 EXPORT_C CImEmailMessage::~CImEmailMessage()
       
   125 	{
       
   126 	Cancel();
       
   127 	delete iAttachmentNameList;
       
   128 	delete iCompleteSel;
       
   129 	delete iResultSel;
       
   130 	delete iUriResolver;
       
   131 	delete iStoreMessagePart;
       
   132 	delete iRemoveMessagePart;
       
   133 	iFs.Close();
       
   134 	delete iAttachmentManager;
       
   135 	delete iStore;
       
   136 	}
       
   137 
       
   138 
       
   139 CImEmailMessage::CImEmailMessage(CMsvEntry& aEntry)
       
   140 	: CMsgActive(EPriorityStandard), iClientEntry(aEntry)
       
   141 	{
       
   142 	}
       
   143 
       
   144 
       
   145 void CImEmailMessage::ConstructL()
       
   146 	{
       
   147 	iCompleteSel=new (ELeave) CMsvEntrySelection();
       
   148 	iResultSel=new (ELeave) CMsvEntrySelection();
       
   149 	iUriResolver = CImMhtmlUriResolver::NewL(iClientEntry);
       
   150 	iProgress = KMsvNullIndexEntryId;
       
   151 	User::LeaveIfError(iFs.Connect());
       
   152 	iAttachmentNameList = new (ELeave) CDesCArrayFlat(KMiutAttachmentListGranularity);
       
   153 	iEmailEntryId = iClientEntry.EntryId();
       
   154 	iAttachmentManager = CImAttachmentManager::NewL(*this,iClientEntry);
       
   155 	iAttachmentManager->LoadL();
       
   156 	iAttachmentState=ENoAttachment; 
       
   157 	CActiveScheduler::Add(this);	
       
   158 	}
       
   159 
       
   160 /** 
       
   161 Asynchronously retrieves the body text for a specified message. If the email's character
       
   162 set has been overridden by a prior call to SetCharacterSetL(), the body text is decoded
       
   163 with the new character set before it is inserted into the rich text object. A list containing
       
   164 the entry Ids for each body text part within the specified message is created during this call.
       
   165 The list can be retrieved after this call has completed by calling Selection().
       
   166 
       
   167 @param aStatus
       
   168 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   169 completes.  aStatus should be checked by the caller to ensure that the operation
       
   170 was successful.
       
   171 
       
   172 @param aMessageId
       
   173 The entry Id of the email message that the body text is to be retrieved from.
       
   174 The entry must be of type KUidMsvMessageEntry.
       
   175 
       
   176 @param aEntryType
       
   177 Specifies whether to search just the email message (EThisMessageOnly), 
       
   178 or to search within any embedded messages it may contain (EThisMessageAndEmbeddedMessages).
       
   179 
       
   180 @param aRichText
       
   181 Upon completion, returns the aRichText object that contains the message body text of all text parts found
       
   182 for the message entry specified by aMessageId.  If the body text was not found,
       
   183 then aRichText will be unchanged.
       
   184 
       
   185 @param aParaLayer
       
   186 Paragraph format layer for the rich text object specified by aRichText.
       
   187 
       
   188 @param aCharLayer
       
   189 Character format layer for the rich text object specified by aRichText.
       
   190 
       
   191 @leave KErrNotFound
       
   192 aMessageId entry could not be located.
       
   193 
       
   194 @panic imcm 10
       
   195 aMessageId is not of type KUidMsvMessageEntry.
       
   196 */
       
   197 EXPORT_C void CImEmailMessage::GetBodyTextL(TRequestStatus& aStatus, TMsvId aMessageId, TImEmailEntryType aEntryType, CRichText& aRichText,CParaFormatLayer& aParaLayer, CCharFormatLayer& aCharLayer)
       
   198 	{
       
   199 	DoGetBodyTextInitL(aMessageId, aEntryType, aRichText, aParaLayer, aCharLayer);
       
   200 	Start(aStatus);
       
   201 	}
       
   202 
       
   203 
       
   204 /** 
       
   205 Retrieves the body text for a specified message. If the email's character
       
   206 set has been overridden by a prior call to SetCharacterSetL(), the body text is decoded
       
   207 with the new character set before it is inserted into the rich text object.
       
   208 A list containing the entry Ids for each body text part within the specified message
       
   209 is created during this call. The list can be retrieved by calling Selection().
       
   210 
       
   211 @param aMessageId
       
   212 The entry Id of the email message that the body text is to be retrieved from.
       
   213 The entry must be of type KUidMsvMessageEntry.
       
   214 
       
   215 @param aEntryType
       
   216 Specifies whether to search just the email message (EThisMessageOnly), 
       
   217 or to search within any embedded messages it may contain (EThisMessageAndEmbeddedMessages).
       
   218 
       
   219 @param aRichText
       
   220 Returns the aRichText object that contains the message body text of all text parts found
       
   221 for the message entry specified by aMessageId.  If the body text was not found,
       
   222 then aRichText will be unchanged.
       
   223 
       
   224 @param aParaLayer
       
   225 Paragraph format layer for the rich text object specified by aRichText.
       
   226 
       
   227 @param aCharLayer
       
   228 Character format layer for the rich text object specified by aRichText.
       
   229 
       
   230 @leave KErrNotFound
       
   231 aMessageId entry could not be located.
       
   232 
       
   233 @panic imcm 10
       
   234 aMessageId is not of type KUidMsvMessageEntry.
       
   235 */
       
   236 EXPORT_C void CImEmailMessage::GetBodyTextL(TMsvId aMessageId, TImEmailEntryType aEntryType, CRichText& aRichText,CParaFormatLayer& aParaLayer, CCharFormatLayer& aCharLayer)
       
   237 	{
       
   238 	DoGetBodyTextInitL(aMessageId, aEntryType, aRichText, aParaLayer, aCharLayer);
       
   239 	StartL();
       
   240 	}
       
   241 
       
   242 void CImEmailMessage::DoGetBodyTextInitL(TMsvId aMessageId, TImEmailEntryType aEntryType, CRichText& aRichText,CParaFormatLayer& aParaLayer, CCharFormatLayer& aCharLayer)
       
   243 	{
       
   244 	CheckAndInitialiseL(aMessageId);
       
   245 
       
   246 	if (aEntryType==EThisMessageOnly)
       
   247 		iState=ETextForThisMsg;
       
   248 	else if (aEntryType==EThisMessageAndEmbeddedMessages)
       
   249 		iState=ETextForMsgDigest;
       
   250 	else
       
   251 		User::LeaveIfError(KErrNotSupported);
       
   252 	iEntryType=aEntryType;
       
   253 	iRichText=&aRichText;
       
   254 	iParaLayer=&aParaLayer;
       
   255 	iCharLayer=&aCharLayer;
       
   256 	iCompleteSel->AppendL(iParentMsgId);
       
   257 	// Get the new character set if it has been specified.
       
   258 	iCharacterSetId = GetOverrideCharacterSetL();
       
   259 	}
       
   260 
       
   261 
       
   262 EXPORT_C void CImEmailMessage::GetBodyTextEntryIdL(TRequestStatus& aStatus, TMsvId aMessageId, TImEmailEntryType aEntryType)
       
   263 	{
       
   264 	DoGetBodyTextEntryIdL(aMessageId, aEntryType);
       
   265 	Start(aStatus);
       
   266 	}
       
   267 	
       
   268 EXPORT_C void CImEmailMessage::GetBodyTextEntryIdL(TMsvId aMessageId, TImEmailEntryType aEntryType)
       
   269 	{
       
   270 	DoGetBodyTextEntryIdL(aMessageId, aEntryType);
       
   271 	StartL();
       
   272 	}
       
   273 	
       
   274 void CImEmailMessage::DoGetBodyTextEntryIdL(TMsvId aMessageId, TImEmailEntryType aEntryType)
       
   275 	{
       
   276 	CheckAndInitialiseL(aMessageId);
       
   277 
       
   278 	if (aEntryType==EThisMessageOnly)
       
   279 		iState=ETextEntryIdForThisMsg;
       
   280 	else if (aEntryType==EThisMessageAndEmbeddedMessages)
       
   281 		iState=ETextEntryIdMsgDigest;
       
   282 	else
       
   283 		User::LeaveIfError(KErrNotSupported);
       
   284 	
       
   285 	iEntryType=aEntryType;
       
   286 	iCompleteSel->AppendL(iParentMsgId);
       
   287 	}
       
   288 
       
   289 
       
   290 /**
       
   291 Asynchronously populates a list containing all the attachment entry Ids found that are of a specified
       
   292 type belonging to the specified message. After this function has completed, call AttachmentSelection()
       
   293 to get the list of found attachments. 
       
   294 
       
   295 If the email's character set has been overridden by a prior call
       
   296 to SetCharacterSetL(), the attachment names are decoded with the new character set.
       
   297 
       
   298 @param aStatus
       
   299 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   300 completes.  aStatus should be checked by the caller to ensure that the operation
       
   301 was successful.
       
   302 
       
   303 @param aMessageId
       
   304 The entry Id of the email message that the body text is to be retrieved from.
       
   305 The entry must be of type KUidMsvMessageEntry.
       
   306 
       
   307 @param aAttachmentType
       
   308 The type of attachment to find. Supported attachment 
       
   309 types are EAllAttachments, which would get all attachments for the message, 
       
   310 EVCards that would get all attachments that are VCards, EVCalendars that would 
       
   311 get VCalenders, EICalendar that would get ICalendars, and EVEntries which would get 
       
   312 attachments that are either VCards, VCalendars or ICalendars. EEncrypted, ESigned 
       
   313 and ESecure are currently not supported.
       
   314 
       
   315 @param aEntryType
       
   316 Specifies whether to search just the email message (EThisMessageOnly), 
       
   317 or to search within any embedded messages it may contain (EThisMessageAndEmbeddedMessages).
       
   318 
       
   319 @leave KErrNotFound
       
   320 aMessageId entry could not be located.
       
   321 
       
   322 @panic imcm 10
       
   323 aMessageId is not of type KUidMsvMessageEntry.
       
   324 
       
   325 @leave KErrNotSupported
       
   326 aEntryType is not EThisMessageOnly or EThisMessageAndEmbeddedMessages. 
       
   327 */
       
   328 EXPORT_C void CImEmailMessage::GetAttachmentsListL(TRequestStatus& aStatus, TMsvId aMessageId, TImAttachmentType aAttachmentType,TImEmailEntryType aEntryType)
       
   329 	{
       
   330 	DoGetAttachmentsListL(aMessageId, aAttachmentType, aEntryType);
       
   331 	Start(aStatus);
       
   332 	}
       
   333 
       
   334 
       
   335 /**
       
   336 Populates a list containing all the attachment entry Ids found that are of a specified
       
   337 type belonging to the specified message. After this function has completed, call AttachmentSelection()
       
   338 to get the list of found attachments. 
       
   339 
       
   340 If the email's character set has been overridden by a prior call
       
   341 to SetCharacterSetL(), the attachment names are decoded with the new character set.
       
   342 
       
   343 @param aMessageId
       
   344 The entry Id of the email message that the attachment list is to be populated.
       
   345 The entry must be of type KUidMsvMessageEntry.
       
   346 
       
   347 @param aAttachmentType
       
   348 The type of attachment to find. Supported attachment 
       
   349 types are EAllAttachments, which would get all attachments for the message, 
       
   350 EVCards that would get all attachments that are VCards, EVCalendars that would 
       
   351 get VCalenders, EICalendar that would get ICalendars, and EVEntries which would get 
       
   352 attachments that are either VCards, VCalendars or ICalendars. EEncrypted, ESigned 
       
   353 and ESecure are currently not supported.
       
   354 
       
   355 @param aEntryType
       
   356 Specifies whether to search just the email message (EThisMessageOnly), 
       
   357 or to search within any embedded messages it may contain (EThisMessageAndEmbeddedMessages).
       
   358 
       
   359 @leave KErrNotFound
       
   360 aMessageId entry could not be located.
       
   361 
       
   362 @panic imcm 10
       
   363 aMessageId is not of type KUidMsvMessageEntry.
       
   364 
       
   365 @leave KErrNotSupported
       
   366 aEntryType is not EThisMessageOnly or EThisMessageAndEmbeddedMessages. 
       
   367 */
       
   368 EXPORT_C void CImEmailMessage::GetAttachmentsListL(TMsvId aMessageId, TImAttachmentType aAttachmentType,TImEmailEntryType aEntryType)
       
   369 	{
       
   370 	DoGetAttachmentsListL(aMessageId, aAttachmentType, aEntryType);
       
   371 	StartL();
       
   372 	}
       
   373 
       
   374 	
       
   375 void CImEmailMessage::DoGetAttachmentsListL(TMsvId aMessageId, TImAttachmentType aAttachmentType,TImEmailEntryType aEntryType)
       
   376 	{
       
   377 	CheckAndInitialiseL(aMessageId);
       
   378 
       
   379 
       
   380 	iAttachmentManager->AttachmentInfoSelection().ResetAndDestroy();
       
   381 	
       
   382 	iAttachmentType=aAttachmentType;
       
   383 	if (aEntryType==EThisMessageOnly)
       
   384 		iState=EAttachmentsForThisMsg;
       
   385 	else if (aEntryType==EThisMessageAndEmbeddedMessages)
       
   386 		iState=EAttachmentsForMsgDigest;
       
   387 	else
       
   388 		User::LeaveIfError(KErrNotSupported);
       
   389 	iEntryType=aEntryType;
       
   390 	iCompleteSel->AppendL(iParentMsgId);
       
   391 	}
       
   392 
       
   393 
       
   394 /**
       
   395 Asynchronously populates a list of embedded message entries contained within the specified message.
       
   396 Note that any embedded messages within embedded messages are not included in the list. 
       
   397 Call Selection() to get the results of the search after it has completed. 
       
   398 
       
   399 @param aStatus
       
   400 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   401 completes.  aStatus should be checked by the caller to ensure that the operation
       
   402 was successful.
       
   403 
       
   404 @param aMessageId
       
   405 The entry Id of the email message that will be searched for embedded messages.
       
   406 The entry must be of type KUidMsvMessageEntry.
       
   407 
       
   408 @leave KErrNotFound
       
   409 aMessageId entry could not be located.
       
   410 
       
   411 @panic imcm 10
       
   412 aMessageId is not of type KUidMsvMessageEntry.
       
   413 */
       
   414 EXPORT_C void CImEmailMessage::GetMessageDigestEntriesL(TRequestStatus& aStatus, TMsvId aMessageId)
       
   415 	{
       
   416 	CheckAndInitialiseL(aMessageId);
       
   417 	iState=EMsgDigestEntries;
       
   418 	iCompleteSel->AppendL(iParentMsgId);
       
   419 	Queue(aStatus);
       
   420 	TRequestStatus* status=&iStatus;
       
   421 	iStatus=KRequestPending;
       
   422 	User::RequestComplete(status,KErrNone);
       
   423 	SetActive();
       
   424 	}
       
   425 
       
   426 
       
   427 /**
       
   428 Asynchronously searches for the starting MHTML part embedded in a multipart/related email message.
       
   429 
       
   430 Used when retrieving specific parts of an MHTML message, such as inline images
       
   431 that are referenced as MHTML anchors within the HTML part of a message.  
       
   432 Refer to RFC 2557 - "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)" for information
       
   433 about MHTML email messages.
       
   434 
       
   435 If the starting MHTML part cannot be located, then the first HTML part
       
   436 that occurs within the multipart/related message is located.
       
   437 
       
   438 The result of the search is retrieved by calling GetUniversalResourceIdentifierL() after this methods
       
   439 has completed.
       
   440 
       
   441 @param aMessageId
       
   442 The entry Id of the email message that will be searched.
       
   443 
       
   444 @param aStatus
       
   445 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   446 completes.  aStatus should be checked by the caller to ensure that the operation
       
   447 was successful.
       
   448 
       
   449 @leave KErrNotFound
       
   450 aMessageId entry could not be located.
       
   451 
       
   452 @panic imcm 10
       
   453 aMessageId is not of type KUidMsvMessageEntry.
       
   454 */
       
   455 EXPORT_C void CImEmailMessage::FindFirstHTMLPageL(TMsvId aMessageId, TRequestStatus& aStatus)
       
   456 	{
       
   457 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   458 	__ASSERT_ALWAYS(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
   459 	iUriResolver->FindFirstL(aMessageId,ETrue,iStatus);
       
   460 	Queue(aStatus);
       
   461 	iState = EResolveURI;
       
   462 	SetActive();
       
   463 	}
       
   464 
       
   465 /**
       
   466 Asynchronously searches a message entry for an MHTML URI, and resolves it to the message entry that
       
   467 contains the message part specified by the URI.
       
   468 
       
   469 Used when retrieving specific parts of an MHTML message, such as inline images
       
   470 that are referenced as MHTML anchors within the HTML part of a message.  
       
   471 Refer to RFC 2557 - "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)" for information
       
   472 about MHTML email messages.
       
   473 
       
   474 The result of the search is retrieved by calling GetUniversalResourceIdentifierL() after this method
       
   475 has completed.
       
   476 
       
   477 @param aMessageId
       
   478 The message Id of the body part that is to be searched for the URI.
       
   479 In the first instance, this value should be the starting MHTML entry Id that was located
       
   480 by calling FindFirstHTMLPageL().
       
   481 
       
   482 @param aBase
       
   483 The base URI to use when searching for aURI if aURI is relative.
       
   484 If aBase is empty, and aURI is relative, then the Content-location
       
   485 MIME header contained within the HTML part specified by aMessageId is used as a base.
       
   486 If the Content-location header does not exist or is not absolute, then
       
   487 just the relative aURI is searched for. 
       
   488 
       
   489 
       
   490 @param aURI
       
   491 The absolute or relative URI to resolve.  If aURI is absolute, then aBase is ignored
       
   492 and this method completes faster.  If aURI is relative, then aBase is used as a base
       
   493 to resolve the relative URI.  If aBase is empty and aURI is relative, then the 
       
   494 Content-location MIME header contained within the HTML part specified by aMessageId is
       
   495 used as the base.  If the Content-location header does not exist or is not absolute, then
       
   496 just the relative aURI is searched for.
       
   497 
       
   498 @param aStatus
       
   499 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   500 completes.  aStatus should be checked by the caller to ensure that the operation
       
   501 was successful.
       
   502 
       
   503 @leave KErrNotFound
       
   504 aMessageId entry could not be located.
       
   505 
       
   506 @panic imcm 10
       
   507 aMessageId is not of type KUidMsvMessageEntry.
       
   508 */
       
   509 EXPORT_C void CImEmailMessage::FindUniversalResourceIdentifierL(TMsvId aMessageId, const TDesC& aBase, const TDesC& aURI, TRequestStatus &aStatus)
       
   510 	{
       
   511 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   512 	__ASSERT_ALWAYS(entry.iType==KUidMsvEmailHtmlEntry, gPanic(EEntryIsNotMessage));
       
   513 	iUriFileFound = EFalse;
       
   514 	iUriResolver->ResolveL(aURI, aBase, aMessageId,ETrue,iStatus);
       
   515 	Queue(aStatus);
       
   516 	iState = EResolveURI;
       
   517 	SetActive();
       
   518 	}
       
   519 
       
   520 /**
       
   521 Gets the results from FindUniversalResourceIdentifierL() or FindFirstHTMLPageL() 
       
   522 method calls when they have completed. 
       
   523 
       
   524 Used when retrieving specific parts of an MHTML message, such as inline images
       
   525 that are referenced as MHTML anchors within the HTML part of a message.  
       
   526 Refer to RFC 2557 - "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)" for information
       
   527 about MHTML email messages.
       
   528 
       
   529 @pre
       
   530 FindUniversalResourceIdentifierL() or FindFirstHTMLPageL() must have been called
       
   531 prior and completed successfully.
       
   532 
       
   533 @param aLinkedEntryId
       
   534 Returns the message Id of the message entry that contains the resolved body part, providing 
       
   535 one is found. Note that you should keep a record of the returned message Id 
       
   536 as it is required for resolving any URI's that may be found in the resolved body part.
       
   537 
       
   538 @param aFileFound
       
   539 Returns ETrue if the URI has been resolved and the message entry containing the MHTML part has been
       
   540 located. Returns EFalse otherwise.
       
   541 
       
   542 @return
       
   543 If the URI is resolved, returns the full path specification and file name of the file containing the HTML,
       
   544 image, or other such content stored in the message store.  If no file can be located, the absolute URI is returned
       
   545 instead.
       
   546 */
       
   547 EXPORT_C HBufC* CImEmailMessage::GetUniversalResourceIdentifierL(TMsvId& aLinkedEntryId, TBool& aFileFound) const
       
   548 	{
       
   549 	aLinkedEntryId = iUriResolver->LinkedEntryId();
       
   550 	aFileFound = iUriFileFound;
       
   551 	return iUriResolver->FileNameL();
       
   552 	}
       
   553 
       
   554 /**
       
   555 Asynchronously searches for the starting MHTML part embedded in a multipart/related email message.
       
   556 
       
   557 Used when retrieving specific parts of an MHTML message, such as inline images
       
   558 that are referenced as MHTML anchors within the HTML part of a message.  
       
   559 Refer to RFC 2557 - "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)" for information
       
   560 about MHTML email messages.
       
   561 
       
   562 If the starting MHTML part cannot be located, then the first HTML part
       
   563 that occurs within the multipart/related message is located.
       
   564 
       
   565 The result of the search is retrieved by calling GetUniversalResourceIdentifierFileHandle() after this methods
       
   566 has completed.
       
   567 
       
   568 @param aMessageId
       
   569 The entry Id of the email message that will be searched.
       
   570 
       
   571 @param aStatus
       
   572 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   573 completes.  aStatus should be checked by the caller to ensure that the operation
       
   574 was successful.
       
   575 
       
   576 @leave KErrNotFound
       
   577 aMessageId entry could not be located.
       
   578 
       
   579 @panic imcm 10
       
   580 aMessageId is not of type KUidMsvMessageEntry.
       
   581 */
       
   582 EXPORT_C void CImEmailMessage::FindFirstHTMLPageFileHandleL(TMsvId aMessageId, TRequestStatus& aStatus)
       
   583 	{
       
   584 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   585 	__ASSERT_ALWAYS(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
   586 	
       
   587 	iUriResolver->FindFirstL(aMessageId,EFalse,iStatus);
       
   588 	Queue(aStatus);
       
   589 	iState = EResolveURI;
       
   590 	SetActive();
       
   591 	}
       
   592 
       
   593 /**
       
   594 Asynchronously searches a message entry for an MHTML URI, and resolves it to the message entry that
       
   595 contains the message part specified by the URI.
       
   596 
       
   597 Used when retrieving specific parts of an MHTML message, such as inline images
       
   598 that are referenced as MHTML anchors within the HTML part of a message.  
       
   599 Refer to RFC 2557 - "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)" for information
       
   600 about MHTML email messages.
       
   601 
       
   602 The result of the search is retrieved by calling GetUniversalResourceIdentifierFileHandle() after this method
       
   603 has completed.
       
   604 
       
   605 @param aMessageId
       
   606 The message Id of the body part that is to be searched for the URI.
       
   607 In the first instance, this value should be the starting MHTML entry Id that was located
       
   608 by calling FindFirstHTMLPageFileHandleL().
       
   609 
       
   610 @param aBase
       
   611 The base URI to use when searching for aURI if aURI is relative.
       
   612 If aBase is empty, and aURI is relative, then the Content-location
       
   613 MIME header contained within the HTML part specified by aMessageId is used as a base.
       
   614 If the Content-location header does not exist or is not absolute, then
       
   615 just the relative aURI is searched for. 
       
   616 
       
   617 
       
   618 @param aURI
       
   619 The absolute or relative URI to resolve.  If aURI is absolute, then aBase is ignored
       
   620 and this method completes faster.  If aURI is relative, then aBase is used as a base
       
   621 to resolve the relative URI.  If aBase is empty and aURI is relative, then the 
       
   622 Content-location MIME header contained within the HTML part specified by aMessageId is
       
   623 used as the base.  If the Content-location header does not exist or is not absolute, then
       
   624 just the relative aURI is searched for.
       
   625 
       
   626 @param aStatus
       
   627 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   628 completes.  aStatus should be checked by the caller to ensure that the operation
       
   629 was successful.
       
   630 
       
   631 @leave KErrNotFound
       
   632 aMessageId entry could not be located.
       
   633 
       
   634 @panic imcm 10
       
   635 aMessageId is not of type KUidMsvMessageEntry.
       
   636 */
       
   637 EXPORT_C void CImEmailMessage::FindUniversalResourceIdentifierFileHandleL(TMsvId aMessageId, const TDesC& aBase, const TDesC& aURI, TRequestStatus &aStatus)
       
   638 	{
       
   639 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   640 	__ASSERT_ALWAYS(entry.iType==KUidMsvEmailHtmlEntry, gPanic(EEntryIsNotMessage));
       
   641 	iUriFileFound = EFalse;
       
   642 	//Browsers always append "amp;", when "&" is found while writing URLs in HTML
       
   643 	//replacing "&amp;" with "&", before resolving the URLs
       
   644 	// eg : if the content location of the image is as below
       
   645 	// https://www.ttdm.symbian.com/tmtrack.dll?AttachmentPage&AttachmentID=552810/Morning.jpg
       
   646 	// then the browsers writes this to hmtl file by appending "amp;" after "&" because browsers
       
   647 	// treat "&" as special character. After apending, the content-location now looks as below
       
   648 	// https://www.ttdm.symbian.com/tmtrack.dll?AttachmentPage&amp;AttachmentID=552810/Morning.jpg
       
   649 	const TDesC& ampersand = KMhtmlUrlAmpersand;
       
   650 	TInt embedUrlIndex;
       
   651 	if((embedUrlIndex = aBase.Find(ampersand))!=KErrNotFound)
       
   652 		{
       
   653 		HBufC* embedUrl = aBase.AllocLC();
       
   654 		TPtr embedUrlPtr = embedUrl->Des();
       
   655 		embedUrlPtr.Delete(embedUrlIndex+1, 4);
       
   656 		iUriResolver->ResolveL(embedUrlPtr, embedUrlPtr, aMessageId,EFalse, iStatus);
       
   657 		CleanupStack::PopAndDestroy(); //embedUrl
       
   658 		}
       
   659 	else 
       
   660 		{
       
   661 		iUriResolver->ResolveL(aURI, aBase, aMessageId,EFalse, iStatus);
       
   662 		} 
       
   663 
       
   664 	Queue(aStatus);
       
   665 	iState = EResolveURI;
       
   666 	SetActive();
       
   667 	}
       
   668 	
       
   669 /**
       
   670 Gets the results from FindUniversalResourceIdentifierFileHandleL() or FindFirstHTMLPageFileHandleL() 
       
   671 method calls when they have completed. 
       
   672 
       
   673 Used when retrieving specific parts of an MHTML message, such as inline images
       
   674 that are referenced as MHTML anchors within the HTML part of a message.  
       
   675 Refer to RFC 2557 - "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)" for information
       
   676 about MHTML email messages.
       
   677 
       
   678 @pre
       
   679 FindUniversalResourceIdentifierFileHandleL() or FindFirstHTMLPageFileHandleL() must have been called
       
   680 prior and completed successfully.
       
   681 
       
   682 @param aLinkedEntryId
       
   683 Returns the message Id of the message entry that contains the resolved body part, providing 
       
   684 one is found. Note that you should keep a record of the returned message Id 
       
   685 as it is required for resolving any URI's that may be found in the resolved body part.
       
   686 
       
   687 @param aFile
       
   688 Returns the file handle of the file containing the HTML,image, or other such 
       
   689 content stored in the message store if the URI has been resolved. If not then
       
   690 this argument is not valid. Ownership is transferred. The caller must close the file handle.
       
   691 
       
   692 @return
       
   693 If the URI is resolved, returns KErrNone. The output argument aFile is the file
       
   694 handle to the content. If no file is located the KErrNotFound is returned and 
       
   695 aFile is not valid.
       
   696 */
       
   697 EXPORT_C TInt CImEmailMessage::GetUniversalResourceIdentifierFileHandle(TMsvId& aLinkedEntryId, RFile& aFile) const
       
   698 	{
       
   699 	aLinkedEntryId = iUriResolver->LinkedEntryId();
       
   700 	return iUriResolver->FileHandle(aFile);
       
   701 	}
       
   702 
       
   703 /**
       
   704 Returns a selection of entries. The entries are either the results of GetMessageDigestEntriesL(), 
       
   705 or of GetBodyTextL().
       
   706 
       
   707 @pre
       
   708 GetMessageDigestEntriesL() or GetBodyTextL() must be called prior and successfully completed.
       
   709 
       
   710 @return
       
   711 Selection of entries populated by GetMessageDigestEntriesL() or GetBodyTextL().
       
   712 */
       
   713 EXPORT_C const CMsvEntrySelection& CImEmailMessage::Selection() const
       
   714 	{
       
   715 	return *iResultSel;
       
   716 	}
       
   717 	
       
   718 
       
   719 /**
       
   720 Returns a message entry Id as a type-safe package buffer (TPckg<TMsvId>).
       
   721 The meaning of the Id depends on the request as follows:
       
   722 
       
   723 AddAttachmentL(), AddMessageAsAttachmentL(), and AddRelatedPartL():
       
   724 While the attachment, message, or related part is being added, a null Id 
       
   725 (KMsvNullIndexEntryId); Once the attachment, message, or related part has been added, the entry Id
       
   726 of the newly created attachment, message, or related part.
       
   727 
       
   728 DeleteAttachmentL() and DeleteAttachedMessageL(): While the attachment or attached 
       
   729 message is being removed, a null Id (KMsvNullIndexEntryId); Once the attachment
       
   730 or attached message has been removed, the Id of the message from which the
       
   731 attachment or attached message was removed.
       
   732 
       
   733 StoreBodyTextL(): While the body text is being stored, a null Id (KMsvNullIndexEntryId);
       
   734 Once the text has been stored, the Id of the message for which the body text was 
       
   735 stored.
       
   736 
       
   737 @pre
       
   738 Call this method after the following asynchronous calls have completed to check progress.
       
   739 AddAttachmentL()
       
   740 AddMessageAsAttachmentL()
       
   741 AddRelatedPartL()
       
   742 DeleteAttachmentL()
       
   743 DeleteAttachedMessageL()
       
   744 StoreBodyTextL()
       
   745 
       
   746 @code
       
   747 // Example code demonstrating how to retrieve the progress.
       
   748 
       
   749 // Create and initialise a temporary TPckg object that can hold a message Id.
       
   750 TMsvId msgId;
       
   751 TPckg<TMsvId> param(msgId);
       
   752 
       
   753 // Copy the message Id returned from the ProgressL() call into the
       
   754 // temporary TPckg object.
       
   755 param.Copy(emailMsg->ProgressL());  // where emailMsg is of type CImEmailMessage.
       
   756 
       
   757 // Check the value of the returned message Id in the TPckg object.
       
   758 if (msgId != KMsvNullIndexEntryId)
       
   759 	{
       
   760 	// More code...
       
   761 	} 
       
   762 @endcode
       
   763 
       
   764 @return
       
   765 The entry Id as a type-safe packaged buffer (TPckg<TMsvId>).
       
   766 */
       
   767 EXPORT_C const TDesC8& CImEmailMessage::ProgressL() const
       
   768 	{
       
   769 	return iProgress;
       
   770 	}
       
   771 	
       
   772 
       
   773 /**
       
   774 Adds a file to a specified message as a MIME multipart/related part. After the
       
   775 call has completed, calling ProgressL() will return the Id of the newly created
       
   776 related part entry.
       
   777 
       
   778 Used when adding specific parts of an MHTML message, such as inline images
       
   779 that are referenced as MHTML anchors within the HTML part of a message.  
       
   780 Refer to RFC 2557 - "MIME Encapsulation of Aggregate Documents, such as HTML (MHTML)" for information
       
   781 about MHTML email messages.
       
   782 
       
   783 @pre
       
   784 This function should only be used on messages created using CImEmailOperation.
       
   785 
       
   786 @param aMessageId
       
   787 The entry Id of the email message that the related part will be added to.
       
   788 The entry must be of type KUidMsvMessageEntry.
       
   789 
       
   790 @param aAttachmentFullName
       
   791 The full path and file name of the related part file to be copied to the message store.
       
   792 If the file cannot be located, this call completes with KErrNotFound.
       
   793 
       
   794 @param aStatus
       
   795 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   796 completes. aStatus should be checked by the caller to ensure that the operation
       
   797 was successful.
       
   798 
       
   799 @param aRelatedPartId
       
   800 The entry Id of the MHTML message part that the file being added is referenced from.
       
   801 
       
   802 @param aContentId
       
   803 The Content-Id of the related part.
       
   804 
       
   805 @leave KErrNotFound
       
   806 aMessageId entry could not be located.
       
   807 
       
   808 @panic imcm 10
       
   809 aMessageId is not of type KUidMsvMessageEntry.
       
   810 */
       
   811 EXPORT_C void CImEmailMessage::AddRelatedPartL(TMsvId aMessageId, const TDesC& aAttachmentFullName, TRequestStatus& aStatus, TMsvId aRelatedPartId, const TDesC8& aContentId)
       
   812 	{
       
   813 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   814 	__ASSERT_ALWAYS(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
   815 
       
   816 	// adds 'object' with name aAttachmentFullName related to aRelatedPartId in Multipart/Related Folder
       
   817 	CImStoreMessagePart* temp = CImStoreMessagePart::AddRelatedPartL(iStatus, iClientEntry, aMessageId, aAttachmentFullName, aRelatedPartId, aContentId);
       
   818 	delete iStoreMessagePart;
       
   819 	iStoreMessagePart = temp;
       
   820 	Queue(aStatus);
       
   821 	iState = EStoreMessagePart;
       
   822 	SetActive();
       
   823 	}
       
   824 
       
   825 
       
   826 /** 
       
   827 Asynchronously stores a body text part for the specified message. After the call
       
   828 has completed, calling ProgressL() will return the Id of the message entry for
       
   829 which the body text was stored.
       
   830  
       
   831 @pre
       
   832 This function should only be used on messages created using CImEmailOperation.
       
   833 
       
   834 @param aMessageId
       
   835 The entry Id of the email message that the body text will be stored in.
       
   836 The entry must be of type KUidMsvMessageEntry.
       
   837 
       
   838 @param aRichText
       
   839 A rich text object (CRichText) that contains the message body text.
       
   840 
       
   841 @param aStatus
       
   842 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   843 completes. aStatus should be checked by the caller to ensure that the operation
       
   844 was successful.
       
   845 
       
   846 @leave KErrNotFound
       
   847 aMessageId entry could not be located.
       
   848 
       
   849 @panic imcm 10
       
   850 aMessageId is not of type KUidMsvMessageEntry.
       
   851 */
       
   852 EXPORT_C void CImEmailMessage::StoreBodyTextL(TMsvId aMessageId, CRichText& aRichText, TRequestStatus& aStatus)
       
   853 	{
       
   854 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   855 	__ASSERT_ALWAYS(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
   856 	delete iStoreMessagePart;
       
   857 	iStoreMessagePart = NULL;
       
   858 	iStoreMessagePart = CImStoreMessagePart::StoreBodyTextL(iStatus, iClientEntry, aMessageId, aRichText);
       
   859 	Queue(aStatus);
       
   860 	iState = EStoreMessagePart;
       
   861 	SetActive();
       
   862 	}
       
   863 
       
   864 /** 
       
   865 Asynchronously stores a body text part for the specified message. After the call
       
   866 has completed, calling ProgressL() will return the Id of the message entry for
       
   867 which the body text was stored.
       
   868  
       
   869 @pre
       
   870 This function should only be used on messages created using CImEmailOperation.
       
   871 
       
   872 @param aMessageId
       
   873 The entry Id of the email message that the body text will be stored in.
       
   874 The entry must be of type KUidMsvMessageEntry.
       
   875 
       
   876 @param aRichText
       
   877 A rich text object (CRichText) that contains the message body text.
       
   878 
       
   879 @param aStatus
       
   880 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   881 completes. aStatus should be checked by the caller to ensure that the operation
       
   882 was successful.
       
   883 
       
   884 @param aUsePlainTextStorage		
       
   885 if set to ETrue inidcates that the new message entry needs to be created as plain text
       
   886 if set to EFalse indicates that message will be created as richtext entry.
       
   887 
       
   888 @leave KErrNotFound
       
   889 aMessageId entry could not be located.
       
   890 
       
   891 @panic imcm 10
       
   892 aMessageId is not of type KUidMsvMessageEntry.
       
   893 */	
       
   894 EXPORT_C void CImEmailMessage::StoreBodyTextL(TMsvId aMessageId, CRichText& aRichText, TRequestStatus& aStatus, TBool aUsePlainTextStorage)
       
   895 	{
       
   896 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   897 	__ASSERT_ALWAYS(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
   898 	delete iStoreMessagePart;
       
   899 	iStoreMessagePart = NULL;
       
   900 	iStoreMessagePart = CImStoreMessagePart::StoreBodyTextL(iStatus, iClientEntry, aMessageId, aRichText, aUsePlainTextStorage);
       
   901 	Queue(aStatus);
       
   902 	iState = EStoreMessagePart;
       
   903 	SetActive();
       
   904 	}	
       
   905 	
       
   906 /** 
       
   907 Asynchronously stores a body text part for the specified message. A Mime header
       
   908 is created with the passed in the CImMimeHeader object passed.
       
   909 After the call has completed, calling ProgressL() will return the Id of 
       
   910 the message entry for which the body text was stored.
       
   911  
       
   912 @pre
       
   913 This function should only be used on messages created using CImEmailOperation.
       
   914 
       
   915 @param aMessageId
       
   916 The entry Id of the email message that the body text will be stored in.
       
   917 The entry must be of type KUidMsvMessageEntry.
       
   918 
       
   919 @param aRichText
       
   920 A rich text object (CRichText) that contains the message body text.
       
   921 
       
   922 @param aMimeHeader
       
   923 A MIME header object (CImMimeHeader) that contains the content-type etc.
       
   924 
       
   925 @param aStatus
       
   926 Asynchronous status object (TRequestStatus) that is signalled when the operation
       
   927 completes. aStatus should be checked by the caller to ensure that the operation
       
   928 was successful.
       
   929 
       
   930 @leave KErrNotFound
       
   931 aMessageId entry could not be located.
       
   932 
       
   933 @panic imcm 10
       
   934 aMessageId is not of type KUidMsvMessageEntry.
       
   935 */
       
   936 EXPORT_C void CImEmailMessage::StoreBodyTextWithMimeHeaderL(TMsvId aMessageId, CRichText& aRichText, const CImMimeHeader& aMimeHeader, TRequestStatus& aStatus)
       
   937 	{
       
   938 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
   939 	__ASSERT_ALWAYS(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
   940 	delete iStoreMessagePart;
       
   941 	iStoreMessagePart = NULL;
       
   942 	iStoreMessagePart = CImStoreMessagePart::StoreBodyTextWithMimeHeaderL(iStatus, iClientEntry, aMessageId, aRichText, aMimeHeader);
       
   943 	Queue(aStatus);
       
   944 	iState = EStoreMessagePart;
       
   945 	SetActive();
       
   946 	}
       
   947 
       
   948 /**
       
   949 Returns the character set Id that the body text will be decoded in when it is 
       
   950 returned in the call to GetBodyTextL(). It also indicates whether the original
       
   951 character set has been overridden by calling SetCharacterSetL().
       
   952 
       
   953 @pre
       
   954 The store_8bit_body_text flag in imcm.rss should be enabled. This is done at build
       
   955 time by the manufacturer.
       
   956 
       
   957 @param aMessageId
       
   958 The entry Id of the email message that the character set Id is to be retrieved from.
       
   959 The entry must be of type KUidMsvMessageEntry.
       
   960 
       
   961 @param aCharacterSetId
       
   962 Returns the character set Id that the message will be displayed when it is viewed.
       
   963 If aCharacterSetId is zero and aOverride is EFalse, the store_8bit_body_text flag
       
   964 in imcm.rss has not been enabled.  
       
   965 
       
   966 @param aOverride
       
   967 Returns ETrue if the message's original character set has been overridden (changed)
       
   968 via the call to SetCharacterSetL(). If aCharacterSetId is zero and aOverride is EFalse,
       
   969 the store_8bit_body_text flag in imcm.rss has not been enabled.
       
   970 
       
   971 @leave KErrNotFound
       
   972 aMessageId entry could not be located.
       
   973 
       
   974 @panic imcm 10
       
   975 aMessageId is not of type KUidMsvMessageEntry.
       
   976 */
       
   977 EXPORT_C void CImEmailMessage::GetCharacterSetL(TMsvId aMessageId, TUint& aCharacterSetId, TBool& aOverride)
       
   978 	{
       
   979 	CheckAndInitialiseL(aMessageId);
       
   980 	aCharacterSetId = GetOverrideCharacterSetL();
       
   981 	if (aCharacterSetId == 0)
       
   982 		{
       
   983 		// The user has not changed the character set.  Return the body text character set.
       
   984 		aOverride = EFalse;
       
   985 		iState = ETextForThisMsgGetCharacterSet;
       
   986 		iEntryType = EThisMessageOnly;
       
   987 		iCompleteSel->AppendL(aMessageId);
       
   988 		StartL();
       
   989 		aCharacterSetId = iCharacterSetId;
       
   990 		}
       
   991 	else
       
   992 		{
       
   993 		aOverride = ETrue;
       
   994 		}
       
   995 	}
       
   996 
       
   997 
       
   998 /**
       
   999 Stores the new character set that the message will be displayed as next time
       
  1000 it is viewed.
       
  1001 
       
  1002 @pre
       
  1003 The store_8bit_body_text flag in imcm.rss should be enabled. This is done at build
       
  1004 time by the manufacturer.
       
  1005 
       
  1006 @param aMessageId
       
  1007 The entry Id of the email message that the character set will be returned from.
       
  1008 The entry must be of type KUidMsvMessageEntry.
       
  1009 
       
  1010 @param aCharacterSetId
       
  1011 The character set Id to be stored in the message store.  Setting this value to
       
  1012 zero will cause the message to be displayed in its original character set when
       
  1013 it was viewed for the first time after it was downloaded.
       
  1014 
       
  1015 @leave KErrNotFound
       
  1016 aMessageId entry can not be located in the message store, or the character set
       
  1017 information can not be located. If the character set information cannot be
       
  1018 located, it could be because it was not stored when downloaded. To enable this
       
  1019 functionality set the store_8bit_body_text flag in imcm.rss.
       
  1020 It is also possible that a call to StoreBodyTextL() has overwritten
       
  1021 the original character set stored when the message was downloaded.
       
  1022 
       
  1023 @panic imcm 10
       
  1024 aMessageId is not of type KUidMsvMessageEntry.
       
  1025 */
       
  1026 EXPORT_C void CImEmailMessage::SetCharacterSetL(TMsvId aMessageId, TUint aCharacterSetId)
       
  1027 	{
       
  1028 	CheckAndInitialiseL(aMessageId);
       
  1029 	CMsvStore* store = iClientEntry.EditStoreL();
       
  1030 	CleanupStack::PushL(store);
       
  1031 	
       
  1032 	// If the character set is zero, remove the new character set stream so that the original
       
  1033 	// character set from the body text will be returned when GetCharacterSetL is called.
       
  1034 	if (aCharacterSetId == 0)
       
  1035 		{
       
  1036 		if (store->IsPresentL(KMessageCharSetStreamUid))
       
  1037 			{
       
  1038 			store->RemoveL(KMessageCharSetStreamUid);
       
  1039 			store->CommitL();
       
  1040 			}
       
  1041 		CleanupStack::PopAndDestroy(store);
       
  1042 		return;
       
  1043 		}
       
  1044 		
       
  1045 	// Write the new character set to the store.
       
  1046 	RMsvWriteStream out;
       
  1047 	out.AssignLC(*store, KMessageCharSetStreamUid);
       
  1048 	out.WriteUint8L(KMessageCharSetStreamVersion);
       
  1049 	out.WriteUint32L(aCharacterSetId);
       
  1050 	out.CommitL();
       
  1051 	store->CommitL();
       
  1052 	CleanupStack::PopAndDestroy(2, store); //out, store.
       
  1053 	}
       
  1054 
       
  1055 
       
  1056 void CImEmailMessage::CheckAndInitialiseL(TMsvId aMessageId)
       
  1057 	{
       
  1058 	iClientEntry.SetEntryNoCheckL(aMessageId);
       
  1059 	const TMsvEmailEntry& entry=iClientEntry.Entry();
       
  1060 	__ASSERT_ALWAYS(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
  1061 	iParentMsgId=aMessageId;
       
  1062 	iIsAMHTMLmessage=entry.MHTMLEmail();
       
  1063 	iCharacterSetId = 0;
       
  1064 	Reset();
       
  1065 	}
       
  1066 
       
  1067 
       
  1068 void CImEmailMessage::Reset()
       
  1069 	{
       
  1070 	iState=EIdle;
       
  1071 	iCompleteSel->Reset();
       
  1072 	iResultSel->Reset();
       
  1073 	iAttachmentManager->AttachmentInfoSelection().ResetAndDestroy();
       
  1074 	iAttachmentNameList->Reset();
       
  1075 	}
       
  1076 
       
  1077 
       
  1078 void CImEmailMessage::DoCancel()
       
  1079 	{
       
  1080 	Reset();
       
  1081 	iUriResolver->Cancel();
       
  1082 	if (iStoreMessagePart)
       
  1083 		iStoreMessagePart->Cancel();
       
  1084 	if (iRemoveMessagePart)
       
  1085 		iRemoveMessagePart->Cancel();
       
  1086 	CMsgActive::DoCancel();
       
  1087 	}
       
  1088 
       
  1089 
       
  1090 void CImEmailMessage::DoComplete(TInt& aStatus)
       
  1091 	{//set back to the context the user passed in
       
  1092 	TRAPD(error, iClientEntry.SetEntryL(iParentMsgId));
       
  1093     if(aStatus == KErrNone)
       
  1094 	{
       
  1095 	    aStatus = error;   	
       
  1096 	}
       
  1097 	}
       
  1098 
       
  1099 
       
  1100 void CImEmailMessage::DoStateL()
       
  1101 	{
       
  1102 	switch (iState)
       
  1103 		{
       
  1104 	case EResolveURI:
       
  1105 		iUriFileFound = (iStatus == KErrNone) ? ETrue : EFalse;
       
  1106 		iState = EIdle;
       
  1107 		return;
       
  1108 	case EStoreMessagePart:
       
  1109 		iProgress.Copy(iStoreMessagePart->ProgressL());
       
  1110 		if(iAttachmentState == EAddAttachment || iAttachmentState == ECreateAttachment)
       
  1111 			{
       
  1112 			TMsvId attachmentId =  iProgress();
       
  1113 			iAttachmentManager->AppendAttachmentArrayL(attachmentId);
       
  1114 			// Once the file is attached to email, reseting the iAttachmentState
       
  1115 			iAttachmentState = ENoAttachment;
       
  1116 			}
       
  1117 		iState = EIdle;
       
  1118 		return;
       
  1119 	case ERemoveMessagePart:
       
  1120 		iProgress.Copy(iRemoveMessagePart->ProgressL());
       
  1121 		if(iAttachmentState ==  EDeleteAttachment)
       
  1122 			{
       
  1123 			TMsvId deletedAttachmentId = iRemoveMessagePart->RemovedAttachmentId();
       
  1124 			// check whether we currently have a cache of the attachments before
       
  1125 			// trying to delete the one we have removed.
       
  1126 			if(iAttachmentManager->AttachmentCount()!=0)
       
  1127 				{			
       
  1128 				iAttachmentManager->DeleteAttachmentInArrayL(deletedAttachmentId);
       
  1129 				}
       
  1130 			}
       
  1131 		
       
  1132 		iState = EIdle;
       
  1133 		return;
       
  1134 	case EFinished:
       
  1135 		return;
       
  1136 	case ETextForThisMsg:
       
  1137 	case ETextForThisMsgGetCharacterSet:
       
  1138 	case ETextForMsgDigest:
       
  1139 	case ETextEntryIdForThisMsg:
       
  1140 	case ETextEntryIdMsgDigest:
       
  1141 	case EAttachmentsForThisMsg:
       
  1142 	case EAttachmentsForMsgDigest:
       
  1143 	case EMsgDigestEntries:
       
  1144 		ChangeMessageContextL();
       
  1145 		break;
       
  1146 	default:
       
  1147 		break;
       
  1148 		};
       
  1149 	}
       
  1150 
       
  1151 
       
  1152 void CImEmailMessage::Start(TRequestStatus& aStatus)
       
  1153 	{
       
  1154 	Queue(aStatus);
       
  1155 	TRequestStatus* status=&iStatus;
       
  1156 	iStatus=KRequestPending;
       
  1157 	User::RequestComplete(status,KErrNone);
       
  1158 	SetActive();
       
  1159 	}
       
  1160 
       
  1161 
       
  1162 void CImEmailMessage::StartL()
       
  1163 	{
       
  1164 	TRAPD(error, do DoStateL(); while(iState != EIdle && iState != EFinished););
       
  1165 	DoComplete(error);
       
  1166 	User::LeaveIfError(error);
       
  1167 	}
       
  1168 
       
  1169 
       
  1170 void CImEmailMessage::DoRunL()
       
  1171 	{
       
  1172 	DoStateL();
       
  1173 	if (iState != EIdle && iState != EFinished)
       
  1174 		{
       
  1175 		TRequestStatus* status=&iStatus;
       
  1176 		iStatus=KRequestPending;
       
  1177 		User::RequestComplete(status,KErrNone);
       
  1178 		SetActive();
       
  1179 		}
       
  1180 	}
       
  1181 
       
  1182 
       
  1183 /**
       
  1184 This function takes the first id in iCompleteSel and sets the context to 
       
  1185 that and appends its children to the same list and deletes the id(current) after it has finished with it.
       
  1186 */
       
  1187 void CImEmailMessage::ChangeMessageContextL()
       
  1188 	{
       
  1189 	iClientEntry.SetEntryL((*iCompleteSel)[0]);
       
  1190 	iEntry=iClientEntry.Entry();
       
  1191 	TUid type=iEntry.iType;
       
  1192 	TBool searchChildren=ETrue;
       
  1193 	
       
  1194 	switch (type.iUid)
       
  1195 		{
       
  1196 		case KUidMsvFolderEntryValue:
       
  1197 			{
       
  1198 			searchChildren=HandleDifferentFolderTypesL();
       
  1199 			break;
       
  1200 			}
       
  1201 		case KUidMsvAttachmentEntryValue:
       
  1202 			{
       
  1203 			if (iState==EAttachmentsForThisMsg || iState==EAttachmentsForMsgDigest)
       
  1204 				AttachmentInfoL();
       
  1205 			break;
       
  1206 			}
       
  1207 		case KUidMsvEmailTextEntryValue:
       
  1208 			{
       
  1209 			switch (iState)
       
  1210 				{
       
  1211 				case ETextForThisMsg:
       
  1212 				case ETextForMsgDigest:
       
  1213 					{
       
  1214 					iResultSel->AppendL((*iCompleteSel)[0]);
       
  1215 					AssembleBodyTextL();
       
  1216 					break;
       
  1217 					}
       
  1218 
       
  1219 				case ETextEntryIdForThisMsg:
       
  1220 				case ETextEntryIdMsgDigest:
       
  1221 					{
       
  1222 					iResultSel->AppendL((*iCompleteSel)[0]);
       
  1223 					break;
       
  1224 					}
       
  1225 
       
  1226 				case ETextForThisMsgGetCharacterSet:
       
  1227 					{
       
  1228 					if (GetBodyTextCharacterSetL())
       
  1229 						{
       
  1230 						// Found an 8 bit body text part.  The character set is the
       
  1231 						// same for every 8 bit body text part so we can return immediately.
       
  1232 						iCompleteSel->Reset();
       
  1233 						iState=EFinished;
       
  1234 						return;
       
  1235 						}
       
  1236 					break;
       
  1237 					}
       
  1238 				default:
       
  1239 					{
       
  1240 					break;
       
  1241 					}
       
  1242 				}
       
  1243 			break;
       
  1244 			}
       
  1245 		case KUidMsvMessageEntryValue:
       
  1246 			{
       
  1247 			//check if user requested for this entry or digest entry and terminate accordingly.   
       
  1248 			if ((*iCompleteSel)[0]!=iParentMsgId)
       
  1249 				{
       
  1250 				// we have a entry attachment, append this to the list of attachments
       
  1251 				AppendEntryAttachmentInfoL();
       
  1252 				if (iEntryType==EThisMessageOnly || iState==EMsgDigestEntries)
       
  1253 					{
       
  1254 					searchChildren=EFalse;
       
  1255 					if (iState==EMsgDigestEntries)
       
  1256 						iResultSel->AppendL((*iCompleteSel)[0]);
       
  1257 					}
       
  1258 				}
       
  1259 			break;
       
  1260 			}
       
  1261 		default:
       
  1262 			{
       
  1263 			break;
       
  1264 			}
       
  1265 		};
       
  1266 	
       
  1267 	TInt index=iCompleteSel->Find(iEntry.Id());
       
  1268 	iCompleteSel->Delete(index);
       
  1269 	if (searchChildren)
       
  1270 		CompareChildrenAndPopulateSelL();
       
  1271 	if (!iCompleteSel->Count()) 
       
  1272 		{
       
  1273 		iState=EFinished;
       
  1274 		return;
       
  1275 		}
       
  1276 	}
       
  1277 
       
  1278 
       
  1279 void CImEmailMessage::CompareChildrenAndPopulateSelL()
       
  1280 	{  
       
  1281 	TKeyArrayFix uidKey(0,ECmpTUint32);
       
  1282 	iClientEntry.SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone,ETrue));
       
  1283 	TInt count = iClientEntry.Count();
       
  1284 
       
  1285 	TMsvId id = KMsvNullIndexEntryId;
       
  1286 	for (TInt i=0; i<count; ++i)
       
  1287  		{
       
  1288 		id = iClientEntry[i].Id();
       
  1289 		if (iCompleteSel->Find(id) == KErrNotFound)
       
  1290 			{			
       
  1291 			iCompleteSel->InsertIsqL(id ,uidKey);
       
  1292 			}
       
  1293  		}
       
  1294 	}
       
  1295 
       
  1296 
       
  1297 void CImEmailMessage::AssembleBodyTextL()
       
  1298 	{
       
  1299    	if (!iClientEntry.HasStoreL())
       
  1300    		return;
       
  1301    		
       
  1302 	CMsvStore* store=iClientEntry.ReadStoreL();
       
  1303    	CleanupStack::PushL(store);
       
  1304 	
       
  1305 	if (store->HasBodyTextL())
       
  1306    		{
       
  1307 		CRichText* bodyText=CRichText::NewL(iParaLayer,iCharLayer);	
       
  1308 		CleanupStack::PushL(bodyText);
       
  1309 		store->RestoreBodyTextL(*bodyText, iCharacterSetId);
       
  1310 		iRichText->AppendTakingSolePictureOwnershipL(*bodyText);
       
  1311 		CleanupStack::PopAndDestroy(bodyText);	
       
  1312 		}
       
  1313 	
       
  1314    	CleanupStack::PopAndDestroy(store);
       
  1315 	}
       
  1316 
       
  1317 void CImEmailMessage::AttachmentInfoL()
       
  1318 	{
       
  1319 	switch (iAttachmentType)
       
  1320 		{
       
  1321 	case EAllAttachments: break;
       
  1322 	case EVCards:
       
  1323 		if (!iEntry.VCard()) return; break;
       
  1324 	case EVCalendars:
       
  1325 		if (!iEntry.VCalendar()) return; break;
       
  1326 	case EICalendars:
       
  1327 		if (!iEntry.ICalendar()) return; break;
       
  1328 	case EVEntries: 
       
  1329 		if (iEntry.VCard() || iEntry.VCalendar() || iEntry.ICalendar()) break; return;
       
  1330 	case EEncrypted:
       
  1331 		if (!iEntry.Encrypted()) return; break;
       
  1332 	case ESigned:
       
  1333 		if (!iEntry.Signed()) return; break;
       
  1334 	case ESecure: 
       
  1335 		if (iEntry.Encrypted() || iEntry.Signed()) break; return;
       
  1336 	default: return;
       
  1337 		};
       
  1338 
       
  1339 	AppendAttachmentL();
       
  1340 	}
       
  1341 
       
  1342 /**
       
  1343 Walking the tree attachments added as found.
       
  1344 */
       
  1345 void CImEmailMessage::AppendAttachmentL()
       
  1346 	{
       
  1347 	if(iClientEntry.HasStoreL())
       
  1348 		{
       
  1349 		CMsvStore* store = iClientEntry.ReadStoreL();
       
  1350 		CleanupStack::PushL(store);
       
  1351 		MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
  1352 		// Modified to handle multiple attachments belonging to a single attachment entry
       
  1353 		for(TInt i=0;i<attachmentMgr.AttachmentCount();i++)
       
  1354 			{
       
  1355 			CMsvAttachment* attachment = attachmentMgr.GetAttachmentInfoL(i);
       
  1356 			CleanupStack::PushL(attachment);
       
  1357 			attachment->SetSize(iEntry.iSize);
       
  1358 			attachment->SetComplete(iEntry.Complete());
       
  1359 			// For compatibility keep entry [0] as the TMsvId of the owning attachment entry
       
  1360 			if(i == 0)
       
  1361 				{
       
  1362 				attachment->SetId(iClientEntry.EntryId());
       
  1363 				}
       
  1364 			else
       
  1365 				{				
       
  1366 				// Store the index and the owning attachment entry's TMsvId
       
  1367 				attachment->SetIntAttributeL(KUidMsvEmailAttachmentEntryIndex,i);
       
  1368 				attachment->SetIntAttributeL(KUidMsvEmailAttachmentEntryId,iClientEntry.EntryId());
       
  1369 				attachment->SetId(iAttachmentManager->UniqueAttachmentId());
       
  1370 				}
       
  1371 			// Add to the per-message list of CMsvAttachments
       
  1372 			User::LeaveIfError(iAttachmentManager->AttachmentInfoSelection().Append(attachment));
       
  1373 			// Add the attachment id to the results
       
  1374 			iResultSel->AppendL(iClientEntry.EntryId());
       
  1375 			CleanupStack::Pop(attachment);				
       
  1376 			}
       
  1377 		CleanupStack::PopAndDestroy(store);	
       
  1378 		}
       
  1379 	AppendAttachmentNameL();
       
  1380 	}
       
  1381 
       
  1382 
       
  1383 /** 
       
  1384 Retrieves the encoded mime header containing the encoded data for the attachment
       
  1385 name and redecodes with the overriding character set if one has been given. If
       
  1386 no overriding character set has been specified, a zero length entry is added.
       
  1387 This indicates whether redcoding is required at retrieval time.
       
  1388 */
       
  1389 void CImEmailMessage::AppendAttachmentNameL()
       
  1390 	{
       
  1391 	TMsvId originalId = iClientEntry.EntryId();
       
  1392 	TUint  overrideCharset = 0;
       
  1393 
       
  1394 	iClientEntry.SetEntryL(iParentMsgId);
       
  1395 	overrideCharset = GetOverrideCharacterSetL();
       
  1396 
       
  1397 	// Set iClientEntry back to original entry.
       
  1398 	iClientEntry.SetEntryL(originalId);
       
  1399 	
       
  1400 	TFileName filename;
       
  1401 	TPtrC filenamePtr(KNullDesC);
       
  1402 	// If our override charset has been set.
       
  1403 	if (overrideCharset != 0)
       
  1404 		{
       
  1405 		CImMimeHeader* mimeHeader = FindAttachmentMimeHeaderL();	
       
  1406 		if (mimeHeader != NULL)
       
  1407 			{
       
  1408 			CleanupStack::PushL(mimeHeader);
       
  1409 			// Decode mime header
       
  1410 			FindFilenameDecodeL(*mimeHeader, filename, overrideCharset);
       
  1411 
       
  1412 			filenamePtr.Set(filename);
       
  1413 			CleanupStack::PopAndDestroy(mimeHeader);
       
  1414 			}
       
  1415 		}
       
  1416 	iAttachmentNameList->AppendL(filenamePtr);
       
  1417 	}
       
  1418 
       
  1419 CImMimeHeader* CImEmailMessage::FindAttachmentMimeHeaderL()
       
  1420 	{
       
  1421 	TMsvId     originalId = iClientEntry.EntryId();
       
  1422 	CMsvStore* store      = NULL;
       
  1423 
       
  1424 	// If the current entry in the message hierarchy has a store, look for the
       
  1425 	// mime header there.
       
  1426 	if (iClientEntry.HasStoreL())
       
  1427 		{
       
  1428 		store = iClientEntry.ReadStoreL();
       
  1429 		CleanupStack::PushL(store);
       
  1430 		if (!store->IsPresentL(KUidMsgFileMimeHeader))
       
  1431 			{
       
  1432 			CleanupStack::PopAndDestroy(store);
       
  1433 			store = NULL;
       
  1434 			}
       
  1435 		}
       
  1436 
       
  1437 	if (store == NULL)
       
  1438 		{
       
  1439 		// Check the parent entry in the message hierarchy for the mime header
       
  1440 		// but only if it is the message.
       
  1441 		iClientEntry.SetEntryL(iClientEntry.Entry().Parent());
       
  1442 		if (iClientEntry.Entry().iType == KUidMsvMessageEntry && 
       
  1443 			iClientEntry.HasStoreL())
       
  1444 			{
       
  1445 			store = iClientEntry.ReadStoreL();
       
  1446 			CleanupStack::PushL(store);
       
  1447 			if(!store->IsPresentL(KUidMsgFileMimeHeader))
       
  1448 				{
       
  1449 				CleanupStack::PopAndDestroy(store);
       
  1450 				store = NULL;
       
  1451 				}
       
  1452 			}
       
  1453 		}
       
  1454 
       
  1455 	CImMimeHeader* mimeHeader = NULL;
       
  1456 	if (store)
       
  1457 		{
       
  1458 		mimeHeader = CImMimeHeader::NewLC();
       
  1459 		mimeHeader->RestoreL(*store);
       
  1460 		// found the mime headers,
       
  1461 		CMsvMimeHeaders* mimeHeaders = ConvertToMsvMimeHeadersL(mimeHeader);
       
  1462 		CleanupStack::PushL(mimeHeaders);
       
  1463 		// store the mimeheaders into the previously stored attachment  
       
  1464 		TInt count = iAttachmentManager->AttachmentInfoSelection().Count();
       
  1465 		if(count)
       
  1466 			mimeHeaders->StoreL(*(iAttachmentManager->AttachmentInfoSelection()[count-1]));
       
  1467 		CleanupStack::PopAndDestroy(mimeHeaders);
       
  1468 		CleanupStack::Pop(mimeHeader);
       
  1469 		CleanupStack::PopAndDestroy(store);
       
  1470 		CleanupStack::PushL(mimeHeader);
       
  1471 		}
       
  1472 	if (iClientEntry.EntryId() != originalId)
       
  1473 		iClientEntry.SetEntryL(originalId);
       
  1474 
       
  1475 	if (mimeHeader)
       
  1476 		CleanupStack::Pop(mimeHeader);
       
  1477 	return mimeHeader;
       
  1478 	}
       
  1479 
       
  1480 
       
  1481 
       
  1482 	
       
  1483 TInt CImEmailMessage::FindFilename(const CImMimeHeader& aMimeInfo, TPtrC8& aFilename)
       
  1484 	{
       
  1485 	_LIT8(KMimeName,"NAME");
       
  1486 	_LIT8(KMimeNameRFC2231, "NAME*");
       
  1487 	_LIT8(KMimeFilename, "FILENAME");
       
  1488 	_LIT8(KMimeFilenameRFC2231, "FILENAME*");
       
  1489 
       
  1490 	// Look in content-type list
       
  1491 	const CDesC8Array& ctype = aMimeInfo.ContentTypeParams();
       
  1492 	TInt tuple = 0;
       
  1493 
       
  1494 	while (tuple < ctype.Count())
       
  1495 		{
       
  1496 		// Look for "name xxx"
       
  1497 		if (ctype[tuple].CompareF(KMimeName) == 0)
       
  1498 			{
       
  1499 			// Got it: report that we found it
       
  1500 			aFilename.Set(ctype[tuple + 1]);
       
  1501 			return (KErrNone);
       
  1502 			}
       
  1503 		else if (ctype[tuple].CompareF(KMimeNameRFC2231) == 0)
       
  1504 			{
       
  1505 			// Got it: report that we found it
       
  1506 			aFilename.Set(ctype[tuple + 1]);
       
  1507 			return(KRFC2231Encoded);
       
  1508 			}
       
  1509 		tuple += 2;
       
  1510 		}
       
  1511 
       
  1512 	// Not found in the content type, try content disposition
       
  1513 	tuple = 0;
       
  1514 	const CDesC8Array& cdisp = aMimeInfo.ContentDispositionParams();
       
  1515 	while (tuple < cdisp.Count())
       
  1516 		{
       
  1517 		// Look for "filename xxx"
       
  1518 		if (cdisp[tuple].CompareF(KMimeFilename) == 0)
       
  1519 			{
       
  1520 			// Got it: report that we found it
       
  1521 			aFilename.Set(cdisp[tuple + 1]);
       
  1522 			return(KErrNone);
       
  1523 			}
       
  1524 		else if (cdisp[tuple].CompareF(KMimeFilenameRFC2231) == 0)
       
  1525 			{
       
  1526 			// Got it: report that we found it
       
  1527 			aFilename.Set(cdisp[tuple + 1]);
       
  1528 			return (KRFC2231Encoded);
       
  1529 			}
       
  1530 
       
  1531 		tuple += 2;
       
  1532 		}
       
  1533 
       
  1534 	// Didn't find it
       
  1535 	return(KErrNotFound);
       
  1536 	}
       
  1537 
       
  1538 void CImEmailMessage::FindFilenameDecodeL(
       
  1539 	const CImMimeHeader& aMimeInfo, TFileName& aFileName, TUint aCharset)
       
  1540 	{
       
  1541 	// Create everything needed for a CImConvertHeader.
       
  1542 	RFs& fileSvrSession = iClientEntry.Session().FileSession();
       
  1543 	CCnvCharacterSetConverter* characterConverter = CCnvCharacterSetConverter::NewL();
       
  1544 	CleanupStack::PushL(characterConverter);
       
  1545 	CImConvertCharconv* charConv = CImConvertCharconv::NewL(*characterConverter, fileSvrSession);
       
  1546 	CleanupStack::PushL(charConv);
       
  1547 	CImConvertHeader* headerConverter = CImConvertHeader::NewL(*charConv); 
       
  1548 	CleanupStack::PushL(headerConverter);
       
  1549 
       
  1550 	// Make an attachment name
       
  1551 	aFileName.Zero();
       
  1552 
       
  1553 	TPtrC8 origFileName;
       
  1554 
       
  1555 	// Look for filename in Content-Type list
       
  1556 	TInt returnValue = FindFilename(aMimeInfo, origFileName);
       
  1557 	
       
  1558 	if (KErrNotFound != returnValue && KRFC2231Encoded != returnValue)
       
  1559 		{
       
  1560 		// Run it through the QP decoder
       
  1561 		HBufC* decoded = HBufC::NewLC(origFileName.Length());
       
  1562 		TPtr decoded_ptr(decoded->Des());
       
  1563 		// Set the overriding charset.
       
  1564 		headerConverter->SetOverrideCharset(aCharset);
       
  1565 
       
  1566 		/* if it starts =? then assume its RFC2047 encoding -
       
  1567 		 * otherwise assume its plain text encoded in the system
       
  1568 		 * charset and decode directly */
       
  1569 		if (origFileName.Length() >= 2 && origFileName[0] == KImcvEquals && origFileName[1] == KImcvQuestionMark)
       
  1570 			headerConverter->DecodeHeaderFieldL(origFileName, decoded_ptr);
       
  1571 		else
       
  1572 			{
       
  1573 			if (charConv->PrepareToConvertToFromOurCharsetL(charConv->SystemDefaultCharset()))
       
  1574 				{
       
  1575 				// Character set conversion
       
  1576 				TInt unconvertedChars;
       
  1577 				TInt pos;
       
  1578 				charConv->ConvertToOurCharsetL(origFileName, decoded_ptr, unconvertedChars, pos);
       
  1579 				}
       
  1580 			else
       
  1581 				{
       
  1582 				// Charset not available, don't decode.
       
  1583 				decoded_ptr.Copy(origFileName);
       
  1584 				}
       
  1585 			}
       
  1586 		aFileName.Copy(decoded_ptr);
       
  1587 		CleanupStack::PopAndDestroy(); // decoded
       
  1588 		}
       
  1589 	CleanupStack::PopAndDestroy(3, characterConverter);
       
  1590 	}
       
  1591 
       
  1592 TBool CImEmailMessage::HandleDifferentFolderTypesL()
       
  1593 	{
       
  1594 	/* This bit of code looks at the folder type and finds out how many children there are
       
  1595 	 and depending on the type of the reqest (attachments/bodytext etc..) it selects only 
       
  1596 	those type of children and ignores the others.  This avoids going through the whole tree. */
       
  1597 	TImEmailFolderType folderType=iEntry.MessageFolderType();
       
  1598 	
       
  1599 	if(iIsAMHTMLmessage == EFalse && folderType==EFolderTypeRelated)
       
  1600 		folderType=EFolderTypeMixed;
       
  1601 
       
  1602 	switch (folderType)
       
  1603 		{
       
  1604 	case EFolderTypeUnknown:
       
  1605 	case EFolderTypeMixed:
       
  1606 	case EFolderTypeParallel:
       
  1607 	case EFolderTypeDigest:
       
  1608 	case EFolderTypeRFC822:
       
  1609 	case EFolderTypePartial:
       
  1610 	case EFolderTypeDirectory:
       
  1611 	case EFolderTypeExternal:
       
  1612 		return ETrue;
       
  1613 	case EFolderTypeRelated:  //doesn't apply for get- txt,attch,msgdigest
       
  1614 		if (iState == EAttachmentsForThisMsg)
       
  1615 			{
       
  1616 			GetAttachmentsForRelatedFolderL();
       
  1617 			return EFalse;	
       
  1618 			}
       
  1619 		else if (iState==EAttachmentsForMsgDigest || iState==EMsgDigestEntries)
       
  1620 			{
       
  1621 			return EFalse;
       
  1622 			}
       
  1623 
       
  1624 		if (iState==ETextForThisMsg || iState==ETextForThisMsgGetCharacterSet || iState==ETextForMsgDigest
       
  1625 			|| iState == ETextEntryIdForThisMsg || iState == ETextEntryIdMsgDigest)
       
  1626 			{
       
  1627 			GetTextForRelatedFolderL();
       
  1628 			return EFalse;
       
  1629 			}
       
  1630 		return ETrue;
       
  1631 	case EFolderTypeAlternative: // only applies for get text, get body text character set.
       
  1632 		if (iState==EAttachmentsForThisMsg || iState==EAttachmentsForMsgDigest)
       
  1633 			{
       
  1634 			return ETrue;
       
  1635 			}
       
  1636 
       
  1637 		if (iState==ETextForThisMsg || iState==ETextForThisMsgGetCharacterSet || iState==ETextForMsgDigest
       
  1638 			|| iState == ETextEntryIdForThisMsg || iState == ETextEntryIdMsgDigest)
       
  1639 			{
       
  1640 			GetTextForAlternateFolderL();
       
  1641 			}
       
  1642 		return EFalse;
       
  1643 		}
       
  1644 	return ETrue;
       
  1645 	}
       
  1646 
       
  1647 
       
  1648 void CImEmailMessage::GetTextForAlternateFolderL()		
       
  1649 	{
       
  1650 	iClientEntry.SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone,ETrue));
       
  1651 	TInt count = iClientEntry.Count();
       
  1652 	TInt typeindex=-1;  //for alternate we need the last id.
       
  1653 	while (count--)
       
  1654 		{
       
  1655 		if (iClientEntry[count].iType.iUid==KUidMsvEmailTextEntryValue)  //ignore the rest of the types.  The last text entry is the best one.
       
  1656 			{
       
  1657 			typeindex=count;
       
  1658 			break;
       
  1659 			}
       
  1660 		}
       
  1661 	if (typeindex >-1) //means it found a txt entry
       
  1662 		{
       
  1663 		TKeyArrayFix uidKey(0,ECmpTUint32);
       
  1664 		iCompleteSel->InsertIsqL(iClientEntry[typeindex].Id(),uidKey);
       
  1665 		}
       
  1666 	}
       
  1667 
       
  1668 
       
  1669 void CImEmailMessage::GetTextForRelatedFolderL()		
       
  1670 	{
       
  1671 	iClientEntry.SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone,ETrue));
       
  1672 	CMsvEntrySelection* sel=iClientEntry.ChildrenL();
       
  1673 	CleanupStack::PushL(sel);		
       
  1674 	TInt count=sel->Count();
       
  1675 	TMsvEmailEntry entry;
       
  1676 	TKeyArrayFix uidKey(0,ECmpTUint32);
       
  1677 	for (TInt i=0; i<count; i++)
       
  1678 		{
       
  1679 		entry=iClientEntry.ChildDataL((*sel)[i]);
       
  1680 
       
  1681 		if ((entry.iType.iUid==KUidMsvFolderEntryValue) || ((iState==ETextForMsgDigest || iState == ETextEntryIdMsgDigest)
       
  1682 		&& (entry.iType.iUid==KUidMsvMessageEntryValue))) 
       
  1683 			{
       
  1684 			iCompleteSel->InsertIsqL((*sel)[i],uidKey);
       
  1685 			};
       
  1686 		}
       
  1687 	CleanupStack::PopAndDestroy(); //sel
       
  1688 	}
       
  1689 
       
  1690 
       
  1691 void CImEmailMessage::GetAttachmentsForRelatedFolderL()
       
  1692 	{
       
  1693 	// This fixes a defect where forwarding an inline attachment failed. Before this
       
  1694 	// fix, no attachments under multipart related were forwarded. 
       
  1695 	// This routine will only forward attachments taht are directly under the multipart
       
  1696 	// related folder.
       
  1697 	TKeyArrayFix uidKey(0,ECmpTUint32);
       
  1698 	iClientEntry.SetSortTypeL(TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone,ETrue));
       
  1699 	for (TInt entry(0); entry < iClientEntry.Count(); entry++)
       
  1700 		{
       
  1701 		if (iClientEntry[entry].iType.iUid == KUidMsvAttachmentEntryValue)
       
  1702 			{
       
  1703 			iCompleteSel->InsertIsqL(iClientEntry[entry].Id(), uidKey);
       
  1704 			}
       
  1705 		}
       
  1706 	}
       
  1707 
       
  1708 TBool CImEmailMessage::GetBodyTextCharacterSetL()
       
  1709 	{
       
  1710 	// Open body text entry store for reading.
       
  1711 	CMsvStore* store = iClientEntry.ReadStoreL();
       
  1712 	CleanupStack::PushL(store);
       
  1713 
       
  1714  	// check the body text entry store available if not return EFalse
       
  1715  	if(!store->HasBodyTextL())
       
  1716  		{
       
  1717  		CleanupStack::PopAndDestroy(store); // store.	
       
  1718 		return EFalse;
       
  1719  		}
       
  1720 
       
  1721 	// Test if the old rich text body OR 16 bit plain body text is present. Return immediately if so, 
       
  1722 	// We are looking for the new 8 bit body text format which has character set
       
  1723 	// information stored with it. 
       
  1724 	if (store->IsPresentL(KMsvEntryRichTextBody) || store->IsPresentL(KMsvPlainBodyText16))
       
  1725 		{
       
  1726 		CleanupStack::PopAndDestroy(store);
       
  1727 		return EFalse;
       
  1728 		}
       
  1729 	// Check if body text is stored as 8 bit body text format
       
  1730 	if(store->IsPresentL(KMsv8BitEncodedBodyData))
       
  1731 		{
       
  1732 		// The body text entry must be the new 8 bit format.
       
  1733 		CMsvBodyText* bodyText = CMsvBodyText::NewLC();
       
  1734 
       
  1735 		// If there is no body text for this message RestoreL will leave
       
  1736 		// In this case we will change that into returning EFalse so any
       
  1737 		// attachments will display properly
       
  1738 		TRAPD(err, bodyText->RestoreL(*store));
       
  1739 		if (err == KErrNotFound)
       
  1740 			{
       
  1741 			CleanupStack::PopAndDestroy(2, store); // bodyText, store.	
       
  1742 			return EFalse;
       
  1743 			}
       
  1744 	
       
  1745 		iCharacterSetId = bodyText->CharacterSet();
       
  1746 		
       
  1747 		if (!iCharacterSetId)
       
  1748 			{
       
  1749 			iCharacterSetId = bodyText->DefaultCharacterSet();
       
  1750 			}
       
  1751 		CleanupStack::PopAndDestroy(bodyText);
       
  1752 		}
       
  1753 	else // Body text is stored as 8 bit plain text.
       
  1754 		{
       
  1755 		CMsvPlainBodyText* plainBodyText = store->InitialisePlainBodyTextForReadL(KMaxChunkLength);
       
  1756 		CleanupStack::PushL(plainBodyText);
       
  1757 		iCharacterSetId = plainBodyText->CharacterSet();
       
  1758 		if(!iCharacterSetId)
       
  1759 			{
       
  1760 			iCharacterSetId = plainBodyText->DefaultCharacterSet();
       
  1761 			}
       
  1762 		CleanupStack::PopAndDestroy(plainBodyText);	
       
  1763 		}
       
  1764 	
       
  1765 	CleanupStack::PopAndDestroy(store);
       
  1766 	return ETrue;
       
  1767 	}
       
  1768 
       
  1769 
       
  1770 /**
       
  1771 Returns the character set id of the email message entry if it exists.  This method assumes that the
       
  1772 context is set to the top level message entry.
       
  1773 */	
       
  1774 TUint CImEmailMessage::GetOverrideCharacterSetL()
       
  1775 	{
       
  1776 	TUint characterSetId = 0;
       
  1777 	if (iClientEntry.HasStoreL())
       
  1778 		{
       
  1779 		CMsvStore* store  = iClientEntry.ReadStoreL();
       
  1780 		CleanupStack::PushL(store);
       
  1781 		if (store->IsPresentL(KMessageCharSetStreamUid))
       
  1782 			{
       
  1783 			RMsvReadStream in;
       
  1784 			in.OpenLC(*store, KMessageCharSetStreamUid);
       
  1785 			in.ReadUint8L(); // Version. 
       
  1786 			characterSetId = in.ReadUint32L();
       
  1787 			in.Close();
       
  1788 			CleanupStack::PopAndDestroy(&in);
       
  1789 			}
       
  1790 		CleanupStack::PopAndDestroy(store);
       
  1791 		}
       
  1792 	return characterSetId;
       
  1793 	}
       
  1794 
       
  1795 TMsvEntry CImEmailMessage::FindIdEntryL(TMsvId aMessageId)
       
  1796 	{
       
  1797 	TMsvId service;
       
  1798 	TMsvEntry returnEntry;
       
  1799 	iClientEntry.Session().GetEntry(aMessageId, service, returnEntry);
       
  1800 	return returnEntry;
       
  1801 	}
       
  1802 	
       
  1803 EXPORT_C MMsvAttachmentManager& CImEmailMessage::AttachmentManager() const
       
  1804 	{
       
  1805 	return *iAttachmentManager;
       
  1806 	}
       
  1807 	
       
  1808 void CImEmailMessage::CheckEntryAndResetStoreMessageL(TMsvId aMessageId)
       
  1809 	{
       
  1810 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
  1811 	__ASSERT_DEBUG(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
  1812 	
       
  1813 	// reset the entry with which CImEmailMessage was created
       
  1814 	iClientEntry.SetEntryL(iEmailEntryId);
       
  1815 	
       
  1816 	delete iStoreMessagePart;
       
  1817 	iStoreMessagePart = NULL;
       
  1818 	}
       
  1819 	
       
  1820 void CImEmailMessage::CheckEntryAndResetRemoveMessageL(TMsvId aMessageId)
       
  1821 	{
       
  1822 	TMsvEntry entry = FindIdEntryL(aMessageId);
       
  1823 	__ASSERT_DEBUG(entry.iType==KUidMsvMessageEntry, gPanic(EEntryIsNotMessage));
       
  1824 	
       
  1825 	// reset the entry with which CImEmailMessage was created
       
  1826 	iClientEntry.SetEntryL(iEmailEntryId);
       
  1827 	
       
  1828 	delete iRemoveMessagePart;
       
  1829 	iRemoveMessagePart = NULL;
       
  1830 	}	
       
  1831 	
       
  1832 void CImEmailMessage::DoSetActive(TRequestStatus& aStatus)
       
  1833 	{
       
  1834 	Queue(aStatus);
       
  1835 	SetActive();	
       
  1836 	}	
       
  1837 
       
  1838 void CImEmailMessage::AddAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
  1839 	{
       
  1840 	// get the message id
       
  1841 	TMsvId messageId = iClientEntry.EntryId();
       
  1842 	CheckEntryAndResetStoreMessageL(messageId);
       
  1843 
       
  1844 	iStoreMessagePart = CImStoreMessagePart::AddAttachmentL(messageId,aFilePath,iClientEntry, aAttachmentInfo,iStatus );
       
  1845 	iState = EStoreMessagePart;
       
  1846 	iAttachmentState = EAddAttachment;
       
  1847 
       
  1848 	DoSetActive(aStatus);
       
  1849 	}
       
  1850 
       
  1851 void CImEmailMessage::AddAttachmentL(RFile& aFile, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
  1852 	{
       
  1853 	// get the message id
       
  1854 	TMsvId messageId = iClientEntry.EntryId();
       
  1855 	CheckEntryAndResetStoreMessageL(messageId);
       
  1856 	
       
  1857 	iStoreMessagePart = CImStoreMessagePart::AddAttachmentL(messageId,aFile,iClientEntry, aAttachmentInfo, iStatus);
       
  1858 	iState = EStoreMessagePart;
       
  1859 	iAttachmentState = EAddAttachment;
       
  1860 	
       
  1861 	DoSetActive(aStatus);
       
  1862 	}
       
  1863 	
       
  1864 void CImEmailMessage::AddLinkedAttachmentL(const TDesC& aFilePath, CMsvAttachment* aAttachmentInfo,TRequestStatus& aStatus)
       
  1865 	{
       
  1866 	// get the message id
       
  1867 	TMsvId messageId = iClientEntry.EntryId();
       
  1868 	CheckEntryAndResetStoreMessageL(messageId);
       
  1869 	
       
  1870 	iStoreMessagePart = CImStoreMessagePart::AddLinkedAttachmentL(messageId,aFilePath,iClientEntry, aAttachmentInfo,iStatus);
       
  1871 	iState = EStoreMessagePart;
       
  1872 	iAttachmentState = EAddAttachment;
       
  1873 	
       
  1874 	DoSetActive(aStatus);
       
  1875 	}
       
  1876 	
       
  1877 void CImEmailMessage::AddEntryAsAttachmentL(TMsvId aAttachmentEntryId, CMsvAttachment* aAttachmentInfo,TRequestStatus& aStatus)
       
  1878 	{
       
  1879 	// get the message id
       
  1880 	TMsvId messageId = iClientEntry.EntryId();
       
  1881 	CheckEntryAndResetStoreMessageL(messageId);
       
  1882 		
       
  1883 	iStoreMessagePart = CImStoreMessagePart::AddEntryAsAttachmentL(messageId,aAttachmentEntryId,iClientEntry,aAttachmentInfo,iStatus);
       
  1884 	iState = EStoreMessagePart;
       
  1885 	iAttachmentState = EAddAttachment;
       
  1886 	
       
  1887 	DoSetActive(aStatus);
       
  1888 	}
       
  1889 
       
  1890 void CImEmailMessage::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
  1891 	{
       
  1892 	// get the message id
       
  1893 	TMsvId messageId = iClientEntry.EntryId();
       
  1894 	CheckEntryAndResetStoreMessageL(messageId);
       
  1895 	
       
  1896 	iStoreMessagePart = CImStoreMessagePart::CreateAttachmentL(messageId,aFileName,aAttachmentFile,iClientEntry, aAttachmentInfo,iStatus);
       
  1897 	iState = EStoreMessagePart;
       
  1898 	iAttachmentState = ECreateAttachment;
       
  1899 	
       
  1900 	DoSetActive(aStatus);
       
  1901 	}
       
  1902 	
       
  1903 /**
       
  1904 Returns a list of attachment information pointers (CMsvAttachment)
       
  1905 populated by a call to GetAttachmentsListL().
       
  1906 
       
  1907 @pre
       
  1908 The attachment information list must first be populated by calling GetAttachmentsListL().
       
  1909 
       
  1910 @return
       
  1911 An array of attachment information objects (CMsvAttachment) representing the attachments
       
  1912 contained within a particular message specified in the call to GetAttachmentsListL().
       
  1913 */
       
  1914 const RPointerArray<CMsvAttachment>& CImEmailMessage::AttachmentInfoSelection() const
       
  1915 	{
       
  1916 	return iAttachmentManager->AttachmentInfoSelection();
       
  1917 	}
       
  1918 
       
  1919 void CImEmailMessage::RemoveAttachmentL(TMsvAttachmentId aAttachmentId,TRequestStatus& aStatus) 
       
  1920 	{
       
  1921 	// get the message id
       
  1922 	TMsvId messageId = iClientEntry.EntryId();
       
  1923 	CheckEntryAndResetRemoveMessageL(messageId);
       
  1924 	
       
  1925 	iRemoveMessagePart = CImRemoveMessagePart::DeleteAttachmentL(iStatus, iClientEntry, messageId, aAttachmentId);
       
  1926 	iState = ERemoveMessagePart;
       
  1927 	iAttachmentState = EDeleteAttachment;
       
  1928 	
       
  1929 	DoSetActive(aStatus);
       
  1930 	}
       
  1931 	
       
  1932 void CImEmailMessage::RemoveAttachedMessageL(TMsvAttachmentId aAttachmentId,TRequestStatus& aStatus) 
       
  1933 	{
       
  1934 	// get the message id
       
  1935 	TMsvId messageId = iClientEntry.EntryId();
       
  1936 	CheckEntryAndResetRemoveMessageL(messageId);
       
  1937 	
       
  1938 	iRemoveMessagePart = CImRemoveMessagePart::DeleteAttachmentL(iStatus, iClientEntry, messageId, aAttachmentId);
       
  1939 	iState = ERemoveMessagePart;
       
  1940 	iAttachmentState = EDeleteAttachment;
       
  1941 	
       
  1942 	DoSetActive(aStatus);
       
  1943 	}
       
  1944 	
       
  1945 CMsvMimeHeaders* CImEmailMessage::ConvertToMsvMimeHeadersL(CImMimeHeader* aMimeHeader)
       
  1946 	{
       
  1947 	CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();
       
  1948 	CleanupStack::PushL(mimeHeaders);
       
  1949 	
       
  1950 	mimeHeaders->SetContentDescriptionL(aMimeHeader->ContentDescription());
       
  1951 	mimeHeaders->SetContentBaseL(aMimeHeader->ContentBase());
       
  1952 	mimeHeaders->SetContentLocationL(aMimeHeader->ContentLocation());
       
  1953 	mimeHeaders->SetContentIdL(aMimeHeader->ContentID());
       
  1954 	mimeHeaders->SetContentTypeL(aMimeHeader->ContentType());
       
  1955 	mimeHeaders->SetContentDispositionL(aMimeHeader->ContentDisposition());
       
  1956 	mimeHeaders->SetMimeCharset(aMimeHeader->MimeCharset());
       
  1957 	mimeHeaders->SetRelativePathL(aMimeHeader->RelativePath());
       
  1958 	mimeHeaders->SetContentSubTypeL(aMimeHeader->ContentSubType());
       
  1959 	mimeHeaders->SetRelativePathL(aMimeHeader->RelativePath());
       
  1960 	
       
  1961 	CleanupStack::Pop(mimeHeaders);	
       
  1962 	return mimeHeaders;
       
  1963 	}
       
  1964 	
       
  1965 CImMimeHeader* CImEmailMessage::ConvertToImMimeHeadersL(CMsvMimeHeaders* aMimeHeaders)
       
  1966 	{
       
  1967 	CImMimeHeader* mimeHeader = CImMimeHeader::NewL();
       
  1968 	CleanupStack::PushL(mimeHeader);
       
  1969 	
       
  1970 	mimeHeader->SetContentDescriptionL(aMimeHeaders->ContentDescription());
       
  1971 	mimeHeader->SetContentBaseL(aMimeHeaders->ContentBase());
       
  1972 	mimeHeader->SetContentLocationL(aMimeHeaders->ContentLocation());
       
  1973 	mimeHeader->SetContentIDL(aMimeHeaders->ContentId());
       
  1974 	mimeHeader->SetContentTypeL(aMimeHeaders->ContentType());
       
  1975 	mimeHeader->SetContentDispositionL(aMimeHeaders->ContentDisposition());
       
  1976 	mimeHeader->SetMimeCharset(aMimeHeaders->MimeCharset());
       
  1977 	mimeHeader->SetRelativePathL(aMimeHeaders->RelativePath());
       
  1978 	mimeHeader->SetContentSubTypeL(aMimeHeaders->ContentSubType());
       
  1979 	mimeHeader->SetRelativePathL(aMimeHeaders->RelativePath());
       
  1980 	CleanupStack::Pop(mimeHeader);	
       
  1981 	return mimeHeader;
       
  1982 	}	
       
  1983 	
       
  1984 void CImEmailMessage::AppendEntryAttachmentInfoL()
       
  1985 	{
       
  1986 	CMsvStore* store = iClientEntry.ReadStoreL();
       
  1987 	CleanupStack::PushL(store);
       
  1988 	MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
  1989 	// Modified to handle multiple attachments belonging to a single attachment entry
       
  1990 	for(TInt i=0;i<attachmentMgr.AttachmentCount();i++)
       
  1991 		{
       
  1992 		CMsvAttachment* attachment = attachmentMgr.GetAttachmentInfoL(i);
       
  1993 		CleanupStack::PushL(attachment);
       
  1994 		attachment->SetSize(iEntry.iSize);
       
  1995 		attachment->SetComplete(iEntry.Complete());
       
  1996 		// For compatibility keep entry [0] as the TMsvId of the owning attachment entry
       
  1997 		if(i == 0)
       
  1998 			{
       
  1999 			attachment->SetId(iClientEntry.EntryId());
       
  2000 			}
       
  2001 		else
       
  2002 			{				
       
  2003 			// Store the index and the owning attachment entry's TMsvId
       
  2004 			attachment->SetIntAttributeL(KUidMsvEmailAttachmentEntryIndex,i);
       
  2005 			attachment->SetIntAttributeL(KUidMsvEmailAttachmentEntryId,iClientEntry.EntryId());
       
  2006 			attachment->SetId(iAttachmentManager->UniqueAttachmentId());
       
  2007 			}
       
  2008 		// Add to the per-message list of CMsvAttachments
       
  2009 		User::LeaveIfError(iAttachmentManager->AttachmentInfoSelection().Append(attachment));
       
  2010 		CleanupStack::Pop(attachment);				
       
  2011 		}
       
  2012 	CleanupStack::PopAndDestroy(store);		
       
  2013 	}
       
  2014 	
       
  2015 TMsvId CImEmailMessage::EmailEntryId()
       
  2016 	{
       
  2017 	return iClientEntry.EntryId();
       
  2018 	}
       
  2019 
       
  2020 /**
       
  2021 This returns a object of CImPlainBodyText.This needs to be called when bodytext 
       
  2022 needs to be restored in chunks for Read operation.
       
  2023 @param aMessageId	The Message Id for which to get plain body text part.
       
  2024 @param aEntryType   The TImEmailEntryType for this message.
       
  2025 @return CMsvPlainBodyText
       
  2026 */
       
  2027 EXPORT_C CImPlainBodyText* CImEmailMessage::OpenPlainBodyTextForReadL(TImEmailEntryType aEntryType, TInt aChunkLength)
       
  2028 	{
       
  2029 	CImPlainBodyText* plainBodyText = CImPlainBodyText::NewL(*this, iClientEntry, aEntryType, aChunkLength, EFalse);
       
  2030 	return plainBodyText;
       
  2031 	}
       
  2032 
       
  2033 /**
       
  2034 This returns a object of CImPlainBodyText.This needs to be called when bodytext 
       
  2035 needs to be created in chunks.
       
  2036 @param aMessageId	  The id of the message whose bodytext needs to be edited.
       
  2037 @return CImPlainBodyText
       
  2038 */	
       
  2039 EXPORT_C CImPlainBodyText* CImEmailMessage::OpenPlainBodyTextForWriteL()
       
  2040 	{
       
  2041 	CImPlainBodyText* plainBodyText = CImPlainBodyText::NewL(*this, iClientEntry, CImEmailMessage::EThisMessageOnly, KMaxChunkLength, ETrue);
       
  2042 	return plainBodyText;
       
  2043 	}
       
  2044 
       
  2045 //
       
  2046 // CImRemoveMessagePart
       
  2047 //
       
  2048 
       
  2049 CImRemoveMessagePart* CImRemoveMessagePart::DeleteAttachmentL(TRequestStatus &aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId, TMsvId aAttachmentId)
       
  2050 	{
       
  2051 	CImRemoveMessagePart* self = new(ELeave) CImRemoveMessagePart(aStatus, aMsvEntry, aMessageId);
       
  2052 	CleanupStack::PushL(self);
       
  2053 	self->ConstructL(aAttachmentId);
       
  2054 	CleanupStack::Pop(); //self
       
  2055 	return self;
       
  2056 	}
       
  2057 
       
  2058 CImRemoveMessagePart* CImRemoveMessagePart::DeleteAttachedMessageL(TRequestStatus &aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId, TMsvId aAttachedMessageId)
       
  2059 	{
       
  2060 	// this does exactly the same as for DeleteAttachmentL() but this function is added to seperate deleting attachments/attached messages
       
  2061 	CImRemoveMessagePart* self = new(ELeave) CImRemoveMessagePart(aStatus, aMsvEntry, aMessageId);
       
  2062 	CleanupStack::PushL(self);
       
  2063 	self->ConstructL(aAttachedMessageId);
       
  2064 	CleanupStack::Pop();
       
  2065 	return self;
       
  2066 	}
       
  2067 
       
  2068 CImRemoveMessagePart::~CImRemoveMessagePart()
       
  2069 	{
       
  2070 	Cancel();
       
  2071 	delete iMsvOperation;
       
  2072 	delete iMessageEntrySelection;
       
  2073 	delete iEmailMessage;
       
  2074 	}
       
  2075 
       
  2076 const TDesC8& CImRemoveMessagePart::FinalProgress()
       
  2077 	{
       
  2078 	__ASSERT_ALWAYS(!IsActive(), gPanic(EMiutActiveInFinalProgress));
       
  2079  	const TDesC8* progress = &KNullDesC8();
       
  2080  	TRAPD(leave, progress = &ProgressL());
       
  2081 	__ASSERT_ALWAYS(leave == KErrNone, gPanic(EImcmFinalProgressFailed));
       
  2082 	return *progress;	
       
  2083 	}
       
  2084 
       
  2085 const TDesC8& CImRemoveMessagePart::ProgressL()
       
  2086 	{
       
  2087 	if (iState==EFinished)
       
  2088 		iDataMember() = iMessageId;
       
  2089 	return iDataMember;
       
  2090 	}
       
  2091 
       
  2092 void CImRemoveMessagePart::DoCancel()
       
  2093 	{
       
  2094 	if (iMsvOperation)
       
  2095 		iMsvOperation->Cancel();
       
  2096 	if (iEmailMessage)
       
  2097 		iEmailMessage->Cancel();
       
  2098 	Recover();
       
  2099 
       
  2100 	TRequestStatus* st = &iObserverRequestStatus;
       
  2101 	User::RequestComplete(st, KErrCancel);
       
  2102 	}
       
  2103 
       
  2104 void CImRemoveMessagePart::SelectAndChangeToNextStateL()
       
  2105 	{
       
  2106 	SelectNextStateL();
       
  2107 	ChangeStateL();
       
  2108 	}
       
  2109 
       
  2110 void CImRemoveMessagePart::RunL()
       
  2111 	{
       
  2112 	if (iStatus.Int() != KErrNone)
       
  2113 		{
       
  2114 		ErrorRecovery(iStatus.Int());
       
  2115 		return;
       
  2116 		}
       
  2117 	if ((iState == EMoveOtherEntryToParentOfFolder) || 
       
  2118 		(iState == EDeleteAttachmentEntry) ||
       
  2119 		(iState == EDeleteFolderEntry) ||
       
  2120 		(iState == ECompleteRemoveMessagePart))
       
  2121 		{
       
  2122 		TInt sysProgressError = McliUtils::GetProgressErrorL(*iMsvOperation);
       
  2123 		if (sysProgressError != KErrNone)
       
  2124 			{
       
  2125 			ErrorRecovery(sysProgressError);
       
  2126 			return;
       
  2127 			}
       
  2128 		}
       
  2129 	if (iState != EFinished)
       
  2130 		{
       
  2131 		TRAPD(error, SelectAndChangeToNextStateL());
       
  2132 		if (error)
       
  2133 			ErrorRecovery(error);
       
  2134 		else if (iState != EFinished)
       
  2135 			SetActive();
       
  2136 		}
       
  2137 	}
       
  2138 
       
  2139 CImRemoveMessagePart::CImRemoveMessagePart(TRequestStatus& aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId)
       
  2140 	: CMsvOperation(aMsvEntry.Session(), EPriorityStandard, aStatus),
       
  2141 	  iMsvEntry(aMsvEntry),
       
  2142 	  iMessageId(aMessageId)
       
  2143 	{
       
  2144 	}
       
  2145 
       
  2146 void CImRemoveMessagePart::ConstructL(TMsvId aAttachmentId)
       
  2147 	{
       
  2148 	iDataMember = KMsvNullIndexEntryId;
       
  2149 	iAttachmentId = aAttachmentId;
       
  2150 	iFolderToDeleteId = KMsvNullIndexEntryId;
       
  2151 	iEntryToMoveId = KMsvNullIndexEntryId;
       
  2152 	iEmailMessage = CImEmailMessage::NewL(iMsvEntry);
       
  2153 	
       
  2154 	CActiveScheduler::Add(this);
       
  2155 
       
  2156 	TMsvId serviceId = KMsvNullIndexEntryId;
       
  2157 	TMsvEmailEntry attachmentEntry;
       
  2158 	iMsvEntry.Session().GetEntry(iAttachmentId, serviceId, attachmentEntry);
       
  2159 	iAttachmentSize = attachmentEntry.iSize;
       
  2160 	iState = ECheckAttachmentParentType;
       
  2161 	ChangeStateL();
       
  2162 
       
  2163 	iObserverRequestStatus = KRequestPending;
       
  2164 	SetActive();
       
  2165 	}
       
  2166 
       
  2167 void CImRemoveMessagePart::ErrorRecovery(TInt error)
       
  2168 	{
       
  2169 	// if there is an error then leave message in a 'good' state
       
  2170 	Recover();
       
  2171 	
       
  2172 	// complete the observer with error
       
  2173 	TRequestStatus* status=&iObserverRequestStatus;
       
  2174 	User::RequestComplete(status,error);
       
  2175 	}
       
  2176 
       
  2177 void CImRemoveMessagePart::SelectNextStateL()
       
  2178 	{
       
  2179 	switch (iState)
       
  2180 		{
       
  2181 	// do move and then the delete because if the move fails, the message
       
  2182 	// will still be in a good state
       
  2183 	case ECheckAttachmentParentType:
       
  2184 		{
       
  2185 		// set entry to parent just in case GetAttachmentsListL changes context
       
  2186 		TMsvId serviceId; // temp
       
  2187 		TMsvEmailEntry attachmentEntry;
       
  2188 		iMsvEntry.Session().GetEntry(iAttachmentId, serviceId, attachmentEntry);
       
  2189 		iMsvEntry.SetEntryL(attachmentEntry.Parent());
       
  2190 
       
  2191 		iState = EDeleteAttachmentEntry;
       
  2192 		}
       
  2193 		break;
       
  2194 	case EMoveOtherEntryToParentOfFolder:
       
  2195 		iState = EDeleteFolderEntry;
       
  2196 		break;
       
  2197 	case EDeleteAttachmentEntry:
       
  2198 		if (iFolderToDeleteId)
       
  2199 			iState = EMoveOtherEntryToParentOfFolder;
       
  2200 		else
       
  2201 			iState = ECompleteRemoveMessagePart;
       
  2202 		break;
       
  2203 	case EDeleteFolderEntry:
       
  2204 		iState = ECompleteRemoveMessagePart;
       
  2205 		break;
       
  2206 	case ECompleteRemoveMessagePart:
       
  2207 		iState = EFinished;
       
  2208 		break;
       
  2209 	default:
       
  2210 		User::LeaveIfError(KErrNotSupported);
       
  2211 		}
       
  2212 	}
       
  2213 
       
  2214 void CImRemoveMessagePart::ChangeStateL()
       
  2215 	{
       
  2216 	switch (iState)
       
  2217 		{
       
  2218 	case ECheckAttachmentParentType:
       
  2219 		CheckAttachmentParentTypeL();
       
  2220 		break;
       
  2221 	case EMoveOtherEntryToParentOfFolder:
       
  2222 		MoveOtherEntryToParentOfFolderL();
       
  2223 		break;
       
  2224 	case EDeleteAttachmentEntry:
       
  2225 		DeleteAttachmentEntryL();
       
  2226 		break;
       
  2227 	case EDeleteFolderEntry:
       
  2228 		DeleteFolderEntryL();
       
  2229 		break;
       
  2230 	case ECompleteRemoveMessagePart:
       
  2231 		CompleteRemoveMessagePartL();
       
  2232 		break;
       
  2233 	case EFinished:
       
  2234 		{
       
  2235 		TRequestStatus* status=&iObserverRequestStatus;
       
  2236 		User::RequestComplete(status,KErrNone);
       
  2237 		}
       
  2238 		}
       
  2239 	}
       
  2240 
       
  2241 void CImRemoveMessagePart::RequestComplete(TInt aError)
       
  2242 	{
       
  2243 	iStatus = KRequestPending;
       
  2244 	TRequestStatus* status=&iStatus;
       
  2245 	iStatus=KRequestPending;
       
  2246 	User::RequestComplete(status,aError);
       
  2247 	}
       
  2248 
       
  2249 void CImRemoveMessagePart::Recover()
       
  2250 	{
       
  2251 	switch (iState)
       
  2252 		{
       
  2253 	case EDeleteFolderEntry:
       
  2254 	case EDeleteAttachmentEntry:
       
  2255 		// delete folder if one exists else delete attachment
       
  2256 		if (iFolderToDeleteId)
       
  2257 			iMsvEntry.Session().RemoveEntry(iFolderToDeleteId);
       
  2258 		else
       
  2259 			iMsvEntry.Session().RemoveEntry(iAttachmentId);
       
  2260 		break;
       
  2261 	case ECompleteRemoveMessagePart: // not fatal - details might be incorrect but delete already done
       
  2262 	// for other states - original message not changed:
       
  2263 	case EMoveOtherEntryToParentOfFolder:
       
  2264 	case ECheckAttachmentParentType: 
       
  2265 	case EFinished:	// operation completed anyway
       
  2266 		break;
       
  2267 		}
       
  2268 	}
       
  2269 
       
  2270 void CImRemoveMessagePart::CheckAttachmentParentTypeL()
       
  2271 	{
       
  2272 	TMsvId serviceId; // temp
       
  2273 	TMsvEmailEntry attachmentEntry;
       
  2274 	iMsvEntry.Session().GetEntry(iAttachmentId, serviceId, attachmentEntry);
       
  2275 	iMsvEntry.SetEntryL(attachmentEntry.Parent());
       
  2276 
       
  2277 	// get children of attachments parent
       
  2278 	iMessageEntrySelection = iMsvEntry.ChildrenL();
       
  2279 
       
  2280 	TMsvEmailEntry parentEntry = iMsvEntry.Entry();
       
  2281 	if (parentEntry.iType == KUidMsvFolderEntry)
       
  2282 		{
       
  2283 		// if there are 2 or less children, the other children need to be moved and then the folder deleted
       
  2284 		if (iMessageEntrySelection->Count() <= 2)
       
  2285 			iFolderToDeleteId = iMsvEntry.EntryId();
       
  2286 		}
       
  2287 	// if there are no other attachments then unset attachment flag in message
       
  2288 	iEmailMessage->GetAttachmentsListL(iStatus, iMessageId, CImEmailMessage::EAllAttachments,CImEmailMessage::EThisMessageOnly);
       
  2289 	}
       
  2290 
       
  2291 void CImRemoveMessagePart::MoveOtherEntryToParentOfFolderL()
       
  2292 	{
       
  2293 	// context on parent of attachment
       
  2294 	// move entry to folder's parent
       
  2295 	TInt i = iMessageEntrySelection->Count();
       
  2296 	while (i--)
       
  2297 		{
       
  2298 		if ((*iMessageEntrySelection)[i] != iAttachmentId)
       
  2299 			iEntryToMoveId = (*iMessageEntrySelection)[i];
       
  2300 		}
       
  2301 	delete iMsvOperation;
       
  2302 	iMsvOperation = NULL;
       
  2303 	iMsvOperation = iMsvEntry.MoveL(iEntryToMoveId, iMsvEntry.Entry().Parent(), iStatus);
       
  2304 	}
       
  2305 
       
  2306 void CImRemoveMessagePart::DeleteAttachmentEntryL()
       
  2307 	{
       
  2308 	// context on parent of attachment
       
  2309 	delete iMsvOperation;
       
  2310 	iMsvOperation = NULL;
       
  2311 	iMsvOperation = iMsvEntry.DeleteL(iAttachmentId, iStatus);
       
  2312 	}
       
  2313 
       
  2314 void CImRemoveMessagePart::DeleteFolderEntryL()
       
  2315 	{
       
  2316 	// context on parent of attachment - i.e. folder
       
  2317 	// move context to parent of folder before deleting folder
       
  2318 	iMsvEntry.SetEntryL(iMsvEntry.Entry().Parent());
       
  2319 
       
  2320 	delete iMsvOperation;
       
  2321 	iMsvOperation = NULL;
       
  2322 	iMsvOperation = iMsvEntry.DeleteL(iFolderToDeleteId, iStatus);
       
  2323 	}
       
  2324 
       
  2325 void CImRemoveMessagePart::CompleteRemoveMessagePartL()
       
  2326 	{
       
  2327 	iMsvEntry.SetEntryL(iMessageId);
       
  2328 	TMsvEntry entry(iMsvEntry.Entry());
       
  2329 
       
  2330 	TInt count = iEmailMessage->AttachmentManager().AttachmentCount();
       
  2331 	if (count)
       
  2332 		{
       
  2333 		entry.SetAttachment((count-1)); // minus one since we have removed attachment
       
  2334 		}
       
  2335 
       
  2336 	// update the size
       
  2337 	entry.iSize -= iAttachmentSize;
       
  2338 
       
  2339 	CMsvEntrySelection* selection = iMsvEntry.ChildrenWithTypeL(KUidMsvFolderEntry);
       
  2340 	CleanupStack::PushL(selection);
       
  2341 	CMsvStore* store = iMsvEntry.EditStoreL();
       
  2342 	CleanupStack::PushL(store);
       
  2343 
       
  2344 	if (selection->Count()) // folder exist
       
  2345 		{
       
  2346 		TMsvEmailEntry childEntry = iMsvEntry.ChildDataL((*selection)[0]);
       
  2347 	
       
  2348 		CImMimeHeader* mimeHeader = CImMimeHeader::NewLC();
       
  2349 		mimeHeader->RestoreL(*store);
       
  2350 		switch (childEntry.MessageFolderType())
       
  2351 			{
       
  2352 		case EFolderTypeAlternative:
       
  2353 			mimeHeader->SetContentSubTypeL(KMimeAlternative);
       
  2354 			break;
       
  2355 		case EFolderTypeMixed:
       
  2356 			mimeHeader->SetContentSubTypeL(KMimeMixed);
       
  2357 			break;
       
  2358 		case EFolderTypeRelated:
       
  2359 			mimeHeader->SetContentSubTypeL(KMimeRelated);
       
  2360 			break;
       
  2361 		default:
       
  2362 			User::Leave(KErrNotSupported);
       
  2363 			}
       
  2364 		mimeHeader->StoreL(*store);
       
  2365 		store->CommitL();
       
  2366 		CleanupStack::PopAndDestroy(); // mimeHeader
       
  2367 		}
       
  2368 	else if (store->IsPresentL(KUidMsgFileMimeHeader))
       
  2369 		{
       
  2370 		// if the child of the message is not a folder then the MimeHeader must be deleted
       
  2371 		store->RemoveL(KUidMsgFileMimeHeader);
       
  2372 		store->CommitL();
       
  2373 		}
       
  2374 	CleanupStack::PopAndDestroy(2); // selection, store
       
  2375 	delete iMsvOperation;
       
  2376 	iMsvOperation=NULL;
       
  2377 	iMsvOperation=iMsvEntry.ChangeL(entry, iStatus);
       
  2378 	}
       
  2379 	
       
  2380 TMsvId CImRemoveMessagePart::RemovedAttachmentId()
       
  2381 	{
       
  2382 	return iAttachmentId;
       
  2383 	}
       
  2384 
       
  2385 //
       
  2386 // CImStoreMessagePart
       
  2387 //
       
  2388 
       
  2389 CImStoreMessagePart* CImStoreMessagePart::AddAttachmentL(TMsvId aMessageId,const TDesC& aFilePath, CMsvEntry& aMsvEntry,CMsvAttachment* aAttachmentInfo,TRequestStatus& aStatus )
       
  2390 	{
       
  2391 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry,aMessageId);
       
  2392 	CleanupStack::PushL(self);
       
  2393 	self->ConstructL(aFilePath);
       
  2394 	self->ConstructAttachmentInfo(aAttachmentInfo,EAddAttachment);
       
  2395 	CleanupStack::Pop(self);
       
  2396 	return self;
       
  2397 	}
       
  2398 	
       
  2399 CImStoreMessagePart* CImStoreMessagePart::AddEntryAsAttachmentL(TMsvId aMessageId,TMsvId aAttachmentMessageId, CMsvEntry& aMsvEntry, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)
       
  2400 	{
       
  2401 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry, aMessageId);
       
  2402 	CleanupStack::PushL(self);
       
  2403 	self->ConstructL(aAttachmentMessageId);
       
  2404 	self->ConstructAttachmentInfo(aAttachmentInfo,EAddEntryAsAttachment);
       
  2405 	CleanupStack::Pop(self);
       
  2406 	return self;
       
  2407 	}
       
  2408 
       
  2409 CImStoreMessagePart* CImStoreMessagePart::AddAttachmentL(TMsvId aMessageId, RFile& aFile, CMsvEntry& aMsvEntry, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus) 	
       
  2410 	{
       
  2411 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry,aMessageId);
       
  2412 	CleanupStack::PushL(self);
       
  2413 	self->ConstructL(aFile);
       
  2414 	self->ConstructAttachmentInfo(aAttachmentInfo,EAddAttachmentUsingFileHandle);
       
  2415 	CleanupStack::Pop(self);
       
  2416 	return self;
       
  2417 	}
       
  2418 	
       
  2419 CImStoreMessagePart* CImStoreMessagePart::CreateAttachmentL(TMsvId aMessageId,const TDesC& aFileName, RFile& aAttachmentFile,CMsvEntry& aMsvEntry, CMsvAttachment* aAttachmentInfo, TRequestStatus& aStatus)	
       
  2420 	{
       
  2421 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry,aMessageId);
       
  2422 	CleanupStack::PushL(self);
       
  2423 	self->ConstructL(aAttachmentFile,aFileName);
       
  2424 	self->ConstructAttachmentInfo(aAttachmentInfo,ECreateAttachment);
       
  2425 	CleanupStack::Pop(self);
       
  2426 	return self;
       
  2427 	}
       
  2428 	
       
  2429 CImStoreMessagePart* CImStoreMessagePart::AddLinkedAttachmentL(TMsvId aMessageId,const TDesC& aFilePath, CMsvEntry& aMsvEntry,CMsvAttachment* aAttachmentInfo,TRequestStatus& aStatus )	
       
  2430 	{
       
  2431 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry,aMessageId);
       
  2432 	CleanupStack::PushL(self);
       
  2433 	self->ConstructL(aFilePath);
       
  2434 	self->ConstructAttachmentInfo(aAttachmentInfo,EAddLinkedAttachment);
       
  2435 	CleanupStack::Pop(self);
       
  2436 	return self;
       
  2437 	}
       
  2438 
       
  2439 
       
  2440 CImStoreMessagePart* CImStoreMessagePart::AddRelatedPartL(TRequestStatus &aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId, const TDesC& aAttachmentFullName, TMsvId aRelatedPartId, const TDesC8& aContentId)
       
  2441 	{
       
  2442 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry, aMessageId);
       
  2443 	CleanupStack::PushL(self);
       
  2444 	self->ConstructL(aAttachmentFullName, aRelatedPartId, aContentId);
       
  2445 	CleanupStack::Pop(self);
       
  2446 	return self;
       
  2447 	}
       
  2448 
       
  2449 CImStoreMessagePart* CImStoreMessagePart::StoreBodyTextL(TRequestStatus& aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId, CRichText& aRichText, TBool aUsePlainTextStorage)
       
  2450 	{
       
  2451 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry, aMessageId, aUsePlainTextStorage);
       
  2452 	CleanupStack::PushL(self);
       
  2453 	self->ConstructL(aRichText);
       
  2454 	CleanupStack::Pop(self);
       
  2455 	return self;
       
  2456 	}
       
  2457 
       
  2458 CImStoreMessagePart* CImStoreMessagePart::StoreBodyTextWithMimeHeaderL(TRequestStatus& aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId, CRichText& aRichText, const CImMimeHeader& aMimeHeader, TBool aUsePlainTextStorage)
       
  2459 	{
       
  2460 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry, aMessageId, aUsePlainTextStorage);
       
  2461 	CleanupStack::PushL(self);
       
  2462 	self->ConstructL(aRichText, aMimeHeader);
       
  2463 	CleanupStack::Pop(self);
       
  2464 	return self;
       
  2465 	}
       
  2466 
       
  2467 
       
  2468 CImStoreMessagePart* CImStoreMessagePart::StorePlainBodyTextL(TRequestStatus& aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId, TBool aUsePlainTextStorage)
       
  2469 	{
       
  2470 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry, aMessageId, aUsePlainTextStorage);
       
  2471 	CleanupStack::PushL(self);
       
  2472 	self->ConstructL(EMessagePartBody);
       
  2473 	CleanupStack::Pop(self);
       
  2474 	return self;
       
  2475 	}
       
  2476 	
       
  2477 
       
  2478 	
       
  2479 CImStoreMessagePart* CImStoreMessagePart::StorePlainBodyTextL(TRequestStatus& aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId,CImMimeHeader& aMimeHeader, TBool aUsePlainTextStorage)
       
  2480 	{
       
  2481 	CImStoreMessagePart* self = new(ELeave) CImStoreMessagePart(aStatus, aMsvEntry, aMessageId, aUsePlainTextStorage);
       
  2482 	CleanupStack::PushL(self);
       
  2483 	self->ConstructL(aMimeHeader);
       
  2484 	CleanupStack::Pop(self);
       
  2485 	return self;
       
  2486 	}
       
  2487 		
       
  2488 CImStoreMessagePart::~CImStoreMessagePart()
       
  2489 	{
       
  2490 	Cancel();
       
  2491 	delete iMsvOperation;
       
  2492 	delete iFileMan;
       
  2493 	delete iMessageEntrySelection;
       
  2494 	delete iAttachmentFullName;
       
  2495 	delete iContentId;
       
  2496 	delete iHtmlConverter;
       
  2497 	delete iParaLayer;
       
  2498 	delete iCharLayer;
       
  2499 	delete iEmailMessage;
       
  2500 	delete iRichText;
       
  2501 	delete iStore;
       
  2502 	delete iAttachmentInfo;
       
  2503 	}
       
  2504 
       
  2505 const TDesC8& CImStoreMessagePart::FinalProgress()
       
  2506 	{
       
  2507 	__ASSERT_ALWAYS(!IsActive(), gPanic(EMiutActiveInFinalProgress));
       
  2508  	const TDesC8* progress = &KNullDesC8();
       
  2509  	TRAPD(leave, progress = &ProgressL());
       
  2510 	__ASSERT_ALWAYS(leave == KErrNone, gPanic(EImcmFinalProgressFailed));
       
  2511 	return *progress;	
       
  2512 	}
       
  2513 
       
  2514 const TDesC8& CImStoreMessagePart::ProgressL()
       
  2515 	{
       
  2516 	if (iState==EFinished)
       
  2517 		{
       
  2518 		switch(iMessagePart)
       
  2519 			{
       
  2520 		case EMessagePartAttachment:
       
  2521 		case EMessagePartMessageAttachment:
       
  2522 			iDataMember() = iAttachmentId;
       
  2523 			break;
       
  2524 		case EMessagePartBody:
       
  2525 			iDataMember() = iMessageId;
       
  2526 			break;
       
  2527 		default:
       
  2528 			iDataMember() = KMsvNullIndexEntryId;
       
  2529 			User::Leave(KErrNotSupported);
       
  2530 			}
       
  2531 		}
       
  2532 	return iDataMember;
       
  2533 	}
       
  2534 
       
  2535 void CImStoreMessagePart::DoCancel()
       
  2536 	{
       
  2537 	if (iMsvOperation)
       
  2538 		iMsvOperation->Cancel();
       
  2539 	if (iEmailMessage)
       
  2540 		iEmailMessage->Cancel();
       
  2541 
       
  2542 	// If we are in a state where we are waiting for the attachment manager to
       
  2543 	// complete us, then we need to cancel the attachment manager request
       
  2544 	if ((iState == EStoreAttachment) || (iState == EAddEntryAttachment))
       
  2545 		{
       
  2546 		if (iStore != NULL)
       
  2547 			{
       
  2548 			MMsvAttachmentManager* attachmentMgr(NULL);
       
  2549 
       
  2550 			TRAPD(err, attachmentMgr = &(iStore->AttachmentManagerL()));
       
  2551 
       
  2552 			if (err == KErrNone)
       
  2553 				{
       
  2554 				attachmentMgr->CancelRequest();
       
  2555 				}
       
  2556 			}
       
  2557 		}
       
  2558 	else
       
  2559 		{
       
  2560 		// we are not waiting for the attachment manager to complete us,
       
  2561 		// so the file handle needs to be closed by us.
       
  2562 		if((iAttachmentInfo != NULL) && (iAttachmentCreateState == EAddAttachmentUsingFileHandle))
       
  2563 			{
       
  2564 			iFile.Close();
       
  2565 			}
       
  2566 		}
       
  2567 
       
  2568 	// Use ErrorRecovery routine to cleanup and complete the caller with KErrCancel
       
  2569 	ErrorRecovery(KErrCancel);
       
  2570 
       
  2571 	}
       
  2572 
       
  2573 void CImStoreMessagePart::SelectAndChangeToNextStateL()
       
  2574 	{
       
  2575 	SelectNextStateL();
       
  2576 	ChangeStateL();
       
  2577 	}
       
  2578 
       
  2579 void CImStoreMessagePart::RunL()
       
  2580 	{
       
  2581 	if (iStatus.Int() != KErrNone)
       
  2582 		{
       
  2583 		ErrorRecovery(iStatus.Int());
       
  2584 		return;
       
  2585 		}
       
  2586 	if ((iState == ECreateAttachmentEntry) || 
       
  2587 		(iState == ECopyOrigMessageToMessage) || 
       
  2588 		(iState == ECreateMultipartMixedFolderEntry) ||
       
  2589 		(iState == ECreateMultipartRelatedFolderEntry) ||
       
  2590 		(iState == ECreateMultipartAlternativeFolderEntry) ||
       
  2591 		(iState == EMoveOriginalMessageEntryChildrenToNewFolder) ||
       
  2592 		(iState == ECreateTextEntry) ||
       
  2593 		(iState == EStoreRichText) ||
       
  2594 		(iState == ECreateHTMLEntry) ||
       
  2595 		(iState == ERemoveHTMLEntry && iHtmlId !=KMsvNullIndexEntryId) || 
       
  2596 		(iState == EMoveTextToAlternativeFolder) ||
       
  2597 		(iState == ECompleteStoreMessage))
       
  2598 		{
       
  2599 		TInt sysProgressError = McliUtils::GetProgressErrorL(*iMsvOperation);
       
  2600 		if (sysProgressError != KErrNone)
       
  2601 			{
       
  2602 			ErrorRecovery(sysProgressError);
       
  2603 			return;
       
  2604 			}
       
  2605 		}
       
  2606 	if (iState != EFinished)
       
  2607 		{
       
  2608 		TRAPD(error, SelectAndChangeToNextStateL());
       
  2609 		if (error)
       
  2610 			ErrorRecovery(error);
       
  2611 		else if (iState != EFinished)
       
  2612 			SetActive();
       
  2613 		}
       
  2614 	}
       
  2615 
       
  2616 CImStoreMessagePart::CImStoreMessagePart(TRequestStatus& aStatus, CMsvEntry& aMsvEntry, TMsvId aMessageId, TBool aUsePlainTextStorage)
       
  2617 	: CMsvOperation(aMsvEntry.Session(), EPriorityStandard, aStatus),
       
  2618 	  iMsvEntry(aMsvEntry),
       
  2619 	  iMessageId(aMessageId),
       
  2620 	  iUsePlainTextStorage(aUsePlainTextStorage)
       
  2621 	{
       
  2622 	}
       
  2623 
       
  2624 void CImStoreMessagePart::OpenAndReadResourceFileL()
       
  2625 	{
       
  2626 	RResourceFile resourceFile;
       
  2627 	OpenResourceFileL(resourceFile, iMsvSession.FileSession());
       
  2628 	CleanupClosePushL(resourceFile);
       
  2629 
       
  2630 	if (iHtmlConverter)
       
  2631 		iHtmlConverter->ReadDefaultAttachmentNameL(resourceFile);
       
  2632 			
       
  2633 	CleanupStack::PopAndDestroy(); // resourceFile (Close resourceFile)
       
  2634 	}
       
  2635 
       
  2636 void CImStoreMessagePart::ConstructL()
       
  2637 	{
       
  2638 	iFlags = KStoreMessagePartClearFlag;
       
  2639 	iDataMember = KMsvNullIndexEntryId;
       
  2640 	iMixFolderId = KMsvNullIndexEntryId;
       
  2641 	iAltFolderId = KMsvNullIndexEntryId;
       
  2642 	iAttachmentId = KMsvNullIndexEntryId;
       
  2643 	iTextId = KMsvNullIndexEntryId;
       
  2644 	iHtmlId = KMsvNullIndexEntryId;
       
  2645 
       
  2646 	iFileMan = CFileMan::NewL(iMsvEntry.Session().FileSession());
       
  2647 
       
  2648 	iParaLayer = CParaFormatLayer::NewL();
       
  2649 	iCharLayer = CCharFormatLayer::NewL();
       
  2650 	iRichText = CRichText::NewL(iParaLayer, iCharLayer);
       
  2651 	iEmailMessage = CImEmailMessage::NewL(iMsvEntry);
       
  2652 	
       
  2653 	CActiveScheduler::Add(this);
       
  2654 
       
  2655 	if (iRelatedPartId != KMsvNullIndexEntryId)
       
  2656 		iState = EFindMultipartRelatedFolder;
       
  2657 	else
       
  2658 		iState = ECheckForSubfolder;
       
  2659 	ChangeStateL();
       
  2660 	
       
  2661 
       
  2662 	iObserverRequestStatus = KRequestPending;
       
  2663 	SetActive();
       
  2664 	}
       
  2665 
       
  2666 void CImStoreMessagePart::ConstructL(TImMessagePart aMessagePart)
       
  2667 	{
       
  2668 	iMessagePart = aMessagePart;
       
  2669 	ConstructL();	
       
  2670 	}
       
  2671 	
       
  2672 void CImStoreMessagePart::ConstructL(const TDesC& aAttachmentFullName)
       
  2673 	{
       
  2674 	iAttachmentFullName = aAttachmentFullName.AllocL();
       
  2675 	iMessagePart = EMessagePartAttachment;
       
  2676 	ConstructL();
       
  2677 	}
       
  2678 
       
  2679 void CImStoreMessagePart::ConstructL(TMsvId aAttachmentMessageId)
       
  2680 	{
       
  2681 	iAttachmentMessageId = aAttachmentMessageId;
       
  2682 	iMessagePart = EMessagePartMessageAttachment;
       
  2683 	ConstructL();
       
  2684 	}
       
  2685 
       
  2686 void CImStoreMessagePart::ConstructL(const TDesC& aAttachmentFullName, TMsvId aRelatedPartId, const TDesC8& aContentId)
       
  2687 	{
       
  2688 	iAttachmentFullName = aAttachmentFullName.AllocL();
       
  2689 	iRelatedPartId = aRelatedPartId;
       
  2690 	iMessagePart = EMessagePartAttachment;
       
  2691 	iContentId = aContentId.AllocL();
       
  2692 	ConstructL();
       
  2693 	}
       
  2694 
       
  2695 void CImStoreMessagePart::ConstructL(CRichText& aRichText)
       
  2696 	{
       
  2697 	iRichTextToStore=&aRichText;
       
  2698 	iMessagePart = EMessagePartBody;
       
  2699 	ConstructL();
       
  2700 	}
       
  2701 
       
  2702 void CImStoreMessagePart::ConstructL(CRichText& aRichText, const CImMimeHeader& aMimeHeader)
       
  2703 	{
       
  2704 	iRichTextToStore=&aRichText;
       
  2705 	// We don't take ownership of the Mime header, we just 'flag' 
       
  2706 	// its presence:
       
  2707 	iMimeHeaderOfBodyText=const_cast<CImMimeHeader*>(&aMimeHeader);
       
  2708 	iMessagePart = EMessagePartBody;
       
  2709 	ConstructL();
       
  2710 	}
       
  2711 
       
  2712 void CImStoreMessagePart::ConstructL(CImMimeHeader& aMimeHeader)
       
  2713 	{
       
  2714 	// We don't take ownership of the Mime header, we just 'flag' 
       
  2715 	// its presence:
       
  2716 	iMimeHeaderOfBodyText = &aMimeHeader;
       
  2717 	iMessagePart = EMessagePartBody;
       
  2718 	ConstructL();
       
  2719 	}
       
  2720 void CImStoreMessagePart::ConstructL(const TDesC& aAttachmentFullName, const TDesC8& aContentId)
       
  2721 	{
       
  2722 	iAttachmentFullName = aAttachmentFullName.AllocL();
       
  2723 	iMessagePart = EMessagePartAttachment;
       
  2724 	iContentId = aContentId.AllocL();
       
  2725 	iStore=NULL;
       
  2726 	ConstructL();
       
  2727 	}
       
  2728 	
       
  2729 void CImStoreMessagePart::ConstructL(RFile& aFile)
       
  2730 	{
       
  2731 	iFile = aFile;
       
  2732 	iFileHandle=&aFile;
       
  2733 	iMessagePart = EMessagePartAttachment;
       
  2734 	iIsAddByFileHandle = ETrue;
       
  2735 	ConstructL();
       
  2736 	}
       
  2737 
       
  2738 void CImStoreMessagePart::ConstructL(RFile& aFile,const TDesC& aAttachmentName)
       
  2739 	{
       
  2740 	iAttachmentFullName = aAttachmentName.AllocL();
       
  2741 	iFileHandle=&aFile;
       
  2742 	iMessagePart = EMessagePartAttachment;
       
  2743 	iIsAddByFileHandle=ETrue;
       
  2744 	ConstructL();
       
  2745 	}
       
  2746 
       
  2747 void CImStoreMessagePart::ConstructAttachmentInfo(CMsvAttachment* aAttachmentInfo,TInt aAttachmentCreationState)
       
  2748 	{
       
  2749 	iAttachmentInfo = aAttachmentInfo;
       
  2750 	iAttachmentCreateState = aAttachmentCreationState;
       
  2751 	}
       
  2752 	
       
  2753 void CImStoreMessagePart::ErrorRecovery(TInt error)
       
  2754 	{
       
  2755 	iHtmlConverter->ResetStoreWithoutCommit();
       
  2756 	// Close store if it is currently open for read or edit
       
  2757 	if (iStore != NULL)
       
  2758 		{
       
  2759 		delete iStore;
       
  2760 		iStore = NULL;
       
  2761 		}
       
  2762 	
       
  2763 	// if there is an error then need to undo any changes
       
  2764 	Recover();
       
  2765 
       
  2766 	// complete the observer with error
       
  2767 	TRequestStatus* status=&iObserverRequestStatus;
       
  2768 	User::RequestComplete(status,error);
       
  2769 	}
       
  2770 
       
  2771 void CImStoreMessagePart::SelectNextStateL()
       
  2772 	{
       
  2773 	switch (iState)
       
  2774 		{
       
  2775 	case EFindMultipartRelatedFolder:
       
  2776 		iState = ECheckForSubfolder;
       
  2777 		break;
       
  2778 	case ECheckForSubfolder:
       
  2779 		// context on Message
       
  2780 		if (iEmailMessage->Selection().Count())
       
  2781 			iTextId = iEmailMessage->Selection().At(0);
       
  2782 		SetTextPartExists(iEmailMessage->Selection().Count());
       
  2783 		if (iMessagePart == EMessagePartAttachment)
       
  2784 			{
       
  2785 			if (iMessageEntrySelection->Count() && (iRelatedPartId == KMsvNullIndexEntryId) && (!MultipartMixedExists()))
       
  2786 				// one item under message entry as we should have more than one entry under message entry
       
  2787 				iState = ECreateMultipartMixedFolderEntry;
       
  2788 			else if (iMessageEntrySelection->Count() && (iRelatedPartId != KMsvNullIndexEntryId) && (!MultipartRelatedExists())) 
       
  2789 				{
       
  2790 				// we want to add an attachment related to iRelatedPartId
       
  2791 				if (MultipartMixedExists())
       
  2792 					iMsvEntry.SetEntryL(iMixFolderId);
       
  2793 				iState = ECreateMultipartRelatedFolderEntry;
       
  2794 				}
       
  2795 			else
       
  2796 				{
       
  2797 				// if multipart/related exists then set context to related
       
  2798 				if (MultipartRelatedExists())
       
  2799 					iMsvEntry.SetEntryL(iRelFolderId);
       
  2800 				if (MultipartMixedExists())
       
  2801 					iMsvEntry.SetEntryL(iMixFolderId);
       
  2802 				iState = ECreateAttachmentEntry;
       
  2803 				}
       
  2804 			}
       
  2805 		else if (iMessagePart == EMessagePartMessageAttachment)
       
  2806 			{
       
  2807 			if (iMessageEntrySelection->Count() && (iRelatedPartId == KMsvNullIndexEntryId) && (!MultipartMixedExists()))
       
  2808 				// one item under message entry as we should have more than one entry under message entry
       
  2809 				iState = ECreateMultipartMixedFolderEntry;
       
  2810 			else 
       
  2811 				iState = ECopyOrigMessageToMessage;
       
  2812 			}
       
  2813 		else if (iMessagePart == EMessagePartBody)
       
  2814 			{
       
  2815 	        if (HTMLMessage() && iHtmlConverter)
       
  2816 	            {
       
  2817 	            if (iTextId != KMsvNullIndexEntryId)
       
  2818 		            {
       
  2819 		            if (MultipartAlternativeExists())
       
  2820 		                {
       
  2821 		                // Alternative folder exists - continue as normal...
       
  2822 		                iState = EStoreRichText;
       
  2823 		                }
       
  2824 	                else
       
  2825 						{	
       
  2826 						// This is an HTML message and the text entry already
       
  2827 						// exists. Need to check that the text entry's parent
       
  2828 						// is an alternative folder.
       
  2829 						TMsvId serviceId = KMsvNullIndexEntryId;
       
  2830 						TMsvEmailEntry entry;
       
  2831 						// Get text entry...
       
  2832 						iMsvEntry.Session().GetEntry(iTextId, serviceId, entry);
       
  2833 						// ...and then its parent
       
  2834 						iMsvEntry.Session().GetEntry(entry.Parent(), serviceId, entry);
       
  2835 						if (entry.MessageFolderType() != EFolderTypeAlternative)
       
  2836 							{
       
  2837 						   // The situation is that a text entry exist, but there
       
  2838 	                       // is no alternative folder for. This is probably cos
       
  2839                            // the message was originally plain, but has been changed
       
  2840                            // to be an HTML message. Create the alternative folder
       
  2841                            // under the text entry's parent.
       
  2842 	                       if (iMsvEntry.EntryId() != entry.Id())
       
  2843 		                       {
       
  2844 		                       // Ensure that entry text entry's parent
       
  2845 		                       iMsvEntry.SetEntryL(entry.Id());
       
  2846 							   }
       
  2847 			                  iState = ECreateMultipartAlternativeFolderEntry;
       
  2848 		                   }
       
  2849 						else
       
  2850 						   {
       
  2851 			              // Alternative folder exists - continue as normal...
       
  2852 	                      iState = EStoreRichText;
       
  2853 						   }
       
  2854 						}
       
  2855 					}
       
  2856 				else
       
  2857 					{
       
  2858 					// No text entry exists - need to create an alternative folder
       
  2859 					iState = ECreateMultipartAlternativeFolderEntry;
       
  2860 					}
       
  2861 				}
       
  2862 			else if (iTextId != KMsvNullIndexEntryId)
       
  2863 				iState = EStoreRichText;
       
  2864 			else if (iMessageEntrySelection->Count() && (!MultipartMixedExists())) // one item under message entry
       
  2865 				iState = ECreateMultipartMixedFolderEntry;
       
  2866 			else
       
  2867 				{
       
  2868 				if (MultipartMixedExists())
       
  2869 					iMsvEntry.SetEntryL(iMixFolderId);
       
  2870 				iState = ECreateTextEntry;
       
  2871 				}
       
  2872 			}
       
  2873 		break;
       
  2874 	case ECreateMultipartMixedFolderEntry:
       
  2875 		{
       
  2876 		SetMultipartMixedCreated(ETrue);
       
  2877 		iMixFolderId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  2878 		iMsvEntry.SetEntryL(iMixFolderId);
       
  2879 		switch (iMessagePart)
       
  2880 			{
       
  2881 		case EMessagePartAttachment:
       
  2882 		case EMessagePartMessageAttachment:
       
  2883 			if ((iRelatedPartId != KMsvNullIndexEntryId) && (!MultipartRelatedExists()))
       
  2884 				iState = ECreateMultipartRelatedFolderEntry;
       
  2885 			else if (iMessagePart == EMessagePartAttachment)
       
  2886 				iState = ECreateAttachmentEntry;
       
  2887 			else if (iMessagePart == EMessagePartMessageAttachment)
       
  2888 				iState = ECopyOrigMessageToMessage;
       
  2889 			break;
       
  2890 		case EMessagePartBody:
       
  2891 			if (HTMLMessage())
       
  2892 				iState = ECreateMultipartAlternativeFolderEntry;
       
  2893 			else
       
  2894 				iState = ECreateTextEntry;
       
  2895 			break;
       
  2896 		default:
       
  2897 			User::Leave(KErrNotSupported);
       
  2898 			}
       
  2899 		}
       
  2900 		break;
       
  2901 	case ECreateMultipartRelatedFolderEntry:
       
  2902 		{
       
  2903 		SetMultipartRelatedCreated(ETrue);
       
  2904 		iRelFolderId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  2905 		iMsvEntry.SetEntryL(iRelFolderId);
       
  2906 		iState = ECreateAttachmentEntry;
       
  2907 		}
       
  2908 		break;
       
  2909 	case ECreateAttachmentEntry:
       
  2910 		{
       
  2911 		SetAttachmentEntryCreated(ETrue);
       
  2912 		iAttachmentId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  2913 		iMsvEntry.SetEntryL(iAttachmentId);
       
  2914 		// we only need to store the attachment if the path is provided - otherwise, only 
       
  2915 		// the entry needs to be created so that the actual attachment can be added later.
       
  2916 		if(iIsAddByFileHandle || iAttachmentFullName->Length())	
       
  2917 			iState = EStoreAttachment;
       
  2918 		else if (MultipartMixedCreated() || MultipartRelatedCreated())
       
  2919 			iState = EMoveOriginalMessageEntryChildrenToNewFolder;
       
  2920 		else
       
  2921 			iState = ECompleteStoreMessage;
       
  2922 		}
       
  2923 		break;
       
  2924 	case EStoreAttachment:
       
  2925 		iStore->CommitL();
       
  2926 	
       
  2927 		delete iStore;
       
  2928 		iStore = NULL;	
       
  2929 		
       
  2930 		if (MultipartMixedCreated() || MultipartRelatedCreated())
       
  2931 			iState = EMoveOriginalMessageEntryChildrenToNewFolder;
       
  2932 		else
       
  2933 			iState = ECompleteStoreMessage;
       
  2934 		break;
       
  2935 	case ECopyOrigMessageToMessage:
       
  2936 		{
       
  2937 		iAttachmentId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  2938 		iState = EAddEntryAttachment;
       
  2939 		}
       
  2940 		break;
       
  2941 	case ECreateMultipartAlternativeFolderEntry:
       
  2942 		{
       
  2943 		iAltFolderId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  2944 		iMsvEntry.SetEntryL(iAltFolderId);
       
  2945 		SetMultipartAlternativeCreated(ETrue);
       
  2946 		SetMultipartAlternativeExists(ETrue);
       
  2947 		
       
  2948 		// Text Entry was already created without alternative folder . 
       
  2949 		// This is because of change in email settings from Plain (when creating the message) 
       
  2950 		// to Formatted (when sending the message)
       
  2951 		if(iTextId != KMsvNullIndexEntryId)
       
  2952 			iState = EMoveTextToAlternativeFolder;
       
  2953 		else 
       
  2954 			iState = ECreateTextEntry;
       
  2955 		}
       
  2956 		break;
       
  2957 	case EMoveTextToAlternativeFolder:
       
  2958 		{
       
  2959 		iState = EStoreRichText;
       
  2960 		}
       
  2961 		break;
       
  2962 	case ECreateTextEntry:
       
  2963 		if (iTextId == KMsvNullIndexEntryId)
       
  2964 			{
       
  2965 			iTextId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  2966 			}
       
  2967 		iState = EStoreRichText;
       
  2968 		break;
       
  2969 	case EStoreRichText:
       
  2970 		// a text part has been created ONLY if one did not exist previously
       
  2971 		SetTextPartCreated(!TextPartExists());
       
  2972 		if (TextPartExists() && MultipartAlternativeCreated())
       
  2973 			{
       
  2974 			// The text entry already existed, but an alternative folder had to
       
  2975 			// created. This is probably due to the message being originally
       
  2976 			// plain and then being changed to be an HTML message. Need to create
       
  2977 			// the HTML entry.
       
  2978 			iState = ECreateHTMLEntry;
       
  2979 			}
       
  2980 		else if (TextPartExists() && iHtmlConverter)
       
  2981 			{
       
  2982 			// create HTML alternative if HTML message and text part just created
       
  2983 			iState = EPrepareToStoreHTMLEntryText;
       
  2984 			}
       
  2985 		else if (!HTMLMessage() && !TextPartCreated())
       
  2986 			{
       
  2987 			// The message is a non-HTML message, and this is not the first time
       
  2988 			// that the message body has been stored. Need to remove an HTML 
       
  2989 			// entry if it exists.
       
  2990 			iState = ERemoveHTMLEntry;
       
  2991 			}
       
  2992 		else if (HTMLMessage() && (TextPartCreated() || MultipartAlternativeCreated()))
       
  2993 			iState = ECreateHTMLEntry;
       
  2994 		else if (MultipartMixedCreated())
       
  2995 			iState = EMoveOriginalMessageEntryChildrenToNewFolder;
       
  2996 		else
       
  2997 			iState = ECompleteStoreMessage;
       
  2998 		break;
       
  2999 	case ECreateHTMLEntry:
       
  3000 		{
       
  3001 		iHtmlId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  3002 		// Store character set info in a MimeHeader.
       
  3003 		iMsvEntry.SetEntryL(iHtmlId);
       
  3004 		CMsvStore* store = iMsvEntry.EditStoreL();
       
  3005 		CleanupStack::PushL(store);
       
  3006 		CImMimeHeader* mimeHeader = CImMimeHeader::NewLC();
       
  3007 		mimeHeader->SetMimeCharset(KCharacterSetIdentifierUtf8);
       
  3008 		mimeHeader->StoreL(*store);
       
  3009 		store->CommitL();
       
  3010 		CleanupStack::PopAndDestroy(2,store); //mimeHeader, store
       
  3011 		iState = EPrepareToStoreHTMLEntryText;
       
  3012 		}
       
  3013 		break;
       
  3014 	case EPrepareToStoreHTMLEntryText:
       
  3015 		iFinishedConvertingHTML=EFalse;
       
  3016 		if(iUsePlainTextStorage && iRestoreErr == KErrNoMemory)
       
  3017 			{
       
  3018 			// If iRestoreErr is KErrNoMemory then complete the store message operation.
       
  3019 			iState = ECompleteStoreMessage;	
       
  3020 			}
       
  3021 		else
       
  3022 			{
       
  3023 			iState = iHtmlId ? EStoreHTMLEntryText : ECompleteStoreMessage;	
       
  3024 			}
       
  3025 		break;
       
  3026 	case EStoreHTMLEntryText:
       
  3027 		if (!iFinishedConvertingHTML)
       
  3028 			break;
       
  3029 		iState = EStoreHTMLTextInEntry;
       
  3030 		iHtmlConverter->ResetStoreL();	
       
  3031 		break;
       
  3032 	case EStoreHTMLTextInEntry:
       
  3033 		if (MultipartMixedCreated())
       
  3034 			iState = EMoveOriginalMessageEntryChildrenToNewFolder;
       
  3035 		else
       
  3036 			iState = ECompleteStoreMessage;
       
  3037 		break;
       
  3038 	case EAddEntryAttachment:
       
  3039 		{
       
  3040 		iStore->CommitL();
       
  3041 		delete iStore;
       
  3042 		iStore = NULL;
       
  3043 					
       
  3044 		if (MultipartMixedCreated() || MultipartRelatedCreated())
       
  3045 			iState = EMoveOriginalMessageEntryChildrenToNewFolder;
       
  3046 		else
       
  3047 			{
       
  3048 			// AddEntryAsAttachmentL() was called in this state and resets iMsvEntry.
       
  3049 			// Next state requires that it's set to the messageId
       
  3050 			// DEF 050410
       
  3051 			iMsvEntry.SetEntryL(iMessageId);
       
  3052 			iState = ECompleteStoreMessage;
       
  3053 			}
       
  3054 		} break;
       
  3055 	case ERemoveHTMLEntry:
       
  3056 		{
       
  3057 		iState = ECompleteStoreMessage;
       
  3058 		} break;
       
  3059 	case EMoveOriginalMessageEntryChildrenToNewFolder:
       
  3060 		iState = ECompleteStoreMessage;
       
  3061 		break;
       
  3062 	case ECompleteStoreMessage:
       
  3063 		iState = EFinished;
       
  3064 		break;
       
  3065 	default:
       
  3066 		gPanic(EImcmUnknownState);
       
  3067 		}
       
  3068 	}
       
  3069 
       
  3070 void CImStoreMessagePart::ChangeStateL()
       
  3071 	{
       
  3072 	CMsvOperation* op;
       
  3073 	switch (iState)
       
  3074 		{
       
  3075 	case EFindMultipartRelatedFolder:
       
  3076 		FindMultipartRelatedFolderL();
       
  3077 		break;
       
  3078 	case ECheckForSubfolder:
       
  3079 		CheckForSubfolderL();
       
  3080 		break;
       
  3081 	case ECreateMultipartMixedFolderEntry:
       
  3082 		CreateMultipartMixedFolderEntryL();
       
  3083 		break;
       
  3084 	case ECreateMultipartRelatedFolderEntry:
       
  3085 		CreateMultipartRelatedFolderEntryL();
       
  3086 		break;
       
  3087 	case ECreateAttachmentEntry:
       
  3088 		CreateAttachmentEntryL();
       
  3089 		break;
       
  3090 	case EStoreAttachment:
       
  3091 		{
       
  3092 		// store the attachment
       
  3093 		DoAttachmentStoreL();
       
  3094 		}
       
  3095 		break;
       
  3096 	case ECopyOrigMessageToMessage:
       
  3097 		CopyOrigMessageToMessageL();
       
  3098 		break;
       
  3099 	case ECreateMultipartAlternativeFolderEntry:
       
  3100 		CreateMultipartAlternativeFolderEntryL();
       
  3101 		break;
       
  3102 	case EMoveTextToAlternativeFolder:
       
  3103 		// This case arrives when the email settings was plain while the message was created and 
       
  3104 		// the setting is changed to formatted (html) while sending.
       
  3105 		MoveTextEntryToAltFolderL();
       
  3106 		break;
       
  3107 	case ECreateTextEntry:
       
  3108 		CreateTextEntryL();
       
  3109 		break;
       
  3110 	case EStoreRichText:
       
  3111 		StoreRichTextL();
       
  3112 		break;
       
  3113 	case ECreateHTMLEntry:
       
  3114 		CreateHTMLEntryL();
       
  3115 		break;
       
  3116 	case EPrepareToStoreHTMLEntryText:
       
  3117 		TRAP(iRestoreErr ,iHtmlConverter->PrepareToStoreHTMLEntryTextL(iHtmlId, iTextId));
       
  3118 		// Do not leave if it is KErrNoMemory while creating HTML part for a message, since the 
       
  3119 		// plainbody text part of message is already created and that be used to send the message.
       
  3120 		if(iUsePlainTextStorage)
       
  3121 			{
       
  3122 			if(iRestoreErr != KErrNoMemory)
       
  3123 				{
       
  3124 				User::LeaveIfError(iRestoreErr);
       
  3125 				}
       
  3126 			}
       
  3127 		else
       
  3128 			{
       
  3129 			User::LeaveIfError(iRestoreErr);
       
  3130 			}
       
  3131 		
       
  3132 		RequestComplete(KErrNone);
       
  3133 		break;
       
  3134 	case EStoreHTMLEntryText:
       
  3135 		iFinishedConvertingHTML = iHtmlConverter->StoreHTMLEntryTextAL(iStatus);
       
  3136 		if (!iFinishedConvertingHTML)
       
  3137 			RequestComplete(KErrNone);
       
  3138 		break;
       
  3139 	case EStoreHTMLTextInEntry:
       
  3140 		op = iHtmlConverter->ChangeHTMLTextInEnrtyL(iStatus);
       
  3141 		if (!op)
       
  3142 			{
       
  3143 			RequestComplete(KErrNone);
       
  3144 			}
       
  3145 		else
       
  3146 			{
       
  3147 			delete iMsvOperation;
       
  3148 			iMsvOperation = op;
       
  3149 			}
       
  3150 		break;
       
  3151 	case EAddEntryAttachment:
       
  3152 		AddEntryAsAttachmentL();		
       
  3153 		break;
       
  3154 	case ERemoveHTMLEntry:
       
  3155 		{
       
  3156 		RemoveHTMLEntryL();
       
  3157 		} break;
       
  3158 	case EMoveOriginalMessageEntryChildrenToNewFolder:
       
  3159 		MoveOriginalMessageEntryChildrenToNewFolderL();
       
  3160 		break;
       
  3161 	case ECompleteStoreMessage:
       
  3162 		CompleteStoreMessagePartL();
       
  3163 		break;
       
  3164 	case EFinished:
       
  3165 		{
       
  3166 		TRequestStatus* status=&iObserverRequestStatus;
       
  3167 		User::RequestComplete(status,KErrNone);
       
  3168 		}
       
  3169 		break;
       
  3170 	default:
       
  3171 		gPanic(EImcmUnknownState);
       
  3172 		}
       
  3173 	}
       
  3174 
       
  3175 void CImStoreMessagePart::RequestComplete(TInt aError)
       
  3176 	{
       
  3177 	iStatus = KRequestPending;
       
  3178 	TRequestStatus* status=&iStatus;
       
  3179 	iStatus=KRequestPending;
       
  3180 	User::RequestComplete(status,aError);
       
  3181 	}
       
  3182 
       
  3183 void CImStoreMessagePart::Recover()
       
  3184 	{
       
  3185 	switch (iState)
       
  3186 		{
       
  3187 	case ECreateHTMLEntry:
       
  3188 	case EStoreRichText:
       
  3189 	case ERemoveHTMLEntry:
       
  3190 	case ECreateTextEntry:
       
  3191 	case ECreateMultipartAlternativeFolderEntry:
       
  3192 	case ECreateMultipartRelatedFolderEntry:
       
  3193 	case EPrepareToStoreHTMLEntryText:
       
  3194 	case EStoreHTMLEntryText:
       
  3195 		if (MultipartMixedCreated()) // iMixFolderId set when folder created
       
  3196 			iMsvEntry.Session().RemoveEntry(iMixFolderId);
       
  3197 		else if (MultipartRelatedCreated())
       
  3198 			iMsvEntry.Session().RemoveEntry(iRelFolderId);
       
  3199 		else if (MultipartAlternativeCreated())
       
  3200 			iMsvEntry.Session().RemoveEntry(iAltFolderId);
       
  3201 		else if (TextPartCreated())
       
  3202 			iMsvEntry.Session().RemoveEntry(iTextId);
       
  3203 		break;
       
  3204 	case EMoveOriginalMessageEntryChildrenToNewFolder:
       
  3205 	case ECopyOrigMessageToMessage:
       
  3206 	case EStoreAttachment:
       
  3207 	case EMoveTextToAlternativeFolder:
       
  3208 	case ECreateAttachmentEntry:
       
  3209 		{
       
  3210 		if (MultipartMixedCreated())
       
  3211 			iMsvEntry.Session().RemoveEntry(iMixFolderId);
       
  3212 		else if (MultipartRelatedCreated())
       
  3213 			iMsvEntry.Session().RemoveEntry(iRelFolderId);
       
  3214 		else if (MultipartAlternativeCreated())
       
  3215 			iMsvEntry.Session().RemoveEntry(iAltFolderId);
       
  3216 		else if (iAttachmentId != KMsvNullIndexEntryId)
       
  3217 			iMsvEntry.Session().RemoveEntry(iAttachmentId);
       
  3218 		}
       
  3219 		break;
       
  3220 	// for other states - original message not changed:
       
  3221 	case ECompleteStoreMessage: // message details may be incorrect but structure is ok to send
       
  3222 	case ECreateMultipartMixedFolderEntry:
       
  3223 	case ECheckForSubfolder:
       
  3224 	case EFindMultipartRelatedFolder:
       
  3225 	case EFinished:	// operation completed anyway
       
  3226 		break;
       
  3227 	default:
       
  3228 		// shouldn't get to this state
       
  3229 		__ASSERT_DEBUG(EFalse, gPanic(EImcmUnknownState));
       
  3230 		}
       
  3231 	}
       
  3232 
       
  3233 TBool CImStoreMessagePart::HTMLMessage() const
       
  3234 	{
       
  3235 	return iFlags & KStoreMessagePartHTMLMessage;
       
  3236 	}
       
  3237 
       
  3238 void CImStoreMessagePart::SetHTMLMessage(TBool aFlag)
       
  3239 	{
       
  3240 	iFlags = (iFlags & ~KStoreMessagePartHTMLMessage) | (aFlag ? KStoreMessagePartHTMLMessage : KStoreMessagePartClearFlag);
       
  3241 	}
       
  3242 
       
  3243 TBool CImStoreMessagePart::MultipartMixedExists() const
       
  3244 	{
       
  3245 	return iFlags & KStoreMessagePartMultipartMixedExists;
       
  3246 	}
       
  3247 
       
  3248 void CImStoreMessagePart::SetMultipartMixedExists(TBool aFlag)
       
  3249 	{
       
  3250 	iFlags = (iFlags & ~KStoreMessagePartMultipartMixedExists) | (aFlag ? KStoreMessagePartMultipartMixedExists : KStoreMessagePartClearFlag);
       
  3251 	}
       
  3252 
       
  3253 TBool CImStoreMessagePart::MultipartMixedCreated() const
       
  3254 	{
       
  3255 	return iFlags & KStoreMessagePartMultipartMixedCreated;
       
  3256 	}
       
  3257 
       
  3258 void CImStoreMessagePart::SetMultipartMixedCreated(TBool aFlag)
       
  3259 	{
       
  3260 	iFlags = (iFlags & ~KStoreMessagePartMultipartMixedCreated) | (aFlag ? KStoreMessagePartMultipartMixedCreated : KStoreMessagePartClearFlag);
       
  3261 	}
       
  3262 
       
  3263 TBool CImStoreMessagePart::MultipartAlternativeExists() const
       
  3264 	{
       
  3265 	return iFlags & KStoreMessagePartMultipartAlternativeExists;
       
  3266 	}
       
  3267 
       
  3268 void CImStoreMessagePart::SetMultipartAlternativeExists(TBool aFlag)
       
  3269 	{
       
  3270 	iFlags = (iFlags & ~KStoreMessagePartMultipartAlternativeExists) | (aFlag ? KStoreMessagePartMultipartAlternativeExists : KStoreMessagePartClearFlag);
       
  3271 	}
       
  3272 
       
  3273 TBool CImStoreMessagePart::MultipartAlternativeCreated() const
       
  3274 	{
       
  3275 	return iFlags & KStoreMessagePartMultipartAlternativeCreated;
       
  3276 	}
       
  3277 
       
  3278 void CImStoreMessagePart::SetMultipartAlternativeCreated(TBool aFlag)
       
  3279 	{
       
  3280 	iFlags = (iFlags & ~KStoreMessagePartMultipartAlternativeCreated) | (aFlag ? KStoreMessagePartMultipartAlternativeCreated : KStoreMessagePartClearFlag);
       
  3281 	}
       
  3282 
       
  3283 TBool CImStoreMessagePart::MultipartRelatedExists() const
       
  3284 	{
       
  3285 	return iFlags & KStoreMessagePartMultipartRelatedExists;
       
  3286 	}
       
  3287 
       
  3288 void CImStoreMessagePart::SetMultipartRelatedExists(TBool aFlag)
       
  3289 	{
       
  3290 	iFlags = (iFlags & ~KStoreMessagePartMultipartRelatedExists) | (aFlag ? KStoreMessagePartMultipartRelatedExists : KStoreMessagePartClearFlag);
       
  3291 	}
       
  3292 
       
  3293 TBool CImStoreMessagePart::MultipartRelatedCreated() const
       
  3294 	{
       
  3295 	return iFlags & KStoreMessagePartMultipartRelatedCreated;
       
  3296 	}
       
  3297 
       
  3298 void CImStoreMessagePart::SetMultipartRelatedCreated(TBool aFlag)
       
  3299 	{
       
  3300 	iFlags = (iFlags & ~KStoreMessagePartMultipartRelatedCreated) | (aFlag ? KStoreMessagePartMultipartRelatedCreated : KStoreMessagePartClearFlag);
       
  3301 	}
       
  3302 
       
  3303 TBool CImStoreMessagePart::TextPartExists() const
       
  3304 	{
       
  3305 	return iFlags & KStoreMessagePartTextPartExists;
       
  3306 	}
       
  3307 
       
  3308 void CImStoreMessagePart::SetTextPartExists(TBool aFlag)
       
  3309 	{
       
  3310 	iFlags = (iFlags & ~KStoreMessagePartTextPartExists) | (aFlag ? KStoreMessagePartTextPartExists : KStoreMessagePartClearFlag);
       
  3311 	}
       
  3312 
       
  3313 TBool CImStoreMessagePart::TextPartCreated() const
       
  3314 	{
       
  3315 	return iFlags & KStoreMessagePartTextPartCreated;
       
  3316 	}
       
  3317 
       
  3318 void CImStoreMessagePart::SetTextPartCreated(TBool aFlag)
       
  3319 	{
       
  3320 	iFlags = (iFlags & ~KStoreMessagePartTextPartCreated) | (aFlag ? KStoreMessagePartTextPartCreated : KStoreMessagePartClearFlag);
       
  3321 	}
       
  3322 
       
  3323 TBool CImStoreMessagePart::AttachmentEntryCreated() const
       
  3324 	{
       
  3325 	return iFlags & KStoreMessagePartAttachmentEntryCreated;
       
  3326 	}
       
  3327 
       
  3328 void CImStoreMessagePart::SetAttachmentEntryCreated(TBool aFlag)
       
  3329 	{
       
  3330 	iFlags = (iFlags & ~KStoreMessagePartAttachmentEntryCreated) | (aFlag ? KStoreMessagePartAttachmentEntryCreated : KStoreMessagePartClearFlag);
       
  3331 	}
       
  3332 
       
  3333 void CImStoreMessagePart::FindMultipartRelatedFolderL()
       
  3334 	{
       
  3335 	TMsvId serviceId = KMsvNullIndexEntryId;
       
  3336 	TMsvEmailEntry entry;
       
  3337 	iMsvEntry.Session().GetEntry(iRelatedPartId, serviceId, entry);
       
  3338 	iMsvEntry.SetEntryL(entry.Parent());
       
  3339 	entry = iMsvEntry.Entry();
       
  3340 	switch (entry.MessageFolderType())
       
  3341 		{
       
  3342 	case EFolderTypeRelated:
       
  3343 		iRelFolderId = entry.Id();
       
  3344 		SetMultipartRelatedExists(ETrue);
       
  3345 		break;
       
  3346 	case EFolderTypeAlternative:
       
  3347 		iAltFolderId = entry.Id();
       
  3348 		iMsvEntry.Session().GetEntry(iAltFolderId, serviceId, entry);
       
  3349 		iMsvEntry.SetEntryL(entry.Parent());
       
  3350 		entry = iMsvEntry.Entry();
       
  3351 		if (entry.MessageFolderType() == EFolderTypeRelated)
       
  3352 			{
       
  3353 			iRelFolderId = entry.Id();
       
  3354 			SetMultipartRelatedExists(ETrue);
       
  3355 			}
       
  3356 		break;
       
  3357 	default:
       
  3358 		User::Leave(KErrNotSupported);
       
  3359 		}
       
  3360 	RequestComplete(KErrNone);
       
  3361 	}
       
  3362 
       
  3363 void CImStoreMessagePart::CheckForSubfolderL()
       
  3364 	{
       
  3365 	/* 
       
  3366 	//	Check whether the message entry has a multipart mixed folder under it.
       
  3367 	*/
       
  3368 	iMsvEntry.SetEntryL(iMessageId);
       
  3369 	TMsvEmailEntry emailEntry = iMsvEntry.Entry();
       
  3370 	SetHTMLMessage(emailEntry.MHTMLEmail());
       
  3371 	if (HTMLMessage())
       
  3372 		{
       
  3373 		TRAPD(err,iHtmlConverter=CImHtmlConverter::NewL(iMsvEntry, *iParaLayer, *iCharLayer));
       
  3374  		if (err)
       
  3375 			{
       
  3376 			if (err == KErrNoMemory)
       
  3377 				User::Leave(KErrNoMemory);
       
  3378 			else
       
  3379 				gPanic(EImcmHtmlConverterNotFound);
       
  3380 			}
       
  3381 
       
  3382 		// Need to check if the Html converter has been created as we only open the resource file
       
  3383 		// to get the default html attachment name.
       
  3384 		if (iHtmlConverter)
       
  3385 			OpenAndReadResourceFileL();
       
  3386 		}
       
  3387 
       
  3388 	iMessageEntrySelection = iMsvEntry.ChildrenL();
       
  3389 	CMsvEntrySelection* entrySelection = iMsvEntry.ChildrenWithTypeL(KUidMsvFolderEntry);
       
  3390 	CleanupStack::PushL(entrySelection);
       
  3391 
       
  3392 	if (entrySelection->Count())
       
  3393 		{
       
  3394 		__ASSERT_DEBUG(entrySelection->Count() == 1, gPanic(EImcmMessageEntryHasMoreThanOneFolder));
       
  3395 		emailEntry = iMsvEntry.ChildDataL((*entrySelection)[0]);
       
  3396 		if (emailEntry.MessageFolderType() == EFolderTypeMixed)
       
  3397 			{
       
  3398 			iMixFolderId = (*entrySelection)[0];
       
  3399 			SetMultipartMixedExists(ETrue);
       
  3400 			}
       
  3401 		else if (emailEntry.MessageFolderType() == EFolderTypeRelated)
       
  3402 			{
       
  3403 			iRelFolderId = (*entrySelection)[0];
       
  3404 			SetMultipartRelatedExists(ETrue);
       
  3405 			}
       
  3406 		else if (emailEntry.MessageFolderType() == EFolderTypeAlternative)
       
  3407 			{
       
  3408 			iAltFolderId = (*entrySelection)[0];
       
  3409 			SetMultipartAlternativeExists(ETrue);
       
  3410 			}
       
  3411 		}
       
  3412 
       
  3413 	CleanupStack::PopAndDestroy(); // entrySelection
       
  3414 	
       
  3415 	iEmailMessage->GetBodyTextEntryIdL(iMessageId, CImEmailMessage::EThisMessageOnly);	
       
  3416 	TBool isPlainText = EFalse;
       
  3417 	if(iEmailMessage->Selection().Count())
       
  3418 		{
       
  3419 		TMsvId textId = iEmailMessage->Selection().At(0);	
       
  3420 		iMsvEntry.SetEntryL(textId);// pointing to the text entry
       
  3421 			
       
  3422 		if(iMsvEntry.HasStoreL())
       
  3423 			{
       
  3424 			CMsvStore* bodyTextStore = iMsvEntry.ReadStoreL();
       
  3425 			CleanupStack::PushL(bodyTextStore);
       
  3426 			
       
  3427 			// Check if the original message was stored as plain text.
       
  3428 			if(iUsePlainTextStorage)
       
  3429 				{
       
  3430 				isPlainText = (bodyTextStore->IsPresentL(KMsvPlainBodyText16) || bodyTextStore->IsPresentL(KMsvPlainBodyText8));
       
  3431 				}			
       
  3432 			
       
  3433 			// This is not a richtext message.	
       
  3434 			if(isPlainText)
       
  3435 				{
       
  3436 				CMsvPlainBodyText* textOrig = bodyTextStore->InitialisePlainBodyTextForReadL(KMaxChunkLength);	
       
  3437 				iSizeFwdReplyBody = textOrig->Size();
       
  3438 				
       
  3439 				delete textOrig;
       
  3440 
       
  3441 				// Need to release body text store before changing to a new entry
       
  3442 				CleanupStack::PopAndDestroy(bodyTextStore);
       
  3443 
       
  3444 				iMsvEntry.SetEntryL(iMessageId);
       
  3445 
       
  3446 				TRequestStatus* myStatus=&iStatus;
       
  3447 				iStatus=KRequestPending;
       
  3448 				User::RequestComplete(myStatus,KErrNone);	
       
  3449 				}
       
  3450 			else
       
  3451 				{
       
  3452 				CleanupStack::PopAndDestroy(bodyTextStore);
       
  3453 				iMsvEntry.SetEntryL(iMessageId);
       
  3454 				iEmailMessage->GetBodyTextL(iStatus, iMessageId, CImEmailMessage::EThisMessageOnly, *iRichText, *iParaLayer, *iCharLayer);	
       
  3455 				}
       
  3456 			}
       
  3457 		else
       
  3458 			{
       
  3459 			iMsvEntry.SetEntryL(iMessageId);
       
  3460 			iEmailMessage->GetBodyTextL(iStatus, iMessageId, CImEmailMessage::EThisMessageOnly, *iRichText, *iParaLayer, *iCharLayer);	
       
  3461 			}
       
  3462 		}
       
  3463 	else
       
  3464 		{
       
  3465 		iMsvEntry.SetEntryL(iMessageId);
       
  3466 		iEmailMessage->GetBodyTextL(iStatus, iMessageId, CImEmailMessage::EThisMessageOnly, *iRichText, *iParaLayer, *iCharLayer);	
       
  3467 		}	
       
  3468 	}
       
  3469 
       
  3470 void CImStoreMessagePart::CreateMultipartMixedFolderEntryL()
       
  3471 	{
       
  3472 	iMsvEntry.SetEntryL(iMessageId);
       
  3473 
       
  3474 	TMsvEmailEntry entry;
       
  3475 	entry.iType = KUidMsvFolderEntry;
       
  3476 	entry.iMtm = iMsvEntry.Entry().iMtm;
       
  3477 	entry.iServiceId = iMsvEntry.Entry().iServiceId;
       
  3478 	entry.SetMessageFolderType(EFolderTypeMixed);
       
  3479 	entry.iSize = 0;
       
  3480 
       
  3481 	delete iMsvOperation;
       
  3482 	iMsvOperation=NULL;
       
  3483 	iMsvOperation=iMsvEntry.CreateL(entry, iStatus);
       
  3484 	}
       
  3485 
       
  3486 void CImStoreMessagePart::CreateMultipartRelatedFolderEntryL()
       
  3487 	{
       
  3488 	TMsvEmailEntry entry;
       
  3489 	entry.iType = KUidMsvFolderEntry;
       
  3490 	entry.iMtm = iMsvEntry.Entry().iMtm;
       
  3491 	entry.iServiceId = iMsvEntry.Entry().iServiceId;
       
  3492 	entry.SetMessageFolderType(EFolderTypeRelated);
       
  3493 	entry.iSize = 0;
       
  3494 
       
  3495 	delete iMsvOperation;
       
  3496 	iMsvOperation=NULL;
       
  3497 	iMsvOperation=iMsvEntry.CreateL(entry, iStatus);
       
  3498 	}
       
  3499 
       
  3500 void CImStoreMessagePart::CreateAttachmentEntryL()
       
  3501 	{
       
  3502 	// create the index entry
       
  3503 	TMsvEntry entry;
       
  3504 	entry.iMtm = iMsvEntry.Entry().iMtm;
       
  3505 	entry.iServiceId = iMsvEntry.Entry().iServiceId;
       
  3506 	entry.iType = KUidMsvAttachmentEntry;
       
  3507 	entry.iDate.UniversalTime();
       
  3508 	entry.SetAttachment(ETrue);
       
  3509 	entry.SetInPreparation(ETrue);
       
  3510 	TParse parse;
       
  3511 	if(!iIsAddByFileHandle)
       
  3512 		{
       
  3513 	//if the attachment path is set then set details, otherwise just create the entry.
       
  3514 	if (iAttachmentFullName->Length())
       
  3515 		{
       
  3516 		parse.Set(iAttachmentFullName->Des(), NULL, NULL);
       
  3517 		entry.iDetails.Set(parse.NameAndExt());
       
  3518 
       
  3519 		// Set the size of the attachment
       
  3520 		TEntry attEntry;
       
  3521 		iMsvEntry.Session().FileSession().Entry(iAttachmentFullName->Des(), attEntry);
       
  3522 		iAttachmentSize = attEntry.iSize;
       
  3523 		entry.iSize = iAttachmentSize;
       
  3524 		}
       
  3525 		}
       
  3526 	else if(iIsAddByFileHandle)
       
  3527 		{
       
  3528 		SetEntryDetailsL(entry);
       
  3529 		}
       
  3530 	delete iMsvOperation;
       
  3531 	iMsvOperation = NULL;
       
  3532 	iMsvOperation = iMsvEntry.CreateL(entry, iStatus);
       
  3533 	}
       
  3534 	
       
  3535 void CImStoreMessagePart::DoAttachmentStoreL()
       
  3536 	{
       
  3537 	if(iRelatedPartId)
       
  3538 		{
       
  3539 		delete iAttachmentInfo;
       
  3540 		iAttachmentInfo=NULL;
       
  3541 		iAttachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
  3542 		iAttachmentCreateState = EAddAttachment;	
       
  3543 		}
       
  3544 	switch(iAttachmentCreateState)	
       
  3545 		{
       
  3546 	case ECreateAttachment:
       
  3547 		{
       
  3548 		CreateAttachmentL();
       
  3549 		}
       
  3550 		break;
       
  3551 	case EAddAttachment:
       
  3552 		{
       
  3553 		AddAttachmentL();	
       
  3554 		}
       
  3555 	break;	
       
  3556 	case EAddAttachmentUsingFileHandle:
       
  3557 		{
       
  3558 		AddAttachmentUsingFileHandleL();
       
  3559 		}
       
  3560 	break;	
       
  3561 	case  EAddLinkedAttachment:
       
  3562 		{
       
  3563 		AddLinkedAttachmentL();	
       
  3564 		}
       
  3565 	break;
       
  3566 	case EAddEntryAsAttachment:
       
  3567 		{
       
  3568 		AddEntryAsAttachmentL();
       
  3569 		}
       
  3570 	break;	
       
  3571 	default:
       
  3572 	__ASSERT_DEBUG(EFalse, User::Invariant());
       
  3573 	break;
       
  3574 		}
       
  3575 	}
       
  3576 	
       
  3577 void CImStoreMessagePart::CreateAttachmentL()
       
  3578 	{
       
  3579 	
       
  3580 	iStore = iMsvEntry.EditStoreL();
       
  3581 	
       
  3582 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  3583 	attachmentMgr.CreateAttachmentL(iAttachmentFullName->Des(),(*iFileHandle),iAttachmentInfo,iStatus);
       
  3584 	iAttachmentInfo=NULL; 
       
  3585 	}
       
  3586 	
       
  3587 void CImStoreMessagePart::AddAttachmentL()
       
  3588 	{
       
  3589 	iStore = iMsvEntry.EditStoreL();
       
  3590 	
       
  3591 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  3592 	attachmentMgr.AddAttachmentL(iAttachmentFullName->Des(),iAttachmentInfo,iStatus); 
       
  3593 	iAttachmentInfo=NULL; 
       
  3594 	}
       
  3595 void CImStoreMessagePart::AddAttachmentUsingFileHandleL()	
       
  3596 	{
       
  3597 
       
  3598 	iStore = iMsvEntry.EditStoreL();
       
  3599 	
       
  3600 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  3601 	attachmentMgr.AddAttachmentL((*iFileHandle),iAttachmentInfo,iStatus);
       
  3602 	iAttachmentInfo=NULL; 
       
  3603 	}
       
  3604 	
       
  3605 void CImStoreMessagePart::AddLinkedAttachmentL()	
       
  3606 	{
       
  3607 
       
  3608 	iStore = iMsvEntry.EditStoreL();
       
  3609 	
       
  3610 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  3611 	attachmentMgr.AddLinkedAttachmentL(iAttachmentFullName->Des(),iAttachmentInfo,iStatus);
       
  3612 	iAttachmentInfo=NULL; 
       
  3613 	}
       
  3614 	
       
  3615 void CImStoreMessagePart::AddEntryAsAttachmentL()	
       
  3616 	{
       
  3617 
       
  3618 	iMsvEntry.SetEntryL(iAttachmentId);
       
  3619 	iStore = iMsvEntry.EditStoreL();
       
  3620 	
       
  3621 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  3622 	attachmentMgr.AddEntryAsAttachmentL(iAttachmentMessageId,iAttachmentInfo,iStatus);
       
  3623 	iAttachmentInfo=NULL; 
       
  3624 	}
       
  3625 
       
  3626 TInt CImStoreMessagePart::CheckMimeInAttachmentInfoL(CMsvMimeHeaders& aMsvMimeHeaders)
       
  3627 	{
       
  3628 	if(!iMsvEntry.HasStoreL())
       
  3629 		return KErrNotFound;
       
  3630 	
       
  3631 	CMsvStore* store  = iMsvEntry.ReadStoreL();
       
  3632 	CleanupStack::PushL(store);
       
  3633 	// get the attachment info
       
  3634 	MMsvAttachmentManager& attachmentMgr = 	store->AttachmentManagerL();
       
  3635 	TInt mimefound = KErrNotFound;
       
  3636 	if(attachmentMgr.AttachmentCount())
       
  3637 		{
       
  3638 		// one attachment per attachment entry in email
       
  3639 		CMsvAttachment* attachmentInfo = attachmentMgr.GetAttachmentInfoL(0);
       
  3640 		CleanupStack::PushL(attachmentInfo);
       
  3641 		TPtrC8 bufferPtr;
       
  3642 		// check if attachment info had mimeheaders
       
  3643 			mimefound =  attachmentInfo->GetDesC8Attribute(KUidMimeHeaders, bufferPtr);
       
  3644 		
       
  3645 		// mimeheaders found
       
  3646 		if(mimefound == KErrNone)
       
  3647 			aMsvMimeHeaders.RestoreL(*attachmentInfo);
       
  3648 	
       
  3649 		CleanupStack::PopAndDestroy(attachmentInfo);	
       
  3650 		}
       
  3651 	CleanupStack::PopAndDestroy(store); 
       
  3652 	return mimefound;		
       
  3653 	}
       
  3654 	
       
  3655 CImMimeHeader* CImStoreMessagePart::ProcessAttachmentMimeHeadersL()
       
  3656 	{
       
  3657 	CImMimeHeader* mimeHeader = NULL;
       
  3658 	CMsvMimeHeaders* msvMimeHeaders = CMsvMimeHeaders::NewLC();
       
  3659 	TInt err = CheckMimeInAttachmentInfoL(*msvMimeHeaders);
       
  3660 	if(err == KErrNone)
       
  3661 		{
       
  3662 		// convert the CMsvMimeHeaders in attactment info to CImMimeHeader
       
  3663 		mimeHeader = iEmailMessage->ConvertToImMimeHeadersL(msvMimeHeaders);
       
  3664 		CleanupStack::PushL(mimeHeader);
       
  3665 
       
  3666 		CMsvStore* store = iMsvEntry.EditStoreL();
       
  3667 		CleanupStack::PushL(store);
       
  3668 		mimeHeader->StoreL(*store);
       
  3669 		store->CommitL();				
       
  3670 		CleanupStack::PopAndDestroy(store);
       
  3671 		
       
  3672 		CleanupStack::Pop(mimeHeader);//mimeHeader
       
  3673 		}
       
  3674 	CleanupStack::PopAndDestroy(msvMimeHeaders);
       
  3675 	return mimeHeader;	
       
  3676 	}	
       
  3677 
       
  3678 void CImStoreMessagePart::SetEntryDetailsL(TMsvEntry& aEntry)	
       
  3679 	{
       
  3680 	if(iAttachmentFullName)
       
  3681 		{
       
  3682 		// for create attachment name is set by user
       
  3683 		aEntry.iDetails.Set(iAttachmentFullName->Des());
       
  3684 		}
       
  3685 	else
       
  3686 		{
       
  3687 		// adding the attachment using file handle. , get the name from handle
       
  3688 		TFileName fileName;
       
  3689 		User::LeaveIfError(iFileHandle->Name(fileName));
       
  3690 		aEntry.iDetails.Set(fileName);
       
  3691 		}
       
  3692 	// get the size of the file from the handle	if add by file handle
       
  3693 	if(iAttachmentCreateState != ECreateAttachment)
       
  3694 		{
       
  3695 		iFileHandle->Size(iAttachmentSize);
       
  3696 		aEntry.iSize = iAttachmentSize;		
       
  3697 		}
       
  3698 	}		
       
  3699 
       
  3700 
       
  3701 void CImStoreMessagePart::CopyOrigMessageToMessageL()
       
  3702 	{
       
  3703 	TMsvId serviceId;
       
  3704 	TMsvEmailEntry entry;
       
  3705 	iMsvEntry.Session().GetEntry(iAttachmentMessageId, serviceId, entry);
       
  3706 	iMsvEntry.SetEntryL(entry.Parent());
       
  3707 
       
  3708 	delete iMsvOperation;
       
  3709 	iMsvOperation = NULL;
       
  3710 	
       
  3711 	if (MultipartMixedCreated() || MultipartMixedExists())
       
  3712 		iMsvOperation = iMsvEntry.CopyL(iAttachmentMessageId, iMixFolderId, iStatus);
       
  3713 	else 
       
  3714 		iMsvOperation = iMsvEntry.CopyL(iAttachmentMessageId, iMessageId, iStatus);
       
  3715 	}
       
  3716 
       
  3717 void CImStoreMessagePart::CreateMultipartAlternativeFolderEntryL()
       
  3718 	{
       
  3719 	TMsvEmailEntry entry;
       
  3720 	entry.iType = KUidMsvFolderEntry;
       
  3721 	entry.iMtm = iMsvEntry.Entry().iMtm;
       
  3722 	entry.iServiceId = iMsvEntry.Entry().iServiceId;
       
  3723 	entry.SetMessageFolderType(EFolderTypeAlternative);
       
  3724 	entry.iSize = 0;
       
  3725 
       
  3726 	delete iMsvOperation;
       
  3727 	iMsvOperation=NULL;
       
  3728 	iMsvOperation=iMsvEntry.CreateL(entry, iStatus);
       
  3729 	}
       
  3730 
       
  3731 void CImStoreMessagePart::CreateTextEntryL()
       
  3732 	{
       
  3733 	// create the index entry
       
  3734 	TMsvEntry entry;
       
  3735 	entry.iMtm = iMsvEntry.Entry().iMtm;
       
  3736 	entry.iServiceId = iMsvEntry.Entry().iServiceId;
       
  3737 	entry.iType = KUidMsvEmailTextEntry;
       
  3738 	entry.iDate.UniversalTime();
       
  3739 	entry.iSize = 0;
       
  3740 
       
  3741 	delete iMsvOperation;
       
  3742 	iMsvOperation = NULL;
       
  3743 	iMsvOperation = iMsvEntry.CreateL(entry, iStatus);
       
  3744 	}
       
  3745 
       
  3746 void CImStoreMessagePart::StoreRichTextL()
       
  3747 	{
       
  3748 	if(iUsePlainTextStorage)
       
  3749 		{
       
  3750 		StorePlainTextL();
       
  3751 		return;
       
  3752 		}
       
  3753 	
       
  3754 	iMsvEntry.SetEntryL(iTextId);	//pointing to the text entry
       
  3755 	CMsvStore* store = iMsvEntry.EditStoreL();
       
  3756 	CleanupStack::PushL(store);
       
  3757 	
       
  3758 	store->StoreBodyTextL(*iRichTextToStore);
       
  3759 	store->CommitL();
       
  3760 	
       
  3761 	// Store Mime header if we've got one
       
  3762 	if ( iMimeHeaderOfBodyText )
       
  3763 		{
       
  3764 		iMimeHeaderOfBodyText->StoreL(*store);
       
  3765 		store->CommitL();
       
  3766 		iMimeHeaderOfBodyText = NULL;	// We never really took ownership of the object
       
  3767 		}
       
  3768 	
       
  3769 	CleanupStack::PopAndDestroy(store);
       
  3770 
       
  3771 	// update size of text entry
       
  3772 	TMsvEmailEntry entry(iMsvEntry.Entry());
       
  3773 	// DocumentLength() gives no. of chars and since unicode we multiply by 2
       
  3774 	entry.iSize = (iRichTextToStore->DocumentLength() * 2); 
       
  3775 	
       
  3776 	entry.iDate.UniversalTime();
       
  3777 	
       
  3778 	delete iMsvOperation;
       
  3779 	iMsvOperation = NULL;
       
  3780 	iMsvOperation = iMsvEntry.ChangeL(entry, iStatus);	
       
  3781 	}
       
  3782 
       
  3783 
       
  3784 void CImStoreMessagePart::StorePlainTextL()
       
  3785 	{
       
  3786 	TUint charset = 0;
       
  3787 	TBool override = EFalse;
       
  3788 
       
  3789 	iEmailMessage->GetCharacterSetL(iMessageId,charset,override);
       
  3790 	iMsvEntry.SetEntryL(iTextId);	//pointing to the text entry
       
  3791 	CMsvStore* store = iMsvEntry.EditStoreL();
       
  3792 	CleanupStack::PushL(store);
       
  3793 	
       
  3794 	iSizeOfBody = 0;
       
  3795 	// If this method was called as a result of a call to CImEmailMessage::StoreBodyTextL
       
  3796 	if(iRichTextToStore)
       
  3797 		{
       
  3798 		RFs& fileSvrSession = iMsvSession.FileSession();
       
  3799 		
       
  3800 		CCnvCharacterSetConverter* characterConverter = CCnvCharacterSetConverter::NewL();
       
  3801 		CleanupStack::PushL(characterConverter);
       
  3802 		
       
  3803 		CImConvertCharconv* charConv = CImConvertCharconv::NewL(*characterConverter, fileSvrSession);
       
  3804 		CleanupStack::PushL(charConv);
       
  3805 		
       
  3806 		TUint defaultCharset =	charConv->SystemDefaultCharset();
       
  3807 	
       
  3808 		CleanupStack::PopAndDestroy(2,characterConverter);
       
  3809 		characterConverter = NULL;
       
  3810 		charConv = NULL;
       
  3811 		
       
  3812 		// Body text is stored in MailStore as 16 bit so set iIs8Bit to EFalse.		
       
  3813 		CMsvPlainBodyText* text = store->InitialisePlainBodyTextForWriteL(EFalse,charset,defaultCharset);	
       
  3814 		CleanupStack::PushL(text);
       
  3815 		
       
  3816 		text->StoreRichTextAsPlainTextL(*iRichTextToStore);
       
  3817 		text->CommitL();
       
  3818 		
       
  3819 		CleanupStack::PopAndDestroy(text);	
       
  3820 		}
       
  3821 	else // If this method was called as a result to a call to CImPlainBodyText::CommitL
       
  3822 		{
       
  3823 		// Delete the store since for Read operation we need to open in Read mode.
       
  3824 		CleanupStack::PopAndDestroy(store);
       
  3825 		store = NULL;
       
  3826 		
       
  3827 		store = iMsvEntry.ReadStoreL();
       
  3828 		CleanupStack::PushL(store);	
       
  3829 		// The plain bodytext storeoperation is completed when CImPlainBodyText::CommitL is called
       
  3830 		// Find out the length of the body text here.
       
  3831 		CMsvPlainBodyText* bodyText = store->InitialisePlainBodyTextForReadL(KMaxChunkLength);	
       
  3832 		iSizeOfBody = bodyText->Size();
       
  3833 		delete bodyText;
       
  3834 			
       
  3835 		CleanupStack::PopAndDestroy(store);
       
  3836 		store = NULL;
       
  3837 		// Open it in Edit mode so that store CommitL do not fail.
       
  3838 		store = iMsvEntry.EditStoreL();
       
  3839 		CleanupStack::PushL(store);	
       
  3840 		}
       
  3841 	
       
  3842 	// Store Mime header if we've got one
       
  3843 	if ( iMimeHeaderOfBodyText )
       
  3844 		{
       
  3845 		iMimeHeaderOfBodyText->StoreL(*store);
       
  3846 		store->CommitL();
       
  3847 		iMimeHeaderOfBodyText = NULL;	// We never really took ownership of the object
       
  3848 		}
       
  3849 	
       
  3850 	CleanupStack::PopAndDestroy(store);
       
  3851 
       
  3852 	// update size of text entry
       
  3853 	TMsvEmailEntry entry(iMsvEntry.Entry());
       
  3854 	
       
  3855 	// DocumentLength() gives no. of chars and since unicode we multiply by 2
       
  3856 	if(iRichTextToStore)
       
  3857 		{
       
  3858 		entry.iSize = (iRichTextToStore->DocumentLength() * 2); 
       
  3859 		iSizeOfBody = entry.iSize;
       
  3860 		}
       
  3861 	else
       
  3862 		{
       
  3863 		entry.iSize = iSizeOfBody;	
       
  3864 		}
       
  3865 		
       
  3866 	entry.iDate.UniversalTime();
       
  3867 	
       
  3868 	delete iMsvOperation;
       
  3869 	iMsvOperation = NULL;
       
  3870 	iMsvOperation = iMsvEntry.ChangeL(entry, iStatus);	
       
  3871 	}
       
  3872 	
       
  3873 	
       
  3874 void CImStoreMessagePart::CreateHTMLEntryL()
       
  3875 	{
       
  3876 	iMsvEntry.SetEntryL(iAltFolderId);
       
  3877 
       
  3878 	TMsvEntry entry;
       
  3879 	entry.iServiceId = iMsvEntry.Entry().iServiceId;
       
  3880 	entry.iType = KUidMsvEmailHtmlEntry;
       
  3881 	entry.iMtm = iMsvEntry.Entry().iMtm;
       
  3882 	entry.iDate.UniversalTime();
       
  3883 	entry.iSize = 0;
       
  3884 	
       
  3885 	delete iMsvOperation;
       
  3886 	iMsvOperation = NULL;
       
  3887 	iMsvOperation = iMsvEntry.CreateL(entry, iStatus);
       
  3888 	}
       
  3889 
       
  3890 void CImStoreMessagePart::RemoveHTMLEntryL()
       
  3891 	{
       
  3892 	// Find the id for the HTML Entry - current entry is the text entry. Set 
       
  3893 	// entry to the parent and verify that this is an EFolderTypeAlternative.
       
  3894 	// Then search its children for an HTML entry.
       
  3895 	iHtmlId = KMsvNullIndexEntryId;
       
  3896 	iMsvEntry.SetEntryL(iMsvEntry.Entry().Parent());
       
  3897 
       
  3898 	if( ((TMsvEmailEntry) iMsvEntry.Entry()).MessageFolderType() != EFolderTypeAlternative )
       
  3899 		{
       
  3900 		// Self-complete to continue with state machine.
       
  3901 		RequestComplete(KErrNone);
       
  3902 		return;
       
  3903 		}
       
  3904 
       
  3905 	TInt ii = iMsvEntry.Count();
       
  3906 	while( ii-- )
       
  3907 		{
       
  3908 		if( iMsvEntry[ii].iType == KUidMsvEmailHtmlEntry )
       
  3909 			{
       
  3910 			iHtmlId = iMsvEntry[ii].Id();
       
  3911 			break;
       
  3912 			}
       
  3913 		}
       
  3914 
       
  3915 	if( iHtmlId == KMsvNullIndexEntryId )
       
  3916 		{
       
  3917 		// There is no HTML entry - self-complete to continue with state machine.
       
  3918 		RequestComplete(KErrNone);
       
  3919 		return;
       
  3920 		}
       
  3921 
       
  3922 	// Delete the HTML entry asynchronously.
       
  3923 	delete iMsvOperation;
       
  3924 	iMsvOperation = NULL;
       
  3925 	iMsvOperation = iMsvEntry.DeleteL(iHtmlId, iStatus);
       
  3926 	}
       
  3927 
       
  3928 void CImStoreMessagePart::MoveTextEntryToAltFolderL()
       
  3929 	{
       
  3930 	// moves the text entry to alternativelder entry
       
  3931 	TMsvId serviceId = KMsvNullIndexEntryId;
       
  3932 	TMsvEmailEntry entry;
       
  3933 	iMsvEntry.Session().GetEntry(iTextId, serviceId, entry);
       
  3934 	iMsvEntry.SetEntryL(entry.Parent());
       
  3935 	
       
  3936 	delete iMsvOperation;
       
  3937 	iMsvOperation = NULL;
       
  3938 	iMsvOperation = iMsvEntry.MoveL(iTextId, iAltFolderId, iStatus);
       
  3939 	}
       
  3940 
       
  3941 void CImStoreMessagePart::MoveOriginalMessageEntryChildrenToNewFolderL()
       
  3942 	{
       
  3943 	if (MultipartRelatedCreated())
       
  3944 		{
       
  3945 		// set entry to the multipart/related folders parent and copy the multipart alternative
       
  3946 		// into the multipart/related.
       
  3947 		TMsvId serviceId = KMsvNullIndexEntryId;
       
  3948 		TMsvEmailEntry entry;
       
  3949 		iMsvEntry.Session().GetEntry(iRelFolderId, serviceId, entry);
       
  3950 		iMsvEntry.SetEntryL(entry.Parent());
       
  3951 		delete iMsvOperation;
       
  3952 		iMsvOperation = NULL;
       
  3953 		iMsvOperation = iMsvEntry.MoveL(iAltFolderId, iRelFolderId, iStatus);
       
  3954 		}
       
  3955 	else //if MultipartMixedCreated()
       
  3956 		{
       
  3957 		iMsvEntry.SetEntryL(iMessageId);
       
  3958 		delete iMsvOperation;
       
  3959 		iMsvOperation = NULL;
       
  3960 		iMsvOperation = iMsvEntry.MoveL(*iMessageEntrySelection, iMixFolderId, iStatus);
       
  3961 		}
       
  3962 	}
       
  3963 
       
  3964 void CImStoreMessagePart::CompleteStoreMessagePartL()
       
  3965 	{
       
  3966 	if (iMsvEntry.Entry().iType != KUidMsvMessageEntry)
       
  3967 		iMsvEntry.SetEntryL(iMessageId);	//pointing to the message
       
  3968 	
       
  3969 	TMsvEmailEntry entry(iMsvEntry.Entry());
       
  3970 
       
  3971 	if (iMessagePart == EMessagePartAttachment)
       
  3972 		{
       
  3973 		entry.iSize += iAttachmentSize;
       
  3974 		entry.SetAttachment(ETrue);
       
  3975 		}
       
  3976 	else if (iMessagePart == EMessagePartMessageAttachment)
       
  3977 		{
       
  3978 		TMsvId serviceId;
       
  3979 		TMsvEmailEntry attachmentMessageEntry;
       
  3980 		iMsvEntry.Session().GetEntry(iAttachmentMessageId, serviceId, attachmentMessageEntry);
       
  3981 		entry.SetAttachment(ETrue);
       
  3982 		entry.iSize += attachmentMessageEntry.iSize;
       
  3983 		}
       
  3984 	else if (iMessagePart == EMessagePartBody)
       
  3985 		{
       
  3986 		if(iUsePlainTextStorage)
       
  3987 			{
       
  3988 			entry.iSize -= iSizeFwdReplyBody; // first subtract length of original plain text.
       
  3989 			entry.iSize += iSizeOfBody;
       
  3990 			}
       
  3991 		else
       
  3992 			{
       
  3993 			// DocumentLength() gives no. of chars and since unicode we multiply by 2
       
  3994 			entry.iSize -= (iRichText->DocumentLength() * 2); // first subtract length of original RichText
       
  3995 			entry.iSize += (iRichTextToStore->DocumentLength() * 2);
       
  3996 			}
       
  3997 		
       
  3998 		
       
  3999 		}
       
  4000 	if (iHtmlConverter)
       
  4001 		entry.iSize+=iHtmlConverter->Size();
       
  4002 
       
  4003 	entry.iDate.UniversalTime();
       
  4004 
       
  4005 	StoreMimeHeaderL();
       
  4006 
       
  4007 	delete iMsvOperation;
       
  4008 	iMsvOperation = NULL;
       
  4009 	entry.SetInPreparation(EFalse);
       
  4010 	iMsvOperation = iMsvEntry.ChangeL(entry, iStatus);
       
  4011 	}
       
  4012 
       
  4013 void CImStoreMessagePart::StoreMimeHeaderL()
       
  4014 	{
       
  4015 	CImMimeHeader* mimeHeader = NULL;
       
  4016 	
       
  4017 	if (MultipartMixedCreated() || MultipartAlternativeCreated() || MultipartRelatedCreated())
       
  4018 		{
       
  4019 		CMsvStore* store = iMsvEntry.EditStoreL();
       
  4020 		CleanupStack::PushL(store);
       
  4021 
       
  4022 		mimeHeader = CImMimeHeader::NewLC();
       
  4023 		CreateFolderMimeHeaderL(*mimeHeader);
       
  4024 		mimeHeader->StoreL(*store);
       
  4025 		store->CommitL();		
       
  4026 		CleanupStack::PopAndDestroy(2); //mimeHeader, store
       
  4027 		}
       
  4028 	
       
  4029 	if (iMessagePart==EMessagePartAttachment && iAttachmentId)
       
  4030 		{
       
  4031 		TMsvId oldId = iMsvEntry.Entry().Id();
       
  4032 		iMsvEntry.SetEntryL(iAttachmentId);
       
  4033 		mimeHeader = NULL;
       
  4034 		mimeHeader = ProcessAttachmentMimeHeadersL();
       
  4035 		// mimeheader not found in attachment info, hence create mime header
       
  4036 		if (mimeHeader == NULL)
       
  4037 			{
       
  4038 			mimeHeader = CImMimeHeader::NewLC();
       
  4039 			if (CreateAttachmentMimeHeaderL(*mimeHeader, iMsvEntry.Entry().iDetails))
       
  4040 				{
       
  4041 				CMsvStore* store = iMsvEntry.EditStoreL();
       
  4042 				CleanupStack::PushL(store);
       
  4043 				mimeHeader->StoreL(*store);
       
  4044 				store->CommitL();			
       
  4045 				CleanupStack::PopAndDestroy(store);
       
  4046 				}
       
  4047 			CleanupStack::PopAndDestroy(mimeHeader);
       
  4048 			}
       
  4049 		else
       
  4050 			{
       
  4051 			delete mimeHeader;
       
  4052 			}
       
  4053 		iMsvEntry.SetEntryL(oldId); // Reset
       
  4054 		}
       
  4055 	else if (iMessagePart==EMessagePartMessageAttachment && iAttachmentMessageId)
       
  4056 		{
       
  4057 		CMsvStore* store = iMsvEntry.EditStoreL();
       
  4058 		CleanupStack::PushL(store);
       
  4059 		mimeHeader = CImMimeHeader::NewLC();
       
  4060 	
       
  4061 		CreateMessageMimeHeaderL(*mimeHeader);
       
  4062 		mimeHeader->StoreL(*store);
       
  4063 		store->CommitL();
       
  4064 		CleanupStack::PopAndDestroy(2); //mimeHeader, store
       
  4065 		}
       
  4066 	}
       
  4067 
       
  4068 void CImStoreMessagePart::CreateFolderMimeHeaderL(CImMimeHeader& aMimeHeader)
       
  4069 	{
       
  4070 	aMimeHeader.SetContentTypeL(KMimeMultipart);
       
  4071 	if (MultipartMixedCreated())
       
  4072 		aMimeHeader.SetContentSubTypeL(KMimeMixed);
       
  4073 	else if (MultipartRelatedCreated())
       
  4074 		aMimeHeader.SetContentSubTypeL(KMimeRelated);
       
  4075 	else
       
  4076 		aMimeHeader.SetContentSubTypeL(KMimeAlternative);
       
  4077 	aMimeHeader.SetContentTransferEncodingL(KMimeQuotedPrintable);
       
  4078 	}
       
  4079 	
       
  4080 void CImStoreMessagePart::CreateMessageMimeHeaderL(CImMimeHeader& aMimeHeader)
       
  4081 	{
       
  4082 	aMimeHeader.SetContentTypeL(KMimeMessage);
       
  4083 	aMimeHeader.SetContentSubTypeL(KMimeRfc822);
       
  4084 	}
       
  4085 
       
  4086 TBool CImStoreMessagePart::CreateAttachmentMimeHeaderL(CImMimeHeader& aMimeHeader, const TDesC& aDetails)
       
  4087 /**
       
  4088 Opens attachment file & extract initial text, pass into recognizer.
       
  4089 If the file type is recognized, use the MIME string produced in 
       
  4090 the MIMEheader object stored in the attachment entry.
       
  4091 */
       
  4092 	{
       
  4093 	if (!aDetails.Length())
       
  4094 		return EFalse; // No file to check 
       
  4095 	
       
  4096 	RApaLsSession lsSession;
       
  4097 	if (lsSession.Connect() != KErrNone)
       
  4098 		{
       
  4099 		// Unable to connect to Recognizer server.
       
  4100 		return EFalse;
       
  4101 		}
       
  4102 	
       
  4103 	CleanupClosePushL(lsSession);
       
  4104 	TDataRecognitionResult result;
       
  4105 	User::LeaveIfError(lsSession.RecognizeData(aDetails, TPtrC8(), result));
       
  4106 
       
  4107 	TPtrC8 mimeBuf8=result.iDataType.Des8();
       
  4108 	if (!mimeBuf8.Length())
       
  4109 		{
       
  4110 		// No point passing the file handle to the recogniser for Create Attachment 
       
  4111 		// as it will be zero length
       
  4112 		if(iAttachmentCreateState != ECreateAttachment)
       
  4113 			{
       
  4114 			CMsvStore* store = iMsvEntry.ReadStoreL();
       
  4115 			CleanupStack::PushL(store);
       
  4116 			MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
  4117 			// as this is email attachment entry , it has one attachment per entry
       
  4118 			RFile file = attachmentMgr.GetAttachmentFileL(0);
       
  4119 			CleanupStack::PopAndDestroy(store);
       
  4120 			CleanupClosePushL(file);
       
  4121 
       
  4122 			// pass the handle to the recogniser instead of filepath
       
  4123 			User::LeaveIfError(lsSession.RecognizeData(file, result));
       
  4124 			CleanupStack::PopAndDestroy(&file);
       
  4125 
       
  4126 	   		mimeBuf8.Set(result.iDataType.Des8());
       
  4127 			}
       
  4128  				
       
  4129 		if (!mimeBuf8.Length())
       
  4130 			{
       
  4131 			CleanupStack::PopAndDestroy(); // lssession
       
  4132 			return EFalse;
       
  4133 			}
       
  4134 		}
       
  4135 
       
  4136 	TInt locatePos = mimeBuf8.Locate(TChar('/'));
       
  4137 	
       
  4138 	if (locatePos != KErrNotFound)
       
  4139 		{
       
  4140 		aMimeHeader.SetContentTypeL(mimeBuf8.Left(locatePos));
       
  4141 		aMimeHeader.SetContentSubTypeL(mimeBuf8.Mid(locatePos + 1));
       
  4142 		}
       
  4143 		
       
  4144 	if (iRelatedPartId)
       
  4145 		aMimeHeader.SetContentIDL(*iContentId);
       
  4146 	
       
  4147 	CleanupStack::PopAndDestroy(); // lssession
       
  4148 	return ETrue; 
       
  4149 	}
       
  4150 
       
  4151 //	---------------------------------------------------------------------
       
  4152 //	Class to create receipts, replies, forwarded emails, and new emails
       
  4153 //	---------------------------------------------------------------------
       
  4154 
       
  4155 /** Creates a new email message.
       
  4156 
       
  4157 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4158 operation completes
       
  4159 @param aMsvSession Message server session to use
       
  4160 @param aDestination The Id of the folder where the new message is to be created
       
  4161 @param aPartList The body parts that are required in the new message. If a 
       
  4162 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4163 and KMsvMessagePartAttachments parts have to be set.
       
  4164 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4165 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4166 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4167 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4168 @return Operation object by which to control the operation */
       
  4169 EXPORT_C CImEmailOperation* CImEmailOperation::CreateNewL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4170 	{
       
  4171 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4172 	CleanupStack::PushL(self);
       
  4173 	self->ConstructL(ENew);
       
  4174 	CleanupStack::Pop(self);
       
  4175 	return self;
       
  4176 	}
       
  4177 
       
  4178 /** Creates a new email message with a specified priority and SMTP service.
       
  4179 
       
  4180 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4181 operation completes
       
  4182 @param aMsvSession Message server session to use
       
  4183 @param aDestination The Id of the folder where the new message is to be created
       
  4184 @param aSmtpServiceId The Id of the SMTP service entry to handle the email
       
  4185 @param aPartList The body parts that are required in the new message. If a 
       
  4186 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4187 and KMsvMessagePartAttachments parts have to be set.
       
  4188 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4189 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4190 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4191 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4192 @param aPriority The priority setting for the email
       
  4193 @return Operation object by which to control the operation */
       
  4194 EXPORT_C CImEmailOperation* CImEmailOperation::CreateNewL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aDestination, TMsvId aSmtpServiceId, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority)
       
  4195 	{
       
  4196 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, aSmtpServiceId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, EFalse);
       
  4197 	CleanupStack::PushL(self);
       
  4198 	self->ConstructL(ENew);
       
  4199 	CleanupStack::Pop(self);
       
  4200 	return self;
       
  4201 	}
       
  4202 
       
  4203 
       
  4204 /** 
       
  4205 Creates a new plain text email message with a specified priority and SMTP service.
       
  4206 
       
  4207 @param aObserverRequestStatus  	Asynchronous status word to complete when the 
       
  4208 								operation completes
       
  4209 @param aMsvSession 				Message server session to use
       
  4210 @param aDestination 			The Id of the folder where the new message is to be created
       
  4211 @param aSmtpServiceId 			The Id of the SMTP service entry to handle the email
       
  4212 @param aPartList 				The body parts that are required in the new message. If a 
       
  4213 								message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4214 								and KMsvMessagePartAttachments parts have to be set.
       
  4215 @param aMsvEmailTypeList 		Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4216 								KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4217 								If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4218 @param aMsgType 				The type of message to create e.g. KUidMsgTypeSMTP.
       
  4219 @param aPriority 				The priority setting for the email- by default this must be EPriorityStandard.
       
  4220 @param aUsePlainTextStorage		TBool, if set to ETrue inidcates that the new message entry needs to be created as plain text
       
  4221 								if set to EFalse indicates that message will be created as richtext entry.
       
  4222 @return CImEmailOperation		Operation object by which to control the operation 
       
  4223 */
       
  4224 EXPORT_C CImEmailOperation* CImEmailOperation::CreateNewL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aDestination, TMsvId aSmtpServiceId, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority, TBool aUsePlainTextStorage)
       
  4225 	{
       
  4226 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, aSmtpServiceId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, aUsePlainTextStorage);
       
  4227 	CleanupStack::PushL(self);
       
  4228 	self->ConstructL(ENew);
       
  4229 	CleanupStack::Pop(self);
       
  4230 	return self;
       
  4231 	}
       
  4232 
       
  4233 
       
  4234 /** Creates a reply email message, overriding the default subject format string.
       
  4235 
       
  4236 The aFormatString parameter allows you to override the default string used 
       
  4237 in the subject field of the new message (the default is the localised string 
       
  4238 STRING_reply_formatting_string1 defined in the source file imcm.rls).
       
  4239 
       
  4240 Note that if you reply to an HTML message that does not contain a text/plain 
       
  4241 alternative to the HTML, then the HTML part is copied as an attachment (still 
       
  4242 an HTML entry) into the new message even if aPartList does not specify KMsvMessagePartAttachments. 
       
  4243 This occurs because there is no other way of reading the original message 
       
  4244 unless the user switches between the editor/viewer and the application. 
       
  4245 
       
  4246 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4247 operation completes
       
  4248 @param aMsvSession Message server session to use
       
  4249 @param aMessageId The Id of the message to reply to
       
  4250 @param aDestination The Id of the folder where the new message is to be created
       
  4251 @param aPartList The body parts that are required in the new message. If a 
       
  4252 message with body text is required, then set KMsvMessagePartBody; if attachments 
       
  4253 are required too, also set KMsvMessagePartAttachments. To reply to the originator 
       
  4254 only, set KMsvMessagePartOriginator, otherwise a reply will be sent to all 
       
  4255 recipients of the original message. If the subject field is not required, 
       
  4256 then do not set KMsvMessagePartDescription.
       
  4257 @param aFormatString A string to be inserted into the subject field in the 
       
  4258 header before the subject, e.g. "Re: %S", sets the field to be "Re: " followed 
       
  4259 by the original subject text
       
  4260 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4261 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4262 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4263 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4264 @return Operation object by which to control the operation */
       
  4265 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReplyL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TDesC& aFormatString, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4266 	{
       
  4267 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4268 	CleanupStack::PushL(self);
       
  4269 	self->ConstructL(aMessageId, aFormatString, EReply);
       
  4270 	CleanupStack::Pop(self);
       
  4271 	return self;
       
  4272 	}
       
  4273 
       
  4274 /** Creates a reply email message.
       
  4275 
       
  4276 For details of how replies to HTML messages are handled, see the description 
       
  4277 above for the first overload of this function.
       
  4278 
       
  4279 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4280 operation completes
       
  4281 @param aMsvSession Message server session to use
       
  4282 @param aMessageId The Id of the message to reply to
       
  4283 @param aDestination The Id of the folder where the new message is to be created
       
  4284 @param aPartList The body parts that are required in the new message. If a 
       
  4285 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4286 and KMsvMessagePartAttachments parts have to be set.
       
  4287 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4288 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4289 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4290 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4291 @return Operation object by which to control the operation */
       
  4292 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReplyL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4293 	{
       
  4294 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4295 	CleanupStack::PushL(self);
       
  4296 	self->ConstructL(aMessageId, EReply);
       
  4297 	CleanupStack::Pop(self);
       
  4298 	return self;
       
  4299 	}
       
  4300 
       
  4301 /** Creates a reply email message, specifying a message priority.
       
  4302 
       
  4303 For details of how replies to HTML messages are handled, see the description 
       
  4304 above for the first overload of this function.
       
  4305 
       
  4306 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4307 operation completes
       
  4308 @param aMsvSession Message server session to use
       
  4309 @param aMessageId The Id of the message to reply to
       
  4310 @param aDestination The Id of the folder where the new message is to be created
       
  4311 @param aPartList The body parts that are required in the new message. If a 
       
  4312 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4313 and KMsvMessagePartAttachments parts have to be set.
       
  4314 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4315 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4316 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4317 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4318 @param aPriority The priority setting for the email
       
  4319 @return Operation object by which to control the operation */
       
  4320 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReplyL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority)
       
  4321 	{
       
  4322 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, EFalse);
       
  4323 	CleanupStack::PushL(self);
       
  4324 	self->ConstructL(aMessageId, EReply);
       
  4325 	CleanupStack::Pop(self);
       
  4326 	return self;
       
  4327 	}
       
  4328 
       
  4329 /** Creates a reply email message, specifying a message priority.
       
  4330 
       
  4331 For details of how replies to HTML messages are handled, see the description 
       
  4332 above for the first overload of this function.
       
  4333 
       
  4334 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4335 operation completes
       
  4336 @param aMsvSession Message server session to use
       
  4337 @param aMessageId The Id of the message to reply to
       
  4338 @param aDestination The Id of the folder where the new message is to be created
       
  4339 @param aPartList The body parts that are required in the new message. If a 
       
  4340 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4341 and KMsvMessagePartAttachments parts have to be set.
       
  4342 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4343 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4344 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4345 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4346 @param aPriority The priority setting for the email
       
  4347 @param aUsePlainTextStorage		TBool, if set to ETrue inidcates that the new message entry needs to be created as plain text
       
  4348 								if set to EFalse indicates that message will be created as richtext entry.
       
  4349 @return Operation object by which to control the operation */
       
  4350 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReplyL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority, TBool aUsePlainTextStorage)
       
  4351 	{
       
  4352 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, aUsePlainTextStorage);
       
  4353 	CleanupStack::PushL(self);
       
  4354 	self->ConstructL(aMessageId, EReply);
       
  4355 	CleanupStack::Pop(self);
       
  4356 	return self;
       
  4357 	}
       
  4358 	
       
  4359 /** Creates a forwarded email message, overriding the default subject format string.
       
  4360 
       
  4361 The aFormatString parameter allows you to override the default string used 
       
  4362 in the subject field of the new message (the default is the localised string 
       
  4363 STRING_forward_formatting_string1 defined in the source file imcm.rls).
       
  4364 
       
  4365 Note that if you forward an HTML message that does not contain a text/plain 
       
  4366 alternative to the HTML, then the HTML part is copied as an attachment (still 
       
  4367 an HTML entry) into the new message even if aPartList does not specify KMsvMessagePartAttachments. 
       
  4368 This occurs because there is no other way of reading the original message 
       
  4369 unless the user switches between the editor/viewer and the application. 
       
  4370 
       
  4371 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4372 operation completes
       
  4373 @param aMsvSession Message server session to use
       
  4374 @param aMessageId The Id of the message to forward
       
  4375 @param aDestination The Id of the folder where the new message is to be created
       
  4376 @param aPartList The body parts that are required in the new message. If a 
       
  4377 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4378 and KMsvMessagePartAttachments parts have to be set.
       
  4379 @param aFormatString A string to be inserted into the subject field in the 
       
  4380 header before the subject, e.g. "Fwd: %S", sets the field to be "Fwd: " followed 
       
  4381 by the original subject text
       
  4382 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4383 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4384 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4385 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4386 @return Operation object by which to control the operation */
       
  4387 EXPORT_C CImEmailOperation* CImEmailOperation::CreateForwardL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TDesC& aFormatString, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4388 	{
       
  4389 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId,  aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4390 	CleanupStack::PushL(self);
       
  4391 	self->ConstructL(aMessageId, aFormatString, EForward);
       
  4392 	CleanupStack::Pop(self);
       
  4393 	return self;
       
  4394 	}
       
  4395 
       
  4396 /** Creates a forwarded email message.
       
  4397 
       
  4398 For details of how forwarding HTML messages is handled, see the description 
       
  4399 above for the first overload of this function.
       
  4400 
       
  4401 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4402 operation completes
       
  4403 @param aMsvSession Message server session to use
       
  4404 @param aMessageId The Id of the message to forward
       
  4405 @param aDestination The Id of the folder where the new message is to be created
       
  4406 @param aPartList The body parts that are required in the new message. If a 
       
  4407 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4408 and KMsvMessagePartAttachments parts have to be set.
       
  4409 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4410 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4411 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4412 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4413 @return Operation object by which to control the operation */
       
  4414 EXPORT_C CImEmailOperation* CImEmailOperation::CreateForwardL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4415 	{
       
  4416 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId,  aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4417 	CleanupStack::PushL(self);
       
  4418 	self->ConstructL(aMessageId, EForward);
       
  4419 	CleanupStack::Pop(self);
       
  4420 	return self;
       
  4421 	}
       
  4422 
       
  4423 /** Creates a forwarded email message, specifying the message priority and SMTP 
       
  4424 service with which to send the message.
       
  4425 
       
  4426 For details of how forwarding HTML messages is handled, see the description 
       
  4427 above for the first overload of this function.
       
  4428 
       
  4429 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4430 operation completes
       
  4431 @param aMsvSession Message server session to use
       
  4432 @param aMessageId The Id of the message to forward
       
  4433 @param aDestination The Id of the folder where the new message is to be created
       
  4434 @param aSmtpServiceId The Id of the SMTP service with which to send the new 
       
  4435 message
       
  4436 @param aPartList The body parts that are required in the new message. If a 
       
  4437 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4438 and KMsvMessagePartAttachments parts have to be set.
       
  4439 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4440 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4441 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4442 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4443 @param aPriority The priority setting for the email
       
  4444 @return Operation object by which to control the operation */
       
  4445 EXPORT_C CImEmailOperation* CImEmailOperation::CreateForwardL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvId aSmtpServiceId, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority)
       
  4446 	{
       
  4447 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, aSmtpServiceId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, EFalse);
       
  4448 	CleanupStack::PushL(self);
       
  4449 	self->ConstructL(aMessageId, EForward);
       
  4450 	CleanupStack::Pop(self);
       
  4451 	return self;
       
  4452 	}
       
  4453 	
       
  4454 /** Creates a forwarded email message, specifying the message priority and SMTP 
       
  4455 service with which to send the message.
       
  4456 
       
  4457 For details of how forwarding HTML messages is handled, see the description 
       
  4458 above for the first overload of this function.
       
  4459 
       
  4460 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4461 operation completes
       
  4462 @param aMsvSession Message server session to use
       
  4463 @param aMessageId The Id of the message to forward
       
  4464 @param aDestination The Id of the folder where the new message is to be created
       
  4465 @param aSmtpServiceId The Id of the SMTP service with which to send the new 
       
  4466 message
       
  4467 @param aPartList The body parts that are required in the new message. If a 
       
  4468 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4469 and KMsvMessagePartAttachments parts have to be set.
       
  4470 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4471 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4472 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4473 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4474 @param aPriority The priority setting for the email
       
  4475 @param aUsePlainTextStorage		TBool, if set to ETrue inidcates that the new message entry needs to be created as plain text
       
  4476 								if set to EFalse indicates that message will be created as richtext entry.
       
  4477 @return Operation object by which to control the operation */
       
  4478 EXPORT_C CImEmailOperation* CImEmailOperation::CreateForwardL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvId aSmtpServiceId, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority, TBool aUsePlainTextStorage)
       
  4479 	{
       
  4480 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, aSmtpServiceId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, aUsePlainTextStorage);
       
  4481 	CleanupStack::PushL(self);
       
  4482 	self->ConstructL(aMessageId, EForward);
       
  4483 	CleanupStack::Pop(self);
       
  4484 	return self;
       
  4485 	}
       
  4486 
       
  4487 /** Creates a forwarded email message.
       
  4488 
       
  4489 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4490 operation completes
       
  4491 @param aMsvSession Message server session to use
       
  4492 @param aMessageId The Id of the message to forward
       
  4493 @param aDestination The Id of the folder where the new message is to be created
       
  4494 @param aPartList The body parts that are required in the new message. If a 
       
  4495 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4496 and KMsvMessagePartAttachments parts have to be set.
       
  4497 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4498 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4499 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4500 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4501 @return Operation object by which to control the operation */
       
  4502 EXPORT_C CImEmailOperation* CImEmailOperation::CreateForwardAsAttachmentL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4503 	{
       
  4504 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4505 	CleanupStack::PushL(self);
       
  4506 	self->ConstructL(aMessageId, EForwardAsAttachment);
       
  4507 	CleanupStack::Pop(self);
       
  4508 	return self;
       
  4509 	}
       
  4510 
       
  4511 /** Creates a forwarded email message, specifying the message priority and SMTP 
       
  4512 service with which to send the message.
       
  4513 
       
  4514 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4515 operation completes
       
  4516 @param aMsvSession Message server session to use
       
  4517 @param aMessageId The Id of the message to forward
       
  4518 @param aSmtpServiceId The Id of the SMTP service with which to send the new 
       
  4519 message
       
  4520 @param aDestination The Id of the folder where the new message is to be created
       
  4521 @param aPartList The body parts that are required in the new message. If a 
       
  4522 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4523 and KMsvMessagePartAttachments parts have to be set.
       
  4524 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4525 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4526 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4527 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4528 @param aPriority The priority setting for the email
       
  4529 @return Operation object by which to control the operation */
       
  4530 EXPORT_C CImEmailOperation* CImEmailOperation::CreateForwardAsAttachmentL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvId aSmtpServiceId, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority)
       
  4531 	{
       
  4532 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, aSmtpServiceId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, EFalse);
       
  4533 	CleanupStack::PushL(self);
       
  4534 	self->ConstructL(aMessageId, EForwardAsAttachment);
       
  4535 	CleanupStack::Pop(self);
       
  4536 	return self;
       
  4537 	}
       
  4538 
       
  4539 /** Creates a email receipt message, overriding the default subject format string.
       
  4540 
       
  4541 The aFormatString parameter allows you to override the default string used 
       
  4542 in the subject field of the new message (the default is the localised string 
       
  4543 STRING_receipt_formatting_string1 defined in the source file imcm.rls).
       
  4544 
       
  4545 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4546 operation completes
       
  4547 @param aMsvSession Message server session to use
       
  4548 @param aMessageId The Id of the original message for which the receipt is required
       
  4549 @param aDestination The Id of the folder where the new message is to be created
       
  4550 @param aPartList The body parts that are required in the new message. If a 
       
  4551 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4552 and KMsvMessagePartAttachments parts have to be set.
       
  4553 @param aFormatString A string to be inserted into the subject field in the 
       
  4554 header before the subject, e.g. "Receipt of message: %S", sets the field to 
       
  4555 be "Receipt of message: " followed by the original subject text
       
  4556 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4557 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4558 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4559 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4560 @return Operation object by which to control the operation */
       
  4561 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReceiptL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TDesC& aFormatString, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4562 	{
       
  4563 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination,KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4564 	CleanupStack::PushL(self);
       
  4565 	self->ConstructL(aMessageId, aFormatString, EReceipt);
       
  4566 	CleanupStack::Pop(self);
       
  4567 	return self;
       
  4568 	}
       
  4569 
       
  4570 /** Creates a email receipt message.
       
  4571 
       
  4572 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4573 operation completes
       
  4574 @param aMsvSession Message server session to use
       
  4575 @param aMessageId The Id of the original message for which the receipt is required
       
  4576 @param aDestination The Id of the folder where the new message is to be created
       
  4577 @param aPartList The body parts that are required in the new message. If a 
       
  4578 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4579 and KMsvMessagePartAttachments parts have to be set.
       
  4580 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4581 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4582 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4583 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4584 @return Operation object by which to control the operation */
       
  4585 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReceiptL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4586 	{
       
  4587 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4588 	CleanupStack::PushL(self);
       
  4589 	self->ConstructL(aMessageId, EReceipt);
       
  4590 	CleanupStack::Pop(self);
       
  4591 	return self;
       
  4592 	}
       
  4593 
       
  4594 /** Creates a email receipt message, specifying the message priority.
       
  4595 
       
  4596 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4597 operation completes
       
  4598 @param aMsvSession Message server session to use
       
  4599 @param aMessageId The Id of the original message for which the receipt is required
       
  4600 @param aDestination The Id of the folder where the new message is to be created
       
  4601 @param aPartList The body parts that are required in the new message. If a 
       
  4602 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4603 and KMsvMessagePartAttachments parts have to be set.
       
  4604 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4605 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4606 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4607 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4608 @param aPriority The priority setting for the email
       
  4609 @return Operation object by which to control the operation */
       
  4610 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReceiptL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority)
       
  4611 	{
       
  4612 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, EFalse);
       
  4613 	CleanupStack::PushL(self);
       
  4614 	self->ConstructL(aMessageId, EReceipt);
       
  4615 	CleanupStack::Pop(self);
       
  4616 	return self;
       
  4617 	}
       
  4618 
       
  4619 /** Creates a email receipt message, specifying the message priority.
       
  4620 
       
  4621 @param aObserverRequestStatus Asynchronous status word to complete when the 
       
  4622 operation completes
       
  4623 @param aMsvSession Message server session to use
       
  4624 @param aMessageId The Id of the original message for which the receipt is required
       
  4625 @param aDestination The Id of the folder where the new message is to be created
       
  4626 @param aPartList The body parts that are required in the new message. If a 
       
  4627 message with body text and attachments is required, then the KMsvMessagePartBody 
       
  4628 and KMsvMessagePartAttachments parts have to be set.
       
  4629 @param aMsvEmailTypeList Creation flags. This can be 0, or a bitmask of KMsvEmailTypeListMHTMLMessage, 
       
  4630 KMsvEmailTypeListInvisibleMessage, and KMsvEmailTypeListMessageInPreparation. 
       
  4631 If KMsvEmailTypeListMHTMLMessage is not set, a plain-text message is created.
       
  4632 @param aMsgType The type of message to create e.g. KUidMsgTypeSMTP.
       
  4633 @param aPriority The priority setting for the email
       
  4634 @param aUsePlainTextStorage		TBool, if set to ETrue inidcates that the new message entry needs to be created as plain text
       
  4635 								if set to EFalse indicates that message will be created as richtext entry.
       
  4636 @return Operation object by which to control the operation */
       
  4637 EXPORT_C CImEmailOperation* CImEmailOperation::CreateReceiptL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority, TBool aUsePlainTextStorage)
       
  4638 	{
       
  4639 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId, aPartList, aMsvEmailTypeList, aMsgType, aPriority, aUsePlainTextStorage);
       
  4640 	CleanupStack::PushL(self);
       
  4641 	self->ConstructL(aMessageId, EReceipt);
       
  4642 	CleanupStack::Pop(self);
       
  4643 	return self;
       
  4644 	}
       
  4645 	
       
  4646 CImEmailOperation* CImEmailOperation::CreateCopyL(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aMessageId, TMsvId aDestination, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType)
       
  4647 	{
       
  4648 	CImEmailOperation* self = new(ELeave) CImEmailOperation(aObserverRequestStatus, aMsvSession, aDestination, KMsvUnknownServiceIndexEntryId,  aPartList, aMsvEmailTypeList, aMsgType, EPriorityStandard, EFalse);
       
  4649 	CleanupStack::PushL(self);
       
  4650 	self->ConstructL(aMessageId, ECopy);
       
  4651 	CleanupStack::Pop(self);
       
  4652 	return self;
       
  4653 	}
       
  4654 
       
  4655 
       
  4656 /** Destructor. */
       
  4657 EXPORT_C CImEmailOperation::~CImEmailOperation()
       
  4658 	{
       
  4659 	Cancel();
       
  4660 	delete iMsvOperation;
       
  4661 	delete iFormatString;
       
  4662 	delete iRichText;
       
  4663 	delete iParaLayer;
       
  4664 	delete iCharLayer;
       
  4665 	delete iEmailMessage;
       
  4666 	delete iNewHeader;
       
  4667 	delete iFileMan;
       
  4668 	delete iBodyHeaderFormatString;
       
  4669 	delete iBodyHeaderDateTimeFormatString;
       
  4670 	delete iBodyHeader;
       
  4671 	iAttachmentInfoList.ResetAndDestroy();
       
  4672 	iFile.Close();
       
  4673 	delete iStore;
       
  4674 	delete iMsvEntry;
       
  4675 	delete iSignatureText;
       
  4676 	delete iDefaultVCardNameFormatString;
       
  4677 	delete iHtmlConverter;
       
  4678 	delete iSmtpSettings;
       
  4679 	delete iVcardStore;
       
  4680 	delete iBodyHeaderToString;
       
  4681 	delete iBodyHeaderCcString;
       
  4682 	iOriginalHeader = NULL;
       
  4683 	delete iOriginalHeader;
       
  4684 	}
       
  4685 
       
  4686 /** Gets progress information for a completed operation.
       
  4687 
       
  4688 The function returns (in packaged form):
       
  4689 
       
  4690 for a successfully completed operation, the Id of the new message 
       
  4691 
       
  4692 if there was an error/problem while creating the message, a null Id (KMsvNullIndexEntryId). 
       
  4693 The new message will also be deleted.
       
  4694 
       
  4695 @return A message Id as a TPckg<TMsvId> */
       
  4696 EXPORT_C const TDesC8& CImEmailOperation::FinalProgress()
       
  4697 	{
       
  4698 	__ASSERT_ALWAYS(!IsActive(), gPanic(EMiutActiveInFinalProgress));
       
  4699  	const TDesC8* progress = &KNullDesC8();
       
  4700  	TRAPD(leave, progress = &ProgressL());
       
  4701 	__ASSERT_ALWAYS(leave == KErrNone, gPanic(EImcmFinalProgressFailed));
       
  4702 	return *progress;	
       
  4703 	}
       
  4704 
       
  4705 /** Gets progress information.
       
  4706 
       
  4707 While the operation is in progress, a null Id (KMsvNullIndexEntryId) is returned. 
       
  4708 For a completed operation, values are as described for FinalProgress().
       
  4709 
       
  4710 @return A message Id as a TPckg<TMsvId> */
       
  4711 const TDesC8& CImEmailOperation::ProgressL()
       
  4712 	{
       
  4713 	if (iState==EFinished)
       
  4714 		iDataMember() = iNewMessageId;
       
  4715 	return iDataMember;
       
  4716 	}
       
  4717 
       
  4718 void CImEmailOperation::DoCancel()
       
  4719 	{
       
  4720 	if (iMsvOperation)
       
  4721 		iMsvOperation->Cancel();
       
  4722 	if (iEmailMessage)
       
  4723 		iEmailMessage->Cancel();
       
  4724 	if (iNewMessageId!=KMsvNullIndexEntryId)
       
  4725 		iMsvEntry->Session().RemoveEntry(iNewMessageId);
       
  4726 
       
  4727 	TRequestStatus* st = &iObserverRequestStatus;
       
  4728 	User::RequestComplete(st, KErrCancel);
       
  4729 	}
       
  4730 
       
  4731 void CImEmailOperation::SelectAndProcessNextStateL()
       
  4732 	{
       
  4733 	SelectNextStateL();
       
  4734 	ProcessStateL();
       
  4735 	}
       
  4736 
       
  4737 void CImEmailOperation::RunL()
       
  4738 	{
       
  4739 	if (iStatus.Int() != KErrNone)
       
  4740 		{
       
  4741 		ErrorRecovery(iStatus.Int());
       
  4742 		return;
       
  4743 		}
       
  4744 	if ((iState == ECreateNewMessageEntry) || 
       
  4745 		(iState == ECreateMultipartMixedFolderEntry) ||
       
  4746 		(iState == ECreateTextEntry) ||
       
  4747 		(iState == EStoreBody) ||
       
  4748 		(iState == ECreateAttachmentEntry) || 
       
  4749 		(iState == ECreateMultipartAlternativeFolderEntry) ||
       
  4750 		(iState == ECreateHTMLEntry) ||
       
  4751 		(iState == EStoreAttachment) ||
       
  4752 		(iState == ECreateVCardAttachment) ||
       
  4753 		(iState == ECompleteEmailOperation)
       
  4754 		|| (iState == ECreateDefaultHtmlAttachment)	
       
  4755 		|| (iState == EStoreHTMLTextInEntry)
       
  4756 		) 
       
  4757 		{
       
  4758 		TInt progressError = McliUtils::GetProgressErrorL(*iMsvOperation);
       
  4759 		if (progressError != KErrNone)
       
  4760 			{
       
  4761 			ErrorRecovery(progressError);
       
  4762 			return;
       
  4763 			}			
       
  4764 		}
       
  4765 	if (iState != EFinished)
       
  4766 		{
       
  4767 		TRAPD(error, SelectAndProcessNextStateL());
       
  4768 		if (error)
       
  4769 			{
       
  4770 			ErrorRecovery(error);
       
  4771 			return;
       
  4772 			}
       
  4773 		else if (iState != EFinished)
       
  4774 			SetActive();
       
  4775 		}
       
  4776 	}
       
  4777 
       
  4778 CImEmailOperation::CImEmailOperation(TRequestStatus& aObserverRequestStatus, CMsvSession& aMsvSession, TMsvId aDestination, TMsvId aSmtpServiceId, TMsvPartList aPartList, const TMsvEmailTypeList& aMsvEmailTypeList, TUid aMsgType, TInt aPriority, TBool aUsePlainTextStorage)
       
  4779 	: CMsvOperation(aMsvSession, aPriority, aObserverRequestStatus),
       
  4780 	  iDestinationId(aDestination),
       
  4781 	  iSmtpServiceId(aSmtpServiceId),
       
  4782 	  iMsgType(aMsgType),
       
  4783 	  iPartList(aPartList),
       
  4784 	  iMsvEmailTypeList(aMsvEmailTypeList),
       
  4785 	  iAttachmentFile(aMsvSession.FileSession()),
       
  4786 	  iUsePlainTextStorage(aUsePlainTextStorage)
       
  4787 	{
       
  4788 	iMtm = iMsgType;
       
  4789 	}
       
  4790 
       
  4791 void CImEmailOperation::ConstructL(TMsvId aMessageId, const TDesC& aFormatString, TImEmailOperation aOperation)
       
  4792 	{
       
  4793     iOrigMessageId = aMessageId;
       
  4794 	iFormatString = aFormatString.AllocL();
       
  4795 	ConstructL(aOperation);
       
  4796 	}
       
  4797 
       
  4798 void CImEmailOperation::ConstructL(TMsvId aMessageId, TImEmailOperation aOperation)
       
  4799 	{
       
  4800     iOrigMessageId = aMessageId;
       
  4801 	ConstructL(aOperation);
       
  4802 	}
       
  4803 
       
  4804 void CImEmailOperation::ConstructL(TImEmailOperation aOperation)
       
  4805 	{
       
  4806 	iOperation = aOperation;
       
  4807 	iMsvEntry = CMsvEntry::NewL(iMsvSession, iDestinationId, TMsvSelectionOrdering());
       
  4808 	iSmtpSettings = new (ELeave) CImSmtpSettings;
       
  4809 		
       
  4810 	if( iMsgType == KUidMsgTypeSMTP )
       
  4811 		{
       
  4812 		// Restore the SMTP settings - check if the service has been supplied.
       
  4813 		if( iSmtpServiceId == KMsvNullIndexEntryId || iSmtpServiceId == KMsvUnknownServiceIndexEntryId )
       
  4814 			{
       
  4815 			// Nope - the operation dictates where the SMTP settings are restored
       
  4816 			// from.
       
  4817 			switch( iOperation )
       
  4818 				{
       
  4819 			case EReply:
       
  4820 			case EReceipt:
       
  4821  			case EForward:
       
  4822 			case EForwardAsAttachment:
       
  4823 				{
       
  4824 				// Restore from the original message.
       
  4825 				TRAPD(error, SetSmtpServiceFromOriginalMessageL());
       
  4826 
       
  4827 				if( error != KErrNone )
       
  4828 					{
       
  4829 					// Failed to restore the SMTP settings from the original 
       
  4830 					// message - use the SMTP settings from the default settings
       
  4831 					// specified in the root entry.
       
  4832 					SetSmtpServiceFromDefaultsL();
       
  4833 					}
       
  4834 				} break;
       
  4835 			case ENew:
       
  4836 			case ECopy:
       
  4837 				{
       
  4838 				// No SMTP service has been supplied - restore SMTP settings 
       
  4839 				// from the default service specified in the root entry.
       
  4840 				SetSmtpServiceFromDefaultsL();
       
  4841 				} break;
       
  4842 			default:
       
  4843 				__ASSERT_DEBUG( EFalse, User::Invariant() );
       
  4844 				break;
       
  4845 				}
       
  4846 			}
       
  4847 		else
       
  4848 			{
       
  4849 			// Restore SMTP settings from the service supplied.
       
  4850 			iMsvEntry->SetEntryL(iSmtpServiceId);
       
  4851 			RestoreSmtpSettingsL();
       
  4852 			}
       
  4853 
       
  4854 		}
       
  4855 	else if( iMsgType == KUidMsgTypePCMail )
       
  4856 		{
       
  4857 		if( iOperation == EReply )
       
  4858 			{
       
  4859 			// reply via the same service as the original message
       
  4860 			iMsvEntry->SetEntryL(iOrigMessageId);
       
  4861 			iPCMailServiceId = iMsvEntry->Entry().iServiceId;
       
  4862 			}
       
  4863 		else if( iSmtpServiceId != KMsvNullIndexEntryId ) // iSmtpService may hold the PCMail Service Id!
       
  4864 			iPCMailServiceId = iSmtpServiceId; 
       
  4865 		else
       
  4866 			iPCMailServiceId = KMsvUnknownServiceIndexEntryId;
       
  4867 		}
       
  4868 	
       
  4869 	iNewHeader = CImHeader::NewLC();
       
  4870 	CleanupStack::Pop(iNewHeader);
       
  4871 	iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
       
  4872 
       
  4873 	iParaLayer = CParaFormatLayer::NewL();
       
  4874 	iCharLayer = CCharFormatLayer::NewL();
       
  4875 	iRichText = CRichText::NewL(iParaLayer, iCharLayer);
       
  4876 
       
  4877 	iAttachmentInfoList.ResetAndDestroy();
       
  4878 	if( iOrigMessageId != KMsvNullIndexEntryId )
       
  4879 		{
       
  4880 		iMsvEntry->SetEntryL(iOrigMessageId);
       
  4881 		iOrigMessageHtml = static_cast<TMsvEmailEntry>(iMsvEntry->Entry()).MHTMLEmail();
       
  4882 		}
       
  4883 
       
  4884 	if( iMsvEmailTypeList & KMsvEmailTypeListMHTMLMessage )
       
  4885 		{
       
  4886 		TRAPD(err, iHtmlConverter = CImHtmlConverter::NewL(*iMsvEntry, *iParaLayer, *iCharLayer));
       
  4887  		if( err != KErrNone )
       
  4888 			{
       
  4889 			if( err == KErrNoMemory )
       
  4890 				User::Leave(KErrNoMemory);
       
  4891 			else
       
  4892 				gPanic(EImcmHtmlConverterNotFound);
       
  4893 			}
       
  4894 		iCreateHtmlMessage = ETrue;
       
  4895 		}
       
  4896 
       
  4897 	if( iMsgType == KUidMsgTypeSMTP && iOperation != ECopy )
       
  4898 		CheckForSignatureOrVCardL();
       
  4899 
       
  4900 	if( iNeedToAddVCardAttachment || iCreateHtmlMessage || (iOperation!=ENew && iOperation!=ECopy) )
       
  4901 		OpenAndReadResourceFileL();
       
  4902 
       
  4903 	CActiveScheduler::Add(this);
       
  4904 
       
  4905 	// The signature needs to be added to the richtext regardless of whether the
       
  4906 	// body is included iSignatureText will only be set if the Signature flag is
       
  4907 	// set in the SMTP settings and if there is a richtext stream.
       
  4908 	if( iSignatureText )
       
  4909 		iRichText->AppendTakingSolePictureOwnershipL(*iSignatureText);
       
  4910 	
       
  4911 
       
  4912 	if( iOperation == ENew )
       
  4913 		iState = ECreateNewMessageEntry;
       
  4914 	ProcessStateL();
       
  4915 
       
  4916 	iObserverRequestStatus = KRequestPending;
       
  4917 	SetActive();
       
  4918 	}
       
  4919 
       
  4920 void CImEmailOperation::OpenAndReadResourceFileL()
       
  4921 	{
       
  4922 	RResourceFile resourceFile;
       
  4923 	OpenResourceFileL(resourceFile, iMsvSession.FileSession());
       
  4924 	CleanupClosePushL(resourceFile);
       
  4925 
       
  4926 	HBufC8* buf;
       
  4927 	TResourceReader reader;
       
  4928 	if( iFormatString == NULL )
       
  4929 		{
       
  4930 		if( (iOperation == EForward) || (iOperation == EForwardAsAttachment) )
       
  4931 			{
       
  4932 			buf = resourceFile.AllocReadLC(FORWARD_FORMATTING_STRING);
       
  4933 			reader.SetBuffer(buf);
       
  4934 			iFormatString = (reader.ReadTPtrC()).AllocL();
       
  4935 			CleanupStack::PopAndDestroy(buf);
       
  4936 			}
       
  4937 		else if( iOperation == EReply )
       
  4938 			{
       
  4939 			buf = resourceFile.AllocReadLC(REPLY_FORMATTING_STRING);
       
  4940 			reader.SetBuffer(buf);
       
  4941 			iFormatString = (reader.ReadTPtrC()).AllocL();
       
  4942 			CleanupStack::PopAndDestroy(buf);
       
  4943 			}
       
  4944 		else if( iOperation == EReceipt )
       
  4945 			{
       
  4946 			buf = resourceFile.AllocReadLC(RECEIPT_FORMATTING_STRING);
       
  4947 			reader.SetBuffer(buf);
       
  4948 			iFormatString = (reader.ReadTPtrC()).AllocL();
       
  4949 			CleanupStack::PopAndDestroy(buf);
       
  4950 			}
       
  4951 		}
       
  4952 	if( (iOperation == EForward) || (iOperation == EForwardAsAttachment) || (iOperation == EReply) )
       
  4953 		{
       
  4954 		RestoreOriginalHeaderL();
       
  4955 		TInt format;
       
  4956 		if( (iOperation == EForward) || (iOperation == EForwardAsAttachment) )
       
  4957 			{
       
  4958 			switch (iBodyHeaderFormat)
       
  4959 				{
       
  4960 				case EToAndCc:
       
  4961 					format = FORWARD_BODY_HEADER_TOCC;
       
  4962 					break;				
       
  4963 				case EToOnly:
       
  4964 					format = FORWARD_BODY_HEADER_TOONLY;
       
  4965 					break;
       
  4966 				case ECcOnly:
       
  4967 					format = FORWARD_BODY_HEADER_CCONLY;
       
  4968 					break;
       
  4969 				case ENoToCcInfo:
       
  4970 				default:
       
  4971 					format = FORWARD_BODY_HEADER;
       
  4972 					break;
       
  4973 				}
       
  4974 
       
  4975 			}
       
  4976 		else  // iOperation == EReply
       
  4977 			{
       
  4978 			switch (iBodyHeaderFormat)
       
  4979 				{
       
  4980 				case EToAndCc:
       
  4981 					format = REPLY_BODY_HEADER_TOCC;
       
  4982 					break;				
       
  4983 				case EToOnly:
       
  4984 					format = REPLY_BODY_HEADER_TOONLY;
       
  4985 					break;
       
  4986 				case ECcOnly:
       
  4987 					format = REPLY_BODY_HEADER_CCONLY;
       
  4988 					break;
       
  4989 				case ENoToCcInfo:
       
  4990 				default:
       
  4991 					format = REPLY_BODY_HEADER;
       
  4992 					break;
       
  4993 				}
       
  4994 			}
       
  4995 		buf = resourceFile.AllocReadLC(format);
       
  4996 		reader.SetBuffer(buf);
       
  4997 		iBodyHeaderFormatString = (reader.ReadTPtrC()).AllocL();
       
  4998 		CleanupStack::PopAndDestroy(buf);
       
  4999 		
       
  5000 		buf = resourceFile.AllocReadLC(BODY_HEADER_DATETIME_FORMAT);
       
  5001 		reader.SetBuffer(buf);
       
  5002 		iBodyHeaderDateTimeFormatString = (reader.ReadTPtrC()).AllocL();
       
  5003 		CleanupStack::PopAndDestroy(buf);
       
  5004 		}
       
  5005 
       
  5006 	if( iNeedToAddVCardAttachment )
       
  5007 		{
       
  5008 		buf = resourceFile.AllocReadLC(DEFAULT_VCARD_NAME);
       
  5009 		reader.SetBuffer(buf);
       
  5010 		iDefaultVCardNameFormatString = (reader.ReadTPtrC()).AllocL();
       
  5011 		CleanupStack::PopAndDestroy(buf);
       
  5012 		}
       
  5013 	if( iHtmlConverter != NULL )
       
  5014 		iHtmlConverter->ReadDefaultAttachmentNameL(resourceFile);
       
  5015 
       
  5016 	CleanupStack::PopAndDestroy(&resourceFile);
       
  5017 	}
       
  5018 
       
  5019 void CImEmailOperation::SetSmtpServiceFromDefaultsL()
       
  5020 	{
       
  5021   	// Get the default SMTP service Id from CenRep
       
  5022   	CEmailAccounts* account = CEmailAccounts::NewLC();		
       
  5023   	TSmtpAccount id;
       
  5024 	TInt error = account->DefaultSmtpAccountL(id);
       
  5025 	CleanupStack::PopAndDestroy(account); 	   
       
  5026   	
       
  5027   	if (error == KErrNone)
       
  5028   		{
       
  5029 		iSmtpServiceId = id.iSmtpService;		
       
  5030   		iMsvEntry->SetEntryL(iSmtpServiceId);
       
  5031   		RestoreSmtpSettingsL();		
       
  5032   		}
       
  5033   	else if (error == KErrNotFound)
       
  5034   		{
       
  5035   		iSmtpServiceId = KMsvUnknownServiceIndexEntryId;
       
  5036   		}
       
  5037 	}
       
  5038 
       
  5039 void CImEmailOperation::SetSmtpServiceFromOriginalMessageL()
       
  5040 	{
       
  5041 	__ASSERT_DEBUG( iOperation != ENew, User::Invariant() );
       
  5042 
       
  5043 	iMsvEntry->SetEntryL(iOrigMessageId);
       
  5044 
       
  5045 	__ASSERT_DEBUG(iMsvEntry->Entry().iServiceId != KMsvLocalServiceIndexEntryIdValue, gPanic(EMiutLocalServiceIdSet));
       
  5046 
       
  5047 	// Get iServiceId from original message and then move context to the service
       
  5048 	// (e.g. POP).
       
  5049 	iSmtpServiceId = iMsvEntry->Entry().iServiceId;
       
  5050 	iMsvEntry->SetEntryL(iMsvEntry->Entry().iServiceId);
       
  5051 
       
  5052 	// Now move context to SMTP to access the SMTP settings.
       
  5053 	iSmtpServiceId = iMsvEntry->Entry().iRelatedId;
       
  5054 	iMsvEntry->SetEntryL(iSmtpServiceId);
       
  5055 
       
  5056 	RestoreSmtpSettingsL();
       
  5057 	}
       
  5058 
       
  5059 void CImEmailOperation::RestoreSmtpSettingsL()
       
  5060 	{
       
  5061   	CEmailAccounts* account = CEmailAccounts::NewLC();  	
       
  5062   	TSmtpAccount id;
       
  5063 	account->GetSmtpAccountL(iMsvEntry->Entry().Id(), id);
       
  5064 	account->LoadSmtpSettingsL(id, *iSmtpSettings);  	
       
  5065   	CleanupStack::PopAndDestroy(account);    
       
  5066 	}
       
  5067 
       
  5068 void CImEmailOperation::ErrorRecovery(TInt error)
       
  5069 	{
       
  5070 	if (iNewMessageId!=KMsvNullIndexEntryId)
       
  5071 		iMsvEntry->Session().RemoveEntry(iNewMessageId);
       
  5072 	// complete the observer with error
       
  5073 	TRequestStatus* status=&iObserverRequestStatus;
       
  5074 	User::RequestComplete(status,error);
       
  5075 	}
       
  5076 
       
  5077 void CImEmailOperation::SelectNextStateL()
       
  5078 	{
       
  5079 	switch( iState )
       
  5080 		{
       
  5081 	case ECreateNewHeader:
       
  5082 		{
       
  5083 		
       
  5084 		if( iOperation & EAttachOriginal )
       
  5085 			iState = ECreateNewMessageEntry;
       
  5086 		else if( iPartList & KMsvMessagePartBody )
       
  5087 			iState = EGetBodyText;
       
  5088 		else if( iPartList & KMsvMessagePartAttachments )
       
  5089 			iState = EGetAttachmentList;
       
  5090 		else
       
  5091 			iState = EGetMessageDigest;
       
  5092 		} break;
       
  5093 	case EGetBodyText:
       
  5094 		{
       
  5095 		// This may be an HTML message with no text alternative to the HTML if 
       
  5096 		// there is no body text.
       
  5097 		TInt sizeOfBody = 0;
       
  5098 		TBool isPlainText = EFalse;
       
  5099 		iEmailMessage->GetBodyTextEntryIdL(iOrigMessageId,CImEmailMessage::EThisMessageOnly);
       
  5100 		// Check if the original message was stored as plain text or rich text.
       
  5101 		if( iEmailMessage->Selection().Count() )
       
  5102 			{
       
  5103 			TMsvId textId = iEmailMessage->Selection().At(0);
       
  5104 			iMsvEntry->SetEntryL(textId);	
       
  5105 			CMsvStore* store = iMsvEntry->ReadStoreL();
       
  5106 			CleanupStack::PushL(store);
       
  5107 			
       
  5108 			isPlainText = (store->IsPresentL(KMsvPlainBodyText16) || store->IsPresentL(KMsvPlainBodyText8));
       
  5109 			CleanupStack::PopAndDestroy(store);
       
  5110 			store = NULL;
       
  5111 			}
       
  5112 		
       
  5113 		// The body text is not in richtext format, so don't populate it.	
       
  5114 		if(isPlainText)
       
  5115 			{
       
  5116 			// Find out the size of the body text.
       
  5117 			sizeOfBody = GetPlainBodyTextSizeL();
       
  5118 			}
       
  5119 		else
       
  5120 			{
       
  5121 			sizeOfBody = iRichText->DocumentLength();
       
  5122 			sizeOfBody = sizeOfBody * 2;
       
  5123 			}
       
  5124 			
       
  5125 		if( iOrigMessageHtml && (((sizeOfBody) - iRichTextSize) == 0) )
       
  5126 			iHtmlNoTextAlt = ETrue;
       
  5127 
       
  5128 		if( iPartList & KMsvMessagePartAttachments )
       
  5129 			iState = EGetAttachmentList;
       
  5130 		else
       
  5131 			iState = EGetMessageDigest;
       
  5132 		} break;
       
  5133 	case EGetAttachmentList:
       
  5134 		{
       
  5135 		// Need a copy of attachment list as the CImEmailMessage object may be reset
       
  5136 		TInt count = iEmailMessage->AttachmentManager().AttachmentCount();
       
  5137 		for(TInt index = 0; index < count ; index++)
       
  5138 			{
       
  5139 			CMsvAttachment* attachment = CMsvAttachment::NewL(*iEmailMessage->AttachmentInfoSelection()[index]);
       
  5140 			CleanupStack::PushL(attachment);
       
  5141 			User::LeaveIfError(iAttachmentInfoList.Append(attachment));
       
  5142 			CleanupStack::Pop(attachment);
       
  5143 			}
       
  5144 		iState = EGetMessageDigest;
       
  5145 		} break;
       
  5146 	case EGetMessageDigest:
       
  5147 		{
       
  5148 		iEmbeddedMessagesToProcess = iEmailMessage->Selection().Count();
       
  5149 		iState = ECreateNewMessageEntry;
       
  5150 		} break;
       
  5151 	case ECreateNewMessageEntry:
       
  5152 		{
       
  5153 		iNewMessageId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  5154 		iState = ECheckMultipartMixedFolderRequired;
       
  5155 		} break;
       
  5156 	case ECheckMultipartMixedFolderRequired:
       
  5157 		{
       
  5158 		if(	NeedMultipartMixedFolder() )
       
  5159 			iState = ECreateMultipartMixedFolderEntry;
       
  5160 		else
       
  5161 			iState = ECheckMultipartAlternativeFolderRequired;
       
  5162 		} break;
       
  5163 	case ECreateMultipartMixedFolderEntry:
       
  5164 		{
       
  5165 		iMultipartMixedFolderCreated = ETrue;
       
  5166 		iMultipartMixedId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  5167 		iState = ECheckMultipartAlternativeFolderRequired;
       
  5168 		} break;
       
  5169 	case ECheckMultipartAlternativeFolderRequired:
       
  5170 		{
       
  5171 		if( iCreateHtmlMessage )
       
  5172 			iState = ECreateMultipartAlternativeFolderEntry;
       
  5173 		else
       
  5174 			iState = ECheckTextEntryRequired;
       
  5175 		} break;
       
  5176 	case ECreateMultipartAlternativeFolderEntry:
       
  5177 		{
       
  5178 		iMultipartAlternativeFolderCreated = ETrue;
       
  5179 		iMultipartAlternativeId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  5180 		iState = ECheckTextEntryRequired;
       
  5181 		} break;
       
  5182 	case ECheckTextEntryRequired:
       
  5183 		{
       
  5184 		if( (iMultipartMixedFolderCreated && ((iPartList & KMsvMessagePartBody) || iNeedToAddVCardAttachment || iSignatureText )) ||
       
  5185 			(iMultipartAlternativeFolderCreated) ||
       
  5186 			(iPartList & KMsvMessagePartBody) ||
       
  5187 			((iPartList & KMsvMessagePartAttachments) && iOperation != ECopy && iTotalAttachments == 0) ||
       
  5188 			(!(iPartList & KMsvMessagePartAttachments) && !(iPartList & KMsvMessagePartBody) && !iNeedToAddVCardAttachment && !iCreateHtmlMessage) )
       
  5189 			{
       
  5190 			// Hmmm, quite a convaluted way of working out if a text entry is needed!!
       
  5191 			iState = ECreateTextEntry;
       
  5192 			}
       
  5193 		else
       
  5194 			iState = ECheckVCardRequired;
       
  5195 		} break;
       
  5196 	case ECreateTextEntry:
       
  5197 		{
       
  5198 		iTextId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  5199 	
       
  5200 		if( (iPartList & KMsvMessagePartBody && !(iOperation & EAttachOriginal)) || iSignatureText )
       
  5201 			iState = EStoreBody;
       
  5202 		else
       
  5203 			iState = ECheckVCardRequired;
       
  5204 		} break;
       
  5205 	case EStoreBody:
       
  5206 		{
       
  5207 		iState = ECheckVCardRequired;
       
  5208 		} break;
       
  5209 	case ECheckVCardRequired:
       
  5210 		{
       
  5211 		if( iNeedToAddVCardAttachment && (iOperation != ECopy) )
       
  5212 			iState = ECreateVCardAttachment;
       
  5213 		else
       
  5214 			iState = ECheckHTMLEntryRequired;
       
  5215 		} break;
       
  5216 	case ECreateVCardAttachment:
       
  5217 		{
       
  5218 		iVcardId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  5219 		iState = EAddVCardAttachment;
       
  5220 		} break;
       
  5221 	case EAddVCardAttachment:
       
  5222 		{
       
  5223 		iState = ECheckHTMLEntryRequired;
       
  5224 		} break;
       
  5225 	case ECheckHTMLEntryRequired:
       
  5226 		{
       
  5227 		if( iCreateHtmlMessage )
       
  5228 			iState = ECreateHTMLEntry;
       
  5229 		else
       
  5230 			iState = ECheckAttachOriginalMessageRequired;
       
  5231 		} break;
       
  5232 	case ECreateHTMLEntry:
       
  5233 		{
       
  5234 		__ASSERT_DEBUG( iMultipartAlternativeFolderCreated, User::Invariant() );
       
  5235 
       
  5236 		iHtmlId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  5237 		TMsvId serviceId;
       
  5238 		TMsvEmailEntry textEntry;
       
  5239 		iMsvEntry->Session().GetEntry(iTextId, serviceId, textEntry);
       
  5240 
       
  5241 		// Store character set info in a MimeHeader.
       
  5242 		iMsvEntry->SetEntryL(iHtmlId);
       
  5243 		iState = ECreateDefaultHtmlAttachment;
       
  5244 		iStore = iMsvEntry->EditStoreL();
       
  5245 		} break;
       
  5246 	case ECreateDefaultHtmlAttachment:
       
  5247 		{
       
  5248 		CImMimeHeader* mimeHeader = CImMimeHeader::NewLC();
       
  5249 		mimeHeader->SetMimeCharset(KCharacterSetIdentifierUtf8);
       
  5250 		mimeHeader->StoreL(*iStore);
       
  5251 		iStore->CommitL();
       
  5252 		CleanupStack::PopAndDestroy(mimeHeader); 
       
  5253 		iFile.Close();
       
  5254 		delete iStore;
       
  5255 		iStore=NULL;
       
  5256 		
       
  5257 		TMsvId serviceId;
       
  5258 		TMsvEmailEntry textEntry;
       
  5259 		iMsvEntry->Session().GetEntry(iTextId, serviceId, textEntry);
       
  5260 		
       
  5261 		iMsvEntry->SetEntryL(iMultipartAlternativeId);
       
  5262 
       
  5263 		if( iPartList & KMsvMessagePartBody && (textEntry.iSize > 0) && !(iOperation & EAttachOriginal) )
       
  5264 			iState = EPrepareToStoreHTMLEntryText;
       
  5265 		else 
       
  5266 			iState = ECheckAttachOriginalMessageRequired;
       
  5267 		}break;
       
  5268 	case EPrepareToStoreHTMLEntryText:
       
  5269 		{
       
  5270 		iFinishedConvertingHTML = EFalse;
       
  5271 		
       
  5272 		if(iUsePlainTextStorage && iRestoreErr == KErrNoMemory)
       
  5273 			{
       
  5274 			// If iRestoreErr is KErrNoMemory then complete the store message operation.
       
  5275 			iState = ECompleteEmailOperation;	
       
  5276 			}
       
  5277 		else
       
  5278 			{
       
  5279 			if( iHtmlId != KMsvNullIndexEntryId )
       
  5280 				iState = EStoreHTMLEntryText;
       
  5281 			else 
       
  5282 				iState = ECheckAttachOriginalMessageRequired;
       
  5283 			}
       
  5284 		} break;
       
  5285 	case EStoreHTMLEntryText:
       
  5286 		{
       
  5287 		if( iFinishedConvertingHTML )
       
  5288 			{
       
  5289 			iHtmlConverter->ResetStoreL();
       
  5290 			iState = EStoreHTMLTextInEntry;	
       
  5291 			}
       
  5292 		// Otherwise stay in this state until the HTML has been converted.
       
  5293 		} break;
       
  5294 	case EStoreHTMLTextInEntry:
       
  5295 		iState = ECheckAttachOriginalMessageRequired;
       
  5296 		break;
       
  5297 	case EAddMessageAttachmentInfo:
       
  5298 		{
       
  5299 		ResetStoreL();
       
  5300 		iState = ECompleteEmailOperation;
       
  5301 		}break;
       
  5302 	case ECheckAttachOriginalMessageRequired:
       
  5303 		{
       
  5304 		if( (iOperation & EAttachOriginal) && (iPartList & KMsvMessagePartBody || iPartList & KMsvMessagePartAttachments) )
       
  5305 			iState = EAttachOriginalMessage;
       
  5306 		else
       
  5307 			iState = ECheckHTMLPageRequired;
       
  5308 		} break;
       
  5309 	case EAttachOriginalMessage:
       
  5310 		{
       
  5311 		TPckgBuf<TMsvId> paramPack; 
       
  5312 		paramPack.Copy(iMsvOperation->FinalProgress());
       
  5313 		iAttachedMessageId = paramPack();
       
  5314 		iMsvEntry->SetEntryL(iAttachedMessageId);
       
  5315 		iState = EAddMessageAttachmentInfo;
       
  5316 		} break;
       
  5317 	case ECheckHTMLPageRequired:
       
  5318 		{
       
  5319 		TInt sizeOfBody = 0;
       
  5320 		if(iUsePlainTextStorage && iOperation != ENew)
       
  5321 			{
       
  5322 			iEmailMessage->GetBodyTextEntryIdL(iNewMessageId, CImEmailMessage::EThisMessageOnly);
       
  5323 			sizeOfBody = GetPlainBodyTextSizeL();
       
  5324 			}
       
  5325 		else
       
  5326 			{
       
  5327 			sizeOfBody = iRichText->DocumentLength();
       
  5328 			sizeOfBody = sizeOfBody * 2;
       
  5329 			}
       
  5330 		if( iPartList & KMsvMessagePartBody && iOrigMessageHtml &&
       
  5331 			(iOperation != ENew) &&	(((sizeOfBody) - iRichTextSize) == 0) )
       
  5332 			iState = EFindHTMLPage;
       
  5333 		else
       
  5334 			iState = ECheckAttachmentsRequired;
       
  5335 		} break;
       
  5336 	case EFindHTMLPage:
       
  5337 		{
       
  5338 		iState = ECopyHTMLPartToAttachment;
       
  5339 		} break;
       
  5340 	case ECopyHTMLPartToAttachment:
       
  5341 		{
       
  5342 		iState = ECheckAttachmentsRequired;
       
  5343 		} break;
       
  5344 	case ECheckAttachmentsRequired:
       
  5345 		{
       
  5346 		if( iPartList & KMsvMessagePartAttachments && (iTotalAttachments > 0) && (iOperation != ENew) )
       
  5347 			{
       
  5348 			iFileMan = CFileMan::NewL(iMsvSession.FileSession());
       
  5349 			iState = ECreateAttachmentEntry;
       
  5350 			}
       
  5351 		else
       
  5352 			iState = ECheckEmbeddedMessagesRequired;
       
  5353 		} break;
       
  5354 	case ECreateAttachmentEntry:
       
  5355 		{
       
  5356 		iState = EStoreAttachment;
       
  5357 		} break;
       
  5358 	case EStoreAttachment:
       
  5359 		{
       
  5360 		ResetStoreL();
       
  5361 		//	Are there more attachments to be added?
       
  5362 		if( ++iAttachmentCount < iTotalAttachments )
       
  5363 			iState = ECreateAttachmentEntry;
       
  5364 		else 
       
  5365 			iState = ECheckEmbeddedMessagesRequired;
       
  5366 		} break;
       
  5367 	case ECheckEmbeddedMessagesRequired:
       
  5368 		{
       
  5369 		if( iEmbeddedMessagesToProcess > 0 )
       
  5370 			iState = EAddEmbeddedMessagesAsAttachments;
       
  5371 		else
       
  5372 			iState = ECompleteEmailOperation;
       
  5373 		} break;
       
  5374 	case EAddEmbeddedMessagesAsAttachments:
       
  5375 		{
       
  5376 		if(iEmbeddedMessagesToProcess > 0)
       
  5377    			{   			
       
  5378    			iState = EAddEmbeddedMessagesAsAttachments;
       
  5379    			}
       
  5380    		else
       
  5381    			{			
       
  5382    			iState = ECompleteEmailOperation;
       
  5383    			}
       
  5384 		} break;
       
  5385 	case ECompleteEmailOperation:
       
  5386 		{
       
  5387 		iState = EFinished;
       
  5388 		} break;
       
  5389 	default:
       
  5390 		__ASSERT_DEBUG( EFalse, User::Invariant() );
       
  5391 		break;
       
  5392 		}
       
  5393 	}
       
  5394 
       
  5395 void CImEmailOperation::ProcessStateL()
       
  5396 	{
       
  5397 	CMsvOperation* op = NULL;
       
  5398 	switch( iState )
       
  5399 		{
       
  5400 	case ECreateNewHeader:
       
  5401 		{
       
  5402 		CreateNewHeaderL();
       
  5403 		} break;
       
  5404 	case EGetBodyText:
       
  5405 		{
       
  5406 		GetBodyTextL();
       
  5407 		} break;
       
  5408 	case EGetAttachmentList:
       
  5409 		{
       
  5410 		iEmailMessage->GetAttachmentsListL(iStatus, iOrigMessageId, CImEmailMessage::EAllAttachments, CImEmailMessage::EThisMessageOnly);
       
  5411 		} break;
       
  5412 	case EGetMessageDigest:
       
  5413 		{
       
  5414 		iEmailMessage->GetMessageDigestEntriesL(iStatus, iOrigMessageId);
       
  5415 		} break;
       
  5416 	case ECreateNewMessageEntry:
       
  5417 		{
       
  5418 		CreateNewMessageL(iDestinationId);
       
  5419 		} break;
       
  5420 	case ECreateMultipartMixedFolderEntry:
       
  5421 		{
       
  5422 		CreateMultipartMixedFolderEntryL();
       
  5423 		} break;
       
  5424 	case ECreateMultipartAlternativeFolderEntry:
       
  5425 		{
       
  5426 		CreateMultipartAlternativeFolderEntryL();
       
  5427 		} break;
       
  5428 	case ECreateTextEntry:
       
  5429 		{
       
  5430 		if (iMultipartAlternativeFolderCreated)
       
  5431 			CreateTextEntryL(iMultipartAlternativeId);
       
  5432 		else if (iMultipartMixedFolderCreated)
       
  5433 			CreateTextEntryL(iMultipartMixedId);
       
  5434 		else 
       
  5435 			CreateTextEntryL(iNewMessageId);
       
  5436 
       
  5437 		} break;
       
  5438 	case EStoreBody:
       
  5439 		{
       
  5440 		StoreBodyL();
       
  5441 		} break;
       
  5442 	case ECreateVCardAttachment:
       
  5443 		{
       
  5444 		CreateVCardAttachmentL();
       
  5445 		} break;
       
  5446 	case EAddVCardAttachment:
       
  5447 		{
       
  5448 		AddVCardAttachmentL();
       
  5449 		} break;
       
  5450 	case ECreateHTMLEntry:
       
  5451 		{
       
  5452 		CreateHTMLEntryL();
       
  5453 		} break;
       
  5454 	case EPrepareToStoreHTMLEntryText:
       
  5455 		{
       
  5456 		TRAP(iRestoreErr ,iHtmlConverter->PrepareToStoreHTMLEntryTextL(iHtmlId, iTextId));
       
  5457 		// Do not leave if it is KErrNoMemory while creating HTML part for a message, since the 
       
  5458 		// plainbody text part of message is already created and that be used to send the message.
       
  5459 		if(iUsePlainTextStorage)
       
  5460 			{
       
  5461 			if(iRestoreErr != KErrNoMemory)
       
  5462 				{
       
  5463 				User::LeaveIfError(iRestoreErr);
       
  5464 				}
       
  5465 			}
       
  5466 		else
       
  5467 			{
       
  5468 			User::LeaveIfError(iRestoreErr);
       
  5469 			}	
       
  5470 		RequestComplete(KErrNone);
       
  5471 		} break;
       
  5472 	case EStoreHTMLEntryText:
       
  5473 		{
       
  5474 		iFinishedConvertingHTML = iHtmlConverter->StoreHTMLEntryTextAL(iStatus);
       
  5475 		if(!iFinishedConvertingHTML)
       
  5476 			RequestComplete(KErrNone);
       
  5477 		else
       
  5478 			{			
       
  5479 			iVCardAndHtmlSize += iHtmlConverter->Size();
       
  5480 			}
       
  5481 		} break;
       
  5482 	case ECreateDefaultHtmlAttachment:
       
  5483 		{
       
  5484 		CreateDefaultAttachmentL();	
       
  5485 		}break;
       
  5486 	case EStoreHTMLTextInEntry:
       
  5487 		op = iHtmlConverter->ChangeHTMLTextInEnrtyL(iStatus);
       
  5488 		if(!op)
       
  5489 			RequestComplete(KErrNone);	
       
  5490 		else
       
  5491 			{
       
  5492 			delete iMsvOperation;
       
  5493 			iMsvOperation = op;		
       
  5494 			}
       
  5495 		break;
       
  5496 	case EAddMessageAttachmentInfo:
       
  5497 		{
       
  5498 		AddMessageAttachmentInfoL(iAttachedMessageId);
       
  5499 		} break;	
       
  5500 	case EAttachOriginalMessage:
       
  5501 		{
       
  5502 		AttachOriginalMessageToNewMessageL();
       
  5503 		} break;
       
  5504 	case EFindHTMLPage:
       
  5505 		{
       
  5506 		iEmailMessage->FindFirstHTMLPageL(iOrigMessageId, iStatus);
       
  5507 		} break;
       
  5508 	case ECopyHTMLPartToAttachment:
       
  5509 		{
       
  5510 		AppendHtmlAttachmentL();
       
  5511 		} break;
       
  5512 	case ECreateAttachmentEntry:
       
  5513 		{
       
  5514 		CreateAttachmentEntryL();
       
  5515 		} break;
       
  5516 	case EStoreAttachment:
       
  5517 		{
       
  5518 		StoreAttachmentL();
       
  5519 		} break;
       
  5520 	case EAddEmbeddedMessagesAsAttachments:
       
  5521 		{
       
  5522 		AddMessageAsAttachmentL();
       
  5523 		} break;
       
  5524 	case ECompleteEmailOperation:
       
  5525 		{
       
  5526 		CompleteEmailOperationL();
       
  5527 		} break;
       
  5528 	case EFinished:
       
  5529 		{
       
  5530 		TRequestStatus* status=&iObserverRequestStatus;
       
  5531 		User::RequestComplete(status,KErrNone);
       
  5532 		} break;
       
  5533 	case ECheckMultipartMixedFolderRequired:
       
  5534 	case ECheckMultipartAlternativeFolderRequired:
       
  5535 	case ECheckTextEntryRequired:
       
  5536 	case ECheckVCardRequired:
       
  5537 	case ECheckHTMLEntryRequired:
       
  5538 	case ECheckAttachOriginalMessageRequired:
       
  5539 	case ECheckHTMLPageRequired:
       
  5540 	case ECheckAttachmentsRequired:
       
  5541 	case ECheckEmbeddedMessagesRequired:
       
  5542 		{
       
  5543 		RequestComplete(KErrNone);
       
  5544 		} break;
       
  5545 	default:
       
  5546 		__ASSERT_DEBUG( EFalse, User::Invariant() );
       
  5547 		break;
       
  5548 		}
       
  5549 	}
       
  5550 
       
  5551 void CImEmailOperation::RequestComplete(TInt aError)
       
  5552 	{
       
  5553 	iStatus = KRequestPending;
       
  5554 	TRequestStatus* status=&iStatus;
       
  5555 	iStatus=KRequestPending;
       
  5556 	User::RequestComplete(status,aError);
       
  5557 	}
       
  5558 
       
  5559 TMsvId CImEmailOperation::ServiceId()
       
  5560 	{
       
  5561 	// this functions returns the correct service id dependant on the Message Type.
       
  5562 	if (iMsgType == KUidMsgTypePCMail)
       
  5563 		return iPCMailServiceId;
       
  5564 
       
  5565 	return iSmtpServiceId;
       
  5566 	}
       
  5567 	
       
  5568 void CImEmailOperation::CreateNewHeaderL()
       
  5569 	{
       
  5570 	//	1.	Create new header using the original message.
       
  5571 	//	2.	Change header details depending on the operation required.
       
  5572 	//	3.	Create the body header now since we have the original message
       
  5573 	if (iOriginalHeader==NULL)
       
  5574 		{
       
  5575 		RestoreOriginalHeaderL();
       
  5576 		}
       
  5577 		
       
  5578 	switch( iOperation )
       
  5579 		{
       
  5580 	case EForward:
       
  5581 	case EForwardAsAttachment:
       
  5582 		{
       
  5583 		iOriginalHeader->CreateForwardL(*iNewHeader, *iFormatString);
       
  5584 		} break;
       
  5585 	case EReply:
       
  5586 		{
       
  5587 		if( (iPartList & KMsvMessagePartOriginator) && !(iPartList & KMsvMessagePartRecipient) )
       
  5588 			iOriginalHeader->CreateReplyL(*iNewHeader, CImHeader::EOriginator, *iFormatString);
       
  5589 		else
       
  5590 			{
       
  5591 			if( (iPartList & KMsvMessagePartOriginator) && (iPartList & KMsvMessagePartRecipient) )
       
  5592 				iOriginalHeader->CreateReplyL(*iNewHeader, CImHeader::EAll, *iFormatString);
       
  5593 			else
       
  5594 				iOriginalHeader->CreateReplyL(*iNewHeader, CImHeader::ERecipients, *iFormatString);
       
  5595 
       
  5596 			// Remove the user's email address (if provisioned) from the To: and Cc: headers
       
  5597 			// of the reply message.  But ensure there is at least one email
       
  5598 			// address in the To: header to account for the scenario when the
       
  5599 			// user may be replying to a message they sent themselves.
       
  5600 			if (iSmtpSettings->EmailAddress().Length())
       
  5601    				{
       
  5602 				TInt i = 0;
       
  5603 				while (i < iNewHeader->ToRecipients().Count())
       
  5604    					{
       
  5605 					if ((iNewHeader->ToRecipients().Count() > 1) && (iNewHeader->ToRecipients()[i]).FindF(iSmtpSettings->EmailAddress()) >= 0)
       
  5606 						// Only delete if there is more than one recipient because we do 
       
  5607 						// not want to create a reply with an empty To: header.
       
  5608    						iNewHeader->ToRecipients().Delete(i);
       
  5609 					else
       
  5610 						++i;
       
  5611    					}
       
  5612 				
       
  5613 				i = 0;
       
  5614 				while (i < iNewHeader->CcRecipients().Count())
       
  5615    					{
       
  5616 					if ((iNewHeader->CcRecipients()[i]).FindF(iSmtpSettings->EmailAddress()) >= 0)
       
  5617 						iNewHeader->CcRecipients().Delete(i);
       
  5618 					else
       
  5619 						++i;
       
  5620    					}
       
  5621    				}
       
  5622 			}
       
  5623 		} break;
       
  5624 	case ECopy:
       
  5625 		{
       
  5626 		delete iNewHeader;
       
  5627 		iNewHeader = iOriginalHeader;
       
  5628 		} break;
       
  5629 	case EReceipt:
       
  5630 		{
       
  5631 		iOriginalHeader->CreateReceiptL(*iNewHeader, *iFormatString);
       
  5632 		} break;
       
  5633 	default:
       
  5634 		__ASSERT_DEBUG( EFalse, User::Invariant() );
       
  5635 		break;
       
  5636 		}
       
  5637 
       
  5638 	if (iPartList & !KMsvMessagePartDescription)
       
  5639 		iNewHeader->SetSubjectL(KNullDesC);
       
  5640 
       
  5641 	if ((iBodyHeaderFormatString != NULL ) && (iBodyHeaderFormatString->Find(KMiutFormatString)))
       
  5642 		{
       
  5643 		__ASSERT_DEBUG(iBodyHeaderDateTimeFormatString!=NULL, User::Invariant());
       
  5644 		
       
  5645 		TTime date = iMsvEntry->Entry().iDate;
       
  5646 		
       
  5647 		//Convert time to local time. 
       
  5648 		RTz myTZoneServer; 
       
  5649 		// Connect to the time zone server, leaves if fails to connect
       
  5650 		User::LeaveIfError(myTZoneServer.Connect()); 
       
  5651 		CleanupClosePushL(myTZoneServer);
       
  5652 		// Create a converter object.
       
  5653 		CTzConverter* myConverter = CTzConverter::NewL(myTZoneServer); 
       
  5654 		CleanupStack::PushL(myConverter);
       
  5655 		myConverter->ConvertToLocalTime(date); 
       
  5656 		CleanupStack::PopAndDestroy(2);  //myTZoneServer,myConverter
       
  5657 		
       
  5658 		TBuf<KMaxLongDateFormatSpec+KMaxTimeFormatSpec+1> parsedDateTime;
       
  5659 	        date.FormatL(parsedDateTime, *iBodyHeaderDateTimeFormatString);   
       
  5660 
       
  5661 		// Numberconvertion to the local phone language
       
  5662 		TLocale localeInfo;
       
  5663 		localeInfo.Refresh();
       
  5664 		TDigitType dgType = localeInfo.DigitType();
       
  5665 
       
  5666 		NumberConversion::ConvertDigits(parsedDateTime, dgType);
       
  5667 
       
  5668 		TPtrC subject = iOriginalHeader->Subject();
       
  5669 		TPtrC author = iOriginalHeader->From();
       
  5670 		iOriginalHeader = NULL;
       
  5671 		
       
  5672 		switch (iBodyHeaderFormat)
       
  5673 			{
       
  5674 			case EToAndCc:
       
  5675 				{
       
  5676 				iBodyHeader = HBufC::NewL(subject.Length() + author.Length() + parsedDateTime.Length() + iBodyHeaderToString->Length() + iBodyHeaderCcString->Length() + iBodyHeaderFormatString->Length());
       
  5677 				TPtr bodyHeaderPtr = iBodyHeader->Des();
       
  5678 				bodyHeaderPtr.Format(TRefByValue<const TDesC>(*iBodyHeaderFormatString), &subject, &author, iBodyHeaderToString, iBodyHeaderCcString, &parsedDateTime);
       
  5679 				} break;				
       
  5680 			case EToOnly:
       
  5681 				{
       
  5682 				iBodyHeader = HBufC::NewL(subject.Length() + author.Length() + parsedDateTime.Length() + iBodyHeaderToString->Length() + iBodyHeaderFormatString->Length());
       
  5683 				TPtr bodyHeaderPtr = iBodyHeader->Des();
       
  5684 				bodyHeaderPtr.Format(TRefByValue<const TDesC>(*iBodyHeaderFormatString), &subject, &author, iBodyHeaderToString, &parsedDateTime);
       
  5685 				} break;
       
  5686 			case ECcOnly:
       
  5687 				{
       
  5688 				iBodyHeader = HBufC::NewL(subject.Length() + author.Length() + parsedDateTime.Length() + iBodyHeaderCcString->Length() + iBodyHeaderFormatString->Length());
       
  5689 				TPtr bodyHeaderPtr = iBodyHeader->Des();
       
  5690 				bodyHeaderPtr.Format(TRefByValue<const TDesC>(*iBodyHeaderFormatString), &subject, &author, iBodyHeaderCcString, &parsedDateTime);
       
  5691 				} break;
       
  5692 			case ENoToCcInfo:
       
  5693 			default:
       
  5694 				{
       
  5695 				iBodyHeader = HBufC::NewL(subject.Length() + author.Length() + parsedDateTime.Length() + iBodyHeaderFormatString->Length());
       
  5696 				TPtr bodyHeaderPtr = iBodyHeader->Des();
       
  5697 				bodyHeaderPtr.Format(TRefByValue<const TDesC>(*iBodyHeaderFormatString), &subject, &author, &parsedDateTime);
       
  5698 				}
       
  5699 			} // switch (iBodyHeaderFormat)
       
  5700 		}
       
  5701 
       
  5702 	RequestComplete(KErrNone);
       
  5703 	}
       
  5704 
       
  5705 void CImEmailOperation::RestoreOriginalHeaderL()
       
  5706 	{
       
  5707 	__ASSERT_DEBUG(iOriginalHeader==NULL, User::Invariant());
       
  5708 	iOriginalHeader = CImHeader::NewLC();
       
  5709 	CleanupStack::Pop(iOriginalHeader);
       
  5710 
       
  5711 	// Restore the header from the original message.
       
  5712 	iMsvEntry->SetEntryL(iOrigMessageId);
       
  5713 	CMsvStore* store = iMsvEntry->ReadStoreL();
       
  5714 	CleanupStack::PushL(store);
       
  5715 	iOriginalHeader->RestoreL(*store);
       
  5716 	CleanupStack::PopAndDestroy(store);
       
  5717 	SetBodyHeaderFormatL();
       
  5718 	}
       
  5719 	
       
  5720 void CImEmailOperation::SetBodyHeaderFormatL()
       
  5721 	{
       
  5722 	// determine if To: and CC: fields are to be included in reply/forwarded email
       
  5723 	// body header. If so, prepare the string to be included.
       
  5724 	if (iSmtpSettings->ToCcIncludeLimit() > 0)
       
  5725 		{
       
  5726 		if (iOriginalHeader->ToRecipients().Count()>0)
       
  5727 			{
       
  5728 			if (iOriginalHeader->CcRecipients().Count()>0)
       
  5729 				{
       
  5730 				iBodyHeaderFormat=EToAndCc;
       
  5731 				CreateAddressListStringL(iBodyHeaderCcString, iOriginalHeader->CcRecipients());
       
  5732 				}
       
  5733 			else
       
  5734 				{
       
  5735 				iBodyHeaderFormat=EToOnly;
       
  5736 				}
       
  5737 			CreateAddressListStringL(iBodyHeaderToString, iOriginalHeader->ToRecipients());
       
  5738 			}
       
  5739 		else // no "to" recipients, any "cc"?
       
  5740 			{
       
  5741 			if (iOriginalHeader->CcRecipients().Count()>0)
       
  5742 				{
       
  5743 				iBodyHeaderFormat=ECcOnly;
       
  5744 				CreateAddressListStringL(iBodyHeaderCcString, iOriginalHeader->CcRecipients());
       
  5745 				}
       
  5746 			else
       
  5747 				{
       
  5748 				iBodyHeaderFormat=ENoToCcInfo;
       
  5749 				}
       
  5750 			}
       
  5751 		}
       
  5752 	else
       
  5753 		{
       
  5754 		iBodyHeaderFormat=ENoToCcInfo;
       
  5755 		}
       
  5756 	}
       
  5757 
       
  5758 void CImEmailOperation::CreateAddressListStringL(HBufC*& aListBuffer, const CDesCArray& aAddressArray)
       
  5759 	{
       
  5760 	// Prepares a list of addresses to include in body header of reply/forwarded emails,
       
  5761 	// truncated if exceeding the set limit.
       
  5762 	// The original data may be either an array of individual addresses, or a single
       
  5763 	// descriptor containing multiple comma separated addresses.
       
  5764 	TBool truncate=EFalse;
       
  5765 	TInt  length=0;
       
  5766 	TInt  count=0;
       
  5767 	TInt  limit=iSmtpSettings->ToCcIncludeLimit();
       
  5768 	TInt  elements=aAddressArray.Count();
       
  5769 	
       
  5770 	if (elements==0)
       
  5771 		return;
       
  5772 
       
  5773 	if (elements==1) // handle single string containing one or more addresses
       
  5774 		{
       
  5775 		// truncate the string if necessary
       
  5776 		TInt lastChar=0;
       
  5777 		truncate=iMessageField.TruncateAddressString(aAddressArray[0], limit, lastChar);
       
  5778 		if (!truncate)
       
  5779 			{
       
  5780 			aListBuffer = HBufC::NewL(aAddressArray[0].Length());
       
  5781 			TPtr addrStringPtr = aListBuffer->Des();
       
  5782 			addrStringPtr.Append(aAddressArray[0]);
       
  5783 			}
       
  5784 		else
       
  5785 			{
       
  5786 			aListBuffer = HBufC::NewL(lastChar+KEllipsesString.iTypeLength); // room for the truncated list + ellipses
       
  5787 			TPtr addrStringPtr = aListBuffer->Des();
       
  5788 			TPtrC16 leftString=aAddressArray[0].Left(lastChar);
       
  5789 			TInt temp1 = leftString.Length();
       
  5790 			TInt temp2 = aListBuffer->Length();
       
  5791 			addrStringPtr.Append(leftString);
       
  5792 			addrStringPtr.Append(KEllipsesString);
       
  5793 			}
       
  5794 		}
       
  5795 	else	// handle array of individual addresses.
       
  5796 		{
       
  5797 		// determine if list to be truncated
       
  5798 		if (limit<elements)
       
  5799 			{
       
  5800 			count=limit;
       
  5801 			truncate=ETrue;
       
  5802 			}
       
  5803 		else
       
  5804 			{
       
  5805 			count=elements;
       
  5806 			}
       
  5807 		
       
  5808 		// calculate length required for the address string
       
  5809 		TInt n;
       
  5810 		for (n=0;n<count-1;++n)
       
  5811 			{
       
  5812 			length+=aAddressArray[n].Length()+KSeparatorString.iTypeLength;
       
  5813 			}
       
  5814 		length+=aAddressArray[n].Length();
       
  5815 		if (truncate)
       
  5816 			{
       
  5817 			length+=KEllipsesString.iTypeLength;
       
  5818 			}
       
  5819 
       
  5820 		delete aListBuffer;
       
  5821 		aListBuffer = NULL;
       
  5822 		aListBuffer = HBufC::NewL(length);
       
  5823 		TPtr addrStringPtr = aListBuffer->Des();
       
  5824 
       
  5825 		// populate the address buffer
       
  5826 		for (n=0;n<count-1;++n)
       
  5827 			{
       
  5828 			addrStringPtr.Append(aAddressArray[n]);
       
  5829 			addrStringPtr.Append(KSeparatorString);
       
  5830 			}
       
  5831 		addrStringPtr.Append(aAddressArray[n]);			
       
  5832 		if (truncate)
       
  5833 			{
       
  5834 			addrStringPtr.Append(KEllipsesString);
       
  5835 			}
       
  5836 		}
       
  5837 	}
       
  5838 	
       
  5839 void CImEmailOperation::GetBodyTextL()
       
  5840 	{
       
  5841 	//	1.	Insert body header
       
  5842 	//	2.	Get the Body Text from the original message
       
  5843 
       
  5844 	if (iBodyHeaderFormatString != NULL)
       
  5845 		iRichText->InsertL(iRichText->DocumentLength(), *iBodyHeader);
       
  5846 
       
  5847 	// DocumentLength() gives no. of chars and since unicode we multiply by 2
       
  5848 	iRichTextSize = (iRichText->DocumentLength() * 2);
       
  5849 	
       
  5850 	iEmailMessage->GetBodyTextEntryIdL(iOrigMessageId,CImEmailMessage::EThisMessageOnly);
       
  5851 	TMsvId textId = 0;
       
  5852 	TBool isPlainText = EFalse;
       
  5853 	
       
  5854 	// Check if the body text of the message restored here was stored as rich text or not.
       
  5855 	if( iEmailMessage->Selection().Count() )
       
  5856 		{
       
  5857 		textId = iEmailMessage->Selection().At(0);
       
  5858 		iMsvEntry->SetEntryL(textId);
       
  5859 		CMsvStore* store = iMsvEntry->ReadStoreL();
       
  5860 		CleanupStack::PushL(store);
       
  5861 		// Check if the original message was stored as plain text.
       
  5862 		if(iUsePlainTextStorage)
       
  5863 			{
       
  5864 			isPlainText = (store->IsPresentL(KMsvPlainBodyText16)|| store->IsPresentL(KMsvPlainBodyText8));
       
  5865 			}		
       
  5866 		CleanupStack::PopAndDestroy(store);
       
  5867 		store = NULL;
       
  5868 		}
       
  5869 		
       
  5870 	// If the original message was not rich text then need not populate bodytext here.
       
  5871 	// Body text will be retrieved and stored when StoreBodyL is called .
       
  5872 	if(isPlainText)
       
  5873 		{
       
  5874 		TRequestStatus* myStatus=&iStatus;
       
  5875 		iStatus=KRequestPending;
       
  5876 		User::RequestComplete(myStatus,KErrNone);	
       
  5877 		}
       
  5878 	else
       
  5879 		{
       
  5880 		iEmailMessage->GetBodyTextL(iStatus, iOrigMessageId, CImEmailMessage::EThisMessageOnly, *iRichText, *iParaLayer, *iCharLayer);
       
  5881 		}
       
  5882 	
       
  5883 	
       
  5884 	}
       
  5885 
       
  5886 TInt CImEmailOperation::RemoveIncompleteAttachments()
       
  5887 	{
       
  5888 	TInt completeAttachmentCount = 0;
       
  5889 	while (completeAttachmentCount < iAttachmentInfoList.Count())
       
  5890 		{
       
  5891 		if (!(iAttachmentInfoList[completeAttachmentCount]->Complete()))
       
  5892 			{
       
  5893 			delete iAttachmentInfoList[completeAttachmentCount];
       
  5894 			iAttachmentInfoList.Remove(completeAttachmentCount);
       
  5895 			}
       
  5896 		else
       
  5897 			++completeAttachmentCount;
       
  5898 		}
       
  5899 	return iAttachmentInfoList.Count();	
       
  5900 	}
       
  5901 
       
  5902 void CImEmailOperation::CreateEntryDetails(TMsvEmailEntry& entry)
       
  5903 	{
       
  5904 	entry.iMtm = iMsgType;
       
  5905 	entry.iServiceId = ServiceId();
       
  5906 	entry.iType = KUidMsvMessageEntry;
       
  5907 	entry.iDate.UniversalTime();
       
  5908 	if ((iOperation != ENew) && (iPartList & KMsvMessagePartAttachments))
       
  5909 		iTotalAttachments = RemoveIncompleteAttachments();
       
  5910 	entry.SetNew(ETrue);
       
  5911 	if (iEmbeddedMessagesToProcess!=0)
       
  5912 		entry.SetAttachment(ETrue);
       
  5913 	entry.SetVisible(!(iMsvEmailTypeList & KMsvEmailTypeListInvisibleMessage));
       
  5914 	entry.SetMHTMLEmail(iCreateHtmlMessage);
       
  5915 	entry.SetInPreparation(iMsvEmailTypeList & KMsvEmailTypeListMessageInPreparation);
       
  5916 	}
       
  5917 
       
  5918 void CImEmailOperation::CreateNewMessageL(TMsvId aDestinationId)
       
  5919 	{
       
  5920 	//	Create a new message so that the different sections can be added to it:
       
  5921 	iMsvEntry->SetEntryL(aDestinationId);
       
  5922 	delete iMsvOperation;
       
  5923 	iMsvOperation = NULL;
       
  5924 	TMsvEmailEntry entry;
       
  5925 	CreateEntryDetails(entry);
       
  5926 	iMsvOperation = iMsvEntry->CreateL(entry, iStatus);
       
  5927 	}
       
  5928 
       
  5929 TBool CImEmailOperation::NeedMultipartMixedFolder() const
       
  5930 	{
       
  5931 	if( (iPartList & KMsvMessagePartAttachments && (iTotalAttachments > 0)) &&
       
  5932 		(iPartList & KMsvMessagePartBody || iSignatureText || iCreateHtmlMessage || iOperation & EAttachOriginal) )
       
  5933 		{
       
  5934 		// In this case the operation is attaching 1 or more attachments. As there
       
  5935 		// is either message body (signature text implies) or at least another
       
  5936 		// attachment (HTML body or the original message) then a mixed folder is
       
  5937 		// needed.
       
  5938 		return ETrue;
       
  5939 		}
       
  5940 
       
  5941 	if( iPartList & KMsvMessagePartAttachments && (iTotalAttachments > 0) )
       
  5942 		{
       
  5943 		// If this case is reached then although the message body is not required
       
  5944 		// but it has attachment/s a mixed folder is needed.
       
  5945 		return ETrue;
       
  5946 		}
       
  5947 
       
  5948 	if( iOperation & EAttachOriginal && iPartList & KMsvMessagePartBody )
       
  5949 		{
       
  5950 		// In this case the operation was attaching the original message as an 
       
  5951 		// attachment (e.g ForwardAsAttachment). As the message body is required
       
  5952 		// then mixed folder needed.
       
  5953 		return ETrue;
       
  5954 		}
       
  5955 
       
  5956 	if( (iNeedToAddVCardAttachment || iHtmlNoTextAlt || iEmbeddedMessagesToProcess) && 
       
  5957 		(iPartList & KMsvMessagePartBody || iPartList & KMsvMessagePartAttachments))
       
  5958 		{
       
  5959 		// A V-card is required or the body text is added as an attachment or 
       
  5960 		// there are embedded messages to attach - all imply an attachment of
       
  5961 		// some description. As the message body or the attachments are required
       
  5962 		// then a mixed folder is needed.
       
  5963 		return ETrue;
       
  5964 		}
       
  5965 	
       
  5966 	if( iNeedToAddVCardAttachment )
       
  5967 		{
       
  5968 		//  Now this case is probably not needed - added here because a text 
       
  5969 		// entry is always added. Therefore if defect sorted so that text entry
       
  5970 		// onlu added when required this case can be removed.
       
  5971 		return ETrue;
       
  5972 		}
       
  5973 
       
  5974 	// Got here therefore no mixed folder needed.
       
  5975 	return EFalse;
       
  5976 	}
       
  5977 
       
  5978 void CImEmailOperation::CreateMultipartMixedFolderEntryL()
       
  5979 	{
       
  5980 	iMsvEntry->SetEntryL(iNewMessageId);
       
  5981 	TMsvEmailEntry entry;
       
  5982 	entry.iType = KUidMsvFolderEntry;
       
  5983 	entry.iMtm = iMsvEntry->Entry().iMtm;
       
  5984 	entry.iServiceId = iMsvEntry->Entry().iServiceId;
       
  5985 	entry.SetMessageFolderType(EFolderTypeMixed);
       
  5986 	entry.iSize = 0;
       
  5987 	delete iMsvOperation;
       
  5988 	iMsvOperation = NULL;
       
  5989 	iMsvOperation = iMsvEntry->CreateL(entry, iStatus);
       
  5990 	}
       
  5991 
       
  5992 void CImEmailOperation::CreateTextEntryL(TMsvId aFolderId)
       
  5993 	{
       
  5994 	iMsvEntry->SetEntryL(aFolderId);
       
  5995 	TMsvEntry entry;
       
  5996 	entry.iType = KUidMsvEmailTextEntry;
       
  5997 	entry.iMtm = iMsvEntry->Entry().iMtm;
       
  5998 	entry.iServiceId = ServiceId();
       
  5999 	entry.iDate.UniversalTime();
       
  6000 	entry.iSize = 0;
       
  6001 	delete iMsvOperation;
       
  6002 	iMsvOperation=NULL;
       
  6003 	iMsvOperation=iMsvEntry->CreateL(entry, iStatus);
       
  6004 	}
       
  6005 
       
  6006 void CImEmailOperation::StoreBodyL()
       
  6007 	{
       
  6008 	if(iUsePlainTextStorage)
       
  6009 		{
       
  6010 		StorePlainBodyL();
       
  6011 		return;
       
  6012 		}
       
  6013 	iMsvEntry->SetEntryL(iTextId);	//pointing to the text entry
       
  6014 	CMsvStore* store = iMsvEntry->EditStoreL();
       
  6015 	CleanupStack::PushL(store);
       
  6016 	
       
  6017 	store->StoreBodyTextL(*iRichText);
       
  6018 	store->CommitL();
       
  6019 	
       
  6020 	CleanupStack::PopAndDestroy(store);	
       
  6021 	// update size of text entry
       
  6022 	TMsvEmailEntry entry(iMsvEntry->Entry());
       
  6023 
       
  6024 	// DocumentLength() gives no. of chars and since unicode, multiply by 2
       
  6025 	entry.iSize = (iRichText->DocumentLength() * 2);	
       
  6026 	entry.iDate.UniversalTime();
       
  6027 	
       
  6028 	delete iMsvOperation;
       
  6029 	iMsvOperation = NULL;
       
  6030 	iMsvOperation = iMsvEntry->ChangeL(entry, iStatus);	
       
  6031 	}
       
  6032 
       
  6033 
       
  6034 void CImEmailOperation::StorePlainBodyL()
       
  6035 	{
       
  6036 	TUint charset = 0;
       
  6037 	TUint defaultCharset = 0;
       
  6038 	TBool override = EFalse;
       
  6039 	
       
  6040 	RFs& fileSvrSession = iMsvSession.FileSession();
       
  6041 	CCnvCharacterSetConverter* characterConverter = CCnvCharacterSetConverter::NewL();
       
  6042 	CleanupStack::PushL(characterConverter);
       
  6043 	
       
  6044 	CImConvertCharconv* charConv = CImConvertCharconv::NewL(*characterConverter, fileSvrSession);
       
  6045 	CleanupStack::PushL(charConv);
       
  6046 	defaultCharset = charConv->SystemDefaultCharset();
       
  6047 	CleanupStack::PopAndDestroy(2);
       
  6048 	
       
  6049 	
       
  6050 	// To store the ids of all the text part of a email message.
       
  6051 	RArray<TMsvId> textIdArray;
       
  6052 	CleanupClosePushL (textIdArray);
       
  6053 	
       
  6054 	RPointerArray<CMsvPlainBodyText> plainTextArray;
       
  6055 	TCleanupItem closePlainTextArray (CImEmailOperation::ClosePlainBodyTextArray, &plainTextArray);
       
  6056 	CleanupStack::PushL(closePlainTextArray);
       
  6057 	TInt origSize = 0;
       
  6058 	
       
  6059 	// Chunk storage mechanism is used and we are doing a replyto OR fwding a mail then 
       
  6060 	// get the size of the message.
       
  6061 	if(iOperation == EForward || iOperation == EReply)
       
  6062 		{
       
  6063 		iEmailMessage->GetCharacterSetL(iOrigMessageId,charset,override);
       
  6064 		
       
  6065 		iEmailMessage->GetBodyTextEntryIdL(iOrigMessageId,CImEmailMessage::EThisMessageOnly);
       
  6066 		TInt count = iEmailMessage->Selection().Count();
       
  6067 		for(TInt i=0; i<count; ++i)
       
  6068 			{
       
  6069 			User::LeaveIfError (textIdArray.Append( iEmailMessage->Selection().At(i) ));
       
  6070 			}
       
  6071 		TInt textIdCount = 	textIdArray.Count();
       
  6072 		for(TInt i=0; i<textIdCount; ++i)
       
  6073 			{
       
  6074 			// Pointing to the text entry.
       
  6075 			iMsvEntry->SetEntryL(textIdArray[i]);	
       
  6076 			CMsvStore* bodyTextStore = iMsvEntry->ReadStoreL();
       
  6077 			CleanupStack::PushL(bodyTextStore);
       
  6078 		
       
  6079 			plainTextArray.Append( bodyTextStore->InitialisePlainBodyTextForReadL(KMsvDecodeChunkLength));
       
  6080 			origSize += plainTextArray[i]->Size();
       
  6081 				
       
  6082 			CleanupStack::PopAndDestroy(bodyTextStore);
       
  6083 			bodyTextStore = NULL;
       
  6084 			}
       
  6085 		}
       
  6086 	
       
  6087 	iMsvEntry->SetEntryL(iTextId);	//pointing to the text entry
       
  6088 	
       
  6089 	CMsvStore* bodyTextStore = iMsvEntry->EditStoreL();
       
  6090 	CleanupStack::PushL(bodyTextStore);
       
  6091 	
       
  6092 	// If chunk storage mechanism is used then get CMsvPlainBodyText.
       
  6093 	// Body text is stored as 16 bit so set iIs8Bit to EFalse.When a message is created from
       
  6094 	// the client side data is stored as 16 bit.
       
  6095 	CMsvPlainBodyText* text = bodyTextStore->InitialisePlainBodyTextForWriteL(EFalse,charset,defaultCharset);	
       
  6096 	CleanupStack::PushL(text);
       
  6097 	
       
  6098 	// Add signature if it exists.
       
  6099 	if(iSignatureText)
       
  6100 		{
       
  6101 		TInt len = iSignatureText->DocumentLength();
       
  6102 		HBufC16* signatureText = HBufC16::NewLC(len);
       
  6103 		TPtr signatureTextPtr = signatureText->Des();
       
  6104 		iSignatureText->Extract(signatureTextPtr, 0, len);
       
  6105 		text->StoreChunkL(signatureTextPtr);
       
  6106 		CleanupStack::PopAndDestroy(signatureText);
       
  6107 		}
       
  6108 	
       
  6109 	if(iBodyHeader)
       
  6110 		{
       
  6111 		if(iOperation == EForward || iOperation == EReply)
       
  6112 			{
       
  6113 			text->StoreChunkL(iBodyHeader->Des());
       
  6114 			}
       
  6115 		}
       
  6116 			
       
  6117 	// If email is Fwd'ed or ReplyTo then need to read from the existing mail and add it to
       
  6118 	// the newly created mail since this was not done in GetBodyTextL.
       
  6119 	TInt plainTextCount = plainTextArray.Count();
       
  6120 	for(TInt i=0; i<plainTextCount; ++i)
       
  6121 		{
       
  6122 		TInt size = plainTextArray[i]->Size();
       
  6123 		while( size > 0)
       
  6124 			{
       
  6125 			TBuf <KMsvDecodeChunkLength> buf;
       
  6126 			plainTextArray[i]->NextChunkL(buf);
       
  6127 			text->StoreChunkL(buf);
       
  6128 			size -= KMsvDecodeChunkLength;
       
  6129 			}	
       
  6130 		delete plainTextArray[i];
       
  6131 		plainTextArray[i] = NULL;
       
  6132 		}
       
  6133 	text->CommitL();
       
  6134 	CleanupStack::PopAndDestroy(4, &textIdArray);// text, bodyTextStore, plainTextArray
       
  6135 	
       
  6136 	TMsvEmailEntry entry(iMsvEntry->Entry());
       
  6137 
       
  6138 	entry.iSize = origSize;	
       
  6139 	entry.iDate.UniversalTime();
       
  6140 	
       
  6141 	delete iMsvOperation;
       
  6142 	iMsvOperation = NULL;
       
  6143 	iMsvOperation = iMsvEntry->ChangeL(entry, iStatus);	
       
  6144 	}
       
  6145 
       
  6146 
       
  6147 void CImEmailOperation::CheckForSignatureOrVCardL()
       
  6148    	{
       
  6149    	if (!iSmtpServiceId || iSmtpServiceId==KMsvUnknownServiceIndexEntryId)
       
  6150    		return; // No smtp service set.
       
  6151    
       
  6152 	if( iSmtpSettings->AddVCardToEmail() )
       
  6153    		{
       
  6154 		CContactDatabase* db = NULL;
       
  6155    		// check whether the actual VCard exists
       
  6156 		TRAPD(error, db = CContactDatabase::OpenL());
       
  6157 		if( error == KErrNone )
       
  6158 			{
       
  6159 			CleanupStack::PushL(db);
       
  6160 			TContactItemId contactId = db->OwnCardId();
       
  6161 			if( contactId != KNullContactId )
       
  6162 				iNeedToAddVCardAttachment = ETrue;
       
  6163 			CleanupStack::PopAndDestroy(db);
       
  6164 			}
       
  6165 		else
       
  6166 			{
       
  6167 			if( db )
       
  6168 				delete db;
       
  6169 			}
       
  6170    		}
       
  6171    	
       
  6172 	if( iSmtpSettings->AddSignatureToEmail() )
       
  6173    		{
       
  6174 		// Check the SMTP settings entry for the signature text.
       
  6175 		iMsvEntry->SetEntryL(iSmtpServiceId);
       
  6176 		CMsvStore* store = iMsvEntry->ReadStoreL();
       
  6177 		CleanupStack::PushL(store);
       
  6178 
       
  6179 		if( store->IsPresentL(KMsvEntryRichTextBody) )
       
  6180 			{
       
  6181    			iSignatureText=CRichText::NewL(iParaLayer,iCharLayer);	
       
  6182    			store->RestoreBodyTextL(*iSignatureText);
       
  6183 			}
       
  6184 		CleanupStack::PopAndDestroy(store);
       
  6185    		}
       
  6186    	else
       
  6187    		iSignatureText=NULL;
       
  6188    	}
       
  6189 
       
  6190 void CImEmailOperation::CreateVCardAttachmentL()
       
  6191 	{
       
  6192 	// Get the vcard from contact database, need owncard entry..
       
  6193 
       
  6194 	CContactDatabase* db = CContactDatabase::OpenL();
       
  6195 	CleanupStack::PushL(db);
       
  6196 	TContactItemId contactId = db->OwnCardId();
       
  6197 	CContactIdArray *ids=CContactIdArray::NewLC();
       
  6198 	ids->AddL(contactId);
       
  6199 	if(contactId == KNullContactId)
       
  6200 		{
       
  6201 		CleanupStack::PopAndDestroy(2); // db, ids
       
  6202 		RequestComplete(KErrNone);
       
  6203 		return; // vcard not present, do nothing.
       
  6204 		}
       
  6205 	
       
  6206 	// Retrieve vcard to a temp store. 
       
  6207 
       
  6208 	TUid uid;
       
  6209 	uid.iUid=KUidVCardConvDefaultImpl;
       
  6210 
       
  6211 	delete iVcardStore;
       
  6212 	iVcardStore=NULL;
       
  6213 	iVcardStore=CBufStore::NewL(128);
       
  6214 	RStoreWriteStream tmpWrite;
       
  6215 	iVcardStoreId = tmpWrite.CreateLC(*iVcardStore);
       
  6216 
       
  6217 	db->ExportSelectedContactsL(uid,*ids, tmpWrite, CContactDatabase::ETTFormat);
       
  6218 	tmpWrite.CommitL();
       
  6219 	iVcardStore->CommitL();
       
  6220 
       
  6221 	// create attachment CMsvEntry entry
       
  6222 	TBuf<KVCardFilenameLength> textDef;
       
  6223 	CContactTextDef* contactTextDef = CContactTextDef::NewLC();
       
  6224 	TLanguage language = User::Language();
       
  6225 	if( language == ELangTaiwanChinese || 
       
  6226 		language == ELangHongKongChinese || 
       
  6227 		language == ELangPrcChinese )
       
  6228 		{
       
  6229 		contactTextDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
       
  6230 		contactTextDef->AppendL(TContactTextDefItem(KUidContactFieldGivenName));
       
  6231 		}
       
  6232 	else
       
  6233 		{
       
  6234 		contactTextDef->AppendL(TContactTextDefItem(KUidContactFieldGivenName));
       
  6235 		contactTextDef->AppendL(TContactTextDefItem(KUidContactFieldFamilyName));
       
  6236 		}
       
  6237 	contactTextDef->SetExactMatchOnly(ETrue);
       
  6238 	db->ReadContactTextDefL(contactId,textDef,contactTextDef);
       
  6239 	CleanupStack::PopAndDestroy(contactTextDef);
       
  6240 	if (textDef.Length())
       
  6241 		iFileName.Copy(textDef);
       
  6242 	else
       
  6243 		iFileName.Copy(*iDefaultVCardNameFormatString);
       
  6244 	iFileName.Append(KMimeVCardExtension);
       
  6245 
       
  6246 	if (iMultipartMixedFolderCreated)
       
  6247 		iMsvEntry->SetEntryL(iMultipartMixedId);
       
  6248 	else 
       
  6249 		iMsvEntry->SetEntryL(iNewMessageId);
       
  6250 	CleanupStack::PopAndDestroy(3); // db, ids, tmpWrite,
       
  6251 
       
  6252 	CreateAttachmentEntryL(); //Async
       
  6253 	}
       
  6254 
       
  6255 void CImEmailOperation::AddVCardAttachmentL()
       
  6256 	{
       
  6257 	iMsvEntry->SetEntryL(iVcardId);
       
  6258 	if (!iFileName.Length())
       
  6259 		{
       
  6260 		RequestComplete(KErrNone);
       
  6261 		return; // ergo no attachment.
       
  6262 		}
       
  6263 
       
  6264 	// Put vcard into a file.
       
  6265 	TFileName filePath;
       
  6266 	CMsvStore* store = iMsvEntry->EditStoreL();
       
  6267 	CleanupStack::PushL(store);
       
  6268 		
       
  6269 	MMsvAttachmentManagerSync& attachmentMgrSync = store->AttachmentManagerExtensionsL();
       
  6270 	CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
  6271 	RFile file;
       
  6272 	attachmentMgrSync.CreateAttachmentL(iFileName,file,attachment);
       
  6273 	store->CommitL();
       
  6274 	CleanupStack::PopAndDestroy(store);
       
  6275 	
       
  6276 	// set the file attachment file handle with write mode
       
  6277 	iAttachmentFile.SetFileHandle(file,TImAttachmentFile::EImFileWrite);
       
  6278 	RStoreReadStream dummy;
       
  6279 	dummy.OpenLC(*iVcardStore,iVcardStoreId);
       
  6280 	TInt size = (dummy.Source()->SizeL());
       
  6281 	
       
  6282 	HBufC8* textBuffer=HBufC8::NewLC(size);
       
  6283 	TPtr8 bufPtr=textBuffer->Des();
       
  6284 	dummy.ReadL(bufPtr,size);
       
  6285 	iAttachmentFile.WriteFile(bufPtr);
       
  6286 	iAttachmentFile.CloseFile();
       
  6287 
       
  6288 	delete iVcardStore;
       
  6289 	iVcardStore=NULL;
       
  6290 	CleanupStack::PopAndDestroy(2); // dummy, textBuffer
       
  6291 
       
  6292 	iMsvEntry->SetEntryL(iVcardId);
       
  6293 	TMsvEmailEntry entry = iMsvEntry->Entry();
       
  6294 	entry.iSize = size;
       
  6295 	entry.iDetails.Set(iFileName);
       
  6296 	entry.SetVCard(ETrue);
       
  6297 	iVCardAndHtmlSize+=entry.iSize;
       
  6298 
       
  6299 	delete iMsvOperation;
       
  6300 	iMsvOperation=NULL;
       
  6301 	iMsvOperation=iMsvEntry->ChangeL(entry, iStatus);
       
  6302 	}
       
  6303 
       
  6304 void CImEmailOperation::CreateAttachmentEntryL()
       
  6305 	{
       
  6306 	if (iMultipartMixedFolderCreated)
       
  6307 		iMsvEntry->SetEntryL(iMultipartMixedId);
       
  6308 	else 
       
  6309 		iMsvEntry->SetEntryL(iNewMessageId);
       
  6310 
       
  6311 	// create the index entry
       
  6312 	TMsvEntry entry;
       
  6313 	entry.iMtm = iMsgType;
       
  6314 	entry.iServiceId = ServiceId();
       
  6315 	entry.iType = KUidMsvAttachmentEntry;
       
  6316 	entry.iDate.UniversalTime();
       
  6317 	entry.SetAttachment(ETrue);
       
  6318 
       
  6319 	if (iAttachmentInfoList.Count())
       
  6320 		{
       
  6321 		// set the size and attachment name of the entry
       
  6322 		CMsvAttachment* attachment = iAttachmentInfoList[iAttachmentCount];
       
  6323 		entry.iSize = iAttachmentInfoList[iAttachmentCount]->Size();
       
  6324 		if(iAttachmentInfoList[iAttachmentCount]->AttachmentName().Length() == 0)
       
  6325 			{
       
  6326 			TParse parseFile;
       
  6327 			parseFile.Set(iAttachmentInfoList[iAttachmentCount]->FilePath(),NULL,NULL);
       
  6328 			entry.iDetails.Set(parseFile.NameAndExt());
       
  6329 			}
       
  6330 		else 
       
  6331 			{
       
  6332 			entry.iDetails.Set(iAttachmentInfoList[iAttachmentCount]->AttachmentName());
       
  6333 			}	
       
  6334 		}
       
  6335 	delete iMsvOperation;
       
  6336 	iMsvOperation = NULL;
       
  6337 	iMsvOperation = iMsvEntry->CreateL(entry, iStatus);
       
  6338 	}
       
  6339 
       
  6340 void CImEmailOperation::StoreAttachmentL()
       
  6341 	{
       
  6342 	RFile origAttachmentFile;
       
  6343 	if (iAttachmentInfoList[iAttachmentCount]->Type() == CMsvAttachment::EMsvFile)
       
  6344 		{
       
  6345 		// Need to get a file handle for the original attachment.
       
  6346 		TMsvId origAttachId = iAttachmentInfoList[iAttachmentCount]->Id();
       
  6347 		iMsvEntry->SetEntryL(origAttachId);
       
  6348 		CMsvStore* store = iMsvEntry->ReadStoreL();
       
  6349 		CleanupStack::PushL(store);
       
  6350 		MMsvAttachmentManager& origAttachmentMgr = store->AttachmentManagerL();
       
  6351 
       
  6352 		// This is an email attachment entry, so it only has one attachment per entry
       
  6353 		origAttachmentFile = origAttachmentMgr.GetAttachmentFileL(0);
       
  6354 		CleanupStack::PopAndDestroy(store);
       
  6355 		CleanupClosePushL(origAttachmentFile);
       
  6356 		}
       
  6357 
       
  6358 	TMsvId msvId = McliUtils::GetProgressIdL(*iMsvOperation);
       
  6359 	iMsvEntry->SetEntryL(msvId);//pointing to the attachment
       
  6360 	iStore = iMsvEntry->EditStoreL();
       
  6361 
       
  6362 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  6363 	// Reset the Id to 1, email attachments have one entry 
       
  6364 	iAttachmentInfoList[iAttachmentCount]->SetId(1);
       
  6365 	CMsvAttachment* attachment = CMsvAttachment::NewL(*iAttachmentInfoList[iAttachmentCount]);
       
  6366 
       
  6367 	CleanupStack::PushL(attachment);
       
  6368 
       
  6369  	if(attachment->Type() == CMsvAttachment::EMsvFile)
       
  6370  		{
       
  6371 		attachmentMgr.AddAttachmentL(origAttachmentFile, attachment, iStatus);
       
  6372 		CleanupStack::Pop(2, &origAttachmentFile);   // attachment, origAttachmentFile
       
  6373  		}
       
  6374  	else if(attachment->Type() == CMsvAttachment::EMsvLinkedFile)
       
  6375  		{
       
  6376  		attachmentMgr.AddLinkedAttachmentL(attachment->FilePath(), attachment, iStatus);
       
  6377  		CleanupStack::Pop(attachment);
       
  6378  		}
       
  6379  	else if(attachment->Type() == CMsvAttachment::EMsvMessageEntry)
       
  6380  		{
       
  6381  		attachmentMgr.AddEntryAsAttachmentL(attachment->EntryAttachmentId(), attachment, iStatus);
       
  6382  		CleanupStack::Pop(attachment);
       
  6383  		}
       
  6384  	else
       
  6385  		{
       
  6386  		// If we have hit this line then a new attachment type has been added
       
  6387  		// so this function will need to be updated.
       
  6388  		__ASSERT_DEBUG(0, gPanic(EImEmailOpUnknownAttachmentType));
       
  6389  		}
       
  6390 	}
       
  6391 
       
  6392 void CImEmailOperation::AddMessageAsAttachmentL()
       
  6393 	{
       
  6394 	TMsvId serviceId;
       
  6395 	TMsvEmailEntry entry;
       
  6396 
       
  6397 	iMsvEntry->Session().GetEntry(iEmailMessage->Selection()[--iEmbeddedMessagesToProcess], serviceId, entry);
       
  6398 	iMsvEntry->SetEntryL(entry.Parent());
       
  6399 
       
  6400 	delete iMsvOperation;
       
  6401 	iMsvOperation = NULL;
       
  6402 	if (iMultipartMixedFolderCreated)
       
  6403 		iMsvOperation = iMsvEntry->CopyL(iEmailMessage->Selection()[iEmbeddedMessagesToProcess], iMultipartMixedId, iStatus);
       
  6404 	else 
       
  6405 		iMsvOperation = iMsvEntry->CopyL(iEmailMessage->Selection()[iEmbeddedMessagesToProcess], iNewMessageId, iStatus);
       
  6406 	}
       
  6407 
       
  6408 void CImEmailOperation::CreateMultipartAlternativeFolderEntryL()
       
  6409 	{
       
  6410 	if (iMultipartMixedFolderCreated)
       
  6411 		iMsvEntry->SetEntryL(iMultipartMixedId);
       
  6412 	else 
       
  6413 		iMsvEntry->SetEntryL(iNewMessageId);
       
  6414 
       
  6415 	TMsvEmailEntry entry;
       
  6416 	entry.iType = KUidMsvFolderEntry;
       
  6417 	entry.iMtm = iMsvEntry->Entry().iMtm;
       
  6418 	entry.iServiceId = iMsvEntry->Entry().iServiceId;
       
  6419 	entry.SetMessageFolderType(EFolderTypeAlternative);
       
  6420 	entry.iSize = 0;
       
  6421 
       
  6422 	delete iMsvOperation;
       
  6423 	iMsvOperation = NULL;
       
  6424 	iMsvOperation = iMsvEntry->CreateL(entry, iStatus);
       
  6425 	}
       
  6426 
       
  6427 void CImEmailOperation::AppendHtmlAttachmentL()
       
  6428 	{
       
  6429 	TBool copyHtml = EFalse;
       
  6430 	HBufC* temp = NULL;
       
  6431 	temp = iEmailMessage->GetUniversalResourceIdentifierL(iHtmlId, copyHtml);
       
  6432 	delete temp;
       
  6433 	temp = NULL;
       
  6434 	if (copyHtml)
       
  6435 		{
       
  6436 		iMsvEntry->SetEntryL(iHtmlId);
       
  6437 		TMsvEmailEntry entry(iMsvEntry->Entry());
       
  6438 			CMsvStore* store = iMsvEntry->ReadStoreL();
       
  6439 			CleanupStack::PushL(store);
       
  6440 			MMsvAttachmentManager& attachmentMgr = store->AttachmentManagerL();
       
  6441 			if(attachmentMgr.AttachmentCount())
       
  6442 				{
       
  6443 				// as this is email attachment entry , it has one attachment per entry
       
  6444 				CMsvAttachment* attachment = attachmentMgr.GetAttachmentInfoL(0);
       
  6445 				CleanupStack::PushL(attachment);
       
  6446 				
       
  6447 				attachment->SetSize(entry.iSize);
       
  6448 				attachment->SetComplete(entry.Complete());
       
  6449 				// def070915 - propagated fix
       
  6450 				attachment->SetId(iHtmlId);
       
  6451 				CleanupStack::Pop(attachment);
       
  6452 				iAttachmentInfoList.Append(attachment);
       
  6453 				++iTotalAttachments;
       
  6454 				iPartList=iPartList|KMsvMessagePartAttachments;
       
  6455 				}
       
  6456 			CleanupStack::PopAndDestroy(store);	
       
  6457 		}
       
  6458 	RequestComplete(KErrNone);
       
  6459 	}
       
  6460 
       
  6461 /**
       
  6462 Creates another CImEmailOperation object that creates a copy of the original
       
  6463 message as an attachment to this message.
       
  6464 
       
  6465 The partlist supplied to the current CImEmailOperation is passed to the new one
       
  6466 but ensuring that the orginator and recipient lists are included in the copy.
       
  6467 
       
  6468 The copied message is attached as a child of the Multipart Mixed folder entry if
       
  6469 it exists or as a child of this message's message entry.
       
  6470 */
       
  6471 void CImEmailOperation::AttachOriginalMessageToNewMessageL()
       
  6472 	{
       
  6473 	TMsvPartList partList = iPartList | KMsvMessagePartRecipient | KMsvMessagePartOriginator;
       
  6474 
       
  6475 	TInt typeList = 0;
       
  6476 	if( iOrigMessageHtml )
       
  6477 		typeList |= KMsvEmailTypeListMHTMLMessage;
       
  6478 
       
  6479 	delete iMsvOperation;
       
  6480 	iMsvOperation = NULL;
       
  6481 	if( iMultipartMixedFolderCreated )
       
  6482 		iMsvOperation = CImEmailOperation::CreateCopyL(iStatus, iMsvSession, iOrigMessageId, iMultipartMixedId, partList, typeList, iMsgType);
       
  6483 	else 
       
  6484 		iMsvOperation = CImEmailOperation::CreateCopyL(iStatus, iMsvSession, iOrigMessageId, iNewMessageId, partList, typeList, iMsgType);
       
  6485 	}
       
  6486 
       
  6487 void CImEmailOperation::CompleteEmailOperationL()
       
  6488 	{
       
  6489 	//	1.	Set the Details (and Description if applicable)
       
  6490 	//	2.	Set the Size = Size of Header + Size of Body + Size of Attachments
       
  6491 	
       
  6492 	iMsvEntry->SetEntryL(iNewMessageId);	//pointing to the message
       
  6493 	TMsvEmailEntry entry(iMsvEntry->Entry());
       
  6494 
       
  6495 	// Set the service id and the related id if the message we have created is a PCMail
       
  6496 	// Note that this only needs to be done for Reply as otherwise we don't know the service.
       
  6497 	// The service id will already be set for New and Forward PCMails if the service id was passed
       
  6498 	// into the Constructor.
       
  6499 	if( iMsgType == KUidMsgTypePCMail )
       
  6500 		entry.iServiceId = entry.iRelatedId = ServiceId();
       
  6501 
       
  6502 	// if there are multiple recipients then set the flag
       
  6503 	if( (iNewHeader->ToRecipients().Count() + iNewHeader->CcRecipients().Count() + iNewHeader->BccRecipients().Count()) > 1 )
       
  6504 		entry.SetMultipleRecipients(ETrue);
       
  6505 
       
  6506 	if( iNewHeader->ToRecipients().Count() )
       
  6507 		entry.iDetails.Set(iNewHeader->ToRecipients()[0]);
       
  6508 	else if( iNewHeader->CcRecipients().Count() )
       
  6509 		entry.iDetails.Set(iNewHeader->CcRecipients()[0]);
       
  6510 	else if( iNewHeader->BccRecipients().Count() )
       
  6511 		entry.iDetails.Set(iNewHeader->BccRecipients()[0]);
       
  6512 	//else do nothing as there are no recipients yet!
       
  6513 
       
  6514 	entry.iDescription.Set(iNewHeader->Subject());
       
  6515 	entry.iDate.UniversalTime();
       
  6516 	
       
  6517 	TInt sizeOfHeader = iNewHeader->DataSize();
       
  6518 	
       
  6519 	// only add the size of the rich text if the body is required or a signature has been added
       
  6520 	// as otherwise it is not added
       
  6521 	TInt sizeOfBody = 0;
       
  6522 	if( iSignatureText || (iPartList & KMsvMessagePartBody) )
       
  6523 		{
       
  6524 		if(iUsePlainTextStorage)
       
  6525 			{
       
  6526 			iEmailMessage->GetBodyTextEntryIdL(iNewMessageId,CImEmailMessage::EThisMessageOnly);
       
  6527 			sizeOfBody = GetPlainBodyTextSizeL();
       
  6528 			iMsvEntry->SetEntryL(iNewMessageId);
       
  6529 			}
       
  6530 		else
       
  6531 			{
       
  6532 			// DocumentLength() gives no. of chars and since unicode we multiply by 2
       
  6533 			sizeOfBody = (iRichText->DocumentLength() * 2);
       
  6534 			}
       
  6535 			
       
  6536 		}
       
  6537 	
       
  6538 	TInt sizeOfAttachments = 0;
       
  6539 	if( (iOperation != ENew) && (iPartList & KMsvMessagePartAttachments) )
       
  6540 		{
       
  6541 		for( TInt i=0; i<iTotalAttachments; ++i )
       
  6542 			{
       
  6543 			sizeOfAttachments += iAttachmentInfoList[i]->Size();
       
  6544 			}
       
  6545 		}
       
  6546 
       
  6547 	TInt sizeOfAttachedMessage = 0;
       
  6548 	if( iOperation & EAttachOriginal )
       
  6549 		{
       
  6550 		TMsvId serviceId;
       
  6551 		TMsvEmailEntry attachedMessageEntry;
       
  6552 		iMsvEntry->Session().GetEntry(iAttachedMessageId, serviceId, attachedMessageEntry);
       
  6553 		sizeOfAttachedMessage = attachedMessageEntry.iSize;
       
  6554 		}
       
  6555 
       
  6556 	entry.iSize = sizeOfHeader + sizeOfBody + sizeOfAttachments + sizeOfAttachedMessage + iVCardAndHtmlSize;
       
  6557 
       
  6558 	// For receipt messages set the sending state to KMsvSendStateWaiting as receipts can be sent
       
  6559 	// immediately
       
  6560 	// For all others messages, use the setting in the SMTP settings
       
  6561 	if( iOperation == EReceipt )
       
  6562 		entry.SetSendingState(KMsvSendStateWaiting);
       
  6563 	else if( iMsgType == KUidMsgTypeSMTP && iOperation != ECopy )
       
  6564 		{
       
  6565 		TUint sendState = 0;
       
  6566 		switch( iSmtpSettings->SendMessageOption() )
       
  6567 			{
       
  6568 		case ESendMessageImmediately: // No send state for this !!
       
  6569 		case ESendMessageOnNextConnection:
       
  6570 			sendState = KMsvSendStateWaiting;
       
  6571 			break;
       
  6572 		case ESendMessageOnRequest:
       
  6573 		default:
       
  6574 			sendState = KMsvSendStateUponRequest;
       
  6575 			break;
       
  6576 			}
       
  6577 		entry.SetSendingState(sendState);
       
  6578 		}
       
  6579 
       
  6580 	// If a VCard has been added then the attachment flag needs to be set
       
  6581 	if( iVcardId || (iTotalAttachments > 0) )
       
  6582 		{
       
  6583 		entry.SetAttachment(ETrue);
       
  6584 		}
       
  6585 
       
  6586 	if(iVcardId)
       
  6587 		{
       
  6588 		// The vcard is set on the actual email entry.
       
  6589 		entry.SetVCard(ETrue);
       
  6590 		}
       
  6591 
       
  6592 	if( iOperation != ECopy )
       
  6593 		{
       
  6594 		// Adding a receipt flag or adding body encoding to the header does not
       
  6595 		// apply to ECopy operations.
       
  6596 
       
  6597 		// Add receipt flag if required (check SMTP settings)
       
  6598 		if( (iMsgType == KUidMsgTypeSMTP) && (iOperation != EReceipt) && (iSmtpServiceId != KMsvUnknownServiceIndexEntryId) )
       
  6599 			{
       
  6600 			if( iSmtpSettings->RequestReceipts() )
       
  6601 				{
       
  6602 				if( iSmtpSettings->ReceiptAddress().Length() )
       
  6603 					iNewHeader->SetReceiptAddressL(iSmtpSettings->ReceiptAddress());
       
  6604 				else if( iSmtpSettings->ReplyToAddress().Length() )
       
  6605 					iNewHeader->SetReceiptAddressL(iSmtpSettings->ReplyToAddress());
       
  6606 				// else don't know who to send a receipt to - receipt will not be sent.
       
  6607 				
       
  6608 				if( iNewHeader->ReceiptAddress().Length() )
       
  6609 					entry.SetReceipt(ETrue);
       
  6610 				}
       
  6611 			}
       
  6612 
       
  6613 		// Store the body encoding in the header from the SMTP account settings
       
  6614 		// if the user is creating a plaintext message even though the settings
       
  6615 		// specify HTML message, the body encoding is set to EMsgOutboxMIME
       
  6616 		if( iCreateHtmlMessage )
       
  6617 			iNewHeader->SetBodyEncoding(EMsgOutboxMHTMLAlternativeAsMIME);
       
  6618 		else if( (iMsgType == KUidMsgTypeSMTP) || (iSmtpSettings->BodyEncoding() != EMsgOutboxMHTMLAlternativeAsMIME) )
       
  6619 			iNewHeader->SetBodyEncoding(iSmtpSettings->BodyEncoding());	
       
  6620 		else
       
  6621 			iNewHeader->SetBodyEncoding(EMsgOutboxMIME);
       
  6622 		}
       
  6623 
       
  6624 	CMsvStore* store = iMsvEntry->EditStoreL();
       
  6625 	CleanupStack::PushL(store);
       
  6626 	// store the header - this has not been done previously
       
  6627 	iNewHeader->StoreL(*store);
       
  6628 
       
  6629 	if( iMultipartMixedFolderCreated || iMultipartAlternativeFolderCreated )
       
  6630 		{
       
  6631 		CImMimeHeader* mimeHeader = CImMimeHeader::NewLC();
       
  6632 		mimeHeader->SetContentTypeL(KMimeMultipart);
       
  6633 		if( iMultipartMixedFolderCreated )
       
  6634 			mimeHeader->SetContentSubTypeL(KMimeMixed);
       
  6635 		else
       
  6636 			mimeHeader->SetContentSubTypeL(KMimeAlternative);
       
  6637 		mimeHeader->SetContentTransferEncodingL(KMimeQuotedPrintable);
       
  6638 		mimeHeader->StoreL(*store);
       
  6639 		entry.iSize += mimeHeader->Size();
       
  6640 		CleanupStack::PopAndDestroy(mimeHeader);
       
  6641 		}
       
  6642 	store->CommitL();
       
  6643 	CleanupStack::PopAndDestroy(store);
       
  6644 	delete iMsvOperation;
       
  6645 	iMsvOperation=NULL;
       
  6646 	iMsvOperation=iMsvEntry->ChangeL(entry, iStatus);
       
  6647 	}
       
  6648 
       
  6649 void CImEmailOperation::CreateHTMLEntryL()
       
  6650 	{
       
  6651 	iMsvEntry->SetEntryL(iMultipartAlternativeId);
       
  6652 
       
  6653 	TMsvEntry entry;
       
  6654 	entry.iServiceId = ServiceId();
       
  6655 	entry.iType = KUidMsvEmailHtmlEntry;
       
  6656 	entry.iMtm = iMsvEntry->Entry().iMtm;
       
  6657 	entry.iDate.UniversalTime();
       
  6658 	entry.iSize = 0;
       
  6659 
       
  6660 	delete iMsvOperation;
       
  6661 	iMsvOperation = NULL;
       
  6662 	iMsvOperation = iMsvEntry->CreateL(entry, iStatus);
       
  6663 	iHtmlId = iMsvEntry->Entry().Id();
       
  6664 	}
       
  6665 	
       
  6666 void CImEmailOperation::AddMessageAttachmentInfoL(TMsvId aAttachmentMessageId)
       
  6667 	{
       
  6668 	iMsvEntry->SetEntryL(aAttachmentMessageId);
       
  6669 	
       
  6670 	iStore = iMsvEntry->EditStoreL();
       
  6671 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  6672 
       
  6673 	CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvMessageEntry); 
       
  6674 	CleanupStack::PushL(attachment);
       
  6675 	attachmentMgr.AddEntryAsAttachmentL(aAttachmentMessageId,attachment,iStatus);
       
  6676 	CleanupStack::Pop(attachment);
       
  6677 	}
       
  6678 void CImEmailOperation::CreateDefaultAttachmentL()
       
  6679 	{
       
  6680 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  6681 	CMsvAttachment* attachment = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
       
  6682 	TFileName fileName;
       
  6683 	ReadDefaultHtmlAttachmentNameL(fileName);
       
  6684 	attachmentMgr.CreateAttachmentL(fileName,iFile,attachment,iStatus);
       
  6685 	}
       
  6686 
       
  6687 void CImEmailOperation::ReadDefaultHtmlAttachmentNameL(TDes& aFileName)
       
  6688 	{
       
  6689 	RResourceFile resourceFile;
       
  6690 	OpenResourceFileL(resourceFile, iMsvSession.FileSession());
       
  6691 	CleanupClosePushL(resourceFile);
       
  6692 	
       
  6693 	TResourceReader reader;
       
  6694 	HBufC8* buf = resourceFile.AllocReadLC( DEFAULT_ATTACHMENT_NAME );
       
  6695 	reader.SetBuffer(buf);
       
  6696 	
       
  6697 	TPtrC attachmentName = reader.ReadTPtrC();
       
  6698 	const TDesC& ext = KMimeHtmlExtension;
       
  6699 	HBufC* defaultAttachmentName = HBufC::NewL(attachmentName.Length() + ext.Length());
       
  6700 	CleanupStack::PushL(defaultAttachmentName);
       
  6701 
       
  6702 	defaultAttachmentName->Des().Copy(attachmentName);
       
  6703 	defaultAttachmentName->Des().Append(ext);
       
  6704 	aFileName.Append(*defaultAttachmentName);
       
  6705 
       
  6706 	CleanupStack::PopAndDestroy(3,&resourceFile ); //buf, defaultAttachmentName,resourceFile (Close resourceFile)
       
  6707 	}
       
  6708 	
       
  6709 void CImEmailOperation::ResetStoreL()	
       
  6710 	{
       
  6711 	iStore->CommitL();
       
  6712 	delete iStore;
       
  6713 	iStore = NULL;
       
  6714 	}
       
  6715 
       
  6716 /**
       
  6717 Method that will be called when object in RPointerArray<CMsvPlainBodyText> is deleted.
       
  6718 @param aPtr		Pointer to the RPointerArray.
       
  6719 @return void.
       
  6720 */
       
  6721 void CImEmailOperation::ClosePlainBodyTextArray( TAny* aPtr )
       
  6722 	{
       
  6723 	RPointerArray<CMsvPlainBodyText>* plainBodyTextArray = reinterpret_cast<RPointerArray<CMsvPlainBodyText>*> (aPtr);
       
  6724 	plainBodyTextArray->ResetAndDestroy();
       
  6725 	}
       
  6726 
       
  6727 /**
       
  6728 Return the size of the body text for a email message.
       
  6729 */
       
  6730 TInt CImEmailOperation::GetPlainBodyTextSizeL()
       
  6731 	{
       
  6732 	TInt count = iEmailMessage->Selection().Count();
       
  6733 	TInt sizeOfBody = 0;		
       
  6734 	for(TInt i=0; i< count ;++i)
       
  6735 		{
       
  6736 		iMsvEntry->SetEntryL(iEmailMessage->Selection().At(i));	//pointing to the text entry	
       
  6737 		CMsvStore* bodyTextStore = iMsvEntry->ReadStoreL();
       
  6738 		CleanupStack::PushL(bodyTextStore);
       
  6739 			
       
  6740 		CMsvPlainBodyText* plainBodyText = bodyTextStore->InitialisePlainBodyTextForReadL(KMaxChunkLength);
       
  6741 		sizeOfBody += plainBodyText->Size();
       
  6742 				
       
  6743 		delete plainBodyText;
       
  6744 		plainBodyText = NULL;
       
  6745 			
       
  6746 		CleanupStack::PopAndDestroy(bodyTextStore);
       
  6747 		bodyTextStore = NULL;
       
  6748 		}
       
  6749 	return 	sizeOfBody;
       
  6750 	}
       
  6751 	
       
  6752 void CImHtmlConverter::ResetStoreL()
       
  6753 	{
       
  6754 	if(iStore != NULL )
       
  6755 		{
       
  6756 		iStore->CommitL();
       
  6757 		delete iStore;
       
  6758 		iStore = NULL;
       
  6759 		}
       
  6760 	}
       
  6761 	
       
  6762  void CImHtmlConverter::ResetStoreWithoutCommit()
       
  6763  	{
       
  6764  	if (this != NULL)
       
  6765 	 	{
       
  6766 	 	if(iStore != NULL )
       
  6767 	 		{
       
  6768 	 		delete iStore;
       
  6769 	 		iStore = NULL;
       
  6770 	 		}	
       
  6771 	 	}
       
  6772   	}
       
  6773 
       
  6774 //-----------------------------------------------------------------
       
  6775 
       
  6776 //-----------------------------------------------------------------
       
  6777 
       
  6778 CImHtmlConverter* CImHtmlConverter::NewL(CMsvEntry& aMsvEntry, 
       
  6779 								   CParaFormatLayer& aParaLayer, CCharFormatLayer& aCharLayer)
       
  6780 	{
       
  6781 	CImHtmlConverter* self = new (ELeave) CImHtmlConverter(aMsvEntry, aParaLayer, aCharLayer);
       
  6782 	CleanupStack::PushL(self);
       
  6783 	self->ConstructL();
       
  6784 	CleanupStack::Pop();
       
  6785 	return self;
       
  6786 	}
       
  6787 
       
  6788 CImHtmlConverter::CImHtmlConverter(CMsvEntry& aMsvEntry, CParaFormatLayer& aParaLayer, CCharFormatLayer& aCharLayer)
       
  6789 :iMsvEntry(aMsvEntry), iParaLayer(aParaLayer), iCharLayer(aCharLayer)
       
  6790 {
       
  6791 }
       
  6792 
       
  6793 void CImHtmlConverter::ConstructL()
       
  6794 	{
       
  6795 	_LIT8(KHtmlInMimeType, "epoc32/crichtext");
       
  6796 	_LIT8(KHtmlOutMimeType, "text/html");
       
  6797 
       
  6798 	TDataType inMimeType(KHtmlInMimeType);
       
  6799 	TDataType outMimeType(KHtmlOutMimeType);
       
  6800 
       
  6801 	iConverterList = CCnaConverterList::NewL();
       
  6802 	iConverterList->UpdateL();
       
  6803 
       
  6804 	TUid uid = iConverterList->ConverterL(inMimeType, outMimeType);
       
  6805 
       
  6806 	iToHTMLConverter = iConverterList->NewConverterL(uid);
       
  6807 	User::LeaveIfNull(iToHTMLConverter);
       
  6808 	User::LeaveIfError(iToHTMLConverter->Capabilities() & CConverterBase::EConvertsFiles);
       
  6809 	}
       
  6810 
       
  6811 void CImHtmlConverter::PrepareToStoreHTMLEntryTextL (TMsvId& aHtmlId, const TMsvId aTextId)
       
  6812 	{
       
  6813 	// 0. Check html entry exists.
       
  6814 	if (!aHtmlId)
       
  6815 		{
       
  6816 		iMsvEntry.SetEntryL(iMsvEntry.Entry().Parent());	//pointing to the text entry
       
  6817 		if ( ((TMsvEmailEntry)iMsvEntry.Entry()).MessageFolderType() != EFolderTypeAlternative)
       
  6818 			return;
       
  6819 		TInt i = iMsvEntry.Count();
       
  6820 		while (i--)
       
  6821 			{
       
  6822 			if (aTextId!=iMsvEntry[i].Id())
       
  6823 				{
       
  6824 				aHtmlId=iMsvEntry[i].Id();
       
  6825 				break;
       
  6826 				}
       
  6827 			}
       
  6828 		}
       
  6829 
       
  6830 	if (aHtmlId <=0)
       
  6831 		return;
       
  6832 
       
  6833 	// 1. Create file containing Rich text.
       
  6834 
       
  6835 	iMsvEntry.SetEntryL(aTextId);	//pointing to the text entry
       
  6836 	TFileName filepath;
       
  6837 // Create the file with Rich text in non secure version 
       
  6838 
       
  6839 	CMsvStore* store=NULL;
       
  6840     TRAPD(err,store=iMsvEntry.ReadStoreL());
       
  6841  	if (err)
       
  6842 		{
       
  6843 		aHtmlId=0;
       
  6844 	    User::Leave(err);
       
  6845 		}
       
  6846 	CleanupStack::PushL(store);
       
  6847 
       
  6848 	if ( !store->IsPresentL(KMsvEntryRichTextBody) && !store->IsPresentL(KMsvPlainBodyText16) && !store->IsPresentL(KMsvPlainBodyText8))
       
  6849 		{
       
  6850 		aHtmlId=0;
       
  6851 		User::Leave(KErrNotFound); // Rich text not found
       
  6852 		}
       
  6853 
       
  6854 	CRichText* bodyText=CRichText::NewL(&iParaLayer,&iCharLayer);
       
  6855 	CleanupStack::PushL(bodyText);
       
  6856 	store->RestoreBodyTextL(*bodyText);
       
  6857 	
       
  6858 	if (bodyText->PictureCount())
       
  6859 		{
       
  6860 		RMsvReadStream in;
       
  6861 		in.OpenL(*store, KMsvEntryRichTextBody);
       
  6862 		CEmbeddedStore* embeddedStore = CEmbeddedStore::FromL(in);
       
  6863 	
       
  6864 		// Create store resolver
       
  6865 		CImStoreResolver* storeResolver = new(ELeave)CImStoreResolver(embeddedStore); // Takes ownership
       
  6866 		CleanupStack::PushL(storeResolver);
       
  6867 	
       
  6868 		// Set the picture factory
       
  6869 		__ASSERT_ALWAYS(CEikonEnv::Static(), gPanic(EImcmNoEikonEnvironment));
       
  6870 		MPictureFactory* factory = CEikonEnv::Static()->PictureFactory();
       
  6871 		bodyText->SetPictureFactory(factory, storeResolver);
       
  6872 		bodyText->DetachFromStoreL(CPicture::EDetachFull);
       
  6873 		CleanupStack::PopAndDestroy(storeResolver);
       
  6874 		}
       
  6875 	CleanupStack::Pop(bodyText);
       
  6876 	delete iRichText;
       
  6877 	iRichText = NULL;
       
  6878 	iRichText = bodyText;
       
  6879 	TPckgBuf<CRichText*> bufferRichText(iRichText); //text to be converted
       
  6880 	iSourceStream.Open(bufferRichText);
       
  6881 	
       
  6882 	CleanupStack::PopAndDestroy(store);
       
  6883 	// 2. Convert to HTML file
       
  6884 	iMsvEntry.SetEntryL(aHtmlId);
       
  6885 	iStore = iMsvEntry.EditStoreL();
       
  6886 	MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  6887 	iFile = attachmentMgr.GetAttachmentFileForWriteL(0);
       
  6888 	// open the write stream setting with file handle
       
  6889 	iTargetStream.Attach(iFile);
       
  6890 	// Prepares for asyn conversion. 	
       
  6891 	iHtmlId=aHtmlId;
       
  6892 	iTextId=aTextId;
       
  6893 	
       
  6894 	iToHTMLConverter->ConvertObjectAL(iSourceStream,iTargetStream);
       
  6895 	}
       
  6896 	
       
  6897 TBool CImHtmlConverter::StoreHTMLEntryTextAL(TRequestStatus& aStatus)
       
  6898 	{
       
  6899 	TBool finishedConvertingHTML = (!iToHTMLConverter->DoConvertL());
       
  6900 			
       
  6901 	if (finishedConvertingHTML)
       
  6902 		{
       
  6903 		TFileName filepath;
       
  6904 		RDir dir;
       
  6905 		TEntry entry;
       
  6906 		TParse dirPath;
       
  6907 		iToHTMLConverter->CancelConvert();
       
  6908 		iSourceStream.Close();
       
  6909 		iTargetStream.CommitL();
       
  6910 		iTargetStream.Close();
       
  6911 		iFile.Close();
       
  6912 		ResetStoreL();
       
  6913 
       
  6914 		// Set to html attachment entry
       
  6915 		iMsvEntry.SetEntryL(iHtmlId);
       
  6916 		iStore = iMsvEntry.EditStoreL();
       
  6917 		MMsvAttachmentManager& attachmentMgr = iStore->AttachmentManagerL();
       
  6918 		
       
  6919 		// Email Mtm will have one attachment per attachment entry , ehnce index 0
       
  6920 		CMsvAttachment* attachment = attachmentMgr.GetAttachmentInfoL(0);
       
  6921 		RFile file = attachmentMgr.GetAttachmentFileL(0);
       
  6922 		CleanupStack::PushL(attachment);
       
  6923 		TInt error = file.Size(iSize);
       
  6924 		if(error == KErrNone)
       
  6925 			attachment->SetSize(iSize);
       
  6926 		file.Close();
       
  6927 		TFileName filename = HtmlFilename(iMsvEntry, GetDefaultAttachmentName());
       
  6928 		attachment->SetAttachmentNameL(filename);
       
  6929 		CleanupStack::Pop(attachment); // ownership passed to attachment manager 
       
  6930 		
       
  6931 		attachmentMgr.ModifyAttachmentInfoL(attachment,aStatus);
       
  6932 		return 	finishedConvertingHTML; // true
       
  6933 		}
       
  6934 	return finishedConvertingHTML; // false
       
  6935 	}	
       
  6936 	
       
  6937 CMsvOperation*CImHtmlConverter::ChangeHTMLTextInEnrtyL(TRequestStatus& aStatus)
       
  6938 	{
       
  6939 	TMsvEmailEntry emailEntry = iMsvEntry.Entry();
       
  6940 	
       
  6941 	TFileName filename = HtmlFilename(iMsvEntry, GetDefaultAttachmentName());
       
  6942 	emailEntry.iDetails.Set(filename);
       
  6943 	emailEntry.iSize = iSize;	
       
  6944 	return iMsvEntry.ChangeL(emailEntry, aStatus);	
       
  6945 	}
       
  6946 
       
  6947 TFileName CImHtmlConverter::HtmlFilename(CMsvEntry& aEntry, TPtrC aFileName)
       
  6948 	{
       
  6949 	TFileName path;
       
  6950 	TFileName name;
       
  6951 	TMsvEntry entry = aEntry.Entry();	
       
  6952 // this is not used at all , need to get rid of this 
       
  6953 	if (entry.iDetails.Length())
       
  6954 		name=entry.iDetails;
       
  6955 	else if (aFileName.Length())
       
  6956 		name.Copy(aFileName);
       
  6957 	return name;
       
  6958 	}
       
  6959 
       
  6960 void CImHtmlConverter::ReadDefaultAttachmentNameL(RResourceFile& resourceFile)
       
  6961 	{	
       
  6962 	TResourceReader reader;
       
  6963 	HBufC8* buf;
       
  6964 
       
  6965 	buf = resourceFile.AllocReadLC( DEFAULT_ATTACHMENT_NAME );
       
  6966 	reader.SetBuffer(buf);
       
  6967 	TPtrC attachmentName = reader.ReadTPtrC();
       
  6968 	const TDesC& ext = KMimeHtmlExtension;
       
  6969 	iDefaultAttachmentName = HBufC::NewL(attachmentName.Length() + ext.Length());
       
  6970 	iDefaultAttachmentName->Des().Copy(attachmentName);
       
  6971 	iDefaultAttachmentName->Des().Append(ext);
       
  6972 	CleanupStack::PopAndDestroy(); // buf
       
  6973 	}
       
  6974 
       
  6975 TPtrC CImHtmlConverter::GetDefaultAttachmentName()
       
  6976 	{
       
  6977 	return (iDefaultAttachmentName) ? iDefaultAttachmentName->Des() : TPtrC();
       
  6978 	}
       
  6979 
       
  6980 CImHtmlConverter::~CImHtmlConverter()
       
  6981 	{
       
  6982 	delete iToHTMLConverter;
       
  6983 	delete iDefaultAttachmentName;
       
  6984 	delete iConverterList;
       
  6985 	delete iRichText;
       
  6986 	iSourceStream.Close();
       
  6987 	iTargetStream.Close();
       
  6988 	iFile.Close();
       
  6989 	delete iStore;
       
  6990 	}
       
  6991 
       
  6992 TInt CImHtmlConverter::Size() const
       
  6993 	{
       
  6994 	return iSize;
       
  6995 	}
       
  6996 
       
  6997 
       
  6998 //**********************************
       
  6999 // CImStoreResolver
       
  7000 //**********************************
       
  7001 
       
  7002 CImStoreResolver::CImStoreResolver(CStreamStore* aStore)
       
  7003 : iStore(aStore)
       
  7004 	{
       
  7005 	}
       
  7006 
       
  7007 CImStoreResolver::~CImStoreResolver()
       
  7008 	{
       
  7009 	delete iStore;
       
  7010 	}
       
  7011 
       
  7012 const CStreamStore& CImStoreResolver::StreamStoreL(TInt) const
       
  7013 	{
       
  7014 	return *iStore;
       
  7015 	}
       
  7016