Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


Imap4Example: An Email manager using IMAP4 and SMTP

Found in examples\Messaging\Imap4Example\.

The following sections provide more information about this example application:

[Top]


Description

This example application demonstrates how to create SMTP (Simple Mail Transfer Protocol) and IMAP (Internet Message Access Protocol) accounts to send and receive emails respectively. The application creates dummy messages and sends them using SMTP.

The application starts a session with the messaging server using CMsvSession::OpenSyncL() and gets an instance of the client MTM (Message Type Module) registry using CClientMtmRegistry::NewL(). Using this registry it creates IMAP4 client-side MTM objects for the specified UID.

After creating the client MTM objects, the application creates IMAP4 and SMTP accounts using CEmailAccounts::CreateImapAccountL() and CEmailAccounts::CreateSmtpAccountL() respectively. Settings and preferences for these accounts are configured using the CImImap4Settings, CImIAPPreferences and CImSmtpSettings.

A simple SMTP message is created by the application using the CImEmailOperation::CreateNewL() function, and then sent to the email address stored in the literal KTo.

Note: Each email account created by the application has a pair of service entries, which are used to store settings required for email transport.

The application also provides the CMessAsyncWaiter class to issue asynchronous requests to the messaging server and handles completed requests. This class implements the CActive abstract interface.

[Top]


Pre-requisites

A null modem cable (NTRAS - New Technology Remote Access Services) must be connected to your system for the example to be functional. Also, change the values of literals KSmtpServerAddress and KImapServer defined in the imap4example.cpp file to your system address.

In addition to the above mentioned changes, you must have an account with the messaging server. You can create an account using any messaging proxy server application such as Communigate-Pro, which is freely downloadable from http://www.stalker.com/CommuniGatePro/. The name of the newly created account can either be the account name used by the application or a different one. If you choose to name the new account different from the account name used by the application, change the value of the literal KImapLoginName defined in the imap4example.cpp file to the new account name.

Note: To check the messages sent by the application, you must configure your email client to retrieve messages for the newly created IMAP4 account. For information on how to configure your email client, refer its user guide.

[Top]


Class summary

Related APIs

[Top]


Build

The Symbian OS build process describes how to build an application.

The IMAP4 example builds an executable called impa4Example.exe in the standard location (\epoc32\release\winscw\<build_variant> for CodeWarrior). After launching the executable, depending on the emulator you are using, you may need to task away from the app launcher/shell screen to view the console.

[Top]


Example code


bld.inf

/// BLD.INF
// 
// IMap4ClientMtm
// Copyright (c) Symbian Software Ltd 2005. All rights reserved.
//


PRJ_MMPFILES
imap4example.mmp

imap4example.mmp

// imap4example.mmp
//
// Copyright (c) Symbian Software Ltd 2005. All rights reserved.
//

TARGET          imap4example.exe
TARGETTYPE      exe

UID              0xE80000A7
VENDORID       0x70000001
CAPABILITY       ReadUserData WriteUserData NetworkServices CommDD Location UserEnvironment MultimediaDD ReadDeviceData WriteDeviceData NetworkControl





SOURCEPATH      .
SOURCE          IMAP4EXAMPLE.CPP
SOURCE          ASYNCWAITER.CPP

USERINCLUDE      .
SYSTEMINCLUDE  \Epoc32\include

LIBRARY     euser.lib sendas2.lib efsrv.lib msgs.lib estor.lib imcm.lib
LIBRARY     etext.lib BioDB.lib bifu.lib biut.lib
LIBRARY     bafl.lib charconv.lib commsdat.lib esock.lib commdb.lib        

imap4example.h

// imap4example.h
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//

#ifndef __IMAP4EXAMPLE_H__
#define __IMAP4EXAMPLE_H__

// epoc include
#include <mtclreg.h> 
#include <cemailaccounts.h> 
#include <CommsDatTypesV1_1.h>
using namespace CommsDat;

_LIT(LDD_NAME,"ECOMM");

#if defined (__WINS__)
_LIT(PDD_NAME,"ECDRV");
#else
_LIT(PDD_NAME,"ECUART1");
#endif

/**
CImap4Example is a class that publicly inherits two 
classes, CBase and MMsvSessionObserver. 
CBase is the base class for all classes to be instantiated on the heap. 
MMsvSessionObserver is the interface for notification of events from a Message Server session.
Objects that need to observe a session view should implement this interface.
The class demonstrates the creation of client registry, smtp and imap accounts,
Smtp and imap messages, connection to email server and sending of the message using imap4 protocol.
*/
class CImap4Example :public CBase, public MMsvSessionObserver
    {
public:
    static CImap4Example* NewL();
    ~CImap4Example();
    
    // Overriden function of session event.
    //  Session observer, reports whatever notification it receives.
    void HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3);
    void CreateClientRegistryL();
    void CreateImapAndSmtpAccountL();
    void CreateSmtpMessageL();
    void SendSMTPMessageL();
    void ConnectAndCopyAllMailAndDisconnectL();

