Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
miltertest(8)		    System Manager's Manual		 miltertest(8)

NAME
       miltertest - milter unit	test utility

SYNOPSIS
       miltertest [-D name[=value]] [-s	script]	[-u] [-v] [-V] [-w]

DESCRIPTION
       miltertest  simulates  the  MTA	side  of an MTA-milter interaction for
       testing a milter-aware filter application.  It takes as input a	script
       using  the Lua language,	and by exporting some utility functions, makes
       it possible for users to	write scripts that exercise a filter.

       See documentation on Lua	(e.g. http://www.lua.org) for  the  syntax  of
       the  language  in general.  The documentation below describes functions
       that are	added to Lua by	this application to make testing possible.

       Documentation on	milter can be found at http://www.milter.org.  A  par-
       ticular	transaction  must  follow  a  series of	steps to be completed,
       namely negotiate, connection information, envelope sender, envelope re-
       cipient(s),  header field(s), end-of-header, body chunk(s), end-of-mes-
       sage.  To make the work of writing tests	with miltertest	 simpler,  any
       of  these  steps	prior to end-of-message	that is	skipped	will be	filled
       in using	arbitrary, but legal, data.

       Interspersed with these protocol	phases are optional macro  (key/value)
       deliveries  from	 the  MTA.  miltertest will never send these automati-
       cally.  If they are needed for your tests, you must send	them  as  part
       of your test script.

OPTIONS
       -D name[=value]
	      Defines  a  global  variable called name to the Lua interpreter.
	      If a value is provided, the global variable is set to that value
	      (as a string, although Lua can convert strings to	numbers	inter-
	      nally).  If no value is provided,	the global variable is set  to
	      1.

       -s script
	      Use  the	contents  of  file script as the Lua script to be exe-
	      cuted.  The default is to	read from standard input.

       -u     After the	filter being tested is	terminated,  report  user  and
	      system time consumed.  See getrusage(2).

       -v     Increase verbose output.	May be specified multiple times	to re-
	      quest more and more information.

       -V     Print version number and exit.

       -w     Don't wait for child status to be	returned when testing is  com-
	      plete.

FUNCTIONS
       The  following functions	are made available to Lua scripts for exercis-
       ing a filter.  All functions return Lua constant	"nil" on success or an
       error string on failure,	unless otherwise indicated.

       mt.abort(conn)
	      Aborts the transaction in	progress on the	specified connection.

       mt.bodyfile(conn, file)
	      Sends  the  contents of the named	file to	the connection as body
	      data.  If	there is any error opening file	for reading, the  test
	      aborts.

       mt.bodyrandom(conn, n)
	      Sends  at	 least n bytes of random-length	lines of random	print-
	      able ASCII data as body chunks to	the specified connection.

       mt.bodystring(conn, str)
	      Sends str	as a chunk of body text	on the specified connection.

       mt.chdir(directory)
	      Changes the current working directory to the named directory.

       mt.connect(sockinfo[, count, interval])
	      Makes a connection to a filter listening at the socket described
	      by  sockinfo.  Returns a handle referring	to that	connection, or
	      the Lua constant "nil" on	error.	If count and interval are  in-
	      cluded,  they  specify  the number of times to try to connect to
	      the filter and the delay	between	 each  connection  in  seconds
	      (with  floating  point  values  permitted).   If the environment
	      variable MILTERTEST_RETRY_SPEED_FACTOR is	 set  and  appears  to
	      contain  an integer, the value of	interval (if set) will be mul-
	      tiplied by the value found in that environment  variable.	  This
	      is  included  to	allow tests in a large test suite to be	easily
	      adjusted on slow systems without reconfiguring the  entire  test
	      suite.

       mt.conninfo(conn, host, ip)
	      Sends information	about a	new SMTP connection to the MTA,	repre-
	      sented by	connection conn, from the host named host  at  IP  ad-
	      dress ip (both strings).	If host	is the Lua constant "nil", the
	      string "localhost" is assumed.  If ip is the Lua constant	"nil",
	      a	 DNS  query  will be made for the IP address matching host; if
	      none is found, the test will abort.  The ip may also be the spe-
	      cial  string "unspec", which will	tell the filter	that a connec-
	      tion came	in from	an unknown protocol family.

       mt.data(conn)
	      Announces	the DATA command on the	 specified  connection,	 which
	      occurs between the last RCPT TO command and the beginning	of the
	      header block.

       mt.disconnect(conn[, polite]))
	      Sends a "quit" message to	 the  specified	 connection  and  then
	      closes  that  connection.	  The  specified conn handle should no
	      longer be	used.  If polite is defined, it	must be	a Boolean  in-
	      dicating whether a normal	disconnect should be done (true) or an
	      abrupt disconnect	should be done (false).	 An abrupt  disconnect
	      skips standard protocol shutdown steps.

       mt.echo(string)
	      Prints  the  specified string on standard	output.	 Returns noth-
	      ing.

       mt.eoh(conn)
	      Announces	end-of-header on the specified connection.

       mt.eom(conn)
	      Announces	end-of-message on the specified	connection, and	begins
	      capturing	 any other operations the filter might perform in that
	      phase.

       mt.eom_check(conn, op, param[, ...])
	      Checks the captured set of EOM operations	(see above) to	deter-
	      mine  whether  or	 not specific milter actions were requested by
	      the filter.  Returns a Boolean value (true or false).   See  the
	      EOM CHECKS section for details.

       mt.getheader(conn, hdr, n)
	      Retrieves	 the  value  of	the nth	instance of header field named
	      hdr added	during end-of-message processing on the	specified con-
	      nection.	 This  can  be	used  by the script to verify that the
	      header thus added	contains the right thing.  Returns  the	 value
	      as a string, or the Lua constant "nil" on	error.

       mt.getcwd()
	      Returns the current working directory as a string.

       mt.getreply(conn)
	      Returns  the  last milter	reply received from the	specified con-
	      nection, as an integer.  This can	be compared to any of the  SM-
	      FIR_* constants defined by milter	to see if the filter responded
	      as expected.  This value is initially set	to the NULL character.

       mt.header(conn, name, value)
	      Sends the	header with the	given name and value to	the  specified
	      connection.

       mt.helo(conn, name)
	      Sends  HELO/EHLO information using the specified name as the pa-
	      rameter given.

       mt.macro(conn, type, name, value[, name2, value2[, ...]])
	      Declares a macro called name whose value is value	and whose type
	      (matching	protocol element) is type.  Valid types	are SMFIC_CON-
	      NECT, SMFIC_HELO,	SMFIC_MAIL  and	 SMFIC_RCPT.   Multiple	 macro
	      names and	values can be provided,	but they must appear in	pairs.

       mt.mailfrom(conn, envfrom[, ...])
	      Announces	 envfrom  as  the  envelope  sender  of	a new message.
	      ESMTP parameters as additional arguments are permitted.

       mt.negotiate(conn, version, actions, steps)
	      Performs milter option negotiation with the connection conn, ad-
	      vertising	 that the specified protocol version, protocol actions
	      and protocol steps are offered by	the MTA.  Returns the Lua con-
	      stant "nil" on success or	an error string	on failure.  If	any of
	      the protocol parameters are "nil", the current defaults (defined
	      in libmilter/mfdef.h, provided with the milter source code) will
	      be used.

       mt.rcptto(conn, envrcpt[, ...])
	      Announces	envrcpt	as an envelope recipient of a message.	 ESMTP
	      parameters as additional arguments are permitted.

       mt.set_timeout(n)
	      Sets the read timeout to n seconds.  The default is ten seconds.
	      Returns nothing.

       mt.sleep(n)
	      Sleeps for n seconds.  The value may be an  integer  (for	 whole
	      seconds) or a floating-point value (for partial seconds).

       mt.signal(n)
	      Sends the	specified signal number	n to the running filter.

       mt.startfilter(path, arg1, arg2,	...)
	      Starts  the filter whose binary is located at path with argument
	      vector comprised of strings path,	arg1,  arg2,  etc.   Basically
	      this  is	almost	the  same  syntax as execl(3) except that mil-
	      tertest also does	the  fork  for	you,  and  will	 remember  the
	      process  ID  in  order to	request	a clean	shutdown using SIGTERM
	      and wait(2) at the end of	the test script.  If the filter	 could
	      not  be started, an exception is generated with an error message
	      returned.

       mt.test_action(conn, action)
	      Tests whether or not the	connection  represented	 by  conn  re-
	      quested  the  specified  milter protocol action, specified by an
	      SMFIF_* constant,	during option negotiation.  (See the libmilter
	      documentation and/or include files for details.)

       mt.test_option(conn, option)
	      Tests  whether  or  not  the  connection represented by conn re-
	      quested the specified milter protocol option,  specified	by  an
	      SMFIP_* constant,	during option negotiation.  (See the libmilter
	      documentation and/or include files for details.)

       mt.unknown(conn,	str)
	      Announces	that the unknown SMTP command  str  arrived  over  the
	      connection represented by	conn.

