--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/email/pop3andsmtpmtm/clientmtms/src/SMTCMTM.CPP Thu Dec 17 08:44:11 2009 +0200
@@ -0,0 +1,1068 @@
+// 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:
+// Client MTM for the SMTP protocol
+//
+//
+
+#include <bautils.h> // BaflUtils::NearestLanguageFile()
+#include <txtrich.h> // CRichText
+
+#include <barsc.h> //RResourceFile
+#include <barsread.h>
+
+#include <msvstore.h> // CMsvStore
+#include <mtmdef.h> //KUidMtmQueryxxx & TMsvPartList flags
+#include <imcm.rsg>
+#include <mmsvattachmentmanager.h>
+#include <cmsvmimeheaders.h>
+#include <cemailaccounts.h>
+#include "CImAttachmentWaiter.h"
+#include "cmsvsmtpsendoperation.h"
+#include "MIUTHDR.H" //CImHeader
+#include "SMTCMTM.H"
+#include "MIUT_ERR.H"
+#include "IMCMMAIN.H"
+#include "IMCMUTIL.H"
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <mtmuidsdef.hrh>
+#include "timrfc822datefield.h"
+#include "miut_errconsts.h"
+#include "msvconsts.h"
+#include "cimmessagepart.h"
+#endif
+
+#include <msvenhancesearchsortutil.h>
+
+#if defined (_UNICODE)
+ #define KUidMsgInternetMailEditorDLL 0x10003C53 // (268450899)
+#else
+ #define KUidMsgInternetMailEditorDLL 0x100011AC // (268439980)
+#endif
+
+/**
+@internalTechnology
+*/
+
+EXPORT_C CSmtpClientMtm* CSmtpClientMtm::NewL(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aMsvSession)
+ {
+ CSmtpClientMtm* self = new(ELeave) CSmtpClientMtm(aRegisteredMtmDll, aMsvSession);
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+CSmtpClientMtm::CSmtpClientMtm(CRegisteredMtmDll& aRegisteredMtmDll, CMsvSession& aMsvSession)
+ : CBaseMtm(aRegisteredMtmDll, aMsvSession)
+ {
+ __DECLARE_NAME(_S("CSmtpClientMtm"));
+ }
+
+void CSmtpClientMtm::ConstructL()
+ {
+ iWait=CMsvOperationActiveSchedulerWait::NewLC();
+ CleanupStack::Pop(); // iWait
+
+ iImSmtpSettings = new (ELeave) CImSmtpSettings;
+ iHeader = CImHeader::NewLC();
+ CleanupStack::Pop(); // iHeader
+
+ //open the resource file
+ RResourceFile resourceFile;
+ OpenResourceFileL(resourceFile, Session().FileSession());
+ CleanupClosePushL(resourceFile);
+
+ HBufC8* buf = resourceFile.AllocReadLC(EMAIL_ADDRESS_FORMATTING_STRING);
+ TResourceReader reader;
+ reader.SetBuffer(buf);
+ iEmailAddressFormatString = (reader.ReadTPtrC()).AllocL();
+ CleanupStack::PopAndDestroy(2); // resourceFile (Close resourceFile), buf
+ }
+
+CSmtpClientMtm::~CSmtpClientMtm()
+/** Destructor. */
+ {
+ delete iWait;
+ delete iImSmtpSettings;
+ delete iHeader;
+ delete iSubject;
+ delete iEmailAddressFormatString;
+ delete iEntrySelection;
+ delete iImEmailOperation;
+ delete iAttachmentWaiter;
+ delete iEmailMessage;
+ }
+
+void CSmtpClientMtm::ResetData()
+ {
+ // The client MTM owns a number of objects which are used to store data
+ // from service settings and messages.
+ iAddresseeList->Reset();
+ iImSmtpSettings->Reset();
+
+ delete iSubject;
+ iSubject = NULL;
+
+ iHeader->Reset();
+ Body().Reset(); // discard old contents of CRichText object
+ }
+
+void CSmtpClientMtm::SaveMessageL()
+/** Commits cached changes to the current message context to the storage controlled
+by the Message Server. */
+ {
+ __ASSERT_DEBUG(iMsvEntry!=NULL,gPanic(ESmtcMTMNoCMsvEntrySet));
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvMessageEntryValue, gPanic(ESmtcMTMNotAMessageEntry));
+
+ StoreEmailMessageL();
+ }
+
+void CSmtpClientMtm::StoreEmailMessageL()
+ {
+ __ASSERT_DEBUG(KUidMsvMessageEntryValue==iMsvEntry->Entry().iType.iUid, gPanic(ESmtcMTMNotAMessageEntry));
+ CMsvStore* store = iMsvEntry->EditStoreL();
+ CleanupStack::PushL(store);
+
+ // Save the Email header stream...
+ iHeader->SetSubjectL(SubjectL());
+ const TInt numberOfRecipients=iAddresseeList->Count();
+ // put all addressees in the To: field...
+ for (TInt n=0 ; n < numberOfRecipients ; ++n)
+ {
+ // validation done by ValidateMessage()
+ switch(iAddresseeList->Type(n))
+ {
+ case EMsvRecipientTo:
+ iHeader->ToRecipients().AppendL(AddresseeList()[n]);
+ break;
+ case EMsvRecipientCc:
+ iHeader->CcRecipients().AppendL(AddresseeList()[n]);
+ break;
+ case EMsvRecipientBcc:
+ iHeader->BccRecipients().AppendL(AddresseeList()[n]);
+ break;
+ }
+ }
+
+ iHeader->StoreL(*store);
+ store->CommitL();
+
+ // NB the From field will be set by server MTM when the email message is sent
+
+ CleanupStack::PopAndDestroy();
+
+ TMsvEntry messageEntry=iMsvEntry->Entry();
+ CImEmailMessage* emailMessage = CImEmailMessage::NewLC(*iMsvEntry);
+
+ // now store the body text
+ emailMessage->StoreBodyTextL(messageEntry.Id(), Body(), iWait->iStatus);
+ iWait->Start(); // wait for the asynch operation to complete
+
+ //
+ // I have stored away all the email data,
+ // now update the TMsventry that represents
+ // the email to ensure that it is up to date
+ //
+ TInt32 totalSizeOfAllAttachments = GetAttachmentSizeL(*emailMessage, messageEntry.Id());
+
+ messageEntry.iSize = iHeader->DataSize() + Body().DocumentLength() + totalSizeOfAllAttachments;
+ messageEntry.iDescription.Set(iHeader->Subject());
+ messageEntry.iDate.UniversalTime();
+
+ // fix for DEF051564 - SMTP client MTM CreateMessageL not creating message in correct state
+ //
+ // since CreateMessageL creates message as in preparation and non-visible, the SaveMessageL
+ // must now make it visible and not in preparation
+ messageEntry.SetVisible(ETrue);
+ messageEntry.SetInPreparation(EFalse);
+
+ if (iHeader->ToRecipients().Count()>0)
+ messageEntry.iDetails.Set(iHeader->ToRecipients()[0]);
+ else if (iHeader->CcRecipients().Count())
+ messageEntry.iDetails.Set(iHeader->CcRecipients()[0]);
+ else if (iHeader->BccRecipients().Count())
+ messageEntry.iDetails.Set(iHeader->BccRecipients()[0]);
+ //else do nothing as there are no recipients yet!
+
+ if (totalSizeOfAllAttachments>0)
+ messageEntry.SetAttachment(ETrue);
+
+ // if there are multiple recipients then set the flag
+ if ((iHeader->ToRecipients().Count() + iHeader->CcRecipients().Count() + iHeader->BccRecipients().Count()) >=2)
+ messageEntry.SetMultipleRecipients(ETrue);
+
+ // update the contents of the message entry
+ iMsvEntry->ChangeL(messageEntry);
+
+ CleanupStack::PopAndDestroy(); // emailMessage
+ }
+
+EXPORT_C void CSmtpClientMtm::StoreSettingsL()
+/** Stores the current service settings from the object's cache in to the Central
+Repository for the current entry.
+
+The current entry must be a service. */
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvServiceEntryValue, gPanic(ESmtcMTMNotAServiceEntry));
+
+ CEmailAccounts* account = CEmailAccounts::NewLC();
+ TSmtpAccount id;
+ account->GetSmtpAccountL(iMsvEntry->Entry().Id(), id);
+ account->SaveSmtpSettingsL(id, *iImSmtpSettings);
+ CleanupStack::PopAndDestroy(account);
+ }
+
+EXPORT_C void CSmtpClientMtm::RestoreSettingsL()
+/** Loads into the object's cache the service settings from the Central Repository
+for the current entry. */
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvServiceEntryValue, gPanic(ESmtcMTMNotAServiceEntry));
+
+ CEmailAccounts* account = CEmailAccounts::NewLC();
+ TSmtpAccount id;
+ account->GetSmtpAccountL(iMsvEntry->Entry().Id(), id);
+ account->LoadSmtpSettingsL(id, *iImSmtpSettings);
+ CleanupStack::PopAndDestroy(account);
+ }
+
+void CSmtpClientMtm::LoadMessageL()
+/** Loads the cache with the message data for the current context. */
+ {
+ __ASSERT_DEBUG(iMsvEntry!=NULL,gPanic(ESmtcMTMNoCMsvEntrySet));
+ switch (iMsvEntry->Entry().iType.iUid)
+ {
+ case KUidMsvServiceEntryValue:
+ RestoreSettingsL();
+ break;
+ case KUidMsvMessageEntryValue:
+ RestoreEmailMessageL();
+ break;
+ };
+ }
+
+void CSmtpClientMtm::RestoreEmailMessageL()
+ {
+
+ // Get a reference to TMsvEnhanceSearchSortUtil instance set by CMsvSearchsortOpOnHeaderBody class
+ // If advanced search and sort is being performed than do not load the message header and body.
+ // These are loaded when the search criteria is known in DoFindL()
+ // For API's other than CMsvSearchsortOpOnHeaderBody-> FindInHeaderBodyL(), a call to LoadMessageL()
+ // loads the body and the header.
+
+ TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
+ if ( searchsortutil == NULL )
+ {
+ CMsvStore* msvStore = iMsvEntry->ReadStoreL();
+ CleanupStack::PushL(msvStore);
+
+ // message must have a CImHeader stream...if it's not there leave as there's something wrong
+ iHeader->RestoreL(*msvStore);
+
+ TPtrC subject = iHeader->Subject();
+ TPtrC to;
+ if (iHeader->ToRecipients().Count())
+ to.Set(iHeader->ToRecipients()[0]);
+ else if (iHeader->CcRecipients().Count())
+ to.Set(iHeader->CcRecipients()[0]);
+ else if (iHeader->BccRecipients().Count())
+ to.Set(iHeader->BccRecipients()[0]);
+ //else do nothing as there are no recipients!
+
+ SetSubjectL(subject);
+ SetAddresseeListL();
+
+ // Get the attachments and the body text...
+ TMsvEntry messageEntry=iMsvEntry->Entry();
+
+ CleanupStack::PopAndDestroy(); // msvStore
+ CImEmailMessage* emailMessage = CImEmailMessage::NewLC(*iMsvEntry);
+
+ GetBodyTextL(*emailMessage, messageEntry.Id());
+ TInt32 totalSizeOfAllAttachments = GetAttachmentSizeL(*emailMessage, messageEntry.Id());
+
+ messageEntry.iSize = iHeader->DataSize() + Body().DocumentLength() + totalSizeOfAllAttachments;
+ messageEntry.iDescription.Set(subject);
+ messageEntry.iDetails.Set(to);
+
+ // update the contents of the message entry
+ iMsvEntry->ChangeL(messageEntry);
+
+ CleanupStack::PopAndDestroy(); // emailMessage
+
+ }
+ }
+
+
+void CSmtpClientMtm::GetBodyTextL(CImEmailMessage& aMessage, TMsvId aMsvId)
+ {
+ CRichText* messageText = CRichText::NewL(iParaFormatLayer, iCharFormatLayer);
+ CleanupStack::PushL(messageText);
+
+ aMessage.GetBodyTextL(aMsvId, CImEmailMessage::EThisMessageOnly, *messageText,*iParaFormatLayer,*iCharFormatLayer);
+
+ Body().Reset();
+ Body().AppendTakingSolePictureOwnershipL(*messageText);
+
+ CleanupStack::PopAndDestroy();
+ }
+
+TInt32 CSmtpClientMtm::GetAttachmentSizeL(CImEmailMessage& aMessage, TMsvId aMsvId)
+ {
+ // Calculate the total size of all attachments associated with this message
+ TInt total=0;
+ aMessage.GetAttachmentsListL(iWait->iStatus, aMsvId, CImEmailMessage::EAllAttachments,CImEmailMessage::EThisMessageOnly);
+ iWait->Start(); // wait for the asynch operation to complete
+ TInt numAttachments=aMessage.AttachmentManager().AttachmentCount();
+ for (TInt n=0 ; n<numAttachments ; ++n)
+ {
+ CMsvAttachment* attachment = aMessage.AttachmentManager().GetAttachmentInfoL(n);
+ total+=attachment->Size();
+ delete attachment;
+ }
+ return total;
+ }
+
+CMsvOperation* CSmtpClientMtm::ReplyL(TMsvId aDestination, TMsvPartList aPartList, TRequestStatus& aCompletionStatus)
+/** Creates a reply message to the current message context.
+
+@return If successful, this is an asynchronously completing reply operation.
+If failed, this is a completed operation, with status set to the relevant error code.
+@param aDestination The entry to which to assign the reply
+@param aPartList Defines the parts that are to be copied from the original message into the reply
+@param aCompletionStatus The request status to be completed when the operation has finished
+*/
+ {
+ TMsvEmailTypeList msvEmailTypeList = 0;
+ TUid messageType = KUidMsgTypeSMTP;
+ return CImEmailOperation::CreateReplyL(aCompletionStatus, Session(), iMsvEntry->EntryId(), aDestination, aPartList, msvEmailTypeList, messageType);
+ }
+
+CMsvOperation* CSmtpClientMtm::ForwardL(TMsvId aDestination, TMsvPartList aPartList, TRequestStatus& aCompletionStatus)
+/** Creates a forwarded message from the current message context.
+
+@return If successful, this is an asynchronously completing forward message operation.
+If failed, this is a completed operation, with status set to the relevant error code.
+@param aDestination The entry to which to assign the forwarded message
+@param aPartList Defines the parts that are to be copied from the original message into the forwarded message
+@param aCompletionStatus The request status to be completed when the operation has finished
+*/
+ {
+ TMsvEmailTypeList msvEmailTypeList = 0;
+ TUid messageType = KUidMsgTypeSMTP;
+ return CImEmailOperation::CreateForwardL(aCompletionStatus, Session(), iMsvEntry->EntryId(), aDestination, aPartList, msvEmailTypeList, messageType);
+ }
+
+EXPORT_C void CSmtpClientMtm::SetSubjectL(const TDesC& aSubject)
+/** Sets the message context's subject text.
+
+@param aSubject Subject text */
+ {
+ HBufC* newSubject= aSubject.AllocL();
+ delete iSubject;
+ iSubject = newSubject;
+ }
+
+EXPORT_C const TPtrC CSmtpClientMtm::SubjectL() const
+/** Gets the message context's subject text.
+
+@return Subject text */
+ {
+ // NB won't ever leave
+ return (iSubject) ? TPtrC(*iSubject) : TPtrC();
+ }
+
+TMsvPartList CSmtpClientMtm::ValidateMessage(TMsvPartList aPartList)
+/** Validates the current message context.
+
+The addresses for the message are checked to be well-formed email addresses.
+
+@param aPartList Indicates the message parts for which validation is requested
+@return If valid, KErrNone If invalid, identifies the invalid part(s). The
+error value is the bitmask of the TMsvPartList IDs for each invalid part */
+ {
+ __ASSERT_DEBUG(iMsvEntry!=NULL,gPanic(ESmtcMTMNoCMsvEntrySet));
+
+ TMsvPartList failed(0);
+ if (aPartList & KMsvMessagePartRecipient)
+ {
+ if (iAddresseeList->Count() == 0)
+ failed |= KMsvMessagePartRecipient;
+ else
+ {
+ // check the recipient list for valid 'addresses'
+ for (TInt ii=0; ii < iAddresseeList->Count(); ++ii)
+ {
+ if (((*iAddresseeList)[ii].Length() == 0) || !ValidateAddress((*iAddresseeList)[ii]))
+ {
+ failed |= KMsvMessagePartRecipient;
+ break;
+ }
+ }
+ }
+ }
+ return failed;
+ }
+
+TBool CSmtpClientMtm::ValidateAddress(const TPtrC& anAddress)
+ {
+ return iTImMessageField.ValidInternetEmailAddress(anAddress);
+ }
+
+TMsvPartList CSmtpClientMtm::DoFindL(const TDesC& aTextToFind, TMsvPartList aPartList)
+ {
+ CImClientMTMUtils* clientMTMUtils = CImClientMTMUtils::NewL();
+ CleanupStack::PushL(clientMTMUtils);
+
+ TMsvPartList retList = KMsvMessagePartNone;
+
+ // Get a reference to TMsvEnhanceSearchSortUtil instance set by CMsvSearchsortOpOnHeaderBody class
+ TMsvEnhanceSearchSortUtil* searchsortutil = (TMsvEnhanceSearchSortUtil*)(GetExtensionData());
+
+ // searchsortuitl variable will not be NULL for Advanced Search and Sort called from CMsvSearchsortOpOnHeaderBody
+ // For the old implementation, it will be NULL
+ if(searchsortutil != NULL)
+ {
+ // Get the searchsort setting flags
+ TUint32 searchsortsetting=searchsortutil->GetSearchSortSetting();
+
+ // The body was not loaded in LoadMessageL()
+ // If 2 search query options are on the body or on the header, than it sets EMessagePartBodyLoaded flag
+ // or EMessagePartHeaderLoaded of searchsortsetting
+ if(aPartList & KMsvMessagePartBody && !(searchsortsetting & EMessagePartBodyLoaded))
+ {
+ // Restore the body
+
+ Body().Reset();
+ // Get the attachments and the body text...
+ TMsvEntry messageEntry=iMsvEntry->Entry();
+ CImEmailMessage* emailMessage = CImEmailMessage::NewLC(*iMsvEntry);
+ GetBodyTextL(*emailMessage, messageEntry.Id());
+ CleanupStack::PopAndDestroy(); // emailMessage
+ searchsortutil->SetSearchSortSetting(EMessagePartBodyLoaded);
+ }
+ else if (!(searchsortsetting & EMessagePartHeaderLoaded))
+ {
+ // Restore the header
+ CMsvStore* msvStore = iMsvEntry->ReadStoreL();
+ CleanupStack::PushL(msvStore);
+
+ // message must have a CImHeader stream...if it's not there leave as there's something wrong
+ iHeader->RestoreL(*msvStore);
+
+ TPtrC subject = iHeader->Subject();
+ TPtrC to;
+ if (iHeader->ToRecipients().Count())
+ to.Set(iHeader->ToRecipients()[0]);
+ else if (iHeader->CcRecipients().Count())
+ to.Set(iHeader->CcRecipients()[0]);
+ else if (iHeader->BccRecipients().Count())
+ to.Set(iHeader->BccRecipients()[0]);
+ //else do nothing as there are no recipients!
+
+ SetSubjectL(subject);
+ SetAddresseeListL();
+
+ // Get the attachments and the body text...
+ TMsvEntry messageEntry=iMsvEntry->Entry();
+
+ CleanupStack::PopAndDestroy(); // msvStore
+ searchsortutil->SetSearchSortSetting(EMessagePartHeaderLoaded);
+ }
+
+ // Issue a request to FindL
+ clientMTMUtils->FindL(aTextToFind, Body(), *iHeader, aPartList, retList);
+
+ /* Copy the sort data if sorting is specified.
+ The operations being performed could be only be sort or it could be search and sort
+ If the operation is search and sort than copy the sort data only if the
+ search operation succeeded */
+
+ if ((searchsortsetting & EMessagePartSort ) || (((searchsortsetting & EMessagePartSearchSort) && (searchsortsetting & EMessagePartLastQueryOption) && (retList))))
+ {
+ /* Copy the data to be sorted from the header stream.
+ This done by setting iExtensionData to point to the field being copied */
+
+ if (iHeader)
+ {
+ if (searchsortsetting & EMessagePartToSort )
+ {
+ SetExtensionData((TAny*)&iHeader->ToRecipients());
+ }
+ else if(searchsortsetting & EMessagePartCcSort)
+ {
+ SetExtensionData((TAny*)&iHeader->CcRecipients());
+ }
+ else if(searchsortsetting & EMessagePartBccSort)
+ {
+ SetExtensionData((TAny*)&iHeader->BccRecipients());
+ }
+ else if(searchsortsetting & EMessagePartFromSort)
+ {
+ SetExtensionData((TAny*)(iHeader->From().Ptr()));
+ }
+ else if(searchsortsetting & EMessagePartSubjectSort)
+ {
+ SetExtensionData((TAny*)(iHeader->Subject().Ptr()));
+ }
+ }
+ }
+ }
+ else
+ {
+
+ clientMTMUtils->FindL(aTextToFind, Body(), *iHeader, aPartList, retList);
+ }
+ CleanupStack::PopAndDestroy(clientMTMUtils);
+ return retList;
+ }
+
+TMsvPartList CSmtpClientMtm::Find(const TDesC& aTextToFind, TMsvPartList aPartList)
+/** Searches the specified message part(s) for the plain-text version of the text
+to be found.
+
+@param aTextToFind The plain-text version of the text to be found.
+@param aPartList Indicates the message parts which should be searched.
+@return If the text was not found, or searching is unsupported, 0. If the text
+was found, a bitmask of the TMsvPartList IDs for each part in which the text
+was present. */
+ {
+ TMsvPartList retList = KMsvMessagePartNone;
+ TRAPD(ret, retList = DoFindL(aTextToFind, aPartList));
+ return retList;
+ }
+
+void CSmtpClientMtm::AddAddresseeL(const TDesC& aRealAddress)
+/** Adds an addressee for the current context.
+
+@param aRealAddress String representing an address to be added to the list
+for the current message */
+ {
+ iAddresseeList->AppendL(EMsvRecipientTo, aRealAddress);
+ }
+
+void CSmtpClientMtm::SetAddresseeListL()
+ {
+ // fill in the addressee list from the contents of iHeader
+ // copy all of the recipient addresses into the addressee list
+
+ iAddresseeList->Reset();
+ TInt numberOfRecipients=iHeader->ToRecipients().Count();
+ TInt n;
+ for (n=0 ; n < numberOfRecipients ; ++n)
+ {
+ TPtrC addressWithoutAlias = iTImMessageField.GetValidInternetEmailAddressFromString(iHeader->ToRecipients()[n]);
+ AddAddresseeL(EMsvRecipientTo, addressWithoutAlias);
+ }
+
+ numberOfRecipients=iHeader->CcRecipients().Count();
+ for (n=0 ; n < numberOfRecipients ; ++n)
+ {
+ TPtrC addressWithoutAlias = iTImMessageField.GetValidInternetEmailAddressFromString(iHeader->CcRecipients()[n]);
+ AddAddresseeL(EMsvRecipientCc, addressWithoutAlias);
+ }
+
+ // there shouldn't be any Bcc: addresses in an incoming email
+ // but add them anyway?
+ numberOfRecipients=iHeader->BccRecipients().Count();
+ for (n=0 ; n < numberOfRecipients ; ++n)
+ {
+ TPtrC addressWithoutAlias = iTImMessageField.GetValidInternetEmailAddressFromString(iHeader->BccRecipients()[n]);
+ AddAddresseeL(EMsvRecipientBcc, addressWithoutAlias);
+ }
+ }
+
+void CSmtpClientMtm::AddAddresseeL(const TDesC& aRealAddress, const TDesC& aAlias)
+/** Adds an addressee with an alias for the current context.
+
+@param aRealAddress String representing an address to be added to the list
+for the current message
+@param aAlias Alias information */
+ {
+ HBufC* emailAddress = HBufC::NewLC(aRealAddress.Length()+aAlias.Length()+iEmailAddressFormatString->Length()-4);
+ emailAddress->Des().Format(*iEmailAddressFormatString,&aAlias,&aRealAddress);
+ iAddresseeList->AppendL(EMsvRecipientTo, *emailAddress);
+ CleanupStack::PopAndDestroy(); // emailAddress
+ }
+
+void CSmtpClientMtm::RemoveAddressee(TInt aIndex)
+/** Removes an address from the current address list.
+
+@param aIndex Index of address to be removed */
+ {
+ if (iAddresseeList->Count() > aIndex)
+ iAddresseeList->Delete(aIndex);
+ }
+
+void CSmtpClientMtm::AddAddresseeL(TMsvRecipientType aType, const TDesC& aRealAddress)
+ {
+ iAddresseeList->AppendL(aType, aRealAddress);
+ }
+
+void CSmtpClientMtm::AddAddresseeL(TMsvRecipientType aType, const TDesC& aRealAddress, const TDesC& aAlias)
+ {
+ HBufC* emailAddress = HBufC::NewLC(aRealAddress.Length()+aAlias.Length()+iEmailAddressFormatString->Length()-4);
+ emailAddress->Des().Format(*iEmailAddressFormatString,&aAlias,&aRealAddress);
+ iAddresseeList->AppendL(aType, *emailAddress);
+ CleanupStack::PopAndDestroy(emailAddress);
+ }
+
+void CSmtpClientMtm::ContextEntrySwitched()
+ {
+ ResetData();
+ }
+
+TInt CSmtpClientMtm::QueryCapability(TUid aCapability, TInt& aResponse)
+/** Queries if the MTM supports a particular capability, specified by a UID.
+
+@param aCapability UID of capability to be queried
+@param aResponse Response value. The format of the response varies according
+to the capability.
+@return KErrNone: aCapability is a recognised value and a response is returned
+KErrNotSupported: aCapability is not a recognised value */
+ {
+ TInt error = KErrNone;
+ switch (aCapability.iUid)
+ {
+ // Supported:
+ case KUidMtmQueryMaxBodySizeValue:
+ case KUidMtmQueryMaxTotalMsgSizeValue:
+ aResponse = KMaxTInt;
+ break;
+ case KUidMsvMtmQueryEditorUidValue:
+ aResponse = KUidMsgInternetMailEditorDLL;
+ break;
+ case KUidMtmQuerySupportedBodyValue:
+ aResponse = KMtm7BitBody + KMtm8BitBody + KMtm16BitBody + KMtmBinaryBody;
+ break;
+ case KUidMtmQuerySupportSubjectValue:
+ case KUidMtmQuerySupportAttachmentsValue:
+ case KUidMtmQueryCanSendMsgValue:
+ case KUidMtmQuerySupportsRecipientTypeValue:
+ case KUidMtmQuerySendAsMessageSendSupportValue:
+ break;
+ // All others - Not Supported:
+ default:
+ error = KErrNotSupported;
+ }
+ return error;
+ }
+
+EXPORT_C void CSmtpClientMtm::SetSettingsL(const CImSmtpSettings& aSettings)
+/** Copies the specified service settings to the cached service settings.
+
+@param aSettings New service settings */
+ {
+ iImSmtpSettings->CopyL(aSettings);
+ }
+
+EXPORT_C const CImSmtpSettings& CSmtpClientMtm::Settings() const
+/** Gets the current cached service settings.
+
+@return The current cached service settings */
+ {
+ __ASSERT_DEBUG(iImSmtpSettings!=NULL, User::Invariant());
+ return *iImSmtpSettings;
+ }
+
+void CSmtpClientMtm::InvokeSyncFunctionL(TInt aFunctionId, const CMsvEntrySelection& aSelection, TDes8& aParameter)
+/** Invokes a synchronous SMTP-specific operation.
+
+@param aFunctionId Specifies which operation to perform. The only valid ID is KSMTPMTMIsConnected.
+@param aSelection A selection of messages for the operation.
+@param aParameter Not used
+*/
+ {
+ __ASSERT_DEBUG(iMsvEntry!=NULL,gPanic(ESmtcMTMNoCMsvEntrySet));
+
+ TInt error = KErrNone;
+ switch (aFunctionId)
+ {
+ case KSMTPMTMIsConnected:
+ {
+ TPckgBuf<TImSmtpProgress> progress;
+ Session().TransferCommandL(aSelection, KSMTPMTMIsConnected, aParameter, progress);
+ aParameter.Copy(progress);
+ return;
+ }
+ default:
+ error=KErrNotSupported;
+ __ASSERT_DEBUG(EFalse,gPanic(ESmtcUnknownSyncFunction));
+ }
+
+ User::LeaveIfError(error);
+ }
+
+CMsvOperation* CSmtpClientMtm::InvokeAsyncFunctionL(TInt aFunctionId, const CMsvEntrySelection& aSelection,
+ TDes8& aParameter, TRequestStatus& aCompletionStatus)
+/** Invokes asynchronous SMTP-specific operations.
+
+@param aFunctionId Specifies which operation to perform e.g. connect, copy
+new mail etc. The specific operations are defined by the TSmtpCmds enumeration.
+@param aSelection A selection of messages that need to be copied/moved to a
+local folder. The first entry in this selection MUST be the service.
+@param aParameter Not used
+@param aCompletionStatus The status when the operation completes.
+@leave KErrNotFound The selection of email to be moved or copied is empty
+@leave KErrNotSupported The specified operation is not recognised
+@return If successful, this is an asynchronously completing operation. If failed,
+this is a completed operation, with status set to the relevant error code.
+@see TSmtpCmds */
+ {
+ switch(aFunctionId)
+ {
+ case KMTMStandardFunctionsSendMessage:
+ return CMsvSmtpProgressOperation::NewL(Session(), aSelection, KSMTPMTMSendOnNextConnection, aParameter, aCompletionStatus);
+ case KSMTPMTMSendOnNextConnection:
+ return (Session().TransferCommandL(aSelection, aFunctionId, aParameter, aCompletionStatus));
+ case KSMTPMTMCreateNewEmailMessage:
+ case KSMTPMTMCreateReplyEmailMessage:
+ case KSMTPMTMCreateForwardEmailMessage:
+ case KSMTPMTMCreateForwardAsAttachmentEmailMessage:
+ case KSMTPMTMCreateReceiptEmailMessage:
+ {
+ TImCreateMessageOptions createMessageOptions;
+ TPckgC<TImCreateMessageOptions> paramPack(createMessageOptions);
+ paramPack.Set(aParameter);
+ switch (aFunctionId)
+ {
+ case KSMTPMTMCreateNewEmailMessage:
+ return iImEmailOperation->CreateNewL(aCompletionStatus, iMsvEntry->Session(), aSelection[0], paramPack().iMsvPartList, paramPack().iMsvEmailTypeList, paramPack().iMessageType);
+ case KSMTPMTMCreateReplyEmailMessage:
+ return iImEmailOperation->CreateReplyL(aCompletionStatus, iMsvEntry->Session(), aSelection[1], aSelection[0], paramPack().iMsvPartList, paramPack().iMsvEmailTypeList, paramPack().iMessageType);
+ case KSMTPMTMCreateForwardEmailMessage:
+ return iImEmailOperation->CreateForwardL(aCompletionStatus, iMsvEntry->Session(), aSelection[1], aSelection[0], paramPack().iMsvPartList, paramPack().iMsvEmailTypeList, paramPack().iMessageType);
+ case KSMTPMTMCreateForwardAsAttachmentEmailMessage:
+ return iImEmailOperation->CreateForwardAsAttachmentL(aCompletionStatus, iMsvEntry->Session(), aSelection[1], aSelection[0], paramPack().iMsvPartList, paramPack().iMsvEmailTypeList, paramPack().iMessageType);
+ case KSMTPMTMCreateReceiptEmailMessage:
+ return iImEmailOperation->CreateReceiptL(aCompletionStatus, iMsvEntry->Session(), aSelection[1], aSelection[0], paramPack().iMsvPartList, paramPack().iMsvEmailTypeList, paramPack().iMessageType);
+ }
+ }
+ break;
+ default:
+ User::Leave(KErrNotSupported);
+ };
+ return NULL;
+ }
+
+// Attachment functions to support the SendAs API
+
+EXPORT_C void CSmtpClientMtm::AddAttachmentL(const TDesC& aFilePath, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvMessageEntryValue, gPanic(ESmtcMTMNotAMessageEntry));
+
+ if( iAttachmentWaiter == NULL )
+ {
+ iAttachmentWaiter = CImAttachmentWaiter::NewL();
+ }
+
+ if (iEmailMessage == NULL)
+ {
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+ else if (iEmailMessage->EmailEntryId() != iMsvEntry->EntryId())
+ {
+ delete iEmailMessage;
+ iEmailMessage = NULL;
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+
+ CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
+ CleanupStack::PushL(attachmentInfo);
+
+ attachmentInfo->SetMimeTypeL(aMimeType);
+ TParse fileNameParser;
+ User::LeaveIfError(fileNameParser.Set(aFilePath, NULL, NULL));
+ attachmentInfo->SetAttachmentNameL(fileNameParser.NameAndExt());
+ if( aCharset!=0 )
+ {
+ CMsvMimeHeaders* headers = CMsvMimeHeaders::NewLC();
+ headers->SetMimeCharset(aCharset);
+ headers->StoreL(*attachmentInfo);
+ CleanupStack::PopAndDestroy(headers);
+ }
+
+ iEmailMessage->AttachmentManager().AddAttachmentL(aFilePath, attachmentInfo, iAttachmentWaiter->iStatus);
+ CleanupStack::Pop(attachmentInfo);// ownership passed to attachment manager
+
+ iAttachmentWaiter->StartWaitingL(aStatus, iEmailMessage, EFalse);
+ }
+
+EXPORT_C void CSmtpClientMtm::AddAttachmentL(RFile& aFile, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvMessageEntryValue, gPanic(ESmtcMTMNotAMessageEntry));
+
+ if( iAttachmentWaiter == NULL )
+ {
+ iAttachmentWaiter = CImAttachmentWaiter::NewL();
+ }
+
+ if (iEmailMessage == NULL)
+ {
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+ else if (iEmailMessage->EmailEntryId() != iMsvEntry->EntryId())
+ {
+ delete iEmailMessage;
+ iEmailMessage = NULL;
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+
+ CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
+ CleanupStack::PushL(attachmentInfo);
+
+ attachmentInfo->SetMimeTypeL(aMimeType);
+ TFileName fileName;
+ aFile.Name(fileName);
+ attachmentInfo->SetAttachmentNameL(fileName);
+ if( aCharset!=0 )
+ {
+ CMsvMimeHeaders* headers = CMsvMimeHeaders::NewLC();
+ headers->SetMimeCharset(aCharset);
+ headers->StoreL(*attachmentInfo);
+ CleanupStack::PopAndDestroy(headers);
+ }
+
+ iEmailMessage->AttachmentManager().AddAttachmentL(aFile, attachmentInfo, iAttachmentWaiter->iStatus);
+ CleanupStack::Pop(attachmentInfo);// ownership passed to attachment manager
+
+ iAttachmentWaiter->StartWaitingL(aStatus, iEmailMessage, EFalse);
+ }
+
+EXPORT_C void CSmtpClientMtm::AddLinkedAttachmentL(const TDesC& aFilePath, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvMessageEntryValue, gPanic(ESmtcMTMNotAMessageEntry));
+
+ if( iAttachmentWaiter == NULL )
+ {
+ iAttachmentWaiter = CImAttachmentWaiter::NewL();
+ }
+
+ if (iEmailMessage == NULL)
+ {
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+ else if (iEmailMessage->EmailEntryId() != iMsvEntry->EntryId())
+ {
+ delete iEmailMessage;
+ iEmailMessage = NULL;
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+
+ CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvLinkedFile);
+ CleanupStack::PushL(attachmentInfo);
+
+ attachmentInfo->SetMimeTypeL(aMimeType);
+
+ TParse fileNameParser;
+ User::LeaveIfError(fileNameParser.Set(aFilePath, NULL, NULL));
+ attachmentInfo->SetAttachmentNameL(fileNameParser.NameAndExt());
+
+ if( aCharset!=0 )
+ {
+ CMsvMimeHeaders* headers = CMsvMimeHeaders::NewLC();
+ headers->SetMimeCharset(aCharset);
+ headers->StoreL(*attachmentInfo);
+ CleanupStack::PopAndDestroy(headers);
+ }
+
+ iEmailMessage->AttachmentManager().AddLinkedAttachmentL(aFilePath, attachmentInfo, iAttachmentWaiter->iStatus);
+ CleanupStack::Pop(attachmentInfo);// ownership passed to attachment manager
+
+ iAttachmentWaiter->StartWaitingL(aStatus, iEmailMessage, EFalse);
+ }
+
+EXPORT_C void CSmtpClientMtm::AddEntryAsAttachmentL(TMsvId aAttachmentId, TRequestStatus& aStatus)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvMessageEntryValue, gPanic(ESmtcMTMNotAMessageEntry));
+
+ if( iAttachmentWaiter == NULL )
+ {
+ iAttachmentWaiter = CImAttachmentWaiter::NewL();
+ }
+
+ if (iEmailMessage == NULL)
+ {
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+ else if (iEmailMessage->EmailEntryId() != iMsvEntry->EntryId())
+ {
+ delete iEmailMessage;
+ iEmailMessage = NULL;
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+
+ CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvMessageEntry);
+ CleanupStack::PushL(attachmentInfo);
+
+ iEmailMessage->AttachmentManager().AddEntryAsAttachmentL(aAttachmentId, attachmentInfo, iAttachmentWaiter->iStatus);
+ CleanupStack::Pop(attachmentInfo);// ownership passed to attachment manager
+
+ iAttachmentWaiter->StartWaitingL(aStatus, iEmailMessage, EFalse);
+ }
+
+EXPORT_C void CSmtpClientMtm::CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, const TDesC8& aMimeType, TUint aCharset, TRequestStatus& aStatus)
+ {
+ __ASSERT_DEBUG(iMsvEntry->Entry().iType.iUid==KUidMsvMessageEntryValue, gPanic(ESmtcMTMNotAMessageEntry));
+
+ if( iAttachmentWaiter == NULL )
+ {
+ iAttachmentWaiter = CImAttachmentWaiter::NewL();
+ }
+
+ if (iEmailMessage == NULL)
+ {
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+ else if (iEmailMessage->EmailEntryId() != iMsvEntry->EntryId())
+ {
+ delete iEmailMessage;
+ iEmailMessage = NULL;
+ iEmailMessage = CImEmailMessage::NewL(*iMsvEntry);
+ }
+
+ CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);
+ CleanupStack::PushL(attachmentInfo);
+
+ attachmentInfo->SetAttachmentNameL(aFileName);
+ attachmentInfo->SetMimeTypeL(aMimeType);
+
+ if( aCharset!=0 )
+ {
+ CMsvMimeHeaders* headers = CMsvMimeHeaders::NewLC();
+ headers->SetMimeCharset(aCharset);
+ headers->StoreL(*attachmentInfo);
+ CleanupStack::PopAndDestroy(headers);
+ }
+
+ iEmailMessage->AttachmentManager().CreateAttachmentL(aFileName, aAttachmentFile, attachmentInfo, iAttachmentWaiter->iStatus);
+ CleanupStack::Pop(attachmentInfo);// ownership passed to attachment manager
+
+ iAttachmentWaiter->StartWaitingL(aStatus, iEmailMessage, EFalse);
+ }
+
+
+EXPORT_C void CSmtpClientMtm::CreateMessageL(TMsvId aServiceId)
+/** Creates a new message entry as a child of the current context.
+
+@param aServiceId ID of the service to own the entry. */
+ {
+ // fix for DEF051564 - SMTP client MTM CreateMessageL not creating message in correct state
+ TMsvEmailTypeList emailTypeList = KMsvEmailTypeListInvisibleMessage | KMsvEmailTypeListMessageInPreparation;
+
+ CEmailAccounts* account = CEmailAccounts::NewLC();
+
+ CImSmtpSettings* smtpSettings = new (ELeave) CImSmtpSettings;
+ CleanupStack::PushL(smtpSettings);
+ TSmtpAccount id;
+ account->GetSmtpAccountL(aServiceId, id);
+ account->LoadSmtpSettingsL(id, *smtpSettings);
+
+ switch (smtpSettings->BodyEncoding())
+ {
+ case EMsgOutboxMHTMLAsMIME:
+ case EMsgOutboxMHTMLAlternativeAsMIME:
+ emailTypeList |= KMsvEmailTypeListMHTMLMessage;
+ break;
+ case EMsgOutboxDefault:
+ case EMsgOutboxNoAlgorithm:
+ case EMsgOutboxMIME:
+ break;
+ }
+ CleanupStack::PopAndDestroy(2, account); // smtpSettings, account
+
+ // Now invoke the create new mail operation.
+ // Note that it is wrapped up to make the asynchronous call synchronous.
+ CMsvOperationActiveSchedulerWait* waiter=CMsvOperationActiveSchedulerWait::NewLC();
+ CImEmailOperation* createNewMailOp = CImEmailOperation::CreateNewL(waiter->iStatus, iMsvEntry->Session(), iMsvEntry->Entry().Id(), aServiceId, KMsvMessagePartBody|KMsvMessagePartAttachments, emailTypeList, KUidMsgTypeSMTP);
+ CleanupStack::PushL(createNewMailOp);
+ waiter->Start();
+
+ // The the entry is expected to be set to the new message.
+ TMsvId temp;
+ TPckgC<TMsvId> paramPack(temp);
+ const TDesC8& progBuf = createNewMailOp->ProgressL();
+ paramPack.Set(progBuf);
+ TMsvId messageId = paramPack();
+ iMsvEntry->SetEntryL(messageId);
+
+ CMsvStore* store = iMsvEntry->ReadStoreL();
+ CleanupStack::PushL(store);
+ iHeader->RestoreL(*store);
+
+ CleanupStack::PopAndDestroy(3, waiter); // waiter, createNewMailOp, store
+ }
+
+/**
+Gets the default SMTP service.
+
+@return
+The default service
+
+@leave
+KErrNotFound If default service setting does not exist.
+*/
+EXPORT_C TMsvId CSmtpClientMtm::DefaultServiceL() const
+ {
+ // Get default service Id from CenRep
+ CEmailAccounts* account = CEmailAccounts::NewLC();
+ TSmtpAccount id;
+ TInt error = account->DefaultSmtpAccountL(id);
+ if (error == KErrNotFound)
+ {
+ User::Leave(error);
+ }
+
+ CleanupStack::PopAndDestroy(account);
+ return id.iSmtpService;
+ }
+
+/**
+Removes the default SMTP service.
+*/
+EXPORT_C void CSmtpClientMtm::RemoveDefaultServiceL()
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+/**
+Sets the default SMTP service.
+
+@param aService
+The default service
+*/
+EXPORT_C void CSmtpClientMtm::ChangeDefaultServiceL(const TMsvId& aService)
+ {
+ CEmailAccounts* account = CEmailAccounts::NewLC();
+ TSmtpAccount id;
+ account->GetSmtpAccountL(aService, id);
+ account->SetDefaultSmtpAccountL(id);
+ CleanupStack::PopAndDestroy(account);
+ }
+
+/**
+Cancels the current attachment operation.
+*/
+EXPORT_C void CSmtpClientMtm::CancelAttachmentOperation()
+ {
+ if ( iAttachmentWaiter)
+ {
+ iAttachmentWaiter->Cancel();
+ }
+
+ if ( iWait )
+ {
+ iWait->Cancel();
+ }
+ }
+