private:

    CImap4Example();
    void ConstructL();
    /** Pointer to the console interface */
    CConsoleBase*      iConsole;
    /** Pointer to the Client-side MTM registry*/
    CClientMtmRegistry* iClientRegistry;
    /** Pointer to the channel of communication between a client thread and the Message Server thread*/
    CMsvSession*        iSession;
    /** Pointer to the CBase MTM*/
    CBaseMtm*           iMtm;
    /** Pointer to the CMsvOperation to get progress information about the operation*/
    CMsvOperation*      iOperation;
    /** Imap account Name*/
    TImapAccount        iImapAccount;
    /** Smtp account Name*/
    TSmtpAccount        iSmtpAccount;


    };

#endif //__IMAP4EXAMPLE_H__

imap4example.cpp

// imap4example.cpp
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/**
@file

This is a simple code example that demonstrates the use of 
the IMAP4 protocol to retrieve emails. 
The code creates a simple SMTP mail, sends it 
and then retrieves the same using IMAP4.
*/

#include "imap4example.h"
#include "asyncwaiter.h"
#include <e32cons.h>
#include "imapset.h"
#include "impcmtm.h"
#include <mtclbase.h>
#include <IAPPrefs.h>

_LIT(KTitle, "Imap4example");
_LIT(KTextPressAKey, "\n\n Press any key to step through the example");
_LIT(KExit,"\n\n Press any key to exit the application ");
_LIT(KCreateMtm,"\n\n Creating an IMAP4 client MTM");
_LIT(KTxtAccountName, "ImapAccount");
_LIT(KCreateAccounts,"\n\n Creating IMAP and SMTP acoounts");
_LIT(KSmtpServerAddress, "ban-sindhub01.intra");
_LIT(KEmailAlias, "Messaging example");
_LIT(KSmtpEmailAddress, "[email protected]");
_LIT8(KFrom, "[email protected]");
_LIT(KTo, "[email protected]");
_LIT(KSubject, "SimpleEmail");
_LIT(KBodyContents, "This is a very simple mail");
_LIT(KSendMail,"\n\n Sending the mail ... please wait");
_LIT(KImapServer, "ban-sindhub01.intra");
_LIT8(KImapPassword,"ban-sindhub01");
_LIT8(KImapLoginName,"ban-sindhub01");
_LIT(KWait,"\n\n Connecting to the IMAP server");
_LIT(KPopulate,"\n\n Downloading........");
_LIT(KDisconnect,"\n\n Disconnecting from the IMAP server");

/**
Allocates and constructs a CImap4Example object. 
Initialises all member data to their default values.
*/
CImap4Example* CImap4Example::NewL()
    {
    CImap4Example* self= new (ELeave) CImap4Example();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }

/**
Constructor
*/
CImap4Example::CImap4Example()
    {}

/**
Second phase constructor
*/
void CImap4Example::ConstructL()
    {
    iConsole = Console::NewL(KTitle,TSize(KConsFullScreen,KConsFullScreen));

    iConsole->Printf ( KTextPressAKey );
    iConsole->Getch ();
    }

/**
Destructor
*/
CImap4Example::~CImap4Example()
    {
    iConsole->Printf(KExit);
    iConsole->Getch();
    delete iMtm;
    delete iClientRegistry;
    delete iSession;
    delete iConsole;
    }

/**
Starts a message server session, creates a client side MTM registry 
and IMAP client MTM.
@leave KErrNoMemory
@leave KErrNotFound
@leave KErrBadLibraryEntryPoint
*/
void CImap4Example::CreateClientRegistryL()
    {
    // Create a message server session
    iSession=CMsvSession::OpenSyncL(*this);
    CleanupStack::PushL(iSession);

    // Create a client-side MTM registry
    iClientRegistry=CClientMtmRegistry::NewL(*iSession,KMsvDefaultTimeoutMicroSeconds32);
    if (iClientRegistry != NULL && iClientRegistry->IsPresent(KUidMsgTypeIMAP4))
        {
        CleanupStack::PushL(iClientRegistry);
        }
    // Create a client-side MTM object for the specified MTM UID.
    iMtm=(CImap4ClientMtm*)iClientRegistry->NewMtmL(KUidMsgTypeIMAP4); 
    iConsole->Printf(KCreateMtm);
    CleanupStack::Pop(2,iSession); // iClientRegistry,iSession
    }

