1*7c478bd9Sstevel@tonic-gate# 2*7c478bd9Sstevel@tonic-gate# Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate# Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate# 5*7c478bd9Sstevel@tonic-gate# ident "%Z%%M% %I% %E% SMI" 6*7c478bd9Sstevel@tonic-gate# 7*7c478bd9Sstevel@tonic-gate 8*7c478bd9Sstevel@tonic-gateThe sendmail Mail Filter API (Milter) is designed to allow third-party 9*7c478bd9Sstevel@tonic-gateprograms access to mail messages as they are being processed in order to 10*7c478bd9Sstevel@tonic-gatefilter meta-information and content. 11*7c478bd9Sstevel@tonic-gate 12*7c478bd9Sstevel@tonic-gateThis README file describes the steps needed to compile and run a filter, 13*7c478bd9Sstevel@tonic-gatethrough reference to a sample filter which is attached at the end of this 14*7c478bd9Sstevel@tonic-gatefile. 15*7c478bd9Sstevel@tonic-gate 16*7c478bd9Sstevel@tonic-gate+----------------+ 17*7c478bd9Sstevel@tonic-gate| SECURITY HINTS | 18*7c478bd9Sstevel@tonic-gate+----------------+ 19*7c478bd9Sstevel@tonic-gate 20*7c478bd9Sstevel@tonic-gateNote: we strongly recommend not to run any milter as root. Libmilter 21*7c478bd9Sstevel@tonic-gatedoes not need root access to communicate with sendmail. It is a 22*7c478bd9Sstevel@tonic-gategood security practice to run a program only with root privileges 23*7c478bd9Sstevel@tonic-gateif really necessary. A milter should probably check first whether 24*7c478bd9Sstevel@tonic-gateit runs as root and refuse to start in that case. libmilter will 25*7c478bd9Sstevel@tonic-gatenot unlink a socket when running as root. 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate+-------------------+ 28*7c478bd9Sstevel@tonic-gate| BUILDING A FILTER | 29*7c478bd9Sstevel@tonic-gate+-------------------+ 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gateThe following command presumes that the sample code from the end of this 32*7c478bd9Sstevel@tonic-gateREADME is saved to a file named 'sample.c'. 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate cc -D_REENTRANT -o sample sample.c -lmilter 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gateFilters must be thread-safe! 37*7c478bd9Sstevel@tonic-gate 38*7c478bd9Sstevel@tonic-gateNote that since filters use threads, it may be necessary to alter per 39*7c478bd9Sstevel@tonic-gateprocess limits in your filter. For example, you might look at using 40*7c478bd9Sstevel@tonic-gatesetrlimit() to increase the number of open file descriptors if your filter 41*7c478bd9Sstevel@tonic-gateis going to be busy. 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate+----------------------------------------+ 45*7c478bd9Sstevel@tonic-gate| SPECIFYING FILTERS IN SENDMAIL CONFIGS | 46*7c478bd9Sstevel@tonic-gate+----------------------------------------+ 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gateFilters are specified with a key letter ``X'' (for ``eXternal''). 49*7c478bd9Sstevel@tonic-gate 50*7c478bd9Sstevel@tonic-gateFor example: 51*7c478bd9Sstevel@tonic-gate 52*7c478bd9Sstevel@tonic-gate Xfilter1, S=local:/var/run/f1.sock, F=R 53*7c478bd9Sstevel@tonic-gate Xfilter2, S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m 54*7c478bd9Sstevel@tonic-gate Xfilter3, S=inet:3333@localhost 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gatespecifies three filters. Filters can be specified in your .mc file using 57*7c478bd9Sstevel@tonic-gatethe following: 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`filter1', `S=local:/var/run/f1.sock, F=R') 60*7c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`filter2', `S=inet6:999@localhost, F=T, T=C:10m;S:1s;R:1s;E:5m') 61*7c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`filter3', `S=inet:3333@localhost') 62*7c478bd9Sstevel@tonic-gate 63*7c478bd9Sstevel@tonic-gateThe first attaches to a Unix-domain socket in the /var/run directory; the 64*7c478bd9Sstevel@tonic-gatesecond uses an IPv6 socket on port 999 of localhost, and the third uses an 65*7c478bd9Sstevel@tonic-gateIPv4 socket on port 3333 of localhost. The current flags (F=) are: 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate R Reject connection if filter unavailable 68*7c478bd9Sstevel@tonic-gate T Temporary fail connection if filter unavailable 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gateIf neither F=R nor F=T is specified, the message is passed through sendmail 71*7c478bd9Sstevel@tonic-gatein case of filter errors as if the failing filters were not present. 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gateFinally, you can override the default timeouts used by sendmail when 74*7c478bd9Sstevel@tonic-gatetalking to the filters using the T= equate. There are four fields inside 75*7c478bd9Sstevel@tonic-gateof the T= equate: 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gateLetter Meaning 78*7c478bd9Sstevel@tonic-gate C Timeout for connecting to a filter (if 0, use system timeout) 79*7c478bd9Sstevel@tonic-gate S Timeout for sending information from the MTA to a filter 80*7c478bd9Sstevel@tonic-gate R Timeout for reading reply from the filter 81*7c478bd9Sstevel@tonic-gate E Overall timeout between sending end-of-message to filter 82*7c478bd9Sstevel@tonic-gate and waiting for the final acknowledgment 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gateNote the separator between each is a ';' as a ',' already separates equates 85*7c478bd9Sstevel@tonic-gateand therefore can't separate timeouts. The default values (if not set in 86*7c478bd9Sstevel@tonic-gatethe config) are: 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gateT=C:5m;S:10s;R:10s;E:5m 89*7c478bd9Sstevel@tonic-gate 90*7c478bd9Sstevel@tonic-gatewhere 's' is seconds and 'm' is minutes. 91*7c478bd9Sstevel@tonic-gate 92*7c478bd9Sstevel@tonic-gateWhich filters are invoked and their sequencing is handled by the 93*7c478bd9Sstevel@tonic-gateInputMailFilters option. Note: if InputMailFilters is not defined no filters 94*7c478bd9Sstevel@tonic-gatewill be used. 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate O InputMailFilters=filter1, filter2, filter3 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gateThis is is set automatically according to the order of the 99*7c478bd9Sstevel@tonic-gateINPUT_MAIL_FILTER commands in your .mc file. Alternatively, you can 100*7c478bd9Sstevel@tonic-gatereset its value by setting confINPUT_MAIL_FILTERS in your .mc file. 101*7c478bd9Sstevel@tonic-gateThis options causes the three filters to be called in the same order 102*7c478bd9Sstevel@tonic-gatethey were specified. It allows for possible future filtering on output 103*7c478bd9Sstevel@tonic-gate(although this is not intended for this release). 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gateAlso note that a filter can be defined without adding it to the input 106*7c478bd9Sstevel@tonic-gatefilter list by using MAIL_FILTER() instead of INPUT_MAIL_FILTER() in your 107*7c478bd9Sstevel@tonic-gate.mc file. 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gateTo test sendmail with the sample filter, the following might be added (in 110*7c478bd9Sstevel@tonic-gatethe appropriate locations) to your .mc file: 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate INPUT_MAIL_FILTER(`sample', `S=local:/var/run/f1.sock') 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate+------------------+ 116*7c478bd9Sstevel@tonic-gate| TESTING A FILTER | 117*7c478bd9Sstevel@tonic-gate+------------------+ 118*7c478bd9Sstevel@tonic-gate 119*7c478bd9Sstevel@tonic-gateOnce you have compiled a filter, modified your .mc file and restarted 120*7c478bd9Sstevel@tonic-gatethe sendmail process, you will want to test that the filter performs as 121*7c478bd9Sstevel@tonic-gateintended. 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gateThe sample filter takes one argument -p, which indicates the local port 124*7c478bd9Sstevel@tonic-gateon which to create a listening socket for the filter. Maintaining 125*7c478bd9Sstevel@tonic-gateconsistency with the suggested options for sendmail.cf, this would be the 126*7c478bd9Sstevel@tonic-gateUNIX domain socket located in /var/run/f1.sock. 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate % ./sample -p local:/var/run/f1.sock 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gateIf the sample filter returns immediately to a command line, there was either 131*7c478bd9Sstevel@tonic-gatean error with your command or a problem creating the specified socket. 132*7c478bd9Sstevel@tonic-gateFurther logging can be captured through the syslogd daemon. Using the 133*7c478bd9Sstevel@tonic-gate'netstat -a' command can ensure that your filter process is listening on 134*7c478bd9Sstevel@tonic-gatethe appropriate local socket. 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gateEmail messages must be injected via SMTP to be filtered. There are two 137*7c478bd9Sstevel@tonic-gatesimple means of doing this; either using the 'sendmail -bs' command, or 138*7c478bd9Sstevel@tonic-gateby telnetting to port 25 of the machine configured for milter. Once 139*7c478bd9Sstevel@tonic-gateconnected via one of these options, the session can be continued through 140*7c478bd9Sstevel@tonic-gatethe use of standard SMTP commands. 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate% sendmail -bs 143*7c478bd9Sstevel@tonic-gate220 test.sendmail.com ESMTP Sendmail 8.11.0/8.11.0; Tue, 10 Nov 1970 13:05:23 -0500 (EST) 144*7c478bd9Sstevel@tonic-gateHELO localhost 145*7c478bd9Sstevel@tonic-gate250 test.sendmail.com Hello testy@localhost, pleased to meet you 146*7c478bd9Sstevel@tonic-gateMAIL From:<testy> 147*7c478bd9Sstevel@tonic-gate250 2.1.0 <testy>... Sender ok 148*7c478bd9Sstevel@tonic-gateRCPT To:<root> 149*7c478bd9Sstevel@tonic-gate250 2.1.5 <root>... Recipient ok 150*7c478bd9Sstevel@tonic-gateDATA 151*7c478bd9Sstevel@tonic-gate354 Enter mail, end with "." on a line by itself 152*7c478bd9Sstevel@tonic-gateFrom: testy@test.sendmail.com 153*7c478bd9Sstevel@tonic-gateTo: root@test.sendmail.com 154*7c478bd9Sstevel@tonic-gateSubject: testing sample filter 155*7c478bd9Sstevel@tonic-gate 156*7c478bd9Sstevel@tonic-gateSample body 157*7c478bd9Sstevel@tonic-gate. 158*7c478bd9Sstevel@tonic-gate250 2.0.0 dB73Zxi25236 Message accepted for delivery 159*7c478bd9Sstevel@tonic-gateQUIT 160*7c478bd9Sstevel@tonic-gate221 2.0.0 test.sendmail.com closing connection 161*7c478bd9Sstevel@tonic-gate 162*7c478bd9Sstevel@tonic-gateIn the above example, the lines beginning with numbers are output by the 163*7c478bd9Sstevel@tonic-gatemail server, and those without are your input. If everything is working 164*7c478bd9Sstevel@tonic-gateproperly, you will find a file in /tmp by the name of msg.XXXXXXXX (where 165*7c478bd9Sstevel@tonic-gatethe Xs represent any combination of letters and numbers). This file should 166*7c478bd9Sstevel@tonic-gatecontain the message body and headers from the test email entered above. 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gateIf the sample filter did not log your test email, there are a number of 169*7c478bd9Sstevel@tonic-gatemethods to narrow down the source of the problem. Check your system 170*7c478bd9Sstevel@tonic-gatelogs written by syslogd and see if there are any pertinent lines. You 171*7c478bd9Sstevel@tonic-gatemay need to reconfigure syslogd to capture all relevant data. Additionally, 172*7c478bd9Sstevel@tonic-gatethe logging level of sendmail can be raised with the LogLevel option. 173*7c478bd9Sstevel@tonic-gateSee the sendmail(8) manual page for more information. 174*7c478bd9Sstevel@tonic-gate 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate+--------------------------+ 177*7c478bd9Sstevel@tonic-gate| SOURCE FOR SAMPLE FILTER | 178*7c478bd9Sstevel@tonic-gate+--------------------------+ 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate/* A trivial filter that logs all email to a file. */ 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate#include <sys/types.h> 183*7c478bd9Sstevel@tonic-gate#include <stdio.h> 184*7c478bd9Sstevel@tonic-gate#include <stdlib.h> 185*7c478bd9Sstevel@tonic-gate#include <string.h> 186*7c478bd9Sstevel@tonic-gate#include <sysexits.h> 187*7c478bd9Sstevel@tonic-gate#include <unistd.h> 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate#include "libmilter/mfapi.h" 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate#ifndef true 192*7c478bd9Sstevel@tonic-gatetypedef int bool; 193*7c478bd9Sstevel@tonic-gate# define false 0 194*7c478bd9Sstevel@tonic-gate# define true 1 195*7c478bd9Sstevel@tonic-gate#endif /* ! true */ 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gatestruct mlfiPriv 198*7c478bd9Sstevel@tonic-gate{ 199*7c478bd9Sstevel@tonic-gate char *mlfi_fname; 200*7c478bd9Sstevel@tonic-gate FILE *mlfi_fp; 201*7c478bd9Sstevel@tonic-gate}; 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate#define MLFIPRIV ((struct mlfiPriv *) smfi_getpriv(ctx)) 204*7c478bd9Sstevel@tonic-gate 205*7c478bd9Sstevel@tonic-gateextern sfsistat mlfi_cleanup(SMFICTX *, bool); 206*7c478bd9Sstevel@tonic-gate 207*7c478bd9Sstevel@tonic-gatesfsistat 208*7c478bd9Sstevel@tonic-gatemlfi_envfrom(ctx, envfrom) 209*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 210*7c478bd9Sstevel@tonic-gate char **envfrom; 211*7c478bd9Sstevel@tonic-gate{ 212*7c478bd9Sstevel@tonic-gate struct mlfiPriv *priv; 213*7c478bd9Sstevel@tonic-gate int fd = -1; 214*7c478bd9Sstevel@tonic-gate 215*7c478bd9Sstevel@tonic-gate /* allocate some private memory */ 216*7c478bd9Sstevel@tonic-gate priv = malloc(sizeof *priv); 217*7c478bd9Sstevel@tonic-gate if (priv == NULL) 218*7c478bd9Sstevel@tonic-gate { 219*7c478bd9Sstevel@tonic-gate /* can't accept this message right now */ 220*7c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate memset(priv, '\0', sizeof *priv); 223*7c478bd9Sstevel@tonic-gate 224*7c478bd9Sstevel@tonic-gate /* open a file to store this message */ 225*7c478bd9Sstevel@tonic-gate priv->mlfi_fname = strdup("/tmp/msg.XXXXXXXX"); 226*7c478bd9Sstevel@tonic-gate if (priv->mlfi_fname == NULL) 227*7c478bd9Sstevel@tonic-gate { 228*7c478bd9Sstevel@tonic-gate free(priv); 229*7c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate if ((fd = mkstemp(priv->mlfi_fname)) < 0 || 232*7c478bd9Sstevel@tonic-gate (priv->mlfi_fp = fdopen(fd, "w+")) == NULL) 233*7c478bd9Sstevel@tonic-gate { 234*7c478bd9Sstevel@tonic-gate if (fd >= 0) 235*7c478bd9Sstevel@tonic-gate (void) close(fd); 236*7c478bd9Sstevel@tonic-gate free(priv->mlfi_fname); 237*7c478bd9Sstevel@tonic-gate free(priv); 238*7c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* save the private data */ 242*7c478bd9Sstevel@tonic-gate smfi_setpriv(ctx, priv); 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate /* continue processing */ 245*7c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 246*7c478bd9Sstevel@tonic-gate} 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gatesfsistat 249*7c478bd9Sstevel@tonic-gatemlfi_header(ctx, headerf, headerv) 250*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 251*7c478bd9Sstevel@tonic-gate char *headerf; 252*7c478bd9Sstevel@tonic-gate char *headerv; 253*7c478bd9Sstevel@tonic-gate{ 254*7c478bd9Sstevel@tonic-gate /* write the header to the log file */ 255*7c478bd9Sstevel@tonic-gate fprintf(MLFIPRIV->mlfi_fp, "%s: %s\r\n", headerf, headerv); 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate /* continue processing */ 258*7c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 259*7c478bd9Sstevel@tonic-gate} 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gatesfsistat 262*7c478bd9Sstevel@tonic-gatemlfi_eoh(ctx) 263*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 264*7c478bd9Sstevel@tonic-gate{ 265*7c478bd9Sstevel@tonic-gate /* output the blank line between the header and the body */ 266*7c478bd9Sstevel@tonic-gate fprintf(MLFIPRIV->mlfi_fp, "\r\n"); 267*7c478bd9Sstevel@tonic-gate 268*7c478bd9Sstevel@tonic-gate /* continue processing */ 269*7c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 270*7c478bd9Sstevel@tonic-gate} 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gatesfsistat 273*7c478bd9Sstevel@tonic-gatemlfi_body(ctx, bodyp, bodylen) 274*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 275*7c478bd9Sstevel@tonic-gate u_char *bodyp; 276*7c478bd9Sstevel@tonic-gate size_t bodylen; 277*7c478bd9Sstevel@tonic-gate{ 278*7c478bd9Sstevel@tonic-gate /* output body block to log file */ 279*7c478bd9Sstevel@tonic-gate if (fwrite(bodyp, bodylen, 1, MLFIPRIV->mlfi_fp) == 0) 280*7c478bd9Sstevel@tonic-gate { 281*7c478bd9Sstevel@tonic-gate /* write failed */ 282*7c478bd9Sstevel@tonic-gate (void) mlfi_cleanup(ctx, false); 283*7c478bd9Sstevel@tonic-gate return SMFIS_TEMPFAIL; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate 286*7c478bd9Sstevel@tonic-gate /* continue processing */ 287*7c478bd9Sstevel@tonic-gate return SMFIS_CONTINUE; 288*7c478bd9Sstevel@tonic-gate} 289*7c478bd9Sstevel@tonic-gate 290*7c478bd9Sstevel@tonic-gatesfsistat 291*7c478bd9Sstevel@tonic-gatemlfi_eom(ctx) 292*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 293*7c478bd9Sstevel@tonic-gate{ 294*7c478bd9Sstevel@tonic-gate return mlfi_cleanup(ctx, true); 295*7c478bd9Sstevel@tonic-gate} 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gatesfsistat 298*7c478bd9Sstevel@tonic-gatemlfi_close(ctx) 299*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 300*7c478bd9Sstevel@tonic-gate{ 301*7c478bd9Sstevel@tonic-gate return SMFIS_ACCEPT; 302*7c478bd9Sstevel@tonic-gate} 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gatesfsistat 305*7c478bd9Sstevel@tonic-gatemlfi_abort(ctx) 306*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 307*7c478bd9Sstevel@tonic-gate{ 308*7c478bd9Sstevel@tonic-gate return mlfi_cleanup(ctx, false); 309*7c478bd9Sstevel@tonic-gate} 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gatesfsistat 312*7c478bd9Sstevel@tonic-gatemlfi_cleanup(ctx, ok) 313*7c478bd9Sstevel@tonic-gate SMFICTX *ctx; 314*7c478bd9Sstevel@tonic-gate bool ok; 315*7c478bd9Sstevel@tonic-gate{ 316*7c478bd9Sstevel@tonic-gate sfsistat rstat = SMFIS_CONTINUE; 317*7c478bd9Sstevel@tonic-gate struct mlfiPriv *priv = MLFIPRIV; 318*7c478bd9Sstevel@tonic-gate char *p; 319*7c478bd9Sstevel@tonic-gate char host[512]; 320*7c478bd9Sstevel@tonic-gate char hbuf[1024]; 321*7c478bd9Sstevel@tonic-gate 322*7c478bd9Sstevel@tonic-gate if (priv == NULL) 323*7c478bd9Sstevel@tonic-gate return rstat; 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate /* close the archive file */ 326*7c478bd9Sstevel@tonic-gate if (priv->mlfi_fp != NULL && fclose(priv->mlfi_fp) == EOF) 327*7c478bd9Sstevel@tonic-gate { 328*7c478bd9Sstevel@tonic-gate /* failed; we have to wait until later */ 329*7c478bd9Sstevel@tonic-gate rstat = SMFIS_TEMPFAIL; 330*7c478bd9Sstevel@tonic-gate (void) unlink(priv->mlfi_fname); 331*7c478bd9Sstevel@tonic-gate } 332*7c478bd9Sstevel@tonic-gate else if (ok) 333*7c478bd9Sstevel@tonic-gate { 334*7c478bd9Sstevel@tonic-gate /* add a header to the message announcing our presence */ 335*7c478bd9Sstevel@tonic-gate if (gethostname(host, sizeof host) < 0) 336*7c478bd9Sstevel@tonic-gate snprintf(host, sizeof host, "localhost"); 337*7c478bd9Sstevel@tonic-gate p = strrchr(priv->mlfi_fname, '/'); 338*7c478bd9Sstevel@tonic-gate if (p == NULL) 339*7c478bd9Sstevel@tonic-gate p = priv->mlfi_fname; 340*7c478bd9Sstevel@tonic-gate else 341*7c478bd9Sstevel@tonic-gate p++; 342*7c478bd9Sstevel@tonic-gate snprintf(hbuf, sizeof hbuf, "%s@%s", p, host); 343*7c478bd9Sstevel@tonic-gate smfi_addheader(ctx, "X-Archived", hbuf); 344*7c478bd9Sstevel@tonic-gate } 345*7c478bd9Sstevel@tonic-gate else 346*7c478bd9Sstevel@tonic-gate { 347*7c478bd9Sstevel@tonic-gate /* message was aborted -- delete the archive file */ 348*7c478bd9Sstevel@tonic-gate (void) unlink(priv->mlfi_fname); 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate 351*7c478bd9Sstevel@tonic-gate /* release private memory */ 352*7c478bd9Sstevel@tonic-gate free(priv->mlfi_fname); 353*7c478bd9Sstevel@tonic-gate free(priv); 354*7c478bd9Sstevel@tonic-gate smfi_setpriv(ctx, NULL); 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate /* return status */ 357*7c478bd9Sstevel@tonic-gate return rstat; 358*7c478bd9Sstevel@tonic-gate} 359*7c478bd9Sstevel@tonic-gate 360*7c478bd9Sstevel@tonic-gatestruct smfiDesc smfilter = 361*7c478bd9Sstevel@tonic-gate{ 362*7c478bd9Sstevel@tonic-gate "SampleFilter", /* filter name */ 363*7c478bd9Sstevel@tonic-gate SMFI_VERSION, /* version code -- do not change */ 364*7c478bd9Sstevel@tonic-gate SMFIF_ADDHDRS, /* flags */ 365*7c478bd9Sstevel@tonic-gate NULL, /* connection info filter */ 366*7c478bd9Sstevel@tonic-gate NULL, /* SMTP HELO command filter */ 367*7c478bd9Sstevel@tonic-gate mlfi_envfrom, /* envelope sender filter */ 368*7c478bd9Sstevel@tonic-gate NULL, /* envelope recipient filter */ 369*7c478bd9Sstevel@tonic-gate mlfi_header, /* header filter */ 370*7c478bd9Sstevel@tonic-gate mlfi_eoh, /* end of header */ 371*7c478bd9Sstevel@tonic-gate mlfi_body, /* body block filter */ 372*7c478bd9Sstevel@tonic-gate mlfi_eom, /* end of message */ 373*7c478bd9Sstevel@tonic-gate mlfi_abort, /* message aborted */ 374*7c478bd9Sstevel@tonic-gate mlfi_close /* connection cleanup */ 375*7c478bd9Sstevel@tonic-gate}; 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gateint 379*7c478bd9Sstevel@tonic-gatemain(argc, argv) 380*7c478bd9Sstevel@tonic-gate int argc; 381*7c478bd9Sstevel@tonic-gate char *argv[]; 382*7c478bd9Sstevel@tonic-gate{ 383*7c478bd9Sstevel@tonic-gate bool setconn = false; 384*7c478bd9Sstevel@tonic-gate int c; 385*7c478bd9Sstevel@tonic-gate const char *args = "p:"; 386*7c478bd9Sstevel@tonic-gate 387*7c478bd9Sstevel@tonic-gate /* Process command line options */ 388*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, args)) != -1) 389*7c478bd9Sstevel@tonic-gate { 390*7c478bd9Sstevel@tonic-gate switch (c) 391*7c478bd9Sstevel@tonic-gate { 392*7c478bd9Sstevel@tonic-gate case 'p': 393*7c478bd9Sstevel@tonic-gate if (optarg == NULL || *optarg == '\0') 394*7c478bd9Sstevel@tonic-gate { 395*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "Illegal conn: %s\n", 396*7c478bd9Sstevel@tonic-gate optarg); 397*7c478bd9Sstevel@tonic-gate exit(EX_USAGE); 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate (void) smfi_setconn(optarg); 400*7c478bd9Sstevel@tonic-gate setconn = true; 401*7c478bd9Sstevel@tonic-gate break; 402*7c478bd9Sstevel@tonic-gate 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate } 405*7c478bd9Sstevel@tonic-gate if (!setconn) 406*7c478bd9Sstevel@tonic-gate { 407*7c478bd9Sstevel@tonic-gate fprintf(stderr, "%s: Missing required -p argument\n", argv[0]); 408*7c478bd9Sstevel@tonic-gate exit(EX_USAGE); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate if (smfi_register(smfilter) == MI_FAILURE) 411*7c478bd9Sstevel@tonic-gate { 412*7c478bd9Sstevel@tonic-gate fprintf(stderr, "smfi_register failed\n"); 413*7c478bd9Sstevel@tonic-gate exit(EX_UNAVAILABLE); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate return smfi_main(); 416*7c478bd9Sstevel@tonic-gate} 417*7c478bd9Sstevel@tonic-gate 418*7c478bd9Sstevel@tonic-gate/* eof */ 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate$Revision: 8.35.2.2 $, Last updated $Date: 2003/05/26 04:10:06 $ 421