Symbian
Symbian OS Library

SYMBIAN OS V9.3

[Index] [Spacer] [Previous] [Next]



Messaging v9.1 Platform Security Migration

This page describes how to update software that uses the messaging APIs from previous releases to work with Symbian OS v9.1. The changes described are a consequence of introducing Platform Security. These changes break both source and binary compatibility, and include the addition and removal of APIs.

Note. Some messaging APIs require the caller to have certain security capabilities. For a description, see Platform Security in the OS Guide.

This page covers the following topics:


Messaging Clients

v9.1 changes the messaging client APIs in two major areas: attachment handling and configuration settings. The following sections, for each of these areas, give an overview of the messaging framework changes, and then discuss the impact on particular MTMs.

This section describes:

[Top]


Attachment handling

In previous versions of messaging, clients could use the HasDirectoryL() and GetFilePath() functions of CMsvEntry and CMsvServerEntry to directly read and write to the directories where attachment files for messages were stored.

From v9.1, the message store is moved to a file system location that is private to the message server, which means that these APIs can no longer have direct access to these directories. Clients that handle attachments must move to using a new attachment manager class MMsvAttachmentManager.

An attachment manager object for a message entry can be obtained from the entry's store (CMsvStore) object (shown below). Some MTMs, such as email, provide higher-level APIs that supply an attachment manager to the client, so that the client does not need to directly access the store object.

MMsvAttachmentManager provides member functions for creating, removing, and retrieving attachments for a message entry. Information about an attachment is encapsulated in a CMsvAttachment object.

The API permits an attachment to be one of three types (defined in CMsvAttachment::TMsvAttachmentType()):

MMsvAttachmentManager defines the functions AddAttachmentL(), AddLinkedAttachmentL() and AddEntryAsAttachmentL() to add attachments for each of these types. Additionally, a CreateAttachmentL() function creates a new attachment file into which the client can write.

Every attachment is given an ID (unique within the scope of the message entry) by the attachment manager by which it can be referenced. Attachments may also have the following attributes:

Additionally, a set of MIME headers can be associated with an attachment. This is done through a CMsvMimeHeaders class, which represents a number of common MIME headers in a single object. The MIME header data can be associated with an attachment and stored and restored using the CMsvMimeHeaders::StoreL() and CMsvMimeHeaders::RestoreL() member functions.

In addition to these standard attributes, additional information can be stored for attachments with a message (see CMsvAttachment::SetDesC8AttributeL() and CMsvAttachment::SetIntAttributeL()). For example, the OBEX MTM stores OBEX headers with each attachment.

The following sections illustrate some of the key uses of the API to create, retrieve, and remove attachments:


Adding attachments

The following code adds a file attachment, and sets its description (just the file name in this case) and size attributes.

Note: All the MMsvAttachmentManager functions that modify the attachments for an entry are asynchronous, so should be called as part of an active object request function.

/* Active object request function to add an attachment.  
Arguments: 
    aEntry – entry to make attachment for  
    aAttachPath – path to file to attach 
    aSize – size of attachment in bytes 
*/ 
void CFoo::AttachFileL(CMsvEntry& aEntry, const TFileName& aAttachPath, TInt aSize) 
    {
    // get attachment manager from the entry's store 
    iStore = aEntry.EditStoreL(); 
    MMsvAttachmentManager& attachMan = iStore->AttachmentManagerL();
 
    // create a new attachment attributes object 
    CMsvAttachment* attachmentInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); 
    CleanupStack::PushL(attachmentInfo);
 
    // set the attachment name and size attributes 
    TParse fparse; 
    User::LeaveIfError(fparse.Set(aAttachPath,NULL,NULL)); 
    attachmentInfo->SetAttachmentNameL(fparse.NameAndExt()); 
    attachmentInfo->SetSize(aSize);
 
    // add the attachment 
    attachMan.AddAttachmentL(aAttachPath, attachmentInfo, iStatus); 

    // ownership of attachmentInfo is transferred to attachMan, so don't delete 
    CleanupStack::Pop(attachmentInfo);
    SetActive(); 
    }

The associated RunL should commit the store on successful completion:

iStore->CommitL();


Retrieving attachments

The following code uses the MMsvAttachmentManager AttachmentCount() and GetAttachmentInfoL() functions to get each attachment for a message entry in turn. It then calls the various CMsvAttachment accessor functions to get the attachment attributes, and to access the attachment file itself:

// get store for entry 
CMsvStore* store = entry->ReadStoreL(); 
CleanupStack::PushL(store); 

// get number of attachments 
TInt numAttach = attachMan.AttachmentCount(); 

