-
Notifications
You must be signed in to change notification settings - Fork 9
/
mimedefang-filter.5.in
2483 lines (2034 loc) · 86 KB
/
mimedefang-filter.5.in
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
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
.\" $Id$
.\"
.TH MIMEDEFANG-FILTER 5 "8 February 2005"
.UC 4
.SH NAME
mimedefang-filter \- Configuration file for MIMEDefang mail filter.
.SH DESCRIPTION
\fBmimedefang-filter\fR is a Perl fragment that controls how
\fBmimedefang.pl\fR disposes of various parts of a MIME message.
In addition, it contains some global variable settings that affect
the operation of \fBmimedefang.pl\fR.
.SH CALLING SEQUENCE
Incoming messages are scanned as follows:
.PP
1) A temporary working directory is created. It is made the current working
directory and the e-mail message is split into parts in this directory.
Each part is represented internally as an instance of MIME::Entity.
.PP
2) If the file \fB@CONFDIR_EVAL@/mimedefang-filter.pl\fR defines a
Perl function called \fBfilter_begin\fR, it is called with a single
argument consisting of a MIME::Entity representing the parsed e-mail
message. Any return value is ignored.
.PP
3) For each \fIleaf\fR part of the mail message, \fBfilter\fR is
called with four arguments: \fBentity\fR, a MIME::Entity object;
\fBfname\fR, the suggested filename taken from the MIME
Content-Disposition header; \fBext\fR, the file extension, and
\fBtype\fR, the MIME Content-Type value. For each \fInon-leaf\fR
part of the mail message, \fBfilter_multipart\fR is called with the
same four arguments as \fBfilter\fR. A non-leaf part of a message
is a part that contains nested parts. Such a part has no useful
body, but you should \fIstill perform filename checks\fR to check
for viruses that use malformed MIME to masquerade as non-leaf
parts (like message/rfc822). In general, any action you perform
in \fBfilter_multipart\fR applies to the part itself \fIand\fR any
contained parts.
.PP
Note that both \fBfilter\fR and \fBfilter_multipart\fR are optional.
If you do not define them, a default function that simply accepts each
part is used.
.PP
4) After all parts have been processed, the function \fBfilter_end\fR
is called if it has been defined. It is passed a single argument consisting
of the (possibly modified) MIME::Entity object representing the message
about to be delivered. Within \fBfilter_end\fR, you can call
functions that modify the message headers body.
.PP
5) After \fBfilter_end\fR returns, the function \fBfilter_wrapup\fR is
called if it has been defined. It is passed a single argument
consisting of the (possibly modified) MIME::Entity object representing
the message about to be delivered, including any modifications made in
\fBfilter_end\fR. Within \fBfilter_wrapup\fR, you can \fInot\fR call
functions that modify the message body, but you can still add or
modify message headers.
.SH DISPOSITION
\fBmimedefang.pl\fR examines each part of the MIME message and chooses
a \fIdisposition\fR for that part. (A disposition is selected by
calling one of the following functions from \fBfilter\fR and then
immediately returning.) Available dispositions are:
.TP
.B action_accept
The part is passed through unchanged. If no disposition function is
returned, this is the default.
.TP
.B action_accept_with_warning
The part is passed through unchanged, but a warning is added to the mail
message.
.TP
.B action_drop
The part is deleted without any notification to the recipients.
.TP
.B action_drop_with_warning
The part is deleted and a warning is added to the mail message.
.TP
.B action_replace_with_warning
The part is deleted and instead replaced with a text message.
.TP
.B action_quarantine
The part is deleted and a warning is added to the mail message. In addition,
a copy of the part is saved on the mail server in the directory
@QDIR@ and a notification is sent
to the MIMEDefang administrator.
.TP
.B action_bounce
The entire e-mail message is rejected and an error returned to the sender.
The intended recipients are not notified. Note that in spite of the
name, MIMEDefang does \fInot\fR generate and e-mail a failure notification.
Rather, it causes the SMTP server to return a 5\fIXX\fR SMTP failure code.
.TP
.B action_discard
The entire e-mail message is discarded silently.
Neither the sender nor the intended recipients are notified.
.TP
.B action_greylist
The e-mail message is greylisted.
If it's the first time we see this sender, the email will be tempfailed,
when the sender will retry the email will be accepted.
.SH CONTROLLING RELAYING
You can define a function called \fBfilter_relay\fR in your filter.
This lets you reject SMTP connection attempts early on in the SMTP
dialog, rather than waiting until the whole message has been sent.
Note that for this check to take place, you must use the \-r flag with
\fBmimedefang\fR.
.PP
\fBfilter_relay\fR is passed six arguments: $hostip is the IP address
of the relay host (for example, "127.0.0.1"), $hostname is the
host name if known (for example, "localhost.localdomain"). If the host
name could not be determined, $hostname is $hostip enclosed in
square brackets. (That is, ("$hostname" eq "[$hostip]") will be true.)
.PP
The remaining four arguments to \fBfilter_relay\fR are
$port, $myip, $myport and $qid, which contain the client's TCP
port, the Sendmail daemon's listening IP address, the
Sendmail daemon's listening port, and the Sendmail Queue-ID,
respectively. \fINote\fR that the Queue-ID may not yet be
available at this stage (for example, Postfix does not allocate
a queue-ID this early.) If the Queue-ID is not available,
the string NOQUEUE is passed instead.
.PP
\fBfilter_relay\fR must return a two-element list:
($code, $msg). $msg specifies the text message to use for the SMTP
reply, but because of limitations in the Milter API, this message is
for documentation purposes only---you cannot set the text of the SMTP
message returned to the SMTP client from \fBfilter_relay\fR.
$code is a literal string, and can have one of the following values:
.TP
.B 'REJECT'
if the connection should be rejected.
.TP
.B 'CONTINUE'
if the connection should be accepted.
.TP
.B 'TEMPFAIL'
if a temporary failure code should be returned.
.TP
.B 'DISCARD'
if the message should be accepted and silently discarded.
.TP
.B 'ACCEPT_AND_NO_MORE_FILTERING'
if the connection should be accepted \fIand no further filtering done\fR.
.PP
Earlier versions of MIMEDefang used -1 for TEMPFAIL, 0 for REJECT and
1 for CONTINUE. These values still work, but are deprecated.
.PP
In the case of REJECT or TEMPFAIL, $msg specifies the text part of the
SMTP reply. $msg \fImust not\fR contain newlines.
.PP
For example, if you wish to reject connection attempts from any
machine in the spammer.com domain, you could use this function:
.nf
sub filter_relay {
my ($ip, $name) = @_;
if ($name =~ /spammer\\.com$/) {
return ('REJECT', "Sorry; spammer.com is blacklisted");
}
return ('CONTINUE', "ok");
}
.fi
.SH FILTERING BY HELO
You can define a function called \fBfilter_helo\fR in your filter.
This lets you reject connections after the HELO/EHLO SMTP command.
Note that for this function to be called, you must use the
\-H flag with \fBmimedefang\fR.
.PP
\fBfilter_helo\fR is passed seven arguments: $ip and $name are the IP
address and name of the sending relay, as in \fBfilter_relay\fR. The
third argument, $helo, is the argument supplied in the HELO/EHLO command.
.PP
The remaining four arguments to \fBfilter_helo\fR are
$port, $myip, $myport and $qid, which contain the client's TCP
port, the Sendmail daemon's listening IP address, the
Sendmail daemon's listening port, and the Sendmail Queue-ID,
respectively. \fINote\fR that the Queue-ID may not yet be
available at this stage (for example, Postfix does not allocate
a queue-ID this early.) If the Queue-ID is not available,
the string NOQUEUE is passed instead.
.PP
\fBfilter_helo\fR must return a two-to-five element list: ($code,
$msg, $smtp_code, $smtp_dsn, $delay). $code is a return code, with
the same meaning as the $code return from \fBfilter_relay\fR. $msg
specifies the text message to use for the SMTP reply. If $smtp_code
and $smtp_dsn are supplied, they become the SMTP numerical reply code
and the enhanced status delivery code (DSN code). If they are not
supplied, sensible defaults are used. $delay specifies a delay in
seconds; the C milter code will sleep for $delay seconds before
returning the reply to Sendmail. $delay defaults to zero.
(Note that the delay is implemented in the Milter C code; if you specify
a delay of 30 seconds, that doesn't mean a Perl worker is tied up for
the duration of the delay. The delay only costs one Milter thread.)
.SH FILTERING BY SENDER
You can define a function called \fBfilter_sender\fR in your filter.
This lets you reject messages from certain senders, rather than
waiting until the whole message has been sent. Note that for this
check to take place, you must use the \-s flag with \fBmimedefang\fR.
.PP
\fBfilter_sender\fR is passed four arguments: $sender is the envelope
e-mail address of the sender (for example, "<[email protected]>").
The address may or may not be surrounded by angle brackets. $ip
and $name are the IP address and host name of the SMTP relay. Finally,
$helo is the argument to the SMTP "HELO" command.
.PP
Inside \fBfilter_sender\fR, you can access any ESMTP arguments
(such as "SIZE=12345") in the array @ESMTPArgs. Each ESMTP argument
occupies one array element.
.PP
\fBfilter_sender\fR must return a two-to-five element list, with the
same meaning as the return value from \fBfilter_helo\fR.
.PP
For example, if you wish to reject messages from [email protected],
you could use this function:
.nf
sub filter_sender {
my ($sender, $ip, $hostname, $helo) = @_;
if ($sender =~ /^<?spammer\\@badguy\\.com>?$/i) {
return ('REJECT', 'Sorry; [email protected] is blacklisted.');
}
return ('CONTINUE', "ok");
}
.fi
.PP
As another example, some spammers identify their own machine as your
machine in the SMTP "HELO" command. This function rejects a machine
claiming to be in the "roaringpenguin.com" domain unless it really
is a Roaring Penguin machine:
.nf
sub filter_sender {
my($sender, $ip, $hostname, $helo) = @_;
if ($helo =~ /roaringpenguin\.com/i) {
if ($ip ne "127.0.0.1" and
$ip ne "216.191.236.23" and
$ip ne "216.191.236.30") {
return('REJECT', "Go away... $ip is not in roaringpenguin.com");
}
}
return ('CONTINUE', "ok");
}
.fi
.PP
As a third example, you may wish to prevent spoofs by requiring SMTP
authentication when email is sent from some email addresses. This
function rejects mail from "[email protected]", unless the connecting
user properly authenticated as "elvisp". Note that this needs access
to the %SendmailMacros global, that is not available in filter_sender
until after a call to \fBread_commands_file\fR.
.nf
sub filter_sender {
my($sender, $ip, $hostname, $helo) = @_;
read_commands_file();
### notice: This assumes The King uses authentication without realm!
if ($sender =~ /^<?king\\@example\\.com>?$/i and
$SendmailMacros{auth_authen} ne "elvisp") {
return('REJECT', "Faking mail from the king is not allowed.");
}
return ('CONTINUE', "ok");
}
.fi
.SH FILTERING BY RECIPIENT
You can define a function called \fBfilter_recipient\fR in your
filter. This lets you reject messages to certain recipients, rather
than waiting until the whole message has been sent. Note that for
this check to take place, you must use the \-t flag with
\fBmimedefang\fR.
.PP
\fBfilter_recipient\fR is passed nine arguments: $recipient
is the envelope address of the recipient and $sender is the envelope
e-mail address of the sender (for example, "<[email protected]>").
The addresses may or may not be surrounded by angle brackets. $ip
and $name are the IP address and host name of the SMTP relay. $first
is the envelope address of the \fIfirst\fR recipient for this message,
and $helo is the argument to the SMTP "HELO" command. The last three
arguments, $rcpt_mailer, $rcpt_host and $rcpt_addr are the Sendmail
mailer, host and address triple for the recipient address. For example,
for local recipients, $rcpt_mailer is likely to be "local", while for
remote recipients, it is likely to be "esmtp".
.PP
Inside \fBfilter_recipient\fR, you can access any ESMTP arguments
(such as "NOTIFY=never") in the array @ESMTPArgs. Each ESMTP argument
occupies one array element.
.PP
\fBfilter_recipient\fR must return a two-to-five element list whose
interpretation is the same as for \fBfilter_sender\fR.
Note, however, that if \fBfilter_recipient\fR
returns 'DISCARD', then the entire message for \fIall\fR recipients
is discarded. (It doesn't really make sense, but that's how Milter
works.)
.PP
For example, if you wish to reject messages from [email protected],
unless they are to [email protected], you could use this function:
.nf
sub filter_recipient {
my ($recipient, $sender, $ip, $hostname, $first, $helo,
$rcpt_mailer, $rcpt_host, $rcpt_addr) = @_;
if ($sender =~ /^<?spammer\\@badguy\\.com>?$/i) {
if ($recipient =~ /^<?postmaster\\@mydomain\\.com>?$/i) {
return ('CONTINUE', "ok");
}
return ('REJECT', 'Sorry; [email protected] is blacklisted.');
}
return ('CONTINUE', "ok");
}
.fi
.SH INITIALIZATION AND CLEANUP
Just before a worker begins processing messages, \fBmimedefang.pl\fR calls
the functions \fBfilter_initialize\fR (if it is defined) with no arguments.
By the time \fBfilter_initialize\fR is called, all the other initialization
(such as setting up syslog facility and priority) has been done.
If you are not using an embedded Perl interpreter, then performing an
action inside \fBfilter_initialize\fR is practically the same as performing
it directly in the filter file, outside any function definition. However,
if you are using an embedded Perl interpreter, then anything you call
directly from outside a function definition is executed \fIonce only\fR
in the parent process. Anything in \fBfilter_initialize\fR is executed
\fIonce per worker\fR. If you use any code that opens a descriptor (for
example, a connection to a database server), you \fImust\fR run that
code inside \fBfilter_initialize\fR and not directly from the filter,
because the multiplexor closes all open descriptors when it activates
a new worker.
From within \fBfilter_initialize\fR a configuration file could be loaded
by calling \fBread_config\fR.
\fBread_config\fR accepts a configuration file path and it can be used
to overwrite global variables.
Configuration file format is pure Perl code.
When a worker is about to exit, \fBmimedefang.pl\fR calls the function
\fBfilter_cleanup\fR (if it is defined) with no arguments. This
function can do whatever cleanup you like, such as closing file
descriptors and cleaning up long-lived worker resources. The return
value from \fBfilter_cleanup\fR becomes the worker's exit status. (You
should therefore ensure that \fBfilter_cleanup\fR returns an integer
suitable for a process exit status.)
.PP
If \fBfilter_cleanup\fR takes longer than 10 seconds to run, the worker
is sent a SIGTERM signal. If that doesn't kill it (because you're
catching signals, perhaps), then a further 10 seconds later, the worker
is sent a SIGKILL signal.
.SH CONTROLLING PARSING
If you define a function called \fBfilter_create_parser\fR taking no
arguments, then \fBmimedefang.pl\fR will call it to create a
MIME::Parser object for parsing mail messages.
\fBFilter_create_parser\fR is expected to return a MIME::Parser object
(or an instance of a class derived from MIME::Parser).
You can use \fBfilter_create_parser\fR to change the behavior
of the MIME::Parser used by \fBmimedefang.pl\fR.
If you do not define a \fBfilter_create_parser\fR function,
then a built-in version equivalent to this is used:
.nf
sub filter_create_parser () {
my $parser = MIME::Parser->new();
$parser->extract_nested_messages(1);
$parser->extract_uuencode(1);
$parser->output_to_core(0);
$parser->tmp_to_core(0);
return $parser;
}
.fi
.SH EXTENDING MIMEDEFANG
The man page for \fBmimedefang-protocol\fR(7) lists commands that are
passed to workers in server mode (see "SERVER COMMANDS".) You can define
a function called \fBfilter_unknown_cmd\fR to extend the set of commands
your filter can handle.
If you define \fBfilter_unknown_cmd\fR, it is passed the unknown command
as a single argument. It should return a list of values as follows: The
first element of the list must be either "ok" or "error:" (with the colon.)
The remaining arguments are percent-encoded. All the resulting pieces
are joined together with a single space between them, and the resulting
string passed back as the reply to the multiplexor.
For example, the following function will make your filter reply
to a "PING" command with "PONG":
.nf
sub filter_unknown_cmd ($) {
my($cmd) = @_;
if ($cmd eq "PING") {
return("ok", "PONG");
}
return("error:", "Unknown command");
}
.fi
You can test this filter by typing the following as root:
.nf
md-mx-ctrl PING
.fi
The response should be:
.nf
ok PONG
.fi
If you extend the set of commands using \fBfilter_unknown_cmd\fR,
you should make all your commands start with an upper-case letter
to avoid clashes with future built-in commands.
.SH REJECTING UNKNOWN USERS EARLY
A very common mail setup is to have a MIMEDefang machine act as an SMTP
proxy, accepting and scanning mail and then relaying it to the real
mail server. Unfortunately, this means that the MIMEDefang machine cannot
know if a local address is valid or not, and will forward all mail
for the appropriate domains. If a mail comes in for an unknown user, the
MIMEDefang machine will be forced to generate a bounce message when
it tries to relay the mail.
.PP
It's often desirable to have the MIMEDefang host reply with a "User
unknown" SMTP response directly. While this can be done by copying
the list of local users to the MIMEDefang machine, MIMEDefang has a
built-in function called \fBmd_check_against_smtp_server\fR for
querying another relay host:
.TP
.B md_check_against_smtp_server($sender, $recip, $helo, $server, $port) This
function connects to the SMTP server $server and pretends to send mail
from $sender to $recip. The return value is always a two-element
array. If the RCPT TO: command succeeds, the return value is
("CONTINUE", "OK"). If the RCPT fails with a permanent failure, the
return value is ("REJECT", $msg), where $msg is the message from the
SMTP server. Any temporary failures, connection errors, etc. result
in a return value of ("TEMPFAIL", $msg).
The optional argument $port specifies the TCP port to connect to. If
it is not supplied, then the default SMTP port of 25 is used.
If the server offers STARTTLS support, TLS step-up is attempted. If TLS
step-up fails, the check will fall-back to using clear text and log the
failure
.PP
Suppose the machine \fBfilter.domain.tld\fR is filtering mail destined
for the real mail server \fBmail.domain.tld\fR. You could have a
\fBfilter_recipient\fR function like this:
.nf
sub filter_recipient
{
my($recip, $sender, $ip, $host, $first, $helo,
$rcpt_mailer, $rcpt_host, $rcpt_addr) = @_;
return md_check_against_smtp_server($sender, $recip,
"filter.domain.tld",
"mail.domain.tld");
}
.fi
For each RCPT TO: command, MIMEDefang opens an SMTP connection to
\fBmail.domain.tld\fR and checks if the command would succeed.
.PP
Please note that you should only use \fBmd_check_against_smtp_server\fR
if your mail server responds with a failure code for nonexistent users
at the RCPT TO: level. Also, this function may impose too much overhead
if you receive a lot of e-mail, and it will generate lots of useless
log entries on the real mail server (because of all the RCPT TO: probes.)
It may also significantly increase the load on the real mail server.
.SH GLOBAL VARIABLES YOU CAN SET
The following Perl global variables should be set in \fBmimedefang-filter\fR:
.TP
.B $AdminAddress
The e-mail address of the MIMEDefang administrator.
.TP
.B $DaemonAddress
The e-mail address from which MIMEDefang-originated notifications come.
.TP
.B $AddWarningsInline
If this variable is set to 0, then all MIMEDefang warnings (such
as created by action_quarantine or action_drop_with_warning) are collected
together and added in a separate MIME part called WARNING.TXT. If the
variable is set to 1, then the warnings are added directly in the first
text/plain and text/html parts of the message. If the message does
not contain any text/plain or text/html parts, then a WARNING.TXT MIME
part is added as before.
.TP
.B $MaxMIMEParts
A message containing many MIME parts can cause MIME::Tools to consume
large amounts of memory and bring your system to its knees. If you
set $MaxMIMEParts to a positive number, then MIME parsing is terminated
for messages with more than that many parts, and the message is bounced.
In this case, \fInone\fR of your filter functions is called.
By default, $MaxMIMEParts is set to -1, meaning there is no limit on
the number of parts in a message. Note that in order to use this
variable, you \fImust\fR install the Roaring Penguin patched version
of MIME::Tools, version 5.411a-RP-Patched-02 or newer.
.TP
.B $Stupidity{"NoMultipleInlines"}
Set this to 1 if your e-mail is too stupid to display multiple
MIME parts in-line. In this case, a nasty hack causes the first part
of the original message to appear as an attachment if warning are
issued. Mail clients that are not this stupid are
Netscape Communicator and Pine. On the other hand, Microsoft Exchange
and Microsoft Outlook are indeed this stupid. Perhaps users of those
clients should switch.
The following global variables may optionally be set. If they are not
set, sensible defaults are used:
.TP
.B $AddApparentlyToForSpamAssassin
By default, MIMEDefang tries to pass SpamAssassin a message that looks
exactly like one it would receive via procmail. This means adding
a Received: header, adding a Message-ID header if necessary, and
adding a Return-Path: header. If you set $AddApparentlyToForSpamAssassin
to 1, then MIMEDefang also adds an Apparently-To: header with all
the envelope recipients before passing the message to SpamAssassin.
This lets SpamAssassin detect possibly whitelisted recipient addresses.
The default value for $AddApparentlyToForSpamAssassin is 0.
.TP
.B $SyslogFacility
This specifies the logging facility used by mimedefang.pl. By default,
it is set to "mail", but you can set it to other possibilites. See the
openlog(3) man page for details. You should name facilities as all-lowercase
without the leading "LOG_". That is, use "local3", not "LOG_LOCAL3".
.TP
.B $WarningLocation \fR(default 0)
If set to 0 (the default), non-inline warnings are placed first. If
you want the warning at the end of the e-mail, set $WarningLocation
to -1.
.TP
.B $DaemonName \fR(default """MIMEDefang"")
The full name used when MIMEDefang sends out notifications.
.TP
.B $AdminName \fR(default """MIMEDefang Administrator"")
The full name of the MIMEDefang administrator.
.TP
.B $SALocalTestsOnly \fR(default 1)
If set to 1, SpamAssassin calls will use only local tests. This is the
default and recommended setting. This disables Received, RBL and Razor
tests in an all or nothing fashion. To use Razor this \fBMUST\fR be set
to 0. You can add 'skip_rbl_checks 1' to your SpamAssassin config file if
you need to.
.TP
.B $NotifySenderSubject \fR(default """MIMEDefang Notification"")
The subject used when e-mail is sent out by action_notify_sender(). If
you set this, you should set it each time you call action_notify_sender()
to ensure consistency.
.\" fix Emacs highlighting..."
.TP
.B $NotifyAdministratorSubject \fR(default """MIMEDefang Notification"")
The subject used when e-mail is sent out by action_notify_administrator(). If
you set this, you should set it each time you call action_notify_administrator()
to ensure consistency.
.TP
.B $QuarantineSubject \fR(default """MIMEDefang Quarantine Report"")
The subject used when a quarantine notice is sent to the administrator. If
you set this, you should set it each time you call action_quarantine() or
action_quarantine_entire_message().
.TP
.B $NotifyNoPreamble \fR(default 0)
Normally, notifications sent by action_notify_sender() have a preamble warning
about message modifications. If you do not want this, set $NotifyNoPreamble
to 1.
.TP
.B $CSSHost \fR(default 127.0.0.1:7777:local)
Host and port for the Symantec CarrierScan Server virus scanner. This
takes the form \fIip_addr\fR:\fIport\fR:\fIlocal_or_nonlocal\fR. The
\fIip_addr\fR and \fIport\fR are the host and port on which
CarrierScan Server is listening. If you want to scan local files,
append :local to force the use of the AVSCANLOCAL command. If the
CarrierScan Server is on another host, append :nonlocal to force the
file contents to be sent to the scanner over the socket.
.TP
.B $SophieSock \fR(default @SPOOLDIR@/sophie)
Socket used for Sophie daemon calls within message_contains_virus_sophie
and entity_contains_virus_sophie unless a socket is provided by the calling
routine.
.TP
.B $ClamdSock \fR(default @SPOOLDIR@/clamd.sock)
Socket used for clamd daemon calls within message_contains_virus_clamd
and entity_contains_virus_clamd unless a socket is provided by the calling
routine.
.TP
.B $TrophieSock \fR(default @SPOOLDIR@/trophie)
Socket used for Trophie daemon calls within message_contains_virus_trophie
and entity_contains_virus_trophie unless a socket is provided by the calling
routine.
.SH FILTER
The heart of \fBmimedefang-filter\fR is the \fBfilter\fR procedure. See
the examples that came with MIMEDefang to learn to write a filter.
The filter is called with the following arguments:
.TP
.B $entity
The MIME::Entity object. (See the MIME::tools Perl module documentation.)
.TP
.B $fname
The suggested attachment filename, or "" if none was supplied.
.TP
.B $ext
The file extension (all characters from the rightmost period to the end of
the filename.)
.TP
.B $type
The MIME type (for example, "text/plain".)
.PP
The filename is derived as follows:
.TP
o
First, if the Content-Disposition header has a "filename" field, it is used.
.TP
o
Otherwise, if the Content-Type header has a "name" field, it is used.
.TP
o
Otherwise, the Content-Description header value is used.
.PP
Note that the truly paranoid will check all three fields for matches.
The functions \fBre_match\fR and \fBre_match_ext\fR perform regular
expression matches on all three of the fields named above, and return
1 if any field matches. See the sample filters for details. The
calling sequence is:
.nf
re_match($entity, "regexp")
re_match_ext($entity, "regexp")
.fi
\fBre_match\fR returns true if any of the fields matches the regexp without
regard to case. \fBre_match_ext\fR returns true if the extension in any
field matches. An extension is defined as the last dot in a name and
all remaining characters.
.PP
A third function called \fBre_match_in_zip_directory\fR will look inside
zip files and return true if any of the file names inside the zip archive
match the regular expression. Call it like this:
.nf
my $bh = $entity->bodyhandle();
my $path = (defined($bh)) ? $bh->path() : undef;
if (defined($path) and re_match_in_zip_directory($path, "regexp")) {
# Take action...
}
.fi
You should \fInot\fR call \fBre_match_in_zip_directory\fR unless you
know that the entity is a zip file attachment.
.PP
Another function called \fBre_match_in_rar_directory\fR will look inside
rar files and return true if any of the file names inside the rar archive
match the regular expression.
The function is very similar to \fBre_match_in_zip_directory\fR but the unrar
binary is required and must be specified in \fB$Features{"unrar"}\fR.
.PP
Another function called \fBre_match_in_7z_directory\fR will look inside
7zip files and return true if any of the file names inside the 7zip archive
match the regular expression.
The function is very similar to \fBre_match_in_zip_directory\fR but the 7z
binary is required and must be specified in \fB$Features{"7zip"}\fR.
.SH GLOBAL VARIABLES SET BY MIMEDEFANG.PL
The following global variables are set by \fBmimedefang.pl\fR and are
available for use in your filter. All of these variables are always
available to filter_begin, filter, filter_multipart and filter_end.
In addition, some of them are available in \fBfilter_relay\fR,
\fBfilter_sender\fR or \fBfilter_recipient\fR. If this is the case,
it will be noted below.
.TP
.B %Features
This hash lets you determine at run-time whether certain functionality
is available. This hash is available at all times assuming the
detect_and_load_perl_modules() function has been called. The defined
features are:
$Features{"SpamAssassin"} is 1 if SpamAssassin 1.6 or better is installed;
0 otherwise.
$Features{"HTML::Parser"} is 1 if HTML::Parser is installed; 0 otherwise.
$Features{"Virus:FPROTD"} is currently always 0. Set it to 1 in your
filter file if you have F-Risk's FPROTD scanner earlier than version 6.
$Features{"Virus:FPROTD6"} is currently always 0. Set it to 1 in your
filter file if you have version 6 of F-Risk's FPROTD scanner.
$Features{"Virus:SymantecCSS"} is currently always 0. Set it to 1 in
your filter file if you have the Symantec CarrierScan Server virus scanner.
$Features{"Virus:NAI"} is the full path to NAI uvscan if it is installed;
0 if it is not.
$Features{"Virus:BDC"} is the full path to Bitdefender bdc if it is installed;
0 if it is not.
$Features{"Virus:NVCC"} is the full path to Norman Virus Control nvcc
if it is installed; 0 if it is not.
$Features{"Virus:HBEDV"} is the full path to H+BEDV AntiVir if it is installed;
0 if it is not.
$Features{"Virus:VEXIRA"} is the full path to Central Command Vexira if it is installed;
0 if it is not.
$Features{"Virus:SOPHOS"} is the full path to Sophos sweep if it is installed;
0 if it is not.
$Features{"Virus:SAVSCAN"} is the full path to Sophos savscan if it is installed;
0 if it is not.
$Features{"Virus:CLAMAV"} is the full path to Clam AV clamscan if it is installed;
0 if it is not.
$Features{"Virus:AVP"} is the full path to AVP AvpLinux if it is installed;
0 if it is not.
$Features{"Virus:AVP5"} is the full path to Kaspersky "aveclient" if
it is installed; 0 if it is not.
$Features{"Virus:CSAV"} is the full path to Command csav if it is installed;
0 if it is not.
$Features{"Virus:FSAV"} is the full path to F-Secure fsav if it is installed;
0 if it is not.
$Features{"Virus:FPROT"} is the full path to F-Risk f-prot if it is installed;
0 if it is not.
$Features{"Virus:FPSCAN"} is the full path to F-Risk fpscan if it is installed;
0 if it is not.
$Features{"Virus:SOPHIE"} is the full path to Sophie if it is installed;
0 if it is not.
$Features{"Virus:CLAMD"} is the full path to clamd if it is installed;
0 if it is not.
$Features{"Virus:CLAMDSCAN"} is the full path to clamdscan if it is installed;
0 if it is not.
$Features{"Virus:TROPHIE"} is the full path to Trophie if it is installed;
0 if it is not.
$Features{"Virus:NOD32"} is the full path to ESET NOD32 nod32cli if it is installed;
0 if it is not.
$Features{"Path:RSPAMC"} is the full path to rspamc(1) if it is installed (deprecated);
0 if it is not.
\fBNOTE:\fR Perl-module based features such as SpamAssassin are determined at
runtime and may change as these are added and removed. Most Virus features are
predetermined at the time of configuration and do not adapt to runtime
availability unless changed by the filter rules.
.TP
.B $CWD
This variable holds the working directory for the current message.
During filter processing, \fBmimedefang.pl\fR chdir's into this
directory before calling any of the filter_ functions. Note that this
variable \fIis\fR set correctly in \fBfilter_sender\fR and
\fBfilter_recipient\fR, but \fInot\fR in \fBfilter_relay\fR.
.TP
.B $SuspiciousCharsInHeaders
If this variable is true, then \fBmimedefang\fR has discovered suspicious
characters in message headers. This might be an exploit for bugs
in MIME-parsing routines in some badly-written mail user agents
(e.g. Microsoft Outlook.) You should \fIalways\fR drop such messages.
.TP
.B $SuspiciousCharsInBody
If this variable is true, then \fBmimedefang\fR has discovered
suspicious characters in the message body. This might be an exploit
for bugs in MIME-parsing routines in some badly-written mail user
agents (e.g. Microsoft Outlook.) You should \fIalways\fR drop such
messages.
.TP
.B $RelayHostname
The host name of the relay. This is the name of the host that is
attempting to send e-mail to your host. May be "undef" if the host
name could not be determined. This variable is available in
\fBfilter_relay\fR, \fBfilter_sender\fR and \fBfilter_recipient\fR in
addition to the body filtering functions.
.TP
.B $RelayAddr
The IP address of the sending relay (as a string consisting of four
dot-separated decimal numbers.) One potential use of \fB$RelayAddr\fR
is to limit mailing to certain lists to people within your
organization. This variable is available in \fBfilter_relay\fR,
\fBfilter_sender\fR and \fBfilter_recipient\fR in addition to the body
filtering functions.
.TP
.B $Helo
The argument given to the SMTP "HELO" command. This variable is
available in \fBfilter_sender\fR and \fBfilter_recipient\fR,
but \fInot\fR in \fBfilter_relay\fR.
.TP
.B $Subject
The contents of the "Subject:" header.
.TP
.B $Sender
The sender of the e-mail. This variable is set in \fBfilter_sender\fR
and \fBfilter_recipient\fR in addition to the body filtering functions.
.TP
.B @Recipients
A list of the recipients. In \fBfilter_recipient\fR, it is set to the
single recipient currently under consideration. Or, after calling
\fBread_commands_file\fR within \fBfilter_recipient\fR, the current
recipient under consideration is in the final position of the array,
at \fB$Recipients[-1]\fR, while any previous (and accepted)
recipients are at the beginning of the array, that is, in
\fB@Recipients[0 .. $#Recipients-1]\fR.
.TP
.B $MessageID
The contents of the "Message-ID:" header if one is present. Otherwise,
contains the string "NOQUEUE".
.TP
.B $QueueID
The Sendmail queue identifier if it could be determined. This
variable \fIis\fR set correctly in \fBfilter_relay\fR,
\fBfilter_helo\fR, \fBfilter_sender\fR and \fBfilter_recipient\fR.
Note, however, that Postfix may not allocate a queue ID until
\fBfilter_recipient\fR time. If a Queue-ID has not yet been
allocated, $QueueID is set to "NOQUEUE".
.TP
.B $MsgID
Set to $QueueID if the queue ID could be determined; otherwise, set
to $MessageID. This identifier should be used in logging, because it
matches the identifier used by Sendmail to log messages. Note that this
variable \fIis\fR set correctly in \fBfilter_sender\fR
and \fBfilter_recipient\fR, but it is \fInot\fR available in
\fBfilter_relay\fR.
.TP
.B $VirusScannerMessages
Each time a virus-scanning function is called, messages (if any) from
the virus scanner are accumulated in this variable. You can use it
in filter_end to formulate a notification (if you wish.)
.TP
.B $VirusName
If a virus-scanning function found a virus, this variable will hold the
virus name (if it could be determined.)
.TP
.B $SASpamTester
If defined, this is the configured Mail::SpamAssassin object used for
mail tests. It may be initialized with a call to \fBspam_assassin_init\fR
which also returns it.
.TP
.B %SendmailMacros
This hash contains the values of some Sendmail macros. The hash elements
exist only for macros defined by Sendmail. See the Sendmail documentation
for the meanings of the macros.
By default, \fBmimedefang\fR passes the values of the following
macros: ${daemon_name}, ${daemon_port}, ${if_name}, ${if_addr}, $j,
$_, $i, ${tls_version}, ${cipher}, ${cipher_bits}, ${cert_subject},
${cert_issuer}, ${auth_type}, ${auth_authen}, ${auth_ssf},
${auth_author}, ${mail_mailer}, ${mail_host} and ${mail_addr}.
In addition, ${client_port} is set to the client's TCP port.
If any macro is not set or not passed to milter, it will be unavailable.
To access the value of a macro, use:
.nf
$SendmailMacros{"macro_name"}
.fi
Do not place curly brackets around the macro name.
This variable is available in \fBfilter_sender\fR and
\fBfilter_recipient\fR after a call to \fBread_commands_file\fR.
.TP
.B @SenderESMTPArgs
This array contains all the ESMTP arguments supplied in the MAIL FROM:
command. For example:
.nf
sub print_sender_esmtp_args {
foreach (@SenderESMTPArgs) {
print STDERR "Sender ESMTP arg: $_\n";
}
}
.fi
.TP
.B %RecipientESMTPArgs
This hash contains all the ESMTP arguments supplied in each RCPT TO:
command. For example: