PageRenderTime 76ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 3ms

/amavisd-new-2.8.0/amavisd

#
Perl | 11249 lines | 9407 code | 279 blank | 1563 comment | 824 complexity | 4fc193aa494cbf85ec5fb01922acc8f3 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. #!/usr/bin/perl -T
  2. #!/usr/bin/perl -d:NYTProf
  3. #------------------------------------------------------------------------------
  4. # This is amavisd-new.
  5. # It is an interface between a message transfer agent (MTA) and virus
  6. # scanners and/or spam scanners, functioning as a mail content filter.
  7. #
  8. # It is a performance-enhanced and feature-enriched version of amavisd
  9. # (which in turn is a daemonized version of AMaViS), initially based
  10. # on amavisd-snapshot-20020300).
  11. #
  12. # All work since amavisd-snapshot-20020300:
  13. # Copyright (C) 2002-2012 Mark Martinec,
  14. # All Rights Reserved.
  15. # with contributions from the amavis-user mailing list and individuals,
  16. # as acknowledged in the release notes.
  17. #
  18. # This program is free software; you can redistribute it and/or modify
  19. # it under the terms of the GNU General Public License as published by
  20. # the Free Software Foundation; either version 2 of the License, or
  21. # (at your option) any later version.
  22. #
  23. # This program is distributed in the hope that it will be useful,
  24. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. # GNU General Public License for details.
  27. #
  28. # You should have received a copy of the GNU General Public License
  29. # along with this program; if not, write to the Free Software
  30. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  31. # Author: Mark Martinec <Mark.Martinec@ijs.si>
  32. # Patches and problem reports are welcome.
  33. #
  34. # The latest version of this program is available at:
  35. # http://www.ijs.si/software/amavisd/
  36. #------------------------------------------------------------------------------
  37. # Here is a boilerplate from the amavisd(-snapshot) version,
  38. # which is the version that served as a base code for the initial
  39. # version of amavisd-new. License terms were the same:
  40. #
  41. # Author: Chris Mason <cmason@unixzone.com>
  42. # Current maintainer: Lars Hecking <lhecking@users.sourceforge.net>
  43. # Based on work by:
  44. # Mogens Kjaer, Carlsberg Laboratory, <mk@crc.dk>
  45. # Juergen Quade, Softing GmbH, <quade@softing.com>
  46. # Christian Bricart <shiva@aachalon.de>
  47. # Rainer Link <link@foo.fh-furtwangen.de>
  48. # This script is part of the AMaViS package. For more information see:
  49. # http://amavis.org/
  50. # Copyright (C) 2000 - 2002 the people mentioned above
  51. # This software is licensed under the GNU General Public License (GPL)
  52. # See: http://www.gnu.org/copyleft/gpl.html
  53. #------------------------------------------------------------------------------
  54. #------------------------------------------------------------------------------
  55. #Index of packages in this file
  56. # Amavis::Boot
  57. # Amavis::Conf
  58. # Amavis::Log
  59. # Amavis::DbgLog
  60. # Amavis::Timing
  61. # Amavis::Util
  62. # Amavis::ProcControl
  63. # Amavis::rfc2821_2822_Tools
  64. # Amavis::Lookup::RE
  65. # Amavis::Lookup::IP
  66. # Amavis::Lookup::Opaque
  67. # Amavis::Lookup::OpaqueRef
  68. # Amavis::Lookup::Label
  69. # Amavis::Lookup::SQLfield (just the new() method)
  70. # Amavis::Lookup::LDAPattr (just the new() method)
  71. # Amavis::Lookup
  72. # Amavis::Expand
  73. # Amavis::TempDir
  74. # Amavis::IO::FileHandle
  75. # Amavis::IO::Zlib
  76. # Amavis::IO::RW
  77. # Amavis::In::Connection
  78. # Amavis::In::Message::PerRecip
  79. # Amavis::In::Message
  80. # Amavis::Out::EditHeader
  81. # Amavis::Out
  82. # Amavis::UnmangleSender
  83. # Amavis::Unpackers::NewFilename
  84. # Amavis::Unpackers::Part
  85. # Amavis::Unpackers::OurFiler
  86. # Amavis::Unpackers::Validity
  87. # Amavis::Unpackers::MIME
  88. # Amavis::Notify
  89. # Amavis::Custom
  90. # Amavis
  91. #optionally compiled-in packages: ---------------------------------------------
  92. # Amavis::ZMQ
  93. # Amavis::DB::SNMP
  94. # Amavis::DB
  95. # Amavis::Lookup::SQLfield (the rest)
  96. # Amavis::Lookup::SQL
  97. # Amavis::LDAP::Connection
  98. # Amavis::Lookup::LDAP
  99. # Amavis::Lookup::LDAPattr (the rest)
  100. # Amavis::In::AMPDP
  101. # Amavis::In::SMTP
  102. #( Amavis::In::Courier )
  103. # Amavis::Out::SMTP::Protocol
  104. # Amavis::Out::SMTP::Session
  105. # Amavis::Out::SMTP
  106. # Amavis::Out::Pipe
  107. # Amavis::Out::BSMTP
  108. # Amavis::Out::Local
  109. # Amavis::OS_Fingerprint
  110. # Amavis::Out::SQL::Connection
  111. # Amavis::Out::SQL::Log
  112. # Amavis::IO::SQL
  113. # Amavis::Out::SQL::Quarantine
  114. # Amavis::AV
  115. # Amavis::SpamControl
  116. # Amavis::SpamControl::ExtProg
  117. # Amavis::SpamControl::SpamdClient
  118. # Mail::SpamAssassin::Logger::Amavislog
  119. # Amavis::SpamControl::SpamAssassin
  120. # Amavis::Unpackers
  121. # Amavis::DKIM::CustomSigner
  122. # Amavis::DKIM
  123. # Amavis::Tools
  124. #------------------------------------------------------------------------------
  125. use strict;
  126. use re 'taint';
  127. use warnings;
  128. use warnings FATAL => qw(utf8 void);
  129. no warnings 'uninitialized';
  130. #
  131. package Amavis::Boot;
  132. use strict;
  133. use re 'taint';
  134. use Errno qw(ENOENT EACCES);
  135. # replacement for a 'require' with a more informative error handling
  136. #sub my_require($) {
  137. # my($filename) = @_;
  138. # my $result;
  139. # if (exists $INC{$filename} && !$INC{$filename}) {
  140. # die "Compilation failed in require\n";
  141. # } elsif (exists $INC{$filename}) {
  142. # $result = 1; # already loaded
  143. # } else {
  144. # my $found = 0;
  145. # for my $prefix (@INC) {
  146. # my $full_fname = "$prefix/$filename";
  147. # my(@stat_list) = stat($full_fname); # symlinks-friendly
  148. # my $errn = @stat_list ? 0 : 0+$!;
  149. # if ($errn != ENOENT) {
  150. # $found = 1;
  151. # $INC{$filename} = $full_fname;
  152. # my $owner_uid = $stat_list[4];
  153. # my $msg;
  154. # if ($errn) { $msg = "is inaccessible: $!" }
  155. # elsif (-d _) { $msg = "is a directory" }
  156. # elsif (!-f _) { $msg = "is not a regular file" }
  157. # elsif ($> && -o _) { $msg = "should not be owned by EUID $>" }
  158. # elsif ($> && -w _) { $msg = "is writable by EUID $>, EGID $)" }
  159. # elsif ($owner_uid) { $msg = "should be owned by root (uid 0) "}
  160. # !defined($msg) or die "Requiring $full_fname, file $msg,\n";
  161. # $! = 0;
  162. # $result = do $full_fname;
  163. # if (!defined($result) && $@ ne '') {
  164. # undef $INC{$filename}; chomp($@);
  165. # die "Error in file $full_fname: $@\n";
  166. # } elsif (!defined($result) && $! != 0) {
  167. # undef $INC{$filename};
  168. # die "Error reading file $full_fname: $!\n";
  169. # } elsif (!$result) {
  170. # undef $INC{$filename};
  171. # die "Module $full_fname did not return a true value\n";
  172. # }
  173. # last;
  174. # }
  175. # }
  176. # die sprintf("my_require: Can't locate %s in \@INC (\@INC contains: %s)\n",
  177. # $filename, join(' ',@INC)) if !$found;
  178. # }
  179. # $result;
  180. #}
  181. # Fetch all required modules (or nicely report missing ones), and compile them
  182. # once-and-for-all at the parent process, so that forked children can inherit
  183. # and share already compiled code in memory. Children will still need to 'use'
  184. # modules if they want to inherit from their name space.
  185. #
  186. sub fetch_modules($$@) {
  187. my($reason, $required, @modules) = @_;
  188. my $have_sawampersand = Devel::SawAmpersand->UNIVERSAL::can('sawampersand');
  189. my $amp = $have_sawampersand && Devel::SawAmpersand::sawampersand() ? 1 : 0;
  190. warn 'fetch_modules: PL_sawampersand flag was already turned on' if $amp;
  191. my(@missing);
  192. for my $m (@modules) {
  193. local $_ = $m;
  194. $_ .= /^auto::/ ? '.al' : '.pm' if !m{^/} && !m{\.(?:pm|pl|al|ix)\z};
  195. s{::}{/}g;
  196. # eval { my_require $_ } #more informative on err, but some problems reported
  197. eval { require $_ }
  198. or do {
  199. my $eval_stat = $@ ne '' ? $@ : "errno=$!"; chomp $eval_stat;
  200. push(@missing,$m);
  201. $eval_stat =~ s/^/ /mgs; # indent
  202. printf STDERR ("fetch_modules: error loading %s module %s:\n%s\n",
  203. $required ? 'required' : 'optional', $_, $eval_stat)
  204. if $eval_stat !~ /\bCan't locate \Q$_\E in \@INC\b/;
  205. };
  206. if ($have_sawampersand && !$amp && Devel::SawAmpersand::sawampersand())
  207. { $amp = 1; warn "Loading of module $m turned on PL_sawampersand flag" }
  208. }
  209. die "ERROR: MISSING $reason:\n" . join('', map(" $_\n", @missing))
  210. if $required && @missing;
  211. \@missing;
  212. }
  213. BEGIN {
  214. if ($] <= 5.008) { # deal with a glob() taint bug (perl 5.6.1, 5.8.0)
  215. fetch_modules('REQUIRED BASIC MODULES', 1, qw(File::Glob));
  216. File::Glob->import(':globally'); # use the same module as Perl 5.8 uses
  217. }
  218. fetch_modules('REQUIRED BASIC MODULES', 1, qw(
  219. Exporter POSIX Fcntl Socket Errno Carp Time::HiRes
  220. IO::Handle IO::File IO::Socket IO::Socket::UNIX
  221. IO::Stringy Digest::MD5 Unix::Syslog File::Basename
  222. Compress::Zlib MIME::Base64 MIME::QuotedPrint MIME::Words
  223. MIME::Head MIME::Body MIME::Entity MIME::Parser MIME::Decoder
  224. MIME::Decoder::Base64 MIME::Decoder::Binary MIME::Decoder::QuotedPrint
  225. MIME::Decoder::NBit MIME::Decoder::UU MIME::Decoder::Gzip64
  226. Net::Server Net::Server::PreFork
  227. ));
  228. # with earlier versions of Perl one may need to add additional modules
  229. # to the list, such as: auto::POSIX::setgid auto::POSIX::setuid ...
  230. fetch_modules('OPTIONAL BASIC MODULES', 0, qw(
  231. PerlIO PerlIO::scalar Unix::Getrusage
  232. Carp::Heavy auto::POSIX::setgid auto::POSIX::setuid
  233. auto::POSIX::SigAction::new auto::POSIX::SigAction::safe
  234. MIME::Decoder::BinHex
  235. ));
  236. 1;
  237. }
  238. 1;
  239. #
  240. package Amavis::Conf;
  241. use strict;
  242. use re 'taint';
  243. # constants; intentionally leave value -1 unassigned for compatibility
  244. use constant D_TEMPFAIL => -4;
  245. use constant D_REJECT => -3;
  246. use constant D_BOUNCE => -2;
  247. use constant D_DISCARD => 0;
  248. use constant D_PASS => 1;
  249. # major contents_category constants, in increasing order of importance
  250. use constant CC_CATCHALL => 0;
  251. use constant CC_CLEAN => 1; # tag_level = "CC_CLEAN,1"
  252. use constant CC_MTA => 2; # trouble passing mail back to MTA
  253. use constant CC_OVERSIZED => 3;
  254. use constant CC_BADH => 4;
  255. use constant CC_SPAMMY => 5; # tag2_level (and: tag3_level = CC_SPAMMY,1)
  256. use constant CC_SPAM => 6; # kill_level
  257. use constant CC_UNCHECKED => 7;
  258. use constant CC_BANNED => 8;
  259. use constant CC_VIRUS => 9;
  260. #
  261. # in other words: major_ccat minor_ccat %subject_tag_maps_by_ccat
  262. ## if score >= kill level => CC_SPAM 0
  263. ## elsif score >= tag3 level => CC_SPAMMY 1 @spam_subject_tag3_maps
  264. ## elsif score >= tag2 level => CC_SPAMMY 0 @spam_subject_tag2_maps
  265. ## elsif score >= tag level => CC_CLEAN 1 @spam_subject_tag_maps
  266. ## else => CC_CLEAN 0
  267. BEGIN {
  268. require Exporter;
  269. use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION);
  270. $VERSION = '2.316';
  271. @ISA = qw(Exporter);
  272. %EXPORT_TAGS = (
  273. 'dynamic_confvars' => # per- policy bank settings
  274. [qw(
  275. $child_timeout $smtpd_timeout
  276. $policy_bank_name $protocol @inet_acl
  277. $myhostname $myauthservid $snmp_contact $snmp_location
  278. $myprogram_name $syslog_ident $syslog_facility
  279. $log_level $log_templ $log_recip_templ $enable_log_capture_dump
  280. $forward_method $notify_method $resend_method $report_format
  281. $release_method $requeue_method $release_format
  282. $attachment_password $attachment_email_name $attachment_outer_name
  283. $os_fingerprint_method $os_fingerprint_dst_ip_and_port
  284. $originating @smtpd_discard_ehlo_keywords $soft_bounce
  285. $propagate_dsn_if_possible $terminate_dsn_on_notify_success
  286. $amavis_auth_user $amavis_auth_pass $auth_reauthenticate_forwarded
  287. $auth_required_out $auth_required_inp $auth_required_release
  288. @auth_mech_avail $tls_security_level_in $tls_security_level_out
  289. $local_client_bind_address $smtpd_message_size_limit
  290. $localhost_name $smtpd_greeting_banner $smtpd_quit_banner
  291. $mailfrom_to_quarantine $warn_offsite $bypass_decode_parts @decoders
  292. @av_scanners @av_scanners_backup @spam_scanners
  293. $first_infected_stops_scan $virus_scanners_failure_is_fatal
  294. $sa_spam_level_char $sa_mail_body_size_limit
  295. $penpals_bonus_score $penpals_halflife $bounce_killer_score
  296. $reputation_factor
  297. $undecipherable_subject_tag $localpart_is_case_sensitive
  298. $recipient_delimiter $replace_existing_extension
  299. $hdr_encoding $bdy_encoding $hdr_encoding_qb
  300. $allow_disclaimers
  301. $prepend_header_fields_hdridx
  302. $allow_fixing_improper_header
  303. $allow_fixing_improper_header_folding $allow_fixing_long_header_lines
  304. %allowed_added_header_fields %prefer_our_added_header_fields
  305. %allowed_header_tests
  306. $X_HEADER_TAG $X_HEADER_LINE
  307. $remove_existing_x_scanned_headers $remove_existing_spam_headers
  308. %sql_clause $partition_tag
  309. %local_delivery_aliases $banned_namepath_re
  310. $per_recip_whitelist_sender_lookup_tables
  311. $per_recip_blacklist_sender_lookup_tables
  312. @anomy_sanitizer_args @altermime_args_defang
  313. @altermime_args_disclaimer @disclaimer_options_bysender_maps
  314. %signed_header_fields @dkim_signature_options_bysender_maps
  315. $enable_dkim_verification $enable_dkim_signing $dkim_signing_service
  316. $enable_ldap
  317. @local_domains_maps @mynetworks_maps @client_ipaddr_policy
  318. @forward_method_maps @newvirus_admin_maps @banned_filename_maps
  319. @spam_quarantine_bysender_to_maps
  320. @spam_tag_level_maps @spam_tag2_level_maps @spam_tag3_level_maps
  321. @spam_kill_level_maps
  322. @spam_subject_tag_maps @spam_subject_tag2_maps @spam_subject_tag3_maps
  323. @spam_dsn_cutoff_level_maps @spam_dsn_cutoff_level_bysender_maps
  324. @spam_crediblefrom_dsn_cutoff_level_maps
  325. @spam_crediblefrom_dsn_cutoff_level_bysender_maps
  326. @spam_quarantine_cutoff_level_maps @spam_notifyadmin_cutoff_level_maps
  327. @whitelist_sender_maps @blacklist_sender_maps @score_sender_maps
  328. @author_to_policy_bank_maps @signer_reputation_maps
  329. @message_size_limit_maps @debug_sender_maps @debug_recipient_maps
  330. @bypass_virus_checks_maps @bypass_spam_checks_maps
  331. @bypass_banned_checks_maps @bypass_header_checks_maps
  332. @viruses_that_fake_sender_maps
  333. @virus_name_to_spam_score_maps @virus_name_to_policy_bank_maps
  334. @remove_existing_spam_headers_maps
  335. @sa_userconf_maps @sa_username_maps
  336. %final_destiny_by_ccat %forward_method_maps_by_ccat
  337. %lovers_maps_by_ccat %defang_maps_by_ccat %subject_tag_maps_by_ccat
  338. %quarantine_method_by_ccat %quarantine_to_maps_by_ccat
  339. %notify_admin_templ_by_ccat %notify_recips_templ_by_ccat
  340. %notify_sender_templ_by_ccat %notify_autoresp_templ_by_ccat
  341. %notify_release_templ_by_ccat %notify_report_templ_by_ccat
  342. %warnsender_by_ccat
  343. %hdrfrom_notify_admin_by_ccat %mailfrom_notify_admin_by_ccat
  344. %hdrfrom_notify_recip_by_ccat %mailfrom_notify_recip_by_ccat
  345. %hdrfrom_notify_sender_by_ccat
  346. %hdrfrom_notify_release_by_ccat %hdrfrom_notify_report_by_ccat
  347. %admin_maps_by_ccat %warnrecip_maps_by_ccat
  348. %always_bcc_by_ccat %dsn_bcc_by_ccat
  349. %addr_extension_maps_by_ccat %addr_rewrite_maps_by_ccat
  350. %smtp_reason_by_ccat
  351. )],
  352. 'confvars' => # global settings (not per-policy, not per-recipient)
  353. [qw(
  354. $myproduct_name $myversion_id $myversion_id_numeric $myversion_date
  355. $myversion $instance_name @additional_perl_modules
  356. $MYHOME $TEMPBASE $QUARANTINEDIR $quarantine_subdir_levels
  357. $daemonize $courierfilter_shutdown $pid_file $lock_file $db_home
  358. $enable_db $enable_zmq @zmq_sockets $mail_id_size_bits
  359. $daemon_user $daemon_group $daemon_chroot_dir $path
  360. $DEBUG $do_syslog $logfile $allow_preserving_evidence $enable_log_capture
  361. $log_short_templ $log_verbose_templ $logline_maxlen
  362. $nanny_details_level $max_servers $max_requests
  363. $min_servers $min_spare_servers $max_spare_servers
  364. %current_policy_bank %policy_bank %interface_policy
  365. @listen_sockets $inet_socket_port $inet_socket_bind $listen_queue_size
  366. $unix_socketname $unix_socket_mode
  367. $smtp_connection_cache_on_demand $smtp_connection_cache_enable
  368. $smtpd_recipient_limit
  369. $smtpd_tls_cert_file $smtpd_tls_key_file
  370. $enforce_smtpd_message_size_limit_64kb_min
  371. $MAXLEVELS $MAXFILES
  372. $MIN_EXPANSION_QUOTA $MIN_EXPANSION_FACTOR
  373. $MAX_EXPANSION_QUOTA $MAX_EXPANSION_FACTOR
  374. $database_sessions_persistent $lookup_maps_imply_sql_and_ldap
  375. @lookup_sql_dsn @storage_sql_dsn
  376. $sql_schema_version $timestamp_fmt_mysql
  377. $sql_quarantine_chunksize_max $sql_allow_8bit_address
  378. $sql_lookups_no_at_means_domain $ldap_lookups_no_at_means_domain
  379. $sql_store_info_for_all_msgs
  380. $trim_trailing_space_in_lookup_result_fields
  381. $default_ldap $mail_digest_algorithm
  382. @keep_decoded_original_maps @map_full_type_to_short_type_maps
  383. %banned_rules $penpals_threshold_low $penpals_threshold_high
  384. %dkim_signing_keys_by_domain
  385. @dkim_signing_keys_list @dkim_signing_keys_storage
  386. $file $altermime $enable_anomy_sanitizer
  387. )],
  388. 'sa' => # global SpamAssassin settings
  389. [qw(
  390. $spamcontrol_obj $sa_num_instances
  391. $helpers_home $sa_configpath $sa_siteconfigpath $sa_userprefs_file
  392. $sa_local_tests_only $sa_timeout $sa_debug
  393. $dspam $sa_spawned
  394. )],
  395. 'platform' => [qw(
  396. $can_truncate $unicode_aware $my_pid
  397. $AF_INET6 $have_inet4 $have_inet6 $have_socket_ip
  398. &D_TEMPFAIL &D_REJECT &D_BOUNCE &D_DISCARD &D_PASS
  399. &CC_CATCHALL &CC_CLEAN &CC_MTA &CC_OVERSIZED &CC_BADH
  400. &CC_SPAMMY &CC_SPAM &CC_UNCHECKED &CC_BANNED &CC_VIRUS
  401. %ccat_display_names %ccat_display_names_major
  402. )],
  403. # other variables settable by user in amavisd.conf,
  404. # but not directly accessible to the program
  405. 'hidden_confvars' => [qw(
  406. $mydomain
  407. )],
  408. 'legacy_dynamic_confvars' =>
  409. # the rest of the program does not use these settings directly and they
  410. # should not be visible in, or imported to other modules, but may be
  411. # referenced indirectly through *_by_ccat variables for compatibility
  412. [qw(
  413. $final_virus_destiny $final_banned_destiny $final_unchecked_destiny
  414. $final_spam_destiny $final_bad_header_destiny
  415. @virus_lovers_maps @spam_lovers_maps @unchecked_lovers_maps
  416. @banned_files_lovers_maps @bad_header_lovers_maps
  417. $always_bcc $dsn_bcc
  418. $mailfrom_notify_sender $mailfrom_notify_recip
  419. $mailfrom_notify_admin $mailfrom_notify_spamadmin
  420. $hdrfrom_notify_sender $hdrfrom_notify_recip
  421. $hdrfrom_notify_admin $hdrfrom_notify_spamadmin
  422. $hdrfrom_notify_release $hdrfrom_notify_report
  423. $notify_virus_admin_templ $notify_spam_admin_templ
  424. $notify_virus_recips_templ $notify_spam_recips_templ
  425. $notify_virus_sender_templ $notify_spam_sender_templ
  426. $notify_sender_templ $notify_release_templ
  427. $notify_report_templ $notify_autoresp_templ
  428. $warnbannedsender $warnbadhsender
  429. $defang_virus $defang_banned $defang_spam
  430. $defang_bad_header $defang_undecipherable $defang_all
  431. $virus_quarantine_method $banned_files_quarantine_method
  432. $unchecked_quarantine_method $spam_quarantine_method
  433. $bad_header_quarantine_method $clean_quarantine_method
  434. $archive_quarantine_method
  435. @virus_quarantine_to_maps @banned_quarantine_to_maps
  436. @unchecked_quarantine_to_maps @spam_quarantine_to_maps
  437. @bad_header_quarantine_to_maps @clean_quarantine_to_maps
  438. @archive_quarantine_to_maps
  439. @virus_admin_maps @banned_admin_maps
  440. @spam_admin_maps @bad_header_admin_maps @spam_modifies_subj_maps
  441. @warnvirusrecip_maps @warnbannedrecip_maps @warnbadhrecip_maps
  442. @addr_extension_virus_maps @addr_extension_spam_maps
  443. @addr_extension_banned_maps @addr_extension_bad_header_maps
  444. )],
  445. 'legacy_confvars' =>
  446. # legacy variables, predeclared for compatibility of amavisd.conf
  447. # The rest of the program does not use them directly and they should
  448. # not be visible in other modules, but may be referenced through
  449. # @*_maps variables for backwards compatibility
  450. [qw(
  451. %local_domains @local_domains_acl $local_domains_re @mynetworks
  452. %bypass_virus_checks @bypass_virus_checks_acl $bypass_virus_checks_re
  453. %bypass_spam_checks @bypass_spam_checks_acl $bypass_spam_checks_re
  454. %bypass_banned_checks @bypass_banned_checks_acl $bypass_banned_checks_re
  455. %bypass_header_checks @bypass_header_checks_acl $bypass_header_checks_re
  456. %virus_lovers @virus_lovers_acl $virus_lovers_re
  457. %spam_lovers @spam_lovers_acl $spam_lovers_re
  458. %banned_files_lovers @banned_files_lovers_acl $banned_files_lovers_re
  459. %bad_header_lovers @bad_header_lovers_acl $bad_header_lovers_re
  460. %virus_admin %spam_admin
  461. $newvirus_admin $virus_admin $banned_admin $bad_header_admin $spam_admin
  462. $warnvirusrecip $warnbannedrecip $warnbadhrecip
  463. $virus_quarantine_to $banned_quarantine_to $unchecked_quarantine_to
  464. $spam_quarantine_to $spam_quarantine_bysender_to
  465. $bad_header_quarantine_to $clean_quarantine_to $archive_quarantine_to
  466. $keep_decoded_original_re $map_full_type_to_short_type_re
  467. $banned_filename_re $viruses_that_fake_sender_re
  468. $sa_tag_level_deflt $sa_tag2_level_deflt $sa_tag3_level_deflt
  469. $sa_kill_level_deflt
  470. $sa_quarantine_cutoff_level @spam_notifyadmin_cutoff_level_maps
  471. $sa_dsn_cutoff_level $sa_crediblefrom_dsn_cutoff_level
  472. $sa_spam_modifies_subj $sa_spam_subject_tag1 $sa_spam_subject_tag
  473. %whitelist_sender @whitelist_sender_acl $whitelist_sender_re
  474. %blacklist_sender @blacklist_sender_acl $blacklist_sender_re
  475. $addr_extension_virus $addr_extension_spam
  476. $addr_extension_banned $addr_extension_bad_header
  477. $sql_select_policy $sql_select_white_black_list
  478. $gets_addr_in_quoted_form @debug_sender_acl
  479. $arc $bzip2 $lzop $lha $unarj $gzip $uncompress $unfreeze
  480. $unrar $zoo $pax $cpio $ar $rpm2cpio $cabextract $ripole $tnef
  481. $gunzip $bunzip2 $unlzop $unstuff
  482. $SYSLOG_LEVEL $syslog_priority $append_header_fields_to_bottom
  483. $insert_received_line $notify_xmailer_header $relayhost_is_client
  484. $sa_spam_report_header $sa_auto_whitelist
  485. $warnvirussender $warnspamsender
  486. $enable_global_cache
  487. $virus_check_negative_ttl $virus_check_positive_ttl
  488. $spam_check_negative_ttl $spam_check_positive_ttl
  489. )],
  490. );
  491. Exporter::export_tags qw(dynamic_confvars confvars sa platform
  492. hidden_confvars legacy_dynamic_confvars legacy_confvars);
  493. 1;
  494. } # BEGIN
  495. use POSIX ();
  496. use Carp ();
  497. use Errno qw(ENOENT EACCES EBADF);
  498. use vars @EXPORT;
  499. sub c($); sub cr($); sub ca($); sub dkim_key($$$;@); # prototypes
  500. use subs qw(c cr ca dkim_key); # access subroutines to config vars and keys
  501. BEGIN { push(@EXPORT,qw(c cr ca dkim_key)) }
  502. # access to dynamic config variables, returns a scalar config variable value;
  503. # one level of indirection is allowed
  504. #
  505. sub c($) {
  506. my $var = $current_policy_bank{$_[0]};
  507. if (!defined $var) {
  508. my $name = $_[0];
  509. if (!exists $current_policy_bank{$name}) {
  510. Carp::croak(sprintf('No entry "%s" in policy bank "%s"',
  511. $name, $current_policy_bank{'policy_bank_name'}));
  512. }
  513. }
  514. my $r = ref $var;
  515. !$r ? $var : $r eq 'SCALAR' || $r eq 'REF' ? $$var : $var;
  516. }
  517. # return a ref to a config variable value, or undef if var is undefined
  518. #
  519. sub cr($) {
  520. my $var = $current_policy_bank{$_[0]};
  521. if (!defined $var) {
  522. my $name = $_[0];
  523. if (!exists $current_policy_bank{$name}) {
  524. Carp::croak(sprintf('No entry "%s" in policy bank "%s"',
  525. $name, $current_policy_bank{'policy_bank_name'}));
  526. }
  527. }
  528. !defined $var ? undef : !ref $var ? \$var : $var;
  529. }
  530. # return a ref to a config variable value (which is supposed to be an array),
  531. # converting undef to an empty array, and a scalar to a one-element array
  532. # if necessary
  533. #
  534. sub ca($) {
  535. my $var = $current_policy_bank{$_[0]};
  536. if (!defined $var) {
  537. my $name = $_[0];
  538. if (!exists $current_policy_bank{$name}) {
  539. Carp::croak(sprintf('No entry "%s" in policy bank "%s"',
  540. $name, $current_policy_bank{'policy_bank_name'}));
  541. }
  542. }
  543. !defined $var ? [] : !ref $var ? [$var] : $var;
  544. }
  545. sub deprecate_var($$$) {
  546. my($data_type, $var_name, $init_value) = @_;
  547. my $code = <<'EOD';
  548. tie(%n, '%p', %v) or die 'Tieing a variable %n failed';
  549. package %p;
  550. use strict; use Carp ();
  551. sub TIESCALAR { my($class,$val) = @_; bless \$val, $class }
  552. sub FETCH { my $self = shift; $$self }
  553. sub STORE { my($self,$newv) = @_; my $oldv = $$self;
  554. if ((defined $oldv || defined $newv) && (%t)) {
  555. Carp::carp('Variable %n was retired, changing its value has no effect.'
  556. . " See release notes.\n");
  557. }
  558. $$self = $newv;
  559. }
  560. 1;
  561. EOD
  562. if ($data_type eq 'bool') {
  563. $code =~ s{%t}'($oldv ? 1 : 0) != ($newv ? 1 : 0)'g;
  564. } elsif ($data_type eq 'num') {
  565. $code =~ s{%t}'!defined $oldv || !defined $newv || $oldv != $newv'g;
  566. } elsif ($data_type eq 'str') {
  567. $code =~ s{%t}'!defined $oldv || !defined $newv || $oldv ne $newv'g;
  568. } else {
  569. die "Error deprecating a variable $var_name: bad type $data_type";
  570. }
  571. $code =~ s/%n/$var_name/g;
  572. $code =~ s/%v/\$init_value/g;
  573. my $barename = $var_name;
  574. $barename =~ s/^[\$\@%&]//; $code =~ s/%p/Amavis::Deprecate::$barename/g;
  575. eval $code
  576. or do { chomp $@; die "Error deprecating a variable $var_name: $@" };
  577. }
  578. # Store a private DKIM signing key for a given domain and selector.
  579. # The argument $key can be a Mail::DKIM::PrivateKey object or a file
  580. # name containing a key in a PEM format (e.g. as generated by openssl).
  581. # For compatibility with dkim_milter the signing domain can include a '*'
  582. # as a wildcard - this is not recommended as this way amavisd could produce
  583. # signatures which have no corresponding public key published in DNS.
  584. # The proper way is to have one dkim_key entry for each published DNS RR.
  585. # Optional arguments can provide additional information about the resource
  586. # record (RR) of a public key, i.e. its options according to RFC 4871.
  587. # The subroutine is typically called from a configuration file, once for
  588. # each signing key available.
  589. #
  590. sub dkim_key($$$;@) {
  591. my($domain,$selector,$key) = @_; shift; shift; shift;
  592. @_%2 == 0 or die "dkim_key: a list of key/value pairs expected as options\n";
  593. my(%key_options) = @_; # remaining args are options from a public key RR
  594. defined $domain && $domain ne ''
  595. or die "dkim_key: domain must not be empty: ($domain,$selector,$key)";
  596. defined $selector && $selector ne ''
  597. or die "dkim_key: selector must not be empty: ($domain,$selector,$key)";
  598. my $key_storage_ind;
  599. if (ref $key) { # key already preprocessed and provided as an object
  600. push(@dkim_signing_keys_storage, [$key]);
  601. $key_storage_ind = $#dkim_signing_keys_storage;
  602. } else { # assume a name of a file containing a private key in PEM format
  603. my $fname = $key;
  604. my $pem_fh = IO::File->new; # open a file with a private key
  605. $pem_fh->open($fname,'<') or die "Can't open PEM file $fname: $!";
  606. my(@stat_list) = stat($pem_fh); # soft-link friendly
  607. @stat_list or warn "Error accessing $fname: $!";
  608. my($dev,$inode) = @stat_list;
  609. if ($dev && $inode) {
  610. for my $j (0..$#dkim_signing_keys_storage) { # same file reused?
  611. my($k,$dv,$in,$fn) = @{$dkim_signing_keys_storage[$j]};
  612. if ($dv == $dev && $in == $inode) { $key_storage_ind = $j; last }
  613. }
  614. }
  615. if (!defined($key_storage_ind)) {
  616. # read file and store its contents as a new entry
  617. $key = ''; Amavis::Util::read_file($pem_fh,\$key);
  618. my $key_fit = $key; # shrink allocated storage size to actual size
  619. undef $key; # release storage
  620. push(@dkim_signing_keys_storage, [$key_fit, $dev, $inode, $fname]);
  621. $key_storage_ind = $#dkim_signing_keys_storage;
  622. }
  623. $pem_fh->close or die "Error closing file $fname: $!";
  624. $key_options{k} = 'rsa' if defined $key_options{k}; # force RSA
  625. }
  626. $domain = lc($domain) if !ref($domain); # possibly a regexp
  627. $selector = lc($selector);
  628. $key_options{domain} = $domain; $key_options{selector} = $selector;
  629. $key_options{key_storage_ind} = $key_storage_ind;
  630. if (@dkim_signing_keys_list > 100) {
  631. # sorry, skip the test to avoid slow O(n^2) searches
  632. } else {
  633. !grep($_->{domain} eq $domain && $_->{selector} eq $selector,
  634. @dkim_signing_keys_list)
  635. or die "dkim_key: selector $selector for domain $domain already in use\n";
  636. }
  637. $key_options{key_ind} = $#dkim_signing_keys_list + 1;
  638. push(@dkim_signing_keys_list, \%key_options); # using a list preserves order
  639. }
  640. # essential initializations, right at the program start time, may run as root!
  641. #
  642. use vars qw($read_config_files_depth @actual_config_files);
  643. BEGIN { # init_primary: version, $unicode_aware, base policy bank
  644. $myprogram_name = $0; # typically 'amavisd'
  645. local $1; $myprogram_name =~ s{([^/]*)\z}{$1}s;
  646. $myproduct_name = 'amavisd-new';
  647. $myversion_id = '2.8.0'; $myversion_date = '20120630';
  648. $myversion = "$myproduct_name-$myversion_id ($myversion_date)";
  649. $myversion_id_numeric = # x.yyyzzz, allows numerical compare, like Perl $]
  650. sprintf('%8.6f', $1 + ($2 + $3/1000)/1000)
  651. if $myversion_id =~ /^(\d+)(?:\.(\d*)(?:\.(\d*))?)?(.*)$/;
  652. $sql_schema_version = $myversion_id_numeric;
  653. $unicode_aware =
  654. $] >= 5.008 && length("\x{263a}")==1 && eval { require Encode };
  655. $read_config_files_depth = 0;
  656. eval { require Devel::SawAmpersand } or 1; # load if avail, ignore failure
  657. # initialize policy bank hash to contain dynamic config settings
  658. for my $tag (@EXPORT_TAGS{'dynamic_confvars', 'legacy_dynamic_confvars'}) {
  659. for my $v (@$tag) {
  660. local($1,$2);
  661. if ($v !~ /^([%\$\@])(.*)\z/) { die "Unsupported variable type: $v" }
  662. else {
  663. no strict 'refs'; my($type,$name) = ($1,$2);
  664. $current_policy_bank{$name} = $type eq '$' ? \${"Amavis::Conf::$name"}
  665. : $type eq '@' ? \@{"Amavis::Conf::$name"}
  666. : $type eq '%' ? \%{"Amavis::Conf::$name"}
  667. : undef;
  668. }
  669. }
  670. }
  671. $current_policy_bank{'policy_bank_name'} = ''; # builtin policy
  672. $current_policy_bank{'policy_bank_path'} = '';
  673. $policy_bank{''} = { %current_policy_bank }; # copy
  674. 1;
  675. } # end BEGIN - init_primary
  676. # boot-time initializations of simple global settings, may run as root!
  677. #
  678. BEGIN {
  679. # serves only as a quick default for other configuration settings
  680. $MYHOME = '/var/amavis';
  681. $mydomain = '!change-mydomain-variable!.example.com';#intentionally bad deflt
  682. # Create debugging output - true: log to stderr; false: log to syslog/file
  683. $DEBUG = 0;
  684. # In case of trouble, allow preserving temporary files for forensics
  685. $allow_preserving_evidence = 1;
  686. # Cause Net::Server parameters 'background' and 'setsid' to be set,
  687. # resulting in the program to detach itself from the terminal
  688. $daemonize = 1;
  689. # Net::Server pre-forking settings - defaults, overruled by amavisd.conf
  690. $max_servers = 2; # number of pre-forked children
  691. $max_requests = 20; # retire a child after that many accepts, 0=unlimited
  692. # timeout for our processing:
  693. $child_timeout = 8*60; # abort child if it does not complete a task in n sec
  694. # timeout for waiting on client input:
  695. $smtpd_timeout = 8*60; # disconnect session if client is idle for too long;
  696. # $smtpd_timeout should be higher than Postfix's max_idle (default 100s)
  697. # Assume STDIN is a courierfilter pipe and shutdown when it becomes readable
  698. $courierfilter_shutdown = 0;
  699. # Can file be truncated?
  700. # Set to 1 if 'truncate' works (it is XPG4-UNIX standard feature,
  701. # not required by Posix).
  702. # Things will go faster with SMTP-in, otherwise (e.g. with milter)
  703. # it makes no difference as file truncation will not be used.
  704. $can_truncate = 1;
  705. # Customizable notification messages, logging
  706. $syslog_ident = 'amavis';
  707. $syslog_facility = 'mail';
  708. $log_level = 0;
  709. # should be less than (1023 - prefix), i.e. 980,
  710. # to avoid syslog truncating lines; see sub write_log
  711. $logline_maxlen = 980;
  712. $nanny_details_level = 1; # register_proc verbosity: 0, 1, 2
  713. # $inner_sock_specs in amavis-services should match one of the sockets
  714. # in the @zmq_sockets list
  715. # @zmq_sockets = ( "ipc://$MYHOME/amavisd-zmq.sock" ); # after-default
  716. # $enable_zmq = undef; # load optional module Amavis::ZMQ
  717. # # (interface to 0MQ or Crossroads I/O)
  718. # $enable_db = undef; # load optional modules Amavis::DB & Amavis::DB::SNMP
  719. # $enable_dkim_signing = undef;
  720. # $enable_dkim_verification = undef;
  721. $reputation_factor = 0.2; # a value between 0 and 1, controlling the amount
  722. # of 'bending' of a calculated spam score towards a fixed score assigned
  723. # to a signing domain (its 'reputation') through @signer_reputation_maps;
  724. # the formula is: adjusted_spam_score = f*reputation + (1-f)*spam_score;
  725. # which has the same semantics as auto_whitelist_factor in SpamAssassin AWL
  726. $database_sessions_persistent = 1; # keep SQL & LDAP sessions open when idle
  727. $lookup_maps_imply_sql_and_ldap = 1; # set to 0 to disable
  728. # Algorithm name for generating a mail header digest and a mail body digest:
  729. # either 'MD5' (will use Digest::MD5, fastest and smallest digest), or
  730. # anything else accepted by Digest::SHA->new(), e.g. 'SHA-1' or 'SHA-256'.
  731. # The generated digest may end up as part of a quarantine file name
  732. # or via macro %b in log or notification templates.
  733. #
  734. $mail_digest_algorithm = 'MD5'; # or 'SHA-1' or 'SHA-256', ...
  735. # Where to find SQL server(s) and database to support SQL lookups?
  736. # A list of triples: (dsn,user,passw). Specify more than one
  737. # for multiple (backup) SQL servers.
  738. #
  739. #@storage_sql_dsn =
  740. #@lookup_sql_dsn =
  741. # ( ['DBI:mysql:mail:host1', 'some-username1', 'some-password1'],
  742. # ['DBI:mysql:mail:host2', 'some-username2', 'some-password2'] );
  743. # Does a database mail address field with no '@' character represent a
  744. # local username or a domain name? By default it implies a username in
  745. # SQL and LDAP lookups (but represents a domain in hash and acl lookups),
  746. # so domain names in SQL and LDAP should be specified as '@domain'.
  747. # Setting these to true will cause 'xxx' to be interpreted as a domain
  748. # name, just like in hash or acl lookups.
  749. #
  750. $sql_lookups_no_at_means_domain = 0;
  751. $ldap_lookups_no_at_means_domain = 0;
  752. # Maximum size (in bytes) for data written to a field 'quarantine.mail_text'
  753. # when quarantining to SQL. Must not exceed size allowed for a data type
  754. # on a given SQL server. It also determines a buffer size in amavisd.
  755. # Too large a value may exceed process virtual memory limits or just waste
  756. # memory, too small a value splits large mail into too many chunks, which
  757. # may be less efficient to process.
  758. #
  759. $sql_quarantine_chunksize_max = 16384;
  760. $sql_allow_8bit_address = 0;
  761. # the length of mail_id in bits, must be an integral multiple of 24
  762. # (i.e. divisible by 6 and 8); the mail_id is represented externally
  763. # as a base64url-encoded string of size $mail_id_size_bits / 6
  764. #
  765. $mail_id_size_bits = 72; # 24, 48, 72, 96
  766. $sql_store_info_for_all_msgs = 1;
  767. $penpals_bonus_score = undef; # maximal (positive) score value by which spam
  768. # score is lowered when sender is known to have previously received mail
  769. # from our local user from this mail system. Zero or undef disables
  770. # pen pals lookups in SQL tables msgs and msgrcpt, and is a default.
  771. $penpals_halflife = 7*24*60*60; # exponential decay time constant in seconds;
  772. # pen pal bonus is halved for each halflife period since the last mail
  773. # sent by a local user to a current message's sender
  774. $penpals_threshold_low = 1.0; # SA score below which pen pals lookups are
  775. # not performed to save time; undef lets the threshold be ignored;
  776. $penpals_threshold_high = undef;
  777. # when (SA_score - $penpals_bonus_score > $penpals_threshold_high)
  778. # pen pals lookup will not be performed to save time, as it could not
  779. # influence blocking of spam even at maximal penpals bonus (age=0);
  780. # usual choice for value would be kill level or other reasonably high
  781. # value; undef lets the threshold be ignored and is a default (useful
  782. # for testing and statistics gathering);
  783. $bounce_killer_score = 0;
  784. #
  785. # Receiving mail related
  786. # $unix_socketname = '/var/amavis/amavisd.sock'; # e.g. milter or release
  787. # $inet_socket_port = 10024; # accept SMTP on this TCP port
  788. # $inet_socket_port = [10024,10026,10027]; # ...possibly on more than one
  789. $AF_INET6 = eval { require Socket; Socket::AF_INET6() } ||
  790. eval { require Socket6; Socket6::AF_INET6() };
  791. # prefer using IO::Socket::IP if it exists, otherwise
  792. # fall back to IO::Socket::INET6 or IO::Socket::INET as appropriate
  793. #
  794. $have_socket_ip = eval {
  795. require IO::Socket::IP;
  796. };
  797. $have_inet4 = # can we make a PF_INET socket?
  798. $have_socket_ip ? eval {
  799. my $sock = IO::Socket::IP->new(LocalAddr => '0.0.0.0', Proto => 'udp');
  800. $sock->close or die "error closing inet6 socket: $!" if $sock;
  801. $sock ? 1 : undef;
  802. } : eval {
  803. require IO::Socket::INET;
  804. my $sock = IO::Socket::INET->new(LocalAddr => '0.0.0.0', Proto => 'udp');
  805. $sock->close or die "error closing inet socket: $!" if $sock;
  806. $sock ? 1 : undef;
  807. };
  808. $have_inet6 = # can we make a PF_INET6 socket?
  809. $have_socket_ip ? eval {
  810. my $sock = IO::Socket::IP->new(LocalAddr => '::', Proto => 'udp');
  811. $sock->close or die "error closing inet6 socket: $!" if $sock;
  812. $sock ? 1 : undef;
  813. } : eval {
  814. require IO::Socket::INET6;
  815. my $sock = IO::Socket::INET6->new(LocalAddr => '::', Proto => 'udp');
  816. $sock->close or die "error closing inet6 socket: $!" if $sock;
  817. $sock ? 1 : undef;
  818. };
  819. # bind socket to a loopback interface
  820. if (Net::Server->VERSION < 2) {
  821. $inet_socket_bind = '127.0.0.1';
  822. } else { # requires Net::Server 2 or a patched 0.99 with IPv6 support)
  823. $inet_socket_bind = $have_inet4 && $have_inet6 ? ['127.0.0.1', '[::1]']
  824. : $have_inet6 ? '[::1]' : '127.0.0.1';
  825. }
  826. @inet_acl = qw( 127.0.0.1 [::1] ); # allow SMTP access only from localhost
  827. @mynetworks = qw( 127.0.0.0/8 [::1] [FE80::]/10 [FEC0::]/10
  828. 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 169.254.0.0/16 );
  829. $originating = 0; # a boolean, initially reflects @mynetworks,
  830. # but may be modified later through a policy bank
  831. $forward_method = $have_inet6 && !$have_inet4 ? 'smtp:[::1]:10025'
  832. : 'smtp:[127.0.0.1]:10025';
  833. $notify_method = $forward_method;
  834. $resend_method = undef; # overrides $forward_method on defanging if nonempty
  835. $release_method = undef; # overrides $notify_method on releasing
  836. # from quarantine if nonempty
  837. $requeue_method = # requeuing release from a quarantine
  838. $have_inet6 && !$have_inet4 ? 'smtp:[::1]:25' : 'smtp:[127.0.0.1]:25';
  839. $release_format = 'resend'; # (dsn), (arf), attach, plain, resend
  840. $report_format = 'arf'; # (dsn), arf, attach, plain, resend
  841. # when $release_format is 'attach', the following control the attachment:
  842. $attachment_password = ''; # '': no pwd; undef: PIN; code ref; or static str
  843. $attachment_email_name = 'msg-%m.eml';
  844. $attachment_outer_name = 'msg-%m.zip';
  845. $virus_quarantine_method = 'local:virus-%m';
  846. $banned_files_quarantine_method = 'local:banned-%m';
  847. $spam_quarantine_method = 'local:spam-%m.gz';
  848. $bad_header_quarantine_method = 'local:badh-%m';
  849. $unchecked_quarantine_method = undef; # 'local:unchecked-%m';
  850. $clean_quarantine_method = undef; # 'local:clean-%m';
  851. $archive_quarantine_method = undef; # 'local:archive-%m.gz';
  852. $prepend_header_fields_hdridx = 0; # normally 0, use 1 for co-existence
  853. # with signing DK and DKIM milters
  854. $remove_existing_x_scanned_headers = 0;
  855. $remove_existing_spam_headers = 1;
  856. # fix improper header fields in passed or released mail - this setting
  857. # is a pre-condition for $allow_fixing_improper_header_folding and similar
  858. # (future) fixups; (desirable, but may break DKIM validation of messages
  859. # with illegal header section)
  860. $allow_fixing_improper_header = 1;
  861. # fix improper folded header fields made up entirely of whitespace, by
  862. # removing all-whitespace lines ($allow_fixing_improper_header must be true)
  863. $allow_fixing_improper_header_folding = 1;
  864. # truncate header section lines longer than 998 characters as limited
  865. # by the RFC 5322 ($allow_fixing_improper_header must be true)
  866. $allow_fixing_long_header_lines = 1;
  867. # encoding (charset in MIME terminology)
  868. # to be used in RFC 2047-encoded ...
  869. # $hdr_encoding = 'iso-8859-1'; # ... header field bodies
  870. # $bdy_encoding = 'iso-8859-1'; # ... notification body text
  871. $hdr_encoding = 'UTF-8'; # ... header field bodies
  872. $bdy_encoding = 'UTF-8'; # ... notification body text
  873. # encoding (encoding in MIME terminology)
  874. $hdr_encoding_qb = 'Q'; # quoted-printable (default)
  875. #$hdr_encoding_qb = 'B'; # base64 (usual for far east charsets)
  876. $smtpd_recipient_limit = 1100; # max recipients (RCPT TO) - sanity limit
  877. # $myhostname is used by SMTP server module in the initial SMTP welcome line,
  878. # in inserted Received: lines, Message-ID in notifications, log entries, ...
  879. $myhostname = (POSIX::uname)[1]; # should be a FQDN !
  880. $snmp_contact = ''; # a value of sysContact OID
  881. $snmp_location = ''; # a value of sysLocation OID
  882. $smtpd_greeting_banner = '${helo-name} ${protocol} ${product} service ready';
  883. $smtpd_quit_banner = '${helo-name} ${product} closing transmission channel';
  884. $enforce_smtpd_message_size_limit_64kb_min = 1;
  885. # $localhost_name is the name of THIS host running amavisd
  886. # (typically 'localhost'). It is used in HELO SMTP command
  887. # when reinjecting mail back to MTA via SMTP for final delivery,
  888. # and in inserted Received header field
  889. $localhost_name = 'localhost';
  890. $propagate_dsn_if_possible = 1; # pass on DSN if MTA announces this
  891. # capability; useful to be turned off globally but enabled in
  892. # MYNETS policy bank to hide internal mail routing from outsiders
  893. $terminate_dsn_on_notify_success = 0; # when true=>handle DSN NOTIFY=SUCCESS
  894. # locally, do not let NOTIFY=SUCCESS propagate to MTA (but allow
  895. # other DSN options like NOTIFY=NEVER/FAILURE/DELAY, ORCPT, RET,
  896. # and ENVID to propagate if possible)
  897. #@auth_mech_avail = ('PLAIN','LOGIN'); # empty list disables incoming AUTH
  898. #$auth_required_inp = 1; # incoming SMTP authentication required by amavisd?
  899. #$auth_required_out = 1; # SMTP authentication required by MTA
  900. $auth_required_release = 1; # secret_id is required for a quarantine release
  901. $tls_security_level_in = undef; # undef, 'may', 'encrypt', ...
  902. $tls_security_level_out = undef; # undef, 'may', 'encrypt', ...
  903. $smtpd_tls_cert_file = undef; # e.g. "$MYHOME/cert/amavisd-cert.pem"
  904. $smtpd_tls_key_file = undef; # e.g. "$MYHOME/cert/amavisd-key.pem"
  905. # SMTP AUTH username and password for notification submissions
  906. # (and reauthentication of forwarded mail if requested)
  907. #$amavis_auth_user = undef; # perhaps: 'amavisd'
  908. #$amavis_auth_pass = undef;
  909. #$auth_reauthenticate_forwarded = undef; # supply our own credentials also
  910. # for forwarded (passed) mail
  911. $smtp_connection_cache_on_demand = 1;
  912. $smtp_connection_cache_enable = 1;
  913. # whom quarantined messages appear to be sent from (envelope sender)
  914. # $mailfrom_to_quarantine = undef; # orig. sender if undef, or set explicitly
  915. # where to send quarantined malware - specify undef to disable, or an
  916. # e-mail address containing '@', or just a local part, which will be
  917. # mapped by %local_delivery_aliases into local mailbox name or directory.
  918. # The lookup key is a recipient address
  919. $virus_quarantine_to = 'virus-quarantine';
  920. $banned_quarantine_to = 'banned-quarantine';
  921. $unchecked_quarantine_to = 'unchecked-quarantine';
  922. $spam_quarantine_to = 'spam-quarantine';
  923. $bad_header_quarantine_to = 'bad-header-quarantine';
  924. $clean_quarantine_to = 'clean-quarantine';
  925. $archive_quarantine_to = 'archive-quarantine';
  926. # similar to $spam_quarantine_to, but the lookup key is the sender address:
  927. $spam_quarantine_bysender_to = undef; # dflt: no by-sender spam quarantine
  928. # quarantine directory or mailbox file or empty
  929. # (only used if $*_quarantine_to specifies direct local delivery)
  930. $QUARANTINEDIR = undef; # no quarantine unless overridden by config
  931. $undecipherable_subject_tag = '***UNCHECKED*** ';
  932. # NOTE: all entries can accept mail_body_size_limit and score_factor options
  933. @spam_scanners = (
  934. ['SpamAssassin', 'Amavis::SpamControl::SpamAssassin' ],
  935. # ['SpamdClient', 'Amavis::SpamControl::SpamdClient',
  936. # mail_body_size_limit => 65000, score_factor => 1.0,
  937. # ],
  938. # ['DSPAM', 'Amavis::SpamControl::ExtProg', $dspam,
  939. # [ qw(--stdout --classify --deliver=innocent,spam
  940. # --mode=toe --feature noise
  941. # --user), $daemon_user ],
  942. # mail_body_size_limit => 65000, score_factor => 1.0,
  943. # ],
  944. # ['CRM114', 'Amavis::SpamControl::ExtProg', 'crm',
  945. # [ qw(-u /var/amavis/home/.crm114 mailreaver.crm
  946. # --dontstore --report_only --stats_only
  947. # --good_threshold=10 --spam_threshold=-10) ],
  948. # mail_body_size_limit => 65000, score_factor => -0.20,
  949. # lock_file => '/var/amavis/crm114.lock',
  950. # lock_type => 'shared', learner_lock_type => 'exclusive',
  951. # ],
  952. # ['Bogofilter', 'Amavis::SpamControl::ExtProg', 'bogofilter',
  953. # [ qw(-e -v)], # -u
  954. # mail_body_size_limit => 65000, score_factor => 1.0,
  955. # ],
  956. );
  957. $sa_spawned = 0; # true: run SA in a subprocess; false: call SA directly
  958. # string to prepend to Subject header field when message qualifies as spam
  959. # $sa_spam_subject_tag1 = undef; # example: '***Possible Spam*** '
  960. # $sa_spam_subject_tag = undef; # example: '***Spam*** '
  961. $sa_spam_level_char = '*'; # character to be used in X-Spam-Level bar;
  962. # empty or undef disables adding this header field
  963. $sa_num_instances = 1; # number of SA instances,
  964. # usually 1, memory-expensive, keep small
  965. $sa_local_tests_only = 0;
  966. $sa_debug = undef;
  967. $sa_timeout = 30; # no longer used since 2.6.5
  968. $file = 'file'; # path to the file(1) utility for classifying contents
  969. $altermime = 'altermime'; # path to the altermime utility (optional)
  970. @altermime_args_defang = qw(--verbose --removeall);
  971. @altermime_args_disclaimer = qw(--disclaimer=/etc/altermime-disclaimer.txt);
  972. # @altermime_args_disclaimer =
  973. # qw(--disclaimer=/etc/_OPTION_.txt --disclaimer-html=/etc/_OPTION_.html);
  974. # @disclaimer_options_bysender_maps = ( 'altermime-disclaimer' );
  975. $MIN_EXPANSION_FACTOR = 5; # times original mail size
  976. $MAX_EXPANSION_FACTOR = 500; # times original mail size
  977. # See amavisd.conf and README.lookups for details.
  978. # What to do with the message (this is independent of quarantining):
  979. # Reject: tell MTA to generate a non-delivery notification, MTA gets 5xx
  980. # Bounce: generate a non-delivery notification by ourselves, MTA gets 250
  981. # Discard: drop the message and pretend it was delivered, MTA gets 250
  982. # Pass: accept/forward a message, MTA gets 250
  983. # TempFail: temporary failure, client should retry, MTA gets 4xx
  984. #
  985. # COMPATIBILITY NOTE: the separation of *_destiny values into
  986. # D_BOUNCE, D_REJECT, D_DISCARD and D_PASS made settings $warn*sender only
  987. # still useful with D_PASS. The combination of D_DISCARD + $warn*sender=1
  988. # is mapped into D_BOUNCE for compatibility.
  989. # The following symbolic constants can be used in *destiny settings:
  990. #
  991. # D_PASS mail will pass to recipients, regardless of contents;
  992. #
  993. # D_DISCARD mail will not be delivered to its recipients, sender will NOT be
  994. # notified. Effectively we lose mail (but it will be quarantined
  995. # unless disabled).
  996. #
  997. # D_BOUNCE mail will not be delivered to its recipients, a non-delivery
  998. # notification (bounce) will be sent to the sender by amavisd-new
  999. # (unless suppressed). Bounce (DSN) will not be sent if a virus
  1000. # name matches $viruses_that_fake_sender_maps, or to messages
  1001. # from mailing lists (Precedence: bulk|list|junk), or for spam
  1002. # exceeding spam_dsn_cutoff_level
  1003. #
  1004. # D_REJECT mail will not be delivered to its recipients, amavisd will
  1005. # return a 5xx status response. Depending on an MTA/amavisd setup
  1006. # this will result either in a reject status passed back to a
  1007. # connecting SMTP client (in a pre-queue setup: proxy or milter),
  1008. # or an MTA will generate a bounce in a post-queue setup.
  1009. # If not all recipients agree on rejecting a message (like when
  1010. # different recipients have different thresholds on bad mail
  1011. # contents and LMTP is not used) amavisd sends a bounce by itself
  1012. # (same as D_BOUNCE).
  1013. #
  1014. # D_TEMPFAIL indicates a temporary failure, mail will not be delivered to
  1015. # its recipients, sender should retry the operation later.
  1016. #
  1017. # Notes:
  1018. # D_REJECT and D_BOUNCE are similar,the difference is in who is responsible
  1019. # for informing the sender about non-delivery, and how informative
  1020. # the notification can be (amavisd-new knows more than MTA);
  1021. # With D_REJECT, MTA may reject original SMTP, or send DSN (delivery status
  1022. # notification, colloquially called 'bounce') - depending on MTA
  1023. # and its interface to a content checker; best suited for sendmail
  1024. # milter or other pre-queue filtering

Large files files are truncated, but you can click here to view the full file