// loop through attachments 
for (int i=0; i<numAttach; i++) 
    {
    // get attachment attributes for indexed attachment 
    CMsvAttachment* attachInfo = attachMan.GetAttachmentInfoL(i); 
    CleanupStack::PushL(attachInfo);
 
    // get attachment's name 
    const TDesC& attachName = attachInfo->AttachmentName(); 

    // get attachment's size 
    TInt attachSize = attachInfo->Size(); 

    // get attachment's type, and test if it's of a file type 
    CMsvAttachment::TMsvAttachmentType attachType = attachInfo->Type(); 
    TBool fileTypeAttachment = (attachType == CMsvAttachment::EMsvFile || attachType == CMsvAttachment::EMsvLinkedFile);

    // get attachment's filepath, if attachment is of a file type
    if (fileTypeAttachment) 
        {
        const TDesC& attachPath = attachInfo->FilePath(); 
        }

    // get MIME type 
    const TDesC8& attachMType = attachInfo->MimeType(); 

    // get completeness flag 
    TBool complete = attachInfo->Complete(); 

    // get attachment file, if attachment is of a file type 
    if (fileTypeAttachment) 
        {
        RFile attachFile = attachMan.GetAttachmentFileL(i); 

        // ... do something with attachment, then tidy up 
        attachFile.Close(); 
        }
    CleanupStack::PopAndDestroy(attachInfo); 
    }
CleanupStack::PopAndDestroy(store);


Removing attachments

The following code removes an attachment from a message, using MMsvAttachmentManager::RemoveAttachmentL().

/* Active object request function to remove specified attachment. 
Arguments: 
    aEntry – entry from which to remove attachment 
    aNum – index of attachment to remove 
    */ 
void CFoo::RemoveAttachL(CMsvEntry& aEntry, TInt aNum) 
    {
    // get attachment manager from the entry's store 
    iStore = aEntry.EditStoreL(); 
    MMsvAttachmentManager& attachMan =
    iStore->AttachmentManagerL(); 

    // remove attachment with index aNum 
    attachMan.RemoveAttachmentL(aNum,iStatus); 

    SetActive(); 
    }

The associated RunL should commit the store:

iStore->CommitL();

[Top]


Email MTM attachment handling

This section describes how the email (POP/SMTP/IMAP) MTM (CImEmailMessage) API changes for attachment handling.


CImEmailMessage

CImEmailMessage previously had functions to add, retrieve, and remove attachments. Clients should now use the attachment manager API for these tasks. To get an attachment manager, use the new CImEmailMessage function:

MMsvAttachmentManager& AttachmentManager()

Details of the now deprecated functions and the equivalent to migrate to are given below:

Previous CImEmailMessage function

Migrate to

AttachmentSelection()

Use MMsvAttachmentManager::AttachmentCount() and MMsvAttachmentManager::GetAttachmentInfoL() to get CMsvAttachment objects.

Instead of getting attributes from TImAttachmentInfo, use CMsvAttachment.

GetAttachmentName()

Use CMsvAttachment::AttachmentName()

AddAttachmentL()

MMsvAttachmentManager::AddAttachmentL()

AddMessageAsAttachmentL()

MMsvAttachmentManager::AddEntryAsAttachmentL()

DeleteAttachmentL()

MMsvAttachmentManager::RemoveAttachmentL()

DeleteAttachedMessageL()

MMsvAttachmentManager::RemoveAttachmentL()

[Top]


MHTML body part access

MImURITranslator defines member functions, implemented in CImEmailMessage, for getting the attachment file corresponding to a relative URI in a MHTML message. From v9.1, the class has a new member function GetUniversalResourceIdentifierFileHandle(), which returns a file handle to the referenced file.


POP3 and IMAP4 Client MTMs

From v9.1 the client MTM (CBaseMtm) changes, and the CreateAttachmentL() and DeleteAttachmentL() functions are deprecated, and are replaced with new overloads of CreateAttachmentL(), CreateLinkedAttachmentL() and CreateMessageAttachmentL() functions. All the functions are implemented for the SMTP Client MTM.

For the POP3 and IMAP4 Client MTMs, the new functions are implemented to leave with KErrNotSupported.

[Top]


OBEX MTM attachment handling

The handling of attachments for the OBEX MTMs (infrared and Bluetooth) has changed, and clients should migrate to using the new API as discussed in the following sections:


Copied attachments

Previously, to add an attachment, a client created an attachment entry and added the attachment file directly to a directory under the attachment entry. A separate attachment entry was required for each attachment file.

Clients should now instead:

  1. Get an attachment manager (MMsvAttachmentManager) for the message entry, using CMsvStore::AttachmentManagerL().

  2. Use MMsvAttachmentManager::AddAttachmentL() to add attachments

  3. Commit the store.


Linked attachments

Previously, the OBEX MTM had special support for adding attachments as linked files, consisting of the following CObexClientMtm functions:

and the utility class CObexMtmFileNameExternaliser. These are now all deprecated, and clients should instead:

  1. Get an attachment manager (MMsvAttachmentManager) for the entry, using CMsvStore::AttachmentManagerL().

  2. Use MMsvAttachmentManager::AddLinkedAttachmentL() to add linked attachments

  3. To add headers to an attachment, use the new member function CObexHeaderList::ExportToAttachmentL(). Headers can be retrieved using the new member function CObexHeaderList::ImportFromAttachmentL().


OBEX client MTM

From v9.1 the client MTM (CBaseMtm) changes, and the CreateAttachmentL() and DeleteAttachmentL() functions are deprecated, and are replaced with new overloads of CreateAttachmentL(), and the CreateLinkedAttachmentL() and CreateMessageAttachmentL() functions.

For the OBEX client MTMs, the default implementations of these functions are available, except for CreateMessageAttachmentL(), which leaves with KErrNotSupported.

[Top]


Configuration settings

Previously, configuration settings, such as email account information, were stored in a message store file associated with a service entry. This has changed for two platform security related reasons:

To eliminate these risks, the settings information is now stored in the Central Repository (which always remains on the device.) The use of the Central Repository is transparent to clients, which access the settings information through wrapper APIs provided by the MTMs.

[Top]


Default service settings

Previously, the CMsvDefaultServices class could be used to access a list of default services per MTM. This list was stored in a message store. This class is now deprecated, and new functions provided in CBaseMtm to get, change and remove default service IDs:

virtual TMsvId DefaultServiceL() const; 
virtual void RemoveDefaultServiceL(); 
virtual void ChangeDefaultServiceL(const TMsvId& aService); 

Note: Email (see below) provides functions in the higher level CEmailAccounts API for managing default accounts.

[Top]


Email settings

CEmailAccounts has been changed in v9.1, so that the creation of IMAP and POP accounts is now separate from the creation of SMTP accounts (used to push or send mail).

The new class allows messaging clients to create, retrieve, edit, and delete email accounts. Account creation and deletion are described further in:

The old TPOP3AccountId API is replaced with TPopAccount and TSmtpAccount.

The old TIMAP4AccountId API is replaced with TImapAccount and TSmtpAccount.

An account encapsulates:

Clients previously used store/restore functions on these settings objects to access and save settings in a message store object associated with a service entry. These store/restore functions are now deprecated, and clients should use instead the CEmailAccounts functions:

where <protocol> is one of the following, depending on the function:

The new simple classes, TPopAccount, TImapAccount and TSmtpAccount are used with these functions to identify particular accounts.

The notion of default IMAP and POP accounts has been removed (along with any associated APIs), only SMTP has a default account, which can be manipulated with these functions:

Licensees can customize default account settings used for a phone by editing the central repository initialisation files (in common\generic\messaging\email\clientmtms\group\).

For more details, see Interface breaks for Device provisioning, ECOM, EZlib, Graphics services, Java, Log engine, Messaging, Multimedia, and Networking.


Creating email accounts

The following example code creates a new IMAP email account. The account uses the default settings and IAP preferences, apart from the login name and password, which are set explicitly.

// create settings objects
CImImap4Settings* imapSet = new (ELeave) CImImap4Settings; 
CleanupStack::PushL(imapSet); 
CImIAPPreferences* imapIap = CImIAPPreferences::NewLC(); 

// populate the setting objects with default values 
CEmailAccounts* account = CEmailAccounts::NewLC(); 
account->PopulateDefaultIMAPSettingsL(*imapSet, *imapIap); 
                
// update settings 
imapSet->SetLoginNameL(KLoginName); 
imapSet->SetPasswordL(KPassword); 

// create IMAP account 
TImapAccount imapAccount = account->CreateIMAPAccountL(accountName, *imapSet, *imapIap, EFalse); 
CleanupStack::PopAndDestroy(3);


Retrieving email accounts

To iterate through all accounts, you can get a list of identifiers using Get<protocol>AccountsL. For example:

CEmailAccounts* accounts = CEmailAccounts::NewLC(); 
RArray<TPOPAccount> popAccounts; 
CleanupClosePushL(popAccount); 
accounts->GetPOPAccountsL(popAccount); 

See Email Settings for a list of <protocol>.

[Top]


SMS (GSM) settings

The new CSmsAccount class enables messaging clients to edit the SMS account settings (there is expected to be only one account on a device). Clients previously used store/restore functions on the CSmsSettings objects to access and save settings in a message store object associated with a service entry. These store/restore functions are now deprecated, and clients should use instead the CSmsAccount functions.

The following example loads the existing account settings, does an update, and saves the settings.

// load existing settings 
CSmsSettings* smsSet = CSmsSettings::NewLC(); 
CSmsAccount* account = CSmsAccount::NewLC(); 
account->LoadSettingsL(*smsSet);

// update settings 
smsSet->SetReplyQuoted(ETrue); 

// save settings 
account->SaveSettingsL(*smsSet); 
CleanupStack::PopAndDestroy(2);

The rest of this section describes:


Service centre configuration

The SMS settings can hold a configuration for one or more SMS service centres. Previously, the configured service centres could be accessed through CSmsSettings member functions, which encapsulated the service centre address in a CSmsNumber object. These functions are now deprecated, and clients should use instead a new set of CSmsSettings member functions, as listed below:

Previous function

Migrate to

NumSCAddresses

ServiceCenterCount

SCAddress

GetServiceCenter

AddSCAddressL

AddServiceCenterL

RemoveSCAddress

RemoveServiceCenter

DefaultSC

DefaultServiceCenter

SetDefaultSC

SetDefaultServiceCenter

SMS service centre details are now encapsulated in CSmsServiceCenter objects, and the new functions now access these objects.

The following code loads the service settings, and gets the details for each configured service centre.

// load settings 
CSmsSettings* smsSet = CSmsSettings::NewLC(); 
CSmsAccount* account = CSmsAccount::NewLC(); 
account->LoadSettingsL(*smsSet); 

// loop through service centres 
TInt numSC = smsSet->ServiceCenterCount(); 
for (int i=0; i<numSC; i++) 
    {
    // get centre details 
    CSmsServiceCenter& sc = smsSet->GetServiceCenter(i); 
    // get name and address of the centre 
    TPtrC address = sc.Address(); 
    TPtrC name = sc.Name(); 
    }