/**
Creates an IMAP account and SMTP account. 
It sets the IMAP server address to system address and sets login name and password.
@leave ... System wide error codes
*/
void CImap4Example::CreateImapAndSmtpAccountL()
    {
    CEmailAccounts* emailAccounts = CEmailAccounts::NewLC();
    CImImap4Settings *imap4Settings = new(ELeave)CImImap4Settings;
    CleanupStack::PushL(imap4Settings);

    // Add IAP to the IAP preferences
    CImIAPPreferences* prefs = CImIAPPreferences::NewLC();
    TImIAPChoice iap;
    TInt iapID = 0;
    CMDBSession* dbSession = CMDBSession::NewL(CMDBSession::LatestVersion());
    CleanupStack::PushL(dbSession);
    CCDConnectionPrefsRecord *connPrefRecord = static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
    CleanupStack::PushL(connPrefRecord);

    // Set the direction of connection
    connPrefRecord->iDirection = ECommDbConnectionDirectionOutgoing;
    connPrefRecord->iRanking = 1;
    if(!connPrefRecord->FindL(*dbSession))
        {
        User::Leave(KErrNotFound);
        }
    iapID = connPrefRecord->iDefaultIAP;
    iap.iIAP = iapID;
    iap.iDialogPref = ECommDbDialogPrefDoNotPrompt;
    prefs->AddIAPL(iap);

    emailAccounts->PopulateDefaultImapSettingsL(*imap4Settings, *prefs);

    // Set the server address to system address
    imap4Settings->SetServerAddressL(KImapServer);
    imap4Settings->SetLoginNameL(KImapLoginName); 
    imap4Settings->SetPasswordL(KImapPassword);
    imap4Settings->SetPort(143);

    // Create an IMAP account
    iImapAccount = emailAccounts->CreateImapAccountL(KTxtAccountName, *imap4Settings,*prefs,EFalse);

    CImSmtpSettings *smtpSettings = new (ELeave) CImSmtpSettings();
    CleanupStack::PushL(smtpSettings);

    emailAccounts->PopulateDefaultSmtpSettingsL(*smtpSettings, *prefs);

    // Create an SMTP acoount
    iConsole->Printf(KCreateAccounts);
    iSmtpAccount= emailAccounts->CreateSmtpAccountL(iImapAccount, *smtpSettings, *prefs, EFalse);

    emailAccounts->SetDefaultSmtpAccountL(iSmtpAccount);

    smtpSettings->SetServerAddressL(KSmtpServerAddress);
    smtpSettings->SetEmailAliasL(KEmailAlias);
    smtpSettings->SetEmailAddressL(KSmtpEmailAddress);
    smtpSettings->SetReplyToAddressL(KSmtpEmailAddress);
    smtpSettings->SetReceiptAddressL(KSmtpEmailAddress);
    smtpSettings->SetPort(25);

    emailAccounts->GetSmtpAccountL(iSmtpAccount.iSmtpService, iSmtpAccount);
    emailAccounts->SaveSmtpSettingsL(iSmtpAccount,*smtpSettings);
    emailAccounts->SaveSmtpIapSettingsL(iSmtpAccount, *prefs);

    CleanupStack::PopAndDestroy(6,emailAccounts); //smtpSettings, connPrefRecord, dbSession, prefs, imap4Settings, emailAccounts
    }

/**
Creates an SMTP message, stores and then 
commits settings to a specified message store.
@leave KErrNoMemory
@leave KErrNotFound
@leave KErrAccessDenied
*/
void CImap4Example::CreateSmtpMessageL() 
    {
    TMsvId outboxId = KMsvGlobalOutBoxIndexEntryId; 

    // Set the context to the folder in which message has to be created
    CMsvEntry* entry = CMsvEntry::NewL(*iSession,outboxId,TMsvSelectionOrdering());
    CleanupStack::PushL(entry);
    entry->SetEntryL(outboxId);

    CMessAsyncWaiter* waiter = CMessAsyncWaiter::NewL();
    CleanupStack::PushL(waiter);

    TMsvEmailTypeList msvEmailTypeList = 0;
    TMsvPartList partList = (KMsvMessagePartBody | KMsvMessagePartAttachments);

    CImEmailOperation* emailOperation = CImEmailOperation::CreateNewL(waiter->iStatus, *iSession,KMsvGlobalOutBoxIndexEntryId, partList, msvEmailTypeList, KUidMsgTypeSMTP);
    CleanupStack::PushL(emailOperation);
    waiter->StartAndWait();

    TMsvId temp;
    TPckgC<TMsvId> paramPack(temp);
    const TDesC8& progBuf = emailOperation->ProgressL();
    paramPack.Set(progBuf);
    TMsvId newMessageId;
    newMessageId = paramPack();

    entry->SetEntryL(newMessageId);

    CMsvStore* store = entry->EditStoreL();
    CleanupStack::PushL(store);
    CImHeader* emailEntry = CImHeader::NewLC();
    emailEntry->RestoreL(*store);
    emailEntry->SetFromL((TDesC8&)KFrom);
    emailEntry->SetSubjectL((TDesC&)KSubject);
    emailEntry->ToRecipients().AppendL((TDesC&)KTo);

    // Paragraph format layer for the rich text object 
    CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
    CleanupStack::PushL(paraFormatLayer);
    // Character format layer for the rich text object
    CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL(); 
    CleanupStack::PushL(charFormatLayer);

    CRichText* bodyText = CRichText::NewL(paraFormatLayer, charFormatLayer, CEditableText::EFlatStorage, 256);
    CleanupStack::PushL(bodyText);

    // Insert the contents of a buffer into the document at specified position
    bodyText->InsertL(0, KBodyContents);
    store->StoreBodyTextL(*bodyText);
    emailEntry->StoreL(*store);
    // Store the changes permanently
    store->CommitL();

    CleanupStack::PopAndDestroy(8,entry); // bodyText,charFormatLayer,paraFormatLayer,emailEntry,store,emailOperation,waiter,entry
    }

