// 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:
// IMCVSEND.H
//
#if !defined(__IMCVSEND_H__)
#define __IMCVSEND_H__
#include <s32mem.h>
#include <badesca.h>
#include <miutatch.h>
#include <miuthdr.h>
#include <mentact.h>
#include <msvuids.h>
#include <msventry.h>
#include <smtpset.h>
#include <imutdll.h>
#include <imcvtext.h>
#include <imcvcodc.h>
#include <imcvutil.h>
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include "timrfc822datefield.h"
#include "cimconvertheader.h"
#endif
class CImSendEmail;
class CImEmailTraverser;
class CImSendPlainEmail;
class CImSendMimeEmail;
class CImSendMimeHeader;
class CImSendRfc822Header;
class CImSendRichText;
class CImSendFile;
class CMsvPlainBodyText;
/**
@internalComponent
@released
*/
enum TMimeHeaderType { EMainMimeHeader, EPartMimeHeader };
const TImHeaderEncodingInfo::TEncodingType
KDefaultSendingHeaderEncoding = TImHeaderEncodingInfo::EBase64;
const TUint KDefaultSendingCharset = KCharacterSetIdentifierIso88591;
const TInt KArrayAllocationNumber =6;
/**
The number of US ASCII UU Encoded characters per line between the CRLF line
terminator and the character count at the beginning of the encoded line when sending
UU encoded emails.
*/
const TInt KMaxUUUnEncodedCharsPerLine = 45; // Historically, UU implmentations use 45.
const TInt KMaxUUEncodedCharsPerLine = static_cast<TInt>(KMaxUUUnEncodedCharsPerLine / 0.75); // 60.
/**
The maximum number of US ASCII characters per line that are before the CRLF line
terminator when sending emails. RFC 2822 recommends that each line SHOULD not exceed
80 characters including the CRLF terminator, and MUST not exceed 1000.
*/
const TInt KMaxB64EncodedCharsPerLine = 60; // Could be increased to 75 characters for every encoded line if KDecodeLineLength = 675. 60 was chosen to maintain existing behaviour.
/**
Size of 8 bit data chunk to extract when encoding using B64 or UU.
The size allows for the appending of CRLF every KMaxEncodedCharsPerLine
characters after encoding to limit the line length as per RFC 2822.
The size also allows for the expansion of every 3 bytes of unencoded data to
4 bytes when encoded.
*/
const TInt KDecodeLineLength = 675; // 675/0.75= 900 = 100 bytes left for CRLF and UU length chars, 900/45 = exactly 20 UU lines per SMTP buffer sent, 900/60 = exactly 15 B64 lines per SMTP buffer sent.
// External interface to imcvsend.
//----------------------------------------------------------------------------------------
class CImSendMessage : public CBase
//----------------------------------------------------------------------------------------
/**
@internalAll
@released
*/
{
public:
IMPORT_C static CImSendMessage* NewL(CMsvServerEntry& aServerEntry);
IMPORT_C static CImSendMessage* NewLC(CMsvServerEntry& aServerEntry);
IMPORT_C ~CImSendMessage( );
// Returns KImcvFinished when done.
IMPORT_C TInt NextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
IMPORT_C void InitialiseL(TMsvId aMessageId, const TTime aTimeDate,
const TDesC& aDomainName, const TImEmailTransformingInfo& aInfo,
const TImSMTPSendCopyToSelf aCopyToSelf);
IMPORT_C void InitialiseL(TMsvId aMessageId, TImSendMethod aSendMethod, const TTime aTimeDate,
const TDesC& aDomainName, TUint aCharset, const TImSMTPSendCopyToSelf aCopyToSelf);
IMPORT_C TInt HeaderSize();
IMPORT_C TInt BodySizeL();
IMPORT_C void Reset();
private:
CImSendMessage(CMsvServerEntry& aServerEntry);
void ConstructL();
void SetSendMethodL(TImSendMethod aSendMethod);
private:
CMsvServerEntry& iServerEntry;
CImSendEmail* iSendEmail;
TMsvId iMessageId;
TTime iTimeDate;
TBool iLogFileExists; // Logging.
RFile iLogFile;
};
// This class is a VIRTUAL base class from which email protocol classes are derived.
// gives derived classes ability to traverse the entry structure and extract
// information from entries.
// It determines which entry to set the current context to and which entry will follow,
// and knows when the end of the message has been reached.
//----------------------------------------------------------------------------------------
class CImSendEmail : public CBase
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
public:
CImSendEmail(CMsvServerEntry& aServerEntry);
~CImSendEmail( );
virtual TInt NextLineL(TDes8& rOutputLine, TInt& rPaddingCount) = 0;
virtual void Reset();
virtual void InitialiseL( const TTime aTimeDate, const TDesC& aDomainName,
const TImSMTPSendCopyToSelf aCopyToSelf,
const TImEmailTransformingInfo& aTransformingInfo);
virtual TInt HeaderSize();
virtual TInt BodySizeL();
protected:
virtual void ConstructL(); // Call base class Construct in the derived function
TBool InitBodyObjectL(TMsvEntry& rEntry);
TBool InitAttachmentObjectL(TMsvEntry& rEntry);
TImFileCodec& Encoder(TImEncodingType aType);
protected:
CMsvServerEntry& iServerEntry;
// Encoding classes including a default.
TImCodecNull iNULLEncoder;
TImCodecUU iUUEncoder;
TImCodecB64WithLineBreaks iB64Encoder;
TImCodecQP iQPEncoder;
// Objects common to all email types
CImSendFile* iSendFile;
CImSendRfc822Header* iRfc822Header;
CImSendRichText* iSendRichText;
CImConvertCharconv* iCharConv;
CCnvCharacterSetConverter* iCharacterConverter;
CImConvertHeader* iHeaderConverter;
TInt iState;
CImEmailTraverser* iEmailTraverser;
CImHeader* iHeader;
TInt iEmbeddedEmail;
TTime iTimeDate;
TPtrC iDomainName;
TUint iAlgorithm; // used for encoding a body/attachment.
TImEmailTransformingInfo iDefaultTransformingInfo;
};
// Traverses the TMsvEntry structure of email message, used by CImSendEmail.
// Complex email messages have a hierarchical structure with more than one LEVEL.
//----------------------------------------------------------------------------------------
class CImEmailTraverser : CBase
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
public:
static CImEmailTraverser* NewL( CMsvServerEntry& aServerEntry );
~CImEmailTraverser();
void InitialiseL(TMsvId aId);
TBool NextEntryL(TMsvEntry& rEntry);
TBool DownLevelL();
TBool UpLevelL();
inline void SetBaseEntry();
inline TBool IsBaseLevel() const;
inline CMsvEntrySelection& CurrentList() const;
inline const TMsvEntry& ThisEntry() const;
private:
CImEmailTraverser( CMsvServerEntry& aServerEntry );
void ConstructL();
void Reset();
inline TBool LevelExists() const;
inline TBool DeleteCurrentList();
inline void AddList(CMsvEntrySelection& children);
inline TInt CurrentEntry();
private:
TMsvId iBaseId; // ID of the Top level email entry.
CMsvServerEntry& iServerEntry;
// Storing the child entries in a hierarchical entry structure.
// List and count arrays
CArrayFixFlat<CMsvEntrySelection*>* iSelectionList;
CArrayFixFlat<TInt> iCurrentEntryList;
};
// This class is derived from CImSendEmail and encapsulates the non-MIME protocol.
// The class only knows about the entry which is currently in its context, which is
// determined by it base class.
//----------------------------------------------------------------------------------------
class CImSendPlainEmail : public CImSendEmail
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
private:
enum TSendState {
ERfc822Header = 0,
EBody,
EAttachmentFile,
};
public:
static CImSendPlainEmail* NewL(CMsvServerEntry& aServerEntry );
static CImSendPlainEmail* NewLC(CMsvServerEntry& aServerEntry );
TInt NextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
private:
CImSendPlainEmail(CMsvServerEntry& aServerEntry);
TBool ChangeStateL();
};
// It encapsulates the MIME protocol and controls what needs to be sent for a specific
// entry type, this being the type of entry that is currently in context.
// Only knows about the entry which is currently in its context, which is determined by
// it base class. Creates and looks after the boundary strings.
//----------------------------------------------------------------------------------------
class CImSendMimeEmail : public CImSendEmail
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
public:
// From RFC 1521, (Boundaries) must be no longer than 70 characters.
enum{KBoundaryStringLength = 55};
private:
enum TSendState {
ERfc822Header = 0,
EMimeMainHeader,
EMimeText,
EBoundary,
EMimePartHeader,
EBody,
EAttachmentFile,
EEndBoundary,
ELineAfterEndBoundary,
};
public:
static CImSendMimeEmail* NewL(CMsvServerEntry& aServerEntry );
static CImSendMimeEmail* NewLC(CMsvServerEntry& aServerEntry );
~CImSendMimeEmail( );
TInt NextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
void Reset();
TInt HeaderSize();
TBool InitBodyObjectL(TMsvEntry& rEntry);
private:
CImSendMimeEmail(CMsvServerEntry& aServerEntry );
void ConstructL();
TBool ChangeStateL();
void CreateBoundaryL();
void DeleteBoundary();
inline void Boundary(TDes8& rOutputLine);
inline TPtrC8 Boundary();
inline TPtrC8 SetBoundaryL(TBool aMultipart);
inline TInt SendBoundaryLine( TDes8& rOutputLine, TInt& rPaddingCount);
inline TBool ValidBoundaryChar( TUint aCharacter );
void InitEmbeddedEmailL();
TBool CreateMimeHeaderL();
void InitMimeHeaderL( TMsvEntry& aEntry, TPtrC8& rBoundary, TPtrC& rFilename);
void InitSendMimeHeaderL(TMsvEntry& aEntry, TMimeHeaderType aMimeHeaderType );
inline TBool Next(TMsvEntry& rEntry);
inline TBool Down(TMsvEntry& rEntry);
inline void GetNextEntryL(TMsvEntry& rEntry);
inline TBool CheckForEmbeddedEmailL(const TMsvEntry& aEntry) const;
inline TBool CheckForMultipartEmailL( TMsvEntry& rEntry, TImEmailFolderType& aFolder);
private:
CDesC8ArrayFlat* iBoundaryArray;
CImSendMimeHeader* iSendMimeHeader;
CImMimeHeader* iMimeHeader;
TBool iTextDisplayed;
TInt64 iRandSeed;
};
// This class creates the main message header lines which conform to the rfc822 specification.
// The code is currently implemented in Imcvsend.cpp.
//----------------------------------------------------------------------------------------
class CImSendRfc822Header : public CBase
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
private:
// Defines the state order of the CImSendRfc822Header object...
// !! DO NOT CHANGE THE ORDER !!
enum TSendState {
EFrom=0, // 0
EReplyTo,
ETo,
ECc,
EBcc,
ESubject,
EDate,
EReturnReceiptTo,
EPriority,
EImportance,
EMessageID,
EXMailer,
EEndOfRfc822Header
};
public:
static CImSendRfc822Header* NewLC( RFs& anFs, CImConvertHeader& aConverter );
static CImSendRfc822Header* NewL( RFs& anFs, CImConvertHeader& aConverter );
~CImSendRfc822Header();
TInt NextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
TBool InitialiseL( const TTime aTimeDate , const TDesC& aDomainName,
CMsvServerEntry& aServerEntry, const TMsvPriority aPriority,
const TImSMTPSendCopyToSelf aCopyToSelf,
TImEmailTransformingInfo& rInfo);
TInt DoRecipientsL( TDes8& rOutputLine, const TPtrC8& aPrompt, CDesCArray& aList );
void PrepareBufferL( const TPtrC8& aPrompt, const TDesC& aData);
void PrepareBufferL( const TPtrC8& aPrompt, const TDesC8& aData);
TInt SendOutput( TDes8& rOutputLine );
TInt PriorityL(TDes8& rOutputLine);
TInt ImportanceL(TDes8& rOutputLine);
TUint HeaderCharset() const;
void SetMessageIdL();
void Reset();
TInt Size() const;
inline const TImEmailTransformingInfo& TransformingInfo() const;
private:
CImSendRfc822Header( RFs& anFs, CImConvertHeader& aConverter );
void ConstructL();
inline TInt FromL( TDes8& rOutputLine );
inline TInt ReplyToL( TDes8& rOutputLine );
inline TInt ToL( TDes8& rOutputLine );
inline TInt CcL( TDes8& rOutputLine );
inline TInt BccL( TDes8& rOutputLine );
inline TInt SubjectL( TDes8& rOutputLine );
inline TInt MessageIdL( TDes8& rOutputLine );
inline TInt XMailerL( TDes8& rOutputLine );
inline TInt ReturnReceiptsL(TDes8& rOutputLine);
inline TBool FieldIsEmailAddress() const;
TBool ValidEmailAddress(const TPtrC8& aData, const TInt aPos, TInt& rStart, TInt& rEnd);
void EncodeHeaderFieldL(const TDesC& aBufIn, RBuf8& rBufOut, const TInt aArrayVal);
void AddCopyToSelfL(TImSMTPSendCopyToSelf aCopyToSelf, CDesCArray& aList);
void HandleSpecialCharacters(TPtr8& aAddressPtr);
TBool IsSpecialCharacter(const TUint aChar);
void PackRemainingData(TDes8& rOutputLine, TPtrC8& aBuf);
private:
RFs& iFs;
CImHeader* iHeader;
TInt iState;
HBufC8* iOutputBuffer;
const TUint8* ipOutputBuffer;
TImRfc822DateField iRfc822Date;
TTime iTimeDate;
TMsvPriority iPriority;
// resource strings
HBufC* iProductName;
HBufC* iDomainName;
CImConvertHeader& iHeaderConverter;
CImcvUtils* iImcvUtils;
CDesC8Array* iPriorityFields;
CDesC8Array* iImportanceFields;
CDesC8Array* iReceiptFields;
TUint iHeaderCharset;
TImEncodingType iHeaderEncoding;
TImSMTPSendCopyToSelf iCopyToSelf;
TImEmailTransformingInfo iTransformingInfo;
TBool iAddSpaceToNewLine;
};
// This class encapsulates the MIME header protocol.
// The header strings are created from a text resource of standard MIME tokens
// Info obtained from cImMimeHeader object.
//----------------------------------------------------------------------------------------
class CImSendMimeHeader : public CBase
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
public:
enum TMimeHeaderState
{
EMimeVersion = 0, // Main only
EContentLanguage, // Main only
EDescription, // Part only
EContentType,
EBoundaryString,
EDisposition,
ETransferEncoding,
ECRLF,
EEndOfMimeHeader
};
enum TImSplitLine
{
EFirstLine = 0,
ESecondLine
};
public:
static CImSendMimeHeader* NewL(CImConvertHeader& aConverter, TMimeHeaderType aType);
static CImSendMimeHeader* NewLC(CImConvertHeader& aConverter, TMimeHeaderType aType);
~CImSendMimeHeader();
TInt NextLine( TDes8& rOutputLine, TInt& rPaddingCount );
void InitialiseL( CImMimeHeader& aMimeHeader, const TPtrC aFilename,
const TPtrC8& aBoundary, const TBool aEmbedded,
const TMsvEntry& aEntry, const TImEmailTransformingInfo& aInfo,
TBool aEmbeddedEmail = EFalse);
inline TInt BlankLine( TDes8& rOutputLine ) const;
inline TInt MimeVersion( TDes8& rOutputLine ) const;
inline TBool ContentType( TDes8& rOutputLine) const;
inline TBool TransferEncoding(TDes8& rOutputLine) const;
inline TInt ContentLanguage( TDes8& rOutputLine ) const;
inline TBool Description( TDes8& rOutputLine) const;
inline TBool Disposition( TDes8& rOutputLine, TInt& rAdvance);
inline const TPtrC8 EncodingType() const;
TUint CharsetUid() const;
void SetCharsetUidL(const TUint aId);
TPtrC8 GetCharsetString() const;
inline TInt Boundary(TDes8& rOutputLine) const;
void AppendFilenameL( TDes8& rOutputLine ) const;
TInt Size() const;
private:
CImSendMimeHeader( CImConvertHeader& aConverter, TMimeHeaderType aType);
private:
CImConvertHeader& iConverter;
TInt iHeaderState;
CImMimeHeader* iMimeHeader;
// Info needed when filling in header details
TImEncodingType iAlgorithm;
HBufC8* iCharsetString;
TPtrC8 iBoundaryString;
TFileName iFilename;
TMsvEntry iEntry;
TInt iLine;
TBool iIsMultipart;
TMimeHeaderType iMimeHeaderType;
TUint iHeaderCharset;
TImEncodingType iHeaderEncodingType;
TUint iCharsetUid;
TImEncodingType iEncodingType;
TBool iDealingWithAnEmbeddedEmail;
};
// This class sends the text from a richtext object.
// The text can be encoded using any of the available encoding techniques
//----------------------------------------------------------------------------------------
class CImSendRichText : public CBase
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
public:
static CImSendRichText* NewL( CImConvertCharconv& aConv );
static CImSendRichText* NewLC( CImConvertCharconv& aConv );
TBool InitialiseL( CMsvServerEntry& aServerEntry, TImCodec& anEncoder,
TImEncodingType aType, TUint aCharset);
TInt NextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
void ExtractLineFromChunkL(TDes16& aOutputLine);
~CImSendRichText();
inline TInt Size() const;
private:
CImSendRichText(CImConvertCharconv& aConv);
void ConstructL();
TInt NoEncodeNextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
TInt RemoveControlCharacters( const TDesC& aInputLine, TDes& rOutputLine, TInt& rPaddingCount );
TInt EncodeNextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
TInt EncodeQPNextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
TInt ConvertNextLineL( const TDesC& aInput, TDes8& rOutput);
TBool SmartBreak( TInt written, const TDesC& pSource );
TBool SmartBreak( TInt written, const TUint8* pSource, TInt aMaxLength );
inline TBool IsBreakable( TChar aChar ) const;
inline TBool IsEOL(TChar aChar) const;
inline TUint8 ReplacementChar(TChar aControlChar) const;
inline TBool IsPlain(TChar aChar) const;
inline int ConvertLineBreaks( TDes& aSource, TBool aLineBreak) const;
private:
// The message store class for reteiving chunks of body text from mail store.
CMsvPlainBodyText* iPlainBodyText;
CImConvertCharconv& iConverter;
TBool iPreparedToConvert;
TImCodec* iEncoder;
TInt iMaxLength;
TBool iUseRichText;
TInt iBodySize;
TInt iPos;
TImEncodingType iBodyEncoding;
HBufC8* iLeftOver;
// Buffer used for extracting line of body text from restored chunk.
RBuf iCurrentChunk;
// Indicates whether a chunk needs to be restored from Message Store.
TBool iIsNewChunk;
};
// This class creates lines to send from files,
// the files can be encoded using any of the available encoding techniques.
//----------------------------------------------------------------------------------------
class CImSendFile : public CBase
//----------------------------------------------------------------------------------------
/**
@internalComponent
@released
*/
{
private:
enum TImSplitLine
{
EFirstLine = 0,
ESecondLine
};
// Length of source text buffer used when encoding and outputting.
// Taking into account that the length may increase.
enum TImAttachmentSend
{
ENextFile = 0,
EPrefixLines,
EEncodeFile,
EPostfixLines,
EEndOfAttachments,
ECloseDelimiter,
ECRLFLine,
EEnd
};
public:
static CImSendFile* NewLC(RFs& anFs, CImConvertCharconv& aCharConv);
static CImSendFile* NewL(RFs& anFs, CImConvertCharconv& aCharConv);
~CImSendFile();
void InitialiseL( CMsvServerEntry& aServerEntry, TImFileCodec& anEncoder);
TInt NextLineL( TDes8& rOutputLine, TInt& rPaddingCount );
inline TInt BlankLine( TDes8& rOutputLine, TInt& rPaddingCount );
const TFileName& Filename() const;
TFileName& Filename( CMsvServerEntry& aEntry, SAttachmentInfo& aInfo);
static void EmbeddedEmailFilename(TMsvEntry& aEntry, TFileName& aFileName);
inline TInt Size() const;
private:
CImSendFile(RFs& anFs, CImConvertCharconv& aCharConv);
void ConstructL();
private:
const RFs& iFs;
TImFileCodec* iEncoder; // Either B64 or UU encoder or none
CImConvertCharconv& iConverter;
SAttachmentInfo iAttachmentInfo;
TImAttachmentFile* iAttachmentFile;
TBuf8<KDecodeLineLength> iSourceLine;
CImMimeHeader* iMimeHeader; // Passed in.
TInt iAttachmentState; // so dont change there order
TInt iFileIndex; // The following are init'ed in the Ctor list
TInt iBodyHeaderState;
TInt iPrefixState;
TInt iPostfixState;
};
//----------------------------------------------------------------------------------------
class CImCalculateMsgSize : public CMsgActive
//----------------------------------------------------------------------------------------
/**
@internalTechnology
@released
*/
{
public:
IMPORT_C static CImCalculateMsgSize* NewL(RFs &anFs,CMsvServerEntry& aServerEntry);
IMPORT_C ~CImCalculateMsgSize();
IMPORT_C void StartL(TRequestStatus& aStatus,TMsvId aMsvId,
TImSendMethod aAlgorithm, TTime& aTimeDate,
const TDesC& aDomainName, const TUint aCharset);
inline TInt MessageSize() const; // total size of Email - once active object has completed
inline void Progress(TInt& aBytes, TInt& aTotal); // current info on size of Email
private:
void DoRunL();
void DoCancel();
private:
CImCalculateMsgSize(RFs &anFs,CMsvServerEntry& aServerEntry);
void ConstructL();
void Reset();
private:
RFs& iFs;
CMsvServerEntry& iServerEntry;
TMsvId iMsvId;
TInt iSize;
TInt iTotal;
CImSendMessage* iSendMsg;
TBuf8<KImMailMaxBufferSize> iMailString;
TBool iFinished;
#if defined (_DEBUG)
RFile iFile;
TBool iFileOpen;
#endif
};
#include <imcvsend.inl>
#endif