email/pop3andsmtpmtm/popservermtm/src/POPS.CPP
changeset 0 72b543305e3a
child 21 c6838af47512
equal deleted inserted replaced
-1:000000000000 0:72b543305e3a
       
     1 // Copyright (c) 2006-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 //
       
    15 
       
    16 #include <e32std.h>
       
    17 #include "POPS.H"
       
    18 #include "POPSOP.H"
       
    19 #include <pop3set.h>
       
    20 
       
    21 #include <iapprefs.h>
       
    22 #include <hash.h>
       
    23 #include <pop3set.h>
       
    24 #include <e32std.h>
       
    25 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
    26 #include "cpopsaslauthhelper.h"
       
    27 #endif
       
    28 #include "POPS.PAN"  // impp's own panic codes
       
    29 
       
    30 #define KPeriod 30000000	// period of timer
       
    31 
       
    32 // Specifies how long a socket is allowed to be inactive before we close it
       
    33 // down. This handles the situation where the mail server closes down the
       
    34 // connection, but we don't receive any indication of that. It has been seen
       
    35 // when connected using GPRS, and a long telephone call is then made.
       
    36 const TInt KPopSendInactivityTimeMinutes = 30;
       
    37 const TInt KPopReceiveInactivityTimeMinutes = 30;
       
    38 
       
    39 // Utility functions used by both active objects...
       
    40 GLDEF_C TBool CommandAccepted(TDesC8& aResponse)
       
    41 	{
       
    42 	// +OK signifies a successful command -ERR otherwise
       
    43 	return (0==aResponse.Locate('+'));
       
    44 	}
       
    45 //
       
    46 // My own panic command 
       
    47 //
       
    48 GLDEF_C void Panic(TPopsPanic aPanic)
       
    49 	{
       
    50 	_LIT(KPanicText,"Pop3 session");
       
    51 	User::Panic(KPanicText, aPanic);
       
    52 	}
       
    53 
       
    54 CImPop3Session::CImPop3Session()
       
    55 	: CMsgActive(KImPopSessionPriority)
       
    56 	{
       
    57 	__DECLARE_NAME(_S("CImPop3Session"));
       
    58 	}
       
    59 
       
    60 
       
    61 CImPop3Session* CImPop3Session::NewL(RSocketServ& aServ, CImConnect& aConnect)
       
    62 	{
       
    63 	CImPop3Session* self = new (ELeave) CImPop3Session();
       
    64 	CleanupStack::PushL(self);
       
    65 	self->ConstructL(aServ, aConnect);
       
    66 	CleanupStack::Pop();
       
    67 	return self;
       
    68 	}
       
    69 
       
    70 
       
    71 void CImPop3Session::ConstructL(RSocketServ& aServ, CImConnect& aConnect)
       
    72 	{
       
    73 	iSocket=CImTextServerSession::NewL(KPopSendInactivityTimeMinutes, KPopReceiveInactivityTimeMinutes, aServ, aConnect);
       
    74 	iNoMessages=0;
       
    75 	iIdTab=NULL;
       
    76 	iSocketConnected=EFalse;
       
    77 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
    78 	iSaslAuthLogin = EFalse;
       
    79 #endif	
       
    80 
       
    81 	CActiveScheduler::Add(this);	  // Add PopSession to scheduler's queue
       
    82 	}
       
    83 
       
    84 
       
    85 CImPop3Session::~CImPop3Session()
       
    86 	{
       
    87 	Cancel();
       
    88 
       
    89 	delete iPopApop;
       
    90 	delete iConnectReply;
       
    91 	delete iSocket;
       
    92 	delete [] iIdTab;
       
    93 	delete iCaf;
       
    94 	delete iPopCapabilities;
       
    95 	}
       
    96 
       
    97 //
       
    98 // Connect to Pop3 with User and Pass
       
    99 //
       
   100 void CImPop3Session::ConnectL(CImPop3Settings* aPopSettings, const CImIAPPreferences& aPrefs, TRequestStatus& aStatus)
       
   101 	{
       
   102 	__ASSERT_DEBUG(!IsActive(),Panic(EImppAlreadyActive));
       
   103 	// copy of pop settings owned by mtm
       
   104 	iPopSettings = aPopSettings;
       
   105 	
       
   106 	iCompleted=KErrNone;
       
   107 	iState=EConnectingToPop;	// Initialise to 1st state of state machine
       
   108 	
       
   109 	Queue(aStatus);
       
   110 
       
   111 	if(iPopSettings->SSLWrapper())
       
   112 		{
       
   113 		iSocket->SSLQueueConnectL(iStatus, iPopSettings->ServerAddress(), aPopSettings->Port(), aPrefs, iPopSettings->TlsSslDomain());
       
   114 		}
       
   115 	else
       
   116 		{
       
   117 		iSocket->QueueConnectL(iStatus, iPopSettings->ServerAddress(), aPopSettings->Port(), aPrefs, iPopSettings->TlsSslDomain());
       
   118 		}
       
   119 	SetActive();
       
   120 	}
       
   121 
       
   122 //
       
   123 // Queue a read if mailbox is in idle state
       
   124 //
       
   125 void CImPop3Session::Waiting(TRequestStatus& aStatus)
       
   126 	{
       
   127 	iState=EPopConnected;
       
   128 	iSocket->QueueReceiveNextTextLine(iStatus);
       
   129 	SetActive();
       
   130 	Queue(aStatus);
       
   131 	}
       
   132 //
       
   133 // Put a QUIT function 
       
   134 //
       
   135 void CImPop3Session::Quit(TRequestStatus& aStatus)
       
   136 	{
       
   137 	__ASSERT_DEBUG(!IsActive(),Panic(EImppAlreadyActive));
       
   138 
       
   139 	iState=EStopPop;
       
   140 
       
   141 	if(iSocketConnected)
       
   142 		{
       
   143 		_LIT8(KPop3CmdQuit, "QUIT\r\n");
       
   144 		iSocket->SendQueueReceive(iStatus,KPop3CmdQuit());
       
   145 		SetActive();
       
   146 		Queue(aStatus);
       
   147 		}
       
   148 	else
       
   149 		{
       
   150 		TRequestStatus* pS=&iStatus;
       
   151 		User::RequestComplete(pS,KErrNone);
       
   152 		}
       
   153 	}
       
   154 
       
   155 //
       
   156 // Pass the TMsg array to our Pop session
       
   157 //
       
   158 void CImPop3Session::SetMessageArray(TInt32* anIdArray, TUint aNoMessages)
       
   159 	{
       
   160 	iIdTab=anIdArray;
       
   161 	iNoMessages=aNoMessages;
       
   162 	}
       
   163 	
       
   164 TInt32* CImPop3Session::MessageArray()
       
   165 	{
       
   166 	return iIdTab;
       
   167 	}
       
   168 
       
   169 TInt CImPop3Session::GetNumMessages()
       
   170 	{
       
   171 	return iNoMessages;
       
   172 	}
       
   173 
       
   174 //
       
   175 // Return Pop3 message no for a given message id
       
   176 //
       
   177 TInt CImPop3Session::MessageNo(TMsvId aMsgId)
       
   178 // AF Using TInt reduces the available range of +ve numbers 
       
   179 // but shouldn't be a problem should it?
       
   180 	{
       
   181 	TInt msgNo=KErrNotFound;
       
   182 	TInt arrayCtr=0;
       
   183 
       
   184 	if(iIdTab==NULL || iNoMessages==0)
       
   185 		{
       
   186 		Panic(EImppBabelMsgArrayNotDefined);
       
   187 		}
       
   188 	
       
   189 	while(arrayCtr<iNoMessages && msgNo==KErrNotFound)
       
   190 		{
       
   191 		if(TInt32(*(iIdTab+arrayCtr))==aMsgId)
       
   192 			{
       
   193 			msgNo=arrayCtr+1;
       
   194 			}
       
   195 		arrayCtr++;
       
   196 		}
       
   197 
       
   198 	return msgNo;
       
   199 	}
       
   200 
       
   201 //
       
   202 // Cancel any current operation
       
   203 //
       
   204 void CImPop3Session::DoCancel()
       
   205 	{
       
   206 	if(iState==EStopPop)
       
   207 		{
       
   208 		iSocket->Disconnect();
       
   209 		iSocketConnected=EFalse;
       
   210 		}
       
   211 	iSocket->Cancel();	// clear a pending socket call
       
   212 	CMsgActive::DoCancel();
       
   213 	}
       
   214 
       
   215 //
       
   216 // Result of last active call
       
   217 //
       
   218 void CImPop3Session::DoRunL()
       
   219     {
       
   220 	if(iState==EStopPop)
       
   221 		{
       
   222 		iSocket->Disconnect();
       
   223 		iSocketConnected=EFalse;
       
   224 		}
       
   225 	
       
   226 	//get the response
       
   227 	if(iState!=EConnectingToPop && iState!=EStopPop)
       
   228 		{
       
   229 		if(iState != EWaitingForReply)
       
   230 			{
       
   231 			TInt lineState=iSocket->GetCurrentTextLine(iResponseBuffer);
       
   232 			__ASSERT_ALWAYS(lineState==ECRLFTerminated,User::Leave(EImppBufferNotTerminated));
       
   233 
       
   234 			if(!CommandAccepted(iResponseBuffer))
       
   235 				{
       
   236 				User::Leave(GetPopError());
       
   237 				}
       
   238 			}
       
   239 		
       
   240 		if(iPopSettings->Apop() && iState==EWaitingForReply)
       
   241 			{
       
   242 			HBufC8* connectReply = HBufC8::NewL(KImMailMaxBufferSize);
       
   243 			// Delete iConnectReply if not NULL & assign newly created
       
   244 			delete iConnectReply;
       
   245 			iConnectReply = connectReply;
       
   246 			iConnectReply->Des().Copy(iResponseBuffer); 
       
   247 			}
       
   248 		}
       
   249 			
       
   250 	if(iState!=EStopPop) 
       
   251 		{
       
   252 		// successful response decide what to do next
       
   253 		switch(iState)
       
   254 			{
       
   255 			case EPopCapabilities:
       
   256 				GetCapabilitiesL();
       
   257 				iState = EWaitingForReply;
       
   258 				break;
       
   259 				
       
   260 			case EWaitingForReply:
       
   261 				if(iPopSettings->SecureSockets())
       
   262 					{
       
   263 					iState = ERequestingTLS;
       
   264 					}
       
   265 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   266 				else if(iPopSettings->POP3Auth())
       
   267 					{
       
   268 					iState = ESaslAuthInProgress; 
       
   269 					SelectAuthExtensionProfileL();
       
   270 					}
       
   271 #endif					
       
   272 				else if(iPopSettings->Apop())
       
   273 					{
       
   274 					iState=EAuthorisingApop;
       
   275 					}
       
   276 				else 
       
   277 					{
       
   278 					iState++;
       
   279 					}
       
   280 				ChangeStateL();
       
   281 				break;
       
   282 
       
   283 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)					
       
   284 			case ESaslAuthInProgress:
       
   285 				// To set the server response, accodring the response will be creating 
       
   286 				// the authentication string.
       
   287 				iPopAuthHelper->SetLastServerMessageL(iResponseBuffer, ETrue);
       
   288 				iState++;
       
   289 				ChangeStateL();
       
   290 				break;
       
   291 			
       
   292 			case ESaslAuthIsDone:
       
   293 				iSocketConnected=ETrue;
       
   294 				break;
       
   295 #endif
       
   296 				
       
   297 			case EConnectingToPop:
       
   298 			case EAuthorisingUser:
       
   299 				iState++;
       
   300 				ChangeStateL();
       
   301 				break;
       
   302 				
       
   303 			case EAuthorisingPass:
       
   304 			case EAuthorisingApop:
       
   305 				iSocketConnected=ETrue;
       
   306 				break;
       
   307 				
       
   308 			// TLS request accepted
       
   309 			case ERequestingTLS:
       
   310 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)			
       
   311 				if(iPopSettings->POP3Auth())
       
   312 					{
       
   313 					iState = ESaslAuthInProgress; 
       
   314 					SelectAuthExtensionProfileL();
       
   315 					}
       
   316 				else
       
   317 #endif
       
   318 					{
       
   319 					iPopSettings->Apop() ? iState = EAuthorisingApop : iState =EAuthorisingUser;
       
   320 					}
       
   321 				ChangeStateL();
       
   322 				break;
       
   323 			}
       
   324 		}
       
   325    }
       
   326 
       
   327 void CImPop3Session::DoComplete(TInt& aCompleteStatus)
       
   328  	{
       
   329 	TInt status=aCompleteStatus;
       
   330 	if (status==KErrNone)	// no error
       
   331 		{
       
   332 		return;
       
   333 		}
       
   334 
       
   335 	if(iSocketConnected && status==KErrCancel)	// Cancel() has been called
       
   336 		{
       
   337 		return;
       
   338 		}
       
   339 
       
   340 	// if we've connected but it all goes wrong send a synchronous quit kludged code
       
   341 	switch (iState)
       
   342 		{
       
   343 	case EWaitingForReply:	// stay connected
       
   344 	case EStopPop:			
       
   345 		break;
       
   346 	case EAuthorisingUser:
       
   347 	case EAuthorisingPass:
       
   348 	case EAuthorisingApop:
       
   349 	case EPopConnected:     // idle read has returned POP server timed out
       
   350 	case EConnectingToPop:	// lose connection
       
   351 	case ERequestingTLS:
       
   352 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   353 	case ESaslAuthInProgress:
       
   354 	case ESaslAuthIsDone:
       
   355 #endif	
       
   356 		iSocket->Disconnect();
       
   357 		iSocketConnected=EFalse;
       
   358 		break;
       
   359 		}
       
   360 	}
       
   361 
       
   362 void CImPop3Session::ChangeStateL()
       
   363 	{
       
   364 	//
       
   365 	// State machine of the POP mail session.
       
   366 	// (But only handle states which can leave)
       
   367 	// Identify state on entry, change to next state and then
       
   368 	// start new operation associated with that new state.
       
   369 	//
       
   370    
       
   371 	__ASSERT_DEBUG(!IsActive(),Panic(EImppAlreadyActive));
       
   372    
       
   373 	switch (iState)
       
   374 		{
       
   375 	case EPopCapabilities:
       
   376 		iSocket->QueueReceiveNextTextLine(iStatus);
       
   377 		break;
       
   378 
       
   379 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)	
       
   380 	case ESaslAuthInProgress:
       
   381 		iPopAuthHelper->GetNextClientMessageL(iResponseBuffer);
       
   382 		iSocket->SendQueueReceive(iStatus, iResponseBuffer);
       
   383 		iSocket->PerformLogging(ETrue);
       
   384 		break;
       
   385 	
       
   386 	case ESaslAuthIsDone:
       
   387 		iPopAuthHelper->GetNextClientMessageL(iResponseBuffer);
       
   388 		iSocket->SendQueueReceive(iStatus, iResponseBuffer);
       
   389 		iSocket->PerformLogging(ETrue);
       
   390 		if(iSaslAuthLogin)
       
   391 			{
       
   392 			iState = ESaslAuthInProgress;
       
   393 			iSaslAuthLogin = EFalse;	
       
   394 			}
       
   395 		break;
       
   396 #endif
       
   397 		
       
   398 	case EAuthorisingUser:
       
   399 	case EAuthorisingApop:
       
   400 		{
       
   401 		TPtrC8 loginName=iPopSettings->LoginName();
       
   402 		if (iState == EAuthorisingApop)
       
   403 			{
       
   404 			TRAPD(apopErr,ConstructApopL());
       
   405 			if(apopErr!=KErrNone)
       
   406 				{
       
   407 				User::Leave(KPop3CannotCreateApopLogonString);
       
   408 				}
       
   409 			iSocket->PerformLogging(EFalse);
       
   410 			_LIT8(KPop3CmdApop, "APOP %S %S\r\n");
       
   411 			iSocket->SendQueueReceive(iStatus, KPop3CmdApop(), &loginName, iPopApop);
       
   412 			iSocket->PerformLogging(ETrue);
       
   413 			delete iPopApop;
       
   414 			iPopApop=NULL;
       
   415 			delete iConnectReply;
       
   416 			iConnectReply=NULL;
       
   417 			}
       
   418 		else
       
   419 			{
       
   420 			iSocket->PerformLogging(EFalse);
       
   421 			_LIT8(KPop3CmdUser, "USER %S\r\n");
       
   422 			iSocket->SendQueueReceive(iStatus, KPop3CmdUser(), &loginName);
       
   423 			iSocket->PerformLogging(ETrue);
       
   424 			}
       
   425 		break;
       
   426 		}
       
   427 	case EAuthorisingPass:
       
   428 		{
       
   429 		TPtrC8 password=iPopSettings->Password();
       
   430 		iSocket->PerformLogging(EFalse);
       
   431 		_LIT8(KPop3CmdPass, "PASS %S\r\n");
       
   432 		iSocket->SendQueueReceive(iStatus, KPop3CmdPass(), &password);
       
   433 		iSocket->PerformLogging(ETrue);
       
   434 		break;
       
   435 		}   
       
   436 	// new request to initiate TLS
       
   437 	case ERequestingTLS:
       
   438 		_LIT8(KPop3CmdOk, "+OK");
       
   439 		iSocket->SetSSLTLSResponseL(KPop3CmdOk());
       
   440 		_LIT8(KPop3CmdStls, "STLS\r\n");
       
   441 		iSocket->SendQueueReceive(iStatus, KPop3CmdStls());
       
   442 		break;
       
   443    
       
   444 	   default: 	// Unknown state
       
   445 		   Panic(EImppBadSessionState);
       
   446 		   break;
       
   447 		}
       
   448 	
       
   449 	SetActive();
       
   450 	}
       
   451 
       
   452 //
       
   453 // return a pointer to our CImTextServerSession so CPop3Operations can use it
       
   454 //
       
   455  CImTextServerSession* CImPop3Session::TextServerSession()
       
   456 	{
       
   457 	return iSocket;
       
   458 	}
       
   459 
       
   460 //
       
   461 // Return POP3 error (based on what state the POP login is in
       
   462 //
       
   463 TInt CImPop3Session::GetPopError()
       
   464 	{
       
   465 	TInt anError=KErrGeneral;
       
   466 	switch (iState)
       
   467 		{
       
   468 	case EWaitingForReply:
       
   469 	case EPopCapabilities:
       
   470 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   471 		if(iPopSettings->POP3Auth() && iState != EPopCapabilities)
       
   472 			{
       
   473 			anError=KPop3AuthenticationFailed;
       
   474 			}
       
   475 		else
       
   476 #endif		
       
   477 			{
       
   478 			anError=KPop3CannotConnect;
       
   479 			} 
       
   480 		break;
       
   481 	case EAuthorisingUser:
       
   482 		anError=KPop3InvalidUser;
       
   483 		break;
       
   484 	case EAuthorisingPass:
       
   485 		anError=KPop3InvalidLogin;
       
   486 		break;
       
   487 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   488 	case ESaslAuthInProgress:
       
   489 		anError=KPop3InvalidUser;
       
   490 		break;
       
   491 	case ESaslAuthIsDone:
       
   492 		anError=KPop3InvalidLogin;
       
   493 		break;
       
   494 #endif		
       
   495 	case EAuthorisingApop:
       
   496 		anError=KPop3InvalidApopLogin;
       
   497 		break;
       
   498 	case EPopConnected:
       
   499 		anError=KErrDisconnected; // assume that this is Pop time out
       
   500 		break;
       
   501 	case ERequestingTLS:
       
   502 		anError = KErrPop3TLSNegotiateFailed;
       
   503 	default:
       
   504 		break;
       
   505 		}
       
   506 	return anError;
       
   507 	}
       
   508 
       
   509 //DMC
       
   510 TInt CImPop3Session::MaxHeaders() 
       
   511 	{
       
   512 	return iPopSettings->InboxSynchronisationLimit();
       
   513 	}
       
   514 
       
   515 //
       
   516 // Set and test state of iOpPending: is a pop operation currently underway?
       
   517 //
       
   518 void CImPop3Session::SetPending()
       
   519 	{
       
   520 	iOpPending=ETrue;
       
   521 	}
       
   522 
       
   523 void CImPop3Session::SetOpNotPending()
       
   524 	{
       
   525 	iOpPending=EFalse;
       
   526 	}
       
   527 
       
   528 TBool CImPop3Session::IsPending()
       
   529 	{
       
   530 	return iOpPending;
       
   531 	}
       
   532 
       
   533 
       
   534 TBool CImPop3Session::IsConnectedToInternet()
       
   535 	{
       
   536 	return iSocketConnected;
       
   537 	}
       
   538 
       
   539 //
       
   540 // construct Apop string using timestamp and user password (and MD5 hash function)
       
   541 //
       
   542 void CImPop3Session::ConstructApopL()
       
   543 	{
       
   544 	TPtrC8 pass(iPopSettings->Password());
       
   545 	TPtrC8 timeStamp;
       
   546 	TInt timeStampEndPos=KErrNotFound;
       
   547 
       
   548 	const TInt timeStampStartPos=iConnectReply->Des().Locate('<');
       
   549 	if(timeStampStartPos==KErrNotFound)
       
   550 		{
       
   551 		User::Leave(KErrNotFound);
       
   552 		}
       
   553 
       
   554 	timeStampEndPos=iConnectReply->Des().Locate('>');
       
   555 	if(timeStampEndPos!=KErrNotFound && (timeStampEndPos>timeStampStartPos))
       
   556 		{
       
   557 		TInt timeStampLength=(timeStampEndPos-timeStampStartPos)+1;
       
   558 		timeStamp.Set(iConnectReply->Des().Mid(timeStampStartPos,timeStampLength));
       
   559 		}
       
   560 	else
       
   561 		{
       
   562 		User::Leave(KErrNotFound);
       
   563 		}
       
   564 		
       
   565 	HBufC8* popBuf = HBufC8::NewLC(timeStamp.Length() + pass.Length());
       
   566 	TPtr8 bufContent=popBuf->Des();
       
   567 	bufContent=timeStamp;
       
   568 	bufContent.Append(pass);
       
   569 
       
   570 	// do MD5
       
   571 	CMD5* doHash = CMD5::NewL();
       
   572 	CleanupStack::PushL(doHash);
       
   573 	HBufC8* popApop = HBufC8::NewL(2*doHash->HashSize());
       
   574 	delete iPopApop;
       
   575 	iPopApop = NULL;
       
   576 	iPopApop = popApop;
       
   577 	TPtr8 hashCont=iPopApop->Des();
       
   578 	hashCont = doHash->Hash(*popBuf);	
       
   579 
       
   580 	TBuf<32> hexHash;  
       
   581 	// MD5 algorithm ALWAYS returns 16 bytes of data - which will be converted into
       
   582 	// 32 characters; each byte represented by a 2 character hex representation, 
       
   583 	// eg 255="ff"
       
   584 	
       
   585 	for (TInt j=0;j<16;j++)
       
   586 		{
       
   587 		hexHash.AppendNumFixedWidth(hashCont[j],EHex,2);
       
   588 		}
       
   589 
       
   590 	// copy Hex values to iPopApop so that it can be used with the APOP command
       
   591 	iPopApop->Des().Copy(hexHash);
       
   592 	
       
   593 	CleanupStack::PopAndDestroy(2); //popBuf & doHash
       
   594 	}
       
   595 
       
   596 CImCaf* CImPop3Session::GetCafL(RFs& aFs)
       
   597 	{
       
   598 	if(!iCaf)
       
   599 		{
       
   600 		iCaf = new(ELeave) CImCaf(aFs);
       
   601 		}
       
   602 	return iCaf;
       
   603 	}
       
   604 
       
   605 //
       
   606 // Use CAPA command to get server capabilities
       
   607 //
       
   608 void CImPop3Session::GetCapabilitiesL()
       
   609 	{
       
   610 	iPopCapabilities = CImPop3Capa::NewL(this);
       
   611 	
       
   612 	iPopCapabilities->Start(iStatus);
       
   613 	SetActive();
       
   614 	}
       
   615 	
       
   616 TBool CImPop3Session::PipeliningSupport()
       
   617 	{
       
   618 	return iPopCapabilities->PipeliningSupport();
       
   619 	}
       
   620 
       
   621 
       
   622 #if (defined SYMBIAN_EMAIL_CAPABILITY_SUPPORT)
       
   623 /**
       
   624 Function to select SASL Authentication Mechanism supported by email server.
       
   625 If CRAM-MD5 Authentication is not supported by server and if Fallback flag is enabled,
       
   626 will fallback to less secure authentication mechanism.
       
   627 Fallback priority will be in a following order when server dosn't support CRAM-MD5.
       
   628 1. APOP
       
   629 2. PLAIN
       
   630 3. LOGIN
       
   631 4. USER/PASS
       
   632 */
       
   633 void CImPop3Session::SelectAuthExtensionProfileL()
       
   634 	{
       
   635 	// get the supported SASL Capabilities
       
   636 	TUint supportedAuthProfiles = iPopCapabilities->SaslAuthExtensionFlag();
       
   637 			
       
   638 	// to check whether CRAM-MD5 supported by the server
       
   639 	if(supportedAuthProfiles & CPopAuthMechanismHelper::ECramMD5)
       
   640 		{
       
   641 		//AUTHENTICATE CRAM-MD5 implementation
       
   642 		iPopAuthHelper = CPopAuthCramMd5MechanismHelper::NewL(*iPopSettings);
       
   643 		}
       
   644 	// if server doesn't support CRAM-MD5, check whether FallBack enabled from POP3 email settings.
       
   645 	else if(iPopSettings->FallBack())
       
   646 		{
       
   647 		if(iPopSettings->Apop())
       
   648 			{
       
   649 			//APOP
       
   650 			iState=EAuthorisingApop;
       
   651 			}
       
   652 		else if(supportedAuthProfiles & CPopAuthMechanismHelper::EPlain)
       
   653 			{
       
   654 			//AUTHENTICATE PLAIN implementation
       
   655 			iPopAuthHelper = CPopAuthPlainMechanismHelper::NewL(*iPopSettings);
       
   656 			iState = ESaslAuthIsDone;
       
   657 			}
       
   658 		else if(supportedAuthProfiles & CPopAuthMechanismHelper::ELogin)
       
   659 			{
       
   660 			//AUTHENTICATE LOGIN implementation
       
   661 			iPopAuthHelper = CPopAuthLoginMechanismHelper::NewL(*iPopSettings);
       
   662 			iSaslAuthLogin = ETrue;
       
   663 			}
       
   664 		else
       
   665 			{
       
   666 			//USER/PASS
       
   667 			iState = EAuthorisingUser;	
       
   668 			}
       
   669 		}
       
   670 	else
       
   671 		{
       
   672 		// if server doesn't support CRAM-MD5 & FallBack is Off, leave with error.
       
   673 		iState = EWaitingForReply;
       
   674 		User::Leave(GetPopError());
       
   675 		}	 
       
   676 	}
       
   677 
       
   678 #endif
       
   679