/**
Accesses the entry with the specified ID. 
Sets the context to the specified entry. 
Sends the created SMTP mail.
@leave KErrNoMemory
@leave KErrNotFound
*/
void CImap4Example::SendSMTPMessageL()
    {
    CMsvEntry* entry = iSession->GetEntryL(iSmtpAccount.iSmtpService);
    CleanupStack::PushL(entry);

    TMsvId outboxId = KMsvGlobalOutBoxIndexEntryId;

    // Create children selection
    TMsvSelectionOrdering order;
    order.SetShowInvisibleEntries(ETrue);
    entry->SetSortTypeL(order);

    entry->SetEntryL(outboxId);
    // Get the  selection containing the IDs of all the context children
    CMsvEntrySelection* selection = entry->ChildrenL();

    // Fetch the ID of the first entry
    TMsvId entryId = KMsvNullIndexEntryId;
    entryId = (*selection)[0];

    delete selection;

    CMessAsyncWaiter* waiter = CMessAsyncWaiter::NewL();
    CleanupStack::PushL(waiter);

    iConsole->Printf(KSendMail);
    // Create asynchronously copies of children of the context
    // as new entries of targetId (smtpServiceId)
    CMsvOperation* operation = entry->CopyL(entryId,iSmtpAccount.iSmtpService, waiter->iStatus);

    CleanupStack::PushL(operation);
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());

    CleanupStack::PopAndDestroy(3, entry); // operation,waiter,entry
    }

/**
Changes the entry on which later actions are performed 
to the entry with the specified TMsvId. 
Connects to the IMAP server. 
Downloads the mail sent using SMTP and disconnects from the service.
@leave KErrNoMemory
@leave KErrNotFound
@leave KErrNotSupported
@leave ... System wide error codes
*/
void CImap4Example::ConnectAndCopyAllMailAndDisconnectL()
    {
    // Change the current context
    iMtm->SwitchCurrentEntryL(iImapAccount.iImapService);
    CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
    CleanupStack::PushL(selection);

    // Append the imapServiceId onto the end of the array
    selection->AppendL(iImapAccount.iImapService);

    TImImap4GetMailInfo imap4GetMailInfo;
    imap4GetMailInfo.iMaxEmailSize = KMaxTInt;
    imap4GetMailInfo.iDestinationFolder = iImapAccount.iImapService+1; // remote inbox
    imap4GetMailInfo.iGetMailBodyParts = EGetImap4EmailBodyText;

    TPckgBuf<TImImap4GetMailInfo> package(imap4GetMailInfo);

    CMessAsyncWaiter* waiter = CMessAsyncWaiter::NewL();
    CleanupStack::PushL(waiter);

    // Connect to the server
    iConsole->Printf (KWait);
    CMsvOperation* operationConnect = iMtm->InvokeAsyncFunctionL(KIMAP4MTMConnect,*selection,package, waiter->iStatus);
    CleanupStack::PushL(operationConnect);

    // Wait on the status
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());

    CMsvOperation* operationSync = iMtm->InvokeAsyncFunctionL(KIMAP4MTMFullSync ,*selection,package, waiter->iStatus);
    CleanupStack::PushL(operationSync);

    // Wait on the status
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());

    CMsvEntry* entry = iSession->GetEntryL(iImapAccount.iImapService);
    CMsvEntrySelection* childrenSelection = entry->ChildrenL();
    TMsvId id = (*childrenSelection)[0];
    selection->AppendL(id);

    // Copy the meassage when already connected
    iConsole->Printf (KPopulate);
    CMsvOperation* operationCopy = iMtm->InvokeAsyncFunctionL(KIMAP4MTMPopulateAllMailWhenAlreadyConnected ,*selection,package, waiter->iStatus);
    CleanupStack::PushL(operationCopy);

    // Wait on the status
    waiter->StartAndWait();

    User::LeaveIfError(waiter->Result());

    // Now disconnect from Imap4 service
    iConsole->Printf (KDisconnect);
    CMsvOperation* operationDis = iMtm->InvokeAsyncFunctionL(KIMAP4MTMDisconnect,*selection,package, waiter->iStatus);
    CleanupStack::PushL(operationDis);

    // Wait on the status
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());
    delete entry;
    delete childrenSelection;

    CleanupStack::PopAndDestroy(6,selection); // operationDis,operationCopy,operationSync,operationConnect,waiter,selection   
    }

