|
1 /* |
|
2 * Copyright (c) 2007 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: This file implements class CIpsPlgMsgMapper. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include "emailtrace.h" |
|
21 #include "ipsplgheaders.h" |
|
22 |
|
23 _LIT( KMimeTypeTextPlain, "text/plain" ); |
|
24 _LIT( KMimeTypeTextHtml, "text/html" ); |
|
25 _LIT( KMimeTypeTextRtf, "text/rtf" ); |
|
26 _LIT( KSlash, "/" ); |
|
27 |
|
28 _LIT( KCharSemicolon, ";" ); |
|
29 _LIT( KCharEquals, "=" ); |
|
30 _LIT( KCharsetTag, "CHARSET" ); |
|
31 _LIT( KMessageExtension, ".eml" ); |
|
32 |
|
33 // Supported multipart content types |
|
34 _LIT( KMimeTypeMultipartRelated, "multipart/related" ); |
|
35 _LIT( KMimeTypeMultipartMixed, "multipart/mixed" ); |
|
36 _LIT( KMimeTypeMultipartAlternative, "multipart/alternative" ); |
|
37 _LIT( KMimeTypeMultipartDigest, "multipart/digest" ); |
|
38 _LIT( KMimeTypeMultipartRfc822, "message/rfc822" ); |
|
39 _LIT( KMimeTypeMultipartPartial, "message/partial" ); |
|
40 _LIT( KMimeTypeMultipartDirectory, "text/directory" ); |
|
41 _LIT( KMimeTypeMultipartExternalBody, "message/external-body" ); |
|
42 _LIT( KMimeTypeMultipartParallel, "multipart/parallel" ); |
|
43 |
|
44 const TInt KCharEscape = 0x5C; |
|
45 const TInt KCharNonPrintable = 0x1F; |
|
46 const TInt KCharAt = 0x40; |
|
47 const TInt KMaxContentTypeLength = 200; |
|
48 const TInt KEmbeddedMsgExtensionLength = 4; |
|
49 |
|
50 // ======== CONSTRUCTORS & DESTRUCTOR ======== |
|
51 |
|
52 // --------------------------------------------------------------------------- |
|
53 // CIpsPlgMsgMapper::NewL() |
|
54 // --------------------------------------------------------------------------- |
|
55 // |
|
56 CIpsPlgMsgMapper* CIpsPlgMsgMapper::NewL( |
|
57 CMsvSession& aSession, |
|
58 CIpsPlgSosBasePlugin& aPlugin ) |
|
59 { |
|
60 FUNC_LOG; |
|
61 CIpsPlgMsgMapper* self = CIpsPlgMsgMapper::NewLC( aSession, aPlugin ); |
|
62 CleanupStack::Pop( self ); |
|
63 return self; |
|
64 } |
|
65 |
|
66 // --------------------------------------------------------------------------- |
|
67 // CIpsPlgMsgMapper::NewLC() |
|
68 // --------------------------------------------------------------------------- |
|
69 // |
|
70 CIpsPlgMsgMapper* CIpsPlgMsgMapper::NewLC( |
|
71 CMsvSession& aSession, |
|
72 CIpsPlgSosBasePlugin& aPlugin ) |
|
73 { |
|
74 FUNC_LOG; |
|
75 CIpsPlgMsgMapper* self = |
|
76 new( ELeave ) CIpsPlgMsgMapper( aSession, aPlugin ); |
|
77 CleanupStack::PushL( self ); |
|
78 self->ConstructL(); |
|
79 return self; |
|
80 } |
|
81 |
|
82 // --------------------------------------------------------------------------- |
|
83 // CIpsPlgMsgMapper::~CIpsPlgMsgMapper() |
|
84 // --------------------------------------------------------------------------- |
|
85 // |
|
86 CIpsPlgMsgMapper::~CIpsPlgMsgMapper() |
|
87 { |
|
88 FUNC_LOG; |
|
89 } |
|
90 |
|
91 // --------------------------------------------------------------------------- |
|
92 // CIpsPlgMsgMapper::CIpsPlgMsgMapper() |
|
93 // --------------------------------------------------------------------------- |
|
94 // |
|
95 CIpsPlgMsgMapper::CIpsPlgMsgMapper( |
|
96 CMsvSession& aSession, |
|
97 CIpsPlgSosBasePlugin& aPlugin ) |
|
98 : iSession( aSession ), iPlugin( aPlugin ) |
|
99 { |
|
100 FUNC_LOG; |
|
101 } |
|
102 |
|
103 // --------------------------------------------------------------------------- |
|
104 // CIpsPlgMsgMapper::ConstructL() |
|
105 // --------------------------------------------------------------------------- |
|
106 // |
|
107 void CIpsPlgMsgMapper::ConstructL() |
|
108 { |
|
109 FUNC_LOG; |
|
110 } |
|
111 |
|
112 // --------------------------------------------------------------------------- |
|
113 // CIpsPlgMsgMapper::GetMailMessageL() |
|
114 // --------------------------------------------------------------------------- |
|
115 // |
|
116 CFSMailMessage* CIpsPlgMsgMapper::GetMailMessageL( |
|
117 CMsvEntry& aEntry ) |
|
118 { |
|
119 FUNC_LOG; |
|
120 TFSMailMsgId msgId( iPlugin.PluginId(), aEntry.Entry().Id() ); |
|
121 CFSMailMessage* fsMsg = CFSMailMessage::NewLC( msgId ); |
|
122 |
|
123 fsMsg->SetFolderId( |
|
124 TFSMailMsgId( iPlugin.PluginId(), aEntry.Entry().Parent() ) ); |
|
125 |
|
126 CMsvStore* store( NULL ); |
|
127 |
|
128 if ( aEntry.HasStoreL() ) |
|
129 { |
|
130 store = aEntry.ReadStoreL(); |
|
131 CleanupStack::PushL( store ); |
|
132 } |
|
133 |
|
134 SetEnvelopeL( &aEntry, store, *fsMsg ); |
|
135 |
|
136 // Apparently, this should be done only with |
|
137 // EFSMsgDataStructure, but EFSMsgDataEnvelope is currently |
|
138 // used by assuming that it reads also the content-type of |
|
139 // the message |
|
140 SetStructureL( &aEntry, *fsMsg ); |
|
141 |
|
142 TMsvEmailEntry tEntry( aEntry.Entry() ); |
|
143 |
|
144 SetFlags( tEntry, *fsMsg ); |
|
145 |
|
146 if ( store ) |
|
147 { |
|
148 CleanupStack::PopAndDestroy( store ); |
|
149 } |
|
150 |
|
151 CleanupStack::Pop( fsMsg ); |
|
152 return fsMsg; |
|
153 } |
|
154 |
|
155 // --------------------------------------------------------------------------- |
|
156 // CIpsPlgMsgMapper::GetMailMessageL() |
|
157 // --------------------------------------------------------------------------- |
|
158 // |
|
159 CFSMailMessage* CIpsPlgMsgMapper::GetMailMessageL( |
|
160 const TFSMailMsgId& aMailboxId, |
|
161 const TMsvEmailEntry& aEntry, |
|
162 const TFSMailDetails& aDetails ) |
|
163 { |
|
164 FUNC_LOG; |
|
165 TFSMailMsgId msgId( iPlugin.PluginId(), aEntry.Id() ); |
|
166 CFSMailMessage* result = CFSMailMessage::NewLC( msgId ); |
|
167 |
|
168 result->SetMailBoxId( aMailboxId ); |
|
169 result->SetFolderId( |
|
170 TFSMailMsgId( iPlugin.PluginId(), aEntry.Parent() ) ); |
|
171 |
|
172 SetFlags( aEntry, *result ); |
|
173 SetFetchStateL( aEntry, aEntry.Id(), EFalse, *result ); |
|
174 |
|
175 switch( aDetails ) |
|
176 { |
|
177 case EFSMsgDataDate: |
|
178 SetDateL( aEntry, *result ); |
|
179 break; |
|
180 case EFSMsgDataSubject: |
|
181 SetSubjectL( aEntry, *result ); |
|
182 break; |
|
183 case EFSMsgDataSender: |
|
184 SetSenderL( aEntry.iDetails, *result ); |
|
185 break; |
|
186 case EFSMsgDataEnvelope: |
|
187 case EFSMsgDataStructure: |
|
188 { |
|
189 CMsvStore* store( NULL ); |
|
190 CMsvEntry* cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
191 CleanupStack::PushL( cEntry ); |
|
192 |
|
193 if ( cEntry && cEntry->HasStoreL() ) |
|
194 { |
|
195 store = cEntry->ReadStoreL(); |
|
196 CleanupStack::PushL( store ); |
|
197 } |
|
198 |
|
199 SetEnvelopeL( cEntry, store, *result ); |
|
200 |
|
201 // Apparently, this should be done only with |
|
202 // EFSMsgDataStructure, but EFSMsgDataEnvelope is currently |
|
203 // used by assuming that it reads also the content-type of |
|
204 // the message |
|
205 SetStructureL( cEntry, *result ); |
|
206 |
|
207 if ( store ) |
|
208 { |
|
209 CleanupStack::PopAndDestroy( store ); |
|
210 } |
|
211 CleanupStack::PopAndDestroy( cEntry ); |
|
212 break; |
|
213 } |
|
214 case EFSMsgDataIdOnly: |
|
215 default: |
|
216 break; |
|
217 } |
|
218 |
|
219 CleanupStack::Pop( result ); |
|
220 return result; |
|
221 } |
|
222 |
|
223 // --------------------------------------------------------------------------- |
|
224 // --------------------------------------------------------------------------- |
|
225 void CIpsPlgMsgMapper::GetChildPartsL( |
|
226 const TFSMailMsgId& aMailBoxId, |
|
227 const TFSMailMsgId& aMessageId, |
|
228 const TFSMailMsgId& aParentId, |
|
229 RPointerArray<CFSMailMessagePart>& aParts ) |
|
230 { |
|
231 FUNC_LOG; |
|
232 |
|
233 if ( aParentId.IsNullId() ) |
|
234 // the caller wants the children of the message |
|
235 { |
|
236 GetChildPartsOfMessageEntryL( aMailBoxId, aMessageId, aParts ); |
|
237 } |
|
238 else |
|
239 // the caller wants the parts of the 'real' subpart |
|
240 { |
|
241 GetChildPartsOfFolderEntryL( aMailBoxId, aMessageId, aParentId.Id(), |
|
242 aParts ); |
|
243 } |
|
244 } |
|
245 |
|
246 // --------------------------------------------------------------------------- |
|
247 // --------------------------------------------------------------------------- |
|
248 CFSMailMessagePart* CIpsPlgMsgMapper::GetMessagePartL( |
|
249 TMsvId aEntryId, |
|
250 const TFSMailMsgId& aMailBoxId, |
|
251 const TFSMailMsgId& aMessageId ) |
|
252 { |
|
253 FUNC_LOG; |
|
254 CFSMailMessagePart* result( NULL ); |
|
255 TInt status; |
|
256 TMsvId serviceId; |
|
257 TMsvEmailEntry tEntry; |
|
258 |
|
259 status = iSession.GetEntry( aEntryId, serviceId, tEntry ); |
|
260 |
|
261 if ( status == KErrNone ) |
|
262 { |
|
263 switch ( tEntry.iType.iUid ) |
|
264 { |
|
265 case KUidMsvFolderEntryValue: |
|
266 { |
|
267 result = ConvertFolderEntry2MessagePartL( tEntry, |
|
268 aMailBoxId, aMessageId ); |
|
269 break; |
|
270 } |
|
271 case KUidMsvAttachmentEntryValue: |
|
272 case KUidMsvMessageEntryValue: |
|
273 { |
|
274 result = ConvertAttachmentEntry2MessagePartL( tEntry, |
|
275 aMailBoxId, aMessageId ); |
|
276 break; |
|
277 } |
|
278 case KUidMsvEmailTextEntryValue: |
|
279 case KUidMsvEmailHtmlEntryValue: |
|
280 case KUidMsvEmailExternalBodyEntryValue: |
|
281 case KUidMsvEmailRtfEntryValue: |
|
282 { |
|
283 result = ConvertBodyEntry2MessagePartL( tEntry, aMailBoxId, |
|
284 aMessageId ); |
|
285 break; |
|
286 } |
|
287 } |
|
288 } |
|
289 |
|
290 return result; |
|
291 } |
|
292 |
|
293 // --------------------------------------------------------------------------- |
|
294 // --------------------------------------------------------------------------- |
|
295 TBool CIpsPlgMsgMapper::ChangeTEntryFlagsL( |
|
296 TMsvEmailEntry& aEmlEntry, |
|
297 const CFSMailMessage& aMessage ) |
|
298 { |
|
299 FUNC_LOG; |
|
300 TInt msgFlags = aMessage.GetFlags(); |
|
301 TBool modified ( EFalse ); |
|
302 TBool unread( aEmlEntry.Unread() ); |
|
303 |
|
304 if ( !LogicalXor( unread, msgFlags & EFSMsgFlag_Read ) ) |
|
305 { |
|
306 aEmlEntry.SetUnread( !unread ); |
|
307 modified = ETrue; |
|
308 } |
|
309 |
|
310 // EFSMsgFlag_Low |
|
311 // EFSMsgFlag_Important |
|
312 TMsvPriority msgPriority; |
|
313 |
|
314 if ( msgFlags & EFSMsgFlag_Important ) |
|
315 { |
|
316 msgPriority = EMsvHighPriority; |
|
317 } |
|
318 else if ( msgFlags & EFSMsgFlag_Low ) |
|
319 { |
|
320 msgPriority = EMsvLowPriority; |
|
321 } |
|
322 else |
|
323 { |
|
324 msgPriority = EMsvMediumPriority; |
|
325 } |
|
326 |
|
327 if ( aEmlEntry.Priority() != msgPriority ) |
|
328 { |
|
329 aEmlEntry.SetPriority( msgPriority ); |
|
330 modified = ETrue; |
|
331 } |
|
332 |
|
333 // EFSMsgFlag_FollowUpComplete: no counterpart in Symbian message |
|
334 |
|
335 // EFSMsgFlag_FollowUp: supported only with IMAP4 (see below) |
|
336 |
|
337 // EFSMsgFlag_Attachments: It does not seem reasonable to update |
|
338 // this flag here (but when attachments are added) |
|
339 |
|
340 // EFSMsgFlag_Multiple: no counterpart in Symbian message |
|
341 |
|
342 // EFSMsgFlag_CalendarMsg |
|
343 if( ( aEmlEntry.iMtm == KSenduiMtmSmtpUid ) && ( msgFlags & EFSMsgFlag_CalendarMsg ) ) |
|
344 { |
|
345 if( !aEmlEntry.ICalendar() ) |
|
346 { |
|
347 aEmlEntry.SetICalendar( ETrue ); |
|
348 modified = ETrue; |
|
349 } |
|
350 } |
|
351 |
|
352 |
|
353 // EFSMsgFlag_Answered: supported only with IMAP4 (see below) |
|
354 |
|
355 // EFSMsgFlag_Forwarded: no counterpart in Symbian message in S60 3.1 |
|
356 |
|
357 // EFSMsgFlag_OnlyToMe: no counterpart in Symbian message |
|
358 |
|
359 // EFSMsgFlag_RemoteDeleted: no counterpart in Symbian message |
|
360 |
|
361 // EFSMsgFlag_HasMsgSender: no counterpart in Symbian message |
|
362 |
|
363 |
|
364 //this applies to POP too. Just ignore the misleading naming |
|
365 // moved to fix EANA-7HUD2G, pop doesn't support permanent flags |
|
366 // EFSMsgFlag_Answered |
|
367 |
|
368 // IMAP flags |
|
369 if ( aEmlEntry.iMtm == KSenduiMtmImap4Uid ) |
|
370 { |
|
371 // EFSMsgFlag_FollowUp |
|
372 if ( LogicalXor( aEmlEntry.FlaggedIMAP4Flag(), |
|
373 ( msgFlags & EFSMsgFlag_FollowUp ) ) ) |
|
374 { |
|
375 aEmlEntry.SetFlaggedIMAP4Flag( !aEmlEntry.FlaggedIMAP4Flag() ); |
|
376 modified = ETrue; |
|
377 } |
|
378 // EFSMsgFlag_Answered |
|
379 if ( LogicalXor( aEmlEntry.AnsweredIMAP4Flag(), |
|
380 ( msgFlags & EFSMsgFlag_Answered ) ) ) |
|
381 { |
|
382 aEmlEntry.SetAnsweredIMAP4Flag( !aEmlEntry.AnsweredIMAP4Flag() ); |
|
383 modified = ETrue; |
|
384 } |
|
385 } |
|
386 return modified; |
|
387 } |
|
388 |
|
389 // --------------------------------------------------------------------------- |
|
390 // --------------------------------------------------------------------------- |
|
391 void CIpsPlgMsgMapper::UpdateMessageFlagsL( |
|
392 TMsvId aEntryId, |
|
393 const CFSMailMessage& aMessage ) |
|
394 { |
|
395 FUNC_LOG; |
|
396 // This function updates tEntry from aMessage |
|
397 CMsvEntry* cEntry = iSession.GetEntryL( aEntryId ); |
|
398 CleanupStack::PushL( cEntry ); |
|
399 |
|
400 TMsvEmailEntry tEntry( cEntry->Entry() ); |
|
401 TBool isModified = ChangeTEntryFlagsL( tEntry, aMessage ); |
|
402 |
|
403 if ( isModified ) |
|
404 { |
|
405 CIpsPlgOperationWait* waiter = CIpsPlgOperationWait::NewLC(); |
|
406 CMsvOperation* ops = cEntry->ChangeL( tEntry, waiter->iStatus ); |
|
407 CleanupStack::PushL( ops ); |
|
408 waiter->Start(); |
|
409 CleanupStack::PopAndDestroy( 2, waiter ); |
|
410 } |
|
411 |
|
412 CleanupStack::PopAndDestroy( cEntry ); |
|
413 } |
|
414 |
|
415 // --------------------------------------------------------------------------- |
|
416 // --------------------------------------------------------------------------- |
|
417 CMsvOperation* CIpsPlgMsgMapper::UpdateMessageFlagsAsyncL( |
|
418 TMsvId aEntryId, |
|
419 const CFSMailMessage& aMessage, |
|
420 TRequestStatus& aStatus ) |
|
421 { |
|
422 FUNC_LOG; |
|
423 // This function updates tEntry from aMessage |
|
424 CMsvEntry* cEntry = iSession.GetEntryL( aEntryId ); |
|
425 CleanupStack::PushL( cEntry ); |
|
426 TMsvEmailEntry tEntry( cEntry->Entry() ); |
|
427 |
|
428 TBool isModified = ChangeTEntryFlagsL( tEntry, aMessage ); |
|
429 CMsvOperation* ops = NULL; |
|
430 if ( isModified ) |
|
431 { |
|
432 ops = cEntry->ChangeL( tEntry, aStatus ); |
|
433 } |
|
434 |
|
435 CleanupStack::PopAndDestroy( cEntry ); |
|
436 return ops; |
|
437 } |
|
438 |
|
439 // --------------------------------------------------------------------------- |
|
440 // --------------------------------------------------------------------------- |
|
441 void CIpsPlgMsgMapper::SetFSMessageFlagsL( |
|
442 const TMsvEmailEntry& aEntry, CFSMailMessage& aMsg ) |
|
443 { |
|
444 FUNC_LOG; |
|
445 // this is just stupid through call, but now not need to |
|
446 // move SetFlags to public |
|
447 SetFlags( aEntry, aMsg ); |
|
448 } |
|
449 |
|
450 // --------------------------------------------------------------------------- |
|
451 // CIpsPlgMsgMapper::NewChildPartL |
|
452 // The method supports currently only the multipart/alternative structure |
|
453 // construction (which is needed in the meeting request messages). |
|
454 // The creation of the multipart structure happens by changing the folder |
|
455 // type of the (SMTP) message entry itself. The folder entry is created |
|
456 // by Symbian MTM later when new parts are added below the multipart |
|
457 // structure. This causes some problems because there is no new entry |
|
458 // in this phase and so the new CFSMailMessagePart instance do not |
|
459 // --------------------------------------------------------------------------- |
|
460 CFSMailMessagePart* CIpsPlgMsgMapper::NewChildPartL( |
|
461 const TFSMailMsgId& /* aMailBoxId */, |
|
462 const TFSMailMsgId& aMessageId, |
|
463 const TFSMailMsgId& /* aParentPartId */, |
|
464 const TDesC& /*aContentType*/ ) |
|
465 { |
|
466 FUNC_LOG; |
|
467 CFSMailMessagePart* result( NULL ); |
|
468 result = CFSMailMessagePart::NewLC( aMessageId, |
|
469 TFSMailMsgId( aMessageId.PluginId().iUid, |
|
470 KMsvNullIndexEntryIdValue ) ); |
|
471 CleanupStack::Pop( result ); |
|
472 return result; |
|
473 } |
|
474 |
|
475 // --------------------------------------------------------------------------- |
|
476 // CIpsPlgMsgMapper::SetDateL |
|
477 // --------------------------------------------------------------------------- |
|
478 // |
|
479 void CIpsPlgMsgMapper::SetDateL( |
|
480 const TMsvEntry& aEntry, |
|
481 CFSMailMessage& aMsg ) |
|
482 { |
|
483 FUNC_LOG; |
|
484 const TTime date = aEntry.iDate; |
|
485 aMsg.SetDate( date ); |
|
486 } |
|
487 |
|
488 // --------------------------------------------------------------------------- |
|
489 // CIpsPlgMsgMapper::SetSubjectL |
|
490 // --------------------------------------------------------------------------- |
|
491 // |
|
492 void CIpsPlgMsgMapper::SetSubjectL( |
|
493 const TMsvEntry& aEntry, |
|
494 CFSMailMessage& aMsg ) |
|
495 { |
|
496 FUNC_LOG; |
|
497 aMsg.SetSubject( aEntry.iDescription ); |
|
498 } |
|
499 |
|
500 // --------------------------------------------------------------------------- |
|
501 // CIpsPlgMsgMapper::SetSenderL |
|
502 // --------------------------------------------------------------------------- |
|
503 // |
|
504 void CIpsPlgMsgMapper::SetSenderL( |
|
505 TPtrC aSender, |
|
506 CFSMailMessage& aMsg ) |
|
507 { |
|
508 FUNC_LOG; |
|
509 CFSMailAddress* addr = CFSMailAddress::NewLC(); |
|
510 ConvertAddressL( aSender, *addr ); |
|
511 aMsg.SetSender( addr ); |
|
512 CleanupStack::Pop( addr ); |
|
513 } |
|
514 |
|
515 // --------------------------------------------------------------------------- |
|
516 // --------------------------------------------------------------------------- |
|
517 void CIpsPlgMsgMapper::SetEnvelopeL( |
|
518 const CMsvEntry* aEntry, |
|
519 CMsvStore* aStore, |
|
520 CFSMailMessage& aMsg ) |
|
521 { |
|
522 FUNC_LOG; |
|
523 CFSMailAddress* addr = NULL; |
|
524 |
|
525 TMsvEmailEntry tEntry( aEntry->Entry() ); |
|
526 |
|
527 SetDateL( tEntry, aMsg ); |
|
528 SetSubjectL( tEntry, aMsg ); |
|
529 |
|
530 if ( aStore && aStore->IsPresentL( KUidMsgFileIMailHeader ) ) |
|
531 { |
|
532 CImHeader* header = CImHeader::NewLC(); |
|
533 header->RestoreL( *aStore ); |
|
534 |
|
535 SetSenderL( header->From(), aMsg ); |
|
536 |
|
537 const CDesCArray& toRecs = header->ToRecipients(); |
|
538 |
|
539 for( TInt i=0; i<toRecs.Count(); i++ ) |
|
540 { |
|
541 addr = CFSMailAddress::NewLC(); |
|
542 ConvertAddressL( toRecs[i], *addr ); |
|
543 aMsg.AppendToRecipient( addr ); |
|
544 CleanupStack::Pop( addr ); |
|
545 } |
|
546 |
|
547 const CDesCArray& ccRecs = header->CcRecipients(); |
|
548 |
|
549 for( TInt i=0; i<ccRecs.Count(); i++ ) |
|
550 { |
|
551 addr = CFSMailAddress::NewLC(); |
|
552 ConvertAddressL( ccRecs[i], *addr ); |
|
553 aMsg.AppendCCRecipient( addr ); |
|
554 CleanupStack::Pop( addr ); |
|
555 } |
|
556 |
|
557 const CDesCArray& bccRecs = header->BccRecipients(); |
|
558 |
|
559 for( TInt i=0; i< bccRecs.Count(); i++ ) |
|
560 { |
|
561 addr = CFSMailAddress::NewLC(); |
|
562 ConvertAddressL( bccRecs[i], *addr ); |
|
563 aMsg.AppendBCCRecipient( addr ); |
|
564 CleanupStack::Pop( addr ); |
|
565 } |
|
566 |
|
567 CleanupStack::PopAndDestroy( header ); |
|
568 } |
|
569 else |
|
570 { |
|
571 // if the email header stream is not available, the sender |
|
572 // information is taken from the index entry |
|
573 SetSenderL( aEntry->Entry().iDetails, aMsg ); |
|
574 } |
|
575 } |
|
576 |
|
577 // --------------------------------------------------------------------------- |
|
578 // --------------------------------------------------------------------------- |
|
579 void CIpsPlgMsgMapper::SetStructureL( |
|
580 const CMsvEntry* aEntry, |
|
581 CFSMailMessage& aMessage ) |
|
582 { |
|
583 FUNC_LOG; |
|
584 // Find out the content type by studying the child entry: |
|
585 // If there are no children, the message contents are not fetched and |
|
586 // thus the content type cannot be inferred. On the other hand, |
|
587 // the message entry should never have more than one child entry |
|
588 // (otherwise, it should be a multipart message) |
|
589 if ( aEntry->Count() == 1 ) |
|
590 { |
|
591 TMsvEmailEntry tEntry = (*aEntry)[0]; |
|
592 if ( tEntry.iType == KUidMsvFolderEntry ) |
|
593 { |
|
594 aMessage.SetContentType( |
|
595 ConvertMultipartMimeType( tEntry.MessageFolderType() ) ); |
|
596 } |
|
597 else |
|
598 // The case in which the content entry is directly below |
|
599 // the message entry.. |
|
600 { |
|
601 aMessage.SetContentType( KMimeTypeMultipartMixed ); |
|
602 } |
|
603 } |
|
604 else |
|
605 { |
|
606 // mark message structure state unknown if we don't have any |
|
607 // child parts. This needed to ui start fetch |
|
608 aMessage.SetMessagePartsStatus( EFSEmailStructureUnknown ); |
|
609 } |
|
610 |
|
611 aMessage.SetContentSize( aEntry->Entry().iSize ); |
|
612 } |
|
613 |
|
614 // --------------------------------------------------------------------------- |
|
615 // CIpsPlgMsgMapper::SetFlags |
|
616 // FS framework's flag definitions and methods are somewhat clumsy and thus |
|
617 // there is quite much code for a pretty simple function.. |
|
618 // --------------------------------------------------------------------------- |
|
619 void CIpsPlgMsgMapper::SetFlags( |
|
620 const TMsvEmailEntry& aEntry, |
|
621 CFSMailMessage& aMsg ) |
|
622 { |
|
623 FUNC_LOG; |
|
624 |
|
625 TBool forwardedMeetingRequest = EFalse; |
|
626 |
|
627 // EFSMsgFlag_Read |
|
628 // EFSMsgFlag_Read_Locally |
|
629 if ( aEntry.Unread() ) |
|
630 { |
|
631 aMsg.ResetFlag( EFSMsgFlag_Read ); |
|
632 aMsg.ResetFlag( EFSMsgFlag_Read_Locally ); |
|
633 } |
|
634 else |
|
635 { |
|
636 aMsg.SetFlag( EFSMsgFlag_Read ); |
|
637 aMsg.SetFlag( EFSMsgFlag_Read_Locally ); |
|
638 } |
|
639 |
|
640 // EFSMsgFlag_Low |
|
641 // EFSMsgFlag_Important |
|
642 switch ( aEntry.Priority() ) |
|
643 { |
|
644 case EMsvHighPriority: |
|
645 { |
|
646 aMsg.SetFlag( EFSMsgFlag_Important ); |
|
647 aMsg.ResetFlag( EFSMsgFlag_Low ); |
|
648 break; |
|
649 } |
|
650 case EMsvMediumPriority: |
|
651 { |
|
652 aMsg.ResetFlag( EFSMsgFlag_Important ); |
|
653 aMsg.ResetFlag( EFSMsgFlag_Low ); |
|
654 break; |
|
655 } |
|
656 case EMsvLowPriority: |
|
657 { |
|
658 aMsg.ResetFlag( EFSMsgFlag_Important ); |
|
659 aMsg.SetFlag( EFSMsgFlag_Low ); |
|
660 break; |
|
661 } |
|
662 } |
|
663 |
|
664 // EFSMsgFlag_FollowUpComplete: cannot be supported with Symbian messages? |
|
665 |
|
666 // EFSMsgFlag_FollowUp: supported only with IMAP4 messages (see below) |
|
667 aMsg.ResetFlag( EFSMsgFlag_FollowUp ); |
|
668 |
|
669 // <cmail> |
|
670 //only for incomplete POP3 messages |
|
671 if ( aEntry.iMtm.iUid == KSenduiMtmPop3UidValue && |
|
672 ( !aEntry.Complete() || aEntry.PartialDownloaded () ) ) |
|
673 { |
|
674 TRAP_IGNORE( AttaCheckForIncompleteMsgL( aEntry, aMsg ) ); |
|
675 } |
|
676 // </cmail> |
|
677 else |
|
678 { |
|
679 // EFSMsgFlag_Attachments |
|
680 if ( aEntry.Attachment() ) |
|
681 { |
|
682 aMsg.SetFlag( EFSMsgFlag_Attachments ); |
|
683 |
|
684 if ( aEntry.ICalendar() ) |
|
685 { |
|
686 // <cmail> implementation changed due to cs warning |
|
687 TInt attCount = 0; |
|
688 TRAPD ( err, attCount = GetAttachmentCountL( aEntry ) ); |
|
689 if ( err == KErrNone && attCount == 1 ) |
|
690 { |
|
691 CMsvEntry* cEntry = NULL; |
|
692 TRAPD ( err2, cEntry = iSession.GetEntryL( aEntry.Id() ) ); |
|
693 if ( err2 == KErrNone && cEntry->Count() == 1 ) |
|
694 { |
|
695 TMsvEmailEntry tEntry = (*cEntry)[0]; |
|
696 TImEmailFolderType ft = tEntry.MessageFolderType(); |
|
697 if ( tEntry.iType == KUidMsvFolderEntry && ft == EFolderTypeMixed ) |
|
698 { |
|
699 // Message with calendar object. But based on content type |
|
700 // (multipart/mixed) we know that this is meeting request |
|
701 // forwarded as email, so it must be seen as normal email. |
|
702 forwardedMeetingRequest = ETrue; |
|
703 aMsg.ResetFlag( EFSMsgFlag_CalendarMsg ); |
|
704 aMsg.SetFlag( EFSMsgFlag_Attachments ); |
|
705 } |
|
706 else |
|
707 { |
|
708 // Only text/calendar part included as attachment |
|
709 aMsg.ResetFlag( EFSMsgFlag_Attachments ); |
|
710 //Set Attachment flag for CMsvEntry (needed for sorting) |
|
711 TRAP_IGNORE( SetAttachmentFlagL( aEntry, EFalse ) ); |
|
712 } |
|
713 } |
|
714 delete cEntry; |
|
715 cEntry = NULL; |
|
716 } |
|
717 // </cmail> |
|
718 } |
|
719 } |
|
720 else |
|
721 { |
|
722 aMsg.ResetFlag( EFSMsgFlag_Attachments ); |
|
723 } |
|
724 } |
|
725 |
|
726 // EFSMsgFlag_Multiple: currently this is not used anywhere and |
|
727 // to evaluate the value, the CMsvStore of the message should be |
|
728 // accessed which is relatively slow (compared to the access of |
|
729 // the index entry) |
|
730 |
|
731 // EFSMsgFlag_CalendarMsg |
|
732 if ( aEntry.ICalendar() && !forwardedMeetingRequest ) // <cmail> |
|
733 { |
|
734 aMsg.SetFlag( EFSMsgFlag_CalendarMsg ); |
|
735 } |
|
736 else if( !( aMsg.GetFlags() & EFSMsgFlag_CalendarMsg ) ) |
|
737 { |
|
738 // Flag not set by mrui, we can reset it |
|
739 aMsg.ResetFlag( EFSMsgFlag_CalendarMsg ); |
|
740 } |
|
741 |
|
742 // EFSMsgFlag_Answered: supported only with IMAP4 messages (see below) |
|
743 aMsg.ResetFlag( EFSMsgFlag_Answered ); |
|
744 |
|
745 // EFSMsgFlag_Forwarded: not supported in S60 3.1 |
|
746 aMsg.ResetFlag( EFSMsgFlag_Forwarded ); |
|
747 |
|
748 // EFSMsgFlag_OnlyToMe: like EFSMsgFlag_Multiple |
|
749 |
|
750 // EFSMsgFlag_RemoteDeleted: no reasonable use in IPS |
|
751 |
|
752 // EFSMsgFlag_HasMsgSender: currently not used anywhere. Could be |
|
753 // probably be supported by checking the contents of TmsvEntry::iDetails |
|
754 // but this should be tested |
|
755 |
|
756 // Additional logic for IMAP4 messages |
|
757 if ( aEntry.iMtm == KSenduiMtmImap4Uid ) |
|
758 { |
|
759 if ( aEntry.FlaggedIMAP4Flag() ) |
|
760 { |
|
761 aMsg.SetFlag( EFSMsgFlag_FollowUp ); |
|
762 } |
|
763 // moved to fix EANA-7HUD2G, pop doesn't support permanent flags |
|
764 if ( aEntry.AnsweredIMAP4Flag() ) |
|
765 { |
|
766 aMsg.SetFlag( EFSMsgFlag_Answered ); |
|
767 } |
|
768 } |
|
769 } |
|
770 |
|
771 // --------------------------------------------------------------------------- |
|
772 // --------------------------------------------------------------------------- |
|
773 void CIpsPlgMsgMapper::SetFetchStateL( |
|
774 const TMsvEmailEntry& aEntry, |
|
775 TMsvId aMsgMainId, |
|
776 TBool aIsAtta, |
|
777 CFSMailMessagePart& aMessage ) |
|
778 { |
|
779 FUNC_LOG; |
|
780 if ( aEntry.iMtm.iUid == KSenduiMtmPop3UidValue && |
|
781 aEntry.Id() != aMsgMainId && |
|
782 !aIsAtta ) |
|
783 { |
|
784 TInt error = KErrNone; |
|
785 TMsvEmailEntry emlEntry; |
|
786 TMsvId dummy; |
|
787 |
|
788 error = iSession.GetEntry( aMsgMainId , dummy, emlEntry ); |
|
789 |
|
790 if ( error == KErrNone ) |
|
791 { |
|
792 DoSetFetchStateL( emlEntry, aMsgMainId, aIsAtta, aMessage ); |
|
793 } |
|
794 else |
|
795 { |
|
796 aMessage.SetMessagePartsStatus( EFSEmailStructureUnknown ); |
|
797 } |
|
798 } |
|
799 else |
|
800 { |
|
801 DoSetFetchStateL( aEntry, aMsgMainId, aIsAtta, aMessage ); |
|
802 } |
|
803 } |
|
804 |
|
805 // --------------------------------------------------------------------------- |
|
806 // --------------------------------------------------------------------------- |
|
807 void CIpsPlgMsgMapper::DoSetFetchStateL( |
|
808 const TMsvEmailEntry& aEntry, |
|
809 TMsvId aMsgMainId, |
|
810 TBool aIsAtta, |
|
811 CFSMailMessagePart& aMessage ) |
|
812 { |
|
813 FUNC_LOG; |
|
814 if ( aEntry.PartialDownloaded() ) |
|
815 { |
|
816 aMessage.SetMessagePartsStatus( EFSPartial ); |
|
817 } |
|
818 else if ( aEntry.BodyTextComplete() && !aIsAtta ) |
|
819 { |
|
820 aMessage.SetMessagePartsStatus( EFSFull ); |
|
821 } |
|
822 else if ( aEntry.Complete() && !aIsAtta ) |
|
823 { |
|
824 aMessage.SetMessagePartsStatus( EFSFull ); |
|
825 } |
|
826 else if ( aEntry.Complete() && aIsAtta ) |
|
827 { |
|
828 CMsvEntry* cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
829 |
|
830 CleanupStack::PushL( cEntry ); |
|
831 |
|
832 TBool hasStore = cEntry->HasStoreL(); |
|
833 |
|
834 if ( hasStore ) |
|
835 { |
|
836 CMsvStore* store = cEntry->EditStoreL(); |
|
837 |
|
838 CleanupStack::PushL( store ); |
|
839 |
|
840 MMsvAttachmentManager& attMgr = store->AttachmentManagerL(); |
|
841 |
|
842 if ( attMgr.AttachmentCount() ) |
|
843 { |
|
844 aMessage.SetMessagePartsStatus( EFSFull ); |
|
845 } |
|
846 else |
|
847 { |
|
848 aMessage.SetMessagePartsStatus( EFSNone ); |
|
849 } |
|
850 |
|
851 CleanupStack::PopAndDestroy( store ); |
|
852 } |
|
853 |
|
854 CleanupStack::PopAndDestroy( cEntry ); |
|
855 } |
|
856 else if ( aEntry.Id() != aMsgMainId ) |
|
857 { |
|
858 // fetch state of some message part, then we sure know |
|
859 // structure, but its not complete nor partial so state must be |
|
860 // none |
|
861 aMessage.SetMessagePartsStatus( EFSNone ); |
|
862 } |
|
863 else |
|
864 { |
|
865 aMessage.SetMessagePartsStatus( EFSEmailStructureUnknown ); |
|
866 } |
|
867 } |
|
868 |
|
869 |
|
870 // --------------------------------------------------------------------------- |
|
871 // --------------------------------------------------------------------------- |
|
872 TPtrC CIpsPlgMsgMapper::ConvertMultipartMimeType( |
|
873 TImEmailFolderType aFolderType ) const |
|
874 { |
|
875 FUNC_LOG; |
|
876 TPtrC result; |
|
877 |
|
878 switch ( aFolderType ) |
|
879 { |
|
880 case EFolderTypeRelated: |
|
881 { |
|
882 result.Set( KMimeTypeMultipartRelated ); |
|
883 break; |
|
884 } |
|
885 case EFolderTypeMixed: |
|
886 { |
|
887 result.Set( KMimeTypeMultipartMixed ); |
|
888 break; |
|
889 } |
|
890 case EFolderTypeParallel: |
|
891 { |
|
892 result.Set( KMimeTypeMultipartParallel ); |
|
893 break; |
|
894 } |
|
895 case EFolderTypeAlternative: |
|
896 { |
|
897 result.Set( KMimeTypeMultipartAlternative ); |
|
898 break; |
|
899 } |
|
900 case EFolderTypeDigest: |
|
901 { |
|
902 result.Set( KMimeTypeMultipartDigest ); |
|
903 break; |
|
904 } |
|
905 case EFolderTypeRFC822: |
|
906 { |
|
907 result.Set( KMimeTypeMultipartRfc822 ); |
|
908 break; |
|
909 } |
|
910 case EFolderTypePartial: |
|
911 { |
|
912 result.Set( KMimeTypeMultipartPartial ); |
|
913 break; |
|
914 } |
|
915 case EFolderTypeDirectory: |
|
916 { |
|
917 result.Set( KMimeTypeMultipartDirectory ); |
|
918 break; |
|
919 } |
|
920 case EFolderTypeExternal: |
|
921 { |
|
922 result.Set( KMimeTypeMultipartExternalBody ); |
|
923 break; |
|
924 } |
|
925 case EFolderTypeUnknown: |
|
926 default: |
|
927 { |
|
928 result.Set( KNullDesC16 ); |
|
929 break; |
|
930 } |
|
931 } |
|
932 |
|
933 return result; |
|
934 } |
|
935 |
|
936 // --------------------------------------------------------------------------- |
|
937 // --------------------------------------------------------------------------- |
|
938 // <cmail> |
|
939 TInt CIpsPlgMsgMapper::ConvertBodyPartMimeType( |
|
940 const TUid& aEntryType, |
|
941 TDes& aMimeType ) |
|
942 { |
|
943 FUNC_LOG; |
|
944 TInt result( KErrNone ); |
|
945 |
|
946 switch ( aEntryType.iUid ) |
|
947 { |
|
948 case KUidMsvEmailTextEntryValue: |
|
949 { |
|
950 aMimeType.Append( KMimeTypeTextPlain ); |
|
951 break; |
|
952 } |
|
953 case KUidMsvEmailHtmlEntryValue: |
|
954 { |
|
955 aMimeType.Append( KMimeTypeTextHtml ); |
|
956 break; |
|
957 } |
|
958 case KUidMsvEmailExternalBodyEntryValue: |
|
959 { |
|
960 // This seems a bit suspicious, but it is improbable that this case |
|
961 // is ever used.. |
|
962 aMimeType.Append( KMimeTypeMultipartExternalBody ); |
|
963 break; |
|
964 } |
|
965 case KUidMsvEmailRtfEntryValue: |
|
966 { |
|
967 aMimeType.Append( KMimeTypeTextRtf ); |
|
968 break; |
|
969 } |
|
970 default: |
|
971 { |
|
972 result = KErrNotFound; |
|
973 } |
|
974 } |
|
975 return result; |
|
976 } |
|
977 // </cmail> |
|
978 |
|
979 // --------------------------------------------------------------------------- |
|
980 // --------------------------------------------------------------------------- |
|
981 void CIpsPlgMsgMapper::ConvertAddressL( |
|
982 TPtrC aSourceAddress, |
|
983 CFSMailAddress& aTargetAddress ) |
|
984 { |
|
985 FUNC_LOG; |
|
986 TInt status( KErrNone ); |
|
987 TImMessageField mailField; |
|
988 |
|
989 aTargetAddress.SetEmailAddress( |
|
990 mailField.GetValidInternetEmailAddressFromString( aSourceAddress ) ); |
|
991 |
|
992 // <cmail> |
|
993 // If previous validation fails because of invalid email address. |
|
994 // e.g '@' is missing. Then address between '<' and '>' marks is used. |
|
995 TInt start( aSourceAddress.LocateReverse('<') ); |
|
996 if ( start != KErrNotFound && start > 0) |
|
997 { |
|
998 TInt end( aSourceAddress.LocateReverse('>') ); |
|
999 start += 1; |
|
1000 aTargetAddress.SetEmailAddress( aSourceAddress.Mid( start, ( end - start ) ) ); |
|
1001 } |
|
1002 // </cmail> |
|
1003 |
|
1004 TPtrC alias = mailField.GetValidAlias( aSourceAddress, status ); |
|
1005 if ( status == KErrNone ) |
|
1006 { |
|
1007 TPtr alias2 = alias.AllocLC()->Des(); // have to create copy because alias might change |
|
1008 for ( TInt ii = 0; ii < alias2.Length(); ii++ ) |
|
1009 { |
|
1010 if ( alias2[ii] <= KCharNonPrintable ) |
|
1011 { |
|
1012 alias2.Delete( ii, 1 ); |
|
1013 ii--; |
|
1014 } |
|
1015 else if ( ii < ( alias2.Length() - 1 ) && |
|
1016 alias2[ii] == KCharEscape ) |
|
1017 { |
|
1018 if( alias2[ii+1] == KCharAt ) |
|
1019 { |
|
1020 alias2.Delete( ii, 1 ); |
|
1021 ii--; |
|
1022 } |
|
1023 } |
|
1024 } |
|
1025 aTargetAddress.SetDisplayName( alias2 ); // creates its own copy |
|
1026 CleanupStack::PopAndDestroy(); |
|
1027 } |
|
1028 else |
|
1029 { |
|
1030 // <cmail> |
|
1031 aTargetAddress.SetDisplayName( aTargetAddress.GetEmailAddress() ); |
|
1032 // </cmail> |
|
1033 } |
|
1034 } |
|
1035 |
|
1036 |
|
1037 // --------------------------------------------------------------------------- |
|
1038 // --------------------------------------------------------------------------- |
|
1039 void CIpsPlgMsgMapper::SetContentTypeL( |
|
1040 CImMimeHeader& aMimeHeader, |
|
1041 CFSMailMessagePart& aMessagePart ) |
|
1042 { |
|
1043 FUNC_LOG; |
|
1044 HBufC8* buffer8 = HBufC8::NewLC( |
|
1045 aMimeHeader.ContentType().Length() + |
|
1046 aMimeHeader.ContentSubType().Length() + 1 ); |
|
1047 buffer8->Des().Append( aMimeHeader.ContentType() ); |
|
1048 buffer8->Des().Append( KSlash ); |
|
1049 buffer8->Des().Append( aMimeHeader.ContentSubType() ); |
|
1050 HBufC* buffer = HBufC::NewLC( buffer8->Length() ); |
|
1051 buffer->Des().Copy( buffer8->Des() ); |
|
1052 aMessagePart.SetContentType( *buffer ); |
|
1053 CleanupStack::PopAndDestroy( 2, buffer8 ); // buffer |
|
1054 } |
|
1055 |
|
1056 // --------------------------------------------------------------------------- |
|
1057 // --------------------------------------------------------------------------- |
|
1058 void CIpsPlgMsgMapper::GetChildPartsOfMessageEntryL( |
|
1059 const TFSMailMsgId& aMailBoxId, |
|
1060 const TFSMailMsgId& aMessageId, |
|
1061 RPointerArray<CFSMailMessagePart>& aParts ) |
|
1062 { |
|
1063 FUNC_LOG; |
|
1064 CFSMailMessagePart* childPart( NULL ); |
|
1065 CMsvEntry* cEntry = iSession.GetEntryL( aMessageId.Id() ); |
|
1066 CleanupStack::PushL( cEntry ); |
|
1067 |
|
1068 if ( cEntry->Count() > 0 ) |
|
1069 { |
|
1070 // Note: it is assumed that there is only one child which is |
|
1071 // either the body part (simple message) or the folder entry |
|
1072 // representing the main level multipart structure |
|
1073 if ( (*cEntry)[0].iType == KUidMsvFolderEntry ) |
|
1074 { |
|
1075 GetChildPartsOfFolderEntryL( aMailBoxId, aMessageId, |
|
1076 (*cEntry)[0].Id(), aParts); |
|
1077 } |
|
1078 else |
|
1079 { |
|
1080 childPart = GetMessagePartL( (*cEntry)[0].Id(), aMailBoxId, aMessageId ); |
|
1081 if( childPart ) |
|
1082 { |
|
1083 aParts.Append( childPart ); |
|
1084 } |
|
1085 } |
|
1086 } |
|
1087 CleanupStack::PopAndDestroy( cEntry ); |
|
1088 } |
|
1089 |
|
1090 // --------------------------------------------------------------------------- |
|
1091 // CIpsPlgMsgMapper::GetChildPartsOfFolderEntryL |
|
1092 // Note: if the aParentId does not refer to a folder entry, childCount |
|
1093 // will be zero and the method does not do anything. |
|
1094 // It assumed that the method is called mainly for the folder entries |
|
1095 // and thus CMsvEntry is constructed without checking the entry type |
|
1096 // beforehand. If the assumption is not correct, the performance can be |
|
1097 // optimized by checking the entry type first. |
|
1098 // --------------------------------------------------------------------------- |
|
1099 void CIpsPlgMsgMapper::GetChildPartsOfFolderEntryL( |
|
1100 const TFSMailMsgId& aMailBoxId, |
|
1101 const TFSMailMsgId& aMessageId, |
|
1102 TMsvId aParentId, |
|
1103 RPointerArray<CFSMailMessagePart>& aParts ) |
|
1104 { |
|
1105 FUNC_LOG; |
|
1106 CMsvEntry* cEntry = iSession.GetEntryL( aParentId ); |
|
1107 CleanupStack::PushL( cEntry ); |
|
1108 CFSMailMessagePart* childPart( NULL ); |
|
1109 TInt childCount( cEntry->Count() ); |
|
1110 TInt i; |
|
1111 TInt position; |
|
1112 TBool textBodyPartFound( EFalse ); |
|
1113 |
|
1114 for (i = 0; i < childCount; i++ ) |
|
1115 { |
|
1116 childPart = GetMessagePartL( (*cEntry)[i].Id(), aMailBoxId, aMessageId ); |
|
1117 |
|
1118 // Child parts have to be ordered so that the plain text body |
|
1119 // part is first (if such exists) and the HTML body is next. |
|
1120 // The rest of the children can be in any order. |
|
1121 if ( (*cEntry)[i].iType == KUidMsvEmailTextEntry ) |
|
1122 { |
|
1123 position = 0; |
|
1124 textBodyPartFound = ETrue; |
|
1125 } |
|
1126 else if ( (*cEntry)[i].iType == KUidMsvEmailHtmlEntry ) |
|
1127 { |
|
1128 if ( textBodyPartFound ) |
|
1129 { |
|
1130 position = 1; |
|
1131 } |
|
1132 else |
|
1133 { |
|
1134 position = 0; |
|
1135 } |
|
1136 } |
|
1137 else |
|
1138 { |
|
1139 position = i; |
|
1140 } |
|
1141 |
|
1142 // Insert the new child part to the result array |
|
1143 if ( childPart ) |
|
1144 { |
|
1145 aParts.Insert( childPart, position ); |
|
1146 childPart = NULL; |
|
1147 } |
|
1148 } |
|
1149 CleanupStack::PopAndDestroy( cEntry ); |
|
1150 } |
|
1151 |
|
1152 // --------------------------------------------------------------------------- |
|
1153 // --------------------------------------------------------------------------- |
|
1154 CFSMailMessagePart* CIpsPlgMsgMapper::ConvertBodyEntry2MessagePartL( |
|
1155 const TMsvEmailEntry& aEntry, |
|
1156 const TFSMailMsgId& aMailBoxId, |
|
1157 const TFSMailMsgId& aMessageId ) |
|
1158 { |
|
1159 FUNC_LOG; |
|
1160 CFSMailMessagePart* result( NULL ); |
|
1161 TInt status; |
|
1162 // <cmail> |
|
1163 HBufC* buf = HBufC::NewLC( KMaxContentTypeLength ); |
|
1164 TPtr contentType = buf->Des(); |
|
1165 |
|
1166 status = ConvertBodyPartMimeType( aEntry.iType, contentType ); |
|
1167 __ASSERT_DEBUG( ( status == KErrNone ), |
|
1168 User::Panic( KIpsPlgPanicCategory, EIpsPlgInvalidEntry ) ); |
|
1169 if ( status == KErrNone ) |
|
1170 { |
|
1171 result = CFSMailMessagePart::NewLC( |
|
1172 aMessageId, TFSMailMsgId( iPlugin.PluginId(), aEntry.Id() ) ); |
|
1173 |
|
1174 // If mimetype is 'text/html' add charset parameter |
|
1175 if ( aEntry.iType.iUid == KUidMsvEmailHtmlEntryValue ) |
|
1176 { |
|
1177 GetCharsetParameterL( aEntry, contentType ); |
|
1178 } |
|
1179 // </cmail> |
|
1180 result->SetContentType( contentType ); |
|
1181 result->SetMailBoxId( aMailBoxId ); |
|
1182 |
|
1183 // Size |
|
1184 result->SetContentSize( aEntry.iSize ); |
|
1185 |
|
1186 if ( aEntry.Complete() ) |
|
1187 { |
|
1188 TMsvEmailEntry parent; |
|
1189 TMsvId dummy; |
|
1190 if ( aEntry.PartialDownloaded() ) |
|
1191 { |
|
1192 CMsvEntry* cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
1193 CleanupStack::PushL( cEntry ); |
|
1194 if ( cEntry->HasStoreL() ) |
|
1195 { |
|
1196 CMsvStore* store = cEntry->ReadStoreL(); |
|
1197 CleanupStack::PushL( store ); |
|
1198 result->SetFetchedContentSize( store->SizeL() ); |
|
1199 CleanupStack::PopAndDestroy( store ); |
|
1200 } |
|
1201 |
|
1202 // sometimes store size is bigger than msg size |
|
1203 // even if msg is partially downloaded, then set |
|
1204 // fetched content size smaller than msg size |
|
1205 TUint fetchedSize = result->FetchedContentSize(); |
|
1206 TUint contentSize = result->ContentSize(); |
|
1207 if ( (contentSize > 0) && (fetchedSize > contentSize) ) |
|
1208 { |
|
1209 result->SetFetchedContentSize( contentSize - 1 ); |
|
1210 } |
|
1211 |
|
1212 CleanupStack::PopAndDestroy( cEntry ); |
|
1213 } |
|
1214 else if ( aEntry.iMtm == KSenduiMtmPop3Uid && |
|
1215 iSession.GetEntry( aEntry.Parent(), dummy, parent ) |
|
1216 == KErrNone && parent.PartialDownloaded() ) |
|
1217 { |
|
1218 // we cant know remote size of pop body part, but |
|
1219 // we know it is not completely fetched at this point |
|
1220 // set content size fetchedSize+1 to make framework know that |
|
1221 // this message is not completely fetched |
|
1222 |
|
1223 result->SetContentSize( aEntry.iSize+1 ); |
|
1224 result->SetFetchedContentSize( aEntry.iSize ); |
|
1225 |
|
1226 } |
|
1227 else |
|
1228 { |
|
1229 result->SetFetchedContentSize( aEntry.iSize ); |
|
1230 } |
|
1231 // This is "gludge-fix" for situation when |
|
1232 // content size is zero and message is complete |
|
1233 // mark sizes to 1 then ui not assume that something |
|
1234 // missing and not try to fetch it |
|
1235 if ( aEntry.iSize == 0 ) |
|
1236 { |
|
1237 result->SetContentSize(1); |
|
1238 result->SetFetchedContentSize(1); |
|
1239 } |
|
1240 } |
|
1241 else |
|
1242 { |
|
1243 result->SetFetchedContentSize( 0 ); |
|
1244 } |
|
1245 |
|
1246 CleanupStack::Pop( result ); |
|
1247 } |
|
1248 SetFetchStateL( aEntry, aMessageId.Id(), EFalse, *result ); |
|
1249 CleanupStack::PopAndDestroy( buf ); |
|
1250 return result; |
|
1251 } |
|
1252 |
|
1253 // --------------------------------------------------------------------------- |
|
1254 // --------------------------------------------------------------------------- |
|
1255 CFSMailMessagePart* CIpsPlgMsgMapper::ConvertAttachmentEntry2MessagePartL( |
|
1256 const TMsvEmailEntry& aEntry, |
|
1257 const TFSMailMsgId& aMailBoxId, |
|
1258 const TFSMailMsgId& aMessageId ) |
|
1259 { |
|
1260 FUNC_LOG; |
|
1261 CFSMailMessagePart* result( NULL ); |
|
1262 HBufC* buffer; |
|
1263 CMsvEntry* cEntry; |
|
1264 |
|
1265 __ASSERT_DEBUG( ( aEntry.iType == KUidMsvAttachmentEntry || |
|
1266 aEntry.iType == KUidMsvMessageEntry ), |
|
1267 User::Panic( KIpsPlgPanicCategory, EIpsPlgInvalidEntry ) ); |
|
1268 |
|
1269 cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
1270 CleanupStack::PushL( cEntry ); |
|
1271 |
|
1272 if ( cEntry->HasStoreL() ) |
|
1273 { |
|
1274 result = CFSMailMessagePart::NewLC( aMessageId, |
|
1275 TFSMailMsgId( iPlugin.PluginId(), aEntry.Id() ) ); |
|
1276 |
|
1277 CMsvStore* store = cEntry->ReadStoreL(); |
|
1278 CleanupStack::PushL( store ); |
|
1279 |
|
1280 if ( store->IsPresentL( KUidMsgFileMimeHeader ) ) |
|
1281 { |
|
1282 CImMimeHeader* mimeHeader = CImMimeHeader::NewLC(); |
|
1283 mimeHeader->RestoreL( *store ); |
|
1284 |
|
1285 // Content-type |
|
1286 if ( aEntry.iType.iUid == KUidMsvMessageEntryValue ) |
|
1287 { |
|
1288 result->SetContentType( KMimeTypeMultipartRfc822 ); |
|
1289 } |
|
1290 else |
|
1291 { |
|
1292 SetContentTypeL( *mimeHeader, *result ); |
|
1293 } |
|
1294 |
|
1295 // Content-description |
|
1296 buffer = HBufC::NewLC( |
|
1297 mimeHeader->ContentDescription().Length ( ) ); |
|
1298 buffer->Des().Copy ( mimeHeader->ContentDescription ( ) ); |
|
1299 result->SetContentDescription ( *buffer ); |
|
1300 CleanupStack::PopAndDestroy ( buffer ); |
|
1301 buffer = NULL; |
|
1302 |
|
1303 // Content-disposition |
|
1304 buffer = HBufC::NewLC( |
|
1305 mimeHeader->ContentDisposition().Length ( ) ); |
|
1306 buffer->Des().Copy( mimeHeader->ContentDisposition() ); |
|
1307 result->SetContentDisposition( *buffer ); |
|
1308 CleanupStack::PopAndDestroy( buffer ); |
|
1309 buffer = NULL; |
|
1310 |
|
1311 // Content-type parameters |
|
1312 |
|
1313 CDesC8Array& sourceArray( mimeHeader->ContentTypeParams() ); |
|
1314 CDesCArray& targetArray( result->ContentTypeParameters() ); |
|
1315 for ( TInt i=0; i<sourceArray.Count(); i++ ) |
|
1316 { |
|
1317 buffer = HBufC::NewLC( sourceArray[i].Length() ); |
|
1318 buffer->Des().Copy( sourceArray[i] ); |
|
1319 targetArray.AppendL( buffer->Des() ); |
|
1320 CleanupStack::PopAndDestroy( buffer ); |
|
1321 buffer = NULL; |
|
1322 i++; |
|
1323 } |
|
1324 |
|
1325 // Content ID |
|
1326 buffer = HBufC::NewLC( |
|
1327 mimeHeader->ContentID().Length ( ) ); |
|
1328 buffer->Des().Copy( mimeHeader->ContentID() ); |
|
1329 result->SetContentIDL( *buffer ); |
|
1330 CleanupStack::PopAndDestroy( buffer ); |
|
1331 buffer = NULL; |
|
1332 |
|
1333 // Content-class: not supported by Symbian (non-standard field) |
|
1334 |
|
1335 CleanupStack::PopAndDestroy( mimeHeader ); |
|
1336 } |
|
1337 // Name |
|
1338 if ( aEntry.iType.iUid == KUidMsvMessageEntryValue ) |
|
1339 { |
|
1340 HBufC* att = HBufC::NewLC( aEntry.iDescription.Length() + KEmbeddedMsgExtensionLength ); |
|
1341 att->Des().Copy( aEntry.iDescription ); |
|
1342 att->Des().Append( KMessageExtension ); |
|
1343 result->SetAttachmentNameL( att->Des() ); |
|
1344 CleanupStack::PopAndDestroy( att ); |
|
1345 } |
|
1346 else |
|
1347 { |
|
1348 result->SetAttachmentNameL( aEntry.iDetails ); |
|
1349 } |
|
1350 |
|
1351 // Size |
|
1352 result->SetContentSize( aEntry.iSize ); |
|
1353 |
|
1354 if ( aEntry.Complete() ) |
|
1355 { |
|
1356 result->SetFetchedContentSize( aEntry.iSize ); |
|
1357 } |
|
1358 else |
|
1359 { |
|
1360 result->SetFetchedContentSize( 0 ); |
|
1361 } |
|
1362 result->SetMailBoxId( aMailBoxId ); |
|
1363 CleanupStack::PopAndDestroy(store); |
|
1364 CleanupStack::Pop( result ); |
|
1365 } |
|
1366 SetFetchStateL( aEntry, aMessageId.Id(), ETrue, *result ); |
|
1367 CleanupStack::PopAndDestroy( cEntry ); |
|
1368 |
|
1369 return result; |
|
1370 } |
|
1371 |
|
1372 // --------------------------------------------------------------------------- |
|
1373 // --------------------------------------------------------------------------- |
|
1374 CFSMailMessagePart* CIpsPlgMsgMapper::ConvertFolderEntry2MessagePartL( |
|
1375 const TMsvEmailEntry& aEntry, |
|
1376 const TFSMailMsgId& aMailBoxId, |
|
1377 const TFSMailMsgId& aMessageId ) |
|
1378 { |
|
1379 FUNC_LOG; |
|
1380 CFSMailMessagePart* result( NULL ); |
|
1381 |
|
1382 __ASSERT_DEBUG( ( aEntry.iType == KUidMsvFolderEntry ), |
|
1383 User::Panic( KIpsPlgPanicCategory, EIpsPlgInvalidEntry ) ); |
|
1384 |
|
1385 TPtrC mimeType = ConvertMultipartMimeType( aEntry.MessageFolderType() ); |
|
1386 |
|
1387 if ( mimeType.Length() > 0 ) |
|
1388 { |
|
1389 result = CFSMailMessagePart::NewLC( |
|
1390 aMessageId, TFSMailMsgId( iPlugin.PluginId(), aEntry.Id() ) ); |
|
1391 |
|
1392 result->SetContentType( mimeType ); |
|
1393 result->SetMailBoxId( aMailBoxId ); |
|
1394 |
|
1395 CleanupStack::Pop( result ); |
|
1396 } |
|
1397 |
|
1398 return result; |
|
1399 } |
|
1400 |
|
1401 |
|
1402 // --------------------------------------------------------------------------- |
|
1403 // |
|
1404 // |
|
1405 // --------------------------------------------------------------------------- |
|
1406 // <cmail> implemented to get rid of cs warning |
|
1407 TInt CIpsPlgMsgMapper::GetAttachmentCountL( |
|
1408 const TMsvEmailEntry& aEntry ) |
|
1409 { |
|
1410 FUNC_LOG; |
|
1411 TInt result( KErrNone ); |
|
1412 |
|
1413 CMsvEntry *cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
1414 CleanupStack::PushL( cEntry ); |
|
1415 CImEmailMessage* message = CImEmailMessage::NewLC( *cEntry ); |
|
1416 |
|
1417 message->GetAttachmentsListL( cEntry->Entry().Id( ), |
|
1418 CImEmailMessage::EAllAttachments, CImEmailMessage::EThisMessageOnly ); |
|
1419 |
|
1420 result = message->Selection().Count(); |
|
1421 |
|
1422 CleanupStack::PopAndDestroy( 2, cEntry ); // message, cEntry |
|
1423 |
|
1424 return result; |
|
1425 } |
|
1426 // </cmail> |
|
1427 |
|
1428 // --------------------------------------------------------------------------- |
|
1429 // --------------------------------------------------------------------------- |
|
1430 void CIpsPlgMsgMapper::AttaCheckForIncompleteMsgL( |
|
1431 const TMsvEmailEntry& aEntry, |
|
1432 CFSMailMessage& aMsg ) |
|
1433 { |
|
1434 aMsg.ResetFlag( EFSMsgFlag_Attachments ); |
|
1435 |
|
1436 TImEmailFolderType ft = aEntry.MessageFolderType(); |
|
1437 |
|
1438 if ( ft == EFolderTypeUnknown ) |
|
1439 { |
|
1440 CMsvEntry* cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
1441 CleanupStack::PushL( cEntry ); |
|
1442 |
|
1443 if ( cEntry->HasStoreL() ) |
|
1444 { |
|
1445 CMsvStore* store = cEntry->ReadStoreL(); |
|
1446 CleanupStack::PushL( store ); |
|
1447 |
|
1448 if ( store->IsPresentL( KUidMsgFileMimeHeader ) ) |
|
1449 { |
|
1450 CImMimeHeader* mimeHeader = CImMimeHeader::NewLC(); |
|
1451 mimeHeader->RestoreL( *store ); |
|
1452 |
|
1453 HBufC8* buffer8 = HBufC8::NewLC( |
|
1454 mimeHeader->ContentType().Length() + |
|
1455 mimeHeader->ContentSubType().Length() + 1 ); |
|
1456 |
|
1457 buffer8->Des().Append( mimeHeader->ContentType() ); |
|
1458 buffer8->Des().Append( KSlash ); |
|
1459 buffer8->Des().Append( mimeHeader->ContentSubType() ); |
|
1460 |
|
1461 HBufC* buffer = HBufC::NewLC( buffer8->Length() ); |
|
1462 buffer->Des().Copy( buffer8->Des() ); |
|
1463 |
|
1464 if ( buffer->CompareF( KMimeTypeMultipartMixed ) == 0 || |
|
1465 buffer->CompareF( KMimeTypeMultipartRelated ) == 0 ) |
|
1466 { |
|
1467 aMsg.SetFlag( EFSMsgFlag_Attachments ); |
|
1468 if ( !aEntry.Attachment() ) |
|
1469 { |
|
1470 SetAttachmentFlagL( aEntry, ETrue ); |
|
1471 } |
|
1472 } |
|
1473 |
|
1474 CleanupStack::PopAndDestroy( 3, mimeHeader ); |
|
1475 } |
|
1476 |
|
1477 CleanupStack::PopAndDestroy( store ); |
|
1478 } |
|
1479 CleanupStack::PopAndDestroy( cEntry ); |
|
1480 } |
|
1481 else if ( ft == EFolderTypeMixed || ft == EFolderTypeRelated ) |
|
1482 { |
|
1483 aMsg.SetFlag( EFSMsgFlag_Attachments ); |
|
1484 if ( !aEntry.Attachment() ) |
|
1485 { |
|
1486 SetAttachmentFlagL( aEntry, ETrue ); |
|
1487 } |
|
1488 } |
|
1489 |
|
1490 if ( !aMsg.IsFlagSet( EFSMsgFlag_Attachments ) && aEntry.Attachment() ) |
|
1491 { |
|
1492 SetAttachmentFlagL( aEntry, EFalse ); |
|
1493 } |
|
1494 } |
|
1495 // </cmail> |
|
1496 |
|
1497 |
|
1498 // --------------------------------------------------------------------------- |
|
1499 // --------------------------------------------------------------------------- |
|
1500 // <cmail> |
|
1501 void CIpsPlgMsgMapper::SetAttachmentFlagL( const TMsvEmailEntry& aEntry, |
|
1502 TBool aHasAttachment ) |
|
1503 { |
|
1504 FUNC_LOG; |
|
1505 CMsvEntry* cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
1506 CleanupStack::PushL( cEntry ); |
|
1507 // Only text/calendar part included as attachment |
|
1508 TMsvEmailEntry entryToBeChanged( aEntry ); |
|
1509 entryToBeChanged.SetAttachment( aHasAttachment ); |
|
1510 CIpsPlgOperationWait* waiter = CIpsPlgOperationWait::NewLC(); |
|
1511 CMsvOperation* ops = cEntry->ChangeL( entryToBeChanged, waiter->iStatus ); |
|
1512 CleanupStack::PushL( ops ); |
|
1513 waiter->Start(); |
|
1514 CleanupStack::PopAndDestroy( 3, cEntry ); |
|
1515 } |
|
1516 // </cmail> |
|
1517 |
|
1518 // <cmail> |
|
1519 // --------------------------------------------------------------------------- |
|
1520 // --------------------------------------------------------------------------- |
|
1521 void CIpsPlgMsgMapper::GetCharsetParameterL( |
|
1522 const TMsvEmailEntry& aEntry, TDes& aContentType ) |
|
1523 { |
|
1524 FUNC_LOG; |
|
1525 |
|
1526 CMsvEntry* cEntry = iSession.GetEntryL( aEntry.Id() ); |
|
1527 CleanupStack::PushL( cEntry ); |
|
1528 if ( cEntry->HasStoreL() ) |
|
1529 { |
|
1530 CMsvStore* store = cEntry->ReadStoreL(); |
|
1531 CleanupStack::PushL( store ); |
|
1532 if ( store->IsPresentL( KUidMsgFileMimeHeader ) ) |
|
1533 { |
|
1534 CImMimeHeader* mimeHeader = CImMimeHeader::NewLC(); |
|
1535 mimeHeader->RestoreL( *store ); |
|
1536 |
|
1537 TInt count = mimeHeader->ContentTypeParams().MdcaCount(); |
|
1538 INFO_1("# of CT params: %d", count); |
|
1539 for ( TInt i = 0; i < count; i++ ) |
|
1540 { |
|
1541 TPtrC8 key8 = mimeHeader->ContentTypeParams().MdcaPoint( i ); |
|
1542 INFO_1("%S", &key8); |
|
1543 TPtr16 keyUppercase16 = HBufC::NewLC( key8.Length() )->Des(); |
|
1544 keyUppercase16.Copy( key8 ); |
|
1545 keyUppercase16.UpperCase(); |
|
1546 if ( keyUppercase16.Compare( KCharsetTag ) == 0 && |
|
1547 count >= i+1 ) // prevent possible indexing over array limits |
|
1548 { |
|
1549 // Starting to append text to the current content-type header.. |
|
1550 // First, add ';' |
|
1551 aContentType.Append( KCharSemicolon ); |
|
1552 |
|
1553 // Then, 'CHARSET' |
|
1554 aContentType.Append( keyUppercase16 ); |
|
1555 |
|
1556 // '=' |
|
1557 aContentType.Append( KCharEquals ); |
|
1558 |
|
1559 // Finally, the actual charset value (e.g. 'utf-8' or similar) |
|
1560 TPtrC8 value8 = mimeHeader->ContentTypeParams().MdcaPoint( i+1 ); |
|
1561 TPtr16 value16 = HBufC::NewLC( value8.Length() )->Des(); |
|
1562 value16.Copy( value8 ); |
|
1563 aContentType.Append( value16 ); |
|
1564 CleanupStack::PopAndDestroy(); // value16 |
|
1565 } |
|
1566 CleanupStack::PopAndDestroy(); // keyUppercase16 |
|
1567 } // for loop |
|
1568 CleanupStack::PopAndDestroy( mimeHeader ); |
|
1569 } |
|
1570 CleanupStack::PopAndDestroy( store ); |
|
1571 } |
|
1572 CleanupStack::PopAndDestroy( cEntry ); |
|
1573 } |
|
1574 // </cmail> |