Scheduled send

An SMS service can have configuration settings that control the scheduled sending of messages. These configuration settings are in four parts:

Storing Settings

These settings were previously stored in the SMS service entry using RestoreL/StoreL functions on the above classes. These functions are now deprecated, and clients should use the new CSmsAccount functions to initialise and edit the settings:

The following example loads the scheduled send settings, updates one of the parameters, and saves the updated settings.

// create an SMS account object 
CSmsAccount *smsAccount = CSmsAccount::NewLC(); 

// create objects for schedule send settings 
CMsvSysAgentActions *sysAgtActions = new (ELeave) CMsvSysAgentActions; 
CleanupStack::PushL(sysAgtActions); 
CMsvSendErrorActions *sendErrorActions = CMsvSendErrorActions::NewLC(); 
CMsvOffPeakTimes *offPeakTimes = new (ELeave) CMsvOffPeakTimes; 
CleanupStack::PushL(offPeakTimes); 
CMsvScheduleSettings *scheduleSettings = CMsvScheduleSettings::NewLC(); 

// load the schedule send settings 
smsAccount->LoadSettingsL(*scheduleSettings, *offPeakTimes, *sendErrorActions, *sysAgtActions); 
                
// do an update 
TTimeIntervalSeconds interval(5); 
scheduleSettings->SetShortInterval(interval); 

// save updated settings 
smsAccount->SaveSettingsL(*scheduleSettings, *offPeakTimes, *sendErrorActions, *sysAgtActions); 
                
CleanupStack::PopAndDestroy(5);

System Agent to Publish and Subscribe

The System Agent component is removed from v9.1. This causes a change in the TMsvSysAgentConditionAction class, which encapsulates a condition that must be satisfied before a message sending attempt.

The TMsvSysAgentConditionAction::iCondition member changes from being a system agent condition, TSysAgentCondition, to being of a new type, TMsvCondition. This defines a condition that a Publish and Subscribe property must satisfy.

Clients should identify the Publish and Subscribe property that is equivalent to the System Agent condition that was previously used, and change their code to set a TMsvCondition object appropriately.

This is a source compatible break with no migration path (all 9.0 clients must change regardless of the configuration macro settings).

[Top]


OBEX settings

An OBEX (Bluetooth/infrared) MTM service previously had one setting, a password, which was accessed using CObexClientMtm::SetPasswordL() and GetPasswordLC.

From v9.1, these functions are deprecated, and no replacement member functions are provided.

[Top]


Message store directory access

From v9.1, the message server's message store, previously located in \System\Mail\, is private to the message server, and its files cannot be directly accessed by other applications. This may cause changes for clients in the following areas:


Message store current drive

Previously, clients could use MessageServer class functions to get the current message store drive and to test if there is a mail store on a particular drive. These functions now require that the caller has the AllFiles security capability, or is running in the message server process. From v9.1, clients should use these new functions instead:


Copying and deleting message stores

Previously, an application could copy or delete the store using file system functions. This is not possible in v9.1, and clients should instead use the following new functions on CMsvSession:


Checking for corrupt mail stores

Previously, a phone's messaging application could check if the message server had deleted a corrupt message store on start-up by checking if the file \System\Mail\storedeleted.tmp existed.

From v9.1, this is not possible, and applications should use instead the function CMsvSession::GetAndClearIndexCorruptFlagL().

[Top]


MTM Providers

This section discusses how authors of message type module (MTM) plugins should migrate to v9.1. It covers:

[Top]


MTM Capabilities

MTMs are DLLs, and must therefore follow the general rule for DLLs under platform security that a process cannot load a DLL with a smaller set of capabilities than itself. Client-side, UI Data, and User Interface MTM DLLs are loaded by email client processes. To make these DLLs available to all clients, it should have the maximum capabilities, as follows:

CAPABILITY All -TCB

Server-side MTMs are loaded by the message server, and must have the capabilities that it requires, as follows:

CAPABILITY ReadDeviceData WriteDevicedata ProtServ NetworkControl NetworkServices LocalServices ReaduserData 

[Top]


MTM registration resource file

The following aspects of the MTM's registration resource file must change:


File location

Because of the altered file system layout for data caging, the location of an MTM's registration resource file must change to be in the resource\messaging\mtm directory. This can be done by changing the mmp file that builds the registration file as follows:

#ifdef             __SECURE_DATA__ 
START RESOURCE txtmtm.rss 
TARGETPATH      resource\messaging\mtm 
END 
#else 
RESOURCE            txtmtm.rss 
#endif          // __SECURE_DATA__ 

This uses the __SECURE_DATA__ macro, which is defined for v9.1, to conditionally put the compiled registration resource file in the correct location.


MTM info

The main resource, MTM_INFO_FILE, used to describe the MTM properties has changed for v9.1. To update your resource file, change the MTM_COMPONENT structure members to be MTM_COMPONENT_V2, and for each structure:

version = VERSION_V2 {};

For example,

MTM_COMPONENT_V2 
    {
    human_readable_name = "TextMTM server MTM"; 
    component_uid = KUidMtmServerComponentVal; 
    entry_point = 1; 
    version = VERSION_V2 {}; 
    filename = "txts.dll"; 
    }