EOM CHECKS
       The  mt.eom_check()  function  is used to determine what	changes	to the
       message the filter requested during its EOM callback.  The changes  can
       be requested in any order.  The first parameter,	op, indicates what op-
       eration is of interest, and it also dictates what the possible  parame-
       ter  list  is.  Valid values and	corresponding parameters for op	are as
       follows:

       MT_HDRADD
	      Checks to	see if a header	field was added	to the message.	 If no
	      parameters  are  given,  the function returns true if any	header
	      field was	added.	If one parameter was given, the	 function  re-
	      turns  true only if the named header field was added (regardless
	      of its value).  If two parameters	are given,  the	 function  re-
	      turns  true  only	 if  the named header field was	added with the
	      specified	value.

       MT_HDRCHANGE
	      Checks to	see if an existing header field	was  changed.	If  no
	      parameters  are  given,  the function returns true if any	header
	      field was	modified.  If one parameter was	 given,	 the  function
	      returns  true  only  if the named	header field was modified (re-
	      gardless of its new value).  If two parameters  are  given,  the
	      function	returns	 true only if the named	header field was modi-
	      fied to have the specified new value.

       MT_HDRDELETE
	      Checks to	see if an existing header field	was  deleted.	If  no
	      parameters  are  given,  the function returns true if any	header
	      field was	deleted.  If one parameter was given, the function re-
	      turns true only if the named header field	was deleted.

       MT_HDRINSERT
	      Checks  to  see if a header field	was inserted into the message.
	      If no parameters are given, the function	returns	 true  if  any
	      header  field  was added.	 If one	parameter was given, the func-
	      tion returns true	only if	the named header field was added  (re-
	      gardless	of its value).	If two parameters are given, the func-
	      tion returns true	only if	the named header field was added  with
	      the  specified  value.  If three parameters are given, the func-
	      tion returns true	only if	the named header field was added  with
	      the specified value at the specified index.

       MT_RCPTADD
	      Checks  to  see  if  an envelope recipient was added.  Currently
	      only one parameter may be	provided.

       MT_RCPTDELETE
	      Checks to	see if an envelope recipient was  deleted.   Currently
	      only one parameter may be	provided.

       MT_BODYCHANGE
	      Checks  to  see if the message's body was	replaced by other con-
	      tent.  With no parameters, the function returns true only	if the
	      body  was	changed	(regardless of the new content).  With one pa-
	      rameter, the function returns true only if the body was  changed
	      to the specified new content.

       MT_QUARANTINE
	      Checks  to  see if the filter requested quarantining of the mes-
	      sage.  With no parameters, the function  returns	true  only  if
	      quarantine  was requested.  With one parameter, the function re-
	      turns true only if quarantine was	requested with	the  specified
	      reason string.

       MT_SMTPREPLY
	      Checks to	see if the filter requested a specific SMTP reply mes-
	      sage.  With no parameters, the function returns true only	 if  a
	      specific	reply was requested.  With one parameter, the function
	      returns true only	if a specific reply  was  requested  with  the
	      specified	 SMTP code.  With two parameters, the function returns
	      true only	if a specific reply was	requested with	the  specified
	      SMTP  code and enhanced status code.  With three parameters, the
	      function returns true only if a  specific	 reply	was  requested
	      with the specified SMTP code, enhanced status code, and text.