/**
Implements the session observer interface to update the registry 
information when MTM groups are installed or uninstalled. 
Invoked by the active object mechanism.
@param aEvent  Event type 
@param aArg1   Event type-specific argument value (unused)
@param aArg2   Event type-specific argument value (unused)
@param aArg3   Event type-specific argument value (unused)
@leave ...   System wide error codes
*/
void CImap4Example::HandleSessionEventL(TMsvSessionEvent /*aEvent*/, TAny* /*aArg1*/, TAny* /*aArg2*/, TAny* /*aArg3*/)
    {}

LOCAL_C void MainL()
    {
    // Create an Active Scheduler to handle asychronous calls
    CActiveScheduler* scheduler = new (ELeave) CActiveScheduler;

    // If Active Scheduler has been created, install it.
    // As it is an asychronous call we need to install it explicitly.
    CActiveScheduler::Install( scheduler );

    CImap4Example* app = CImap4Example::NewL();
    CleanupStack::PushL(app);

    // Create a client registry
    app->CreateClientRegistryL();

    // Create IMAP and SMTP accounts
    app->CreateImapAndSmtpAccountL();

    // Load the physical and logical device drivers.
    // Symbian OS will automatically append .PDD and .LDD
    TInt err;
    err=User::LoadPhysicalDevice(PDD_NAME);
    if (err!=KErrNone && err!=KErrAlreadyExists)
        User::Leave(err);
    err=User::LoadLogicalDevice(LDD_NAME);
    if (err!=KErrNone && err!=KErrAlreadyExists)
        User::Leave(err);

    // Create an SMTP mail to be sent
    app->CreateSmtpMessageL();

    // Send the mail created.
    app->SendSMTPMessageL();

    // Connect, download and disconnect from the IMAP server
    app->ConnectAndCopyAllMailAndDisconnectL();

    CleanupStack::PopAndDestroy(app);

    delete scheduler;
    }

GLDEF_C TInt E32Main()
    {
    __UHEAP_MARK;
    CTrapCleanup* cleanup = CTrapCleanup::New();
    if(cleanup == NULL)
        {
        return KErrNoMemory;
        }
    TRAPD(err, MainL());
    if(err != KErrNone)
        {
        User::Panic(_L("Failed to complete"),err);
        }

    delete cleanup;
    __UHEAP_MARKEND;
    return KErrNone;
    }

MAsyncWaiter.h

// Pop3Example.cpp
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/** 
@file
This is a simple code example that demonstrates the use of the POP3 protocol to retrieve emails.
The code creates a simple SMTP mail, sends it and then retrieves the same using POP. 
*/
#include "pop3Example.h"
#include "MAsyncWaiter.h"

_LIT(KTextPressAKey, "\n\n Press any key to step through the example");
_LIT(KExit,"\n\n Press any key to exit the application ");
_LIT(KCreateMtm,"\n\n Creating a Pop3 client MTM");
_LIT(KKeyPress,"\n\n Press any key");
_LIT(KTxtAccountName, "PopAccount");
_LIT(KCreatePopAccount,"\n\n Creating a Pop account");
_LIT(KCreateSmtpAccount,"\n\n Creating an Smtp account");
_LIT(KSmtpServerAddress, "ban-sindhub01.intra");
_LIT(KEmailAlias, "Messaging example");
_LIT(KSmtpEmailAddress, "[email protected]");
_LIT8(KFrom, "[email protected]");
_LIT(KTo, "[email protected]");
_LIT(KSubject, "SimpleEmail");
_LIT(KBodyContents, "This is a very simple mail");
_LIT(KSendMail,"\n\n Sending the mail... please wait");
_LIT(KPopServer, "ban-sindhub01.intra"); 
_LIT8(KPopPassword,"ban-sindhub01");
_LIT8(KPopLoginName,"ban-sindhub01");
_LIT(KWait,"\n\n Connecting to pop3 server");
_LIT(KDownload,"\n\n Downloading mail from the pop3 server");
_LIT(KDisconnect,"\n\n Press any key to disconnect");
    
/**
Allocates and constructs a CPop3Example object.
Initialises all member data to their default values.
*/  
CPop3Example* CPop3Example::NewL()
    {
    CPop3Example* self = new (ELeave) CPop3Example();
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }
/**
Constructor
*/
CPop3Example::CPop3Example()
    {

    }
    
void CPop3Example::ConstructL()
    {
    iConsole = Console::NewL(KTitle,TSize(KConsFullScreen,KConsFullScreen));
    iConsole->Printf ( KTextPressAKey );
    iConsole->Getch ();
    }

/** 
Destructor
*/
CPop3Example::~CPop3Example()
    {
    iConsole->Printf(KExit);
    iConsole->Getch();
    delete iMtm;
    iMtm = NULL;
    delete iClientRegistry;
    iClientRegistry  = NULL;
    delete ;       
    iSession = NULL;
    delete iConsole;
    }

