Sun Java Communications Suite 5 Event Notification Service Guide

Chapter 4 Messaging Server Specific Information

This chapter describes the Messaging Server specific items you need to use the ENS APIs.

This chapter contains these sections:

Event Notification Types and Parameters

For Messaging Server, there is only one event reference, which can be composed of several parameters. There are various types of event notifications. Table 4–1 lists the event types supported by Messaging Server and gives a description of each:

Table 4–1 Event Types

Event Types  

Description  

DeleteMsg

Messages marked as “Deleted” are removed from the mailbox. This is the equivalent to IMAP expunge. 

Login

User logged in from IMAP, HTTP, or POP. 

Logout

User logged out from IMAP, HTTP, or POP. 

NewMsg

New message was received by the system into the user’s mailbox. Can have a payload of message headers and body. 

OverQuota

Operation failed because the user’s mailbox exceeded one of the quotas (diskquota, msgquota). The MTA channel holds the message until the quota changes or the user’s mail box count goes below the quota. If the message expires while it is being held by the MTA, it will be expunged. 

PurgeMsg

Message expunged (as a result of an expired date) from the mailbox by the server process imexpire. This is a server side expunge, whereas DeleteMsg is a client side expunge. This is not a purge in the true sense of the word. 

ReadMsg

Message in the mailbox was read (in the IMAP protocol, the message was marked Seen). 

TrashMsg

Message was marked for deletion by IMAP or HTTP. The user may still see the message in the folder, depending on the mail client’s configuration. The messages are to be removed from the folder when an expunge is performed. 

UnderQuota

Quota went back to normal from OverQuota state. 

UpdateMsg

Message was appended to the mailbox (other than by NewMsg). for example, the user copied an email message to the mailbox. Can have a payload of message headers and body. 

The following applies to the above supported event types:


Note –

There is no mechanism to select folders; all folders are included when the variable is enabled (value = 1).


Parameters

iBiff uses the following format for the ENS event reference:

enp://127.0.0.1/store?param=value&param1=value1&param2=value2

The event key enp://127.0.0.1/store has no significance other than its uniqueness as a string. For example, the hostname portion of the event key has no significance as a hostname. It is simply a string that is part of the URI. However, the event key is user configurable. The list of iBiff event reference parameters is listed in Table 4–2 and Table 4–3 that follow.

The second part of the event reference consists of parameter-value pairs. This part of the event reference is separated from the event key by a question mark (?). The parameter and value are separated by an equals sign (=). The parameter-value pairs are separated by an ampersand (&). Note that there can be empty values, for which the value simply does not exist.

Table 4–2 describes the mandatory event reference parameters that need to be included in every notification.

Table 4–2 Mandatory Event Reference Parameters

Parameter  

Data Type  

Description  

evtType

string 

Specifies the event type. 

hostname

string 

The hostname of the machine that generated the event. 

mailboxName

string 

Specifies the mailbox name in the message store. The mailboxName has the format uid@domain, where uid is the user’s unique identifier, and domain is the domain the user belongs to. The @domain portion is added only when the user does not belong to the default domain (i.e. the user is in a hosted domain).

pid

integer 

ID of the process that generated the event. 

process

string 

Specifies the name of the process that generated the event. 

timestamp

64-bit integer 

Specifies the number of milliseconds since the epoch (midnight GMT, January 1, 1970). 

Table 4–3 describes optional event reference parameters, which might be seen in the event depending on the event type (see Table 4–4).

Table 4–3 Optional Event Reference Parameters

Parameter  

Data Type  

Description  

client

IP address 

The IP address of the client logging in or out. 

diskQuota

signed 32-bit integer 

Specifies the disk space quota in kilobytes. The value is set to -1 to indicate no quotas. 

diskUsed

signed 32-bit integer 

Specifies the amount of disk space used in kilobytes. 

hdrLen

unsigned 32-bit integer 

Specifies the size of the message header. Note that this might not be the size of the header in the payload, because it might have been truncated. 

imapUid

unsigned 32-bit integer 

Specifies the IMAP uid parameter. 

lastUid

unsigned 32-bit integer 

Specifies the last IMAP uid value that was used. 

numDel 

unsigned 32-bit integer 

Specifies the number of messages marked as deleted in the mailbox. 

numMsgs

unsigned 32-bit integer 

Specifies the number of total messages in the mailbox. 

numMsgsMax 

signed 32-bit integer 

Specifies the quota for the maximum number of messages. The value is set to -1 to indicate no quotas. 

numSeen 

unsigned 32-bit integer 

Specifies the number of messages in the mailbox marked as seen (read). 