The reason for these changes is that with platform security, the message server cannot scan the protected system binary directory for files with a particular UID.

Remember that if you want to be able to use the same resource file with both v9.1 and pre-v9.1 OS releases, you can use macro conditionals, such as

#ifdef __MESSAGING_API_V2__ 
.... 
#endif 

within the resource file.


Security capability specification

With the introduction of platform security, individual MTMs are required to specify the additional security capabilities that messaging clients require in order to send messages by that MTM. These capabilities must be set in the registration resource file that describes the MTM's properties.

This is done using the new resource structure MTM_SECURITY_CAPABILITY_SET. This has a single array member capabilities that specifies the required capabilities: each value should be a capability as defined in TCapability in e32capability.h. For example, this resource specifies that the client must have the local services (e.g. Bluetooth) capability:

RESOURCE MTM_SECURITY_CAPABILITY_SET 
    {
    capabilities = { ECapabilityLocalServices }; 
    }

An MTM_SECURITY_CAPABILITY_SET must be the third resource in the registration file (following the MTM_INFO_FILE and MTM_CAPABILITIES resources), even if the MTM requires no additional capabilities to be defined.

This means if the resource does not already define an MTM_CAPABILITIES structure, it must now do so. MTM_CAPABILITIES has nothing to do with platform security, but specifies flags used by SendAs. If the MTM can support SendAs, it should define the resource as:

RESOURCE MTM_CAPABILITIES 
    {
    send_capability=1; 
    body_capability=1; 
    }

If the MTM doesn't support SendAs, use the following:

RESOURCE MTM_CAPABILITIES 
    {
    }

[Top]


UI resources

UI and UI Data MTMs have resource files to specify their UI resources. Previously, these were built to the \system\data directory. From v9.1, this should be changed to \resource\messaging\, e.g.:

START RESOURCE     txti.rss 
HEADER 
#ifdef              __SECURE_DATA__ 
TARGETPATH          \resource\messaging 
#else 
TARGETPATH          \system\data 
#endif              // __SECURE_DATA__ 
END

MTMs implement the GetResourceFileName functions on CBaseMtmUiData and CBaseMtmUi to pass the path of the resource files to the framework. From v9.1, the framework will assume the file is in z:\resource\messaging\ unless a path to another location is specified.

UI Data MTMs typically also build an mbm file. You should also change the mmp file to build this to \resource\messaging\.

If the UI Data MTM calls CBaseMtmUiData::CreateBitmapsL(), change the call to specify the new path of the mbm file.

[Top]


SendAs support

The SendAs API has changed for platform security (see SendAs Clients), and the MTM APIs change in a number of areas to support this, as explained in the following sections:


Attachment support

As seen above, platsec changes the way that the messaging framework handles attachments. CBaseMtm has attachment handling functions, intended for use by the SendAs API, which also change. If your MTM overrides the default implementation of these functions, you will need to change your MTM implementation.

These functions are deprecated:

IMPORT_C virtual void CreateAttachmentL(TMsvId& aAttachmentId, TFileName& aDirectory); 
IMPORT_C virtual void DeleteAttachmentL(TMsvId aMessageId, TMsvId aAttachmentId);

These new functions handle attachments. They include the new TUint aCharset parameter, which provides the IANA character set:

virtual void AddAttachmentL(const TDesC& aFilePath, const TDesC8& aMimeType, const TUint aCharset, TRequestStatus& aStatus);
virtual void AddAttachmentL(RFile& aFile, const TDesC8& aMimeType, const TUint aCharset, TRequestStatus& aStatus); 
virtual void AddLinkedAttachmentL(const TDesC& aFilePath, const TDesC8& aMimeType, const TUint aCharset, TRequestStatus& aStatus); 
virtual void CreateAttachmentL(const TDesC& aFileName, RFile& aAttachmentFile, const TDesC8& aMimeType, const TUint aCharset, TRequestStatus& aStatus);  

There is no replacement for DeleteAttachmentL(), as the new SendAs API does not require this function.


Address type support

The CBaseMtm API previously had no generic support for specifying whether addresses are of To:, Cc:, or Bcc: types. To enable this, the following functions are added:

void CBaseMtm::AddAddresseeL(TMtmRecipientType aType, const TDesC& aRealAddress) 
void CBaseMtm::AddAddresseeL(TMtmRecipientType aType, const TDesC& aRealAddress, const TDesC& aAlias) 

where TMtmRecipientType is a flag indicating the address type. The default implementation for these functions is to leave with KErrNotSupported. MTMs that support address types should implement these functions. To support this, the CBaseMtm::iAddresseeList data member has changed from being a plain string array into a new list type, CBaseMtmRecipientList, which allows the address type to be stored together with the address itself. The AddresseeList() function has changed to return a const CBaseMtmRecipientList& rather than a const CDesCArray&.

The new functions, as well as the existing AddAddresseeL() overloads, can be implemented to append to this list, e.g.:

// existing overload, assume default is use a To address type 
void CFooClientMtm::AddAddresseeL(const TDesC& aRealAddress)  
    {
    iAddresseeList->AppendL(EMtmRecipientTo, aRealAddress); 
    }
    
// existing overload, assume default is use a To address type 
void CFooClientMtm::AddAddresseeL(const TDesC& aRealAddress, const TDesC& aAlias) 
    {
    AddAddresseeL(EMtmRecipientTo, aRealAddress, aAlias); 
    }
    