/**
Starts a message server session, creates a client side mtm registry
and pop client mtm.
@leave KErrNoMemory, KErrNotFound, KErrBadLibraryEntryPoint
*/
void CPop3Example::CreateClientRegistryL()
    {
    // Create a message server session.
    iSession = CMsvSession::OpenSyncL(*this);
    CleanupStack::PushL(iSession);
    iSession->InstallMtmGroup(KDataComponentFileName);
    
    // Create a client-side MTM registry.
    iClientRegistry = CClientMtmRegistry::NewL(*iSession,KMsvDefaultTimeoutMicroSeconds32);
    if (iClientRegistry != NULL && iClientRegistry->IsPresent(KUidMsgTypePOP3))
        {
        CleanupStack::PushL(iClientRegistry);
        }
    // Create a Client-side MTM object for the specified MTM UID.
    iMtm = (CPop3ClientMtm*)iClientRegistry->NewMtmL(KUidMsgTypePOP3); 
    iConsole->Printf(KCreateMtm);
    iConsole->Printf(KKeyPress);
    iConsole->Getch();
    CleanupStack::Pop(2,iSession); //iClientRegistry,iSession
     
    }

/**
Creates a pop account and smtp account.
Sets the pop server address to system address and sets login name and password
@leave system wide error codes
*/
void CPop3Example::CreatePopAndSmtpAccountL()
    {
    CEmailAccounts* emailAccounts = CEmailAccounts::NewLC();
    CImPop3Settings* settings = new(ELeave) CImPop3Settings();
    CleanupStack::PushL(settings);
    
    CImIAPPreferences* popIAP = CImIAPPreferences::NewLC();
    
    // Set the server address to system address
    settings->SetServerAddressL(KPopServer);
    settings->SetLoginNameL(KPopLoginName); 
    settings->SetPasswordL(KPopPassword);
    settings->SetPort(110);
    
    // Create a Pop account
    iConsole->Printf(KCreatePopAccount);
    iPopAccount = emailAccounts->CreatePopAccountL(KTxtAccountName, *settings,*popIAP,EFalse);
    
    CImSmtpSettings *smtpSettings = new (ELeave) CImSmtpSettings();
    CleanupStack::PushL(smtpSettings);

    emailAccounts->PopulateDefaultSmtpSettingsL(*smtpSettings, *popIAP);
   
   // Create an Smtp acoount
    iConsole->Printf(KCreateSmtpAccount);
    iSmtpAccount = emailAccounts->CreateSmtpAccountL(iPopAccount, *smtpSettings, *popIAP, EFalse);
    
    emailAccounts->SetDefaultSmtpAccountL(iSmtpAccount);

    smtpSettings->SetServerAddressL(KSmtpServerAddress);
    smtpSettings->SetEmailAliasL(KEmailAlias);
    smtpSettings->SetEmailAddressL(KSmtpEmailAddress);
    smtpSettings->SetReplyToAddressL(KSmtpEmailAddress);
    smtpSettings->SetReceiptAddressL(KSmtpEmailAddress);
    smtpSettings->SetPort(25);
        
    // Add IAP to the IAP preferences
    CImIAPPreferences* prefs = CImIAPPreferences::NewLC();
    TImIAPChoice iap;
    TInt iapID = 0;
    CMDBSession* dbSession = CMDBSession::NewL(CMDBSession::LatestVersion());
    CleanupStack::PushL(dbSession);
    CCDConnectionPrefsRecord *connPrefRecord = static_cast<CCDConnectionPrefsRecord*>(CCDRecordBase::RecordFactoryL(KCDTIdConnectionPrefsRecord));
    CleanupStack::PushL(connPrefRecord);
    
    // Set the direction of connection
    connPrefRecord->iDirection = ECommDbConnectionDirectionOutgoing;
    connPrefRecord->iRanking = 1;
    if(!connPrefRecord->FindL(*dbSession))
        {
        User::Leave(KErrNotFound);      
        }           
    iapID = connPrefRecord->iDefaultIAP;
    iap.iIAP = iapID;
    iap.iDialogPref = ECommDbDialogPrefDoNotPrompt;
    prefs->AddIAPL(iap);
    
    emailAccounts->GetSmtpAccountL(iSmtpAccount.iSmtpService, iSmtpAccount);
    emailAccounts->SaveSmtpSettingsL(iSmtpAccount,*smtpSettings);
    emailAccounts->SaveSmtpIapSettingsL(iSmtpAccount, *prefs);
    
    CleanupStack::PopAndDestroy(7,emailAccounts); //connPrefRecord,dbSession,prefs,smtpSettings,popIAP,settings,emailAccounts
    }
    
