meetingui/meetingrequestutils/src/CMRUtilsEmailSender.cpp
changeset 0 f979ecb2b13e
equal deleted inserted replaced
-1:000000000000 0:f979ecb2b13e
       
     1 /*
       
     2 * Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: Implementation for meeting request utils email sender 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // ----------------------------------------------------------------------------
       
    21 // INCLUDE FILES
       
    22 // ----------------------------------------------------------------------------
       
    23 //
       
    24 #include "CMRUtilsEmailSender.h"
       
    25 #include "MRHelpers.h"
       
    26 #include "ICalUILog.h"
       
    27 #include <CalEntryView.h>
       
    28 #include <bautils.h>
       
    29 #include <data_caging_path_literals.hrh>
       
    30 #include <CalEntry.h>
       
    31 #include <stringresourcereader.h>
       
    32 #include <CalSession.h>
       
    33 #include <CalUser.h>
       
    34 #include <SendUi.h>
       
    35 #include <CMessageData.h>
       
    36 #include <MeetingRequestData.h>
       
    37 #include <SendUiConsts.h>
       
    38 #include <CalenExporter.h>
       
    39 #include <txtrich.h>
       
    40 #include <eikenv.h>
       
    41 #include <msvids.h>
       
    42 #include <msgeditorappui.rsg>
       
    43 
       
    44 // CONSTANTS
       
    45 /// Unnamed namespace for local definitions
       
    46 namespace {
       
    47 
       
    48 const TInt KDynBufExpandSize( 100 );
       
    49 const TInt KMethodMaxLength( 14 );
       
    50 _LIT( KSendUiOmrAttachmentFile, "c:attachment.ics" );
       
    51 _LIT( KMsgEditorAppUiResourceFileName, "z:msgeditorappui.rsc" );
       
    52 // one of these methods must be appended to KSendUiOmrContentSubType
       
    53 _LIT8( KMethodPublish, "PUBLISH" );
       
    54 _LIT8( KMethodRequest, "REQUEST" );
       
    55 _LIT8( KMethodReply, "REPLY" );
       
    56 _LIT8( KMethodAdd, "ADD" );
       
    57 _LIT8( KMethodCancel, "CANCEL" );
       
    58 _LIT8( KMethodRefresh, "REFRESH" );
       
    59 _LIT8( KMethodCounter, "COUNTER" );
       
    60 _LIT8( KMethodDeclineCounter, "DECLINECOUNTER" );
       
    61 
       
    62 enum TPanicCode
       
    63     {
       
    64     EPanicIllegalRecipients = 1,
       
    65     EPanicBadSenderAddr,
       
    66     EPanicUnknownMethod
       
    67     };
       
    68 
       
    69 _LIT( KPanicMsg, "CMRUtilsEmailSender" );
       
    70 
       
    71 void Panic( TPanicCode aReason )
       
    72     {
       
    73     User::Panic( KPanicMsg, aReason );
       
    74     }
       
    75 
       
    76 }  // namespace
       
    77 
       
    78 // ----------------------------------------------------------------------------
       
    79 // MEMBER FUNCTIONS
       
    80 // ----------------------------------------------------------------------------
       
    81 //
       
    82 
       
    83 // ----------------------------------------------------------------------------
       
    84 // CMRUtilsEmailSender::NewL
       
    85 // ----------------------------------------------------------------------------
       
    86 //
       
    87 CMRUtilsEmailSender* CMRUtilsEmailSender::NewL(
       
    88     CCalSession& aCalSession )
       
    89 	{
       
    90 	LOG("CMRUtilsEmailSender 1");
       
    91 	CMRUtilsEmailSender* self =
       
    92 	    new( ELeave ) CMRUtilsEmailSender( aCalSession );
       
    93 	LOG("CMRUtilsEmailSender 2");
       
    94 	CleanupStack::PushL( self );
       
    95 	self->ConstructL();
       
    96 	CleanupStack::Pop();
       
    97 	return self;
       
    98 	}
       
    99 
       
   100 // ----------------------------------------------------------------------------
       
   101 // CMRUtilsEmailSender::CMRUtilsEmailSender
       
   102 //
       
   103 // Constructor.
       
   104 // ----------------------------------------------------------------------------
       
   105 //
       
   106 CMRUtilsEmailSender::CMRUtilsEmailSender(
       
   107     CCalSession& aCalSession )
       
   108     : iCalSession( aCalSession )
       
   109     {
       
   110     }
       
   111 
       
   112 // ----------------------------------------------------------------------------
       
   113 // CMRUtilsEmailSender::~CMRUtilsEmailSender
       
   114 //
       
   115 // Destructor.
       
   116 // ----------------------------------------------------------------------------
       
   117 //
       
   118 CMRUtilsEmailSender::~CMRUtilsEmailSender()
       
   119     {
       
   120     delete iSendUi;        
       
   121     delete iResReader;
       
   122     iFs.Close();        
       
   123     }
       
   124 
       
   125 // ----------------------------------------------------------------------------
       
   126 // CMRUtilsEmailSender::ConstructL
       
   127 // ----------------------------------------------------------------------------
       
   128 //
       
   129 void CMRUtilsEmailSender::ConstructL()
       
   130     {
       
   131     User::LeaveIfError( iFs.Connect() );
       
   132     
       
   133     TParse parse;
       
   134     parse.Set( KMsgEditorAppUiResourceFileName, &KDC_RESOURCE_FILES_DIR, NULL );
       
   135     TFileName fileName( parse.FullName() );
       
   136 
       
   137     BaflUtils::NearestLanguageFile( iFs, fileName );
       
   138     // CStringResourceReader does not require CEikonEnv -> MRUtils can be
       
   139     // used without UI context
       
   140     iResReader = CStringResourceReader::NewL( fileName );
       
   141     
       
   142     // Send UI must be created before trying to send anything, because it
       
   143     // gets initialized asynchronously:
       
   144     iSendUi = CSendUi::NewL(); 
       
   145     }
       
   146 
       
   147 // ----------------------------------------------------------------------------
       
   148 // CMRUtilsEmailSender::ReplyToL
       
   149 // ----------------------------------------------------------------------------
       
   150 //
       
   151 void CMRUtilsEmailSender::ReplyToL(
       
   152     CMRUtilsInternal::TMailRecipients aRecipients,
       
   153     const CCalEntry& aCalEntry,
       
   154     TMsvId /*aMailBox*/,
       
   155     const TDesC& aSenderAddr )
       
   156     {
       
   157     // Use send ui for sending ordinary e-mail as a reply:
       
   158 
       
   159 // TODO: when using send ui we can not decide which mailbox to use like
       
   160 // with normal reply. This probably needs fixing in the future.
       
   161 
       
   162     CMessageData* msgData = CMessageData::NewLC();
       
   163 
       
   164     AddRecipientsToMsgL( aRecipients, aCalEntry, aSenderAddr, *msgData );
       
   165 
       
   166     HBufC* subject = CreateSubjectPrefixStringL( aCalEntry.SummaryL(),
       
   167                                                  ETrue );
       
   168     CleanupStack::PushL( subject );
       
   169     msgData->SetSubjectL( subject );
       
   170     CleanupStack::PopAndDestroy( subject );
       
   171 
       
   172     iSendUi->CreateAndSendMessageL( KSenduiMtmSmtpUid, msgData );
       
   173 
       
   174     CleanupStack::PopAndDestroy( msgData );
       
   175     }
       
   176 
       
   177 // ----------------------------------------------------------------------------
       
   178 // CMRUtilsEmailSender::SendL
       
   179 // ----------------------------------------------------------------------------
       
   180 //
       
   181 void CMRUtilsEmailSender::SendL( const CCalEntry& aCalEntry, TMsvId aMailBox )
       
   182     {
       
   183     LOG("CMRUtilsEmailSender::SendL");
       
   184 
       
   185     CMessageData* msgData = CMessageData::NewL();
       
   186     msgData->SetSubjectL(&( aCalEntry.SummaryL() ));
       
   187 
       
   188     CMeetingRequestData* msg =
       
   189         CMeetingRequestData::NewLC();
       
   190 
       
   191     // Set email mailbox, subject, address, content type and entries:
       
   192 
       
   193     if ( aMailBox == KMsvNullIndexEntryId )
       
   194         {
       
   195         User::Leave( KErrArgument );
       
   196         }
       
   197     msg->UseMailbox( aMailBox );
       
   198     AddRecipientsToMsgL( aCalEntry, *msgData  );
       
   199     
       
   200     TBuf8<KMethodMaxLength> method;
       
   201     SetMethodStringL( method, aCalEntry );
       
   202     msg->SetMailHeaderMethodL( method );    
       
   203 
       
   204     msg->AppendEntryLocalId( aCalEntry.LocalUidL() );
       
   205     TCalFileId calFileId;
       
   206     iCalSession.FileIdL( calFileId );
       
   207     msg->SetDatabaseFileId( calFileId );
       
   208 
       
   209     LOG("CMRUtilsEmailSender::SendL, exporting for msg body");  
       
   210     
       
   211     // Set body:
       
   212 	CBufSeg* buf = CBufSeg::NewL( KDynBufExpandSize );
       
   213 	CleanupStack::PushL( buf );
       
   214 
       
   215     RBufWriteStream writeStream;
       
   216     CleanupClosePushL( writeStream );
       
   217 	writeStream.Open( *buf );
       
   218     CCalenExporter* exporter = CCalenExporter::NewL( iCalSession );
       
   219     CleanupStack::PushL( exporter );
       
   220     //Exporter writes data to stream as UTF-8 (8 bit)
       
   221     exporter->ExportICalL( aCalEntry, writeStream );
       
   222              
       
   223     writeStream.CommitL();
       
   224     CleanupStack::PopAndDestroy( 2 ); //exporter, writeStream
       
   225     
       
   226     LOG("CMRUtilsEmailSender::SendL, setting msg body");      
       
   227 
       
   228     CParaFormatLayer* fLayer = CEikonEnv::NewDefaultParaFormatLayerL();
       
   229     CleanupStack::PushL( fLayer );
       
   230     CCharFormatLayer* cLayer = CEikonEnv::NewDefaultCharFormatLayerL();
       
   231     CleanupStack::PushL( cLayer );    
       
   232     CRichText* bodyText = CRichText::NewL( fLayer, cLayer );
       
   233     CleanupStack::PushL( bodyText );
       
   234     
       
   235     RBufReadStream readStream(*buf);
       
   236     CleanupClosePushL( readStream );
       
   237     readStream.Open( *buf );
       
   238         
       
   239     //8 bit buffer for reading data from stream
       
   240     HBufC8* shortBuffer = HBufC8::NewLC(buf->Size());
       
   241     TPtr8 shortPtr = shortBuffer->Des();
       
   242         
       
   243     //Read from stream to buffer
       
   244     readStream.ReadL(shortPtr, buf->Size());
       
   245             
       
   246     //Convert to 16 bit format which can be inserted to Richtext.
       
   247     HBufC* longBuffer = HBufC::NewLC( shortBuffer->Length());
       
   248     TPtr longPtr = longBuffer->Des();
       
   249     longPtr.Copy(*shortBuffer);
       
   250     
       
   251     bodyText->InsertL(0, longPtr);    
       
   252     
       
   253     msgData->SetBodyTextL( bodyText ); // sendui creates own copy of body text
       
   254     
       
   255     // Pop longBuffer, shortBuffer, readStream, bodytext, cLayer, fLayer, buf
       
   256     CleanupStack::PopAndDestroy( 7, buf );
       
   257     
       
   258     // Add meeting request as an attachment:
       
   259     
       
   260     // Store attachment temporarily to caller processes' private directory.
       
   261     // TODO: if this doesn't work, then read again "How-To guide for protecting
       
   262     // private data". One alternative could be to store it to \system\temp,
       
   263     // but it would require and SCB CR.
       
   264     
       
   265     LOG("CMRUtilsEmailSender::SendL, exporting to attachment");      
       
   266     
       
   267     HBufC* fileName = HBufC::NewL( KMaxFileName );
       
   268     TPtr fileNameDes( fileName->Des() );
       
   269     // In case of leave we must try to delete the file too -> custom cleanup:
       
   270     CleanupStack::PushL( TCleanupItem( CleanupTmpAttachment, fileName ) );
       
   271     
       
   272     User::LeaveIfError( iFs.PrivatePath( fileNameDes ) );
       
   273     TParse parse;
       
   274     parse.Set( KSendUiOmrAttachmentFile, fileName, NULL );
       
   275     *fileName = parse.FullName();
       
   276     iFs.MkDirAll( *fileName ); // ignore errors, try to open writestream anyway
       
   277     
       
   278     RFileWriteStream fileWriteStream;
       
   279     CleanupClosePushL( fileWriteStream );    
       
   280     // Prepare file for writing, replace possibly existing temp file:
       
   281     LOG("CMRUtilsEmailSender::SendL, exporting (replacing existing file)");    
       
   282 	User::LeaveIfError( fileWriteStream.Replace( iFs,
       
   283 	                                         *fileName,
       
   284 	                                         EFileStreamText | EFileWrite ) );
       
   285     LOG("CMRUtilsEmailSender::SendL, exporting (creating exporter)");        
       
   286     CCalenExporter* attachmentExporter = CCalenExporter::NewL( iCalSession );
       
   287     CleanupStack::PushL( attachmentExporter );
       
   288     LOG("CMRUtilsEmailSender::SendL, exporting (exporting)");            
       
   289     attachmentExporter->ExportICalL( aCalEntry, fileWriteStream );
       
   290     fileWriteStream.CommitL();
       
   291     CleanupStack::PopAndDestroy( 2 ); //exporter, fileWriteStream  
       
   292     
       
   293     LOG("CMRUtilsEmailSender::SendL, appending attachment to msg");            
       
   294     msgData->AppendAttachmentL( *fileName ); 
       
   295     
       
   296     // create and set opaque data
       
   297     HBufC8* mrDataBuffer = msg->WriteToBufferLC();
       
   298     msgData->SetOpaqueDataL(mrDataBuffer,KSenduiMsgDataMeetingRequest);
       
   299     CleanupStack::PopAndDestroy(mrDataBuffer); 	
       
   300 
       
   301     // Create and send message:
       
   302     LOG("CMRUtilsEmailSender::SendL, calling sendui to send");                
       
   303     iSendUi->CreateAndSendMessageL( KMeetingRequestSender, msgData);
       
   304    
       
   305     // Cleanup temp file and delete heap descriptor:
       
   306     CleanupStack::PopAndDestroy(); // fileName 
       
   307     
       
   308     CleanupStack::PopAndDestroy( msg ); // msg    
       
   309     LOG("CMRUtilsEmailSender::SendL -> End");      
       
   310     }
       
   311     
       
   312 // ----------------------------------------------------------------------------
       
   313 // CMRUtilsEmailSender::AddRecipientsToMsgL
       
   314 // ----------------------------------------------------------------------------
       
   315 //
       
   316 void CMRUtilsEmailSender::AddRecipientsToMsgL(
       
   317     CMRUtilsInternal::TMailRecipients aRecipients,
       
   318     const CCalEntry& aCalEntry,
       
   319     const TDesC& aSenderAddr,
       
   320     CMessageData& aMsgData ) const
       
   321     {
       
   322     const CCalUser* calUser = NULL;
       
   323     switch ( aRecipients )
       
   324         {
       
   325         case CMRUtilsInternal::EOrganizer:
       
   326             { // reply to organizer:
       
   327             calUser = aCalEntry.OrganizerL();
       
   328             AddRecipientToMsgL( calUser, aMsgData );
       
   329             break;
       
   330             }
       
   331         case CMRUtilsInternal::ESender:
       
   332             { // reply to sender given as a parameter:
       
   333             __ASSERT_DEBUG( aSenderAddr.Length() > 0, EPanicBadSenderAddr );
       
   334             if ( aSenderAddr.Length() == 0 )
       
   335                 {
       
   336                 User::Leave( KErrArgument );
       
   337                 }
       
   338             aMsgData.AppendToAddressL( aSenderAddr );
       
   339             break;
       
   340             }
       
   341         case CMRUtilsInternal::EAll:
       
   342             { // send to all non-declined attendees:
       
   343             RPointerArray<CCalAttendee>& attendees = aCalEntry.AttendeesL();
       
   344             TInt count( attendees.Count() );
       
   345             for ( TInt i( 0 ); i < count; ++i )
       
   346                 {
       
   347                 if ( attendees[i]->StatusL() != CCalAttendee::EDeclined )
       
   348                     {                    
       
   349                     calUser = attendees[i];
       
   350                     AddRecipientToMsgL( calUser, aMsgData );
       
   351                     }
       
   352                 }
       
   353             break;
       
   354             }
       
   355         default:
       
   356             {
       
   357             Panic( EPanicIllegalRecipients );
       
   358             break;
       
   359             }
       
   360         }
       
   361     }
       
   362 
       
   363 // ----------------------------------------------------------------------------
       
   364 // CMRUtilsEmailSender::AddRecipientsToMsgL
       
   365 // ----------------------------------------------------------------------------
       
   366 //
       
   367 void CMRUtilsEmailSender::AddRecipientsToMsgL(
       
   368     const CCalEntry& aCalEntry,
       
   369     CMessageData& aMsgData ) const
       
   370     {
       
   371     const CCalUser* calUser = NULL;
       
   372     switch ( aCalEntry.MethodL() )
       
   373         {
       
   374 		case CCalEntry::EMethodRequest:
       
   375 		case CCalEntry::EMethodAdd:
       
   376 		case CCalEntry::EMethodCancel:
       
   377 		case CCalEntry::EMethodDeclineCounter:
       
   378             {
       
   379             // AttendeesL does not return organizer, which is good for us:
       
   380             RPointerArray<CCalAttendee>& attendees = aCalEntry.AttendeesL();
       
   381             TInt count( attendees.Count() );
       
   382             for ( TInt i( 0 ); i < count; ++i )
       
   383                 {
       
   384                 calUser = attendees[i];
       
   385                 AddRecipientToMsgL( calUser, aMsgData );
       
   386                 }
       
   387             break;
       
   388             }
       
   389 		case CCalEntry::EMethodReply:
       
   390 		case CCalEntry::EMethodRefresh:
       
   391 		case CCalEntry::EMethodCounter:
       
   392             {
       
   393             calUser = aCalEntry.OrganizerL(); // ownership not transferred
       
   394             AddRecipientToMsgL( calUser, aMsgData );
       
   395             break;
       
   396             }
       
   397         default: // EMethodNone, EMethodPublish
       
   398             {
       
   399             User::Leave( KErrNotSupported );
       
   400             break;
       
   401             }
       
   402         }
       
   403     }
       
   404 
       
   405 // ----------------------------------------------------------------------------
       
   406 // CMRUtilsEmailSender::AddRecipientToMsgL
       
   407 // ----------------------------------------------------------------------------
       
   408 //
       
   409 void CMRUtilsEmailSender::AddRecipientToMsgL(
       
   410     const CCalUser* aRecipient,
       
   411     CMessageData& aMsgData ) const
       
   412     {
       
   413     if ( !aRecipient || aRecipient->Address().Length() == 0 )
       
   414         {
       
   415         User::Leave( KErrArgument );
       
   416         }
       
   417     TPtrC addr = MRHelpers::AddressWithoutMailtoPrefix( aRecipient->Address() );
       
   418     aMsgData.AppendToAddressL( addr, aRecipient->CommonName() );
       
   419     }
       
   420 
       
   421 // ---------------------------------------------------------
       
   422 // CMRUtilsEmailSender::CreateSubjectPrefixStringL
       
   423 // Same functionality as in CMsgEditorAppUi.
       
   424 // ---------------------------------------------------------
       
   425 //
       
   426 HBufC* CMRUtilsEmailSender::CreateSubjectPrefixStringL(
       
   427     const TDesC& aSubject,
       
   428     TBool aReply ) const
       
   429     {
       
   430     HBufC* newSubject = NULL;
       
   431     TInt length = aSubject.Length();
       
   432 
       
   433     TInt formatResource = aReply
       
   434         ? R_MSG_REPLY_PREFIX
       
   435         : R_MSG_FORWARD_PREFIX;
       
   436 
       
   437     HBufC* subjectFormat =
       
   438         iResReader->ReadResourceString( formatResource ).AllocLC();
       
   439 
       
   440     TInt formatPos = subjectFormat->Find( _L("%S") );
       
   441     TInt foundInSubj = KErrNotFound;
       
   442     if ( formatPos > 0 )
       
   443         {
       
   444         // -1 to avoid % in the string
       
   445         foundInSubj = aSubject.FindF( subjectFormat->Left( formatPos - 1 ) );
       
   446         }
       
   447     // Append only when it is not in the beginning of the
       
   448     // subject line or not found.
       
   449     if ( foundInSubj == KErrNotFound || foundInSubj )
       
   450         {
       
   451         // Create a buffer large enough to hold the re-formated subject - need
       
   452         // to subtract two from the prefix length (the %S).
       
   453         length += subjectFormat->Length() - 2;
       
   454         newSubject = HBufC::NewL( length );
       
   455         TPtr ptr( newSubject->Des() );
       
   456         ptr.Format( *subjectFormat, &aSubject );
       
   457         }
       
   458     CleanupStack::PopAndDestroy( subjectFormat );
       
   459 
       
   460     return newSubject;
       
   461     }
       
   462 
       
   463 // ----------------------------------------------------------------------------
       
   464 // CMRUtilsEmailSender::SetMethodStringL
       
   465 // This is internal method so we can be sure that aOriginal is long enough.
       
   466 // ----------------------------------------------------------------------------
       
   467 //
       
   468 void CMRUtilsEmailSender::SetMethodStringL(
       
   469     TDes8& aString,
       
   470     const CCalEntry& aCalEntry )
       
   471     {
       
   472     switch ( aCalEntry.MethodL() )
       
   473         {     
       
   474         case CCalEntry::EMethodPublish:
       
   475             {
       
   476             aString = KMethodPublish;
       
   477             break;
       
   478             }
       
   479         case CCalEntry::EMethodRequest:
       
   480             {
       
   481             aString = KMethodRequest;            
       
   482             break;
       
   483             }
       
   484         case CCalEntry::EMethodReply:
       
   485             {
       
   486             aString = KMethodReply;            
       
   487             break;
       
   488             }
       
   489         case CCalEntry::EMethodAdd:
       
   490             {
       
   491             aString = KMethodAdd;            
       
   492             break;
       
   493             }
       
   494         case CCalEntry::EMethodCancel:
       
   495             {
       
   496             aString = KMethodCancel;            
       
   497             break;
       
   498             }
       
   499         case CCalEntry::EMethodRefresh:
       
   500             {
       
   501             aString = KMethodRefresh;            
       
   502             break;
       
   503             }   
       
   504         case CCalEntry::EMethodCounter:
       
   505             {
       
   506             aString = KMethodCounter;            
       
   507             break;
       
   508             }                                                                                  
       
   509         case CCalEntry::EMethodDeclineCounter:
       
   510             {
       
   511             aString = KMethodDeclineCounter;            
       
   512             break;
       
   513             }
       
   514         default:
       
   515             {
       
   516             Panic( EPanicUnknownMethod );
       
   517             break;
       
   518             }
       
   519         }
       
   520     }
       
   521 
       
   522 // ---------------------------------------------------------
       
   523 // CMRUtilsEmailSender::CleanupTmpAttachment
       
   524 // ---------------------------------------------------------
       
   525 //
       
   526 void CMRUtilsEmailSender::CleanupTmpAttachment( TAny* aPtr )
       
   527     {
       
   528     HBufC* fileName = static_cast<HBufC*>( aPtr );
       
   529     if ( fileName && (*fileName) != KNullDesC )
       
   530         {
       
   531         // Unfortunately we can't use iFs here since this is a static method,
       
   532         // ignore possible errors with deleting, next time it will be cleaned:
       
   533         CEikonEnv::Static()->FsSession().Delete( *fileName );
       
   534         }
       
   535     delete fileName;
       
   536     }
       
   537     
       
   538 
       
   539 // End of file