MilterClientContext

MilterClientContext — Process milter protocol.

Synopsis

#define             MILTER_CLIENT_CONTEXT_ERROR
enum                MilterClientContextError;
enum                MilterClientContextState;
                    MilterClientContext;
GQuark              milter_client_context_error_quark   (void);
MilterClientContext* milter_client_context_new          (void);
gboolean            milter_client_context_feed          (MilterClientContext *context,
                                                         const gchar *chunk,
                                                         gsize size,
                                                         GError **error);
gpointer            milter_client_context_get_private_data
                                                        (MilterClientContext *context);
void                milter_client_context_set_private_data
                                                        (MilterClientContext *context,
                                                         gpointer data,
                                                         GDestroyNotify destroy);
gboolean            milter_client_context_set_reply     (MilterClientContext *context,
                                                         guint code,
                                                         const gchar *extended_code,
                                                         const gchar *message,
                                                         GError **error);
gchar*              milter_client_context_format_reply  (MilterClientContext *context);
gboolean            milter_client_context_add_header    (MilterClientContext *context,
                                                         const gchar *name,
                                                         const gchar *value,
                                                         GError **error);
gboolean            milter_client_context_insert_header (MilterClientContext *context,
                                                         guint32 index,
                                                         const gchar *name,
                                                         const gchar *value,
                                                         GError **error);
gboolean            milter_client_context_change_header (MilterClientContext *context,
                                                         const gchar *name,
                                                         guint32 index,
                                                         const gchar *value);
gboolean            milter_client_context_delete_header (MilterClientContext *context,
                                                         const gchar *name,
                                                         guint32 index);
gboolean            milter_client_context_change_from   (MilterClientContext *context,
                                                         const gchar *from,
                                                         const gchar *parameters);
gboolean            milter_client_context_add_recipient (MilterClientContext *context,
                                                         const gchar *recipient,
                                                         const gchar *parameters);
gboolean            milter_client_context_delete_recipient
                                                        (MilterClientContext *context,
                                                         const gchar *recipient);
gboolean            milter_client_context_replace_body  (MilterClientContext *context,
                                                         const gchar *body,
                                                         gsize body_size);
gboolean            milter_client_context_progress      (MilterClientContext *context);
gboolean            milter_client_context_quarantine    (MilterClientContext *context,
                                                         const gchar *reason);
void                milter_client_context_set_timeout   (MilterClientContext *context,
                                                         guint timeout);
guint               milter_client_context_get_timeout   (MilterClientContext *context);
void                milter_client_context_set_state     (MilterClientContext *context,
                                                         MilterClientContextState state);
MilterClientContextState milter_client_context_get_state
                                                        (MilterClientContext *context);
void                milter_client_context_set_option    (MilterClientContext *context,
                                                         MilterOption *option);
MilterOption*       milter_client_context_get_option    (MilterClientContext *context);

Description

The MilterClientContext processes one milter protocol session. It means MilterClientContext instance is created for each milter protocol session.

To process each milter protocol command, you need to connect signals of MilterClientContext. MilterClientContext has signals that correspond to milter protocol events:

Here is an example to connect signals. It connects all signals and each connected signal handler prints its event name:

static MilterStatus
cb_negotiate (MilterClientContext *context, MilterOption *option,
              gpointer user_data)
{
    g_print("negotiate\n");
    return MILTER_STATUS_ALL_OPTIONS;
}