size

unsigned 32-bit integer 

Specifies the size of the message. Note that this may not be the size of payload, since the payload is typically a truncated version of the message. 

uidValidity

unsigned 32-bit integer 

Specifies the IMAP uid validity parameter. 


Note –

Subscribers should allow for undocumented parameters when parsing the event reference. This allows for future compatibility when new parameters are added.


Table 4–4 shows the parameters that are available for each event type. For example, to see which parameters apply to a TrashMsg event, look in the column header for “ReadMsg, TrashMsg” and then note that these events can use numDel, numMsgs, numSeen, and userValidity.

Table 4–4 Available Parameters for Each Event Type

Parameter  

NewMsg, UpdateMsg  

ReadMsg, TrashMsg  

DeleteMsg, PurgeMsg  

Login, Logout  

OverQuota, UnderQuota  

client

No 

No 

No 

Yes 

No 

diskQuota

No 

No 

No 

No 

Yes 

diskUsed

No 

No 

No 

No 

Yes 

hdrLen

Yes 

No 

No 

No 

No 

imapUid

Yes 

No 

Yes 

No 

No 

lastUid

No 

No 

Yes 

No 

No 

numDel

No 

Yes 

No 

No 

No 

numMsgs

Yes 

Yes 

Yes 

No 

Yes 

numMsgsMax

No 

No 

No 

No 

Yes 

numSeen

No 

Yes 

No 

No 

No 

size

Yes 

No 

No 

No 

No 

uidValidity

Yes 

Yes 

Yes 

No 

No 

userid

No 

No 

No 

Yes 

No 

Payload

ENS allows a payload for two event types: NewMsg, and UpdateMsg; the other event types do not carry a payload. The payload portion of these two notifications can contain any of the following data:

The amount and type of data sent as the payload of the ENS event is determined by the configuration parameters found in Table 4–5.

Table 4–5 Payload Configuration Parameters

Configuration Parameter  

Description  

local.store.notifyplugin.maxBodySize

Specifies the maximum size (in bytes) of the body that will be transmitted with the notification. Default setting is zero (0). 

local.store.notifyplugin.maxHeaderSize

Specifies the maximum size (in bytes) of the header that will be transmitted with the notification. Default setting is zero (0). 

Note that both parameters are set to zero as the default so that no header or body data is sent with ENS notifications.

Examples

The following example shows a NewMsg event reference (it is actually a single line that is broken up to several lines for readability):


enp://127.0.0.1/store?evtType=NewMsg&timestamp=1047488403000&
hostname=eman&process=imta&pid=476&mailboxName=testuser&numMsgs=16
&uidValidity=1046993605&imapUid=62&size=877&hdrLen=814

         

In this example, for the DeleteMsg event. Messages marked as deleted by IMAP or HTTP were expunged. The user would not see the message in the folder any more.


enp://127.0.0.1/store?evtType=DeleteMsg&timestamp=1047488588000&
hostname=eman&process=imapd&pid=419&mailboxName=testuser&
numMsgs=6&uidValidity=1046993605&imapUid=61&lastUid=62

         

And a third example shows a ReadMsg event. Message was marked as Seen by IMAP or HTTP.


enp://127.0.0.1/store?evtType=ReadMsg&timestamp=1047488477000&
hostname=eman&process=imapd&pid=419&mailboxName=testuser&
uidValidity=1046993605&numSeen=11&numDel=9&numMsgs=16

         

Sample Code

The following two code samples illustrate how to use the ENS API. The sample code is provided with the product in the following directory:

msg-svr-base/examples

ProcedureTo use the sample code

  1. Before running the makefile, set your library search path to include the directory:


    msg-svr-base/lib
  2. Compile the code using the Makefile.sample.

  3. Run apub and asub as follows in separate windows:

    apub localhost 7997

    asub localhost 7997

    Whatever is typed into the apub window should appear on the asub window. If you use the default settings, all iBiff notifications should appear in the asub window.

  4. Remove the msg-svr-base/lib path from your library search path.


    Note –

    If you do not remove this from the library search path, you will not be able to stop and start the directory server.


Sample Publisher

This sample code provides a simple interactive asynchronous publisher.

/*
* Copyright 2006 by Sun Microsystems, Inc.
* All rights reserved
*
* Syntax:
*   apub host port
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "upub.h"

static upub_t *_publisher = NULL;

/* function prototypes */
static void _read_stdin(void);
static void _publish_ack(void *arg);

/**
 *
 **/