// new overload specifying address type (no alias) 
void CFooClientMtm::AddAddresseeL(TMtmRecipientType aType, const TDesC& aRealAddress) 
    {
    iAddresseeList->AppendL(aType, aRealAddress); 
    }
    
// new overload specifying address type (with alias) 
void CFooClientMtm::AddAddresseeL(TMtmRecipientType aType, const TDesC& aRealAddress, const TDesC& aAlias) 
    {
    HBufC* address = HBufC::NewLC(aRealAddress.Length()+aAlias.Length()+iFormatString->Length());
        address->Des().Format(*iFormatString,&aAlias,&aRealAddress);
        iAddresseeList->AppendL(aType, address->Des()); 
    CleanupStack::PopAndDestroy(); // address 
    }

It is recommended that an MTM silently accepts Cc: recipients as To: recipients if Cc: recipients are not supported. MTMs should reject (with an error of KErrNotSupported) Bcc: recipients if they do not support Bcc: recipients.

An MTM can specify to clients whether it supports address types using a new capability, KUidMtmQuerySupportsRecipientTypeValue, defined in MTMDEF.HRH. Implementations of QueryCapability in the client MTM, UI MTM, and UI Data MTM should be updated to handle this capability.


Sending support

The Send-As server sends messages using the CBaseMtm::InvokeAsyncFunctionL() API with a new generic command ID KMTMStandardFunctionsSendMessage.

MTMs that support SendAs must support this command. When it is called, the implementation of InvokeAsyncFunctionL must return an instance of a class that implements the new CMsvSendOperation interface. The purpose of this interface is to provide information to the UI in a generic format about the progress of the sending operation. The MTM implements in its CMsvSendOperation derived-class the function:

virtual const TDesC8& TranslateProgress(const TDesC8& aProgress)=0;

whose purpose is to convert the MTM's native progress data into the standard progress structure, CMsvSendOperation::TSendOperationProgress.

The Send-As server will also require the UI MTM API to be extended to allow non-trusted client applications to send messages. It must implement the new CBaseMtmUi function:

virtual CMsvOperation* ConfirmSendL(TRequestStatus& aStatus, const CMsvEntrySelection& aSelection, const TSecurityInfo& aClientInfo);

Typically this will launch a dialog that will query the user to confirm the send request. The TSecurityInfo parameter provides the security properties of the process that requested the send.

[Top]


Moving settings to the central repository

As discussed in Configuration settings, configuration settings for Symbian supplied MTMs have been moved from the message store to the central repository to improve the security of these settings. Writers of MTMs can also move their settings, though this is not compulsory. The following sections describe how to move these settings:


Determining the repository key format

The central repository has a simple two tier structure:

MTM settings typically require more structure than a flat list: for example, you may want to store multiple groups of settings for multiple services. When using the central repository, this extra structure is encoded in the setting keys using bit fields. The repository API provides helpful functions to retrieve keys that match particular bitmask patterns.

For example, for an MTM with multiple services, the 32 bit key could be structured as follows:

1 bit

11 bit

4 bit

16 bit

service flag

account ID

setting group

setting field

where:

Note that scheduled send settings are now stored in the central repository. For MTMs that support scheduled send, this imposes the following conditions:


Creating a repository definition file

A repository is created by a repository definition file being present in the repository file area (z:\private\10202BE9\). An MTM should define such a file for its repository.

Considerations in creating such a file include:

A simple example of such a file is given below:

cenrep 
version 1

[PlatSec] 
# default security policies for repository 
cap_rd=AlwaysPass cap_wr=WriteDeviceData 

[Main] 
#one setting, a writable string with value "foo". 
0x00000000 string foo 1 

The MTM's bld.inf should export the file to the central repository file area.

#ifdef __MESSAGING_API_V2__ 
[10005247].txt z:\private\10202BE9\[10005247].txt 
#endif

For ROM-based MTMs, the file can then be put into the correct place in the ROM from the IBY file:

#ifdef __MESSAGING_API_V2__ 
data=EPOCROOT##epoc32\data\Z\private\10202BE9\[10005247].txt
private\10202BE9\[10005247].txt 
#endif 


Creating a repository access class

An MTM's repository access class is responsible for creating, deleting, saving and retrieving settings from the repository. Licensees and partners may find CEmailAccounts or CSmsAccount suitable models for writing a new repository access class.

SDK users can find the CMTMTxtSettings at ..\examples\Messaging\TextMTM in the set of SDK examples.


Updating the MTM to use the repository access class

All functions that use CMsvStore StoreL/RestoreL functions to save/access settings should change to using the new repository access class. Some candidates are:

[Top]


Default service support

Three new functions are added to CBaseMtm to support default services:

Function

Purpose

Default implementation

DefaultServiceL

Gets the default MTM service

Finds the first service associated with this MTM and returns that.

RemoveDefaultServiceL

Removes the default service setting

Does nothing

ChangeDefaultServiceL

Sets the default MTM service

Does nothing

The base class implementations assume that the MTM only supports one service, and so does not store any setting to identify the default service. If this assumption is wrong for your MTM, you should override the default implementations to store such a setting. The recommended method is to use a "default service" key in the MTM's repository, whose value is the entry ID of the default service:

