diff -r 000000000000 -r 8466d47a6819 meetingrequest/mrtasks/src/cesmrsendmrfsmailtask.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/meetingrequest/mrtasks/src/cesmrsendmrfsmailtask.cpp Thu Dec 17 08:39:21 2009 +0200 @@ -0,0 +1,798 @@ +/* +* Copyright (c) 2007-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: Implementation for ESMR send MR via fs email task +* +*/ + + +#include "emailtrace.h" +#include "cesmrsendmrfsmailtask.h" +#include "cesmrcaldbmgr.h" +#include "mesmrmeetingrequestentry.h" +#include "cesmrfsemailmanager.h" +#include "cesmrmailplaitextformatter.h" +#include "cesmrcalimportexporter.h" +#include "cesmrcaluserutil.h" +#include "cesmrguilistquery.h" +#include "esmrhelper.h" + +#include +#include +#include +#include +#include +#include +#include + +// Unnamed namespace for local definitions +namespace { + +/** + * Adds updated label into summary field. + */ +void UpdateSummaryL( + CCalEntry& aEntry, + CESMRMailPlainTextFormatter& aPlainTextFormatter ) + { + FUNC_LOG; + TPtrC currentSummary( aEntry.SummaryL() ); + + CCalEntry::TMethod method( aEntry.MethodL() ); + if ( CCalEntry::EMethodRequest == method && aEntry.SequenceNumberL() ) + { + // This is update + HBufC* updateStr = aPlainTextFormatter.UpdatedStringLC(); + HBufC* summary = HBufC::NewLC( + updateStr->Length() + currentSummary.Length() ); + + if ( currentSummary.Find(*updateStr) == KErrNotFound ) + { + TPtr summaryPtr( summary->Des() ); + summaryPtr.Append( *updateStr ); + summaryPtr.Append( currentSummary ); + aEntry.SetSummaryL( summaryPtr ); + } + CleanupStack::PopAndDestroy( summary ); + summary = NULL; + + CleanupStack::PopAndDestroy( updateStr ); + updateStr = NULL; + } + else if ( CCalEntry::EMethodCancel == method ) + { + // This is cancellation + HBufC* cancelStr = aPlainTextFormatter.CanceledStringLC(); + HBufC* summary = HBufC::NewLC( + cancelStr->Length() + currentSummary.Length() ); + + if ( currentSummary.Find(*cancelStr) == KErrNotFound ) + { + TPtr summaryPtr( summary->Des() ); + summaryPtr.Append( *cancelStr ); + summaryPtr.Append( currentSummary ); + aEntry.SetSummaryL( summaryPtr ); + } + CleanupStack::PopAndDestroy( summary ); + summary = NULL; + + CleanupStack::PopAndDestroy( cancelStr ); + cancelStr = NULL; + } + } + +/** + * Cleanup operation for RPointerArray. + * + * @param aArray Pointer to RPointerArray. + */ +void CalAttendeePointerArrayCleanup( TAny* aArray ) + { + RPointerArray* attendeeArray = + static_cast*>( aArray ); + + attendeeArray->ResetAndDestroy(); + attendeeArray->Close(); + } + +#ifdef _DEBUG + +// Literal for panics +_LIT( ESMRSendMRRespMailPanicTxt, "ESMRSendMRFSEMailTask" ); + +// Panic codes +enum TESMRSendMRFSMailTaskPanic + { + EESMRSendMRFSMailInvalidMethod, + EESMRSendMRFSAttendeesMissing, + EESMRSendMRNoEntriesToSend + }; + +// ======== LOCAL FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// Panic wrapper method +// --------------------------------------------------------------------------- +// +void Panic( TESMRSendMRFSMailTaskPanic aPanic ) + { + + User::Panic( ESMRSendMRRespMailPanicTxt, aPanic ); + } + +#endif // _DEBUG + + +// Definition for temporary calendar file +// remove hard coded paths +//_LIT( KPath, "c:\\temp\\" ); //codescanner::driveletters +//_LIT( KFileAndPath, "c:\\temp\\meeting.ics" ); //codescanner::driveletters +//_LIT( KCancellationFile, "c:\\temp\\cancel.ics" ); //codescanner::driveletters +_LIT( KFile, "temp\\meeting.ics" ); +_LIT( KCancelFile, "temp\\cancel.ics" ); +// + +// --------------------------------------------------------------------------- +// Leave wrapper method +// --------------------------------------------------------------------------- +// +inline void DoLeaveIfErrorL( TInt aLeaveCode ) + { + if ( KErrNone != aLeaveCode ) + { + + User::Leave( aLeaveCode ); + } + } +} // namespace + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::CESMRSendMRFSMailTask +// --------------------------------------------------------------------------- +// +CESMRSendMRFSMailTask::CESMRSendMRFSMailTask( + MESMRCalDbMgr& aCalDbMgr, + MESMRMeetingRequestEntry& aEntry, + CMRMailboxUtils& aMRMailboxUtils, + TESMRCommand aCommand ) +: CESMRTaskBase( aCalDbMgr, aEntry, aMRMailboxUtils ), + iCommand( aCommand ) + { + FUNC_LOG; + //do nothing + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::~CESMRSendMRFSMailTask +// --------------------------------------------------------------------------- +// +CESMRSendMRFSMailTask::~CESMRSendMRFSMailTask() + { + FUNC_LOG; + iEntriesToSend.ResetAndDestroy(); + delete iCaluserUtil; + delete iEmailMgr; + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::NewL +// --------------------------------------------------------------------------- +// +CESMRSendMRFSMailTask* CESMRSendMRFSMailTask::NewL( + MESMRCalDbMgr& aCalDbMgr, + MESMRMeetingRequestEntry& aEntry, + CMRMailboxUtils& aMRMailboxUtils, + TESMRCommand aCommand ) + { + FUNC_LOG; + + CESMRSendMRFSMailTask* self = + new (ELeave) CESMRSendMRFSMailTask( + aCalDbMgr, + aEntry, + aMRMailboxUtils, + aCommand ); + + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + + return self; + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::ConstructL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::ConstructL() + { + FUNC_LOG; + BaseConstructL(); + iEmailMgr = CESMRFSEMailManager::NewL( MailboxUtils() ); + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::ExecuteTaskL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::ExecuteTaskL() + { + FUNC_LOG; + + iEntryToSend = ESMREntry().ValidateEntryL(); + + iCaluserUtil = CESMRCalUserUtil::NewL( *iEntryToSend ); + + CCalEntry::TMethod method( iEntryToSend->MethodL() ); + + // Checking input paramters + if( !(CCalEntry::EMethodRequest == method || + CCalEntry::EMethodCancel == method ) || + CCalEntry::EAppt != iEntryToSend->EntryTypeL() ) + { + DoLeaveIfErrorL( KErrArgument ); + } + + // Get entries to be sent + GetEntriesToBeSentL(); + ResolveSendTypeL(); + + if ( NeedToSendInvitationL() ) + { + TInt entryCount( iEntriesToSend.Count() ); + for (TInt i(0); i < entryCount; ++i ) + { + iEntryToSend = iEntriesToSend[i]; + ConstructMailL(); + TInt ret = iEmailMgr->SendMessageL(); + User::LeaveIfError(ret); + } + } + + if ( EESMRCmdSendMRUpdate == iCommand && + NeedToSendCancellationL() ) + { + delete iEmailMgr; iEmailMgr = NULL; + iEmailMgr = CESMRFSEMailManager::NewL( MailboxUtils() ); + + TInt entryCount( iEntriesToSend.Count() ); + for (TInt i(0); i < entryCount; ++i ) + { + // Sending cancellation to removed attendees + iEntryToSend = iEntriesToSend[i]; + iEntryToSend->SetMethodL( CCalEntry::EMethodCancel ); + + ConstructMailL(); + TInt ret = iEmailMgr->SendMessageL(); + User::LeaveIfError(ret); + } + } + + } + +// --------------------------------------------------------------------------- +// CESMRSendMRRespFSMailTask::ConstructMailL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::ConstructMailL() + { + FUNC_LOG; + + // create text formatter: + CESMRMailPlainTextFormatter* textFormatter = + CESMRMailPlainTextFormatter::NewLC( MailboxUtils() ); + + // Prepare email manager for sending + HBufC* mbOwnerAddr = ResolveUsedMailboxUserAddressLC(); + TPtrC emailAddr( ESMRHelper::AddressWithoutMailtoPrefix( *mbOwnerAddr ) ); + iEmailMgr->PrepareForSendingL( emailAddr ); + + TBool isForwarded( ESMREntry().IsForwardedL() ); + if ( isForwarded ) + { + CCalUser* organizer = iEntryToSend->OrganizerL(); + CCalUser* forwardOrganizer = + CCalUser::NewL( + organizer->Address(), + emailAddr ); + CleanupStack::PushL( forwardOrganizer ); + forwardOrganizer->SetCommonNameL( organizer->CommonName() ); + + // Ownership is transferred to entry + iEntryToSend->SetOrganizerL( forwardOrganizer ); + CleanupStack::Pop( forwardOrganizer ); + + iEmailMgr->SetSenderL( + forwardOrganizer->Address(),forwardOrganizer->CommonName() ); + + iEmailMgr->SetReplyToAddressL( + forwardOrganizer->Address(), forwardOrganizer->CommonName() ); + + organizer = NULL; + forwardOrganizer = NULL; + } + + CleanupStack::PopAndDestroy( mbOwnerAddr ); + + // set the email subject: + HBufC* subject = NULL; + if ( CCalEntry::EMethodRequest == iEntryToSend->MethodL() ) + { + subject = textFormatter->Subject16LC( + *iEntryToSend, + ESMREntry().IsForwardedL(), + EESMRCmdSendMRUpdate == iCommand ); + } + else + { + subject = textFormatter->Subject16LC( + *iEntryToSend, + ESMREntry().IsForwardedL(), + EFalse ); + } + + iEmailMgr->SetSubjectL( *subject ); + CleanupStack::PopAndDestroy( subject ); + subject = NULL; + + AddAttendeesL(); + + // Set text/plain part: + HBufC* body = textFormatter->Body16LC( *iEntryToSend ); + iEmailMgr->CreateTextPlainPartL( *body ); + CleanupStack::PopAndDestroy(body); + body = NULL; + + // export the calendar entry in iCal format: + UpdateSummaryL( *iEntryToSend, *textFormatter ); + + TInt priority( iEntryToSend->PriorityL() ); + SetCorrectAttendeesToEntryL(); + CESMRCalImportExporter* calExporter = CESMRCalImportExporter::NewLC(); + HBufC* calendarPart = calExporter->ExportToICal16LC( *iEntryToSend ); + + // Set text/calendar part: + CESMRFSEMailManager::TESMRMethod method( + CESMRFSEMailManager::EESMRMethodRequest); + + CCalEntry::TMethod entryMethod( iEntryToSend->MethodL() ); + switch ( entryMethod ) + { + case CCalEntry::EMethodRequest: + { + method = CESMRFSEMailManager::EESMRMethodRequest; + } + break; + case CCalEntry::EMethodCancel: + { + method = CESMRFSEMailManager::EESMRMethodCancel; + } + break; + case CCalEntry::EMethodReply://fallthrough, EMethodReply not needed + default: + break; + } + + if ( CCalEntry::EMethodCancel == entryMethod ) + { + // removing hardcoded paths + TFileName fileName(KCancelFile); + User::LeaveIfError(ESMRHelper::CreateAndAppendPrivateDirToFileName(fileName)); + SaveICalToFileL( *calendarPart, KCancelFile ); + iEmailMgr->CreateTextCalendarPartL(method, KCancelFile); + // + } + else + { + // removing hardcoded paths + TFileName fileName(KFile); + User::LeaveIfError(ESMRHelper::CreateAndAppendPrivateDirToFileName(fileName)); + SaveICalToFileL( *calendarPart, fileName ); + iEmailMgr->CreateTextCalendarPartL(method, fileName); + // + } + + CleanupStack::PopAndDestroy(3, textFormatter); + + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::SaveICalToFileL +// --------------------------------------------------------------------------- +// +TInt CESMRSendMRFSMailTask::SaveICalToFileL( const TDesC& aICal, + const TDesC& aFilename ) + { + FUNC_LOG; + //create 8 bit buffer for temp file content + TInt length = aICal.Length() * 2; + HBufC8* buffer = HBufC8::NewLC( length ); + TPtr8 des = buffer->Des(); + + // covert the 16 bit iCal to 8 bit iCal: + TInt err = CnvUtfConverter::ConvertFromUnicodeToUtf8(des, aICal); + + RFs& fs( CCoeEnv::Static()->FsSession() ); + + // ensure the path exists: + //remove hardcoded paths + //BaflUtils::EnsurePathExistsL(fs, KPath); + // + + // delete previous file + fs.Delete( aFilename ); + + // save the iCal to file system: + RFile file; + User::LeaveIfError(file.Create(fs, aFilename, EFileWrite)); + CleanupClosePushL(file); + User::LeaveIfError(file.Write(*buffer)); + + // clean up: + CleanupStack::PopAndDestroy(2, buffer); // file, fs, buffer + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::AddAttendeesL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::AddAttendeesL() + { + FUNC_LOG; + + RArray requiredAttendees; + CleanupClosePushL( requiredAttendees ); + + RArray optionalAttendees; + CleanupClosePushL( optionalAttendees ); + + GetAttendeesToBeSentL( requiredAttendees, optionalAttendees ); + + // Add recipients and cc-recipients + TInt attendeeCount( requiredAttendees.Count() ); + TInt optAttendeeCount( optionalAttendees.Count() ); + + __ASSERT_DEBUG( attendeeCount || optAttendeeCount, Panic(EESMRSendMRFSAttendeesMissing) ); + + if ( !attendeeCount && !optAttendeeCount) + { + DoLeaveIfErrorL( KErrArgument ); + } + + for (TInt i(0); i < attendeeCount; ++i) + { + TPtrC emailAddr( requiredAttendees[i]->Address() ); + + + iEmailMgr->AppendToRecipientL( + emailAddr, + requiredAttendees[i]->CommonName() ); + } + + for (TInt i(0); i < optAttendeeCount; ++i) + { + TPtrC emailAddr( optionalAttendees[i]->Address() ); + + + iEmailMgr->AppendCCRecipientL( + emailAddr, + optionalAttendees[i]->CommonName() ); + } + + CleanupStack::PopAndDestroy(2, &requiredAttendees ); + + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::ResolveUsedMailboxUserAddressLC +// --------------------------------------------------------------------------- +// +HBufC* CESMRSendMRFSMailTask::ResolveUsedMailboxUserAddressLC() + { + FUNC_LOG; + + HBufC* mailboxUserAddress = NULL; + MESMRMeetingRequestEntry& mrEntry( ESMREntry()); + if ( mrEntry.IsForwardedL() ) + { + // Entry is forwarded --> Use default mailbox + CMRMailboxUtils::TMailboxInfo mbInfo; + CMRMailboxUtils& mbUtils( MailboxUtils() ); + mbUtils.GetDefaultMRMailBoxL( mbInfo ); + mailboxUserAddress = mbInfo.iEmailAddress.AllocLC(); + } + else + { + CCalUser *mailboxUser = iEntryToSend->PhoneOwnerL(); + mailboxUserAddress = mailboxUser->Address().AllocLC(); + } + + return mailboxUserAddress; + } + + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::ResolveSendTypeL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::ResolveSendTypeL() + { + FUNC_LOG; + + if ( EESMRCmdSendMRUpdate == iCommand ) + { + RArray addedAttendees; + CleanupClosePushL( addedAttendees ); + + RArray removedAttendees; + CleanupClosePushL( removedAttendees ); + + ESMREntry().GetAddedAttendeesL( + addedAttendees, + EESMRRoleRequiredAttendee | EESMRRoleOptionalAttendee ); + ESMREntry().GetRemovedAttendeesL( + removedAttendees, + EESMRRoleRequiredAttendee | EESMRRoleOptionalAttendee ); + + if ( addedAttendees.Count() || removedAttendees.Count() ) + { + TInt sendType = CESMRGUIListQuery::ExecuteL( + CESMRGUIListQuery::EESMRSendUpdateToAllQuery ); + + if ( KErrCancel == sendType ) + { + User::Leave( KErrCancel ); + } + + iSendType = static_cast(sendType ); + } + + CleanupStack::PopAndDestroy( &removedAttendees ); + CleanupStack::PopAndDestroy( &addedAttendees ); + } + + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::NeedToSendInvitationL +// --------------------------------------------------------------------------- +// +TBool CESMRSendMRFSMailTask::NeedToSendInvitationL() + { + FUNC_LOG; + + TBool retValue( ETrue ); + + RArray addedAttendees; + CleanupClosePushL( addedAttendees ); + + if ( EESMRCmdSendMRUpdate == iCommand && + ESentToAddedAndRemoved == iSendType ) + { + ESMREntry().GetAddedAttendeesL( + addedAttendees, + EESMRRoleRequiredAttendee | EESMRRoleOptionalAttendee ); + + if ( !addedAttendees.Count() ) + { + retValue = EFalse; + } + } + + CleanupStack::PopAndDestroy( &addedAttendees ); + + + return retValue; + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::NeedToSendCancellationL +// --------------------------------------------------------------------------- +// +TBool CESMRSendMRFSMailTask::NeedToSendCancellationL() + { + FUNC_LOG; + + TBool retValue( EFalse ); + + RArray removedAttendees; + CleanupClosePushL( removedAttendees ); + + if ( EESMRCmdSendMRUpdate == iCommand ) + { + ESMREntry().GetRemovedAttendeesL( + removedAttendees, + EESMRRoleRequiredAttendee | EESMRRoleOptionalAttendee ); + + if ( removedAttendees.Count() ) + { + retValue = ETrue; + } + } + + CleanupStack::PopAndDestroy( &removedAttendees ); + + + return retValue; + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::NeedToSendCancellationL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::SetCorrectAttendeesToEntryL() + { + FUNC_LOG; + if ( EESMRCmdSendMRUpdate == iCommand ) + { + TESMRMailPlugin plugin( ESMREntry().CurrentPluginL() ); + + CCalEntry::TMethod method( iEntryToSend->MethodL() ); + + RArray requiredAttendees; + CleanupClosePushL( requiredAttendees ); + + RArray optionalAttendees; + CleanupClosePushL( optionalAttendees ); + + GetAttendeesToBeSentL( requiredAttendees, optionalAttendees ); + + RPointerArray attendees; + CleanupStack::PushL( + TCleanupItem( + CalAttendeePointerArrayCleanup, + &attendees ) ); + + + TInt attendeeCount( requiredAttendees.Count() ); + for ( TInt i(0); i < attendeeCount; ++i ) + { + // Make copy of the attendees + CCalAttendee* attendee = ESMRHelper::CopyAttendeeL(*requiredAttendees[i] ); + User::LeaveIfError( + attendees.Append( attendee ) ); + } + + TInt optionalAttendeeCount( optionalAttendees.Count() ); + for ( TInt i(0); i < optionalAttendeeCount; ++i ) + { + // Make copy of the attendees + CCalAttendee* attendee = ESMRHelper::CopyAttendeeL(*optionalAttendees[i] ); + User::LeaveIfError( + attendees.Append( attendee ) ); + } + + // Clean attendee array + while ( iEntryToSend->AttendeesL().Count() ) + { + iEntryToSend->DeleteAttendeeL( 0 ); + } + + while ( attendees.Count() ) + { + CCalAttendee* attendee = attendees[0]; + iEntryToSend->AddAttendeeL( attendee ); + attendees.Remove(0); + } + + CleanupStack::PopAndDestroy( &attendees ); + CleanupStack::PopAndDestroy( &optionalAttendees ); + CleanupStack::PopAndDestroy( &requiredAttendees ); + } + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::NeedToSendCancellationL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::GetAttendeesToBeSentL( + RArray& aRequiredAttendees, + RArray& aOptionalAttendees ) + { + FUNC_LOG; + CCalEntry::TMethod method( iEntryToSend->MethodL() ); + + if ( EESMRCmdSendMRUpdate == iCommand && + ESentToAddedAndRemoved == iSendType && + CCalEntry::EMethodRequest == method ) + { + ESMREntry().GetAddedAttendeesL( + aRequiredAttendees, + EESMRRoleRequiredAttendee ); + ESMREntry().GetAddedAttendeesL( + aOptionalAttendees, + EESMRRoleOptionalAttendee ); + } + else if (EESMRCmdSendMRUpdate == iCommand && + CCalEntry::EMethodCancel == method ) + { + ESMREntry().GetRemovedAttendeesL( + aRequiredAttendees, + EESMRRoleRequiredAttendee ); + ESMREntry().GetRemovedAttendeesL( + aOptionalAttendees, + EESMRRoleOptionalAttendee ); + } + else + { + iCaluserUtil->GetAttendeesL( + aRequiredAttendees, + EESMRRoleRequiredAttendee ); + iCaluserUtil->GetAttendeesL( + aOptionalAttendees, + EESMRRoleOptionalAttendee ); + } + } + +// --------------------------------------------------------------------------- +// CESMRSendMRFSMailTask::GetEntriesToBeSentL +// --------------------------------------------------------------------------- +// +void CESMRSendMRFSMailTask::GetEntriesToBeSentL() + { + FUNC_LOG; + // Clear the entry array + iEntriesToSend.ResetAndDestroy(); + + if ( EESMRCmdSendMRUpdate == iCommand ) + { + // We are sending update and we need to send all the entries + CCalEntry* mainEntry = ESMREntry().ValidateEntryL(); + CleanupStack::PushL( mainEntry ); + + if ( MESMRCalEntry::EESMRAllInSeries == ESMREntry().RecurrenceModRule() ) + { + // Update child entries sequence number + ESMREntry().UpdateChildEntriesSeqNumbersL(); + + // We are sending update to series + // Also the modifying entries need to be sent + // Otherwise the modifying entries may disappear from the + // attendees calendar. + CalDbMgr().NormalDbEntryView()->FetchL( + mainEntry->UidL(), + iEntriesToSend ); + + CleanupStack::PopAndDestroy( mainEntry ); + } + else + { + // Ownership transferred + TInt err = iEntriesToSend.Append( mainEntry ); + User::LeaveIfError( err ); + + CleanupStack::Pop( mainEntry ); + } + + mainEntry = NULL; + } + else + { + // We are sending either: + // a) Single entry + // b) Modified instance from series + // c) First invitation to series + // d) forwarding entry + TInt err = iEntriesToSend.Append( ESMREntry().ValidateEntryL() ); + User::LeaveIfError( err ); + } + + __ASSERT_DEBUG( iEntriesToSend.Count(), Panic(EESMRSendMRNoEntriesToSend ) ); + } + +// EOF +