static void _read_stdin()
{
   static char input[1024];

   while (1) {
      printf("apub> ");
      fflush(stdout);
      if ( !fgets(input, sizeof(input), stdin) ) {
         continue;
      } else {
         char *message;
         unsigned int message_len;

         input[strlen(input) - 1] = 0; /* Strip off the \n */

         if (*input == '.' && input[1] == 0) {
            break;
         }

         message = strdup(input);
         message_len = strlen(message);
         upub_publish(_publisher, "enp://yoyo.com/xyz",
                      message, message_len, _publish_ack);
      }
   }
   
   return;
}

/**
 * call back after publish is done
 **/
static void
_publish_ack(void *arg)
{
   free(arg);
   return;
}


int
main(int argc, char **argv) 
{
   unsigned short port = 7997;
   char host[256];

   if (argc < 2) {
      printf("\nUsage:\n\tapub host port\n");
      exit(2);
   }
   if (*(argv[1]) == '0') {
      strcpy(host, "127.0.0.1");
   } else {
      strcpy(host, argv[1]);
   }
   if (argc > 2) {
      port = (unsigned short)atoi(argv[2]);
   }

   _publisher = upub_init(NULL, host, port, 1);
   if (_publisher == NULL) {
      printf("could not create publisher\n");
      exit(1);
   }
 
   _read_stdin();

   upub_shutdown(_publisher);
}

Sample Subscriber

This sample code provides a simple subscriber.

/*
 * Copyright 1997, 2006 by Sun Microsystems, Inc.
 * All rights reserved
 *
 * asub : example asynchronous subscriber
 *
 * Syntax:
 *      asub host port
*/
*
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "pasdisp.h"
#include "subscriber.h"

#define DEFAULT_EVENT_REF "enp://yoyo.com/xyz"

static pas_dispatcher_t *disp = NULL;
static subscriber_t *_subscriber = NULL;
static subscription_t *_subscription = NULL;
static renl_t *_renl = NULL;
static char *_event_ref = DEFAULT_EVENT_REF;

static void _exit_usage()
{
    printf("\nUsage:\nasub host port\n");
    exit(5);
}

static void _exit_error(const char *msg)
{
    printf("%s\n", msg);
    exit(1);
}

static void _subscribe_ack(void *arg, int rc, void *subscription)
{
    (void)arg;
    if (!rc) {
        _subscription = subscription;
        printf("Subscription successful\n");
        subscriber_keepalive(_subscriber, 30000);
    }else {
        printf("Subscription failed - status %d\n", rc);
        pas_shutdown(disp);
    }
}

static void _unsubscribe_ack(void *arg, int rc, void *ignored)
{
(void *)ignored;
    (void *)arg;
    
    if (rc != 0) {
        printf("Unsubscribe failed - status %d\n", rc);
    }
    
    subscriber_delete(_subscriber);
    pas_shutdown(disp);
}

static int _handle_notify(void *arg, char *url, char *str, int len)
{
    (void *)arg;
    printf("[%s] %.*s\n", url, len, (str) ? str : "(null)");
    return 0;
}

static void _open_ack(void *arg, int rc, void *enc)
{
    _subscriber = (subscriber_t *)enc;
    
    (void *)arg;
    if (rc) {
        printf("Failed to create subscriber with status %d\n", rc);
        pas_shutdown(disp);
        return;
    }
    
    subscribe(_subscriber, "enp://127.0.0.1/store",
              _handle_notify, NULL,
              _subscribe_ack, NULL);
    return;
}

static void _unsubscribe(int sig)
{
    (int)sig;
    unsubscribe(_subscriber, _subscription, _unsubscribe_ack, NULL);
}

int
main(int argc, char **argv)
{
    unsigned short port = 7997;
    char host[256];
    
    if (argc < 2) _exit_usage();
    if (*(argv[1]) == ’0’) {
        strcpy(host, "127.0.0.1");
    s}else {
        strcpy(host, argv[1]);
    }
    if (argc > 2) {
        port = (unsigned short)atoi(argv[2]);
    }
    if (argc > 3) {
        _event_ref = argv[3];
    }
    
    disp = pas_dispatcher_new(NULL);
    if (disp == NULL) _exit_error("Can’t create publisher");
    
    subscriber_new_a(disp, NULL, host, port, _open_ack, NULL);
    
    pas_dispatch(disp);
    
    pas_dispatcher_delete(disp);
    
exit(0);
}

Implementation Notes

The current implementation does not provide security on events that can be subscribed to. Thus, a user could register for all events, and portions of all other users’ mail. Because of this it is strongly recommended that the ENS subscriber be on the “safe” side of the firewall at the very least.