EXAMPLE
       -- Echo that the	test is	starting
       mt.echo("*** begin test")
       -- start	the filter
       mt.startfilter("../myfilter", "-p", "inet:12345@localhost")
       mt.sleep(2)

       -- try to connect to it
       conn = mt.connect("inet:12345@localhost")
       if conn == nil then
	    error "mt.connect()	failed"
       end

       -- send connection information
       -- mt.negotiate() is called implicitly
       if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then
	    error "mt.conninfo() failed"
       end
       if mt.getreply(conn) ~= SMFIR_CONTINUE then
	    error "mt.conninfo() unexpected reply"
       end

       -- send envelope	macros and sender data
       -- mt.helo() is called implicitly
       mt.macro(conn, SMFIC_MAIL, "i", "test-id")
       if mt.mailfrom(conn, "user@example.com")	~= nil then
	    error "mt.mailfrom() failed"
       end
       if mt.getreply(conn) ~= SMFIR_CONTINUE then
	    error "mt.mailfrom() unexpected reply"
       end

       -- send headers
       -- mt.rcptto() is called	implicitly
       if mt.header(conn, "From", "user@example.com") ~= nil then
	    error "mt.header(From) failed"
       end
       if mt.getreply(conn) ~= SMFIR_CONTINUE then
	    error "mt.header(From) unexpected reply"
       end
       if  mt.header(conn,  "Date",  "Tue, 22 Dec 2009 13:04:12	-0800")	~= nil
       then
	    error "mt.header(Date) failed"
       end
       if mt.getreply(conn) ~= SMFIR_CONTINUE then
	    error "mt.header(Date) unexpected reply"
       end
       if mt.header(conn, "Subject", "Signing test") ~=	nil then
	    error "mt.header(Subject) failed"
       end
       if mt.getreply(conn) ~= SMFIR_CONTINUE then
	    error "mt.header(Subject) unexpected reply"
       end
       -- send EOH
       if mt.eoh(conn) ~= nil then
	    error "mt.eoh() failed"
       end
       if mt.getreply(conn) ~= SMFIR_CONTINUE then
	    error "mt.eoh() unexpected reply"
       end

       -- send body
       if mt.bodystring(conn, "This is a test!\r\n") ~=	nil then
	    error "mt.bodystring() failed"
       end
       if mt.getreply(conn) ~= SMFIR_CONTINUE then
	    error "mt.bodystring() unexpected reply"
       end
       -- end of message; let the filter react
       if mt.eom(conn) ~= nil then
	    error "mt.eom() failed"
       end
       if mt.getreply(conn) ~= SMFIR_ACCEPT then
	    error "mt.eom() unexpected reply"
       end

       -- verify that a	test header field got added
       if not mt.eom_check(conn, MT_HDRINSERT, "Test-Header") then
	    error "no header added"
       end

       -- wrap it up!
       mt.disconnect(conn)

