aboutsummaryrefslogtreecommitdiff
path: root/doc/mtasim.texi
blob: e6fa9857be19b051ca7f26b416ee569fd3e65424 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
@c This file is part of the Mailfromd manual.
@c Copyright (C) 2007 Sergey Poznyakoff
@c See file mailfromd.texi for copying conditions.
@c *******************************************************************
@cindex @command{mtasim}, described
  The @command{mtasim} utility is a @acronym{MTA} simulator for testing
@command{mailfromd} filter scripts.  By default it operates in
@dfn{stdio} mode, similar to that of @command{sendmail -bs}.  In this
mode it reads @acronym{SMTP} commands from standard input and sends
its responses to the standard output.  There is also another mode,
called @dfn{daemon}, where @command{mtasim} opens a @acronym{TCP}
socket and listens on it much like any @acronym{MTA} does.  In both
modes no actual delivery is performed, the tool only simulates the
actions an @acronym{MTA} would do and responses it would give.

  This tool is derived from the program @command{mta}, which I wrote
for GNU Anubis test suite.

@menu
* interactive mode::
* expect commands::
* traces::
* daemon mode::
* option summary::
@end menu

@node interactive mode
@section @command{mtasim} interactive mode mode

  If you start @command{mtasim} without options, you will see the
following:

@smallexample
@group
220 mtasim (mailfromd @value{VERSION}) ready
(mtasim) _
@end group
@end smallexample

@cindex readline
@cindex GNU Readline
  The first line is an usual @acronym{RFC} 2821 reply.  The second one is
a prompt, indicating that @command{mtasim} is in interactive mode and
ready for input.  The prompt appears only if the package is compiled
with GNU Readline and @command{mtasim} determines that its standard
input is connected to the terminal.  This is called @dfn{interactive
mode} and is intended to save the human user some typing by offering
line editing and history facilities (@pxref{Command Line Editing, ,
Command Line Editing, readline, GNU Readline Library}).  If the package
is compiled without GNU Readline, you will see:

@smallexample
@group
220 mtasim (mailfromd @value{VERSION}) ready
_
@end group
@end smallexample

@noindent
where @samp{_} represents the cursor.  Whatever the mode,
@command{mtasim} will wait for further input.

@cindex @code{HELP}, @command{mtasim} statement
  The input is expected to consist of valid @acronym{SMTP} commands
and special @command{mtasim} statements.  The utility will act exactly
like a @acronym{RFC} 2821-compliant @acronym{MTA}, except that it will
not do actual message delivery or relaying.  Try typing @code{HELP} to
get the list of supported commands.  You will see something similar
to:

@smallexample
250-mtasim (mailfromd @value{VERSION}); supported SMTP commands:
250- EHLO
250- HELO
250- MAIL
250- RCPT
250- DATA
250- HELP
250- QUIT
250- HELP
250  RSET
@end smallexample

 You can try a simple @acronym{SMTP} session now:

@smallexample
220 mtasim (mailfromd @value{VERSION}) ready
(mtasim) @kbd{ehlo localhost}
250-pleased to meet you
250 HELP
(mtasim) @kbd{mail from: <me@@localhost>}
250 Sender OK
(mtasim) @kbd{rcpt to: <him@@domain>}
250 Recipient OK
(mtasim) @kbd{data}
354 Enter mail, end with `.' on a line by itself
(mtasim) @kbd{.}
250 Mail accepted for delivery
(mtasim) @kbd{quit}
221 Done
@end smallexample

  Notice, that @command{mtasim} does no domain checking, so such thing
as @samp{rcpt to: <him@@domain>} was eaten without complaints.

@anchor{mtasim milter port}
@mtasimopt{port, described}
  So far so good, but what all this has to do with
@command{mailfromd}?  Well, that's what we are going to explain.  To
make @command{mtasim} consult any milter, use @option{--port}
(@option{-X}) command line option.  This option takes a single
argument that specifies the milter port to use.  The port can be given
either in the usual Milter format (@xref{milter port specification},
for a short description), or as a full @file{sendmail.cf} style
@code{X} command, in which case it allows to set timeouts as well:

@smallexample
$ @kbd{mtasim --port=inet:999@@localhost}
# @r{This is also valid}:
$ @kbd{mtasim --port='mailfrom, S=inet:999@@localhost, F=T, T=C:100m;R:180s'}
@end smallexample

  If the milter is actually listening on this port, @command{mtasim}
will connect to it and you will get the following initial prompt:

@smallexample
@group
220-mtasim (mailfromd @value{VERSION}) ready
220 Connected to milter inet:999@@localhost
(mtasim)
@end group
@end smallexample

  Notice, that it makes no difference what implementation is listening
on that port, it may well be some other filter, not necessarily
@command{mailfromd}. 

@cindex @command{mtasim} auto mode
  However, let's return to @command{mailfromd}.  If you do not want to
connect to an existing @command{mailfromd} instance, but prefer
instead to create a new one and run your tests with it (a preferred
way, if you already have a stable filter running but wish to test a
new script without disturbing it), use @option{--port=auto}.  This
option instructs @command{mtasim} to do the following:

@enumerate 1
@item Create a unique temporary directory in @file{/tmp} and create a
communication socket within it.
@item Spawn a new instance of @command{mailfromd}.  The arguments and
options for that instance may be given in the invocation of
@command{mtasim} after a double-dash marker (@samp{--})
@item Connect to that filter.
@end enumerate

  When @command{mtasim} exits, it terminates the subsidiary
@command{mailfromd} process and removes the temporary directory it has
created.  For example, the following command will start
@command{mailfromd -I. -I../mflib test.rc}:

@smallexample
@group
$ @kbd{mtasim -Xauto -- -I. -I../mflib test.rc}
220-mtasim (mailfromd @value{VERSION}) ready
220 Connected to milter unix:/tmp/mtasim-j6tRLC/socket
(mtasim)
@end group
@end smallexample

@anchor{statedir mtasim option}
@mtasimopt{statedir, described}
  The @file{/tmp/mtasim-j6tRLC} directory and any files within it will
exist as long as @command{mtasim} is running and will be removed when
you exit from it.@footnote{However, this is true only if the program
is exited the usual way (via @code{QUIT} or end-of-file).  If it is
aborted with a signal like @code{SIGINTR}, the temporary directory is
not removed.}  You can also instruct the subsidiary
@command{mailfromd} to use this directory as its state directory
(@pxref{statedir}).  This is done by @option{--statedir} command line
option:

@smallexample
$ @kbd{mtasim -Xauto --statedir -- -I. -I../mflib test.rc}
@end smallexample

@noindent
(notice that @option{--statedir} is the @command{mtasim} option,
therefore it must appear @emph{before} @samp{--})

  Now, let's try @code{HELP} command again:

@smallexample
250-mtasim (mailfromd @value{VERSION}); supported SMTP commands:
250- EHLO
250- HELO
250- MAIL
250- RCPT
250- DATA
250- HELP
250- QUIT
250- HELP
250- RSET
250-Supported administrative commands:
250- \Dname=value [name=value...]       Define Sendmail macros
250- \Ecode                             Expect given SMTP reply code
250- \L[name] [name...]                 List macros
250  \Uname [name...]                   Undefine Sendmail macros
@end smallexample

@cindex @command{mtasim} administrative commands
  While the @acronym{SMTP} commands do not need any clarification, some words
about the @dfn{administrative commands} are surely in place.  These
commands allow to define, undefine and list arbitrary Sendmail macros.
Each administrative command consists of a backslash followed by a command
letter.  Just like @acronym{SMTP} ones, administrative commands are
case-insensitive.  If a command takes arguments, the first argument
must follow the command letter without intervening whitespace.
Subsequent arguments can be delimited by arbitrary amount of
whitespace.

@anchor{D command}
@cindex D, @code{\D}, a @command{mtasim} command
@cindex @command{mtasim}, defining Sendmail macros
For example, the @code{\D} command defines Sendmail macros:

@smallexample
(mtasim) @kbd{\Dclient_addr=192.168.10.1 f=sergiusz@@localhost i=testmsg}
(mtasim) 
@end smallexample

@noindent
Notice that @command{mailfromd} does not send any response to the
command, except if there was some syntactic error, in which case it
will return a @samp{502} response.

@cindex L, @code{\L}, a @command{mtasim} command
@cindex @command{mtasim}, listing Sendmail macros
  Now, you can list all available macros:

@smallexample
(mtasim) @kbd{\L}
220-client_addr=192.168.10.1
220-f=sergiusz@@localhost
220 i=testmsg
(mtasim)
@end smallexample

@noindent
or just some of them:

@smallexample
(mtasim) @kbd{\Lclient_addr}
220 client_addr=192.168.10.1
(mtasim)
@end smallexample

@cindex U, @code{\U}, a @command{mtasim} command
@cindex @command{mtasim}, undefining Sendmail macros
  To undefine a macro, use @command{\U} command:

@smallexample
(mtasim) @kbd{\Ui}
(mtasim) @kbd{\l}
220-client_addr=192.168.10.1
220 f=sergiusz@@localhost
(mtasim)    
@end smallexample

  Now, let's try a real-life example.  Suppose you wish to test the
greylisting functionality of the filter script described in @ref{Filter Script
Example}.  To do this, you start @command{mtasim}:

@smallexample
$ @kbd{mtasim -Xauto -- -I. -I../mflib test.rc}
220-mtasim (mailfromd @value{VERSION}) ready
220 Connected to milter unix:/tmp/mtasim-ak3DEc/socket
(mtasim)
@end smallexample

  The script in @file{test.rc} needs to know @code{client_addr} macro,
so you supply it to @command{mtasim}:

@smallexample
(mtasim) @kbd{\Dclient_addr=10.10.1.13}
@end smallexample

Now, you try an @acronym{SMTP} session:

@smallexample
(mtasim) @kbd{ehlo yahoo.com}
250-pleased to meet you
250 HELP
(mtasim) @kbd{mail from: <gray@@yahoo.com>}
250 Sender OK
(mtasim) @kbd{rcpt to: <gray@@localhost>}
450 4.7.0 You are greylisted for 300 seconds
@end smallexample

  OK, this shows that the greylisting works.  Now quit the session:

@smallexample
(mtasim) @kbd{quit}
221 Done
@end smallexample

@node expect commands
@section @command{mtasim} expect commands

@cindex expect mode, @command{mtasim}
@cindex @command{mtasim} expect mode
@cindex E, @code{\E}, a @command{mtasim} command
  Until now we were using @command{mtasim} interactively.  However, it
is often useful in shell scripts, for example the @command{mailfromd}
test suite is written in shell and @command{mtasim}.  To avoid the
necessity to use auxiliary programs like @command{expect} or
@command{DejaGNU}, @command{mtasim} contains a built-in expect
feature.  The administrative command @code{\E} introduces the
@acronym{SMTP} code that the next command is expected to yield.  For
example,

@smallexample
@group
\E250
rcpt to: <foo@@bar.org>
@end group
@end smallexample

@noindent
tells @command{mtasim} that the response to @code{RCPT TO} command
must begin with @samp{250} code.  If it does, @command{mtasim}
continues execution.  Otherwise, it prints an error message and
terminates with exit code 1.  The error message it prints looks like:

@smallexample
Expected 250 but got 470
@end smallexample

  The expect code given with the @code{\E} command may have less than
3 digits.  In this case it specifies the first digits of expected
reply.  For example, the command @samp{\E2} matches replies
@samp{200}, @samp{220}, etc. 

  This feature can be used to automate your tests.  For example, the
following script tests the greylisting functionality (see the previous
section):

@smallexample
# @r{Test the greylisting functionality}
#
\E220
\Dclient_addr=10.10.1.13
\E250
ehlo yahoo.com
\E250
mail from: <gray@@yahoo.com>
\E450
rcpt to: <gray@@localhost>
\E221
quit
@end smallexample

@cindex @command{mtasim}, using in shell scripts
  This example also illustrates the fact that you can use
@samp{#}-style comments in the @command{mtasim} input.  Such a script
can be used in shell programs, for example:

@smallexample
@group
mtasim -Xauto --statedir -- -I. -I../mflib test.rc < @file{scriptfile}
if $? -ne 0; then
  echo "Greylisting test failed"
fi
@end group
@end smallexample

@node traces
@section Trace Files

@cindex trace file, @command{mtasim}
  It is possible to log an entire @acronym{SMTP} session to a file.
This is called @dfn{session tracing}.  Two options are provided for
this purpose: 

@table @option
@mtasimopt{trace-file, described}
@item --trace-file=@var{file}
  Sets the name of the trace file, i.e. a file to which the session
transcript will be written.  Both the input commands, and the
@command{mtasim} responses are logged.  If the file @var{file} exists,
it will be truncated before logging.  This, however, can be changed
using the following option:

@mtasimopt{append, described}
@item -a
@itemx --append
  If the trace file exists, append new trace data to it.
@end table

@node daemon mode
@section Daemon Mode

@mtasimopt{daemon, described}
@cindex @command{mtasim} daemon mode
  To start @command{mtasim} in @dfn{daemon} mode, use the
@option{--daemon} (or @option{-bd}) command line option.  This mode
is not quite the same as Sendmail @option{-bd} mode.  When started in
@dfn{daemon} mode, @command{mtasim} selects the first available
@acronym{TCP} port to use from the range @samp{1024 -- 65535}.
It prints the selected port number on the standard output and
starts listening on it.  When a connection comes, it serves a
@emph{single} @acronym{SMTP} session and exits immediately when it is
ended.

  This mode is designed for use in shell scripts and automated test
cases.

@node option summary
@section @command{mtasim} command line options

  This section summarizes all available @command{mtasim} command line options.

@table @option
@mtasimopt{append, summary}
@mtindex a, -a, @command{mtasim} option, summary
@item --append
@itemx -a 
  Append to the trace file.  @xref{traces}.

@mtasimopt{body-chunk, summary}  
@item --body-chunk=@var{number}
  Set the body chunk length (bytes) for @code{xxfi_body} calls.

@mtasimopt{daemon, summary}
@mtindex bs, -bd, @command{mtasim} option, summary
@item --daemon
@itemx -bd
  Run as daemon.  @xref{daemon mode}.

@mtasimopt{define, summary}
@mtindex D, -D, @command{mtasim} option, summary
@item --define=@var{macro}=@var{value}
@itemx -D @var{macro}=@var{value}
  Define Sendmail macro @var{macro} to the given @var{value}.  It is
similar to the @code{\D} administrative command (@pxref{D command})

@item --help
@itemx -?
  Display a short help summary

@mtasimopt{milter-version, summary}
@item --milter-version=@var{number}
  Force using the given Milter protocol version number.  This option
is intended for development and testing of the Gacopyz library
(@pxref{Gacopyz}).

@mtasimopt{no-interactive, summary}
@item --no-interactive
  Not-interactive mode (disable readline).  @xref{Command Line Editing, ,
Command Line Editing, readline, GNU Readline Library}.

@mtasimopt{port, summary}
@mtindex X, -X, @command{mtasim} option, summary
@item --port=@var{port}
@itemx -X @var{port}
  Communicate with given Milter @var{port}.  @xref{mtasim milter
port}.

@mtasimopt{prompt, summary}
@item --prompt=@var{string}
  Set readline prompt.  The default prompt string is @samp{(mtasim) }.

@mtasimopt{statedir, summary}
@item --statedir
  When using @option{-Xauto}, use the temporary directory name as
@command{mailfromd} state directory (@pxref{statedir mtasim option}).

@mtasimopt{stdio, summary}
@mtindex bs, -bs, @command{mtasim} option, summary
@item --stdio
@itemx -bs
  Use the @acronym{SMTP} protocol on standard input and output.  This
is the default mode for @command{mtasim}.  @xref{interactive mode}.

@mtasimopt{trace-file, summary}
@item --trace-file=@var{file}
  Set name of the trace file.  @xref{traces}.

@item --usage
  Display option summary

@mtasimopt{verbose, summary}  
@mtindex v, -v, @command{mtasim} option, summary
@item --verbose
@itemx -v
  Increase verbosity level.

@item --version
@itemx -V
  Print program version

@end table


Return to:

Send suggestions and report system problems to the System administrator.