opnsense-src/contrib/sendmail/libmilter/docs/sample.html

538 lines
12 KiB
HTML
Raw Normal View History

2007-04-08 21:38:51 -04:00
<HTML>
<HEAD><TITLE>A Sample Filter</TITLE></HEAD>
<BODY>
2004-07-31 21:04:57 -04:00
<!--
2007-04-08 21:38:51 -04:00
$Id: sample.html,v 1.22 2006/10/09 23:14:51 ca Exp $
2004-07-31 21:04:57 -04:00
-->
2007-04-08 21:38:51 -04:00
<H1>A Sample Filter</H1>
2002-02-17 16:56:45 -05:00
The following sample logs each message to a separate temporary file,
2007-04-08 21:38:51 -04:00
adds a recipient given with the -a flag,
and rejects a disallowed recipient address given with the -r flag.
It recognizes the following options:
<P>
<CENTER>
<TABLE border="1" cellpadding=2 cellspacing=1>
<TR><TD><CODE>-p port</CODE></TD><TD>The port through which the MTA will connect to the filter.</TD></TR>
<TR><TD><CODE>-t sec</CODE></TD><TD>The timeout value.</TD></TR>
<TR><TD><CODE>-r addr</CODE></TD><TD>A recipient to reject.</TD></TR>
<TR><TD><CODE>-a addr</CODE></TD><TD>A recipient to add.</TD></TR>
</TABLE>
</CENTER>
<HR>
<PRE>
2002-06-11 17:12:04 -04:00
#include &lt;sys/types.h&gt;
#include &lt;sys/stat.h&gt;
#include &lt;errno.h&gt;
2002-02-17 16:56:45 -05:00
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#include &lt;sysexits.h&gt;
#include &lt;unistd.h&gt;
2002-06-11 17:12:04 -04:00
#include "libmilter/mfapi.h"
#ifndef bool
# define bool int
# define TRUE 1
# define FALSE 0
#endif /* ! bool */
2002-02-17 16:56:45 -05:00
struct mlfiPriv
{
2002-06-11 17:12:04 -04:00
char *mlfi_fname;
char *mlfi_connectfrom;
char *mlfi_helofrom;
FILE *mlfi_fp;
2002-02-17 16:56:45 -05:00
};
2007-04-08 21:38:51 -04:00
#define MLFIPRIV ((struct mlfiPriv *) <A href="smfi_getpriv.html">smfi_getpriv</A>(ctx))
2002-06-11 17:12:04 -04:00
extern sfsistat mlfi_cleanup(SMFICTX *, bool);
2002-02-17 16:56:45 -05:00
/* recipients to add and reject (set with -a and -r options) */
2002-06-11 17:12:04 -04:00
char *add = NULL;
char *reject = NULL;
2002-02-17 16:56:45 -05:00
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_connect.html">mlfi_connect</A>(ctx, hostname, hostaddr)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
char *hostname;
_SOCK_ADDR *hostaddr;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
struct mlfiPriv *priv;
char *ident;
/* allocate some private memory */
priv = malloc(sizeof *priv);
if (priv == NULL)
{
/* can't accept this message right now */
return SMFIS_TEMPFAIL;
}
memset(priv, '\0', sizeof *priv);
/* save the private data */
2007-04-08 21:38:51 -04:00
<A href="smfi_setpriv.html">smfi_setpriv</A>(ctx, priv);
2002-06-11 17:12:04 -04:00
2007-04-08 21:38:51 -04:00
ident = <A href="smfi_getsymval.html">smfi_getsymval</A>(ctx, "_");
2002-06-11 17:12:04 -04:00
if (ident == NULL)
ident = "???";
if ((priv-&gt;mlfi_connectfrom = strdup(ident)) == NULL)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
/* continue processing */
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_helo.html">mlfi_helo</A>(ctx, helohost)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
char *helohost;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
size_t len;
char *tls;
char *buf;
struct mlfiPriv *priv = MLFIPRIV;
2007-04-08 21:38:51 -04:00
tls = <A href="smfi_getsymval.html">smfi_getsymval</A>(ctx, "{tls_version}");
2002-06-11 17:12:04 -04:00
if (tls == NULL)
tls = "No TLS";
if (helohost == NULL)
helohost = "???";
len = strlen(tls) + strlen(helohost) + 3;
if ((buf = (char*) malloc(len)) == NULL)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
snprintf(buf, len, "%s, %s", helohost, tls);
if (priv-&gt;mlfi_helofrom != NULL)
free(priv-&gt;mlfi_helofrom);
priv-&gt;mlfi_helofrom = buf;
/* continue processing */
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_envfrom.html">mlfi_envfrom</A>(ctx, argv)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
char **argv;
2002-02-17 16:56:45 -05:00
{
2004-07-31 21:04:57 -04:00
int fd = -1;
int argc = 0;
2002-06-11 17:12:04 -04:00
struct mlfiPriv *priv = MLFIPRIV;
2007-04-08 21:38:51 -04:00
char *mailaddr = <A href="smfi_getsymval.html">smfi_getsymval</A>(ctx, "{mail_addr}");
2002-06-11 17:12:04 -04:00
/* open a file to store this message */
if ((priv-&gt;mlfi_fname = strdup("/tmp/msg.XXXXXX")) == NULL)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
2004-07-31 21:04:57 -04:00
if ((fd = mkstemp(priv-&gt;mlfi_fname)) == -1)
2002-06-11 17:12:04 -04:00
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
2004-07-31 21:04:57 -04:00
if ((priv-&gt;mlfi_fp = fdopen(fd, "w+")) == NULL)
2002-06-11 17:12:04 -04:00
{
2004-07-31 21:04:57 -04:00
(void) close(fd);
2002-06-11 17:12:04 -04:00
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
/* count the arguments */
while (*argv++ != NULL)
++argc;
/* log the connection information we stored earlier: */
if (fprintf(priv-&gt;mlfi_fp, "Connect from %s (%s)\n\n",
priv-&gt;mlfi_helofrom, priv-&gt;mlfi_connectfrom) == EOF)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
/* log the sender */
if (fprintf(priv-&gt;mlfi_fp, "FROM %s (%d argument%s)\n",
mailaddr ? mailaddr : "???", argc,
(argc == 1) ? "" : "s") == EOF)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
/* continue processing */
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_envrcpt.html">mlfi_envrcpt</A>(ctx, argv)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
char **argv;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
struct mlfiPriv *priv = MLFIPRIV;
2007-04-08 21:38:51 -04:00
char *rcptaddr = <A href="smfi_getsymval.html">smfi_getsymval</A>(ctx, "{rcpt_addr}");
2002-06-11 17:12:04 -04:00
int argc = 0;
/* count the arguments */
while (*argv++ != NULL)
++argc;
/* log this recipient */
if (reject != NULL && rcptaddr != NULL &&
(strcasecmp(rcptaddr, reject) == 0))
{
if (fprintf(priv-&gt;mlfi_fp, "RCPT %s -- REJECTED\n",
rcptaddr) == EOF)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
return SMFIS_REJECT;
}
if (fprintf(priv-&gt;mlfi_fp, "RCPT %s (%d argument%s)\n",
rcptaddr ? rcptaddr : "???", argc,
(argc == 1) ? "" : "s") == EOF)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
2002-02-17 16:56:45 -05:00
}
2002-06-11 17:12:04 -04:00
/* continue processing */
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_header.html">mlfi_header</A>(ctx, headerf, headerv)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
char *headerf;
unsigned char *headerv;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
/* write the header to the log file */
if (fprintf(MLFIPRIV-&gt;mlfi_fp, "%s: %s\n", headerf, headerv) == EOF)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
2002-02-17 16:56:45 -05:00
2002-06-11 17:12:04 -04:00
/* continue processing */
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_eoh.html">mlfi_eoh</A>(ctx)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
/* output the blank line between the header and the body */
if (fprintf(MLFIPRIV-&gt;mlfi_fp, "\n") == EOF)
{
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
2002-02-17 16:56:45 -05:00
2002-06-11 17:12:04 -04:00
/* continue processing */
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_body.html">mlfi_body</A>(ctx, bodyp, bodylen)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
unsigned char *bodyp;
size_t bodylen;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
struct mlfiPriv *priv = MLFIPRIV;
/* output body block to log file */
if (fwrite(bodyp, bodylen, 1, priv-&gt;mlfi_fp) != 1)
{
/* write failed */
fprintf(stderr, "Couldn't write file %s: %s\n",
priv-&gt;mlfi_fname, strerror(errno));
(void) mlfi_cleanup(ctx, FALSE);
return SMFIS_TEMPFAIL;
}
/* continue processing */
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_eom.html">mlfi_eom</A>(ctx)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
bool ok = TRUE;
/* change recipients, if requested */
if (add != NULL)
2007-04-08 21:38:51 -04:00
ok = (<A href="smfi_addrcpt.html">smfi_addrcpt</A>(ctx, add) == MI_SUCCESS);
2002-06-11 17:12:04 -04:00
return mlfi_cleanup(ctx, ok);
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_abort.html">mlfi_abort</A>(ctx)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
return mlfi_cleanup(ctx, FALSE);
2002-02-17 16:56:45 -05:00
}
sfsistat
mlfi_cleanup(ctx, ok)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
bool ok;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
sfsistat rstat = SMFIS_CONTINUE;
struct mlfiPriv *priv = MLFIPRIV;
char *p;
char host[512];
char hbuf[1024];
2002-02-17 16:56:45 -05:00
2002-06-11 17:12:04 -04:00
if (priv == NULL)
return rstat;
2002-02-17 16:56:45 -05:00
2002-06-11 17:12:04 -04:00
/* close the archive file */
if (priv-&gt;mlfi_fp != NULL && fclose(priv-&gt;mlfi_fp) == EOF)
{
/* failed; we have to wait until later */
fprintf(stderr, "Couldn't close archive file %s: %s\n",
priv-&gt;mlfi_fname, strerror(errno));
rstat = SMFIS_TEMPFAIL;
(void) unlink(priv-&gt;mlfi_fname);
}
else if (ok)
{
/* add a header to the message announcing our presence */
if (gethostname(host, sizeof host) &lt; 0)
snprintf(host, sizeof host, "localhost");
p = strrchr(priv-&gt;mlfi_fname, '/');
if (p == NULL)
p = priv-&gt;mlfi_fname;
else
p++;
snprintf(hbuf, sizeof hbuf, "%s@%s", p, host);
2007-04-08 21:38:51 -04:00
if (<A href="smfi_addheader.html">smfi_addheader</A>(ctx, "X-Archived", hbuf) != MI_SUCCESS)
2002-06-11 17:12:04 -04:00
{
/* failed; we have to wait until later */
fprintf(stderr,
"Couldn't add header: X-Archived: %s\n",
hbuf);
ok = FALSE;
rstat = SMFIS_TEMPFAIL;
(void) unlink(priv-&gt;mlfi_fname);
}
}
2002-02-17 16:56:45 -05:00
else
2002-06-11 17:12:04 -04:00
{
/* message was aborted -- delete the archive file */
fprintf(stderr, "Message aborted. Removing %s\n",
priv-&gt;mlfi_fname);
rstat = SMFIS_TEMPFAIL;
(void) unlink(priv-&gt;mlfi_fname);
}
/* release private memory */
if (priv-&gt;mlfi_fname != NULL)
free(priv-&gt;mlfi_fname);
/* return status */
return rstat;
2002-02-17 16:56:45 -05:00
}
sfsistat
2007-04-08 21:38:51 -04:00
<A href="xxfi_close.html">mlfi_close</A>(ctx)
2002-06-11 17:12:04 -04:00
SMFICTX *ctx;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
struct mlfiPriv *priv = MLFIPRIV;
if (priv == NULL)
return SMFIS_CONTINUE;
if (priv-&gt;mlfi_connectfrom != NULL)
free(priv-&gt;mlfi_connectfrom);
if (priv-&gt;mlfi_helofrom != NULL)
free(priv-&gt;mlfi_helofrom);
free(priv);
2007-04-08 21:38:51 -04:00
<A href="smfi_setpriv.html">smfi_setpriv</A>(ctx, NULL);
2002-06-11 17:12:04 -04:00
return SMFIS_CONTINUE;
2002-02-17 16:56:45 -05:00
}
2007-04-08 21:38:51 -04:00
sfsistat
<A href="xxfi_unknown.html">mlfi_unknown</A>(ctx, cmd)
SMFICTX *ctx;
char *cmd;
{
return SMFIS_CONTINUE;
}
sfsistat
<A href="xxfi_data.html">mlfi_data</A>(ctx)
SMFICTX *ctx;
{
return SMFIS_CONTINUE;
}
sfsistat
<A href="xxfi_negotiate.html">mlfi_negotiate</A>(ctx, f0, f1, f2, f3, pf0, pf1, pf2, pf3)
SMFICTX *ctx;
unsigned long f0;
unsigned long f1;
unsigned long f2;
unsigned long f3;
unsigned long *pf0;
unsigned long *pf1;
unsigned long *pf2;
unsigned long *pf3;
{
return SMFIS_ALL_OPTS;
}
2002-02-17 16:56:45 -05:00
struct smfiDesc smfilter =
{
2002-06-11 17:12:04 -04:00
"SampleFilter", /* filter name */
SMFI_VERSION, /* version code -- do not change */
2004-07-31 21:04:57 -04:00
SMFIF_ADDHDRS|SMFIF_ADDRCPT,
/* flags */
2007-04-08 21:38:51 -04:00
<A href="xxfi_connect.html">mlfi_connect</A>, /* connection info filter */
<A href="xxfi_helo.html">mlfi_helo</A>, /* SMTP HELO command filter */
<A href="xxfi_envfrom.html">mlfi_envfrom</A>, /* envelope sender filter */
<A href="xxfi_envrcpt.html">mlfi_envrcpt</A>, /* envelope recipient filter */
<A href="xxfi_header.html">mlfi_header</A>, /* header filter */
<A href="xxfi_eoh.html">mlfi_eoh</A>, /* end of header */
<A href="xxfi_body.html">mlfi_body</A>, /* body block filter */
<A href="xxfi_eom.html">mlfi_eom</A>, /* end of message */
<A href="xxfi_abort.html">mlfi_abort</A>, /* message aborted */
<A href="xxfi_close.html">mlfi_close</A>, /* connection cleanup */
<A href="xxfi_unknown.html">mlfi_unknown</A>, /* unknown SMTP commands */
<A href="xxfi_data.html">mlfi_data</A>, /* DATA command */
<A href="xxfi_negotiate.html">mlfi_negotiate</A> /* Once, at the start of each SMTP connection */
2002-02-17 16:56:45 -05:00
};
2002-06-11 17:12:04 -04:00
static void
usage(prog)
char *prog;
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
fprintf(stderr,
2003-09-19 19:11:30 -04:00
"Usage: %s -p socket-addr [-t timeout] [-r reject-addr] [-a add-addr]\n",
2002-06-11 17:12:04 -04:00
prog);
2002-02-17 16:56:45 -05:00
}
int
main(argc, argv)
2002-06-11 17:12:04 -04:00
int argc;
char **argv;
2002-02-17 16:56:45 -05:00
{
2003-09-19 19:11:30 -04:00
bool setconn = FALSE;
2002-06-11 17:12:04 -04:00
int c;
const char *args = "p:t:r:a:h";
extern char *optarg;
/* Process command line options */
while ((c = getopt(argc, argv, args)) != -1)
{
switch (c)
{
case 'p':
if (optarg == NULL || *optarg == '\0')
{
(void) fprintf(stderr, "Illegal conn: %s\n",
optarg);
exit(EX_USAGE);
}
2007-04-08 21:38:51 -04:00
if (<A href="smfi_setconn.html">smfi_setconn</A>(optarg) == MI_FAILURE)
2002-06-11 17:12:04 -04:00
{
(void) fprintf(stderr,
"smfi_setconn failed\n");
exit(EX_SOFTWARE);
}
/*
** If we're using a local socket, make sure it
** doesn't already exist. Don't ever run this
** code as root!!
*/
if (strncasecmp(optarg, "unix:", 5) == 0)
unlink(optarg + 5);
else if (strncasecmp(optarg, "local:", 6) == 0)
unlink(optarg + 6);
2003-09-19 19:11:30 -04:00
setconn = TRUE;
2002-06-11 17:12:04 -04:00
break;
case 't':
if (optarg == NULL || *optarg == '\0')
{
(void) fprintf(stderr, "Illegal timeout: %s\n",
optarg);
exit(EX_USAGE);
}
2007-04-08 21:38:51 -04:00
if (<A href="smfi_settimeout.html">smfi_settimeout</A>(atoi(optarg)) == MI_FAILURE)
2002-06-11 17:12:04 -04:00
{
(void) fprintf(stderr,
"smfi_settimeout failed\n");
exit(EX_SOFTWARE);
}
break;
case 'r':
if (optarg == NULL)
{
(void) fprintf(stderr,
"Illegal reject rcpt: %s\n",
optarg);
exit(EX_USAGE);
}
reject = optarg;
break;
case 'a':
if (optarg == NULL)
{
(void) fprintf(stderr,
"Illegal add rcpt: %s\n",
optarg);
exit(EX_USAGE);
}
add = optarg;
smfilter.xxfi_flags |= SMFIF_ADDRCPT;
break;
case 'h':
default:
usage(argv[0]);
exit(EX_USAGE);
}
}
2003-09-19 19:11:30 -04:00
if (!setconn)
{
fprintf(stderr, "%s: Missing required -p argument\n", argv[0]);
usage(argv[0]);
exit(EX_USAGE);
}
2007-04-08 21:38:51 -04:00
if (<A href="smfi_register.html">smfi_register</A>(smfilter) == MI_FAILURE)
2002-02-17 16:56:45 -05:00
{
2002-06-11 17:12:04 -04:00
fprintf(stderr, "smfi_register failed\n");
exit(EX_UNAVAILABLE);
2002-02-17 16:56:45 -05:00
}
2007-04-08 21:38:51 -04:00
return <A href="smfi_main.html">smfi_main</A>();
2002-02-17 16:56:45 -05:00
}
/* eof */
2007-04-08 21:38:51 -04:00
</PRE>
<HR size="1">
<FONT size="-1">
Copyright (c) 2000-2004, 2006 Sendmail, Inc. and its suppliers.
2002-02-17 16:56:45 -05:00
All rights reserved.
2007-04-08 21:38:51 -04:00
<BR>
2002-02-17 16:56:45 -05:00
By using this file, you agree to the terms and conditions set
2003-03-29 14:12:53 -05:00
forth in the LICENSE.
2007-04-08 21:38:51 -04:00
</FONT>
</BODY>
</HTML>