This example application demonstrates the usage of the SendAs v2 protocol
for sending the messages. It is located in the folder
examples\Messaging\SendAsv2Example\
.
The overview contains the following sections:
The application establishes a session with the SendAs server, sets a message entry, creates a message, sets its body text, adds a recipient, sends the message and closes the session. The sequence of events is detailed in the following:
Create a session the SendAs server using the
CMsvSession::OpenSyncL()
function.
Set the message entry using the
CMsvEntry::SetEntryL()
function, which points to the drafts
folder.
After setting the entry, the application gets a selection
containing the IDs of all the context children, using the
CMsvEntry::ChildrenL()
function.
Connection to the server is made using the default number of
message slots available to a session, which happens to be 4 represented by the
enumerated data type KSendAsDefaultMessageSlots
. This
determines the maximum number of outstanding requests the client may have with
the server at any one time.
The draft folder is emptied, before creating any new message.
Fetch the names and UIDs for the filtered list of message types
using the RSendAs::FilteredMessageTypesL()
function to
create a SendAs message. Then the UID based on the message type is returned,
and with the entry set on the drafts folder a SendAs message is created by
calling the RSendAsMessage::CreateL()
function.
Set a body text for the message and specify the recipients. In
this example, the body text is set using a plain descriptor and the recipients
are added using the RSendAsMessage::AddRecipientL()
function.
The recipient's address is held in a descriptor. The alias is the displayed recipient name.
The recipient type is one of the
TSendAsRecipientType
enumeration values, that is, one of
the following:
ESendAsRecipientTo
- The recipient goes
in the 'To' field.
ESendAsRecipientCc
- The recipient goes
in the 'Cc' field
ESendAsRecipientBcc
- The recipient goes
in the 'Bcc' field
If the 'Cc' field is not supported, the recipient will instead be added to the 'To' field since these are functionally equivalent.
If the 'Bcc' field is not supported, this function will return
KErrNotSupported
.
The example also features the display of names of the accounts present in the list.
To demonstrate this, 3 new accounts are appended and they are displayed
in a for-loop by calling
CSendAsAccounts::AccountNames().MdcaPoint(i)
, where the
MdcaPoint()
function takes in the integer value of the
current iteration in the for-loop and indexes into a descriptor array.
The example also demonstrates how to refine the available message types
of the connected session using the
RSendAs::FilterAgainstCapability()
function.
The RSendAsMessage::SendMessage()
function is used
asynchronously to send the message. Finally the
RsendAs::Close()
function is used to end the session with
SendAs server.
The Symbian OS build process describes how to build an application.
The SendAs example builds an executable called
SendAs2Example.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. Alternatively, adding the string textshell to the emulator
configuration file epoc.ini
causes the emulator to start in text
mode.
// BLD.INF
//
// SendAsExample
// Copyright (c) Symbian Software Ltd 2005. All rights reserved.
//
PRJ_MMPFILES
SendAs2Example.mmp
// SendAs2Example.mmp
//
// Copyright (c) Symbian Software Ltd 2005. All rights reserved.
//
TARGET SendAs2Example.exe
TARGETTYPE exe
UID 0xE80000A9
CAPABILITY ReadDeviceData WriteDevicedata ProtServ NetworkControl NetworkServices LocalServices ReaduserData WriteUserData
SOURCEPATH .
SOURCE SendAs2Example.cpp
USERINCLUDE .
SYSTEMINCLUDE \epoc32\include
LIBRARY euser.lib sendas2.lib efsrv.lib msgs.lib estor.lib
LIBRARY etext.lib bifu.lib biut.lib BioDB.lib
// SendAs2Example.h
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
// @file
// This contains Class CSendAs2Example.
#ifndef __SENDAS2EXAMPLE_H__
#define __SENDAS2EXAMPLE_H__
// epoc include
#include <sendas2.h>
#include <csendasaccounts.h>
#include <csendasmessagetypes.h>
#include <mtmuids.h>
#include <e32cons.h>
#include <msvids.h>
class CDummyObserver;
/**
CSendAs2Example is a class that publicly inherits from CBase.
CBase is the base class for all classes to be instantiated on the heap.
This class demonstrates- creating a session, connecting to
sendAs server to create a message, displaying the list of SendAs accounts present,
Filtering those messages based on capability and sending the message.
*/
class CSendAs2Example : public CBase
{
public:
static CSendAs2Example* NewL();
~CSendAs2Example();
void StartL();
void Connect();
void CreateL(RSendAsMessage& aMessage);
void DisplayAccountL();
void CapabilityFilterL();
void SendL(RSendAsMessage& aMessage);
private:
CSendAs2Example();
void ConstructL();
void CleanMessageFolderL();
private:
/** Pointer to the console interface */
CConsoleBase* iConsole;
RSendAs iSendAs;
/** Pointer to Session observer used to report whatever notification it receives */
CDummyObserver* iObserver;
/** Pointer to the channel of communication between a client thread and the Message Server */
CMsvSession* iSession;
/** Pointer to a particular Message Server entry */
CMsvEntry* iEntry;
/** Pointer to the array of entry IDs */
CMsvEntrySelection* iSelection;
};
/**
CDummyObserver is a client implementation of MMsvSessionObserver.
It is a class that publicly inherits from two classes, CBase and MMsvSessionObserver.
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.
*/
class CDummyObserver : public CBase, public MMsvSessionObserver
{
public:
void HandleSessionEventL(TMsvSessionEvent, TAny*, TAny*, TAny*) {};
};
#endif /*__SENDASEXAMPLE_H__*/
// SendAs2Example.cpp
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/**
@file
This is a simple example that demonstrates the use of the SendAs v2 protocol to send messages
*/
#include "SendAs2Example.h"
_LIT(KBodyText, "You are limited only by your fears. Remember it is attitude, more than aptitude,that determines your altitude");
_LIT(KAddress1, "[email protected]");
_LIT(KAddress3, "[email protected]");
_LIT(KAddress4, "[email protected]");
_LIT(KAlias1, "Alias1");
_LIT(KAlias2, "Alias2");
_LIT(KAccount1, " \n SendAs Account1 \n");
_LIT(KAccount2, " \n SendAs Account2 \n");
_LIT(KAccount3, " \n SendAs Account3 \n");
_LIT(KAccountNames,"\n The list of accounts present are: \n");
_LIT(KTextWelcome, " SendAs2 Example \n");
_LIT(KTextStartApp, "\n Starting the SendAs2 Example application .... \n");
_LIT(KTextPressAKey, "\n Press any key to step through the example .... \n");
_LIT(KTextConn, "\n Connecting to sendAs server .... \n");
_LIT(KTextErrInn, "\n Connection is successful\n");
_LIT(KTextErrOut, "\n\n Connection has failed\n");
_LIT(KTextCreate, "\n Creating a SendAs message .... \n");
_LIT(KTextSend, "\n Sending the sendAs message .... \n");
_LIT(KTextClose, "\n The SendAs message has been sent \n");
_LIT(KPressAnyKey, "\n Press any key.... \n");
_LIT(KExitKey, "\n Press any key to exit the application.... \n");
_LIT(KSmsClient, "SMS Client");
/**
Allocates and constructs a CSendAs2Example object.
Initialises all member data to their default values.
*/
CSendAs2Example* CSendAs2Example::NewL()
{
CSendAs2Example* self = new (ELeave) CSendAs2Example();
CleanupStack::PushL(self);
self->ConstructL();
CleanupStack::Pop();
return self;
}
/**
Constructor
*/
CSendAs2Example::CSendAs2Example()
{
}
/**
Creating a console window
*/
void CSendAs2Example::ConstructL()
{
iConsole = Console::NewL(KTextWelcome,TSize(KConsFullScreen,KConsFullScreen));
iConsole->Printf ( KTextStartApp );
iConsole->Printf ( KTextPressAKey );
iConsole->Getch ();
}
/**
Cleans the application
- closes the sendAs server
- deletes the console window
- deletes all other member variables
*/
CSendAs2Example::~CSendAs2Example()
{
delete iSelection;
iSelection = NULL;
delete iEntry;
iEntry = NULL;
delete iSession;
iSession = NULL;
delete iObserver;
iObserver = NULL;
iSendAs.Close();
delete iConsole;
}
/**
Main function which calls other functions.
Creates a session observer and sets the entry on drafts folder.
Also, gets a selection containing the IDs of all the context children.
@leave KErrNoMemory, system wide error codes
*/
void CSendAs2Example::StartL()
{
iObserver = new(ELeave) CDummyObserver;
iSession = CMsvSession::OpenSyncL(*iObserver);
TMsvId aFolderId = KMsvDraftEntryId;
iEntry = CMsvEntry::NewL(*iSession, aFolderId,
TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone,ETrue));
iSelection = iEntry->ChildrenL();
Connect();
RSendAsMessage message;
CleanMessageFolderL();
CreateL(message);
DisplayAccountL();
CapabilityFilterL();
SendL(message);
}
/**
Creates a session
- based on the time slots
- connects to the server
@leave system wide error codes
*/
void CSendAs2Example::Connect()
{
iConsole->Printf ( KTextConn );
TInt err = iSendAs.Connect(KSendAsDefaultMessageSlots);
if ( err == KErrNone)
{
iConsole->Printf ( KTextErrInn );
}
else
{
iConsole->Printf ( KTextErrOut );
}
}
/**
Clears the message folder passed in the entry before sending any new messages.
*/
void CSendAs2Example::CleanMessageFolderL()
{
TMsvLocalOperationProgress progress;
if (iSelection->Count() > 0)
{
iEntry->DeleteL(*iSelection, progress);
}
}
/**
Creates a SendAs message
@param aMessage An RSendAsMessage reference, used to create a message
*/
void CSendAs2Example::CreateL( RSendAsMessage& aMessage)
{
CSendAsMessageTypes* messageTypes = CSendAsMessageTypes::NewL();
CleanupStack::PushL(messageTypes);
// Filter all MTMs that can send messages.
// This list can be refined by applying filters using FilterAgainstCapability.
iSendAs.FilteredMessageTypesL(*messageTypes);
TUid sendAsMtmUid;
// Returning the message UID based on the message type
// such as 0 for SMTP Client, 1 for SMS Client
// 2 for Infrared client MTM and 3 for Bluetooth client MTM.
sendAsMtmUid = messageTypes->UidFromNameL(KSmsClient);
CleanupStack::PopAndDestroy(messageTypes);
iConsole->Printf ( KTextCreate );
TInt count = iSelection->Count();
iEntry->SetEntryL(KMsvDraftEntryId);
aMessage.CreateL(iSendAs, sendAsMtmUid);
// Set the body text of this message using a plain descriptor.
// The object must have an open message to use this method.
aMessage.SetBodyTextL(KBodyText);
// Add recipients to this message.
aMessage.AddRecipientL(KAddress1, KAlias1, RSendAsMessage::ESendAsRecipientTo);
aMessage.AddRecipientL(KAddress3, RSendAsMessage::ESendAsRecipientCc);
aMessage.AddRecipientL(KAddress4, KAlias2, RSendAsMessage::ESendAsRecipientCc);
CMsvEntry* entry = CMsvEntry::NewL(*iSession, KMsvDraftEntryId,
TMsvSelectionOrdering(KMsvNoGrouping,EMsvSortByNone,ETrue));
CleanupStack::PushL(entry);
// Sets the context to the specified entry.
entry->SetEntryL(KMsvDraftEntryId);
if(iSelection->Count() >= 1)
{
entry->SetEntryL((*iSelection)[0]);
};
CleanupStack::PopAndDestroy(entry);
}
/**
Displays the names of all the available accounts.
Creates accounts, if not already created.
*/
void CSendAs2Example::DisplayAccountL()
{
CSendAsAccounts* accounts = CSendAsAccounts::NewL();
CleanupStack::PushL(accounts);
// Append 3 new accounts and associated name pair.
if(accounts->Count()==0)
{
accounts->AppendAccountL(KAccount1, 0xaaaaaaaa);
}
if(accounts->Count()==1)
{
accounts->AppendAccountL(KAccount2, 0x55555555);
}
if(accounts->Count()==2)
{
accounts->AppendAccountL(KAccount3, 0x22222222);
}
iConsole->Printf( KAccountNames );
iConsole->Printf ( KPressAnyKey );
iConsole->Getch ();
// Display the array of names of accounts for this message type
for(TInt i = 0; i < 3; i++)
{
TPtrC array = accounts->AccountNames().MdcaPoint(i);
iConsole->Printf( array );
}
CleanupStack::PopAndDestroy(accounts);
}
/**
Refines the connected session's available message types.
Applying a filter will remove all mtms which do not support the supplied capability
@leave system wide error codes
*/
void CSendAs2Example::CapabilityFilterL()
{
// Get a list of MTMs available to send the message
// By specifying the features that the MTMs must have.
// Eg: set filter to test that KUidMtmQueryMaxBodySize >= bodySize
User::LeaveIfError(iSendAs.FilterAgainstCapability(KUidMtmQuerySupportAttachments));
User::LeaveIfError(iSendAs.FilterAgainstCapability(KUidMtmQueryMaxBodySize, 0x10, RSendAs::ESendAsGreaterThan));
User::LeaveIfError(iSendAs.FilterAgainstCapability(KUidMtmQuerySupportedBody, KMtm16BitBody, RSendAs::ESendAsBitwiseAnd));
User::LeaveIfError(iSendAs.FilterAgainstCapability(KUidMtmQuerySupportedBody, KMtm16BitBody, RSendAs::ESendAsBitwiseAnd));
User::LeaveIfError(iSendAs.FilterAgainstCapability(KUidMtmQuerySupportSubject));
User::LeaveIfError(iSendAs.FilterAgainstCapability(KUidMtmQuerySupportsFolder));
User::LeaveIfError(iSendAs.FilterAgainstCapability(KUidMtmQueryMaxRecipientCount));
}
/**
Sends the sendAs2 message
@param aMessage An RSendAsMessage reference, used to send a message
*/
void CSendAs2Example::SendL(RSendAsMessage& aMessage)
{
iConsole->Printf ( KTextSend );
iConsole->Printf ( KPressAnyKey );
iConsole->Getch ();
CMsvOperationWait* wait = CMsvOperationWait::NewLC();
wait->iStatus = KRequestPending;
wait->Start();
// Asynchronously send the message.
// This will only be allowed to happen if the caller
// holds sufficient capabilities to perform this action.
// If the caller does not hold these capabilities, then
// the message send will be automatically demoted to a confirmed send.
aMessage.SendMessage(wait->iStatus);
CleanupStack::PopAndDestroy(wait);
iConsole->Printf ( KTextClose );
iConsole->Printf ( KExitKey );
iConsole->Getch ();
}
LOCAL_C void MainL()
{
// Creates an Active Scheduler to handle asychronous calls.
CActiveScheduler* scheduler = new (ELeave) CActiveScheduler;
/*
If an Active Scheduler has been created, installs it .
As it is an asychronous call we need to install it explicitly.
*/
CActiveScheduler::Install( scheduler );
CSendAs2Example* app = CSendAs2Example::NewL();
CleanupStack::PushL(app);
// Calls the main function in which other functions are called.
app->StartL();
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;
}
// Makmake-generated uid source file
#include <e32cmn.h>
#pragma data_seg(".SYMBIAN")
__EMULATOR_IMAGE_HEADER2(0x1000007a,0xe80000a9,0x00000000,EPriorityForeground,0x0001e530u,0x00000000u,0x00000000,0,0x00010000,0)
#pragma data_seg()
To create advanced applications using the SendAs API refer to the complete SendAs v2.0 API reference documentation, which details all the features of the API.