--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/email/pop3andsmtpmtm/servermtmutils/src/IMCVSEND.CPP Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,2938 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <e32base.h>
+#include <e32math.h>
+#include <txtrich.h>
+#include <bautils.h>
+#include <miut_err.h>
+
+#include "IMUTDLL.H"
+#include "IMCVSEND.H"
+
+#include <miuthdr.h>
+#include <miutpars.h>
+
+#include <imcm.rsg>
+#include <barsread.h> // TResourceReader
+
+#include <cmsvattachment.h>
+#include <mmsvattachmentmanager.h>
+#include <cmsvplainbodytext.h>
+
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "miut_errconsts.h"
+#include "timrfc822datefield.h"
+#include "cimconvertheader.h"
+#endif
+
+
+#define SENDLOG(x) \
+ if (iLogFileExists) \
+ iLogFile.Write(x);
+
+
+#define SENDLOG2(x,y) \
+ if (iLogFileExists) \
+ { \
+ iLogFile.Write(x); \
+ iLogFile.Write(y); \
+ }
+
+_LIT(KLogFilePath, "c:\\logs\\mailtext\\");
+_LIT(KLogFileName, "out.txt");
+_LIT8(KNewLogHeader, "\r\n------ New Send Session ------\r\n");
+_LIT8(KSent, "Sent : ");
+_LIT8(KSetBody, "Body length = %d\r\n");
+
+const TInt KArrayGranularity = 3;
+const TInt KChunkSize = 1024;
+
+
+//*********************************************************************************
+// Class CImSendMessage Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+EXPORT_C CImSendMessage* CImSendMessage::NewLC(CMsvServerEntry& aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ CImSendMessage* self = new (ELeave) CImSendMessage(aServerEntry);
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+EXPORT_C CImSendMessage* CImSendMessage::NewL(CMsvServerEntry& aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ CImSendMessage* self = CImSendMessage::NewLC(aServerEntry);
+ CleanupStack::Pop( );
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendMessage::CImSendMessage(CMsvServerEntry& aServerEntry) : iServerEntry(aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImSendMessage::ConstructL()
+//---------------------------------------------------------------------------------
+ {
+ // logfile stuff
+ TInt ret=0;
+ TParse logFileName;
+ logFileName.Set(KLogFileName, &KLogFilePath, NULL);
+ TFileName filename(logFileName.FullName());
+ ret=iLogFile.Replace(iServerEntry.FileSession(), filename, EFileShareExclusive|EFileWrite );
+ iLogFileExists = (ret==KErrNone);
+ SENDLOG( KNewLogHeader )
+
+ }
+
+//---------------------------------------------------------------------------------
+EXPORT_C void CImSendMessage::InitialiseL(TMsvId aMessageId, TImSendMethod aSendMethod,
+ const TTime aTimeDate, const TDesC& aDomainName,
+ TUint aCharset, const TImSMTPSendCopyToSelf aCopyToSelf)
+//---------------------------------------------------------------------------------
+ {
+ TImEmailTransformingInfo info;
+ info.SetToDefault(aSendMethod); // Sets defaults
+ info.SetHeaderAndBodyCharset(aCharset) ; // Sets charset for header/body
+
+ InitialiseL(aMessageId, aTimeDate, aDomainName, info, aCopyToSelf);
+ }
+
+
+//---------------------------------------------------------------------------------
+EXPORT_C void CImSendMessage::InitialiseL(TMsvId aMessageId, const TTime aTimeDate,
+ const TDesC& aDomainName, const TImEmailTransformingInfo& aInfo,
+ const TImSMTPSendCopyToSelf aCopyToSelf)
+//---------------------------------------------------------------------------------
+ {
+ User::LeaveIfError(iServerEntry.SetEntry(aMessageId));
+ __ASSERT_ALWAYS(iServerEntry.Entry().iType==KUidMsvMessageEntry, gPanic(KPanicEntryIsNotMessage));
+
+ SetSendMethodL(aInfo.SendMethod());
+ iSendEmail->InitialiseL(aTimeDate, aDomainName, aCopyToSelf, aInfo);
+ Reset();
+
+ }
+
+//---------------------------------------------------------------------------------
+EXPORT_C void CImSendMessage::Reset()
+//---------------------------------------------------------------------------------
+ {
+ iSendEmail->Reset();
+ }
+
+
+// Creates the required email sending object, either Mime or non MIME.
+//---------------------------------------------------------------------------------
+void CImSendMessage::SetSendMethodL(TImSendMethod aSendMethod)
+//---------------------------------------------------------------------------------
+ {
+ switch (aSendMethod)
+ {
+ case ESendAsSimpleEmail:
+ iSendEmail = CImSendPlainEmail::NewL(iServerEntry);
+ break;
+ case ESendAsMimeEmail:
+ iSendEmail = CImSendMimeEmail::NewL(iServerEntry);
+ break;
+ default:
+ gPanic(KPanicUnknownSendingMethod);
+ }
+ }
+
+
+//---------------------------------------------------------------------------------
+EXPORT_C TInt CImSendMessage::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ // Format the next line of output into rOutputLine.
+ // If the output line contains more characters than the size of the source data cosumed
+ // in preparing it, then the difference is passed back in aPaddingCount.
+
+ TInt localPaddingCount=0;
+
+ rOutputLine.Zero();
+ TInt ret = iSendEmail->NextLineL( rOutputLine, localPaddingCount );
+
+ AddCRLFAtEndOfLine(rOutputLine, localPaddingCount);
+
+ SENDLOG(KSent);
+ SENDLOG(rOutputLine);
+
+ rPaddingCount = localPaddingCount;
+ return ret;
+ }
+
+
+//---------------------------------------------------------------------------------
+EXPORT_C CImSendMessage::~CImSendMessage( )
+//---------------------------------------------------------------------------------
+ {
+ if (iLogFileExists)
+ iLogFile.Close();
+ delete iSendEmail;
+ }
+
+//---------------------------------------------------------------------------------
+EXPORT_C TInt CImSendMessage::HeaderSize()
+//---------------------------------------------------------------------------------
+ {
+ TInt size = iSendEmail->HeaderSize();
+ iSendEmail->Reset();
+ return size;
+ }
+
+
+//---------------------------------------------------------------------------------
+EXPORT_C TInt CImSendMessage::BodySizeL()
+//---------------------------------------------------------------------------------
+ {
+ return iSendEmail->BodySizeL();
+ }
+
+
+//*********************************************************************************
+// Class CImSendEmail Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+CImSendEmail::CImSendEmail(CMsvServerEntry& aServerEntry) :
+ iServerEntry(aServerEntry), iDomainName(TPtrC())
+//---------------------------------------------------------------------------------
+ {
+ }
+
+
+//---------------------------------------------------------------------------------
+CImSendEmail::~CImSendEmail( )
+//---------------------------------------------------------------------------------
+ {
+ delete iCharConv;
+ delete iCharacterConverter;
+ delete iHeaderConverter;
+
+ delete iSendFile;
+ delete iEmailTraverser;
+
+ delete iRfc822Header;
+ delete iSendRichText;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendEmail::ConstructL()
+//---------------------------------------------------------------------------------
+ {
+ iCharacterConverter = CCnvCharacterSetConverter::NewL();
+ iCharConv = CImConvertCharconv::NewL(*iCharacterConverter, iServerEntry.FileSession());
+
+ iSendFile = CImSendFile::NewL(iServerEntry.FileSession(), *iCharConv);
+
+ iEmailTraverser = CImEmailTraverser::NewL(iServerEntry);
+
+ iHeaderConverter = CImConvertHeader::NewL(*iCharConv);
+ iRfc822Header = CImSendRfc822Header::NewL(iServerEntry.FileSession(), *iHeaderConverter);
+ iSendRichText = CImSendRichText::NewL(*iCharConv);
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendEmail::InitialiseL( const TTime aTimeDate, const TDesC& aDomainName,
+ const TImSMTPSendCopyToSelf aCopyToSelf,
+ const TImEmailTransformingInfo& aTransformingInfo)
+//---------------------------------------------------------------------------------
+ {
+ // get a list of all attachments
+ iDomainName.Set(aDomainName);
+ iDefaultTransformingInfo=aTransformingInfo;
+ iTimeDate=aTimeDate;
+
+ iRfc822Header->InitialiseL(iTimeDate, iDomainName, iServerEntry,
+ iServerEntry.Entry().Priority(), aCopyToSelf, iDefaultTransformingInfo);
+
+ iEmailTraverser->InitialiseL( iServerEntry.Entry().Id() );
+
+ }
+
+
+//---------------------------------------------------------------------------------
+TBool CImSendEmail::InitBodyObjectL(TMsvEntry& rEntry)
+//---------------------------------------------------------------------------------
+ {
+ return ( rEntry.iType==KUidMsvEmailTextEntry
+ && iSendRichText->InitialiseL( iServerEntry,
+ Encoder(EEncodingTypeNone), EEncodingTypeNone,
+ iRfc822Header->TransformingInfo().BodyTextCharset()) );
+ }
+
+
+// calculates & returns the total size of the header info, including the RFC822 tags,
+// comma & space separation, the CRLFs and the blank line after the header itself
+
+//---------------------------------------------------------------------------------
+TInt CImSendEmail::HeaderSize()
+//---------------------------------------------------------------------------------
+ {
+ return iRfc822Header->Size();
+ }
+
+// Sum of body parts and file attachments.
+//---------------------------------------------------------------------------------
+TInt CImSendEmail::BodySizeL()
+//---------------------------------------------------------------------------------
+ {
+ TMsvEntry entry;
+ TInt size=0;
+ TBool isEndOfEmail=EFalse;
+
+ entry = iEmailTraverser->ThisEntry();
+ do {
+ if (InitBodyObjectL(entry))
+ size += iSendRichText->Size();
+ else if (InitAttachmentObjectL(entry))
+ size += iSendFile->Size();
+
+ if ( iEmailTraverser->DownLevelL() )
+ entry = iEmailTraverser->ThisEntry();
+ else
+ while ( !iEmailTraverser->NextEntryL(entry) )
+ {
+ if ( !iEmailTraverser->UpLevelL() || iEmailTraverser->IsBaseLevel() )
+ {
+ // end of traversal, reached message entry.
+ isEndOfEmail=ETrue;
+ break;
+ }
+ }
+
+ } while (!isEndOfEmail);
+
+ return size;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendEmail::Reset()
+//---------------------------------------------------------------------------------
+ {
+ if(iRfc822Header)
+ {
+ iRfc822Header->Reset();
+ }
+ iState = 0;
+ }
+
+//---------------------------------------------------------------------------------
+TImFileCodec& CImSendEmail::Encoder(TImEncodingType aType)
+//---------------------------------------------------------------------------------
+ {
+ switch (aType)
+ {
+ case EEncodingTypeUU:
+ iUUEncoder.Initialise();
+ return iUUEncoder;
+ case EEncodingTypeBASE64:
+ iB64Encoder.Initialise();
+ return iB64Encoder;
+ case EEncodingTypeQP:
+ return iQPEncoder;
+ case EEncodingTypeNone:
+ return iNULLEncoder;
+ default:
+ __ASSERT_DEBUG( ETrue, gPanic(KPanicInvalidEncodingType) );
+ return iNULLEncoder;
+ }
+ }
+
+
+//---------------------------------------------------------------------------------
+TBool CImSendEmail::InitAttachmentObjectL(TMsvEntry& rEntry)
+//---------------------------------------------------------------------------------
+ {
+ if ( !(rEntry.iType==KUidMsvAttachmentEntry || rEntry.iType==KUidMsvEmailHtmlEntry) )
+ return EFalse;
+
+ iSendFile->InitialiseL(iServerEntry, Encoder(iRfc822Header->TransformingInfo().AttachmentEncoding()));
+ return ETrue;
+ }
+
+
+
+//*********************************************************************************
+// Class CImEmailTraverser Functions
+//*********************************************************************************
+
+
+//---------------------------------------------------------------------------------
+CImEmailTraverser* CImEmailTraverser::NewL( CMsvServerEntry& aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ CImEmailTraverser* self = new (ELeave) CImEmailTraverser( aServerEntry );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( );
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImEmailTraverser::CImEmailTraverser( CMsvServerEntry& aServerEntry ) :
+ iServerEntry(aServerEntry), iCurrentEntryList(KArrayGranularity)
+//---------------------------------------------------------------------------------
+ {
+ iBaseId = iServerEntry.Entry().Id();
+ }
+
+//---------------------------------------------------------------------------------
+void CImEmailTraverser::ConstructL()
+//---------------------------------------------------------------------------------
+ {
+ iSelectionList = new (ELeave) CArrayFixFlat<CMsvEntrySelection*>(KArrayGranularity);
+ }
+
+//---------------------------------------------------------------------------------
+CImEmailTraverser::~CImEmailTraverser()
+//---------------------------------------------------------------------------------
+ {
+ Reset();
+ delete iSelectionList;
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImEmailTraverser::Reset()
+//---------------------------------------------------------------------------------
+ {
+ while (DeleteCurrentList())
+ ;
+ }
+
+//---------------------------------------------------------------------------------
+void CImEmailTraverser::InitialiseL( TMsvId aId)
+//---------------------------------------------------------------------------------
+ {
+ iBaseId = aId;
+ User::LeaveIfError(iServerEntry.SetEntry(iBaseId));
+ Reset();
+ }
+
+
+//---------------------------------------------------------------------------------
+TBool CImEmailTraverser::DownLevelL()
+//---------------------------------------------------------------------------------
+ {
+ TMsvSelectionOrdering ordering(KMsvNoGrouping,EMsvSortById,ETrue);
+ iServerEntry.SetSort(ordering);
+ CMsvEntrySelection* children = new(ELeave) CMsvEntrySelection;
+ CleanupStack::PushL(children);
+ User::LeaveIfError(iServerEntry.GetChildren(*children));
+
+ if (children->Count())
+ {
+ AddList(*children);
+ CleanupStack::Pop(children);
+ User::LeaveIfError(iServerEntry.SetEntry( CurrentList()[0]));
+ return ETrue;
+ }
+
+ CleanupStack::PopAndDestroy(children);
+ return EFalse;
+ }
+
+//---------------------------------------------------------------------------------
+TBool CImEmailTraverser::UpLevelL()
+//---------------------------------------------------------------------------------
+ {
+ if (!DeleteCurrentList())
+ return EFalse;
+
+ if (!LevelExists())
+ User::LeaveIfError( iServerEntry.SetEntry(iBaseId) );
+ else
+ User::LeaveIfError( iServerEntry.SetEntry( CurrentList()[CurrentEntry()]) );
+ return ETrue;
+ }
+
+//---------------------------------------------------------------------------------
+TBool CImEmailTraverser::NextEntryL(TMsvEntry& rEntry)
+//---------------------------------------------------------------------------------
+ {
+ if (IsBaseLevel())
+ return EFalse;
+
+ iCurrentEntryList[0] += 1;
+ if ( CurrentEntry()>=CurrentList().Count() )
+ return EFalse; // last entry on this level.
+
+ if (!LevelExists())
+ User::LeaveIfError( iServerEntry.SetEntry(iBaseId) );
+ else
+ User::LeaveIfError( iServerEntry.SetEntry( CurrentList()[CurrentEntry()]) );
+
+ rEntry = ThisEntry();
+ return ETrue;
+ }
+
+
+//*********************************************************************************
+// Class CImSendPlainEmail Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+CImSendPlainEmail* CImSendPlainEmail::NewLC(CMsvServerEntry& aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ CImSendPlainEmail* self = new (ELeave) CImSendPlainEmail(aServerEntry);
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendPlainEmail* CImSendPlainEmail::NewL(CMsvServerEntry& aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ CImSendPlainEmail* self = CImSendPlainEmail::NewLC(aServerEntry);
+ CleanupStack::Pop( );
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendPlainEmail::CImSendPlainEmail(CMsvServerEntry& aServerEntry) : CImSendEmail(aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+// Sending header followed by body and attachment parts, in the order in which they are
+// arranged in the TMsventry structure.
+//---------------------------------------------------------------------------------
+TInt CImSendPlainEmail::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ __ASSERT_DEBUG( iRfc822Header!=NULL, gPanic(KPanicNoRfc822Header) );
+ __ASSERT_DEBUG( iSendRichText!=NULL, gPanic(KPanicNoRichText) );
+
+ TInt advance = 0;
+ TInt length = 0;
+ TInt localPaddingCount=0;
+
+ rOutputLine.Zero();
+ do
+ {
+ switch (iState)
+ {
+ case ERfc822Header:
+ advance = iRfc822Header->NextLineL(rOutputLine, rPaddingCount);
+ if (advance)
+ AppendCRLF(rOutputLine, localPaddingCount);
+ break;
+ case EBody:
+ advance = iSendRichText->NextLineL(rOutputLine, rPaddingCount);
+ break;
+ case EAttachmentFile:
+ advance = iSendFile->NextLineL(rOutputLine, rPaddingCount);
+ break;
+ }
+
+ length = rOutputLine.Length();
+ if ( !length || advance )
+ {
+ if ( iState==EBody )
+ AppendCRLF(rOutputLine, localPaddingCount);
+ while (!ChangeStateL())
+ ;
+ }
+
+ } while ( !length && iState != KImCvFinished);
+
+ rPaddingCount = localPaddingCount;
+ return (iState==KImCvFinished ? KImCvFinished : KErrNone);
+ }
+
+
+//---------------------------------------------------------------------------------
+TBool CImSendPlainEmail::ChangeStateL()
+//---------------------------------------------------------------------------------
+ {
+ TMsvEmailEntry entry = iEmailTraverser->ThisEntry();
+
+ if ( iEmailTraverser->DownLevelL() )
+ entry = iEmailTraverser->ThisEntry();
+ else
+ while ( !iEmailTraverser->NextEntryL(entry) )
+ {
+ if ( !iEmailTraverser->UpLevelL() || iEmailTraverser->IsBaseLevel() )
+ {
+ iState=KImCvFinished;
+ return ETrue;
+ }
+ }
+
+ // Is this entry an attachment entry?
+ if (InitBodyObjectL(entry))
+ iState=EBody;
+ else if (InitAttachmentObjectL(entry))
+ iState=EAttachmentFile;
+ else
+ return EFalse;
+
+ return ETrue;
+ }
+
+
+//*********************************************************************************
+// Class CImSendMimeEmail Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+CImSendMimeEmail* CImSendMimeEmail::NewLC(CMsvServerEntry& aServerEntry )
+//---------------------------------------------------------------------------------
+ {
+ CImSendMimeEmail* self = new (ELeave) CImSendMimeEmail(aServerEntry);
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendMimeEmail* CImSendMimeEmail::NewL(CMsvServerEntry& aServerEntry )
+//---------------------------------------------------------------------------------
+ {
+ CImSendMimeEmail* self = CImSendMimeEmail::NewLC(aServerEntry);
+ CleanupStack::Pop( );
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendMimeEmail::CImSendMimeEmail(CMsvServerEntry& aServerEntry ) : CImSendEmail(aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+//---------------------------------------------------------------------------------
+CImSendMimeEmail::~CImSendMimeEmail()
+//---------------------------------------------------------------------------------
+ {
+ Reset();
+ delete iSendMimeHeader;
+ delete iBoundaryArray;
+ delete iMimeHeader;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeEmail::ConstructL()
+//---------------------------------------------------------------------------------
+ {
+ TTime theTime;
+ theTime.UniversalTime(); // Gets the current universal time to use as a random number seed
+ iRandSeed = theTime.Int64();
+
+ iBoundaryArray = new (ELeave) CDesC8ArrayFlat(KArrayGranularity);
+ CImSendEmail::ConstructL();
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeEmail::Reset()
+//---------------------------------------------------------------------------------
+ {
+ iTextDisplayed=EFalse;
+ iBoundaryArray->Reset();
+ CImSendEmail::Reset();
+ }
+
+
+// Sending a MIME message consisting of a header, main MIME header followed by one or more
+// MIME parts. If more than one, the parts are seperated by a boundary string.
+
+//---------------------------------------------------------------------------------
+TInt CImSendMimeEmail::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ __ASSERT_DEBUG( iRfc822Header!=NULL, gPanic(KPanicNoRfc822Header) );
+ __ASSERT_DEBUG( iSendRichText!=NULL, gPanic(KPanicNoRichText) );
+
+ TInt advance = 0;
+ TInt length = 0;
+ TBool addBlankLine=EFalse;
+
+ rOutputLine.Zero();
+ do
+ {
+ addBlankLine=EFalse;
+ switch (iState)
+ {
+ case ERfc822Header:
+ advance = iRfc822Header->NextLineL( rOutputLine, rPaddingCount );
+ break;
+ case EMimeMainHeader:
+ advance = iSendMimeHeader->NextLine( rOutputLine, rPaddingCount );
+ break;
+ case EMimeText:
+ if ( iBoundaryArray->Count() && !iTextDisplayed )
+ {
+ rOutputLine.Append(KImcvMimeText);
+ rPaddingCount=rOutputLine.Length();
+ AppendCRLF(rOutputLine, rPaddingCount);
+ addBlankLine=ETrue;
+ iTextDisplayed=ETrue;
+ }
+ advance=1;
+ break;
+ case EBoundary:
+ if ( iBoundaryArray->Count() )
+ {
+ SendBoundaryLine( rOutputLine, rPaddingCount );
+ AppendCRLF(rOutputLine, rPaddingCount);
+ }
+ advance = 1;
+ break;
+ case EMimePartHeader:
+ advance = iSendMimeHeader->NextLine( rOutputLine, rPaddingCount );
+ break;
+ case EBody:
+ advance = iSendRichText->NextLineL(rOutputLine, rPaddingCount);
+ break;
+ case EAttachmentFile:
+ advance = iSendFile->NextLineL(rOutputLine, rPaddingCount);
+ break;
+ case EEndBoundary:
+ if ( iBoundaryArray->Count() )
+ {
+ SendBoundaryLine( rOutputLine, rPaddingCount );
+ rOutputLine.Append(KImcvMimeBoundaryStartEnd);
+ DeleteBoundary();
+ rPaddingCount=rOutputLine.Length();
+ }
+ advance = 1;
+ break;
+ case ELineAfterEndBoundary:
+ AppendCRLF(rOutputLine, rPaddingCount);
+ advance = 1;
+ break;
+ }
+
+ length = rOutputLine.Length();
+
+ if ( !length || advance )
+ ChangeStateL();
+
+ if (addBlankLine)
+ AppendCRLF(rOutputLine, rPaddingCount);
+
+ } while ( !length && iState != KImCvFinished);
+
+ return (iState==KImCvFinished ? KImCvFinished : KErrNone);
+ }
+
+
+//---------------------------------------------------------------------------------
+TBool CImSendMimeEmail::ChangeStateL()
+//---------------------------------------------------------------------------------
+ {
+ TInt ret=ETrue;
+ TMsvEmailEntry entry = iEmailTraverser->ThisEntry();
+ TImEmailFolderType folderType;
+
+ switch (iState)
+ {
+ case ERfc822Header:
+ InitSendMimeHeaderL(entry, EMainMimeHeader);
+ iState=EMimeMainHeader;
+ break;
+ case EMimeMainHeader:
+ iState=EMimeText;
+ break;
+ case EMimeText:
+ if ( !CheckForMultipartEmailL(entry, folderType) )
+ {
+ // NOT a multipart email.
+ // Get next entry and see what else it could be..
+ GetNextEntryL(entry);
+
+ if (iState!=EBoundary)
+ break; // Simple MIME message, only one part.
+
+ if ( InitBodyObjectL(entry) )
+ iState=EBody; // Rich text
+ else if ( iEmbeddedEmail )
+ // An embeddef RFC822 message, change state to RGC822 header
+ InitEmbeddedEmailL();
+ else if ( InitAttachmentObjectL(entry) )
+ iState=EAttachmentFile; // Attachment part
+ else
+ GetNextEntryL(entry);
+ }
+ else
+ {
+ // A Multipart message, get next entry to see what first part is.
+ GetNextEntryL(entry);
+
+ // An multipart inside a multipart.
+ if ( iState==EBoundary && entry.iType==KUidMsvFolderEntry )
+ GetNextEntryL(entry);
+ }
+ break;
+ case EBoundary:
+ iEmbeddedEmail = CheckForEmbeddedEmailL(entry);
+ InitSendMimeHeaderL(entry, EPartMimeHeader);
+ iState=EMimePartHeader;
+ break;
+ case EMimePartHeader:
+ if ( entry.iType==KUidMsvFolderEntry )
+ GetNextEntryL(entry);
+ else if ( InitBodyObjectL(entry) )
+ iState=EBody;
+ else if ( iEmbeddedEmail )
+ InitEmbeddedEmailL();
+ else if ( InitAttachmentObjectL(entry) )
+ iState=EAttachmentFile;
+ else
+ GetNextEntryL(entry);
+ break;
+ case EBody:
+ case EAttachmentFile:
+ GetNextEntryL(entry);
+ break;
+ case EEndBoundary:
+ iState=ELineAfterEndBoundary;
+ break;
+ case ELineAfterEndBoundary:
+ GetNextEntryL(entry);
+ break;
+ } // end Switch
+
+ return ret;
+ }
+
+
+// If mimeheader in store, crates relevant mimeHeader object.
+//---------------------------------------------------------------------------------
+TBool CImSendMimeEmail::CreateMimeHeaderL()
+//---------------------------------------------------------------------------------
+ {
+ TBool restored=EFalse;
+ delete iMimeHeader;
+ iMimeHeader=NULL;
+ iMimeHeader = CImMimeHeader::NewL();
+
+ if (iServerEntry.HasStoreL())
+ {
+ CMsvStore* entryStore = iServerEntry.ReadStoreL();
+ CleanupStack::PushL(entryStore);
+ if( entryStore->IsPresentL(KUidMsgFileMimeHeader) )
+ {
+ iMimeHeader->RestoreL(*entryStore);
+ restored=ETrue;
+ }
+ else
+ /* The MIME header store does not exist, but MIME header info will be
+ * sent with this email, so the Sent message should reflect this.
+ * So we create a KUidMsgFileMimeHeader in the store */
+ {
+ // open store for edit
+ CleanupStack::PopAndDestroy(entryStore);
+ entryStore = NULL;
+ entryStore = iServerEntry.EditStoreL();
+ CleanupStack::PushL(entryStore);
+
+ // store the MIMEheader
+ iMimeHeader->StoreL(*entryStore);
+ entryStore->CommitL();
+ }
+
+ CleanupStack::PopAndDestroy(entryStore);
+ }
+ return restored;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeEmail::InitMimeHeaderL( TMsvEntry& aEntry, TPtrC8& rBoundary, TPtrC& rFilename)
+//---------------------------------------------------------------------------------
+ {
+ TBool multipart=EFalse;
+
+ TImEmailFolderType folderType;
+ if (!iEmbeddedEmail && CheckForMultipartEmailL(aEntry, folderType))
+ {
+ //iMimeHeader->Reset();
+ iMimeHeader->SetContentTypeL(KImcvMultipart);
+ switch(folderType)
+ {
+ case EFolderTypeRelated:
+ iMimeHeader->SetContentSubTypeL(KImcvRelated);
+ break;
+ case EFolderTypeMixed:
+ iMimeHeader->SetContentSubTypeL(KImcvMixed);
+ break;
+ case EFolderTypeParallel:
+ iMimeHeader->SetContentSubTypeL(KImcvParallel);
+ break;
+ case EFolderTypeAlternative:
+ iMimeHeader->SetContentSubTypeL(KImcvAlternative);
+ break;
+ case EFolderTypeDigest:
+ iMimeHeader->SetContentSubTypeL(KImcvDigest);
+ break;
+ default:
+ // Should really default to mixed rather than unknown.
+ iMimeHeader->SetContentSubTypeL(KImcvMixed);
+ }
+ multipart=ETrue;
+ }
+
+ rBoundary.Set(SetBoundaryL(multipart));
+
+ //Storing header information(ContentType and SubContentType) for e-mail with attachment
+ if ((aEntry.Attachment()) && (iMimeHeader->ContentType().Length() == 0) && (iServerEntry.HasStoreL()))
+ {
+ CMsvStore* store = iServerEntry.ReadStoreL();
+ CleanupStack::PushL(store);
+ MMsvAttachmentManager& manager=store->AttachmentManagerL();
+ if(manager.AttachmentCount())
+ {
+ CMsvAttachment* attachment = manager.GetAttachmentInfoL(0);
+ CleanupStack::PushL(attachment);
+ TInt length = attachment->MimeType().Length();
+ TInt location = attachment->MimeType().Locate('/');
+ if ((length > 0) && (location != KErrNotFound))
+ {
+ iMimeHeader->SetContentTypeL(attachment->MimeType().Left(location++));
+ iMimeHeader->SetContentSubTypeL(attachment->MimeType().Right((length-location)));
+ }
+ CleanupStack::PopAndDestroy(attachment);
+ }
+ CleanupStack::PopAndDestroy(store);
+ }
+
+ if(InitAttachmentObjectL(aEntry))
+ rFilename.Set(static_cast<TPtrC>(iSendFile->Filename()));
+ else
+ rFilename.Set(KNullDesC);
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeEmail::InitSendMimeHeaderL( TMsvEntry& aEntry, TMimeHeaderType aMimeHeaderType )
+//---------------------------------------------------------------------------------
+ {
+ // When we are dealing with the main Mime header and we don't have a
+ // multipart we want to check if the entry is a text entry and if it
+ // has a Mime header in its store: this means we are probably dealing
+ // with a scheduling message (i.e.meeting invite). In this case we take
+ // the Mime header from the text entry.
+
+ TImEmailFolderType folderType;
+ TBool found = EFalse;
+
+ if ( (aMimeHeaderType==EMainMimeHeader) && !CheckForMultipartEmailL(aEntry, folderType) )
+ {
+ if ( Down(aEntry) )
+ {
+ if ( aEntry.iType==KUidMsvEmailTextEntry )
+ {
+ if ( CreateMimeHeaderL() )
+ {
+ found = ETrue;
+ }
+ }
+
+ // We move back to the previous entry
+ iEmailTraverser->UpLevelL();
+ aEntry = iEmailTraverser->ThisEntry();
+ }
+ }
+
+ // We read the Mimeheader stream if we haven't done it already
+ if ( !found )
+ {
+ CreateMimeHeaderL();
+ }
+
+ TPtrC8 boundary;
+ TPtrC filename;
+
+ InitMimeHeaderL(aEntry, boundary, filename);
+
+ delete iSendMimeHeader;
+ iSendMimeHeader = NULL;
+ iSendMimeHeader = CImSendMimeHeader::NewL(*iHeaderConverter, aMimeHeaderType);
+ if (( aEntry.iType == KUidMsvMessageEntry )
+ && ( !iEmailTraverser->IsBaseLevel() )
+ && ( aMimeHeaderType == EPartMimeHeader ))
+ {
+ iSendMimeHeader->InitialiseL( *iMimeHeader, filename, boundary,iEmbeddedEmail,
+ aEntry, iRfc822Header->TransformingInfo(), ETrue);
+ }
+ else
+ {
+ iSendMimeHeader->InitialiseL( *iMimeHeader, filename, boundary,iEmbeddedEmail,
+ aEntry, iRfc822Header->TransformingInfo());
+ }
+
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImSendMimeEmail::InitEmbeddedEmailL()
+//---------------------------------------------------------------------------------
+ {
+ iRfc822Header->InitialiseL(iServerEntry.Entry().iDate, iDomainName, iServerEntry,
+ iServerEntry.Entry().Priority(), ESendNoCopy, iDefaultTransformingInfo);
+
+ iState=ERfc822Header;
+ iEmbeddedEmail=0;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeEmail::CreateBoundaryL()
+//---------------------------------------------------------------------------------
+ {
+ TBuf8<57> validBoundaryBuffer(KBasicAsciiChars);
+ TBuf8<KBoundaryStringLength> boundaryString;
+ TUint result = 0;
+
+ boundaryString.Append(KImcvEpoc32);
+ boundaryString.Append(KImcvHyphen);
+
+ while( boundaryString.Length()<KBoundaryStringLength )
+ {
+ result=(Math::Rand(iRandSeed));
+ // gets the mod of Rand() which is a number between 0 to KMaxTInt
+ result%=57;
+ boundaryString.AppendFormat(KPrintChar, validBoundaryBuffer[result]);
+ result=0;
+ }
+
+ iBoundaryArray->InsertL(0, boundaryString);
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeEmail::DeleteBoundary()
+//---------------------------------------------------------------------------------
+ {
+ if (iBoundaryArray->Count())
+ iBoundaryArray->Delete(0);
+ }
+
+//---------------------------------------------------------------------------------
+TInt CImSendMimeEmail::HeaderSize()
+//---------------------------------------------------------------------------------
+ {
+ TInt size = CImSendEmail::HeaderSize();
+
+ TMsvId id = iServerEntry.Entry().Id();
+ iEmailTraverser->SetBaseEntry();
+
+ TMsvEntry aId;
+
+ // DEF023106. Can't let Leaves pass into public non-leave function, so Trap.
+ TRAPD(initialiseError, InitSendMimeHeaderL(aId, EMainMimeHeader));
+
+ if (initialiseError != KErrNone)
+ {
+ // DEF023106. Return double the rfc822 header size on Leave.
+ size += size;
+ }
+ else
+ {
+ size += iSendMimeHeader->Size();
+ }
+
+ iServerEntry.SetEntry(id);
+ return size;
+ }
+
+
+//---------------------------------------------------------------------------------
+TBool CImSendMimeEmail::InitBodyObjectL(TMsvEntry& rEntry)
+//---------------------------------------------------------------------------------
+ {
+ TImEncodingType type=iRfc822Header->TransformingInfo().BodyTextEncoding();
+
+ return ( rEntry.iType==KUidMsvEmailTextEntry
+ && iSendRichText->InitialiseL( iServerEntry,
+ Encoder(type), type,
+ iSendMimeHeader->CharsetUid()) );
+ }
+
+
+//*********************************************************************************
+// Class CImSendRfc822Header Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+CImSendRfc822Header* CImSendRfc822Header::NewLC( RFs& anFs, CImConvertHeader& aConverter )
+//---------------------------------------------------------------------------------
+ {
+ CImSendRfc822Header* self = new (ELeave) CImSendRfc822Header(anFs, aConverter);
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendRfc822Header* CImSendRfc822Header::NewL( RFs& anFs, CImConvertHeader& aConverter )
+//---------------------------------------------------------------------------------
+ {
+ CImSendRfc822Header* self = CImSendRfc822Header::NewLC(anFs, aConverter);
+ CleanupStack::Pop( );
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendRfc822Header::CImSendRfc822Header( RFs& anFs, CImConvertHeader& aConverter )
+ : iFs(anFs), iHeaderConverter(aConverter)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+//---------------------------------------------------------------------------------
+CImSendRfc822Header::~CImSendRfc822Header()
+//---------------------------------------------------------------------------------
+ {
+ delete iHeader;
+ delete iDomainName;
+
+ delete iOutputBuffer;
+ delete iProductName;
+ delete iImcvUtils;
+ delete iPriorityFields;
+ delete iImportanceFields;
+ delete iReceiptFields;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::ConstructL()
+//---------------------------------------------------------------------------------
+ {
+ RResourceFile resFile;
+ OpenResourceFileL(resFile,iFs); // leaves if file not found
+
+ // make sure the resource file will be closed if anything goes wrong
+ TCleanupItem close( CloseResourceFile, &resFile );
+ CleanupStack::PushL( close );
+ HBufC8* buf = resFile.AllocReadLC( PRODUCT_NAME );
+
+ TResourceReader reader;
+ reader.SetBuffer(buf);
+ iProductName = reader.ReadTPtrC().AllocL();
+ CleanupStack::PopAndDestroy(2); // close , buf
+ resFile.Close();
+
+ }
+
+//---------------------------------------------------------------------------------
+TBool CImSendRfc822Header::InitialiseL( const TTime aTimeDate , const TDesC& aDomainName,
+ CMsvServerEntry& aServerEntry,const TMsvPriority aPriority,
+ const TImSMTPSendCopyToSelf aCopyToSelf,
+ TImEmailTransformingInfo& aInfo)
+//---------------------------------------------------------------------------------
+ {
+ Reset();
+ iTimeDate = aTimeDate;
+
+ delete iDomainName;
+ iDomainName=NULL;
+ iDomainName=aDomainName.AllocL();
+
+ delete iHeader;
+ iHeader=NULL;
+ iHeader = CImHeader::NewLC();
+ CleanupStack::Pop(); // header
+
+ delete iImcvUtils;
+ iImcvUtils=NULL;
+ iImcvUtils=CImcvUtils::NewL();
+
+ delete iPriorityFields;
+ iPriorityFields=NULL;
+ delete iImportanceFields;
+ iImportanceFields=NULL;
+ delete iReceiptFields;
+ iReceiptFields=NULL;
+
+ iPriorityFields=new (ELeave)CDesC8ArrayFlat(KArrayAllocationNumber);
+ iImcvUtils->SendPriorityFieldsL(*iPriorityFields);
+
+ iImportanceFields=new (ELeave)CDesC8ArrayFlat(KArrayAllocationNumber);
+ iImcvUtils->SendImportanceFieldsL(*iImportanceFields);
+
+ TMsvEmailEntry entry = aServerEntry.Entry();
+ if (entry.Receipt())
+ {
+ iReceiptFields = new (ELeave)CDesC8ArrayFlat(KArrayAllocationNumber);
+ iImcvUtils->SendReturnReceiptFieldsL(*iReceiptFields);
+ }
+ iPriority = aPriority;
+
+ TBool validEmailMsg=EFalse;
+ if (aServerEntry.HasStoreL())
+ {
+ CMsvStore* store = aServerEntry.ReadStoreL();
+ CleanupStack::PushL(store);
+
+ if (store->IsPresentL( KUidMsgFileTransformingInfo))
+ aInfo.RestoreL(*store);
+
+ // Must have an rfc822 header.
+ if (store->IsPresentL( KUidMsgFileIMailHeader) )
+ {
+ iHeader->RestoreL(*store);
+ validEmailMsg=ETrue;
+ }
+
+ CleanupStack::PopAndDestroy(store);
+ }
+
+ iTransformingInfo=aInfo;
+ if(aInfo.HeaderCharset() == 0)
+ aInfo.SetHeaderCharset(iHeaderConverter.CharConv().DefaultCharset());
+
+ iHeaderCharset=aInfo.HeaderCharset();
+ iHeaderEncoding=aInfo.HeaderEncoding();
+
+ iCopyToSelf=aCopyToSelf;
+
+ return validEmailMsg;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::HandleSpecialCharacters(TPtr8& aAddressPtr)
+//---------------------------------------------------------------------------------
+ {
+ // Single address passed in. Make sure the address is of the format
+ // "quoted name" <name@domain>
+ // quoted, name <name@domain>
+ // quoted "name" <name@domain>
+ // name <name@domain>
+ // quoted "name <name@domain>
+ // Comments are not supported.
+ // Remove any leading and trailing white space.
+ aAddressPtr.Trim();
+
+ // If the address isn't the correct format.
+ if (aAddressPtr[aAddressPtr.Length() - 1] != '>')
+ return;
+
+ TInt leftChevron = aAddressPtr.LocateReverse(TChar('<'));
+ if (leftChevron == KErrNotFound)
+ return;
+
+ //If the address has allias
+ if(leftChevron > 0)
+ {
+
+ TInt firstDQuote = aAddressPtr.Locate(TChar('"'));
+ TInt lastDQuote = aAddressPtr.Left(leftChevron).LocateReverse(TChar('"'));
+ TInt aliasLastChar = leftChevron-1;
+
+ //If alias has ',' in between
+ if(aAddressPtr.Left(leftChevron).LocateReverse(TChar(',')) != KErrNotFound)
+ {
+ //get the last character of alias
+ for (TInt index = aliasLastChar ; aAddressPtr[index] == ' ' ; --index )
+ {
+ aliasLastChar--;
+ }
+ //if alias not with in quotes then add quotes
+ if ( firstDQuote != 0 || lastDQuote != aliasLastChar)
+ {
+ aAddressPtr.Insert(0,KImcvQuoteString);
+ firstDQuote = 0;
+ //because alias length has been increased by one character
+ aliasLastChar+=1;
+ aAddressPtr.Insert(aliasLastChar+1 , KImcvQuoteString);
+ lastDQuote = aliasLastChar+1;
+ }
+ }
+ if (lastDQuote == KErrNotFound || lastDQuote == firstDQuote)
+ return;
+
+ //add KBackslash before all spacial characters in alias
+ _LIT8(KBackslash,"\\");
+ for (TInt index = lastDQuote - 1; index > firstDQuote; --index)
+ {
+ if (IsSpecialCharacter(aAddressPtr[index]))
+ {
+ // Character inserted before the current character.
+ aAddressPtr.Insert(index, KBackslash);
+ }
+ }
+ }
+ }
+
+//---------------------------------------------------------------------------------
+TBool CImSendRfc822Header::IsSpecialCharacter(const TUint aChar)
+//---------------------------------------------------------------------------------
+ {
+ return (aChar == '(' || aChar == ')' || aChar == '<' || aChar == '>' || aChar == '@'
+ || aChar == '"' || aChar == ';' || aChar == ':' || aChar == '/' || aChar == ']'
+ || aChar == '[');
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::Reset()
+//---------------------------------------------------------------------------------
+ {
+ iState = 0;
+ }
+
+//---------------------------------------------------------------------------------
+TInt CImSendRfc822Header::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ // Format the next line of output into rOutputLine.
+ // If the output line contains more characters than the size of the source data consumed
+ // in preparing it, then the difference is passed back in aPaddingCount.
+
+ __ASSERT_DEBUG( iHeader!=NULL, gPanic(KPanicNoRfc822Header) );
+
+ TInt advance = 0;
+ TInt length = 0;
+ TInt localPaddingCount=0;
+
+ rOutputLine.Zero();
+ do
+ {
+ switch (iState)
+ {
+ case EFrom: // top of header, generate 'From'
+ advance = FromL( rOutputLine ); // returns 1 if we've finished the field, 0 otherwise
+ break;
+ case EReplyTo: // generate 'Reply-To'
+ advance = ReplyToL( rOutputLine );
+ break;
+ case ETo: // generate 'To'
+ advance = ToL( rOutputLine );
+ break;
+ case ECc: // generate 'Cc'
+ advance = CcL( rOutputLine );
+ break;
+ case EBcc: // generate 'Bcc'
+ advance = BccL( rOutputLine );
+ break;
+ case ESubject: // generate 'Subject'
+ advance = SubjectL( rOutputLine );
+ break;
+ case EDate: // generate date
+ rOutputLine = KImcvDatePrompt;
+ iRfc822Date.SetDate( iTimeDate, rOutputLine );
+ advance = 1;
+ break;
+ case EReturnReceiptTo:
+ if (iReceiptFields)
+ advance = ReturnReceiptsL( rOutputLine );
+ break;
+ case EPriority:
+ advance = PriorityL(rOutputLine );
+ break;
+ case EImportance:
+ advance = ImportanceL(rOutputLine );
+ break;
+ case EMessageID: // iDomainName should be called somewhere before this is called!
+ // (use SetDomainNameL(aDomainName))
+ SetMessageIdL();
+ advance = MessageIdL(rOutputLine);
+ break;
+ case EXMailer: // quick advert for ourselves
+ advance = XMailerL( rOutputLine );
+ break;
+ }
+
+ length = rOutputLine.Length();
+ if (!length || advance)
+ iState ++;
+
+ } while ( !length && (iState < EEndOfRfc822Header) );
+
+ if ( !IsLineCRLF( rOutputLine ) )
+ // only write something if there is any data!
+ AppendCRLF(rOutputLine, localPaddingCount);
+
+ rPaddingCount = localPaddingCount;
+ return (iState>=EEndOfRfc822Header ? KImCvAdvance : KErrNone);
+ }
+
+// Pass in 16 bit descriptor, encode before outputting
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::PrepareBufferL( const TPtrC8& aPrompt, const TDesC& aData)
+//---------------------------------------------------------------------------------
+ {
+ HBufC8* buf = HBufC8::NewL(aData.Length());
+ RBuf8 bufPtr(buf);
+ bufPtr.CleanupClosePushL();
+ EncodeHeaderFieldL(aData, bufPtr, 0);
+ PrepareBufferL(aPrompt,bufPtr);
+ CleanupStack::PopAndDestroy(&bufPtr);
+
+ }
+
+// data is 8 bit, no encoding.
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::PrepareBufferL( const TPtrC8& aPrompt, const TDesC8& aData)
+//---------------------------------------------------------------------------------
+ {
+ if (iOutputBuffer)
+ return;
+
+ iOutputBuffer = HBufC8::NewL( aPrompt.Length() + aData.Length() + 1 );
+ *iOutputBuffer = aPrompt;
+
+ // need to buffer up some output
+ iOutputBuffer->Des().Append( KImcvSpace );
+ iOutputBuffer->Des().Append( aData );
+ ipOutputBuffer = iOutputBuffer->Ptr();
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::AddCopyToSelfL(TImSMTPSendCopyToSelf aCopyToSelf, CDesCArray& aList)
+//---------------------------------------------------------------------------------
+ {
+ if (iCopyToSelf==aCopyToSelf)
+ {
+ if ( iHeader->ReceiptAddress().Length() )
+ aList.AppendL(iHeader->ReceiptAddress());
+ else if ( iHeader->ReplyTo().Length() )
+ aList.AppendL(iHeader->ReplyTo());
+ }
+ }
+
+
+//---------------------------------------------------------------------------------
+TInt CImSendRfc822Header::DoRecipientsL( TDes8& rOutputLine, const TPtrC8& aPrompt,
+ CDesCArray& aList)
+//---------------------------------------------------------------------------------
+ {
+ if (iOutputBuffer)
+ return SendOutput(rOutputLine);
+
+ // first call into this function, so build the output buffer
+ // first establish the length (this is faster than guessing & having to re-allocate)
+ TInt32 totalLength = aPrompt.Length()+1;
+ TInt i=aList.Count(); // loop counter
+ while (i--)
+ // allow 2 chars for comma-separation
+ totalLength += aList[i].Length() + 2;
+
+ iOutputBuffer = HBufC8::NewL( totalLength );
+ // now build the combined list
+ TInt count=aList.Count();
+ for ( i=0; i<count; i++ )
+ {
+ if (!i) // first recipient in list needs to be preceeded by the field identifier
+ {
+ *iOutputBuffer = aPrompt;
+ iOutputBuffer->Des().Append( KImcvSpace );
+ }
+ else // subsequent ones need comma-separation
+ iOutputBuffer->Des().Append( KImcvCommaSpace );
+ // ...and of course the data
+ HBufC8* buf = HBufC8::NewL((aList[i]).Length());
+ RBuf8 bufPtr(buf);
+ bufPtr.CleanupClosePushL();
+
+ EncodeHeaderFieldL(aList[i] , bufPtr, i);
+
+ HBufC8* addrBuffer = HBufC8::NewLC(bufPtr.Length() * 2);
+ TPtr8 addrPtr(addrBuffer->Des());
+ addrPtr.Copy(bufPtr);
+ HandleSpecialCharacters(addrPtr);
+
+ // May have to increase size of iOutputBuf
+ if (iOutputBuffer->Des().MaxLength() < iOutputBuffer->Des().Length() + addrPtr.Length() + 2)
+ iOutputBuffer = iOutputBuffer->ReAllocL( iOutputBuffer->Des().MaxLength() + addrPtr.Length());
+ iOutputBuffer->Des().Append( addrPtr);
+ bufPtr.Close();
+ CleanupStack::PopAndDestroy(2, &bufPtr); // addrBuffer, buf
+
+ } // for (...)
+ ipOutputBuffer = iOutputBuffer->Ptr();
+ return SendOutput( rOutputLine );
+ }
+
+void CImSendRfc822Header::PackRemainingData( TDes8& rOutputLine, TPtrC8& aBuf )
+ {
+
+ if (iAddSpaceToNewLine)
+ {
+ // wrapped lines start with a space to indicate their wrappiness.
+ rOutputLine = KImcvSpace;
+ rOutputLine.Append( aBuf.Ptr(), aBuf.Length() );
+ // we can add this extra byte since MKaxIMailLineLength allows for it
+ rOutputLine.SetLength( aBuf.Length() + 1 );
+ }
+ else
+ {
+ rOutputLine = aBuf;
+ }
+ }
+
+
+//---------------------------------------------------------------------------------
+TInt CImSendRfc822Header::SendOutput( TDes8& rOutputLine )
+//---------------------------------------------------------------------------------
+ {
+ // we have buffered output - first check whether we can bung the rest out on one line.
+ // the size of the remaining data is the whole length less the distance we've already got through
+
+ TInt offset = (ipOutputBuffer-iOutputBuffer->Ptr());
+
+ TInt dataRemaining = iOutputBuffer->Length() - offset;
+ if ( dataRemaining < KMaxIMailHeaderWriteLineLength )
+ {
+ // copy this into the line-output buffer
+ if ( !offset )
+ {
+ // this is the first line for this field since we're still pointing at the start of the buffer
+ rOutputLine = *iOutputBuffer;
+ }
+ else
+ {
+ TPtrC8 data( ipOutputBuffer, dataRemaining );
+ PackRemainingData( rOutputLine, data);
+ }
+
+ delete iOutputBuffer;
+ iOutputBuffer = NULL;
+ ipOutputBuffer = NULL;
+ iAddSpaceToNewLine = EFalse;
+ // we can now advance to the next field
+ return 1;
+ }
+ else // we need to send out the data in line-long segments
+ {
+ // only the first line gets the whole length, cos subsequent ones are prepended with a space.
+ TInt lineLength = (offset ? KMaxIMailHeaderWriteLineLength : KMaxIMailHeaderWriteLineLength-1 );
+
+ TInt pos = 0;
+ TInt left = 0;
+ TInt right = 0;
+ TBool splitAddress = EFalse;
+ iAddSpaceToNewLine = EFalse;
+
+ // if currently handling subject field, then do not attempt to parse for email addresses.
+ // This causes encoded words to be split accross line breaks, resulting in garbled text.
+ if (FieldIsEmailAddress())
+ {
+ TPtrC8 addrData(ipOutputBuffer, dataRemaining);
+ while ( ValidEmailAddress( addrData, pos, left, right) )
+ {
+ if (left+pos < lineLength)
+ {
+ if (right+pos >= lineLength)
+ {
+ // Current Email address won't fit into line
+ splitAddress = ETrue;
+ iAddSpaceToNewLine = ETrue;
+
+ if (right - left < lineLength)
+ {
+ // Break line just before Email address
+ lineLength = left+pos;
+ break;
+ }
+ }
+ }
+ else
+ {
+ //length of alias is less than KMaxIMailHeaderWriteLineLength
+ if(left+pos < KMaxIMailHeaderLineLength)
+ {
+ splitAddress = ETrue;
+ iAddSpaceToNewLine = ETrue;
+ // Break line just before Email address
+ lineLength = left+pos;
+ }
+ else
+ {
+ User::Leave(KErrSmtpBufferOverFlow);
+ }
+ break;
+ }
+ if (right+pos > lineLength)
+ {
+ //length of email address is less than KMaxIMailHeaderWriteLineLength
+ if(right+pos < KMaxIMailHeaderLineLength)
+ {
+ splitAddress = ETrue;
+ iAddSpaceToNewLine = ETrue;
+ // Break line just before Email address
+ lineLength = right+pos;
+ }
+ else
+ {
+ User::Leave(KErrSmtpBufferOverFlow);
+ }
+ break;
+ }
+ // Move pos to end of Email address
+ pos += right;
+ }
+ }
+
+ if ( !splitAddress )
+ {
+ TPtrC8 encData(ipOutputBuffer, dataRemaining);
+ while ( iHeaderConverter.FindEncodedWord(encData, pos, left, right) )
+ {
+ if (left+pos < lineLength)
+ {
+ // Second part of condition checks for too long encoded-words
+ if ((right+pos >= lineLength) && (right - left < lineLength))
+ {
+ // Break line just before encoded word
+ lineLength = left+pos;
+ iAddSpaceToNewLine = ETrue;
+ break;
+ }
+ }
+ else if (right+pos > lineLength)
+ break;
+ // Move pos to end of the encoded word
+ pos += right;
+ }
+ }
+
+
+ if ( !FieldIsEmailAddress() && !iAddSpaceToNewLine )
+ {
+ // We have a subject field and no wrapping set at an Encoded Word
+ _LIT(KInvalidDataSize, "Data Remaining, not suitable for more than a line");
+ __ASSERT_DEBUG( dataRemaining >= KMaxIMailHeaderWriteLineLength, User::Panic(KInvalidDataSize, 1 ));
+
+ // Find space from a resonable length onwards in ascending order
+ TInt minLineLength = KMaxIMailHeaderWriteLineLength/2;
+ TPtrC8 buf(ipOutputBuffer+minLineLength, KMaxIMailHeaderWriteLineLength);
+ lineLength = buf.Locate(' ');
+
+ if ( lineLength != KErrNotFound )
+ {
+ // We have found a space
+ lineLength += minLineLength;
+ // only the first line gets the whole length, cos subsequent ones are prepended with a space.
+ TInt maxLineLength = (offset ? KMaxIMailHeaderWriteLineLength : KMaxIMailHeaderWriteLineLength-1 );
+ if (left+pos < maxLineLength)
+ {
+ // Second part of condition checks for too long encoded-words
+ if ((right+pos >= maxLineLength) && pos>0)
+ {
+ rOutputLine = KImcvSpace;
+ }
+ }
+ rOutputLine.Append( ipOutputBuffer, lineLength );
+ ipOutputBuffer += lineLength;
+ }
+ else
+ {
+ // Line length limit is 1000 chars per line including CRLF (RFC2822, Section 2.1.1)
+ // 1000 chars including "Field name: "+"Field body"+CRLF (here "Resent-Message-ID: " is largest field)
+ if (dataRemaining > KSmtpMaxBufferExcludingCRLF)
+ User::Leave(KErrSmtpBufferOverFlow);
+
+ // No space found, so send the full remaining buffer as it is
+ rOutputLine.Append( ipOutputBuffer, dataRemaining );
+ delete iOutputBuffer;
+ iOutputBuffer = NULL;
+ ipOutputBuffer = NULL;
+ return 1;
+ }
+
+ return 0;
+ }
+ // create a descriptor for the next line-length of characters
+ TPtrC8 data( ipOutputBuffer, lineLength );
+
+ if ( !offset )
+ {
+ // this is the first line for this field
+ rOutputLine = data;
+ }
+ else
+ {
+ PackRemainingData( rOutputLine, data );
+ }
+ // advance the data pointer to the next line-length of data
+ ipOutputBuffer += lineLength;
+
+ // prevent ourselves advancing to the next field
+ return 0;
+ }
+ }
+
+// Assumption:
+// data string coming in has already been formatted.
+// address1@dd.com, address2@dd.com, addreass3@dd
+//
+//---------------------------------------------------------------------------------
+TBool CImSendRfc822Header::ValidEmailAddress(const TPtrC8& aData, const TInt aPos,
+ TInt& rStart, TInt& rEnd)
+//---------------------------------------------------------------------------------
+ {
+ TBool found = EFalse;
+
+ TPtrC8 data = aData.Mid(aPos);
+ TInt len = data.Length();
+ if (len < 3)
+ return found;
+ //Assuming that alias does not contain '@'
+ TInt at = data.Locate(KImcvAt);
+ if ( at!=KErrNotFound )
+ {
+ found = ETrue;
+
+ TPtrC8 findEnd(data.Right(len-at));
+ TPtrC8 findStart(data.Left(at));
+
+ rEnd = findEnd.Locate(KImcvComma);
+ rStart = findStart.LocateReverse(KImcvSpaceChar);
+ }
+
+ rEnd = (rEnd==KErrNotFound) ? data.Length() : rEnd+at;
+
+ if (rStart==KErrNotFound)
+ rStart = 0;
+
+ return found;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::SetMessageIdL()
+//---------------------------------------------------------------------------------
+ {
+ TInt domainNameLength= iDomainName && iDomainName->Length() ? iDomainName->Length():0;
+
+ // list of Valid Characters
+ TBuf8<52> validCharacterBuffer(KValidCharacters);
+ TBuf8<20> randomString;
+ HBufC8* messageId = HBufC8::NewL(domainNameLength+24);
+ CleanupStack::PushL(messageId);
+
+ TPtr8 ptr(messageId->Des());
+ TUint result = 0;
+ TInt64 randSeed;
+ TTime theTime;
+
+ theTime.UniversalTime();
+ // Gets the current universal time to use as a random number seed
+ randSeed = theTime.Int64();
+
+ while(randomString.Length()<20)
+ {
+ result= (Math::Rand(randSeed)%10)*10;
+ result+= Math::Rand(randSeed)%10;
+ result%=52;
+ randomString.AppendFormat(KImcvCharacterFormat, validCharacterBuffer[result]);
+ result=0;
+ }
+
+ ptr.Append(KImcvLeftChevron);
+ ptr.Append(randomString.Left(12));
+ ptr.Append(KImcvFullStop);
+ ptr.Append(randomString.Right(8));
+ if (domainNameLength)
+ {
+ ptr.Append(KImcvAt);
+ ptr.Append(iDomainName->Des());
+ }
+ ptr.Append(KImcvRightChevron);
+ iHeader->SetImMsgIdL(messageId->Des());
+
+ CleanupStack::PopAndDestroy(messageId);
+ }
+
+
+//---------------------------------------------------------------------------------
+TInt CImSendRfc822Header::PriorityL(TDes8& rOutputLine)
+//---------------------------------------------------------------------------------
+ {
+ if (iPriority==EMsvMediumPriority)
+ return 0;
+ if (iPriority==EMsvHighPriority)
+ PrepareBufferL((*iPriorityFields)[0], KImPrioritySendHigh);
+ else if (iPriority==EMsvLowPriority)
+ PrepareBufferL((*iPriorityFields)[0], KImPrioritySendLow);
+ iPriorityFields->Delete(0);
+ SendOutput( rOutputLine );
+
+ return (iPriorityFields->Count()) ? 0:1; // Return 1 if array is empty
+ }
+
+//---------------------------------------------------------------------------------
+TInt CImSendRfc822Header::ImportanceL(TDes8& rOutputLine)
+//---------------------------------------------------------------------------------
+ {
+ // Although importance means priority, it is a different field and
+ // had a different format. When we send the importance field we send
+ // it based on the priority of the e-mail hense the usage of iPriority
+
+ if (iPriority==EMsvMediumPriority)
+ return 0;
+ if (iPriority==EMsvHighPriority)
+ PrepareBufferL((*iImportanceFields)[0], KImImportanceSendHigh);
+ else if (iPriority==EMsvLowPriority)
+ PrepareBufferL((*iImportanceFields)[0], KImImportanceSendLow);
+ iImportanceFields->Delete(0);
+ SendOutput( rOutputLine );
+
+ return (iImportanceFields->Count()) ? 0:1; // Return 1 if array is empty
+ }
+
+// calculates & returns the total size of the header info, including the RFC822 tags,
+// comma & space separation, the CRLFs and the blank line after the header itself
+
+//---------------------------------------------------------------------------------
+TInt CImSendRfc822Header::Size() const
+//---------------------------------------------------------------------------------
+ {
+ __ASSERT_DEBUG( iHeader!=NULL, gPanic(KPanicNoRfc822Header) );
+
+ TInt size = iHeader->DataSize();
+
+ size+= KImcvFromPrompt().Length() + 3;
+ if (iHeader->ReplyTo().
+ Length()>0) //test for existence of replyTo field
+ {
+ size+= KImcvReplyToPrompt().Length() + 3;
+ }
+ size+= KImcvSubjectPrompt().Length() + 3;
+ size+= KImcvDateStringLength + KImcvDatePrompt().Length() + 2;
+ size+= KImcvXMailer().Length() + iProductName->Length() + 2;
+
+
+ if (iHeader->ToRecipients().Length())
+ size+= KImcvToPrompt().Length()+3
+ + iHeader->ToRecipients().Count()*2;
+
+ if (iHeader->CcRecipients().Length())
+ size+= KImcvCcPrompt().Length()+3
+ + iHeader->CcRecipients().Count()*2;
+
+ if (iHeader->BccRecipients().Length())
+ size+= KImcvBccPrompt().Length()+3
+ + iHeader->BccRecipients().Count()*2;
+
+ if (iHeader->ReceiptAddress().Length())
+ // for now there will always be one return receipt field in send. In future if we implement more than one
+ //field then the size should include other fields.
+ size+= KImcvMsgDispositionTo().Length()+3
+ + iHeader->ReceiptAddress().Length()+2;
+ return size;
+ }
+
+
+//---------------------------------------------------------------------------------
+TUint CImSendRfc822Header::HeaderCharset() const
+//---------------------------------------------------------------------------------
+ {
+ return iHeader->Charset();
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendRfc822Header::EncodeHeaderFieldL(const TDesC& aBufIn, RBuf8& rBufOut, const TInt aArrayVal)
+//---------------------------------------------------------------------------------
+ {
+ CArrayFix<TImHeaderEncodingInfo>* infoArray = &(iHeader->EncodingInfo());
+ TImHeaderEncodingInfo::TEncodingType type;
+ switch (iHeaderEncoding)
+ {
+ case EEncodingTypeQP:
+ type=TImHeaderEncodingInfo::EQP;
+ break;
+ case EEncodingTypeBASE64:
+ type=TImHeaderEncodingInfo::EBase64;
+ break;
+ case EEncodingTypeUU:
+ type=TImHeaderEncodingInfo::EUU;
+ break;
+ case EEncodingTypeNone:
+ type=TImHeaderEncodingInfo::ENoEncoding;
+ break;
+ default:
+ __ASSERT_DEBUG( ETrue, gPanic(KPanicInvalidEncodingType) );
+ type=TImHeaderEncodingInfo::ENoEncoding;
+ }
+
+ if (iTransformingInfo.SendMethod() == ESendAsSimpleEmail)
+ {
+ // Don't encode, just convert
+ iHeaderConverter.ConvertHeaderFieldL(aBufIn, rBufOut, FieldIsEmailAddress());
+ }
+ else if (iHeaderCharset && iHeaderCharset!=KUidMsvCharsetNone)
+ {
+ iHeaderConverter.EncodeHeaderFieldL(aBufIn, rBufOut, iHeaderCharset, type, FieldIsEmailAddress());
+ }
+ else if (infoArray->Count())
+ {
+ // Use encoding information stored from incoming message.
+ iHeaderConverter.EncodeHeaderFieldL(aBufIn, rBufOut, infoArray, iState, aArrayVal);
+ }
+ else
+ {
+ // Dont encode
+ rBufOut.Copy(aBufIn);
+ }
+ }
+
+//*********************************************************************************
+// Class CImSendMimeHeader Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+CImSendMimeHeader* CImSendMimeHeader::NewLC(CImConvertHeader& aConverter, TMimeHeaderType aType)
+//---------------------------------------------------------------------------------
+ {
+ CImSendMimeHeader* self = new (ELeave) CImSendMimeHeader(aConverter, aType);
+ CleanupStack::PushL( self );
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendMimeHeader* CImSendMimeHeader::NewL(CImConvertHeader& aConverter, TMimeHeaderType aType)
+//---------------------------------------------------------------------------------
+ {
+ CImSendMimeHeader* self = CImSendMimeHeader::NewLC(aConverter, aType);
+ CleanupStack::Pop();
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendMimeHeader::CImSendMimeHeader(CImConvertHeader& aConverter, TMimeHeaderType aType) :
+ iConverter(aConverter), iBoundaryString(TPtrC8()), iMimeHeaderType(aType)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+//---------------------------------------------------------------------------------
+CImSendMimeHeader::~CImSendMimeHeader()
+//---------------------------------------------------------------------------------
+ {
+ delete iCharsetString;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeHeader::InitialiseL( CImMimeHeader& aMimeHeader, const TPtrC aFilename,
+ const TPtrC8& aBoundary, const TBool aEmbedded,
+ const TMsvEntry& aEntry, const TImEmailTransformingInfo& aInfo,
+ TBool aEmbeddedEmail)
+//---------------------------------------------------------------------------------
+ {
+ iMimeHeader=&aMimeHeader;
+ iBoundaryString.Set(aBoundary);
+ iFilename = aFilename;
+ iHeaderState=0;
+ iDealingWithAnEmbeddedEmail = aEmbeddedEmail;
+ iEntry=aEntry;
+
+ TPtrC8 contentType = iMimeHeader->ContentType();
+ iIsMultipart = (contentType.Length() && contentType==KImcvMultipart) ? ETrue:EFalse;
+
+ // Set the EncodingType of whatever MIME part it is.
+ if (aEmbedded)
+ {
+ // Deals with the case of a message/rfc22 which is 7 bit.
+ iEncodingType=EEncodingTypeNone;
+ }
+ else if (aEntry.iType==KUidMsvMessageEntry && iMimeHeader->ContentType()!=KImcvMultipart)
+ {
+ // Special case: for non multipart HTML message.
+ if ( ((TMsvEmailEntry)aEntry).MHTMLEmail() )
+ {
+ if ( aEntry.Attachment())
+ {
+ iEncodingType=aInfo.AttachmentEncoding();
+ SetCharsetUidL(aInfo.HeaderCharset());
+ }
+ else
+ {
+ iEncodingType=aInfo.HTMLEncoding();
+ SetCharsetUidL(aInfo.HTMLCharset());
+ }
+ }
+ else if (contentType.CompareF(KImcvApplication)==0)
+ {
+ // So we know it is binary..
+ iEncodingType=aInfo.AttachmentEncoding();
+ SetCharsetUidL(aInfo.HeaderCharset());
+ }
+ else
+ {
+ iEncodingType=aInfo.BodyTextEncoding();
+ SetCharsetUidL(aInfo.BodyTextCharset());
+ }
+ }
+ else
+ {
+ if (aEntry.iType == KUidMsvAttachmentEntry)
+ {
+ iEncodingType=aInfo.AttachmentEncoding();
+ SetCharsetUidL(aInfo.HeaderCharset());
+ }
+ else if (aEntry.iType == KUidMsvEmailHtmlEntry)
+ {
+ iEncodingType=aInfo.HTMLEncoding();
+ SetCharsetUidL(aInfo.HTMLCharset());
+ }
+ else
+ {
+ iEncodingType=aInfo.BodyTextEncoding();
+ SetCharsetUidL(aInfo.BodyTextCharset());
+ }
+ }
+
+ TUint mimeCharset = iMimeHeader->MimeCharset();
+ if (mimeCharset)
+ SetCharsetUidL(mimeCharset); // Ovverriding the info value passed in.
+
+ if (aEmbedded)
+ {
+ iMimeHeader->SetContentTypeL(KImcvMessage);
+ iMimeHeader->SetContentSubTypeL(KImcvRfc822);
+ }
+
+ if (iDealingWithAnEmbeddedEmail)
+ {
+ CImSendFile::EmbeddedEmailFilename(this->iEntry, this->iFilename);
+ }
+
+ }
+
+//---------------------------------------------------------------------------------
+TInt CImSendMimeHeader::NextLine( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ TInt advance = 0;
+ rOutputLine.Zero();
+
+ switch (iHeaderState)
+ {
+ case EMimeVersion: // Main only
+ if (iMimeHeaderType==EMainMimeHeader)
+ {
+ advance = MimeVersion(rOutputLine);
+ break;
+ }
+ advance++; // else continue..
+ case EContentLanguage: // Main only
+ if (iMimeHeaderType==EMainMimeHeader)
+ {
+ advance = ContentLanguage( rOutputLine );
+ break;
+ }
+ advance++; // else continue..
+ case EDescription: // Part only
+ advance++;
+ if ( Description(rOutputLine) )
+ break;
+ // else continue on to..
+ case EContentType:
+ advance++;
+ if ( ContentType(rOutputLine) )
+ break;
+ // else continue..
+ case EBoundaryString:
+ if( iBoundaryString.Length() )
+ {
+ advance = Boundary(rOutputLine);
+ break;
+ }
+ advance++; // else continue..
+ case EDisposition:
+ if (iIsMultipart && !iDealingWithAnEmbeddedEmail)
+ advance++;
+ else if (Disposition(rOutputLine, advance))
+ break;
+ // else continue..
+ case ETransferEncoding:
+ advance++;
+ if ( !iIsMultipart && TransferEncoding(rOutputLine) )
+ break;
+ // else continue..
+ case ECRLF:
+ advance += AddCRLF(rOutputLine);
+ break;
+ default:
+ __ASSERT_DEBUG( ETrue, gPanic(EPanicInvalidHeaderState) );
+ }
+
+ iHeaderState += advance;
+ rPaddingCount = rOutputLine.Length();
+ return (iHeaderState >= EEndOfMimeHeader ? KImAttFinished : KErrNone);
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImSendMimeHeader::AppendFilenameL( TDes8& rOutputLine ) const
+//---------------------------------------------------------------------------------
+ {
+ HBufC8* buf = HBufC8::NewL( iFilename.Length() );
+ RBuf8 bufPtr(buf);
+ CleanupClosePushL(bufPtr);
+ iConverter.EncodeHeaderFieldL( iFilename, bufPtr, iCharsetUid, KDefaultSendingHeaderEncoding, EFalse);
+ rOutputLine.Append(KImcvEqualsQuote);
+ rOutputLine.Append( bufPtr );
+ rOutputLine.Append(KImcvQuoteString);
+ CleanupStack::PopAndDestroy(&bufPtr);
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendMimeHeader::SetCharsetUidL(const TUint aId)
+//---------------------------------------------------------------------------------
+ {
+ delete iCharsetString;
+ iCharsetString=NULL;
+
+ iCharsetUid=aId;
+
+ if (iCharsetUid==KUidMsvCharsetNone)
+ // Unknown charset, set string to original
+ iCharsetString = (iMimeHeader->GetContentTypeValue(KImcvCharset)).AllocL();
+ else
+ {
+ if (!iCharsetUid)
+ iCharsetUid=iConverter.CharConv().DefaultCharset();
+
+ iCharsetString = iConverter.CharConv().GetMimeCharsetTextStringL(iCharsetUid);
+ }
+ }
+
+//---------------------------------------------------------------------------------
+TPtrC8 CImSendMimeHeader::GetCharsetString() const
+//---------------------------------------------------------------------------------
+ {
+ return *iCharsetString;
+ }
+
+
+// Only calculates main header size
+//---------------------------------------------------------------------------------
+TInt CImSendMimeHeader::Size() const
+//---------------------------------------------------------------------------------
+ {
+ TInt size=0;
+
+ // MIME VERSION
+ size+=KImcvMimePrompt().Length() +
+ KImcvSpMimeVersion().Length() + 2;
+
+ // CONTENT LANGUAGE
+ size+=KImcvContentLanguage().Length() +
+ KImcvDefaultLanguage().Length() + 2;
+
+ // CONTENT TYPE
+ TPtrC8 contentType = iMimeHeader->ContentType();
+ if (contentType.Length()!=0)
+ {
+ size += KImcvContentType().Length() +
+ contentType.Length() + 2;
+
+ TPtrC8 contentSubType = iMimeHeader->ContentSubType();
+ if ( contentSubType.Length() )
+ {
+ size += KImcvForwardSlash().Length() + contentSubType.Length() + 2;
+ }
+
+ if ( contentType.CompareF(KImcvText)==0 )
+ {
+ size += 3 ; // space, =, semi colon
+ size += KImcvCharset().Length() + (GetCharsetString()).Length() + 2;
+ }
+ }
+
+ // BOUNDARY
+ size+= CImSendMimeEmail::KBoundaryStringLength + GetCharsetString().Length() + 2;
+
+ // TRANSFER ENCODING
+ TPtrC8 encodingType = EncodingType();
+ if (encodingType.Length())
+ size+= KImcvContentTransferEncoding().Length() + encodingType.Length() + 2;
+
+ // CRLF
+ size+= 2;
+
+ return size;
+ }
+
+
+//*********************************************************************************
+// Class CImSendRichText Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+CImSendRichText* CImSendRichText::NewLC(CImConvertCharconv& aConv)
+//---------------------------------------------------------------------------------
+ {
+ CImSendRichText* self = new (ELeave) CImSendRichText(aConv);
+ CleanupStack::PushL( self );
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendRichText* CImSendRichText::NewL(CImConvertCharconv& aConv)
+//---------------------------------------------------------------------------------
+ {
+ CImSendRichText* self = CImSendRichText::NewLC(aConv);
+ CleanupStack::Pop();
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendRichText::CImSendRichText(CImConvertCharconv& aConv) : iConverter(aConv)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+
+//---------------------------------------------------------------------------------
+CImSendRichText::~CImSendRichText()
+//---------------------------------------------------------------------------------
+ {
+ delete iLeftOver;
+ delete iPlainBodyText;
+ iCurrentChunk.Close();
+ }
+
+//---------------------------------------------------------------------------------
+TBool CImSendRichText::InitialiseL( CMsvServerEntry& aServerEntry, TImCodec& anEncoder,
+ TImEncodingType aType, TUint aCharset)
+//---------------------------------------------------------------------------------
+ {
+ TBool ret = 0;
+ iPos = 0;
+ delete iPlainBodyText;
+ iPlainBodyText = NULL;
+ iIsNewChunk = ETrue;
+
+ iCurrentChunk.Close();
+ iCurrentChunk.Create(KChunkSize);
+
+ if (aServerEntry.HasStoreL())
+ {
+ CMsvStore* store = aServerEntry.ReadStoreL();
+ CleanupStack::PushL(store);
+
+ ret = store->HasBodyTextL();
+ if (ret)
+ {
+ // Initialize the plainbodytext message store for reading the bodytext.
+ iPlainBodyText = store->InitialisePlainBodyTextForReadL(KChunkSize);
+ iBodySize = iPlainBodyText->Size(); // Size() returns in no of bytes and the data is 16 bit formatted.
+ }
+
+ CleanupStack::PopAndDestroy(store);
+ }
+
+ if (aCharset ==KCharacterSetIdentifierIso88591 || aCharset== KCharacterSetIdentifierAscii)
+ {
+ aCharset=KCharacterSetIdentifierCodePage1252;
+ }
+
+ iPreparedToConvert= iConverter.PrepareToConvertToFromOurCharsetL(aCharset);
+
+ iBodyEncoding = aType;
+ iEncoder=&anEncoder;
+
+ return ret;
+ }
+
+
+
+//---------------------------------------------------------------------------------
+TInt CImSendRichText::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ __ASSERT_DEBUG( iPlainBodyText != NULL, gPanic(KPanicNoRichText) );
+
+ TInt noMoreChars= 0;
+
+ switch (iBodyEncoding)
+ {
+ case EEncodingTypeQP:
+ noMoreChars = EncodeQPNextLineL(rOutputLine, rPaddingCount);
+ break;
+ case EEncodingTypeUU:
+ case EEncodingTypeBASE64:
+ noMoreChars = EncodeNextLineL(rOutputLine, rPaddingCount);
+ break;
+ case EEncodingTypeNone:
+ default:
+ NoEncodeNextLineL(rOutputLine, rPaddingCount);
+ }
+
+ return noMoreChars;
+ }
+
+/**
+Extract line from the chunk restored from Message Store
+@param rOutputLine The output line to be sent.
+@return void.
+*/
+void CImSendRichText::ExtractLineFromChunkL(TDes16& aOutputLine)
+ {
+ // Check if there is enough data in the chunk to extract a line from it.
+ if((iPos + iMaxLength) > iCurrentChunk.Length())
+ {
+ iIsNewChunk = ETrue;
+ }
+
+ // Restore the newchunk from the messagestore.
+ if(iIsNewChunk)
+ {
+ iIsNewChunk = EFalse;
+
+ // Rearrange the remaining data from current chunk.
+ iCurrentChunk.Delete(0, iPos);
+ TInt currentChunkLength = iCurrentChunk.Length();
+
+ // Resize iCurrentChunk as per data left for send operation.
+ iCurrentChunk.ReAlloc(KChunkSize + currentChunkLength);
+ iCurrentChunk.SetMax();
+
+ TPtr16 restoredChunkPtr = iCurrentChunk.MidTPtr(currentChunkLength);
+
+ // Restore the chunk from Message Store.
+ iPlainBodyText->NextChunkL(restoredChunkPtr);
+ // if NextChunkL did not return a full size chunk, then need to update the size of iCurrentChunk
+ if(restoredChunkPtr.Length() != KChunkSize)
+ {
+ iCurrentChunk.SetLength(currentChunkLength + restoredChunkPtr.Length());
+ }
+ iPos = 0;
+ }
+
+ // Check whether chunk length is not greater than (iPos+iMaxlength).
+ if( (iPos + iMaxLength) >= iCurrentChunk.Length() )
+ {
+ aOutputLine.Copy(iCurrentChunk.MidTPtr(iPos));
+ }
+ else
+ {
+ aOutputLine.Copy(iCurrentChunk.MidTPtr(iPos, iMaxLength));
+ }
+ }
+
+
+// Convert character set of line
+//---------------------------------------------------------------------------------
+TInt CImSendRichText::ConvertNextLineL( const TDesC& aInput, TDes8& rOutput)
+//---------------------------------------------------------------------------------
+ {
+ TInt unconvertedChars=0;
+ TInt pos=0;
+ if (iPreparedToConvert)
+ iConverter.ConvertFromOurCharsetL(aInput, rOutput, unconvertedChars, pos);
+ else
+ rOutput.Copy(aInput);
+
+ return pos;
+ }
+
+//---------------------------------------------------------------------------------
+TInt CImSendRichText::NoEncodeNextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ rOutputLine.Zero();
+
+ // grab a few characters from the buffer
+ // (making sure this is more than we will ever need for the current line).
+
+ TBuf<2*KMaxIMailBodyLineLength> source;
+
+ iMaxLength = iPos+2*KMaxIMailBodyLineLength > iBodySize ?
+ iBodySize-iPos : 2*KMaxIMailBodyLineLength;
+
+ // Extract line from chunk restored from store.
+ ExtractLineFromChunkL(source);
+ HBufC* output = HBufC::NewLC(rOutputLine.MaxLength());
+
+ TPtr outPtr(output->Des());
+ TInt ret = RemoveControlCharacters( source, outPtr, rPaddingCount );
+
+ ConvertNextLineL( outPtr, rOutputLine);
+
+ CleanupStack::PopAndDestroy(output);
+ return ret;
+ }
+
+
+//---------------------------------------------------------------------------------
+TInt CImSendRichText::RemoveControlCharacters( const TDesC& aInputLine, TDes& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ TInt written=0; // number of characters written to the current line
+
+ TLex lexSource(aInputLine);
+ TDes& ptr = rOutputLine;
+
+ while ( (written<KMaxIMailBodyLineLength) && !lexSource.Eos() )
+ {
+ // first check whether we're at a line break
+ if ( IsEOL(lexSource.Peek()) )
+ {
+ Append( ptr, (TDesC8&) KImcvCRLF);
+ written+=2;
+
+ // we just added an extra character
+ rPaddingCount+=1;
+ lexSource.Inc();
+ break;
+ }
+ else if ( SmartBreak(written, lexSource.Remainder()) )
+ {
+ ptr.Append( lexSource.Peek() );
+ Append( ptr, (TDesC8&) KImcvCRLF);
+ written+=3;
+ rPaddingCount+=2;
+ lexSource.Inc();
+ break;
+ }
+ else if ( written >= KMaxIMailBodyLineLength-1 )
+ // make sure we don't exceed 76 chars per line of encoded text (must allow for CRLF)
+ {
+ Append( ptr, (TDesC8&) KImcvCRLF);
+ written+=2;
+ rPaddingCount+=2;
+ }
+ // check whether we have a whacky control character from CEditableText
+ else if ( lexSource.Peek()<KImcvSP )
+ {
+ TUint8 replacement = ReplacementChar( lexSource.Peek() );
+ if (replacement) // potentially ditch the character altogther
+ {
+ ptr.Append( replacement );
+ written++;
+ }
+ else
+ rPaddingCount-=1;
+ }
+ else
+ {
+ ptr.Append( lexSource.Peek() );
+ written++;
+ }
+
+ // advance to next source character
+ lexSource.Inc();
+
+ } // while
+
+ iPos += written - rPaddingCount;
+ rPaddingCount = rPaddingCount >=0 ? rPaddingCount : 0;
+
+ // set up the output parameter & return value
+ return (iPos >= iBodySize ? 1 : 0);
+ }
+
+//---------------------------------------------------------------------------------
+TInt CImSendRichText::EncodeNextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ rOutputLine.Zero();
+ TInt sourceLength=0;
+
+ HBufC8* output = HBufC8::NewLC(rOutputLine.MaxLength());
+ TPtr8 outPtr(output->Des());
+
+ TBuf<KMaxIMailBodyLineLength+1> source;
+
+ iMaxLength = iPos+KMaxIMailBodyLineLength > iBodySize ?
+ iBodySize-iPos : KMaxIMailBodyLineLength;
+
+ TInt leftOverLength= (iLeftOver) ? (*iLeftOver).Length() : 0 ;
+ if (leftOverLength < KDecodeLineLength && iPos<iBodySize )
+ {
+ // Extract line from chunk restored from store.
+ ExtractLineFromChunkL(source);
+ sourceLength=source.Length();
+
+ // Character conversion
+ ConvertNextLineL( source, outPtr );
+
+ ConvertLineBreaks(source, ETrue);
+ }
+
+ if (iLeftOver)
+ {
+ outPtr.Insert(0, *iLeftOver);
+ delete iLeftOver;
+ iLeftOver=NULL;
+ }
+
+ TInt rem = outPtr.Length() - KDecodeLineLength;
+ if (rem>0)
+ {
+ iLeftOver=(outPtr.Right(rem)).AllocL();
+ outPtr.SetLength(KDecodeLineLength);
+ }
+
+ if (outPtr.Length())
+ iEncoder->Encode(outPtr, rOutputLine);
+
+ if (source.Length()) // some text has bee extracted from the rich text store
+ iPos +=sourceLength;
+
+ CleanupStack::PopAndDestroy(output);
+
+ rPaddingCount=rOutputLine.Length();
+
+ // set up the output parameter & return value
+ return iLeftOver ? 0 : (iPos >= iBodySize ? 1 : 0);
+ }
+
+
+//---------------------------------------------------------------------------------
+TInt CImSendRichText::EncodeQPNextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ rOutputLine.Zero();
+ iUseRichText=ETrue;
+ TInt sourceUsed=0;
+ TInt crlfPadding=0;
+ TBool unicodeChars=EFalse;
+ TInt originalSource=0;
+
+ HBufC8* output = HBufC8::NewLC(rOutputLine.MaxLength());
+ TPtr8 outPtr(output->Des());
+
+ TBuf<KMaxIMailBodyLineLength+1> source;
+
+ iMaxLength = iPos+KMaxIMailBodyLineLength > iBodySize ?
+ iBodySize-iPos : KMaxIMailBodyLineLength;
+
+ TInt leftOverLength= (iLeftOver) ? (*iLeftOver).Length() : 0 ;
+ if (leftOverLength < KMaxIMailBodyLineLength && iPos<iBodySize )
+ {
+ // Extract line from chunk restored from store.
+ ExtractLineFromChunkL(source);
+ crlfPadding=ConvertLineBreaks(source, ETrue);
+ originalSource=source.Length()-crlfPadding;
+
+ // Character conversion
+ ConvertNextLineL( source, outPtr );
+
+ unicodeChars = (outPtr.Length() > source.Length()) ? ETrue:EFalse;
+ }
+
+ if (iLeftOver)
+ outPtr.Insert(0, *iLeftOver);
+
+ // QP encode line
+ ((TImCodecQP*) iEncoder)->AddPlainChar(KImcvPlainRichText);
+
+
+ TInt written = iEncoder->Encode(outPtr, rOutputLine);
+ TInt leftover = outPtr.Length() - written;
+
+ if (iLeftOver)
+ {
+ TInt rem = leftOverLength - written;
+ if (rem>0)
+ {
+ // Not all of the leftOver buffer was used.
+ iLeftOver->Des().Copy((*iLeftOver).Right(rem));
+ sourceUsed=0;
+ }
+ else
+ {
+ delete iLeftOver;
+ iLeftOver=NULL;
+ if(leftover)
+ sourceUsed=rem*(-1);
+ else
+ sourceUsed=originalSource;
+ }
+ }
+ else if (leftover)
+ sourceUsed=written;
+ else
+ sourceUsed=originalSource;
+
+ if (unicodeChars && !iLeftOver && leftover>0)
+ {
+ iLeftOver=(outPtr.Right(leftover)).AllocL();
+ iPos += originalSource;
+ }
+ else if (source.Length()) // some text has bee extracted from the rich text store
+ iPos +=sourceUsed;
+
+ CleanupStack::PopAndDestroy(output);
+
+ rPaddingCount=rOutputLine.Length();
+
+ // set up the output parameter & return value
+ return iLeftOver ? 0 : (iPos >= iBodySize ? 1 : 0);
+ }
+
+
+
+//---------------------------------------------------------------------------------
+TBool CImSendRichText::SmartBreak( TInt aWritten, const TUint8* aSource, TInt aMaxLength )
+//---------------------------------------------------------------------------------
+ {
+ // Check whether the current char is breakable.
+
+ TBool ret = EFalse;
+ TUint8 ch = *aSource;
+
+ if ( IsBreakable(ch) )
+ {
+ // Scan ahead looking for the next breakable char
+
+ const TUint8* lookAhead = aSource+1;
+ TBool found = EFalse;
+ while ( !found && lookAhead-aSource <= aMaxLength )
+ {
+ found = IsBreakable(*lookAhead);
+ if (!found)
+ lookAhead++;
+ }
+
+ // There's another breakable char before the end of the text - we need to break now
+ // if it's too far away and only if the non-breakable text fits on an output line.
+
+ ret = (aWritten+(lookAhead-aSource) >= KMaxIMailBodyLineLength
+ && (lookAhead-aSource) < KMaxIMailBodyLineLength);
+ }
+
+ return ret;
+ }
+
+
+//---------------------------------------------------------------------------------
+TBool CImSendRichText::SmartBreak( TInt aWritten, const TDesC& aSource )
+//---------------------------------------------------------------------------------
+ {
+ TBool ret = EFalse;
+ TLex source( aSource );
+
+ // only check for whether we should break if the current char is breakable
+ if ( IsBreakable(source.Peek()) )
+ {
+ // scan ahead looking for the next breakable char
+ source.Inc();
+ TBool found = EFalse;
+ TInt encodingOffset=(IsPlain(source.Peek()) ? 0 : 2);
+ while ( !found && !source.Eos() )
+ {
+ found = IsBreakable(source.Peek());
+ if (!found)
+ {
+ encodingOffset+=(IsPlain(source.Peek()) ? 0 : 2);
+ source.Inc();
+ }
+ }
+ // there's another breakable char before the end of the text
+ // - we need to break now if it's too far away
+ // but only if the non-breakable text fits on a line itself.
+
+ ret = ((aWritten+source.Offset()+encodingOffset) > KMaxIMailBodyLineLength-4);
+ }
+
+ return ret;
+ }
+
+//*********************************************************************************
+// Class CImSendFile Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+CImSendFile* CImSendFile::NewLC(RFs& anFs, CImConvertCharconv& aCharConv)
+//---------------------------------------------------------------------------------
+ {
+ CImSendFile* self = new (ELeave) CImSendFile(anFs, aCharConv);
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+//---------------------------------------------------------------------------------
+CImSendFile* CImSendFile::NewL(RFs& anFs, CImConvertCharconv& aCharConv)
+//---------------------------------------------------------------------------------
+ {
+ CImSendFile* self = CImSendFile::NewLC(anFs, aCharConv);
+ CleanupStack::Pop();
+ return self;
+ }
+
+/**
+ Intended Usage : Second phase of two-phase construction method. Does any
+ allocations required to fully construct the object.
+ @since 7.0s
+ @leave KErrNoMemory.
+ @pre First phase of construction is complete
+ @post The object is fully constructed and initialised.
+ */
+//---------------------------------------------------------------------------------
+void CImSendFile::ConstructL()
+//---------------------------------------------------------------------------------
+ {
+ iAttachmentFile = new(ELeave) TImAttachmentFile(CONST_CAST(RFs&,iFs));
+ }
+
+//---------------------------------------------------------------------------------
+CImSendFile::CImSendFile(RFs& anFs, CImConvertCharconv& aCharConv)
+ :iFs(anFs), iConverter(aCharConv), iAttachmentFile(NULL)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendFile::InitialiseL( CMsvServerEntry& aServerEntry, TImFileCodec& anEncoder)
+//---------------------------------------------------------------------------------
+ {
+ iEncoder = &anEncoder;
+ iAttachmentState=ENextFile;
+ Filename(aServerEntry, iAttachmentInfo);
+ }
+
+//---------------------------------------------------------------------------------
+CImSendFile::~CImSendFile()
+//---------------------------------------------------------------------------------
+ {
+ delete iAttachmentFile;
+ }
+
+//---------------------------------------------------------------------------------
+TInt CImSendFile::NextLineL( TDes8& rOutputLine, TInt& rPaddingCount )
+//---------------------------------------------------------------------------------
+ {
+ rOutputLine.Zero();
+
+ do
+ {
+ switch(iAttachmentState)
+ {
+ case ENextFile:
+ iAttachmentState=EPrefixLines;
+ break;
+ case EPrefixLines:
+ if (iEncoder->PrefixNextLineL(rOutputLine, iAttachmentInfo.iName, rPaddingCount)==KImAttFinished)
+ iAttachmentState=EEncodeFile;
+ break;
+ case EEncodeFile:
+ if (iAttachmentFile->ReadFile( iSourceLine, KDecodeLineLength))
+ {
+ iAttachmentState=EPostfixLines;
+ }
+ else if (iSourceLine.Length()!=0)
+ {
+ iEncoder->Encode(iSourceLine, rOutputLine);
+ rPaddingCount=rOutputLine.Length()-(iSourceLine.Length());
+ }
+ else
+ {
+ iAttachmentState=EPostfixLines;
+ }
+ break;
+ case EPostfixLines:
+ if (iEncoder->PostfixNextLine(rOutputLine, rPaddingCount)==KImAttFinished)
+ iAttachmentState=EEndOfAttachments;
+ break;
+ case EEndOfAttachments:
+ iAttachmentFile->CloseFile();
+ iAttachmentState=ECloseDelimiter;
+ break;
+ case ECloseDelimiter:
+ // Dependent on encoding type
+ iAttachmentState=ECRLFLine;
+ break;
+ case ECRLFLine:
+ AddCRLF(rOutputLine, rPaddingCount);
+ rPaddingCount=rOutputLine.Length();
+ iAttachmentState=EEnd;
+ break;
+ }
+
+ } while(!rOutputLine.Length());
+
+ return (iAttachmentState==EEnd ? KImAttFinished : KErrNone);
+ }
+
+//---------------------------------------------------------------------------------
+const TFileName& CImSendFile::Filename() const
+//---------------------------------------------------------------------------------
+ {
+ return iAttachmentInfo.iName;
+ }
+
+TFileName& CImSendFile::Filename(CMsvServerEntry& aEntry, SAttachmentInfo& aInfo)
+ {
+ TMsvEntry entry = aEntry.Entry();
+ aInfo.iSize=entry.iSize;
+
+ CMsvStore* store = aEntry.ReadStoreL();
+ CleanupStack::PushL(store);
+ MMsvAttachmentManager& manager=store->AttachmentManagerL();
+ if(manager.AttachmentCount())
+ {
+ CMsvAttachment* attachment = manager.GetAttachmentInfoL(0);
+ CleanupStack::PushL(attachment);
+ TParsePtrC parse(attachment->FilePath());
+ aInfo.iPath=parse.DriveAndPath();
+ aInfo.iName=parse.NameAndExt();
+ iAttachmentFile->CloseFile();
+ RFile file=manager.GetAttachmentFileL(0);
+ iAttachmentFile->SetFileHandle(file,TImAttachmentFile::EImFileRead);
+ CleanupStack::PopAndDestroy(attachment);
+ }
+ CleanupStack::PopAndDestroy(store);
+ return aInfo.iName;
+ }
+
+//---------------------------------------------------------------------------------
+void CImSendFile::EmbeddedEmailFilename(TMsvEntry& aEntry, TFileName& aFileName)
+//---------------------------------------------------------------------------------
+ {
+ if (aEntry.iDescription.Length())
+ {
+ aFileName = aEntry.iDescription;
+ if ( (aFileName.MaxLength() - aFileName.Length()) >= KImcvEmbeddedEmailFilenameExtension().Length() )
+ {
+ aFileName.Insert(aFileName.Length(), KImcvEmbeddedEmailFilenameExtension);
+ }
+ else
+ {
+ aFileName = KImcvEmbeddedEmailDefaultFilename;
+ aFileName.Insert(aFileName.Length(), KImcvEmbeddedEmailFilenameExtension);
+ }
+ }
+ }
+
+
+
+
+//*********************************************************************************
+// Class CImCalculateMsgSize Functions
+//*********************************************************************************
+
+//---------------------------------------------------------------------------------
+EXPORT_C CImCalculateMsgSize* CImCalculateMsgSize::NewL(RFs &anFs,CMsvServerEntry& aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ CImCalculateMsgSize* self=new (ELeave) CImCalculateMsgSize(anFs, aServerEntry);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+
+//---------------------------------------------------------------------------------
+CImCalculateMsgSize::CImCalculateMsgSize(RFs &anFs,CMsvServerEntry& aServerEntry)
+ : CMsgActive(EPriorityStandard), iFs(anFs),iServerEntry(aServerEntry)
+//---------------------------------------------------------------------------------
+ {
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImCalculateMsgSize::ConstructL()
+//---------------------------------------------------------------------------------
+ {
+ CActiveScheduler::Add(this);
+ }
+
+//---------------------------------------------------------------------------------
+EXPORT_C CImCalculateMsgSize::~CImCalculateMsgSize()
+//---------------------------------------------------------------------------------
+ {
+ Cancel();
+ Reset();
+ }
+
+
+//---------------------------------------------------------------------------------
+EXPORT_C void CImCalculateMsgSize::StartL(TRequestStatus& aStatus,TMsvId aMsvId,
+ TImSendMethod aAlgorithm, TTime& aTimeDate, const TDesC& aDomainName,
+ const TUint aCharset)
+//---------------------------------------------------------------------------------
+ {
+ Reset();
+ //initialise
+ iMailString.Zero();
+ iFinished=KErrNone;
+ iSize=0;
+ //
+ iSendMsg=CImSendMessage::NewL(iServerEntry);
+ iSendMsg->InitialiseL(aMsvId, aAlgorithm, aTimeDate, aDomainName, aCharset, ESendNoCopy);
+ //
+#if defined (_DEBUG)
+ TBuf<25> KFileName=_L("c:\\mailtest\\imcv\\size.txt");
+ TInt err=iFile.Open(iFs, KFileName, EFileStreamText|EFileWrite|EFileShareAny);
+ if (err==KErrNotFound) // file does not exist - create it
+ {
+ err = iFile.Create(iFs, KFileName, EFileStreamText|EFileWrite|EFileShareAny);
+ }
+ if (err == KErrNone)
+ {
+ iFileOpen=ETrue;
+ }
+#endif
+ Queue(aStatus);
+ TRequestStatus* status=&iStatus;
+ User::RequestComplete(status,0);
+ SetActive();
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImCalculateMsgSize::Reset()
+//---------------------------------------------------------------------------------
+ {
+ delete iSendMsg;
+ iSendMsg=NULL;
+#if defined (_DEBUG)
+ if (iFileOpen)
+ {
+ iFile.Close();
+ iFileOpen=EFalse;
+ }
+#endif
+ }
+
+//---------------------------------------------------------------------------------
+void CImCalculateMsgSize::DoRunL()
+//---------------------------------------------------------------------------------
+ {
+ if (iStatus.Int()!=KErrNone || iFinished==KImCvFinished)
+ return;
+ TInt count=0;
+ iFinished=iSendMsg->NextLineL(iMailString,count);
+ iSize+=iMailString.Length();
+#if defined (_DEBUG)
+ if (iFileOpen)
+ {
+ iFile.Write(iMailString);
+ }
+#endif
+ SetActive();
+ TRequestStatus* status=&iStatus;
+ User::RequestComplete(status,0);
+ }
+
+
+//---------------------------------------------------------------------------------
+void CImCalculateMsgSize::DoCancel()
+//---------------------------------------------------------------------------------
+ {
+ CMsgActive::DoCancel();
+ }
+