miltertest man page on DragonFly

Man page or keyword search:  
man Server   44335 pages
apropos Keyword Search (all sections)
Output format
DragonFly logo
[printable version]

miltertest(8)							 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
       recipient(s),  header  field(s),	 end-of-header, body chunk(s), end-of-
       message.	 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
	      request 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
	      included,	 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
	      address  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  special  string "unspec", which will tell the filter that a
	      connection 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
	      indicating  whether a normal disconnect should be done (true) or
	      an abrupt disconnect should be done (false).  An abrupt  discon‐
	      nect 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
	      SMFIR_*  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
	      parameter 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,
	      advertising  that	 the  specified	 protocol  version,   protocol
	      actions  and protocol steps are offered by the MTA.  Returns the
	      Lua constant "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
	      requested 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
	      requested	 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
       operation is of interest, and it also dictates what the possible param‐
       eter 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
	      returns true only if the named header field was  added  (regard‐
	      less  of	its value).  If two parameters are given, the function
	      returns 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
	      (regardless 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
	      returns 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
	      (regardless of its value).  If two  parameters  are  given,  the
	      function	returns	 true only if the named header field was added
	      with the specified value.	 If three parameters  are  given,  the
	      function	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
	      parameter,  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
	      returns 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
       returned.  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
       reserved.

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

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

			  The Trusted Domain Project		 miltertest(8)
[top]

List of man pages available for DragonFly

Copyright (c) for man pages and the logo by the respective OS vendor.

For those who want to learn more, the polarhome community provides shell access and support.

[legal] [privacy] [GNU] [policy] [cookies] [netiquette] [sponsors] [FAQ]
Tweet
Polarhome, production since 1999.
Member of Polarhome portal.
Based on Fawad Halim's script.
....................................................................
Vote for polarhome
Free Shell Accounts :: the biggest list on the net