/**
Creates an smtp message,stores and then commits settings to a specified message store.
@leave KErrNoMemory,KErrNotFound,KErrAccessDenied,Standard
*/
void CPop3Example::CreateSmtpMessage() 
    {
     
    TMsvId outboxId = KMsvGlobalOutBoxIndexEntryId; 
        
    // Set the context to the folder in which message has to be created
    CMsvEntry*  entry = CMsvEntry::NewL(*iSession,outboxId,TMsvSelectionOrdering());
    CleanupStack::PushL(entry);
    entry->SetEntryL(outboxId);
    
    CMessAsyncWaiter* waiter = CMessAsyncWaiter::NewL();
    CleanupStack::PushL(waiter);
    
    TMsvEmailTypeList msvEmailTypeList = 0;
    TMsvPartList partList = (KMsvMessagePartBody | KMsvMessagePartAttachments);
    
    CImEmailOperation* emailOperation = CImEmailOperation::CreateNewL(waiter->iStatus, *iSession,KMsvGlobalOutBoxIndexEntryId, partList, msvEmailTypeList, KUidMsgTypeSMTP);
    CleanupStack::PushL(emailOperation);
    waiter->StartAndWait();
    
    TMsvId temp;
    TPckgC<TMsvId> paramPack(temp);
    const TDesC8& progBuf = emailOperation->ProgressL();
    paramPack.Set(progBuf);
    TMsvId newMessageId;
    newMessageId = paramPack();

    entry->SetEntryL(newMessageId);

    CMsvStore* store = entry->EditStoreL();
    CleanupStack::PushL(store);
    CImHeader* emailEntry = CImHeader::NewLC();
    emailEntry->RestoreL(*store);
    emailEntry->SetFromL((TDesC8&)KFrom);
    emailEntry->SetSubjectL((TDesC&)KSubject);
    emailEntry->ToRecipients().AppendL((TDesC&)KTo);
    
    // Paragraph format layer for the rich text object 
    CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
    CleanupStack::PushL(paraFormatLayer);
    // Character format layer for the rich text object
    CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL(); 
    CleanupStack::PushL(charFormatLayer);

    CRichText* bodyText = CRichText::NewL(paraFormatLayer, charFormatLayer, CEditableText::EFlatStorage, 256);
    CleanupStack::PushL(bodyText);

    // Inserts the contents of a buffer into the document at specified position
    bodyText->InsertL(0, KBodyContents);
    store->StoreBodyTextL(*bodyText);
    emailEntry->StoreL(*store);
    // Store the changes permanently
    store->CommitL();
    
    CleanupStack::PopAndDestroy(8,entry); // bodyText,charFormatLayer,paraFormatLayer,emailEntry,store,emailOperation,waiter,entry

    }
    
/**
Accesses the entry with the specified ID.
Sets the context to the specified entry.
Sends the created smtp mail.
@leave KErrNoMemory,KErrNotFound
*/
void CPop3Example::SendSMTPMessage()
    {
    
    CMsvEntry* entry = iSession->GetEntryL(iSmtpAccount.iSmtpService);
    CleanupStack::PushL(entry);

    TMsvId outboxId = KMsvGlobalOutBoxIndexEntryId;
    
    // creating Childrenselection
    TMsvSelectionOrdering order;
    order.SetShowInvisibleEntries(ETrue);
    entry->SetSortTypeL(order);
    
    entry->SetEntryL(outboxId);
    // Get the  selection containing the IDs of all the context children
    CMsvEntrySelection* selection = entry->ChildrenL();

    // Fetch the Id of the first entry
    TMsvId entryId = KMsvNullIndexEntryId;
    entryId = (*selection)[0];
    
    delete selection;

    CMessAsyncWaiter* waiter = CMessAsyncWaiter::NewL();
    CleanupStack::PushL(waiter);
    
    iConsole->Printf(KSendMail);
    // Create asynchronously copies of children of the context 
    // as new entries of targetId (smtpServiceId)
    CMsvOperation*  operation = entry->CopyL(entryId,iSmtpAccount.iSmtpService, waiter->iStatus);

    CleanupStack::PushL(operation);
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());

    CleanupStack::PopAndDestroy(3, entry); //operation,waiter,selection
    }
    
/**
Changes the entry on which later actions are performed to the entry with the specified TMsvId.
Connects to the pop server.
Downloads the mail sent using smtp and disconnects from the service.
@leave KErrNoMemory,KErrNotFound,KErrNotSupported,system wide error codes
*/
void CPop3Example::ConnectDownloadAndDisconnectPOPServerL()
    {
    
    // Change the current context
    iMtm->SwitchCurrentEntryL(iPopAccount.iPopService);

    CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
    CleanupStack::PushL(selection);
    
    // Append the popServiceId onto the end of the array
    selection->AppendL(iPopAccount.iPopService);
        
    TBuf8<1> param;
    
    CMessAsyncWaiter* waiter = CMessAsyncWaiter::NewL();
    CleanupStack::PushL(waiter);
    
    // Attempt to connect to the Pop3 Service 
    iConsole->Printf(KWait);
     CMsvOperation* connectOperation = iMtm->InvokeAsyncFunctionL(KPOP3MTMConnect,*selection,param, waiter->iStatus);
    CleanupStack::PushL(connectOperation);
    
    // wait on the status
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());
    
    // Populate the message
    iConsole->Printf(KDownload);
    CMsvOperation* operationPop = iMtm->InvokeAsyncFunctionL(KPOP3MTMPopulate,*selection,param, waiter->iStatus);
    CleanupStack::PushL(operationPop);
    
    // wait on the status
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());
    
    // Now disconnect from Pop3 service
    CMsvOperation* operationDis = iMtm->InvokeAsyncFunctionL(KPOP3MTMDisconnect,*selection,param, waiter->iStatus);
    CleanupStack::PushL(operationDis);
    
    // wait on the status
    waiter->StartAndWait();
    User::LeaveIfError(waiter->Result());
    iConsole->Printf(KDisconnect);
    iConsole->Getch ();
    
    CleanupStack::PopAndDestroy(5,selection); //operationDis,operationPop,connectOperation,waiter,selection
    }
    