EXPORT_C TMsvId CBarSettings::DefaultServiceL() const 
    {
    // Get the default service ID from CenRep, key is KDefaultServiceId 
    TInt temp = 0; 
    User::LeaveIfError(iRepository->Get(KDefaultServiceId, temp)); 
    return static_cast<TMsvId>(temp); 
    }

TMsvId CBarClientMtm::DefaultServiceL() const 
    {
    return iSettings->DefaultServiceL(); 
    }

[Top]


SendAs Clients

The SendAs API classes CSendAs and MSendAsObserver provided in previous releases of the OS are deprecated in v9.1, and a new API is introduced to which clients should migrate.

The new API has all the functionality of the old API, plus support for:

The new API uses the client/server framework, and has two main classes:

Unlike the previous API, the new API does not expose the message server APIs such as CBaseMtm.

To use the new API, the client should include the header sendas2.h and link against the library sendas2.lib.

The rest of this section describes the following:

[Top]


Getting MTMs/accounts

In the old API, the first task was typically to get a list of MTMs available to send the message, by specifying the features that the MTMs must have using AddMtmCapabilityL(); for example:

iSendAs->ResetMtmCapabilitiesL(); 
iSendAs->AddMtmCapabilityL(KUidMtmQuerySupportAttachments,EFalse); 
iSendAs->AddMtmCapabilityL(KUidMtmQueryMaxTotalMsgSize, ETrue); // calls back CapabilityOK() 

Similar functionality is available on RSendAs, using the FilterAgainstCapability() member function:

// reset filter 
User::LeaveIfError(iSendAsServer.ResetMessageFilter()); 
// set filter for presence of capability 
User::LeaveIfError(iSendAsServer.FilterAgainstCapability(KUidMtmQuerySupportAttachments));
// set filter to test that KUidMtmQueryMaxBodySize >= bodySize 
User::LeaveIfError(iSendAsServer.FilterAgainstCapability(KUidMtmQueryMaxBodySize,
bodySize, ESendAsGreaterThan)); 

The chief difference here is that AddMtmCapabilityL() can call back a client implementation of the MSendAsObserver::CapabilityOK() interface to do a further test on a returned capability value. FilterAgainstCapability doesn't need this callback, as the overload:

FilterAgainstCapability(TUid aMessageCapability, TInt aValue, TSendAsConditionType aConditionType) 

allows you to specify a value and a condition type (e.g. greater than) with which to test the capability.

Once a filter has been set, the available MTMs can be retrieved. The replacement for CSendAs::AvailableMtms() is RSendAs::FilteredMessageTypes(), which populates a CSendAsMessageTypes object:

// get message types 
CSendAsMessageTypes* iMessageTypeInfo = CSendAsMessageTypes::NewL(); 
User::LeaveIfError(iSendAsServer.FilteredMessageTypes(*iMessageTypeInfo));
// get array of names of available types 
const MDesCArray& mtms = iMessageTypeInfo->AvailableMessageTypes();

In the old SendAs, once an MTM had been chosen, the available services could be retrieved using CSendAs::AvailableServices(). The new API allows a list of available services to be obtained using RSendAs::AvailableAccountsL(), which populates a CSendAsAccounts object. The MTM for which to get the services is specified by the message type UID, which can be obtained from the CSendAsMessageTypes object:

// get message type UID of first MTM in the list of those available 
TUid mtmuid = iMessageTypeInfo->MessageTypeUid(0); 
// get a list of available services 
CSendAsAccounts* accounts = CSendAsAccounts::NewL(); 
CleanupStack::PushL(accounts); 
iSendAsServer.AvailableAccountsL(mtmuid, *accounts); 
// get the names of the services, e.g. for sub-menu text 
const MDesCArray& accountNames = accounts->AccountNames(); 

Once an account has been selected, the ID of the service can be obtained (for later use when creating a message):

// get ID of first available service 
TSendAsAccount serviceId = accounts->Account(0); 

[Top]


Creating and populating messages

Creating a message and setting its contents is now done through RSendAsMessage.

To create a message, use one of:

void CreateL(RSendAs& aSendAs, TSendAsAccount aAccount); 
void CreateL(RSendAs& aSendAs, TUid aMessageType);

specifying either the service ID or message type obtained from CSendAsMessageTypes or CSendAsAccounts.

The contents of the message can then be set.

Note: There is no direct equivalent for CSendAs::QueryMessageCapability() for testing if an MTM supports a particular feature at this stage. Instead, you should be prepared to handle a returned error code that indicates that the setting cannot be made.

The rest of this section describes:


Setting the text, subject and biotype

RSendAsMessage offers the following member functions to set the message's body text, subject, and BIO type.

void SetBodyTextL(const CRichText& aBody); 
void SetBodyTextL(const TDesC& aBody); 
void SetSubjectL(const TDesC& aSubject); 
void SetBioTypeL(TUid aBioType);

These are very similar to the corresponding member functions on CSendAs.


Setting the recipients

RSendAsMessage has similar member functions to CSendAs for setting recipients:

void AddRecipientL(const TDesC& aAddress, TSendAsRecipientType aRecipientType); 
void AddRecipientL(const TDesC& aAddress, const TDesC& aAlias, TSendAsRecipientType aRecipientType);

