messagingfw/msgtestfw/TestActions/Email/Pop3/src/CMtfTestActionVerifyReplyToAddress.cpp
changeset 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgtestfw/TestActions/Email/Pop3/src/CMtfTestActionVerifyReplyToAddress.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,411 @@
+// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// __ACTION_INFO_BEGIN__
+// [Action Name]
+// VerifyReplyToAddress
+// [Action Parameters]
+// 0) CMsvSession&				session   <input>			:Reference to the session.
+// 1) CMsvEntrySelection&		SentMailSelection <input>	: Reference to the sent mail selection.
+// 2) CMsvEntrySelection&		RecvMailSelection <input>	: Reference to the received mail selection.
+// 3) TInt						Number of mails under test.
+// 4) HBufC&					Full Epoc32 file path of sample email txt file used.
+// 5) TInt						Whether the sample email contains a Reply-To address field or not? (1 = ETrue, 0 = EFalse)
+// [Action Description]
+// Implements the action to compare the Reply-To address set in header of email from txt file to
+// that of the email actual sent as stored in the Message store as a TMsvEntry object.
+// [APIs Used]
+// __ACTION_INFO_END__
+// 
+//
+
+/**
+ @file CMtfTestActionVerifyReplyToAddress.cpp
+*/
+
+#include <e32std.h>
+#include <txtrich.h>
+#include <mtclreg.h>
+#include <imcm.rsg>
+
+#include <msvstore.h>
+#include "CMtfTestActionVerifyReplyToAddress.h"
+#include <cemailaccounts.h>
+#include <iapprefs.h>
+#include "CMtfTestActionUtilsPopScripts.h"
+
+#include "CMtfTestActionUtils.h"
+#include "CMtfTestCase.h"
+#include "CMtfTestActionParameters.h"
+#include "MtfTestActionUtilsUser.h"
+#include "TMtfTestParameterType.h"
+#include "CPop3MailInfo.h"
+
+// Expected Reply-To field to be used in sample emails 
+_LIT8(KReplyToField, "Reply-To: matthewf@msexchange2k.closedtest.intra\r\n");
+
+_LIT(KSettingsFile, "c:\\msgtest\\TestFramework\\Configurations\\EmailSettings\\Pop3Tests-lon-cn-exchng2k.txt");
+
+#ifdef _UNICODE
+ _LIT(KSmtpEmailAddressAndAliasFmtStr,"\"%S\" <%S>");
+#else
+ _LIT8(KSmtpEmailAddressAndAliasFmtStr,"\"%S\" <%S>");
+#endif
+
+/**
+  Function : NewL
+  Description : Standard symbian 2 phase constructor
+  @internalTechnology
+  @param aMtfTestCase - CMtfTestCase test case reference for base class constructor
+  @param aActionParameters - pointer to the parameters for this test action
+  @return A CMtfTestAction pointer to the newly created CMtfTestActionVerifyReplyToAddress object
+  @precondition none
+  @postcondition none
+*/
+CMtfTestAction* CMtfTestActionVerifyReplyToAddress::NewL(CMtfTestCase& aTestCase,CMtfTestActionParameters* aActionParameters)
+	{
+	CMtfTestActionVerifyReplyToAddress* self = new (ELeave) CMtfTestActionVerifyReplyToAddress(aTestCase);
+	CleanupStack::PushL(self);
+	self->ConstructL(aActionParameters);
+	CleanupStack::Pop(self);
+	return self;
+	}
+	
+/**
+  Function : CMtfTestActionVerifyReplyToAddress constructor
+  Description : Private constructor - must not leave
+  @internalTechnology
+  @param  aTestCase - CMtfTestCase reference for the base class constructor
+  @return N/A
+  @precondition none
+  @postcondition none
+*/
+CMtfTestActionVerifyReplyToAddress::CMtfTestActionVerifyReplyToAddress(CMtfTestCase& aTestCase)
+: CMtfSynchronousTestAction(aTestCase), iSession(NULL), iSentSelectionList(NULL), iInboxSelectionList(NULL)
+	{
+	}
+
+/**
+  Function : CMtfTestActionVerifyReplyToAddress destructor
+  Description : Destructor
+  @internalTechnology
+  @param  N/A
+  @return N/A
+  @precondition none
+  @postcondition none
+*/
+CMtfTestActionVerifyReplyToAddress::~CMtfTestActionVerifyReplyToAddress()
+	{
+	}
+
+/**
+  Function : LoadParametersL
+  Description : Loads the test action parameters 
+  @internalTechnology
+  @param  none
+  @return ETrue if parameters loaded Efalse on failure
+  @precondition none
+  @postcondition Upon failure TestCase status is EFail
+*/
+TBool CMtfTestActionVerifyReplyToAddress::LoadParametersL()
+	{
+	iSession = ObtainParameterReferenceL<CMsvSession> (TestCase(),ActionParameters().Parameter(0));
+	if(! iSession)
+		{
+		TestCase().ERR_PRINTF1(_L("Invalid session object"));
+		TestCase().SetTestStepResult(EFail);
+		return EFalse;
+		}
+	iSentSelectionList = ObtainParameterReferenceL<CMsvEntrySelection> (TestCase(), ActionParameters().Parameter(1));
+	if(! iSentSelectionList)
+		{
+		TestCase().ERR_PRINTF1(_L("Invalid sentSelectionList"));
+		TestCase().SetTestStepResult(EFail);
+		return EFalse;
+		}
+	iInboxSelectionList = ObtainParameterReferenceL<CMsvEntrySelection> (TestCase(), ActionParameters().Parameter(2));
+	if(! iInboxSelectionList)
+		{
+		TestCase().ERR_PRINTF1(_L("Invalid inboxSelectionList"));
+		TestCase().SetTestStepResult(EFail);
+		return EFalse;
+		}
+	
+	if(iInboxSelectionList->Count() != iSentSelectionList->Count())
+		{
+		TestCase().ERR_PRINTF3(_L("iInboxSelectionList->Count(%d) != iSentSelectionList->Count(%d)"),
+								 iInboxSelectionList->Count(), iSentSelectionList->Count() );
+		TestCase().SetTestStepResult(EFail);
+		return EFalse;
+		}
+
+	TInt numTests = ObtainValueParameterL<TInt> (TestCase(),ActionParameters().Parameter(3));
+	if(numTests != iInboxSelectionList->Count())
+		{
+		TestCase().ERR_PRINTF2(_L("NumTests != iInboxSelectionList->Count(%d)"), iInboxSelectionList->Count());
+		TestCase().SetTestStepResult(EFail);
+		return EFalse;
+		}
+	
+	iEmailFilePath = ObtainParameterReferenceL<HBufC> (TestCase(),ActionParameters().Parameter(4));
+	TPtr ptrEmailFilePath = iEmailFilePath->Des();
+	TestCase().INFO_PRINTF2(_L("Email path: %S"), &ptrEmailFilePath);
+		
+	iReplyToAddress = ObtainValueParameterL<TInt> (TestCase(),ActionParameters().Parameter(5));	
+	TestCase().INFO_PRINTF2(_L("ReplyToField flag: %d"), iReplyToAddress);
+	
+	return ETrue;
+	}
+
+/**
+  Function : ExecuteActionL
+  Description : Test framework entry point for CMtfTestActionVerifyReplyToAddress test action
+  @internalTechnology
+  @param  none
+  @return void
+  @precondition none  
+  @postcondition TestCase status EPass if tests passed otherwise EFail
+*/
+void CMtfTestActionVerifyReplyToAddress::ExecuteActionL()
+	{
+	TestCase().INFO_PRINTF2(_L("Test Action %S start..."), &KTestActionVerifyReplyToAddress);
+	if(LoadParametersL())
+		{
+		User::LeaveIfError(iFs.Connect());
+		CleanupClosePushL(iFs);	
+			// Normally do not push an object that is a data member of another object.
+			// But in this case we want to close early if we get a leave.
+			// Otherwise the iFs would be open till the thread had begun to die.
+		
+		if(TestCase().TestStepResult() == EPass)
+			{
+			CMsvEntry* recvMsvEntry = iSession->GetEntryL(KMsvRootIndexEntryId);
+			CleanupStack::PushL(recvMsvEntry);
+			CMsvEntry* sentMsvEntry = iSession->GetEntryL(KMsvRootIndexEntryId);
+			CleanupStack::PushL(sentMsvEntry);
+
+			for(TInt i=0; i<iInboxSelectionList->Count(); i++)
+				{
+				recvMsvEntry->SetEntryL(iInboxSelectionList->At(i));
+				TMsvEntry recvEntry = recvMsvEntry->Entry();
+				for(TInt j=0; j<iSentSelectionList->Count(); j++)
+					{
+					sentMsvEntry->SetEntryL(iSentSelectionList->At(j));
+					TMsvEntry sentEntry = sentMsvEntry->Entry();
+					if(recvEntry.iDescription.Compare(sentEntry.iDescription) == 0)
+						{
+						if(! ReplyToHeaderFieldCompareL(sentEntry, iEmailFilePath->Des(), iSession))
+							{
+							TestCase().INFO_PRINTF2(_L("Test %d failed"), j+1);
+							TestCase().SetTestStepResult(EFail);
+							}
+						}
+					}
+				}
+			CleanupStack::PopAndDestroy(2, recvMsvEntry); // recvMsvEntry, sentMsvEntry
+			}
+		CleanupStack::PopAndDestroy(&iFs);
+		}
+		
+	TestCase().INFO_PRINTF1( _L("Test Action CMtfTestActionVerifyEmail Completed") );
+	TestCase().ActionCompletedL(*this);
+	}
+	
+TBool CMtfTestActionVerifyReplyToAddress::ReplyToHeaderFieldCompareL(TMsvEntry& aSentEntry, const TDesC& aFileName, CMsvSession* aSession)
+	{
+	TBool ret = ETrue;
+	
+	// If Reply-To address exists in email header then... 
+	if(iReplyToAddress)
+		{
+		// Read Reply-To field from sample email txt file
+		RFileReadStream rdStream;
+		User::LeaveIfError(rdStream.Open(iFs, aFileName, EFileRead|EFileStreamText));
+	
+		if(IsEofL(rdStream))
+			{
+			ret = EFalse;
+			return ret;
+			}
+		
+		TBuf8<256> line;
+		TChar char_LF('\n');
+		line.Zero();
+		
+		do
+			{
+			rdStream.ReadL(line, char_LF);
+			if(line.Compare(KReplyToField)==0)
+				{
+				// Break from loop if expected Reply-To field found
+				break;
+				}
+			}
+			while(!IsEofL(rdStream));
+			
+		rdStream.Close(); // End of reading stream
+			
+		// aSentEntry - Identifier of the original sent email identified by TMsvEntry	
+		CMsvEntry* msvEntry = aSession->GetEntryL(aSentEntry.Id());
+		CleanupStack::PushL(msvEntry);
+		
+		msvEntry->SetEntryL(aSentEntry.Id());
+	
+		CMsvStore* store = msvEntry->ReadStoreL();
+		CleanupStack::PushL(store);
+	
+		CImHeader* header = CImHeader::NewLC();
+		
+		header->RestoreL(*store);
+		// Read Reply-To address from email header
+		TPtrC line2 = header->ReplyTo();
+		
+		TestCase().INFO_PRINTF2(_L("Reply-To address from actual sent message as stored in the Message store: %S"), &line2);
+	
+		TBuf16<256> tmp;
+		tmp.Copy(line);
+	
+		TBuf16<256> line_16;
+		
+		// Extract just the Reply-To address without the initial tag and trailing CR-LF characters 
+		for(TInt n=10; n<tmp.Length()-2; n++)
+			{
+			line_16.Append(tmp[n]);
+			}
+	
+		// Compare if user-set Reply-To address in sample email txt file equals the one set by system in email header
+		if(line_16.Compare(line2) != 0)
+			{
+			ret = EFalse;
+			}
+		
+		CleanupStack::PopAndDestroy(header); 
+		CleanupStack::PopAndDestroy(store); 
+		CleanupStack::PopAndDestroy(msvEntry); 
+		
+		}
+		// else no Reply-To address exists in email header... 
+		else
+			{
+			// Check if Reply-To address is set correctly from default settings
+			CEmailAccounts* accounts = CEmailAccounts::NewL();
+			CleanupStack::PushL(accounts);
+			CImSmtpSettings* settings = new(ELeave) CImSmtpSettings();
+			CleanupStack::PushL(settings);
+			CImIAPPreferences* smtpIAP = CImIAPPreferences::NewLC();
+	
+			TSmtpAccount smtpAccountId = accounts->CreateSmtpAccountL(_L("SMTP"),*settings, *smtpIAP, EFalse);
+			accounts->SetDefaultSmtpAccountL(smtpAccountId);
+			accounts->PopulateDefaultSmtpSettingsL(*settings, *smtpIAP);
+			
+			CImIAPPreferences *popPrefs = CImIAPPreferences::NewLC();
+			CImPop3Settings *popSettings = new (ELeave) CImPop3Settings;
+			CleanupStack::PushL(popSettings);
+
+			accounts->PopulateDefaultPopSettingsL(*popSettings, *popPrefs);
+			
+			// TestAction CreatePop3Service doesn't save settings to central repository,
+			// so default settings are reloaded
+			CMtfTestActionUtilsPopScripts::ReadPopSettingsFromConfigurationFileL(
+			TestCase(), KSettingsFile, *popSettings, *popPrefs, *settings, *smtpIAP);
+			
+			TPtrC defaultReplyToAddress = settings->ReplyToAddress();
+			
+			TestCase().INFO_PRINTF2(_L("Default ReplyTo Address: %S"), &defaultReplyToAddress);
+			
+			// Format the Reply-To address field
+			HBufC* formatedAddress = CreateFormattedAddressLC(defaultReplyToAddress, settings->EmailAlias());
+			TPtr ptrFormatedAddress = formatedAddress->Des();
+			TestCase().INFO_PRINTF2(_L("Formated ReplyTo Address: %S"), &ptrFormatedAddress);
+			
+			// aSentEntry - Identifier of the original sent email identified by TMsvEntry
+			CMsvEntry* msvEntry = aSession->GetEntryL(aSentEntry.Id());
+			CleanupStack::PushL(msvEntry);
+		
+			msvEntry->SetEntryL(aSentEntry.Id());
+			CMsvStore* store = msvEntry->ReadStoreL();
+			CleanupStack::PushL(store);
+					
+			CImHeader* header = CImHeader::NewLC();
+			
+			header->RestoreL(*store);
+			// Read Reply-To address from email header
+			TPtrC usedReplyToAddress = header->ReplyTo();
+		
+			TestCase().INFO_PRINTF2(_L("Reply-To address from actual sent message as stored in the Message store: %S"), &usedReplyToAddress);
+			
+			// Compare if default Reply-To address equals the one set by system in email header
+			if(ptrFormatedAddress.Compare(usedReplyToAddress) !=0)
+				{
+				ret = EFalse;
+				}
+			
+			CleanupStack::PopAndDestroy(header);
+			CleanupStack::PopAndDestroy(store);
+			CleanupStack::PopAndDestroy(msvEntry);
+			CleanupStack::PopAndDestroy(formatedAddress);
+			CleanupStack::PopAndDestroy(popSettings);
+			CleanupStack::PopAndDestroy(popPrefs);
+			CleanupStack::PopAndDestroy(smtpIAP);
+			CleanupStack::PopAndDestroy(settings);
+			CleanupStack::PopAndDestroy(accounts);
+			}
+		return ret;
+	}
+
+/**
+ IsEofL()
+ Checks if the current position of read stream reached end of file
+*/ 
+TBool CMtfTestActionVerifyReplyToAddress::IsEofL(RReadStream& aReadStream)
+	{
+	TStreamPos streamPos = aReadStream.Source()->TellL(MStreamBuf::ERead);
+	TInt streamSize = aReadStream.Source()->SizeL();
+	
+	if(streamPos >= streamSize)
+		return ETrue;
+	
+	return EFalse;
+	}
+
+/**
+ CreateFormattedAddressL()
+ Re-used code from src/common/generic/messaging/email/smtpservermtm/src/imsmsend.cpp#057
+ Creates a new HBufC* containing the concateneatd alias and address strings
+*/
+HBufC* CMtfTestActionVerifyReplyToAddress::CreateFormattedAddressLC(const TDesC& aString, const TDesC& aAlias)
+    {
+    TImMessageField msgField;
+
+    // Make a buffer...
+    TInt strLen     = aString.Length();
+    TInt aliasLen   = aAlias.Length();
+
+    HBufC* outString = HBufC::NewLC(strLen+aliasLen+5);
+    HBufC* buffer = HBufC::NewL(strLen);
+
+    *buffer = msgField.GetValidInternetEmailAddressFromString(aString);
+
+	if (aliasLen)
+        {
+		outString->Des().Format(KSmtpEmailAddressAndAliasFmtStr,&aAlias,buffer);
+        }
+    else
+        {
+        *outString = *buffer; // just copy email address; as there's no alias to be added
+        }
+
+	delete buffer;
+    return outString;
+    }
+