static MilterStatus
cb_connect (MilterClientContext *context, const gchar *host_name,
            const struct sockaddr *address, socklen_t address_length,
            gpointer user_data)
{
    g_print("connect\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_helo (MilterClientContext *context, const gchar *fqdn, gpointer user_data)
{
    g_print("helo\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_envelope_from (MilterClientContext *context, const gchar *from,
                  gpointer user_data)
{
    g_print("envelope-from\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_envelope_recipient (MilterClientContext *context, const gchar *to,
                       gpointer user_data)
{
    g_print("envelope-recipient\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_data (MilterClientContext *context, gpointer user_data)
{
    g_print("data\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_header (MilterClientContext *context, const gchar *name, const gchar *value,
           gpointer user_data)
{
    g_print("header\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_end_of_header (MilterClientContext *context, gpointer user_data)
{
    g_print("end-of-header\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_body (MilterClientContext *context, const gchar *chunk, gsize length,
         gpointer user_data)
{
    g_print("body\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_end_of_message (MilterClientContext *context, gpointer user_data)
{
    g_print("end-of-message\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_abort (MilterClientContext *context, gpointer user_data)
{
    g_print("abort\n");
    return MILTER_STATUS_CONTINUE;
}

static MilterStatus
cb_unknown (MilterClientContext *context, const gchar *command,
            gpointer user_data)
{
    g_print("unknown\n");
    return MILTER_STATUS_CONTINUE;
}

static void
setup_context_signals (MilterClientContext *context)
{
#define CONNECT(name)                                                   \
    g_signal_connect(context, name, G_CALLBACK(cb_ ## name), NULL)

    CONNECT(negotiate);
    CONNECT(connect);
    CONNECT(helo);
    CONNECT(envelope_from);
    CONNECT(envelope_recipient);
    CONNECT(data);
    CONNECT(header);
    CONNECT(end_of_header);
    CONNECT(body);
    CONNECT(end_of_message);
    CONNECT(abort);
    CONNECT(unknown);

#undef CONNECT
}

Details

MILTER_CLIENT_CONTEXT_ERROR

#define MILTER_CLIENT_CONTEXT_ERROR           (milter_client_context_error_quark())

Used to get the GError quark for MilterClientContext errors.


enum MilterClientContextError

typedef enum
{
    MILTER_CLIENT_CONTEXT_ERROR_INVALID_CODE,
    MILTER_CLIENT_CONTEXT_ERROR_IO_ERROR,
    MILTER_CLIENT_CONTEXT_ERROR_NULL,
    MILTER_CLIENT_CONTEXT_ERROR_INVALID_STATE,
    MILTER_CLIENT_CONTEXT_ERROR_INVALID_ACTION
} MilterClientContextError;

These identify the variable errors that can occur while calling MilterClientContext functions.

MILTER_CLIENT_CONTEXT_ERROR_INVALID_CODE

Indicates a status code specified by milter_client_context_set_reply() is invalid.

MILTER_CLIENT_CONTEXT_ERROR_IO_ERROR

Indicates an IO error causing on writing/reading milter protocol data.

MILTER_CLIENT_CONTEXT_ERROR_NULL

Indicates unexpected NULL is passed.

MILTER_CLIENT_CONTEXT_ERROR_INVALID_STATE

Indicates unexpected operation is requested on the current MilterClientContextState.

MILTER_CLIENT_CONTEXT_ERROR_INVALID_ACTION

Indicates unexpected operation is requested on the context's MilterActionFlags.

enum MilterClientContextState

typedef enum
{
    MILTER_CLIENT_CONTEXT_STATE_INVALID,
    MILTER_CLIENT_CONTEXT_STATE_START,
    MILTER_CLIENT_CONTEXT_STATE_NEGOTIATE,
    MILTER_CLIENT_CONTEXT_STATE_NEGOTIATE_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_CONNECT,
    MILTER_CLIENT_CONTEXT_STATE_CONNECT_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_HELO,
    MILTER_CLIENT_CONTEXT_STATE_HELO_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_FROM,
    MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_FROM_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_RECIPIENT,
    MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_RECIPIENT_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_DATA,
    MILTER_CLIENT_CONTEXT_STATE_DATA_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_UNKNOWN,
    MILTER_CLIENT_CONTEXT_STATE_UNKNOWN_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_HEADER,
    MILTER_CLIENT_CONTEXT_STATE_HEADER_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_END_OF_HEADER,
    MILTER_CLIENT_CONTEXT_STATE_END_OF_HEADER_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_BODY,
    MILTER_CLIENT_CONTEXT_STATE_BODY_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_END_OF_MESSAGE,
    MILTER_CLIENT_CONTEXT_STATE_END_OF_MESSAGE_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_QUIT,
    MILTER_CLIENT_CONTEXT_STATE_QUIT_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_ABORT,
    MILTER_CLIENT_CONTEXT_STATE_ABORT_REPLIED,
    MILTER_CLIENT_CONTEXT_STATE_FINISHED
} MilterClientContextState;

These identify the state of MilterClientContext.

MILTER_CLIENT_CONTEXT_STATE_INVALID

Invalid state.

MILTER_CLIENT_CONTEXT_STATE_START

Just started.

MILTER_CLIENT_CONTEXT_STATE_NEGOTIATE

Starting negotiation.

MILTER_CLIENT_CONTEXT_STATE_NEGOTIATE_REPLIED

Received negotiation response.

MILTER_CLIENT_CONTEXT_STATE_CONNECT

Sent connection information.

MILTER_CLIENT_CONTEXT_STATE_CONNECT_REPLIED

Received connection information response.

MILTER_CLIENT_CONTEXT_STATE_HELO

Starting HELO.

MILTER_CLIENT_CONTEXT_STATE_HELO_REPLIED

Received HELO response.

MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_FROM

Starting MAIL FROM command.

MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_FROM_REPLIED

Receive MAIL FROM response.

MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_RECIPIENT

Starting RCPT TO command.

MILTER_CLIENT_CONTEXT_STATE_ENVELOPE_RECIPIENT_REPLIED

Receive RCPT TO response.

MILTER_CLIENT_CONTEXT_STATE_DATA

Starting DATA command.

MILTER_CLIENT_CONTEXT_STATE_DATA_REPLIED

Receive DATA response.

MILTER_CLIENT_CONTEXT_STATE_UNKNOWN

Receiving unknown SMTP command.

MILTER_CLIENT_CONTEXT_STATE_UNKNOWN_REPLIED

Receive unknown SMTP command response.

MILTER_CLIENT_CONTEXT_STATE_HEADER

Sent a header.

MILTER_CLIENT_CONTEXT_STATE_HEADER_REPLIED

Receive header response.

MILTER_CLIENT_CONTEXT_STATE_END_OF_HEADER

All headers are sent.

MILTER_CLIENT_CONTEXT_STATE_END_OF_HEADER_REPLIED

Receive end-of-header response.

MILTER_CLIENT_CONTEXT_STATE_BODY

Sending body chunks.

MILTER_CLIENT_CONTEXT_STATE_BODY_REPLIED

Received body response.

MILTER_CLIENT_CONTEXT_STATE_END_OF_MESSAGE

All body chunks are sent.

MILTER_CLIENT_CONTEXT_STATE_END_OF_MESSAGE_REPLIED

Receive end-of-message response.

MILTER_CLIENT_CONTEXT_STATE_QUIT

Starting quitting.

MILTER_CLIENT_CONTEXT_STATE_QUIT_REPLIED

Receive quit response.

MILTER_CLIENT_CONTEXT_STATE_ABORT

Starting aborting.

MILTER_CLIENT_CONTEXT_STATE_ABORT_REPLIED

Receive abort response.

MILTER_CLIENT_CONTEXT_STATE_FINISHED

Finished.

MilterClientContext

typedef struct {
    MilterProtocolAgent object;
} MilterClientContext;


milter_client_context_error_quark ()

GQuark              milter_client_context_error_quark   (void);

Returns :


milter_client_context_new ()

MilterClientContext* milter_client_context_new          (void);

Creates a new context object. Normally, context object is created by MilterClient and passed by "connection-established" signal.

Returns :

a new MilterClientContext object.

milter_client_context_feed ()

gboolean            milter_client_context_feed          (MilterClientContext *context,
                                                         const gchar *chunk,
                                                         gsize size,
                                                         GError **error);

Feeds a chunk to the context. You can use it for testing or debugging.

context :

a MilterClientContext.

chunk :

the string to be fed to context.

size :

the size of chunk.

error :

return location for an error, or NULL.

Returns :

TRUE on success.

milter_client_context_get_private_data ()

gpointer            milter_client_context_get_private_data
                                                        (MilterClientContext *context);

Gets the private data of the context.

context :

a MilterClientContext.

Returns :

the private data set by milter_client_context_set_private_data() or NULL.

milter_client_context_set_private_data ()

void                milter_client_context_set_private_data
                                                        (MilterClientContext *context,
                                                         gpointer data,
                                                         GDestroyNotify destroy);

Sets the private data of the context. data is destroyed by destroy when data is unset. data is unset when new private data is set or context is destroyed.

context :

a MilterClientContext.

data :

the private data.

destroy :

the destroy function for data or NULL.

milter_client_context_set_reply ()

gboolean            milter_client_context_set_reply     (MilterClientContext *context,
                                                         guint code,
                                                         const gchar *extended_code,
                                                         const gchar *message,
                                                         GError **error);

Sets the error reply code. 4xx code is used on MILTER_REPLY_TEMPORARY_FAILURE. 5xx code is used on MILTER_REPLY_REJECT.

See also smfi_setreply on milter.org.

context :

a MilterClientContext.

code :

the three-digit SMTP error reply code. (RFC 2821) Only 4xx and 5xx are accepted.

extended_code :

the extended reply code (RFC 1893/2034), or NULL.

message :

the text part of the SMTP reply, or NULL.

error :

return location for an error, or NULL.

Returns :

TRUE on success.

milter_client_context_format_reply ()

gchar*              milter_client_context_format_reply  (MilterClientContext *context);

Formats the current error reply code specified by milter_client_context_set_reply(). If error reply code isn't set, this function returns NULL.

context :

a MilterClientContext.

Returns :

formatted reply code, or NULL.

milter_client_context_add_header ()

gboolean            milter_client_context_add_header    (MilterClientContext *context,
                                                         const gchar *name,
                                                         const gchar *value,
                                                         GError **error);

Adds a header to the current message's header list. This function can be called in "end-of-message" signal.

See also smfi_addheader on milter.org.

FIXME: write about MILTER_ACTION_ADD_HEADERS.

context :

a MilterClientContext.

name :

the header name.

value :

the header value.

error :

return location for an error, or NULL.

Returns :

TRUE on success.

milter_client_context_insert_header ()

gboolean            milter_client_context_insert_header (MilterClientContext *context,
                                                         guint32 index,
                                                         const gchar *name,
                                                         const gchar *value,
                                                         GError **error);

Inserts a header into the current message's header lists at index. This function can be called in "end-of-message" signal. See also smfi_insheader on milter.org.

FIXME: write about MILTER_ACTION_ADD_HEADERS.

context :

a MilterClientContext.

index :

the index to be inserted.

name :

the header name.

value :

the header value.

error :

return location for an error, or NULL.

Returns :

TRUE on success.

milter_client_context_change_header ()

gboolean            milter_client_context_change_header (MilterClientContext *context,
                                                         const gchar *name,
                                                         guint32 index,
                                                         const gchar *value);

Changes a header that is located at index in headers that all of them are named name. If value is NULL, the header is deleted. This function can be called in "end-of-message" signal.

See also smfi_chgheader on milter.org.

FIXME: write about MILTER_ACTION_CHANGE_HEADERS.

context :

a MilterClientContext.

name :

the header name.

index :

the index of headers that all of them are named name. (1-based) FIXME: should change 0-based?

value :

the header value. Use NULL to delete the target header.

Returns :

TRUE on success.

milter_client_context_delete_header ()

gboolean            milter_client_context_delete_header (MilterClientContext *context,
                                                         const gchar *name,
                                                         guint32 index);

Deletes a header that is located at index in headers that all of them are named name. This function can be called in "end-of-message" signal. This function works same as milter_client_context_change_header() with NULL as value.

FIXME: write about MILTER_ACTION_CHANGE_HEADERS.

context :

a MilterClientContext.

name :

the header name.

index :

the index of headers that all of them are named name. (1-based) FIXME: should change 0-based?

Returns :

TRUE on success.

milter_client_context_change_from ()

gboolean            milter_client_context_change_from   (MilterClientContext *context,
                                                         const gchar *from,
                                                         const gchar *parameters);

Changes the envelope from address of the current message. ESMTP's 'MAIL FROM' parameter can be set by parameters. parameters may be NULL. This function can be called in "end-of-message" signal. See also smfi_chgfrom on milter.org.

FIXME: write about MILTER_ACTION_CHANGE_FROM.

context :

a MilterClientContext.

from :

the new envelope from address.

parameters :

the ESMTP's 'MAIL FROM' parameter. It can be NULL.

Returns :

TRUE on success.

milter_client_context_add_recipient ()

gboolean            milter_client_context_add_recipient (MilterClientContext *context,
                                                         const gchar *recipient,
                                                         const gchar *parameters);

Adds a new envelope recipient address to the current message. ESMTP's 'RCPT TO' parameter can be set by parameters. parameters may be NULL. This function can be called in "end-of-message" signal. See also smfi_addrcpt and smfi_addrcpt_par on milter.org.

FIXME: write about MILTER_ACTION_ADD_RECIPIENT and MILTER_ACTION_ADD_ENVELOPE_RECIPIENT_WITH_PARAMETERS.

context :

a MilterClientContext.

recipient :

the new envelope recipient address.

parameters :

the ESMTP's 'RCPT TO' parameter. It can be NULL.

Returns :

TRUE on success.

milter_client_context_delete_recipient ()

gboolean            milter_client_context_delete_recipient
                                                        (MilterClientContext *context,
                                                         const gchar *recipient);

Removes a envelope recipient that named recipient. This function can be called in "end-of-message" signal. See also smfi_delrcpt on milter.org.

FIXME: write about MILTER_ACTION_DELETE_RECIPIENT.

context :

a MilterClientContext.

recipient :

the envelope recipient address to be removed.

Returns :

TRUE on success.

milter_client_context_replace_body ()

gboolean            milter_client_context_replace_body  (MilterClientContext *context,
                                                         const gchar *body,
                                                         gsize body_size);

Replaces the body of the current message with body. This function can be called in "end-of-message" signal. See also smfi_replacebody on milter.org.

FIXME: write about MILTER_ACTION_CHANGE_BODY.

context :

a MilterClientContext.

body :

the new body.

body_size :

the size of body.

Returns :

TRUE on success.

milter_client_context_progress ()

gboolean            milter_client_context_progress      (MilterClientContext *context);

Notifies the MTA that this milter is still in progress. This function can be called in "end-of-message" signal. See also smfi_progress on milter.org.

context :

a MilterClientContext.

Returns :

TRUE on success.

milter_client_context_quarantine ()

gboolean            milter_client_context_quarantine    (MilterClientContext *context,
                                                         const gchar *reason);

Quarantines the current message with reason. This function can be called in "end-of-message" signal. See also smfi_quarantine on milter.org.

FIXME: write about MILTER_ACTION_QUARANTINE.

context :

a MilterClientContext.

reason :

the reason why the current message is quarantined.

Returns :

TRUE on success.

milter_client_context_set_timeout ()

void                milter_client_context_set_timeout   (MilterClientContext *context,
                                                         guint timeout);

Sets the timeout by seconds. If MTA doesn't responses in timeout seconds, "timeout" signal is emitted. See also smfi_settimeout on milter.org.

context :

a MilterClientContext.

timeout :

the timeout by seconds. (default is 7210 seconds)

milter_client_context_get_timeout ()

guint               milter_client_context_get_timeout   (MilterClientContext *context);

Gets the timeout by seconds.

context :

a MilterClientContext.

Returns :

timeout by seconds.

milter_client_context_set_state ()

void                milter_client_context_set_state     (MilterClientContext *context,
                                                         MilterClientContextState state);

Sets the current state.

context :

a MilterClientContext.

state :

a MilterClientContextState.

milter_client_context_get_state ()

MilterClientContextState milter_client_context_get_state
                                                        (MilterClientContext *context);

Gets the current state.

context :

a MilterClientContext.

Returns :

the current state.

milter_client_context_set_option ()

void                milter_client_context_set_option    (MilterClientContext *context,
                                                         MilterOption *option);

Sets the option for the context.

context :

a MilterClientContext.

option :

a MilterOption.

milter_client_context_get_option ()

MilterOption*       milter_client_context_get_option    (MilterClientContext *context);

Gets the option for the context.

context :

a MilterClientContext.

Returns :

the option for the context.