17c478bd9Sstevel@tonic-gate# 27c478bd9Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate# Use is subject to license terms. 47c478bd9Sstevel@tonic-gate# 57c478bd9Sstevel@tonic-gate# ident "%Z%%M% %I% %E% SMI" 67c478bd9Sstevel@tonic-gate# 77c478bd9Sstevel@tonic-gate 87c478bd9Sstevel@tonic-gateThe sendmail Mail Filter API (Milter) is designed to allow third-party 97c478bd9Sstevel@tonic-gateprograms access to mail messages as they are being processed in order to 107c478bd9Sstevel@tonic-gatefilter meta-information and content. 117c478bd9Sstevel@tonic-gate 127c478bd9Sstevel@tonic-gateThis README file describes the steps needed to compile and run a filter, 137c478bd9Sstevel@tonic-gatethrough reference to a sample filter which is attached at the end of this 147c478bd9Sstevel@tonic-gatefile. 157c478bd9Sstevel@tonic-gate 16*49218d4fSjbeckNote: if you want to write a milter in Java, then see 17*49218d4fSjbeckhttp://sendmail-jilter.sourceforge.net/ 18*49218d4fSjbeck 197c478bd9Sstevel@tonic-gate+----------------+ 207c478bd9Sstevel@tonic-gate| SECURITY HINTS | 217c478bd9Sstevel@tonic-gate+----------------+ 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gateNote: we strongly recommend not to run any milter as root. Libmilter 247c478bd9Sstevel@tonic-gatedoes not need root access to communicate with sendmail. It is a 257c478bd9Sstevel@tonic-gategood security practice to run a program only with root privileges 267c478bd9Sstevel@tonic-gateif really necessary. A milter should probably check first whether 277c478bd9Sstevel@tonic-gateit runs as root and refuse to start in that case. libmilter will 287c478bd9Sstevel@tonic-gatenot unlink a socket when running as root. 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate+-------------------+ 317c478bd9Sstevel@tonic-gate| BUILDING A FILTER | 327c478bd9Sstevel@tonic-gate+-------------------+ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gateThe following command presumes that the sample code from the end of this 357c478bd9Sstevel@tonic-gateREADME is saved to a file named 'sample.c'. 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate cc -D_REENTRANT -o sample sample.c -lmilter 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gateFilters must be thread-safe! 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gateNote that since filters use threads, it may be necessary to alter per 427c478bd9Sstevel@tonic-gateprocess limits in your filter. For example, you might look at using 437c478bd9Sstevel@tonic-gatesetrlimit() to increase the number of open file descriptors if your filter 447c478bd9Sstevel@tonic-gateis going to be busy. 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate+----------------------------------------+ 487c478bd9Sstevel@tonic-gate| SPECIFYING FILTERS IN SENDMAIL CONFIGS | 497c478bd9Sstevel@tonic-gate+----------------------------------------+ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gateFilters are specified with a key letter ``X'' (for ``eXternal''). 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gateFor example: 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate Xfilter1, S=local:/var/run/f1.sock, F=R 567c478bd9Sstevel@tonic-gate Xfilter2, S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m 577c478bd9Sstevel@tonic-gate Xfilter3, S=inet:3333@localhost 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gatespecifies three filters. Filters can be specified in your .mc file using 607c478bd9Sstevel@tonic-gatethe following: 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R') 637c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m') 647c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost') 657c478bd9Sstevel@tonic-gate 667c478bd9Sstevel@tonic-gateThe first attaches to a Unix-domain socket in the /var/run directory; the 677c478bd9Sstevel@tonic-gatesecond uses an IPv6 socket on port 999 of localhost, and the third uses an 687c478bd9Sstevel@tonic-gateIPv4 socket on port 3333 of localhost. The current flags (F=) are: 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate R Reject connection if filter unavailable 717c478bd9Sstevel@tonic-gate T Temporary fail connection if filter unavailable 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gateIf neither F=R nor F=T is specified, the message is passed through sendmail 747c478bd9Sstevel@tonic-gatein case of filter errors as if the failing filters were not present. 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gateFinally, you can override the default timeouts used by sendmail when 777c478bd9Sstevel@tonic-gatetalking to the filters using the T= equate. There are four fields inside 787c478bd9Sstevel@tonic-gateof the T= equate: 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gateLetter Meaning 817c478bd9Sstevel@tonic-gate C Timeout for connecting to a filter (if 0, use system timeout) 827c478bd9Sstevel@tonic-gate S Timeout for sending information from the MTA to a filter 837c478bd9Sstevel@tonic-gate R Timeout for reading reply from the filter 847c478bd9Sstevel@tonic-gate E Overall timeout between sending end-of-message to filter 857c478bd9Sstevel@tonic-gate and waiting for the final acknowledgment 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gateNote the separator between each is a ';' as a ',' already separates equates 887c478bd9Sstevel@tonic-gateand therefore can't separate timeouts. The default values (if not set in 897c478bd9Sstevel@tonic-gatethe config) are: 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gateT=C:5m;S:10s;R:10s;E:5m 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gatewhere 's' is seconds and 'm' is minutes. 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gateWhich filters are invoked and their sequencing is handled by the 967c478bd9Sstevel@tonic-gateInputMailFilters option. Note: if InputMailFilters is not defined no filters 977c478bd9Sstevel@tonic-gatewill be used. 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate O InputMailFilters=filter1, filter2, filter3 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gateThis is is set automatically according to the order of the 1027c478bd9Sstevel@tonic-gateINPUT_MAIL_FILTER commands in your .mc file. Alternatively, you can 1037c478bd9Sstevel@tonic-gatereset its value by setting confINPUT_MAIL_FILTERS in your .mc file. 1047c478bd9Sstevel@tonic-gateThis options causes the three filters to be called in the same order 1057c478bd9Sstevel@tonic-gatethey were specified. It allows for possible future filtering on output 1067c478bd9Sstevel@tonic-gate(although this is not intended for this release). 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gateAlso note that a filter can be defined without adding it to the input 1097c478bd9Sstevel@tonic-gatefilter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your 1107c478bd9Sstevel@tonic-gate.mc file. 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gateTo test sendmail with the sample filter, the following might be added (in 1137c478bd9Sstevel@tonic-gatethe appropriate locations) to your .mc file: 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock') 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate+------------------+ 1197c478bd9Sstevel@tonic-gate| TESTING A FILTER | 1207c478bd9Sstevel@tonic-gate+------------------+ 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gateOnce you have compiled a filter, modified your .mc file and restarted 1237c478bd9Sstevel@tonic-gatethe sendmail process, you will want to test that the filter performs as 1247c478bd9Sstevel@tonic-gateintended. 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gateThe sample filter takes one argument -p, which indicates the local port 1277c478bd9Sstevel@tonic-gateon which to create a listening socket for the filter. Maintaining 1287c478bd9Sstevel@tonic-gateconsistency with the suggested options for sendmail.cf, this would be the 1297c478bd9Sstevel@tonic-gateUNIX domain socket located in /var/run/f1.sock. 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate % ./sample -p local:/var/run/f1.sock 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gateIf the sample filter returns immediately to a command line, there was either 1347c478bd9Sstevel@tonic-gatean error with your command or a problem creating the specified socket. 1357c478bd9Sstevel@tonic-gateFurther logging can be captured through the syslogd daemon. Using the 1367c478bd9Sstevel@tonic-gate'netstat -a' command can ensure that your filter process is listening on 1377c478bd9Sstevel@tonic-gatethe appropriate local socket. 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gateEmail messages must be injected via SMTP to be filtered. There are two 1407c478bd9Sstevel@tonic-gatesimple means of doing this; either using the 'sendmail -bs' command, or 1417c478bd9Sstevel@tonic-gateby telnetting to port 25 of the machine configured for milter. Once 1427c478bd9Sstevel@tonic-gateconnected via one of these options, the session can be continued through 1437c478bd9Sstevel@tonic-gatethe use of standard SMTP commands. 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate% sendmail -bs 1467c478bd9Sstevel@tonic-gate220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST) 1477c478bd9Sstevel@tonic-gateHELO localhost 1487c478bd9Sstevel@tonic-gate250 test.sendmail.com Hello testy@localhost, pleased to meet you 1497c478bd9Sstevel@tonic-gateMAIL From:<testy> 1507c478bd9Sstevel@tonic-gate250 2.1.0 <testy>... Sender ok 1517c478bd9Sstevel@tonic-gateRCPT To:<root> 1527c478bd9Sstevel@tonic-gate250 2.1.5 <root>... Recipient ok 1537c478bd9Sstevel@tonic-gateDATA 1547c478bd9Sstevel@tonic-gate354 Enter mail, end with "." on a line by itself 1557c478bd9Sstevel@tonic-gateFrom: testy@test.sendmail.com 1567c478bd9Sstevel@tonic-gateTo: root@test.sendmail.com 1577c478bd9Sstevel@tonic-gateSubject: testing sample filter 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gateSample body 1607c478bd9Sstevel@tonic-gate. 1617c478bd9Sstevel@tonic-gate250 2.0.0 dB73Zxi25236 Message accepted for delivery 1627c478bd9Sstevel@tonic-gateQUIT 1637c478bd9Sstevel@tonic-gate221 2.0.0 test.sendmail.com closing connection 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gateIn the above example, the lines beginning with numbers are output by the 1667c478bd9Sstevel@tonic-gatemail server, and those without are your input. If everything is working 1677c478bd9Sstevel@tonic-gateproperly, you will find a file in /tmp by the name of msg.XXXXXXXX (where 1687c478bd9Sstevel@tonic-gatethe Xs represent any combination of letters and numbers). This file should 1697c478bd9Sstevel@tonic-gatecontain the message body and headers from the test email entered above. 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gateIf the sample filter did not log your test email, there are a number of 1727c478bd9Sstevel@tonic-gatemethods to narrow down the source of the problem. Check your system 1737c478bd9Sstevel@tonic-gatelogs written by syslogd and see if there are any pertinent lines. You 1747c478bd9Sstevel@tonic-gatemay need to reconfigure syslogd to capture all relevant data. Additionally, 1757c478bd9Sstevel@tonic-gatethe logging level of sendmail can be raised with the LogLevel option. 1767c478bd9Sstevel@tonic-gateSee the sendmail(8) manual page for more information. 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate+--------------------------+ 1807c478bd9Sstevel@tonic-gate| SOURCE FOR SAMPLE FILTER | 1817c478bd9Sstevel@tonic-gate+--------------------------+ 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate/* A trivial filter that logs all email to a file. */ 1847c478bd9Sstevel@tonic-gate 1857c478bd9Sstevel@tonic-gate#include <sys/types.h> 1867c478bd9Sstevel@tonic-gate#include <stdio.h> 1877c478bd9Sstevel@tonic-gate#include <stdlib.h> 1887c478bd9Sstevel@tonic-gate#include <string.h> 1897c478bd9Sstevel@tonic-gate#include <sysexits.h> 1907c478bd9Sstevel@tonic-gate#include <unistd.h> 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate#include "libmilter/mfapi.h" 1937c478bd9Sstevel@tonic-gate 1947c478bd9Sstevel@tonic-gate#ifndef true 1957c478bd9Sstevel@tonic-gatetypedef int bool; 1967c478bd9Sstevel@tonic-gate# define false 0 1977c478bd9Sstevel@tonic-gate# define true 1 1987c478bd9Sstevel@tonic-gate#endif /* ! true */ 1997c478bd9Sstevel@tonic-gate 2007c478bd9Sstevel@tonic-gatestruct mlfiPriv 2017c478bd9Sstevel@tonic-gate{ 2027c478bd9Sstevel@tonic-gate char *mlfi_fname; 2037c478bd9Sstevel@tonic-gate FILE *mlfi_fp; 2047c478bd9Sstevel@tonic-gate}; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx)) 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gateextern sfsistat mlfi_cleanup(SMFICTX *, bool); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gatesfsistat 2117c478bd9Sstevel@tonic-gatemlfi_envfrom(ctx, envfrom) 2127c478bd9Sstevel@tonic-gate SMFICTX *ctx; 2137c478bd9Sstevel@tonic-gate char **envfrom; 2147c478bd9Sstevel@tonic-gate{ 2157c478bd9Sstevel@tonic-gate struct mlfiPriv *priv; 2167c478bd9Sstevel@tonic-gate int fd = -1; 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* allocate some private memory */ 2197c478bd9Sstevel@tonic-gate priv = malloc(sizeof *priv); 2207c478bd9Sstevel@tonic-gate if (priv == NULL) 2217c478bd9Sstevel@tonic-gate { 2227c478bd9Sstevel@tonic-gate /* can't accept this message right now */ 2237c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 2247c478bd9Sstevel@tonic-gate } 2257c478bd9Sstevel@tonic-gate memset(priv, '\0', sizeof *priv); 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate /* open a file to store this message */ 2287c478bd9Sstevel@tonic-gate priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX"); 2297c478bd9Sstevel@tonic-gate if (priv->mlfi_fname == NULL) 2307c478bd9Sstevel@tonic-gate { 2317c478bd9Sstevel@tonic-gate free(priv); 2327c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 2337c478bd9Sstevel@tonic-gate } 2347c478bd9Sstevel@tonic-gate if ((fd = mkstemp(priv->mlfi_fname)) < 0 || 2357c478bd9Sstevel@tonic-gate (priv->mlfi_fp = fdopen(fd, "w+")) == NULL) 2367c478bd9Sstevel@tonic-gate { 2377c478bd9Sstevel@tonic-gate if (fd >= 0) 2387c478bd9Sstevel@tonic-gate (void) close(fd); 2397c478bd9Sstevel@tonic-gate free(priv->mlfi_fname); 2407c478bd9Sstevel@tonic-gate free(priv); 2417c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate 2447c478bd9Sstevel@tonic-gate /* save the private data */ 2457c478bd9Sstevel@tonic-gate smfi_setpriv(ctx, priv); 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* continue processing */ 2487c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 2497c478bd9Sstevel@tonic-gate} 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gatesfsistat 2527c478bd9Sstevel@tonic-gatemlfi_header(ctx, headerf, headerv) 2537c478bd9Sstevel@tonic-gate SMFICTX *ctx; 2547c478bd9Sstevel@tonic-gate char *headerf; 2557c478bd9Sstevel@tonic-gate char *headerv; 2567c478bd9Sstevel@tonic-gate{ 2577c478bd9Sstevel@tonic-gate /* write the header to the log file */ 2587c478bd9Sstevel@tonic-gate fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate /* continue processing */ 2617c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 2627c478bd9Sstevel@tonic-gate} 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gatesfsistat 2657c478bd9Sstevel@tonic-gatemlfi_eoh(ctx) 2667c478bd9Sstevel@tonic-gate SMFICTX *ctx; 2677c478bd9Sstevel@tonic-gate{ 2687c478bd9Sstevel@tonic-gate /* output the blank line between the header and the body */ 2697c478bd9Sstevel@tonic-gate fprintf(MLFIPRIV->mlfi_fp, "\r\n"); 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* continue processing */ 2727c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 2737c478bd9Sstevel@tonic-gate} 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gatesfsistat 2767c478bd9Sstevel@tonic-gatemlfi_body(ctx, bodyp, bodylen) 2777c478bd9Sstevel@tonic-gate SMFICTX *ctx; 2787c478bd9Sstevel@tonic-gate u_char *bodyp; 2797c478bd9Sstevel@tonic-gate size_t bodylen; 2807c478bd9Sstevel@tonic-gate{ 2817c478bd9Sstevel@tonic-gate /* output body block to log file */ 2827c478bd9Sstevel@tonic-gate if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) == 0) 2837c478bd9Sstevel@tonic-gate { 2847c478bd9Sstevel@tonic-gate /* write failed */ 2857c478bd9Sstevel@tonic-gate (void) mlfi_cleanup(ctx, false); 2867c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 2877c478bd9Sstevel@tonic-gate } 2887c478bd9Sstevel@tonic-gate 2897c478bd9Sstevel@tonic-gate /* continue processing */ 2907c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 2917c478bd9Sstevel@tonic-gate} 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gatesfsistat 2947c478bd9Sstevel@tonic-gatemlfi_eom(ctx) 2957c478bd9Sstevel@tonic-gate SMFICTX *ctx; 2967c478bd9Sstevel@tonic-gate{ 2977c478bd9Sstevel@tonic-gate return mlfi_cleanup(ctx, true); 2987c478bd9Sstevel@tonic-gate} 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gatesfsistat 3017c478bd9Sstevel@tonic-gatemlfi_close(ctx) 3027c478bd9Sstevel@tonic-gate SMFICTX *ctx; 3037c478bd9Sstevel@tonic-gate{ 3047c478bd9Sstevel@tonic-gate return SMFIS_ACCEPT; 3057c478bd9Sstevel@tonic-gate} 3067c478bd9Sstevel@tonic-gate 3077c478bd9Sstevel@tonic-gatesfsistat 3087c478bd9Sstevel@tonic-gatemlfi_abort(ctx) 3097c478bd9Sstevel@tonic-gate SMFICTX *ctx; 3107c478bd9Sstevel@tonic-gate{ 3117c478bd9Sstevel@tonic-gate return mlfi_cleanup(ctx, false); 3127c478bd9Sstevel@tonic-gate} 3137c478bd9Sstevel@tonic-gate 3147c478bd9Sstevel@tonic-gatesfsistat 3157c478bd9Sstevel@tonic-gatemlfi_cleanup(ctx, ok) 3167c478bd9Sstevel@tonic-gate SMFICTX *ctx; 3177c478bd9Sstevel@tonic-gate bool ok; 3187c478bd9Sstevel@tonic-gate{ 3197c478bd9Sstevel@tonic-gate sfsistat rstat = SMFIS_CONTINUE; 3207c478bd9Sstevel@tonic-gate struct mlfiPriv *priv = MLFIPRIV; 3217c478bd9Sstevel@tonic-gate char *p; 3227c478bd9Sstevel@tonic-gate char host[512]; 3237c478bd9Sstevel@tonic-gate char hbuf[1024]; 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate if (priv == NULL) 3267c478bd9Sstevel@tonic-gate return rstat; 3277c478bd9Sstevel@tonic-gate 3287c478bd9Sstevel@tonic-gate /* close the archive file */ 3297c478bd9Sstevel@tonic-gate if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF) 3307c478bd9Sstevel@tonic-gate { 3317c478bd9Sstevel@tonic-gate /* failed; we have to wait until later */ 3327c478bd9Sstevel@tonic-gate rstat = SMFIS_TEMPFAIL; 3337c478bd9Sstevel@tonic-gate (void) unlink(priv->mlfi_fname); 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate else if (ok) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate /* add a header to the message announcing our presence */ 3387c478bd9Sstevel@tonic-gate if (gethostname(host, sizeof host) < 0) 3397c478bd9Sstevel@tonic-gate snprintf(host, sizeof host, "localhost"); 3407c478bd9Sstevel@tonic-gate p = strrchr(priv->mlfi_fname, '/'); 3417c478bd9Sstevel@tonic-gate if (p == NULL) 3427c478bd9Sstevel@tonic-gate p = priv->mlfi_fname; 3437c478bd9Sstevel@tonic-gate else 3447c478bd9Sstevel@tonic-gate p++; 3457c478bd9Sstevel@tonic-gate snprintf(hbuf, sizeof hbuf, "%s@%s", p, host); 3467c478bd9Sstevel@tonic-gate smfi_addheader(ctx, "X-Archived", hbuf); 3477c478bd9Sstevel@tonic-gate } 3487c478bd9Sstevel@tonic-gate else 3497c478bd9Sstevel@tonic-gate { 3507c478bd9Sstevel@tonic-gate /* message was aborted -- delete the archive file */ 3517c478bd9Sstevel@tonic-gate (void) unlink(priv->mlfi_fname); 3527c478bd9Sstevel@tonic-gate } 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate /* release private memory */ 3557c478bd9Sstevel@tonic-gate free(priv->mlfi_fname); 3567c478bd9Sstevel@tonic-gate free(priv); 3577c478bd9Sstevel@tonic-gate smfi_setpriv(ctx, NULL); 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate /* return status */ 3607c478bd9Sstevel@tonic-gate return rstat; 3617c478bd9Sstevel@tonic-gate} 3627c478bd9Sstevel@tonic-gate 3637c478bd9Sstevel@tonic-gatestruct smfiDesc smfilter = 3647c478bd9Sstevel@tonic-gate{ 3657c478bd9Sstevel@tonic-gate "SampleFilter", /* filter name */ 3667c478bd9Sstevel@tonic-gate SMFI_VERSION, /* version code -- do not change */ 3677c478bd9Sstevel@tonic-gate SMFIF_ADDHDRS, /* flags */ 3687c478bd9Sstevel@tonic-gate NULL, /* connection info filter */ 3697c478bd9Sstevel@tonic-gate NULL, /* SMTP HELO command filter */ 3707c478bd9Sstevel@tonic-gate mlfi_envfrom, /* envelope sender filter */ 3717c478bd9Sstevel@tonic-gate NULL, /* envelope recipient filter */ 3727c478bd9Sstevel@tonic-gate mlfi_header, /* header filter */ 3737c478bd9Sstevel@tonic-gate mlfi_eoh, /* end of header */ 3747c478bd9Sstevel@tonic-gate mlfi_body, /* body block filter */ 3757c478bd9Sstevel@tonic-gate mlfi_eom, /* end of message */ 3767c478bd9Sstevel@tonic-gate mlfi_abort, /* message aborted */ 3777c478bd9Sstevel@tonic-gate mlfi_close /* connection cleanup */ 3787c478bd9Sstevel@tonic-gate}; 3797c478bd9Sstevel@tonic-gate 3807c478bd9Sstevel@tonic-gate 3817c478bd9Sstevel@tonic-gateint 3827c478bd9Sstevel@tonic-gatemain(argc, argv) 3837c478bd9Sstevel@tonic-gate int argc; 3847c478bd9Sstevel@tonic-gate char *argv[]; 3857c478bd9Sstevel@tonic-gate{ 3867c478bd9Sstevel@tonic-gate bool setconn = false; 3877c478bd9Sstevel@tonic-gate int c; 3887c478bd9Sstevel@tonic-gate const char *args = "p:"; 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate /* Process command line options */ 3917c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, args)) != -1) 3927c478bd9Sstevel@tonic-gate { 3937c478bd9Sstevel@tonic-gate switch (c) 3947c478bd9Sstevel@tonic-gate { 3957c478bd9Sstevel@tonic-gate case 'p': 3967c478bd9Sstevel@tonic-gate if (optarg == NULL || *optarg == '\0') 3977c478bd9Sstevel@tonic-gate { 3987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Illegal conn: %s\n", 3997c478bd9Sstevel@tonic-gate optarg); 4007c478bd9Sstevel@tonic-gate exit(EX_USAGE); 4017c478bd9Sstevel@tonic-gate } 4027c478bd9Sstevel@tonic-gate (void) smfi_setconn(optarg); 4037c478bd9Sstevel@tonic-gate setconn = true; 4047c478bd9Sstevel@tonic-gate break; 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate } 4077c478bd9Sstevel@tonic-gate } 4087c478bd9Sstevel@tonic-gate if (!setconn) 4097c478bd9Sstevel@tonic-gate { 4107c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: Missing required -p argument\n", argv[0]); 4117c478bd9Sstevel@tonic-gate exit(EX_USAGE); 4127c478bd9Sstevel@tonic-gate } 4137c478bd9Sstevel@tonic-gate if (smfi_register(smfilter) == MI_FAILURE) 4147c478bd9Sstevel@tonic-gate { 4157c478bd9Sstevel@tonic-gate fprintf(stderr, "smfi_register failed\n"); 4167c478bd9Sstevel@tonic-gate exit(EX_UNAVAILABLE); 4177c478bd9Sstevel@tonic-gate } 4187c478bd9Sstevel@tonic-gate return smfi_main(); 4197c478bd9Sstevel@tonic-gate} 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate/* eof */ 4227c478bd9Sstevel@tonic-gate 423*49218d4fSjbeck$Revision: 8.41 $, Last updated $Date: 2005/04/27 22:47:42 $ 424