NOTES
       If a filter negotiates one of the SMFIP_NO* protocol option bits	and  a
       script attempts to perform one of those protocol	steps, an error	is re-
       turned.	It is up to the	test author to use  mt.test_option()  function
       to  see	if  performing a protocol step has been	explicitly disabled by
       the filter.

MILTER NOTES
       When mt.macro() is called, it replaces all previous macros of the  same
       type  with  the	ones  provided	in  the	argument list.	Thus, one call
       should be made that lists the complete set rather  than	one  call  per
       name-value  pair.   Also,  as  each stage in the	milter process is exe-
       cuted, all macros corresponding stages after the	current	one  are  dis-
       carded.	  For	example,   calling  mt.helo(),	which  corresponds  to
       SMFIC_HELO,  will  cause	 all  prior  macros  of	 type  SMFIC_MAIL  and
       SMFIC_RCPT  to be discarded as they represent a milter stage that comes
       later than SMFIC_HELO.

       Since the milter	protocol and the internals of libmilter	itself are not
       formally	 documented,  there  are myriad	other subtleties of the	milter
       protocol	and implementation that	are not	documented here	and may	not be
       documented elsewhere, and could change without notice.  Caveat emptor.

VERSION
       This man	page covers version 1.5.0 of miltertest.

COPYRIGHT
       Copyright  (c)  2009-2014,  The Trusted Domain Project.	All rights re-
       served.

SEE ALSO
       Milter -- http://www.milter.org

       Lua -- http://www.lua.org

			  The Trusted Domain Project		 miltertest(8)

NAME | SYNOPSIS | DESCRIPTION | OPTIONS | FUNCTIONS | EOM CHECKS | EXAMPLE | NOTES | MILTER NOTES | VERSION | COPYRIGHT | SEE ALSO

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=miltertest&sektion=8&manpath=FreeBSD+13.0-RELEASE+and+Ports>

home | help