Note, however, that compared to CSendAs these member functions have an extra TSendAsRecipientType parameter to specify whether the recipient is of a 'To' , 'Cc' or 'Bcc' type. If the message type does not support 'Cc' recipients, the recipient is instead treated as a 'To' recipient. If the 'Bcc' field is not supported, the member functions return KErrNotSupported.

There is no equivalent to CSendAs::RemoveRecipient().


Adding attachments

CSendAs had a single CreateAttachmentL() member function with which to add an attachment to a message. RSendAsMessage has a collection of member functions as follows:

IMPORT_C void AddAttachment(const TDesC& aFilePath, TRequestStatus& aStatus); 
IMPORT_C void AddAttachment(const TDesC& aFilePath, const TDesC8& aMimeType, TRequestStatus& aStatus); 
IMPORT_C void AddAttachment(RFile& aFile, const TDesC8& aMimeType, TRequestStatus& aStatus); 
IMPORT_C void AddAttachment(RFile& aFile, TRequestStatus& aStatus); 
IMPORT_C void AddLinkedAttachment(const TDesC& aFilePath, const TDesC8& aMimeType, TRequestStatus& aStatus); 
IMPORT_C void AddLinkedAttachment(const TDesC& aFilePath, TRequestStatus& aStatus); 
IMPORT_C void CreateAttachmentL(TDes& aFileName, RFile& aAttachmentFile); 
IMPORT_C void CreateAttachmentL(TDes& aFileName, RFile& aAttachmentFile, const TDesC8& aMimeType);

The first AddAttachment member function is the closest equivalent to CSendAs::CreateAttachmentL(). The other member functions add some extra functionality, which might better suit some applications:

There is no equivalent to CSendAs::DeleteAttachmentL().

[Top]


Sending messages

Sending a message is done using the following member functions:

IMPORT_C void SendMessage(TRequestStatus& aStatus); 
IMPORT_C void SendMessageAndCloseL(); 
IMPORT_C void SendMessageConfirmed(TRequestStatus& aStatus); 
IMPORT_C void SendMessageConfirmedAndCloseL(); 
IMPORT_C void ProgressL(TSendAsProgress& aProgress);

The client application can request to send the created message in two ways – unconfirmed and confirmed.

For an unconfirmed send, or a confirmed send that has been accepted by the user, the message is copied to the Outbox and then the MTM for the message type is used to send the message. The message is now no longer accessible through the Send-As APIs, and the client application cannot modify or delete the message.

The outcome of a successful or unsuccessful send is dependent on the MTMs for the message type. For instance, a successfully sent message may be moved to the Sent folder (e.g. SMS) or deleted (e.g. OBEX), while an unsuccessfully sent message may remain in the Outbox and can be re-scheduled depending on the send error (e.g. SMS).

The synchronous member functions, SendMessageAndCloseL() and SendMessageConfirmedAndCloseL() send the message in the background and close the RSendAsMessage handle.

For the asynchronous member functions, SendMessage() and SendMessageConfirmed():

[Top]


Launching an editor

The following member function allows a client application to launch the editor (as provided by UI MTM) for the created message. The handle to the message is closed, so it can no longer be accessed through RSendAsMessage.

IMPORT_C void LaunchEditorAndCloseL();

[Top]


Saving the message

The message can also be saved to the message store (if this supported by the MTM) without being sent using the member function:

IMPORT_C void SaveMessageAndCloseL();

[Top]


BIO Message Parser Plugins

From v9.1, the BIO-message parsers are:

If you have an existing BIO parser, you need to make the following changes:

1. Change the parser to derive from the new CBaseScriptParser2 class rather than CBaseScriptParser. The significant change is that the parser receives the message to parse as an CMsvEntry rather than a CMsvServerEntry. The CMsvEntry still provides access to all of the BIO message data.

2. Build the binary to the default binaries directory rather than to \system\parsers\. The build tools ignore the mmp file targetpath statement in v9.1, so this does not need to be explicitly configured.

3. In the resource file BIO_INFO_FILEstructure, replace the message_parser_uid member with a member message_parser_name that specifies the parser's filename. For example:

#ifdef  __MESSAGING_API_V2__ 
#ifdef  __MESSAGING_API_V2__ 
message_parser_name="cbcp.dll"; 
#else 
message_parser_uid=0x1000526B; 
#endif

The resource file should include biftool2.rh rather than biftool.rh: i.e. use:

#ifdef  __MESSAGING_API_V2__ 
#include    <biftool2.rh> 
#else 
#include    <biftool.rh> 
#endif  // __MESSAGING_API_V2__

4. Export or build BIF files (built from .rss files) and mbm files to \resource\messaging\bif\ rather than \system\bif\. For example:

START RESOURCE ..\cbcpbif\cbcp.rss 
#ifdef          __MESSAGING_API_V2__ 
TARGETPATH      resource\messaging\Bif 
#else 
TARGETPATH      System\Bif 
#endif 
LANG                SC 
END
 
START BITMAP   cbcp.mbm 
#ifdef          __MESSAGING_API_V2__ 
TARGETPATH      resource\messaging\Bif 
#else 
TARGETPATH      System\Bif 
#endif 

5. If the parser is built into a ROM, amend .iby files accordingly for steps 2 and 4.