/**
Implements the session observer interface to update the registry information when MTM groups are installed or uninstalled.
Invoked by the active object mechanism.
@param aEvent  Event type 
@param aArg1   Event type-specific argument value (unused)
@param aArg2   Event type-specific argument value (unused)
@param aArg3   Event type-specific argument value (unused)
@leave      System wide error codes
 */
void CPop3Example::HandleSessionEventL(TMsvSessionEvent /*aEvent*/, TAny* /*aArg1*/, TAny* /*aArg2*/, TAny* /*aArg3*/)
    {}

LOCAL_C void MainL()
    {

    // Create an Active Scheduler to handle asychronous calls
    CActiveScheduler* scheduler = new (ELeave) CActiveScheduler;
    /*
    If Active Scheduler has been created, install it .
    As it is an asychronous call we need to install it explicitly.
    */
    CActiveScheduler::Install( scheduler );

    CPop3Example* app = CPop3Example::NewL();
    CleanupStack::PushL(app);
    
    // Create a client registry.
    app->CreateClientRegistryL();
    
    // To Create pop and smtp accounts.
    app->CreatePopAndSmtpAccountL();

    // Load the physical and logical device drivers.
    // Symbian OS will automatically append .PDD and .LDD
    
    TInt err;
    err=User::LoadPhysicalDevice(PDD_NAME);
    if (err!=KErrNone && err!=KErrAlreadyExists)
        User::Leave(err);
    err=User::LoadLogicalDevice(LDD_NAME);
    if (err!=KErrNone && err!=KErrAlreadyExists)
        User::Leave(err);
        
    // Create an Smtp mail to be sent.   
    app->CreateSmtpMessage();
     
    // Send the mail created.
    app->SendSMTPMessage();
    
    // Connect to the pop3 server for downloading the mail and disconnect.
    app->ConnectDownloadAndDisconnectPOPServerL();
    
    CleanupStack::PopAndDestroy(app);

    delete scheduler;

    }

GLDEF_C TInt E32Main()
    {
    __UHEAP_MARK;
    CTrapCleanup* cleanup = CTrapCleanup::New();
    if(cleanup == NULL)
        {
        return KErrNoMemory;
        }
    TRAPD(err, MainL());
    
    if(err != KErrNone)
        {
        _LIT(KUserPanic,"Failed to complete");  
        User::Panic(KUserPanic, err);
        }

    delete cleanup;
    __UHEAP_MARKEND;
    return KErrNone;
    }

MAsyncWaiter.cpp

//  MAsyncWaiter.cpp
// 
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/**
@file
Encapsulates both issuing a request to an asynchronous service provider 
and handling the completed requests.
*/

#include "MAsyncWaiter.h"

/**
 Creates an object of CMessAsyncWaiter
*/  
CMessAsyncWaiter* CMessAsyncWaiter::NewL()
    {
    CMessAsyncWaiter* self = new(ELeave) CMessAsyncWaiter();
    return self;
    }

/**
Adds the active object to the scheduler
*/
CMessAsyncWaiter::CMessAsyncWaiter() : CActive(EPriorityStandard)
    {
    CActiveScheduler::Add(this);
    }   


CMessAsyncWaiter::~CMessAsyncWaiter()
    {
    Cancel();
    }
    
/**
Indicates that the active object has issued a request 
and that it is now outstanding .
*/ 
void CMessAsyncWaiter::StartAndWait()
    {
    SetActive();
    CActiveScheduler::Start();
    }
    

TInt CMessAsyncWaiter::Result() const
    {
    return iError;
    }
    
/**
Handles an active object’s request completion event.
It sets to run the desired task.
*/ 
void CMessAsyncWaiter::RunL()
    {
    iError = iStatus.Int();
    CActiveScheduler::Stop();
    }
    
/**
Implements cancellation of an outstanding request,called as part of the active object's Cancel().
*/
void CMessAsyncWaiter::DoCancel()
    {
    iError = KErrCancel;
    CActiveScheduler::Stop();
    }

[Top]


See also

IMAP4 MTM Overview

SMTP MTM Overview