/*
* Copyright (c) 2002-2005 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: MeetingRequestSender implementation
*
*/
// INCLUDE FILES
#include <e32base.h>
#include <e32std.h>
#include <SendUi.h> // TSendingCapabilities
#include <e32svr.h>
#include <mtclreg.h> // CClientMtmRegistry
#include <mtclbase.h> // CBaseMtm
#include <miuthdr.h>
#include <txtrich.h>
#include <MuiuMsvUiServiceUtilities.h>
#include <s32mem.h> // CBufStore
#include <apmstd.h>
#include <mtmextendedcapabilities.hrh> // KUidMsvMtmQuerySupportLinks
#include <apgcli.h>
#include <mtmuids.h>
#include <mtmdef.h>
#include <CSendingServiceInfo.h>
#include <CMessageAddress.h>
#include <SendUiConsts.h> // UIDs for provider and service
#include <CMessageData.h> // CMessageData
#include <MeetingRequestData.h> // CMeetingRequestData
#include <senduisingleton.h>
#include "SendUiDummyMtm.h"
#include "SendUiOperationWait.h"
#include "SenduiDataUtils.h"
#include "SenduiFileRightsEngine.h"
#include "CSendUiAttachment.h"
#include <MeetingRequestIds.hrh>
#include "MeetingRequestSender.h"
namespace
{
_LIT8( KContentType, "multipart" );
_LIT8( KContentSubType,"/alternative; boundary=mr_part; method=");
_LIT( KMsgInvalidSessionEvent, "CMeetingRequestSender: Invalid session event %x" );
_LIT( KMsgEmptyAddreesseeArray,"CMeetingRequestSender:: Addressee array is empty! Message cannot be created." );
_LIT( KMailtoMatchPattern, "mailto:*" ); // this is never localized
const TInt KMailtoLength = 7; // "mailto:" length
// LOCAL CONSTANTS
// For address information separation (start)
const TUint KSendUiMsgAddressStartChar ('<');
// For address information separation (end)
const TUint KSendUiMsgAddressEndChar ('>');
const TInt KRichTextStoreGranularity = 512;
const TInt KContentSubTypeMaxLength( 60 );
const TUint KTransferBufAdditionalInfoMaxLen = 20;
}
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CMeetingRequestSender::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CMeetingRequestSender* CMeetingRequestSender::NewL( TSendingServiceParams* aParams )
{
CMeetingRequestSender* self = CMeetingRequestSender::NewLC( aParams );
CleanupStack::Pop();
return self;
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CMeetingRequestSender* CMeetingRequestSender::NewLC( TSendingServiceParams* aParams )
{
CMeetingRequestSender* self = new( ELeave ) CMeetingRequestSender( aParams->iCoeEnv, aParams->iSingleton );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::~CMeetingRequestSender()
// Destructor.
// -----------------------------------------------------------------------------
//
CMeetingRequestSender::~CMeetingRequestSender()
{
iServiceArray.ResetAndDestroy();
iServiceArray.Close();
delete iStore;
delete iClientMtm;
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::CMeetingRequestSender
// Constructor.
// -----------------------------------------------------------------------------
//
CMeetingRequestSender::CMeetingRequestSender( CCoeEnv& aCoeEnv, CSendUiSingleton& aSingleton ) :
CSendingService( aCoeEnv, aSingleton )
{
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::ConstructL()
{
InitializeServiceL();
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::PopulateServicesListL
// Populates given list with the services provided by this plugin.
// The ownership of the pointed objects remains.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::PopulateServicesListL(
RPointerArray<CSendingServiceInfo>& aList )
{
CleanupClosePushL( aList );
for ( TInt cc = 0; cc < iServiceArray.Count(); cc++ )
{
User::LeaveIfError( aList.Append( iServiceArray[cc] ) );
}
CleanupStack::Pop( &aList );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::CreateAndSendMessageL
// Creates message to be sent and calls MTM to send the message.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::CreateAndSendMessageL(
TUid aServiceUid,
const CMessageData* aMessageData,
TBool /*aLaunchEditorEmbedded*/)
{
if( !aMessageData ||
aServiceUid != KMeetingRequestSender ||
aMessageData->DataType() != KSenduiMsgDataMeetingRequest )
{
User::Leave( KErrNotSupported );
}
CMeetingRequestData* mrData = CMeetingRequestData::NewLC();
mrData->ReadFromBufferL( aMessageData->OpaqueData() );
InitResourcesL( mrData );
//In case of SMTP we just create message and don't check capabilities,
//because SMTP MTM doesn't understand capabilities at the moment.
if( iClientMtm->Type() == KSenduiMtmSmtpUid )
{
DoCreateAndSendMessageL( *aMessageData, mrData );
}
else
{
TUid supportMeetingRequestUid = TUid::Uid(KMtmUiSupportMeetingRequest);
TUid supportICalCapability = TUid::Uid(KMtmUiSupportICalCapability);
TInt capabilityResponse;
TInt errorCode = iClientMtm->QueryCapability(supportMeetingRequestUid, capabilityResponse);
//Check if Meeting request is supported at all. If not then leave.
if(errorCode == KErrNotSupported || capabilityResponse == 0)
{
User::Leave( KErrNotSupported );
}
errorCode = iClientMtm->QueryCapability(supportICalCapability, capabilityResponse);
//Check if MTM supports supportICalCapability.
if ( (errorCode != KErrNotSupported) && (capabilityResponse != 0))
{
DoCreateAndSendMessageL( *aMessageData, mrData );
}
else
{
TransferIdsToClientL( *aMessageData );
DoCreateAndSendMessageL( *aMessageData, mrData );
}
}
CleanupStack::PopAndDestroy( mrData );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::DoCreateAndSendMessageL
// Creates message to be sent and calls MTM to send the message.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::DoCreateAndSendMessageL(
const CMessageData& aMessageData,
CMeetingRequestData* aMeetingRequestData )
{
CreateMessageL( aMessageData );
TInt capabilityResponse;
//Capability to support some kind of body checked
TInt errorCode = iClientMtm->QueryCapability(
TUid::Uid( KUidMtmQuerySupportedBodyValue ),
capabilityResponse );
if(capabilityResponse)
{
SetBodyL( aMessageData );
}
AddAttachmentsL( aMessageData );
// Create message header(s)
CreateHeaderL( aMessageData, aMeetingRequestData );
iClientMtm->SaveMessageL();
//QueryCapability() can't be used here because client gives false answer.
//So only way to do this is check MTM type.
if(iClientMtm->Type() == KSenduiMtmSmtpUid)
{
if( !ValidateEmail( ) )
{
User::Leave( KErrCompletion );
}
}
SendEmailL( );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::TransferIdsToClientL
// Transfers meeting request IDs to client MTM.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::TransferIdsToClientL(
const CMessageData& aMessageData )
{
// Create copy of opaque data. Needed because InvokeSyncFunctionL wants
// non-const buffer.
HBufC8* tempBuf = aMessageData.OpaqueData().AllocLC();
TPtr8 ptr = tempBuf->Des();
// Dummy entry selection
CMsvEntrySelection* entrySelection = new ( ELeave ) CMsvEntrySelection;
CleanupStack::PushL( entrySelection );
//Send data to MTM with InvokeSyncFunction()
iClientMtm->InvokeSyncFunctionL(
KMTMSendMeetingRequestFunctionId,
*entrySelection,
ptr );
CleanupStack::PopAndDestroy( 2, tempBuf ); // entrySelection, buf
}
// ---------------------------------------------------------
// CMeetingRequestSender::ServiceProviderId
// Returns the id of the service provider.
// (other items were commented in a header).
// ---------------------------------------------------------
//
TUid CMeetingRequestSender::ServiceProviderId() const
{
return KMeetingRequestSender; // defined in SendUiConsts.h
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::InitializeServiceL
// Initializes service info.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::InitializeServiceL()
{
if( iServiceArray.Count() )
{
// Already initialized so do nothing
return;
}
CSendingServiceInfo* serviceInfo = CSendingServiceInfo::NewLC();
// Set service type.
serviceInfo->SetServiceProviderId( KMeetingRequestSender );
serviceInfo->SetServiceId( KMeetingRequestSender );
iServiceArray.AppendL( serviceInfo );
CleanupStack::Pop( serviceInfo );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::CreateMessageL
// Creates new message with subject. Index entry is initialized and
// new message is created in drafs folder.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::CreateMessageL(
const CMessageData& aMessageData )
{
CMsvEntry* draftEntry = iSingleton.MsvSessionL().GetEntryL( KMsvDraftEntryId );
CleanupStack::PushL(draftEntry);
iClientMtm->SetCurrentEntryL( draftEntry ); // mtm takes ownership
CleanupStack::Pop(draftEntry);
// Create new message under drafts
iClientMtm->CreateMessageL( iMailServiceId );
// Load email signature, if any
iClientMtm->LoadMessageL();
// Set message subject
iClientMtm->SetSubjectL( aMessageData.Subject() );
// Set attributes on index entry
TMsvEntry indexEntry = iClientMtm->Entry().Entry();
indexEntry.SetInPreparation( ETrue );
indexEntry.SetVisible( EFalse );
indexEntry.iDate.UniversalTime();
indexEntry.SetAttachment( EFalse );
iClientMtm->Entry().ChangeL( indexEntry );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::InitResourcesL
// Client MTM is initialized. Used SMTP service is validated.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::InitResourcesL(
CMeetingRequestData* aMeetingRequestData )
{
iMailServiceId = aMeetingRequestData->Mailbox();
if ( iMailServiceId == KMsvNullIndexEntryId )
{
User::Leave( KErrArgument );
}
ResolveClientMTMTypeL( iMailServiceId );
if ( iClientMtmType == KNullUid )
{
User::Leave( KErrArgument );
}
// Create client side MTM object.
delete iClientMtm;
iClientMtm = NULL;
iClientMtm = iSingleton.ClientMtmRegistryL().NewMtmL( iClientMtmType );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::ResolveClientMTMTypeL
// Resolves the client MTM type by using service id. KNullUid is returned if
// service id doesn't match to any available service.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::ResolveClientMTMTypeL( TMsvId aServiceId )
{
TInt i = 0;
CMsvEntrySelection* entrySelection =
MsvUiServiceUtilities::GetListOfAccountsL( iSingleton.MsvSessionL(), ETrue );
CleanupStack::PushL( entrySelection );
CMsvEntry* rootEntry = CMsvEntry::NewL(
iSingleton.MsvSessionL(),
KMsvRootIndexEntryId,
TMsvSelectionOrdering( KMsvNoGrouping, EMsvSortByNone, ETrue ) );
CleanupStack::PushL( rootEntry );
TMsvId msvId;
for ( i = 0; i < entrySelection->Count(); i++ )
{
msvId = entrySelection->At( i );
if ( msvId == aServiceId )
{
TMsvEntry tEntry = rootEntry->ChildDataL( msvId );
iClientMtmType = tEntry.iMtm;
break;
}
}
CleanupStack::PopAndDestroy( 2, entrySelection ); // entrySelection, rootEntry
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::SetBodyL
// Sets email body.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::SetBodyL(
const CMessageData& aMessageData )
{
// If body has been not set return immediately
if( !aMessageData.BodyText()->DocumentLength() )
{
return;
}
const CRichText& bodyText = *( aMessageData.BodyText() );
CRichText& mtmBody = iClientMtm->Body();
delete iStore;
iStore = NULL;
iStore = CBufStore::NewL( KRichTextStoreGranularity );
// If signature has been set then append it at the end of email
if ( mtmBody.DocumentLength() )
{
CRichText* text = CRichText::NewL(
static_cast<CEikonEnv&>( iCoeEnv ).SystemParaFormatLayerL(),
static_cast<CEikonEnv&>( iCoeEnv ).SystemCharFormatLayerL() );
CleanupStack::PushL( text );
TInt len1 = bodyText.DocumentLength();
TInt len2 = mtmBody.DocumentLength();
HBufC* buf = HBufC::NewLC( len1 );
TPtr ptr = buf->Des();
bodyText.Extract( ptr, 0 );
text->InsertL( 0, *buf );
CleanupStack::PopAndDestroy( buf );
len1 = text->DocumentLength();
text->InsertL( len1, CEditableText::EParagraphDelimiter );
len1 = text->DocumentLength();
text->InsertL( len1, mtmBody.Read( 0, len2 ) );
// Save and restore the rich text
TStreamId id = text->StoreL( *iStore );
mtmBody.RestoreL( *iStore, id );
CleanupStack::PopAndDestroy(text);
}
else
{
// Save and restore the rich text
TStreamId id = bodyText.StoreL( *iStore );
mtmBody.RestoreL( *iStore, id );
}
// Get access to protected data
CSendUiDummyMtm* mtm = ( CSendUiDummyMtm* ) iClientMtm;
mtm->SetCharFormatL( *bodyText.GlobalCharFormatLayer() );
mtm->SetParaFormatL( *bodyText.GlobalParaFormatLayer() );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::CreateHeaderL
// Create email headers. "Standard" and MIME header is initialized.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::CreateHeaderL(
const CMessageData& aMessageData,
CMeetingRequestData* aMeetingRequestData )
{
InitStdHeaderL( aMessageData );
//At the moment only way to check mime capability is to use iClientMtm->Type()
if(iClientMtm->Type() == KSenduiMtmSmtpUid)
{
InitMimeHeaderL( aMeetingRequestData );
}
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::InitStdHeaderL
// Initialize standard header. To, cc and bcc fields are set.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::InitStdHeaderL(
const CMessageData& aMessageData )
{
// Nothing to do if aTo array is empty
if ( aMessageData.ToAddressArray().Count() == 0 )
{
RDebug::Print( KMsgEmptyAddreesseeArray );
User::Leave( KErrArgument );
}
AddAddresseesL( EMsvRecipientTo, aMessageData.ToAddressArray() );
AddAddresseesL( EMsvRecipientCc, aMessageData.CcAddressArray() );
AddAddresseesL( EMsvRecipientBcc, aMessageData.BccAddressArray() );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::AddAddresseesL
// Add To addressees.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::AddAddresseesL(
TMsvRecipientType aRecipientType,
const CMessageAddressArray& aAddressees )
{
TInt i(0);
for( i = 0; i < aAddressees.Count(); i++ )
{
if( aAddressees[i]->Address().Length() > 0 )
{
// If address has an alias, process it
if( aAddressees[i]->Alias().Length() > 0 )
{
TPtrC alias = aAddressees[i]->Alias();
// Check if alias contains illegal characters. If it does
// remove them.
if( ( alias.Locate( KSendUiMsgAddressStartChar ) != KErrNotFound ) ||
( alias.Locate( KSendUiMsgAddressEndChar ) != KErrNotFound ) )
{
HBufC* aliasNew = alias.AllocLC();
RemoveIllegalChars( aliasNew );
iClientMtm->AddAddresseeL(
aRecipientType,
AttendeeAdressWithoutPrefix( aAddressees[i]->Address() ),
*aliasNew );
CleanupStack::PopAndDestroy( aliasNew );
}
else
{
iClientMtm->AddAddresseeL(
aRecipientType,
AttendeeAdressWithoutPrefix(aAddressees[i]->Address() ),
alias );
}
}
else
{
// Address entry didn't have alias
iClientMtm->AddAddresseeL( aRecipientType,
AttendeeAdressWithoutPrefix( aAddressees[i]->Address() ));
}
}
// Done setting one addressee
}
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::RemoveIllegalChars
// Remove illegal chars from string. Illegal chars are replaced with space
// and trimmed string is returned.
// Should everything be removed between KSendUiMsgAddressStartChar and
// KSendUiMsgAddressEndChar?
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::RemoveIllegalChars( HBufC* aCheckedString )
{
TInt stringLength = aCheckedString->Length();
TPtr string = aCheckedString->Des();
while( stringLength-- )
{
if( string[stringLength] == KSendUiMsgAddressStartChar ||
string[stringLength] == KSendUiMsgAddressEndChar )
{
string[stringLength] = CEditableText::ESpace;
}
}
string.TrimAll();
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::InitMimeHeaderL
// Mime message header is initialized with user defined content type.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::InitMimeHeaderL(
CMeetingRequestData* aMeetingRequestData )
{
CMsvEntry& entry = iClientMtm->Entry();
CMsvStore* msvStore = entry.EditStoreL();
CleanupStack::PushL( msvStore );
CImMimeHeader* header = CImMimeHeader::NewLC();
// Set content type
header->SetContentTypeL( KContentType );
TBuf8<KContentSubTypeMaxLength> subtype( KContentSubType() );
subtype.Append( aMeetingRequestData->MailHeaderMethod() );
header->SetContentSubTypeL( subtype );
header->StoreL( *msvStore );
msvStore->CommitL();
CleanupStack::PopAndDestroy( 2, msvStore );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::AddAttachmentsL
// Attachments are added to the email. Method will leave if there is not
// enough space for attachments.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::AddAttachmentsL(
const CMessageData& aMessageData )
{
TInt i(0);
CArrayPtrFlat<CSendUiAttachment>* attachments;
attachments = CSendUiAttachment::InitAttachmentArrayLCC(
aMessageData.AttachmentArray(),
aMessageData.AttachmentHandleArray(),
iCoeEnv.FsSession() );
// If there are no attachments, return immediately.
if( !attachments->Count() )
{
return;
}
// Get total size of attachments.
CSendUiFileRightsEngine* fileRightsEngine =
CSendUiFileRightsEngine::NewLC( iCoeEnv.FsSession() );
// Check if linked attachments are supported.
TInt supportsLinks = 0;
TUid uidQuery = { KUidMsvMtmQuerySupportLinks };
iClientMtm->QueryCapability( uidQuery, supportsLinks );
TInt totalSize = fileRightsEngine->CalculateTotalSizeOfFiles( attachments, supportsLinks );
CleanupStack::PopAndDestroy( fileRightsEngine );
// following will leave if there is not enough space
CheckDiskSpaceL( totalSize );
const RArray<RFile>& attHandles = aMessageData.AttachmentHandleArray();
const CDesCArray& attFilePaths = aMessageData.AttachmentArray();
for( i = 0; i < attachments->Count(); i++ )
{
AddAttachmentL( attachments->At(i), supportsLinks );
}
CleanupStack::PopAndDestroy(2); // *attachments, attacments
TMsvEntry entry = iClientMtm->Entry().Entry();
entry.SetAttachment( ETrue );
iClientMtm->Entry().ChangeL(entry);
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::AddAttachmentL
// Add attachment (file descriptor)
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::AddAttachmentL(
CSendUiAttachment* aAttachment,
TInt aLinksSupported )
{
TDataType mimeType;
CSendUiDataUtils* dataUtils = CSendUiDataUtils::NewL( iCoeEnv.FsSession() );
CleanupStack::PushL( dataUtils );
CSendUiOperationWait* waiter = CSendUiOperationWait::NewLC();
if ( aAttachment->Type() == CSendUiAttachment::EAttachmentPath )
{
dataUtils->ResolveFileMimeTypeL( *(aAttachment->Path()), mimeType );
if ( aLinksSupported )
{
iClientMtm->AddLinkedAttachmentL(
*(aAttachment->Path()), mimeType.Des8(), 0, waiter->iStatus );
}
else
{
iClientMtm->AddAttachmentL(
*(aAttachment->Path()), mimeType.Des8(), 0, waiter->iStatus );
}
}
else
{
dataUtils->ResolveFileMimeTypeL( *(aAttachment->Handle()), mimeType );
RFile attachmentFile;
User::LeaveIfError( attachmentFile.Duplicate( *(aAttachment->Handle()) ) );
CleanupClosePushL( attachmentFile );
// File handle ownership transferred.
iClientMtm->AddAttachmentL(
attachmentFile,
mimeType.Des8(),
NULL,
waiter->iStatus );
CleanupStack::Pop( &attachmentFile );
}
waiter->Start( iClientMtm );
CleanupStack::PopAndDestroy( 2, dataUtils ); // waiter, dataUtils
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::CheckDiskSpaceL
// Check if there are enough space for email (includes attachments). Leaves
// if there are not enough space.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::CheckDiskSpaceL(
TInt aMsgSize )
{
if( MsvUiServiceUtilities::DiskSpaceBelowCriticalLevelL(
iSingleton.MsvSessionL(), aMsgSize ) )
{
User::Leave( KErrDiskFull );
}
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::ValidateEmail
// Validates email before sending it. Returns true if email is valid.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CMeetingRequestSender::ValidateEmail( )
{
TMsvPartList msgCheckParts =
KMsvMessagePartBody |
KMsvMessagePartRecipient |
KMsvMessagePartOriginator |
KMsvMessagePartDate |
KMsvMessagePartDescription;
TMsvPartList msgFailParts =
iClientMtm->ValidateMessage( msgCheckParts );
return ( msgFailParts == KMsvMessagePartNone );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::SendEmailL
// Sends an email.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::SendEmailL( )
{
TMsvEntry entry = iClientMtm->Entry().Entry();
entry.SetInPreparation( EFalse );
entry.SetVisible( ETrue );
entry.SetSendingState( KMsvSendStateWaiting );
iClientMtm->Entry().ChangeL( entry );
iClientMtm->LoadMessageL();
entry = iClientMtm->Entry().Entry();
TMsvId id = entry.Id();
if( entry.Parent() != KMsvGlobalOutBoxIndexEntryId )
{
// move message to outbox
MoveMessageEntryL( KMsvGlobalOutBoxIndexEntryId );
}
CMsvEntrySelection* entrySelection;
entrySelection = new ( ELeave ) CMsvEntrySelection;
CleanupStack::PushL( entrySelection );
entrySelection->AppendL( iMailServiceId );
entrySelection->AppendL( id );
TBuf8<1> params;
CSendUiOperationWait* waiter = CSendUiOperationWait::NewLC();
CMsvOperation* op =
iClientMtm->InvokeAsyncFunctionL(
KMTMStandardFunctionsSendMessage,
*entrySelection,
params,
waiter->iStatus );
waiter->Start( op );
CleanupStack::PopAndDestroy( 2, entrySelection ); // entrySelectoin, waiter
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::MoveMessageEntryL
// Moves email to target folder (usually outbox).
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
void CMeetingRequestSender::MoveMessageEntryL( TMsvId aTarget )
{
TMsvSelectionOrdering sort;
// we want to also handle the invisible entries
sort.SetShowInvisibleEntries( ETrue );
// Take a handle to the parent entry
TMsvEntry msvEntry( iClientMtm->Entry().Entry() );
CMsvEntry* parentEntry =
CMsvEntry::NewL(
iClientMtm->Session(),
msvEntry.Parent(),
sort );
CleanupStack::PushL( parentEntry );
// Move original from the parent to the new location
parentEntry->MoveL( msvEntry.Id(), aTarget );
CleanupStack::PopAndDestroy( parentEntry );
}
// -----------------------------------------------------------------------------
// CMeetingRequestSender::AttendeeAdressWithoutPrefix
// Returns a new descriptor where "MAILTO:" prefix is removed if it existed.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TPtrC CMeetingRequestSender::AttendeeAdressWithoutPrefix( const TDesC& aAddress )
{
TPtrC attendeeAddrWithoutPrefix;
if ( aAddress.MatchF( KMailtoMatchPattern ) != KErrNotFound )
{
attendeeAddrWithoutPrefix.Set( aAddress.Mid( KMailtoLength ) );
}
else
{
attendeeAddrWithoutPrefix.Set( aAddress );
}
return attendeeAddrWithoutPrefix;
}
// -----------------------------------------------------------------------------
// TechnologyType
// -----------------------------------------------------------------------------
//
TUid CMeetingRequestSender::TechnologyTypeId( ) const
{
return KNullUid;
}
// END OF FILE