an effective anti-spam with milter - milter manager

Client library

Client library — The client library to implement a milter.

Description

The milter-client library provides full milter protocol processing features on client-side. "client-side" means milter-side not MTA-side.

MilterClient and MilterClientContext is the main classes in the milter-client library. MilterClient accepts n-connections from MTA and each connection is processed by MilterClientContext.

Usage overview

You need to set connection spec and connect “connection-established” signal before entering mail loop.

Connection spec is a entry point of MilterClient for MTA. It has 'PROTOCOL:INFORMATION' format. For IPv4 socket, 'inet:PORT', 'inet:PORT@HOST' or 'inet:PORT@[ADDRESS]' are valid formats. For IPv6 socket, 'inet6:PORT', 'inet6:PORT@HOST' or 'inet6:PORT@[ADDRESS]' are valid formats. For UNIX domain socket, 'unix:PATH' is a valid format.

MilterClient emits “connection-established” signal. MilterClientContext setup should be done in the signal. In many cases, you just connect callbacks to the passed MilterClientContext. See MilterClientContext for available signals.

milter_client_run() is running main loop function. You can enter into main loop after you finish to prepare your MilterClient.

Here is an example codes that uses the milter-client library. See also tool/milter-test-client.c. It is an example milter implementation using the milter-client library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdlib.h>
#include <milter/client.h>

static void
cb_connection_established (MilterClient *client,
                           MilterClientContext *context,
                           gpointer user_data)
{
   connect_to_your_interesting_signals(client, context, user_data);
}

int
main (int argc, char **argv)
{
    gboolean success;
    const gchar spec[] = "inet:10025@localhost";
    MilterClient *client;
    GError *error = NULL;

    milter_init();
    milter_client_init();

    client = milter_client_new();
    if (!milter_client_set_connection_spec(client, spec, &error)) {
        g_print("%s\n", error->message);
        g_error_free(error);
        return EXIT_FAILURE;
    }
    g_signal_connect(client, "connection-established",
                     G_CALLBACK(cb_connection_established), NULL);
    milter_client_run(client);

    milter_client_quit();
    milter_quit();

    return success ? EXIT_SUCCESS : EXIT_FAILURE;
}

Processing model

The libmilter provided by Sendmail uses a thread for each connection model. But the milter-client library doesn't use it. The milter-client library uses two threads. One thread is for MilterClient and other thread is for MilterClientContexts. MilterClient just accepting connections from MTA and dispatches it in the first thread. Each connection is associated with MilterClientContext and they are processed in the second thread. The milter-client library's model is the same model of memcached. (memcached uses libevent as its event loop backend but the milter-client library uses GLib's GMainLoop for it.)

The libmilter's model will have more cost to accept a connection rather than the milter-client library's model. Because the libmilter's model creates a thread but the milter-client library just allocate MilterClientContext. But in many case, this difference is not bottleneck. :-|

Functions

milter_client_init ()

void
milter_client_init (void);

Call this function before using any other the milter-client library functions.


milter_client_quit ()

void
milter_client_quit (void);

Call this function after the milter-client library use.


milter_client_get_option_group ()

GOptionGroup *
milter_client_get_option_group (MilterClient *client);

Gets a GOptionGroup for the client . The option group has common milter client options.

Parameters

client

a MilterClient.

 

Returns

a new GOptionGroup for client .

Types and Values