email/pop3andsmtpmtm/smtpservermtm/src/IMSM.CPP
changeset 0 72b543305e3a
child 40 224522e33db9
child 42 1367103c24e2
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Internet SMTP Transport Driver
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <msvstd.h>		// TMsvEntry, CMsvEntrySelection
       
    19 #include <msventry.h>	// CMsvServerEntry
       
    20 #include <msvstore.h>	// needed for CMsvStore::~CMsvStore
       
    21 #include <imcvsend.h>	// CImSendConvert
       
    22 
       
    23 #include "IMSM.H"		
       
    24 #include "IMSMSEND.H"	
       
    25 #include "SMTSUTIL.H"	// forward declarations for utility fns
       
    26 #include "csmtpsessionmanager.h"
       
    27 #include "csmtpsettings.h"
       
    28 #include "cimmobilitymanager.h"
       
    29 
       
    30 #if (defined SYMBIAN_USER_PROMPT_SERVICE)
       
    31 #include "csmtpupsresponsewaiter.h"
       
    32 #endif
       
    33 
       
    34 
       
    35 const TInt KBccArraySegment  = 100; 
       
    36 const TUid KUidSmtpServerMtm = {0x10003C79};
       
    37 
       
    38 /**
       
    39 Constructor
       
    40 
       
    41 @param aEntrySelection Selection of messages to send
       
    42 @param aServerEntry SMTP server entry
       
    43 */
       
    44 CMsgImOutboxSend::CMsgImOutboxSend(const CMsvEntrySelection& aEntrySelection,CMsvServerEntry& aServerEntry)
       
    45         : CActive(KMsgImOutboxSendPriority), iEntrySelection(aEntrySelection),iServerEntry(aServerEntry)
       
    46 	{
       
    47 	}
       
    48 
       
    49 /**
       
    50 Factory constructor
       
    51 
       
    52 @param aEntrySelection Selection of messages to send
       
    53 @param aServerEntry SMTP server entry
       
    54 @param aService SMTP service ID
       
    55 
       
    56 @return Constructed class
       
    57 */
       
    58 CMsgImOutboxSend* CMsgImOutboxSend::NewLC(const CMsvEntrySelection& aEntrySelection,CMsvServerEntry& aServerEntry, TMsvId aService)
       
    59 	{
       
    60 	CMsgImOutboxSend* self = new (ELeave) CMsgImOutboxSend(aEntrySelection,aServerEntry);
       
    61 	CleanupStack::PushL(self);
       
    62 	self->ConstructL(aService);
       
    63 	return self;
       
    64 	}
       
    65 
       
    66 /**
       
    67 Factory constructor
       
    68 
       
    69 @param aEntrySelection Selection of messages to send
       
    70 @param aServerEntry SMTP server entry
       
    71 @param aService SMTP service ID
       
    72 
       
    73 @return Constructed class
       
    74 */
       
    75 CMsgImOutboxSend* CMsgImOutboxSend::NewL(const CMsvEntrySelection& aEntrySelection,CMsvServerEntry& aServerEntry, TMsvId aService)
       
    76 	{
       
    77 	CMsgImOutboxSend* self=CMsgImOutboxSend::NewLC(aEntrySelection,aServerEntry,aService);
       
    78 	CleanupStack::Pop();
       
    79 	return self;
       
    80 	}
       
    81 
       
    82 void CMsgImOutboxSend::ConstructL(TMsvId aService)
       
    83 	{
       
    84 	iTotalMessages = iEntrySelection.Count();
       
    85     iCurrentMessageNo = -1;
       
    86 	iProgress.SetServiceId(aService);
       
    87 
       
    88 	//Load service info iServerEntry context..
       
    89 	User::LeaveIfError(iServerEntry.SetEntry(aService));	
       
    90 	__ASSERT_DEBUG(iServerEntry.Entry().iType==KUidMsvServiceEntry,gPanic(EImsmNoServiceInfo));	//	Assert is ServiceEntry..	
       
    91 
       
    92 	iSettings = CSmtpSettings::NewL(iServerEntry);
       
    93 
       
    94 	iBccRcptArray = new (ELeave) CDesCArrayFlat(KBccArraySegment);
       
    95 
       
    96 	//	Assert descriptors != empty
       
    97 	__ASSERT_DEBUG (iSettings->ServerAddress().Length() >0 , gPanic(EImsmEmptyPostOffice));
       
    98 	__ASSERT_DEBUG (iSettings->EmailAddress().Length()   >0 , gPanic(EImsmEmptyEmailAddress));
       
    99 
       
   100 #if (defined SYMBIAN_USER_PROMPT_SERVICE)	
       
   101 	iWaiter = CSmtpUpsResponseWaiter::NewL();
       
   102 #endif
       
   103 
       
   104 	if (iSettings->BearerMobility())
       
   105 		{
       
   106 		iMobilityManager = CImMobilityManager::NewL(KUidSmtpServerMtm, aService, *this);
       
   107 		}
       
   108 
       
   109 	CActiveScheduler::Add(this);
       
   110 	}
       
   111 
       
   112 #if (defined SYMBIAN_USER_PROMPT_SERVICE)	
       
   113 void CMsgImOutboxSend::StartL(TRequestStatus& aStatus, TThreadId aClientThreadId, TBool aHasCapability) 
       
   114 	{
       
   115 	SetupStartL();
       
   116 
       
   117 	iState = EStateUserPrompting;
       
   118 	iWaiter->AuthoriseAndConnectL(iSettings->SmtpSettings(), aHasCapability, aClientThreadId, iStatus);
       
   119 	SetActive();
       
   120 
       
   121 	aStatus = KRequestPending;
       
   122 	iReport = &aStatus;
       
   123 	}
       
   124 #endif
       
   125 
       
   126 void CMsgImOutboxSend::StartL(TRequestStatus& aStatus) 
       
   127 	{
       
   128 	SetupStartL();
       
   129 	StartConnectingL();
       
   130 
       
   131 	aStatus = KRequestPending;
       
   132 	iReport = &aStatus;
       
   133 	}
       
   134 
       
   135 void CMsgImOutboxSend::SetupStartL()
       
   136 	{
       
   137 	iSetDisconnected=EFalse;
       
   138 
       
   139 	//	Get count messages.. leave if none.
       
   140 	if (iTotalMessages == 0)
       
   141 		{
       
   142 		//	No messages leave..
       
   143 		User::Leave(KErrEof);			
       
   144 		}
       
   145 	
       
   146 	//  Set the connected flag messages..
       
   147 	User::LeaveIfError(iServerEntry.SetEntry(KMsvGlobalOutBoxIndexEntryIdValue));
       
   148 	User::LeaveIfError(iServerEntry.ChangeAttributes( iEntrySelection, KMsvConnectedAttribute, 0));
       
   149 	iServerEntry.SetEntry(KMsvNullIndexEntryId);
       
   150 
       
   151 	//	Initialise the progress object..Create and start a new sesion..
       
   152 	iProgress.InitialiseTotal(iTotalMessages);	//	Sets status=EMsgOutboxProgressWaiting etc.
       
   153 	iProgress.SetStatus(EMsgOutboxProgressConnecting);
       
   154 	iProgress.SetMsgNo(-1);
       
   155 	iCurrentMessageNo = -1;
       
   156 	}
       
   157 
       
   158 void CMsgImOutboxSend::StartConnectingL()
       
   159 	{
       
   160 	iState = EStateConnectingSession;
       
   161 	iMobilityOperation = EMobilityOperationIdle;
       
   162 	iSession = NULL;
       
   163 	if (!iSessionManager)
       
   164 		{
       
   165 		iSessionManager = CSmtpSessionManager::NewL(iMobilityManager, iProgress.ServiceId());
       
   166 		}
       
   167 	iSessionManager->GetSessionL(iServerEntry, *iSettings, iSession, iStatus);
       
   168 	SetActive();
       
   169 	}
       
   170 
       
   171 /**
       
   172 A bearer switch has been requested and we should try to switch over to it.
       
   173 The action parameter indicates what should happen to the current operation.
       
   174 
       
   175 @param aAction What should happen to the current operation.
       
   176 @param aIsSeamless Is this a seamless switchover.
       
   177 */
       
   178 void CMsgImOutboxSend::PrepareForNewCarrier(TImMobilityAction aAction, TBool /*aIsSeamless*/)
       
   179 	{
       
   180 	switch (aAction)
       
   181 		{
       
   182 		case KAcceptImmediately:
       
   183 			{
       
   184 			// Just kill the current operation, and then signal that we are
       
   185 			// ready to migrate
       
   186 			CarrierLost();
       
   187 			SignalMigrate();
       
   188 			break;
       
   189 			}
       
   190 
       
   191 		case KAcceptStopCurrent:
       
   192 			{
       
   193 			PrepareForNewCarrierAfterOperation(EMobilityOperationStoppingCurrent);
       
   194 			break;
       
   195 			}
       
   196 
       
   197 		case KAcceptCompleteCurrent:
       
   198 			{
       
   199 			PrepareForNewCarrierAfterOperation(EMobilityOperationCompletingCurrent);
       
   200 			break;
       
   201 			}
       
   202 
       
   203 		default:
       
   204 			{
       
   205 			__ASSERT_DEBUG(EFalse, gPanic(EImsmUnexpectedMobilityAction));
       
   206 			break;
       
   207 			}
       
   208 		}
       
   209 	}
       
   210 
       
   211 /**
       
   212 A bearer switch has been requested and the current bearer should be dropped
       
   213 immediately.
       
   214 */
       
   215 void CMsgImOutboxSend::CarrierLost()
       
   216 	{
       
   217 	switch (iState)
       
   218 		{
       
   219 		case EStateIdle:
       
   220 		case EStateWaitingNewCarrier:
       
   221 		case EStateMobilityError:
       
   222 			{
       
   223 			// do nothing
       
   224 			break;
       
   225 			}
       
   226 
       
   227 		case EStateConnectingSession:
       
   228 			{
       
   229 			CancelForMigrate();
       
   230 			StartWaitingNewCarrier();
       
   231 			break;
       
   232 			}
       
   233 
       
   234 		case EStateSendingFiles:
       
   235 			{
       
   236 			CancelForMigrate();
       
   237 			delete iSession;
       
   238 			iSession = NULL;
       
   239 			StartWaitingNewCarrier();
       
   240 			break;
       
   241 			}
       
   242 
       
   243 		case EStateClosingSession:
       
   244 			{
       
   245 			CancelForMigrate();
       
   246 
       
   247 			// If we have stopped the current operation and there are still some
       
   248 			// messages left to send then we need to wait for the migration to
       
   249 			// occur.
       
   250 			// If we have completed the operation, or we have sent all the messages
       
   251 			// then we need to exit now. We do this by pretending that no bearer
       
   252 			// migration is currently taking place, and self completing. Execution
       
   253 			// will then pass to the RunL which will just assume that the session
       
   254 			// has closed at the end of the operation and we will then exit.
       
   255 			if (PreparingForMigration() && iCurrentMessageNo < iTotalMessages)
       
   256 				{
       
   257 				StartWaitingNewCarrier();
       
   258 				}
       
   259 			else
       
   260 				{
       
   261 				iMobilityOperation = EMobilityOperationIdle;
       
   262 				TRequestStatus* status = &iStatus;
       
   263 				User::RequestComplete(status, KErrNone);
       
   264 				SetActive();
       
   265 				}
       
   266 
       
   267 			break;
       
   268 			}
       
   269 
       
   270 		case EStateUserPrompting:
       
   271 		default:
       
   272 			{
       
   273 			__ASSERT_DEBUG(EFalse, gPanic(EImsmUnexpectedState2));
       
   274 			break;
       
   275 			}
       
   276 		}
       
   277 	}
       
   278 
       
   279 /**
       
   280 The new bearer is now active. Try to start using it.
       
   281 
       
   282 @param aNewAp New access point
       
   283 @param aIsSeamless Is this a seamless switchover
       
   284 */
       
   285 void CMsgImOutboxSend::NewCarrierActive(TAccessPointInfo /*aNewAp*/, TBool /*aIsSeamless*/)
       
   286 	{
       
   287 	if (iState == EStateWaitingNewCarrier)
       
   288 		{
       
   289 		// Self complete to get the active object running again
       
   290 		TRequestStatus* status = &iStatus;
       
   291 		User::RequestComplete(status, KErrNone);
       
   292 		}
       
   293 	else
       
   294 		{
       
   295 		if (iMobilityManager)
       
   296 			{
       
   297 			iMobilityManager->NewCarrierAccepted();
       
   298 			}
       
   299 		}
       
   300 	}
       
   301 
       
   302 /**
       
   303 An error has occured during a bearer mobility switch
       
   304 
       
   305 @param aError Error code
       
   306 */
       
   307 void CMsgImOutboxSend::MobilityError(TUint /*aError*/)
       
   308 	{
       
   309 	CancelForMigrate();
       
   310 
       
   311 	TInt err = KErrNone;
       
   312 
       
   313 	// If the mobility error has occurred when we are closing the connection
       
   314 	// after sending all the messages then we can just self complete to make
       
   315 	// it look like the session close completed successfully.
       
   316 	// If the mobility error occurs in other states, or while closing the
       
   317 	// session for a migration, then we should self complete with an error
       
   318 	// so that the RunL routine cleans up and exits.
       
   319 	if ((iState != EStateClosingSession) ||
       
   320 	    (PreparingForMigration() && iCurrentMessageNo < iTotalMessages))
       
   321 		{
       
   322 		err = KErrDisconnected;	
       
   323 		}
       
   324 
       
   325 	iMobilityOperation = EMobilityOperationIdle;
       
   326 	iState = EStateMobilityError;
       
   327 
       
   328 	// Self complete with error code
       
   329 	TRequestStatus* status = &iStatus;
       
   330 	User::RequestComplete(status, err);
       
   331 	SetActive();
       
   332 	}
       
   333 
       
   334 /**
       
   335 Get progress information for mobility plugin
       
   336 
       
   337 @return Packaged progress information
       
   338 */
       
   339 const TDesC8& CMsgImOutboxSend::MobilityProgress()
       
   340 	{
       
   341 	iMobilityProgressBuffer = Progress();
       
   342 	return iMobilityProgressBuffer;
       
   343 	}
       
   344 
       
   345 /**
       
   346 A bearer switch has been requested and we should either stop the current
       
   347 operation or complete it before indicating that the migration can proceed.
       
   348 
       
   349 @param aMobilityOperation Type of mobility operation that has been requested
       
   350 */
       
   351 void CMsgImOutboxSend::PrepareForNewCarrierAfterOperation(TMobilityOperation aMobilityOperation)
       
   352 	{
       
   353 	switch (iState)
       
   354 		{
       
   355 		case EStateIdle:
       
   356 		case EStateWaitingNewCarrier:
       
   357 		case EStateMobilityError:
       
   358 			{
       
   359 			SignalMigrate();
       
   360 			break;
       
   361 			}
       
   362 
       
   363 		case EStateConnectingSession:
       
   364 			{
       
   365 			CancelForMigrate();
       
   366 			SignalMigrate();
       
   367 			StartWaitingNewCarrier();
       
   368 			break;
       
   369 			}
       
   370 
       
   371 		case EStateSendingFiles:
       
   372 		case EStateClosingSession:
       
   373 			{
       
   374 			// Just need to store what mobility operation has been requested.
       
   375 			// Note that if we are sending files, the file sending operation will
       
   376 			// see this and halt at the requested time.
       
   377 			iMobilityOperation = aMobilityOperation;
       
   378 			break;
       
   379 			}
       
   380 
       
   381 		case EStateUserPrompting:
       
   382 		default:
       
   383 			{
       
   384 			__ASSERT_DEBUG(EFalse, gPanic(EImsmUnexpectedState1));
       
   385 			break;
       
   386 			}
       
   387 		}
       
   388 	}
       
   389 
       
   390 void CMsgImOutboxSend::RunL()
       
   391 	{
       
   392 	TInt status = iStatus.Int();
       
   393 
       
   394 	if (status == KErrNone)
       
   395 		{
       
   396 		switch (iState)
       
   397 			{
       
   398 			case EStateUserPrompting:
       
   399 				{
       
   400 				StartConnectingL();
       
   401 				break;
       
   402 				}
       
   403 
       
   404 			case EStateConnectingSession:
       
   405 				{
       
   406 				SessionConnectedL();
       
   407 				break;
       
   408 				}
       
   409 
       
   410 			case EStateSendingFiles:
       
   411 				{
       
   412 				SentFiles();
       
   413 				break;
       
   414 				}
       
   415 
       
   416 			case EStateClosingSession:
       
   417 				{
       
   418 				SessionClosed();
       
   419 				break;
       
   420 				}
       
   421 
       
   422 			case EStateWaitingNewCarrier:
       
   423 				{
       
   424 				MigratedL();
       
   425 				break;
       
   426 				}
       
   427 
       
   428 			case EStateMobilityError:
       
   429 				{
       
   430 				// A mobility error occurred while we were closing the session after
       
   431 				// sending all the messages.
       
   432 				// do nothing
       
   433 				break;
       
   434 				}
       
   435 
       
   436 			default:
       
   437 				{
       
   438 				__ASSERT_DEBUG(EFalse, gPanic(EImsmUnexpectedState3));
       
   439 				break;
       
   440 				}
       
   441 			}
       
   442 		}
       
   443 	else
       
   444 		{
       
   445 		switch (iState)
       
   446 			{
       
   447 			case EStateUserPrompting:
       
   448 				{
       
   449 				// do nothing
       
   450 				break;
       
   451 				}
       
   452 
       
   453 			case EStateConnectingSession:
       
   454 				{
       
   455 				SessionConnectionFailed();
       
   456 				break;
       
   457 				}
       
   458 
       
   459 			case EStateSendingFiles:
       
   460 				{
       
   461 				// closing Session with server 	
       
   462 				SentFiles();
       
   463 				break;
       
   464 				}
       
   465 
       
   466 			case EStateClosingSession:
       
   467 				{
       
   468 				// Failure to close a session can be ignored as it will have been
       
   469 				// tidied up.
       
   470 				// Continue by assuming the close was successful.
       
   471 				SessionClosed();
       
   472 				break;
       
   473 				}
       
   474 
       
   475 			case EStateMobilityError:
       
   476 				{
       
   477 				// do nothing
       
   478 				break;
       
   479 				}
       
   480 
       
   481 			case EStateWaitingNewCarrier:
       
   482 			default:
       
   483 				{
       
   484 				__ASSERT_DEBUG(EFalse, gPanic(EImsmUnexpectedState4));
       
   485 				}
       
   486 			}
       
   487 		}
       
   488 
       
   489 	// If we are not active then this means we should complete
       
   490 	if (!IsActive())
       
   491 		{
       
   492 		if (iSession)
       
   493 			{
       
   494 			iProgress.iSendFileProgress = iSession->FileProgress();
       
   495 			}
       
   496 		else
       
   497 			{
       
   498 			iProgress.iSendFileProgress.iSessionState = EClosingSmtp;
       
   499 			iProgress.iSendFileProgress.iBytesSent = 0;
       
   500 			iProgress.iSendFileProgress.iBytesToSend = 0;
       
   501 			}
       
   502 
       
   503 		Complete(status);
       
   504 		}
       
   505 	}
       
   506 
       
   507 /**
       
   508 Handles leaves during RunL
       
   509 
       
   510 @param aError Error code
       
   511 */
       
   512 TInt CMsgImOutboxSend::RunError(TInt aError)
       
   513 	{
       
   514 	switch (iState)
       
   515 		{
       
   516 		case EStateConnectingSession:
       
   517 			{
       
   518 			if (iMobilityOperation != EMobilityOperationMigrating)
       
   519 				{
       
   520 				iProgress.iSendFileProgress.iSessionState = EConnectingToSmtp;
       
   521 				iProgress.iSendFileProgress.iBytesSent = 0;
       
   522 				iProgress.iSendFileProgress.iBytesToSend = 0;
       
   523 				iProgress.SetMsgNo(KErrNotFound);
       
   524 				iProgress.SetConnectionIAP(KErrNotFound);
       
   525 				}
       
   526 			break;
       
   527 			}
       
   528 
       
   529 		case EStateSendingFiles:
       
   530 			{
       
   531 			if (iSession)
       
   532 				{
       
   533 				iProgress.iSendFileProgress = iSession->FileProgress();
       
   534 				}
       
   535 			iProgress.iSendFileProgress.iSessionState = ESendingImail;
       
   536 			break;
       
   537 			}
       
   538 
       
   539 		case EStateUserPrompting:
       
   540 		case EStateClosingSession:
       
   541 		case EStateWaitingNewCarrier:
       
   542 		case EStateMobilityError:
       
   543 		default:
       
   544 			{
       
   545 			__ASSERT_DEBUG(EFalse, gPanic(EImsmUnexpectedState6));
       
   546 			break;
       
   547 			}
       
   548 		}
       
   549 
       
   550 	Complete(aError);
       
   551 
       
   552 	return KErrNone;
       
   553 	}
       
   554 
       
   555 /**
       
   556 A new session has been connected
       
   557 */
       
   558 void CMsgImOutboxSend::SessionConnectedL()
       
   559 	{
       
   560 	if (iMobilityOperation == EMobilityOperationMigrating)
       
   561 		{
       
   562 		if (iMobilityManager)
       
   563 			{
       
   564 			iMobilityManager->NewCarrierAccepted();
       
   565 			}
       
   566 
       
   567 		if (iDecrementMessageCountAfterMigration)
       
   568 			{
       
   569 			--iCurrentMessageNo;
       
   570 			iDecrementMessageCountAfterMigration = EFalse;
       
   571 			}
       
   572 		}
       
   573 
       
   574 	iMobilityOperation = EMobilityOperationIdle;
       
   575 
       
   576 	iState = EStateSendingFiles;
       
   577 	iSession->SendFilesL(*this, iStatus);
       
   578 	SetActive();
       
   579 	}
       
   580 
       
   581 /**
       
   582 We have completed sending the files
       
   583 */
       
   584 void CMsgImOutboxSend::SentFiles()
       
   585 	{
       
   586 	iProgress.iSendFileProgress = iSession->FileProgress();
       
   587 
       
   588 	iState = EStateClosingSession;
       
   589 	iSessionManager->DeleteSession(*iSession, iStatus);
       
   590 	iSession = NULL;
       
   591 	SetActive();
       
   592 	}
       
   593 
       
   594 /**
       
   595 The session has been closed
       
   596 */
       
   597 void CMsgImOutboxSend::SessionClosed()
       
   598 	{
       
   599 	// If the session has been closed for a bearer migration, and there are still more
       
   600 	// messages to send, then start waiting for the migration.
       
   601 	if (iMobilityManager)
       
   602 		{
       
   603 		if (PreparingForMigration() && iCurrentMessageNo < iTotalMessages)
       
   604 			{
       
   605 			SignalMigrate();
       
   606 			StartWaitingNewCarrier();
       
   607 			}
       
   608 		}
       
   609 	}
       
   610 
       
   611 /**
       
   612 The mobility framework has told us that the new bearer is now active. We need
       
   613 to conect to it.
       
   614 */
       
   615 void CMsgImOutboxSend::MigratedL()
       
   616 	{
       
   617 	iState = EStateConnectingSession;
       
   618 	iSession = NULL;
       
   619 	iSessionManager->GetSessionL(iServerEntry, *iSettings, iSession, iStatus);
       
   620 	SetActive();
       
   621 	}
       
   622 
       
   623 /**
       
   624 Failed to connect a new session
       
   625 */
       
   626 void CMsgImOutboxSend::SessionConnectionFailed()
       
   627 	{
       
   628 	if (iMobilityOperation != EMobilityOperationMigrating)
       
   629 		{
       
   630 		iSessionManager->ConnectionProgress(iProgress);				
       
   631 		}
       
   632 
       
   633 	// If we support bearer mobility, then we should tell the mobility manager
       
   634 	// to reject the carrier and then wait for a new one.
       
   635 	// If however we are doing the initial (non migration) session connection,
       
   636 	// and the failure is because the network connection did not start then we
       
   637 	// won't have registed with the mobility manager so we should just exit.
       
   638 	if (iMobilityManager &&
       
   639 	   (iMobilityOperation == EMobilityOperationMigrating ||
       
   640 	    iSessionManager->IsConnectionStarted()))
       
   641 		{
       
   642 		iMobilityManager->NewCarrierRejected();
       
   643 		StartWaitingNewCarrier();
       
   644 		}
       
   645 	}
       
   646 
       
   647 /**
       
   648 Tell the mobility manager that we are ready for the migration to proceed
       
   649 */
       
   650 void CMsgImOutboxSend::SignalMigrate()
       
   651 	{
       
   652 	if (iMobilityManager)
       
   653 		{
       
   654 		iMobilityManager->MigrateToNewCarrier();
       
   655 		}
       
   656 	}
       
   657 
       
   658 /**
       
   659 Start waiting for the bearer migration to complete
       
   660 */
       
   661 void CMsgImOutboxSend::StartWaitingNewCarrier()
       
   662 	{
       
   663 	iState = EStateWaitingNewCarrier;
       
   664 	iMobilityOperation = EMobilityOperationMigrating;
       
   665 	iStatus = KRequestPending;
       
   666 	SetActive();
       
   667 	}
       
   668 
       
   669 /**
       
   670 Cancel the current operations prior to a migration taking place. This
       
   671 performs the same as a normal cancel, except that it does not complete
       
   672 the caller.
       
   673 */
       
   674 void CMsgImOutboxSend::CancelForMigrate()
       
   675 	{
       
   676 	iCancellingForMigrate = ETrue;
       
   677 	Cancel();
       
   678 	iCancellingForMigrate = EFalse;
       
   679 	}
       
   680 
       
   681 void CMsgImOutboxSend::DoCancel()
       
   682 	{
       
   683 	switch (iState)
       
   684 		{
       
   685 		case EStateUserPrompting:
       
   686 			{
       
   687 #if (defined SYMBIAN_USER_PROMPT_SERVICE)
       
   688 			iWaiter->Cancel();
       
   689 #endif
       
   690 			break;
       
   691 			}
       
   692 
       
   693 		case EStateConnectingSession:
       
   694 			{
       
   695 			if (iMobilityOperation != EMobilityOperationMigrating)
       
   696 				{
       
   697 				iSessionManager->ConnectionProgress(iProgress);
       
   698 				}
       
   699 			iSessionManager->Cancel();
       
   700 			break;
       
   701 			}
       
   702 
       
   703 		case EStateSendingFiles:
       
   704 			{
       
   705 			__ASSERT_DEBUG(iSession, gPanic(EImsmSessionNotDefined));
       
   706 			if (iSession)
       
   707 				{
       
   708 				// We should not update the file progress information if we are
       
   709 				// cancelling for a bearer migration. For a bearer migration we
       
   710 				// collected the progress information at the end of the last
       
   711 				// successfully completed file and we don't want to overwrite it
       
   712 				// with the information about the file whose send we have cancelled.
       
   713 				if (!iCancellingForMigrate)
       
   714 					{
       
   715 					iProgress.iSendFileProgress = iSession->FileProgress();
       
   716 					}
       
   717 
       
   718 				iSession->Cancel();
       
   719 				delete iSession;
       
   720 				iSession = NULL;
       
   721 
       
   722 				// If we are cancelling for bearer migration, make sure that the
       
   723 				// message being cancelled is restored to its original state.
       
   724 				// We should also decrease our message count so that it indicates
       
   725 				// the last sent message so that we restart from the correct place
       
   726 				// after the migration.
       
   727 				if (iCancellingForMigrate)
       
   728 					{
       
   729 					TRAP_IGNORE(RestoreBccRecipientsToHeaderL());
       
   730 					--iCurrentMessageNo;
       
   731 					}
       
   732 				}
       
   733 			else
       
   734 				{
       
   735 				TRequestStatus* status = &iStatus;
       
   736 				User::RequestComplete(status, KErrCancel);
       
   737 				}
       
   738 			break;
       
   739 			}
       
   740 
       
   741 		case EStateClosingSession:
       
   742 			{
       
   743 			// If the session is being closed because all the emails have been sent, set
       
   744 			// the final progress information. If the session is closing for a bearer
       
   745 			// migration we don't want to overwrite the existing progress values.
       
   746 			if (!PreparingForMigration())
       
   747 				{
       
   748 				iProgress.iSendFileProgress.iSessionState = EClosingSmtp;
       
   749 				iProgress.iSendFileProgress.iBytesSent = 0;
       
   750 				iProgress.iSendFileProgress.iBytesToSend = 0;
       
   751 				}
       
   752 
       
   753 			iSessionManager->Cancel();
       
   754 			break;
       
   755 			}
       
   756 
       
   757 		case EStateWaitingNewCarrier:
       
   758 			{
       
   759 			// There is no outstanding async request so we need to self complete
       
   760 			// to keep the active object going.
       
   761 			TRequestStatus* status = &iStatus;
       
   762 			User::RequestComplete(status, KErrCancel);
       
   763 			break;
       
   764 			}
       
   765 
       
   766 		case EStateMobilityError:
       
   767 		case EStateIdle:
       
   768 		default:
       
   769 			{
       
   770 			__ASSERT_DEBUG(EFalse, gPanic(EImsmUnexpectedState5));
       
   771 			TRequestStatus* status = &iStatus;
       
   772 			User::RequestComplete(status, KErrCancel);
       
   773 			break;
       
   774 			}
       
   775 		}
       
   776 
       
   777 	if (!iCancellingForMigrate)
       
   778 		{
       
   779 		//  Make sure that all message not dealt with
       
   780 		//  already are set connected EFalse...
       
   781 		TRAP_IGNORE(DisconnectUnsentMessagesL());
       
   782 		iSetDisconnected=ETrue;
       
   783 
       
   784 		Complete(KErrCancel);
       
   785 		}
       
   786 	}
       
   787 
       
   788 /**
       
   789 The sending of all the emails has completed.
       
   790 Tidy up and complete the caller.
       
   791 */
       
   792 void CMsgImOutboxSend::Complete(TInt status)
       
   793 	{
       
   794 	if (iState != EStateMobilityError)
       
   795 		{
       
   796 		// Respond to any outstanding bearer mobility requests as we are about
       
   797 		// to exit and we don't need to hold up the migration.
       
   798 		if (PreparingForMigration())
       
   799 			{
       
   800 			SignalMigrate();
       
   801 			}
       
   802 		else if (iMobilityOperation == EMobilityOperationMigrating &&
       
   803 		         iState == EStateConnectingSession)
       
   804 			{
       
   805 			if (iMobilityManager)
       
   806 				{
       
   807 				iMobilityManager->NewCarrierAccepted();
       
   808 				}
       
   809 			}
       
   810 		}
       
   811 
       
   812 	delete iSession;
       
   813 	iSession = NULL;
       
   814 	delete iSessionManager;
       
   815 	iSessionManager = NULL;
       
   816 
       
   817 	iState = EStateIdle;
       
   818 	iMobilityOperation = EMobilityOperationIdle;
       
   819 	iDecrementMessageCountAfterMigration = EFalse;
       
   820 
       
   821 	iProgress.SetStatus(EMsgOutboxProgressDone);
       
   822 	iProgress.SetError(status);
       
   823 
       
   824 	User::RequestComplete(iReport, status);
       
   825 	}
       
   826 
       
   827 //
       
   828 //	Progress()
       
   829 //
       
   830 //	Args: None
       
   831 //
       
   832 //	Return Value:	Reference to a TImSmtpProgress object maintained
       
   833 //					in CImOutboxSend...
       
   834 //
       
   835 //	Remarks:		Returns the current iProgress object...
       
   836 //
       
   837 const TImSmtpProgress& CMsgImOutboxSend::Progress()
       
   838 	{
       
   839 	switch (iState)
       
   840 		{
       
   841 		case EStateUserPrompting:
       
   842 			{
       
   843 			iProgress.iSendFileProgress.iSessionState = EConnectingToSmtp;
       
   844 			iProgress.iSendFileProgress.iBytesSent = 0;
       
   845 			iProgress.iSendFileProgress.iBytesToSend = 0;
       
   846 			iProgress.SetMsgNo(KErrNotFound);
       
   847 			iProgress.SetConnectionIAP(KErrNotFound);
       
   848 			break;
       
   849 			}
       
   850 
       
   851 		case EStateConnectingSession:
       
   852 			{
       
   853 			if (iMobilityOperation != EMobilityOperationMigrating)
       
   854 				{
       
   855 				if (iSessionManager)
       
   856 					{
       
   857 					iSessionManager->ConnectionProgress(iProgress);
       
   858 					}
       
   859 				}
       
   860 			break;
       
   861 			}
       
   862 
       
   863 		case EStateSendingFiles:
       
   864 			{
       
   865 			if (iSession)
       
   866 				{
       
   867 				iProgress.iSendFileProgress = iSession->FileProgress();
       
   868 				}
       
   869 			break;
       
   870 			}
       
   871 
       
   872 		case EStateClosingSession:
       
   873 			{
       
   874 			if (iMobilityOperation != EMobilityOperationMigrating)
       
   875 				{
       
   876 				iProgress.SetStatus(EMsgOutboxProgressDone);
       
   877 				iProgress.iSendFileProgress.iSessionState = EClosingSmtp;
       
   878 				}
       
   879 			break;
       
   880 			}
       
   881 
       
   882 		case EStateWaitingNewCarrier:
       
   883 			{
       
   884 			// do nothing
       
   885 			break;
       
   886 			}
       
   887 
       
   888 		case EStateIdle:
       
   889 		case EStateMobilityError:
       
   890 		default:
       
   891 			{
       
   892 			iProgress.SetStatus(EMsgOutboxProgressDone);
       
   893 			iProgress.iSendFileProgress.iSessionState = EClosingSmtp;
       
   894 			break;	
       
   895 			}
       
   896 		}
       
   897 
       
   898 	if (iProgress.MsgNo() > iProgress.SendTotal())
       
   899 		{
       
   900 		iProgress.SetMsgNo(iProgress.SendTotal());
       
   901 		}
       
   902 
       
   903 	if (iProgress.MsgNo() < 0)
       
   904 		{
       
   905 		iProgress.SetMsgNo(0);
       
   906 		}
       
   907 
       
   908 	return iProgress;
       
   909 	}
       
   910 
       
   911 //
       
   912 //	NextFile()
       
   913 //
       
   914 //	Args:None.
       
   915 //
       
   916 //	Return Value TInt kErrXXX
       
   917 //
       
   918 //	Remarks:	Called from CImStmpSession::SelectNextState() 
       
   919 //				Moves iServerEntry and iProgress::MsgNo() to point
       
   920 //				to the next (or first entry to send)
       
   921 //				Locking done implicitly in SetEntry() call.
       
   922 //
       
   923 TInt CMsgImOutboxSend::NextFile()
       
   924 	{
       
   925 	if(++iCurrentMessageNo >= iTotalMessages) 	//	Stepped past the messages..return
       
   926 		{
       
   927 		return KErrNotFound;
       
   928 		}
       
   929 
       
   930 	// If we are stopping for migration, exit now
       
   931 	if (iMobilityOperation == EMobilityOperationStoppingCurrent)
       
   932 		{
       
   933 		iDecrementMessageCountAfterMigration = ETrue;
       
   934 		return KErrNotFound;
       
   935 		}
       
   936 
       
   937 	//	Set the ServerEntry context to the next message.. and check if the message is suspended.
       
   938 	//if suspended, don't send and try to send the next message
       
   939 	TInt err = iServerEntry.SetEntry(iEntrySelection.At(iCurrentMessageNo));
       
   940 	
       
   941 	if(err == KErrNotFound)
       
   942 		{
       
   943 		return KErrNotFound;
       
   944 		}
       
   945 
       
   946 	TMsvEntry entry=iServerEntry.Entry();
       
   947 	while(entry.SendingState()==KMsvSendStateSuspended && iServerEntry.Entry().iType==KUidMsvMessageEntry)
       
   948 		{
       
   949 		if (++iCurrentMessageNo >= iTotalMessages)
       
   950 			{
       
   951 			err=KErrNotFound;
       
   952 			iProgress.UpdateFailedToSend(); //this is not the correct update.  There should be UpdateNotSent() method.
       
   953 			break;
       
   954 			}
       
   955 		iProgress.UpdateFailedToSend();
       
   956 		err = iServerEntry.SetEntry(iEntrySelection.At(iCurrentMessageNo));
       
   957 		entry=iServerEntry.Entry();
       
   958 		}			
       
   959 
       
   960 	if(err == KErrNone && iServerEntry.Entry().iType != KUidMsvMessageEntry)
       
   961 		{
       
   962 		//	Next context is not a SMTP message type..
       
   963 		err = KErrBadHandle;
       
   964 		}
       
   965 	if(err == KErrNone)
       
   966 		{
       
   967 		iProgress.SetMsgNo(iCurrentMessageNo);	//	Update iProgress.. 
       
   968 		
       
   969 		//if this is the first message we are sending then reset the iProgress.iSent member.
       
   970 		if (iCurrentMessageNo==0)
       
   971 			{
       
   972 			iProgress.SetConnectionIAP(0);	
       
   973 			}
       
   974 
       
   975 		iProgress.SetStatus(EMsgOutboxProgressSending);
       
   976 		}
       
   977 	return(err);
       
   978 	} 
       
   979 
       
   980 //
       
   981 //	SetLastMessageStatusL()
       
   982 //
       
   983 //	Args:				TTime -- time stamp..	
       
   984 //						TInt  -- completion reason from the last send..
       
   985 //
       
   986 //	Return Value:		void.
       
   987 //
       
   988 //	Remarks:			Called by CImSmtpSession::SelectNextState() to set CMsvServeEntry
       
   989 //						data for last file sent.. Either updates iDate etc.. or if 1st call
       
   990 //						with messages to be sent resets iProgress.SetStatus().
       
   991 //
       
   992 
       
   993 void CMsgImOutboxSend::SetLastMessageStatusL(const TTime& aTimeNow, TInt aCompletionReason)
       
   994 	{
       
   995 	//	If its the first message && there are messages to be sent change status..
       
   996 	if (iTotalMessages>0) 
       
   997 		{ 
       
   998 		iProgress.SetStatus(EMsgOutboxProgressSending); 
       
   999 		} 
       
  1000 
       
  1001 	// Store the file progress for the last file sent. This will be used in
       
  1002 	// the situation where we cancel the operation to do a bearer migration
       
  1003 	// so that the progress information is for the last file completed as
       
  1004 	// opposed to the one we have just cancelled.
       
  1005 	if (iSession)
       
  1006 		{
       
  1007 		iProgress.iSendFileProgress = iSession->FileProgress();
       
  1008 		}
       
  1009 
       
  1010 	//	Fill in the iServerEntry details with data from the last message
       
  1011     //  IMCV may had left this inconsistent... so reset the iServerEntry
       
  1012     //  explicitly....
       
  1013 	if (iCurrentMessageNo != -1)
       
  1014 		{     
       
  1015 		TInt err;
       
  1016         err = iServerEntry.SetEntry(iEntrySelection.At(iCurrentMessageNo));
       
  1017 		__ASSERT_DEBUG( err == KErrNone, gPanic(EImsmServerError));
       
  1018 		TMsvEntry entry = iServerEntry.Entry();
       
  1019 
       
  1020 		//	Set date info and completion data..update the iServerEntry with this data..
       
  1021 		entry.iDate=aTimeNow;
       
  1022 		if(aCompletionReason!=KErrCancel)
       
  1023 			{
       
  1024 			entry.SetFailed(aCompletionReason != KErrNone);
       
  1025 			entry.SetSendingState(aCompletionReason==KErrNone? KMsvSendStateSent: KMsvSendStateWaiting);  //set it to send agian.
       
  1026 			if (aCompletionReason)
       
  1027 				entry.iError=CalculateError(aCompletionReason);
       
  1028 			}
       
  1029 		else
       
  1030 			{
       
  1031 			entry.SetFailed(EFalse);
       
  1032 			entry.SetSendingState(KMsvSendStateSuspended);
       
  1033 			entry.iError=KErrNone;
       
  1034 			}
       
  1035 
       
  1036 //		if (aCompletionReason<=KErrNone)
       
  1037 	//		{
       
  1038 			// ignore any +ve errors which may leak from the SMTP code
       
  1039 //			entry.iError=aCompletionReason;
       
  1040 //			entry.SetSendingState(aCompletionReason==KErrNone? KMsvSendStateSent: KMsvSendStateWaiting);  //set it to send agian.
       
  1041 //			}
       
  1042 		RestoreBccRecipientsToHeaderL();
       
  1043 
       
  1044         entry.SetConnected(EFalse);
       
  1045 		err = iServerEntry.ChangeEntry(entry);
       
  1046 		__ASSERT_DEBUG( err == KErrNone, gPanic(EImsmServerError));
       
  1047 		UpdateSummaryInfo(aCompletionReason);
       
  1048 
       
  1049         //  If it went move to the "Sent" folder..
       
  1050         if(!entry.Failed() && aCompletionReason!=KErrCancel)
       
  1051             {
       
  1052             TMsvId id = entry.Id();
       
  1053             err = iServerEntry.SetEntry(KMsvSentEntryIdValue);
       
  1054             if(err == KErrNone)
       
  1055                 {
       
  1056                 err = iServerEntry.SetEntry(KMsvGlobalOutBoxIndexEntryId);
       
  1057                 if(err == KErrNone)
       
  1058                     {
       
  1059                     // Move it....
       
  1060                     err = iServerEntry.MoveEntryWithinService(id, KMsvSentEntryIdValue);
       
  1061                     }
       
  1062                 }
       
  1063             }
       
  1064 		}
       
  1065 	}
       
  1066 
       
  1067 TInt CMsgImOutboxSend::CalculateError(TInt aCompletionReason)
       
  1068 	{
       
  1069 	switch (aCompletionReason)
       
  1070 		{
       
  1071 	case ESmtpMailboxNoAccess:
       
  1072 	case ESmtpMailboxName:
       
  1073 	case ESmtpTransactionFailed:
       
  1074 		return KErrAccessDenied; //KSmtpLoginRefused;
       
  1075 	default:
       
  1076 		break;
       
  1077 		}
       
  1078 	return KErrUnknown;		   
       
  1079 	}
       
  1080 
       
  1081 //
       
  1082 //	UpdateSummaryInfo()
       
  1083 //
       
  1084 //	Args:				TInt -- KErrXXX from calling function
       
  1085 //
       
  1086 //	Return value:		None
       
  1087 //
       
  1088 //	Remarks:			Called from SetLastMessage Status just increments
       
  1089 //						iProgress count for sent or not sent messages...
       
  1090 //
       
  1091 void CMsgImOutboxSend::UpdateSummaryInfo(TInt& aReason)
       
  1092 	{
       
  1093 	if (aReason==KErrNone)	// sent message successfully
       
  1094 		{
       
  1095 		iProgress.UpdateSent();
       
  1096 		}
       
  1097 	//	MRG 26/08/98 -- Switch statement in IdentifySmtpError() returns no
       
  1098 	//					error information at the moment.. 
       
  1099 	//					else if edited accordingly..
       
  1100 	else /*if (IdentifySmtpError(aReason))*/
       
  1101 		{
       
  1102 		iProgress.UpdateFailedToSend();
       
  1103 		}
       
  1104 	}
       
  1105 
       
  1106 
       
  1107 //
       
  1108 //  SessionIsConnected()
       
  1109 //
       
  1110 //  Ask for state of iSessions iSocket...
       
  1111 //
       
  1112 //
       
  1113 TBool CMsgImOutboxSend::SessionIsConnected()
       
  1114 	{
       
  1115 	if (iState == EStateConnectingSession)
       
  1116 		{
       
  1117 		return iSessionManager->IsSessionConnected();
       
  1118 		}
       
  1119 	else if(iSession)
       
  1120 		{
       
  1121 		return iSession->IsConnected();
       
  1122 		}
       
  1123 	else
       
  1124 		{
       
  1125 		return EFalse;
       
  1126 		}
       
  1127 	}
       
  1128 
       
  1129 
       
  1130 void CMsgImOutboxSend::DisconnectUnsentMessagesL()
       
  1131     {
       
  1132     //  Pos errors
       
  1133     TInt err = KErrNone;
       
  1134     //  Temp entry selection...
       
  1135     CMsvEntrySelection* unsentSelection = new (ELeave) CMsvEntrySelection();
       
  1136     CleanupStack::PushL(unsentSelection);
       
  1137     //  Append unsent messages into the temp array..
       
  1138     for(TInt i=0; i<iEntrySelection.Count(); i++)
       
  1139         {
       
  1140         err = iServerEntry.SetEntry((iEntrySelection)[i]);
       
  1141         //  If not found carry on along the array...
       
  1142         if(err != KErrNone)
       
  1143             continue;
       
  1144         if(iServerEntry.Entry().Parent() == KMsvGlobalOutBoxIndexEntryIdValue)
       
  1145             {
       
  1146             unsentSelection->AppendL((iEntrySelection)[i]);
       
  1147             }
       
  1148         }
       
  1149 
       
  1150     //  Reset the iConnected flag on the lot.
       
  1151 	 User::LeaveIfError(iServerEntry.SetEntry(KMsvGlobalOutBoxIndexEntryIdValue));
       
  1152     if(unsentSelection->Count() > 0)
       
  1153         {
       
  1154 		  User::LeaveIfError(iServerEntry.ChangeAttributes(*unsentSelection, 0, KMsvConnectedAttribute));
       
  1155         }
       
  1156 	iServerEntry.SetEntry(KMsvNullIndexEntryId);
       
  1157     CleanupStack::PopAndDestroy();  //  unsentSelection..
       
  1158     }
       
  1159 
       
  1160 void CMsgImOutboxSend::CleanUpOnDestructL()
       
  1161     {
       
  1162 	if(!iSetDisconnected)
       
  1163 		{
       
  1164 		DisconnectUnsentMessagesL();
       
  1165 		}
       
  1166 
       
  1167 	if (iStatus.Int() != KErrNone)
       
  1168 		{
       
  1169 		if ((iCurrentMessageNo != -1) && (iCurrentMessageNo<iTotalMessages))
       
  1170 			{
       
  1171 			TInt err=iServerEntry.SetEntry(iEntrySelection.At(iCurrentMessageNo));
       
  1172 			if(err == KErrNotFound)
       
  1173 				{
       
  1174 				User::Leave(KErrNotFound);
       
  1175 				}
       
  1176 			__ASSERT_DEBUG(err == KErrNone, gPanic(EImsmServerError));
       
  1177 			TMsvEntry entry = iServerEntry.Entry();
       
  1178 
       
  1179 			RestoreBccRecipientsToHeaderL();
       
  1180 
       
  1181 			//	Set date info and completion data..update the iServerEntry with this data..
       
  1182 			TInt errorCode = (TSmtpSessionError)iStatus.Int();
       
  1183 			entry.iDate.UniversalTime();
       
  1184 			if(errorCode!=KErrCancel)
       
  1185 				{
       
  1186 				entry.SetFailed(errorCode != KErrNone);
       
  1187 				entry.SetSendingState(errorCode==KErrNone? KMsvSendStateSent: KMsvSendStateWaiting);  //set it to send agian.
       
  1188 				if (errorCode)
       
  1189 					entry.iError=CalculateError(errorCode);
       
  1190 				}
       
  1191 			else
       
  1192 				{
       
  1193 				entry.SetFailed(EFalse);
       
  1194 				entry.SetSendingState(KMsvSendStateSuspended);
       
  1195 				entry.iError=KErrNone;
       
  1196 				}
       
  1197 			entry.SetConnected(EFalse);
       
  1198 		#ifdef _DEBUG
       
  1199 			err = 
       
  1200 		#endif
       
  1201 			iServerEntry.ChangeEntry(entry);
       
  1202 			__ASSERT_DEBUG(err == KErrNone, gPanic(EImsmServerError));
       
  1203 			}
       
  1204 		}
       
  1205 	}
       
  1206 
       
  1207 //
       
  1208 //	~CMsgImOutboxSend -- destructor.
       
  1209 //
       
  1210 CMsgImOutboxSend::~CMsgImOutboxSend( )
       
  1211 	{
       
  1212 	Cancel();
       
  1213 	TRAP_IGNORE(CleanUpOnDestructL());
       
  1214 
       
  1215 	delete iSession;				//should be dead
       
  1216 	delete iSettings;
       
  1217 
       
  1218 	if (iBccRcptArray)
       
  1219 		{
       
  1220 		iBccRcptArray->Reset();
       
  1221 		delete iBccRcptArray;
       
  1222 		}
       
  1223 #if (defined SYMBIAN_USER_PROMPT_SERVICE)		
       
  1224 	delete iWaiter;	
       
  1225 #endif
       
  1226 
       
  1227 	delete iSessionManager;
       
  1228 	delete iMobilityManager;
       
  1229 	}
       
  1230 
       
  1231 CDesCArray& CMsgImOutboxSend::BccRcptArray()
       
  1232 	{
       
  1233 	return *iBccRcptArray;
       
  1234 	}
       
  1235 
       
  1236 void CMsgImOutboxSend::ResetBccRcptArrayL()
       
  1237 	{
       
  1238 	if(iBccRcptArray)
       
  1239 		{
       
  1240 		iBccRcptArray->Reset();
       
  1241 		delete iBccRcptArray;
       
  1242 		iBccRcptArray=0;
       
  1243 		}
       
  1244 	iBccRcptArray = new (ELeave) CDesCArrayFlat(KBccArraySegment);
       
  1245 	}
       
  1246 
       
  1247 
       
  1248 void CMsgImOutboxSend::RestoreBccRecipientsToHeaderL()
       
  1249 	{
       
  1250 	if (!iServerEntry.HasStoreL() || !iBccRcptArray || iBccRcptArray->Count()==0)
       
  1251 		return; // no recipients to restore.
       
  1252 
       
  1253 	CMsvStore* store = iServerEntry.EditStoreL();
       
  1254 	CleanupStack::PushL(store);
       
  1255 	
       
  1256 	// Must have an rfc822 header.
       
  1257 	CImHeader* header = CImHeader::NewLC();
       
  1258 	if (store->IsPresentL( KUidMsgFileIMailHeader) )
       
  1259 		{
       
  1260 		header->RestoreL(*store);
       
  1261 		header->BccRecipients().Reset();
       
  1262 
       
  1263 		TInt ii = iBccRcptArray->Count(); 
       
  1264 		while (ii-- > 0)
       
  1265 			header->BccRecipients().InsertL(0, (*iBccRcptArray)[ii]);
       
  1266 		header->StoreL(*store);	
       
  1267 		store->CommitL();
       
  1268 		}
       
  1269 
       
  1270 	// To stop the array growing, delete and recreate.
       
  1271 	iBccRcptArray->Reset();
       
  1272 	delete iBccRcptArray;
       
  1273 	iBccRcptArray=0;
       
  1274 	iBccRcptArray = new (ELeave) CDesCArrayFlat(KBccArraySegment);
       
  1275 
       
  1276 	CleanupStack::PopAndDestroy(header);
       
  1277 	CleanupStack::PopAndDestroy(store); 
       
  1278 	}
       
  1279 
       
  1280 /**
       
  1281 Indicates if we are preparing to do a migration based on the mobility
       
  1282 operation value.
       
  1283 
       
  1284 @return ETrue if preparing to do a migration, EFalse otherwise
       
  1285 */
       
  1286 TBool CMsgImOutboxSend::PreparingForMigration()
       
  1287 	{
       
  1288 	if (iMobilityOperation == EMobilityOperationStoppingCurrent ||
       
  1289 	    iMobilityOperation == EMobilityOperationCompletingCurrent)
       
  1290 		{
       
  1291 		return ETrue;
       
  1292 		}
       
  1293 
       
  1294 	return EFalse;
       
  1295 	}
       
  1296 
       
  1297 /**
       
  1298 Gets the access point ID in use for the connection to the server
       
  1299 
       
  1300 @param aAccessPointId On return stores the access point ID value
       
  1301 
       
  1302 @return KErrNone if successful, or a system wide error code
       
  1303 */
       
  1304 TInt CMsgImOutboxSend::GetAccessPointIdForConnection(TUint32& aAccessPointId) const
       
  1305 	{
       
  1306 	if (iSessionManager)
       
  1307 		{
       
  1308 		return iSessionManager->GetAccessPointIdForConnection(aAccessPointId);
       
  1309 		}
       
  1310 
       
  1311 	return KErrNotFound;
       
  1312 	}