Using Message Filtering to Manage Messages

The MAPI spooler makes calls to two different types of extensions by which code can be inserted in the message transmission process. These extensions — known as preprocessors and spooler hooks — can be used for a wide variety of purposes including altering the recipient list or content of an outbound message, archiving outbound messages in local storage or on a central server, directing inbound messages to a particular folder based on arbitrary criteria, and responding automatically to inbound messages.

Design Tasks

  1. Decide whether to use a preprocessor or a spooler hook.

    A preprocessor is called for outbound messages only. It may choose to be called for all messages, or for messages that have recipients of a particular type. Those recipients can be selected based on the address type (PR_ADDRTYPE), on the MAPIUID which qualifies the recipient's entry identifier, or both. See IMAPISupport::RegisterPreprocessor.

    A preprocessor can create new messages based on the input message, returning them through its lpppMessage parameter. In no case should the input message be placed in the lpppMessage parameter. If a preprocessor does not want the input message to be sent, it should delete all the recipients and set the PR_DELETE_AFTER_SUBMIT property; the input message should not be deleted using message store calls.

    A spooler hook may choose to be called for all inbound messages, all outbound messages, or both, by setting the HOOK_INBOUND flag, the HOOK_OUTBOUND flag, or both in its PR_RESOURCE_FLAGS property on the provider profile section in MAPISVC.INF. See File Format of MAPISVC.INF.

    To delete an inbound or outbound message, a hook should set the HOOK_DELETE flag in its lpulFlags parameter. It should not use message store calls to delete the message presented to it through its interface; it may use message store calls to create, modify, or delete other messages. A hook can prevent processing of a message by other hooks, including the default hook that processes receive folder settings, by setting the HOOK_CANCEL flag in lpulFlags.

    When working with a tightly coupled message store and transport, the store itself can transmit a message that is not destined for any spooler-based transports. Whether preprocessors and hooks are called in this situation depends upon the message store implementation. Microsoft Exchange Server, for example, calls preprocessors on outbound messages but does not call either inbound or outbound spooler hooks. See Sending Messages with MAPI.

    On an outbound message, hooks and preprocessors participate in a complicated sequence of events. The following steps involve hooks and preprocessors.

    1. The PreprocessMessage entry point of each preprocessor is called before any transport provider handles the message. It can update the recipient list, alter message content, or even create additional messages. The order in which preprocessors are called is the same as the order in which the transports that registered them are called to handle outbound messages. See Creating and Configuring a Profile.
    2. Transport providers are called to transmit the message. If any transport defers message processing, no hooks are called until the deferred processing is complete.
    3. The RemovePreprocessInfo entry point of each preprocessor is called after all transports have handled the message.
    4. The ISpoolerHook::OutboundMsgHook method is called for each hook that sets the HOOK_OUTBOUND flag in the PR_RESOURCE_FLAGS property. The order in which hooks are called is the same as the order in which they were installed in the profile; it does not follow the transport order because a hook does not necessarily have an associated transport provider.

    For inbound messages, preprocessors are not called. Hooks are called as follows:

    1. The receiving transport provider completes its work.
    2. The ISpoolerHook::InboundMsgHook method is called for each hook that sets the HOOK_INBOUND flag in the PR_RESOURCE_FLAGS property. The order in which hooks are called is the same as the order in which they were installed in the profile; it does not follow the transport order because a hook does not have an associated transport provider.
    3. For inbound messages, the receive folder assignment is honored only if a hook has not moved the message to another folder. Conceptually, the MAPI spooler implements an internal hook which is always called last and only if no previous hook returns the HOOK_CANCEL flag; it finds the receive folder based on the message's PR_MESSAGE_CLASS property and places the message in that folder. See IMsgStore::GetReceiveFolder.
  2. Define configuration parameters and understand how your hook or preprocessor is to be installed. A spooler hook is a distinct service provider type and is added to the user's profile as part of a message service, either alone or together with other related service providers. Any configuration parameters are normally stored in the profile and edited using the property pages for the message service. A preprocessor is not a distinct service provider type; it must be registered by a transport provider. If necessary, a minimal transport provider can be created for this purpose alone.

Implementation Tasks

    To implement a preprocessor
    To implement a spooler hook

About Sample Source Code

See the following topics:

Sample Transport Provider

Sample Messaging Hook Provider