summaryrefslogtreecommitdiff
path: root/files/arts/software/Code/elektropost/mkvalidrcptto
diff options
context:
space:
mode:
Diffstat (limited to 'files/arts/software/Code/elektropost/mkvalidrcptto')
-rwxr-xr-xfiles/arts/software/Code/elektropost/mkvalidrcptto826
1 files changed, 826 insertions, 0 deletions
diff --git a/files/arts/software/Code/elektropost/mkvalidrcptto b/files/arts/software/Code/elektropost/mkvalidrcptto
new file mode 100755
index 0000000..5b03fbb
--- /dev/null
+++ b/files/arts/software/Code/elektropost/mkvalidrcptto
@@ -0,0 +1,826 @@
1#!/usr/bin/perl -w
2#
3# mkvalidrcptto
4# John Simpson <jms1@jms1.net> 2005-04-20
5#
6# reads qmail control files and builds a list of all valid email addresses
7# on the system.
8#
9# 2005-05-04 jms1 - cleaned up the code a little bit. holding the output in
10# memory until the whole thing is done so that partial output doesn't
11# become an issue. it also makes it possible to create a cdb file directly,
12# but i don't think i'm going to do that- i like the "chaining" approach
13# better, piping this script's output through "cdbmake-12" to produce the
14# cdb file.
15#
16# 2005-05-09 jms1 - changing the vpopmail user info process. instead of
17# reading vpasswd.cdb, using "vuserinfo -D {domain}" and parsing that
18# output. this should include mysql user information for people who are
19# using vpopmail with mysql. Thanks to Roman Volf on the qmailrocks
20# mailing list for pointing this out.
21#
22# 2005-06-09 jms1 - adding support for "fastforward" aliases.
23#
24# 2005-06-18 jms1 - finishing support for .qmail-* files in local user home
25# directories... i don't ever use local users for mailboxes myself, so it
26# wasn't an issue for me, but somebody out there may be doing it, so...
27#
28# 2005-06-23 jms1 - changed the search pattern when reading "vuserinfo -D"
29# to get a vpopmail domain's mailbox list, instead of recognizing \w+
30# it now uses \S+ which should allow "." in mailbox names
31#
32# 2005-06-29 jms1 - translating ":" to "." in .qmail-* filenames... i forgot
33# that qmail-local does this. somebody emailed me to remind me about this,
34# but i can't find the email so i don't know who to thank for reminding me
35# about this...
36#
37# 2005-06-30 jms1 - when vpopmail stores everything in a mysql database,
38# aliases are apparently not represented by .qmail files at all. it looks
39# like we have no choice but to use the vpopmail command-line tools to
40# get the lists of mailboxes and aliases in the domain. thanks to Rob Pitt
41# for telling me that this wasn't working (i don't use vpopmail with mysql
42# so i had no way to know that this would be a problem.)
43#
44# 2005-07-17 jms1 - domains listed in smtproutes are currently listed as
45# just "@domain", meaning the entire domain is accepted without any checks
46# done for individual userid's. adding code so that you can create a
47# directory full of files named for the domains, containing userid's
48# which exist in that domain. thanks to roman volf for the suggestion.
49#
50# 2005-08-03 jms1 - turns out if vpopmail is compiled with support for mysql,
51# the "valias -s" command doesn't list aliases which exist by virtue of
52# .qmail-blah files... which rather sucks, because this is how ezmlm sets
53# up the aliases it needs, by creating .qmail-blah files. thanks again to
54# Roman Volf for pointing this out.
55#
56# 2005-10-24 jms1 - adding a "-n" switch to generate a list without the
57# system accounts (i.e. no "locals" or "me" domains will be printed.)
58# note that "fastforward" aliases are considered local, since they are
59# processed through the local delivery mechanism.
60#
61# 2005-11-29 jms1 - now treats missing vpopmail directory as a warning
62# rather than a fatal error.
63#
64# 2005-12-07 jms1 - after reviewing qmail-send.c and controls.c, it
65# turns out that the "me" becoming part of "locals" only happens if
66# the "control/locals" file does not exist... otherwise an empty
67# "control/locals" file means that there are no locals. updating the
68# script to duplicate this logic.
69# also replacing ":" with "." in .qmail filenames.
70# thanks to jeff hedlund for pointing me towards the "me" problem,
71# and for pointing out my oversight with the ":" thing.
72#
73# 2005-12-29 jms1 - adding an array of numeric uid's (empty by default)
74# which will be ignored when system uid's are scanned. thanks to
75# roman volf for the suggestion.
76#
77# 2006-01-08 jms1 - fixed a typo, thanks to "marlowe" for pointing it out.
78#
79# 2006-01-11 jms1 - vpopmail has a "--enable-qmail-ext" option which
80# changes how mailbox names are handled. if vpopmail is running WITH
81# this option, every vpopmail mailbox has an implied "-default" alias
82# whether there's a .qmail-user-default file there or not. thanks to
83# robin bowes for pointing this out.
84#
85# 2006-01-12 jms1 - making the script work correctly in the unlikely
86# case that the user-ext separator character was changed, either by
87# changing conf-break before compiling qmail, or specifying a custom
88# value in the users/cdb file.
89#
90# 2006-02-05 jms1 - adding an "exclude" list, for addresses which you
91# may not want to include in the output (i.e. private mailing list
92# aliases and things like that.) also fixed a bug in the code which
93# handles the user-ext separator character.
94#
95# 2006-03-26 jms1 - fixed a minor typo in the text of an error message
96# (which does not affect how the script works.) Thanks to Robin Bowes
97# for pointing it out.
98#
99# 2006-11-29 jms1 - adding logic to work around the case where users/cdb
100# just plain doesn't exist (which can happen on systems which don't use
101# vpopmail etc.) thanks to "Eric d'Alibut" on djb's qmail mailing list
102# for pointing it out.
103#
104###############################################################################
105#
106# Copyright (C) 2005-2006 John Simpson.
107#
108# This program is free software; you can redistribute it and/or modify
109# it under the terms of the GNU General Public License, version 2, as
110# published by the Free Software Foundation.
111#
112# This program is distributed in the hope that it will be useful,
113# but WITHOUT ANY WARRANTY; without even the implied warranty of
114# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
115# GNU General Public License for more details.
116#
117# You should have received a copy of the GNU General Public License
118# along with this program; if not, write to the Free Software
119# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
120# or visit http://www.gnu.org/licenses/gpl.txt
121#
122###############################################################################
123
124require 5.003 ;
125use strict ;
126
127use CDB_File ;
128
129###############################################################################
130#
131# configuration
132
133my $vq = "/var/qmail" ;
134my $vuser = "vpopmail" ; # vpopmail userid
135
136# any numeric uid's on the system which are lower than this will be ignored
137# this way we don't create entries for root, bin, daemon, lp, news, uucp,
138# and other non-used system users.
139my $uid_min = 500 ; # ignore uid's lower than this
140my $uid_max = 65000 ; # ignore uid's higher than this
141my @uid_ignore = qw ( ) ; # ignore any uid's listed in this array
142
143# any entries listed in this array will NOT be included in the output
144my @exclude = qw
145(
146 sample1@domain.xyz
147 sample2@domain.xyz
148) ;
149
150# if you have text files containing lists of valid mailboxes for smtproutes
151# domains, put them all into a single directory and put that directory in
152# the variable below.
153#
154# each line of each files should contain a mailbox userid- anything on the
155# line which comes after "#" or "@" is deleted, so you can use "#" for
156# comments if you like, and you can use a symlink (or hard link) to cause
157# one file to be effective for multiple domains.
158#
159# note that these files are only consulted for domains listed in the
160# smtproutes file. if this variable is blank, or it points to a directory
161# which doesn't exist, all smtproutes domains will be printed as "@domain",
162# which tells qmail-smtpd to accept any mailbox userid in that domain.
163
164my $smtpr_dir = "" ;
165
166###############################################################################
167#
168# global variables
169
170my ( %alldom , %ldom , %vdom , %sdom , %adom , %lusr , %ausr ,
171 %home , %MRH , %UCDB , @output , $ffl , %ACDB ) ;
172
173my $err = 0 ;
174my $lfound = 0 ;
175my $afound = 0 ;
176my $vfound = 0 ;
177my $showlocal = 1 ;
178my $need_untie = 0 ;
179
180my $vhome = "" ;
181my $vbin = "" ;
182my $vinc = "" ;
183my $vqext = "?" ;
184my $dash = "" ;
185my $gdash = "" ;
186
187###############################################################################
188#
189# debugging function
190
191my $show_debug = 0 ;
192
193sub debug($)
194{
195 $show_debug && print $_[0] ;
196}
197
198###############################################################################
199#
200# function to read /var/qmail/alias/.qmail-default
201
202sub find_ffl($)
203{
204 my $file = shift ;
205
206 my $flagdeliver = 1 ;
207 my $flagpassthrough = 0 ;
208 my $flagdefault = 0 ;
209
210 if ( open ( DQD , "<$file" ) )
211 {
212 while ( my $line = <DQD> )
213 {
214 chomp $line ;
215 next unless ( $line =~ /^\|.*fastforward/ ) ;
216
217 $line =~ s/^.*fastforward\s+// ;
218 my @dw = split ( /\s+/ , $line ) ;
219 while ( my $zz = shift @dw )
220 {
221 next if ( $zz =~ /^\-/ ) ;
222 $ffl = $zz ;
223 last ;
224 }
225
226 last if ( $ffl ) ;
227 }
228 close DQD ;
229 }
230}
231
232###############################################################################
233###############################################################################
234###############################################################################
235
236my $arg = ( shift || "" ) ;
237if ( "-n" eq $arg )
238{
239 $showlocal = 0 ;
240}
241
242###############################################################################
243#
244# only interested in domains for which we legitimately receive mail
245
246open ( I , "<$vq/control/rcpthosts" )
247 or die "$vq/control/rcpthosts: $!\n" ;
248while ( my $line = <I> )
249{
250 chomp $line ;
251 $alldom{$line} = 1 ;
252}
253close I ;
254
255open ( I , "<$vq/control/morercpthosts" )
256 or die "$vq/control/morercpthosts: $!\n" ;
257while ( my $line = <I> )
258{
259 chomp $line ;
260 $alldom{$line} = 1 ;
261}
262close I ;
263
264if ( -f "$vq/control/morercpthosts.cdb" )
265{
266 tie ( %MRH , "CDB_File" , "$vq/control/morercpthosts.cdb" )
267 or die "$vq/control/morercpthosts: $!\n" ;
268 map { $alldom{$_} = 1 } keys %MRH ;
269 untie %MRH ;
270}
271
272###############################################################################
273#
274# classify each one as local, virtual, or pass-thru
275#
276# note that if the control/locals file does not exist, the name listed
277# in the control/me file is used as if control/locals contained the
278# data.
279
280if ( -f "$vq/control/locals" )
281{
282 open ( I , "<$vq/control/locals" )
283 or die "$vq/control/locals: $!\n" ;
284 while ( my $line = <I> )
285 {
286 chomp $line ;
287
288 ########################################
289 # ignore any that we don't actually receive mail for
290
291 next unless ( exists $alldom{$line} ) ;
292 delete $alldom{$line} ;
293
294 ########################################
295 # mark this one as local
296
297 $ldom{$line} = 1 ;
298 $lfound ++ ;
299 $afound ++ ;
300 }
301 close I ;
302}
303elsif ( -f "$vq/control/me" )
304{
305 open ( I , "<$vq/control/me" )
306 or die "$vq/control/me: $!\n" ;
307 while ( my $line = <I> )
308 {
309 chomp $line ;
310
311 ########################################
312 # ignore any that we don't actually receive mail for
313
314 next unless ( exists $alldom{$line} ) ;
315 delete $alldom{$line} ;
316
317 ########################################
318 # mark this one as local
319
320 $ldom{$line} = 1 ;
321 $lfound ++ ;
322 $afound ++ ;
323 }
324 close I ;
325}
326
327if ( -f "$vq/control/virtualdomains" )
328{
329 open ( I , "<$vq/control/virtualdomains" )
330 or die "$vq/control/virtualdomains: $!\n" ;
331 while ( my $line = <I> )
332 {
333 chomp $line ;
334
335 ########################################
336 # extract the domain name
337
338 my ( $dom , $zu ) = split ( /\s*\:\s*/ , $line ) ;
339 $dom || die "error in $vq/control/virtualdomains\n$line\n" ;
340
341 ########################################
342 # ignore any that we don't actually receive mail for
343
344 next unless ( exists $alldom{$dom} ) ;
345 delete $alldom{$dom} ;
346
347 ########################################
348 # check the userid
349
350 if ( $zu eq "alias" )
351 {
352 ########################################
353 # if the domain is handled by the qmail "alias"
354 # user, then it needs alias processing
355
356 $adom{$dom} = 1 ;
357 $afound ++ ;
358 }
359 else
360 {
361 ########################################
362 # mark this one as a virtual domain
363 # and remember the full line, we will need it later
364
365 $vdom{$dom} = $line ;
366 $vfound ++ ;
367 }
368 }
369 close I ;
370}
371
372if ( -f "$vq/control/smtproutes" )
373{
374 open ( I , "<$vq/control/smtproutes" )
375 or die "$vq/control/smtproutes: $!\n" ;
376 while ( my $line = <I> )
377 {
378 chomp $line ;
379
380 ########################################
381 # extract the domain name
382
383 $line =~ s/\:.*// ;
384
385 ########################################
386 # ignore lines with no domain (default instruction)
387
388 next unless $line ;
389
390 ########################################
391 # ignore any that we don't actually receive mail for
392
393 next unless ( exists $alldom{$line} ) ;
394 delete $alldom{$line} ;
395
396 ########################################
397 # mark this one as an smtproutes domain
398
399 $sdom{$line} = 1 ;
400 }
401 close I ;
402}
403
404###############################################################################
405#
406# catch leftovers - domains which come into the machine but are not handled
407
408for my $d ( sort keys %alldom )
409{
410 print "ERROR: $d is listed in rcpthosts/morercpthosts.cdb"
411 . " but is not handled by the server.\n" ;
412 $err ++ ;
413}
414
415$err && die "Cannot continue.\n" ;
416
417###############################################################################
418#
419# start generating output.
420#
421# smtproutes domains - if a directory was specified, and it exists, and a
422# file for the domain exists, read userid's from the file and generate
423# "userid@domain" lines... otherwise just generate a single "@domain" line.
424
425for my $d ( sort keys %sdom )
426{
427 if ( $smtpr_dir && ( -d $smtpr_dir ) && ( -f "$smtpr_dir/$d" ) )
428 {
429 open ( I , "<$smtpr_dir/$d" )
430 or die "Can\'t read $smtpr_dir/$d: $!\n" ;
431 while ( my $line = <I> )
432 {
433 chomp $line ;
434 $line =~ s/#.*// ;
435 $line =~ s/\@.*// ;
436 $line =~ s/^\s+// ;
437 $line =~ s/\s+$// ;
438 next unless ( $line ) ;
439 push ( @output , "$line\@$d" ) ;
440 }
441 close I ;
442 }
443 else
444 {
445 push ( @output, "\@$d" ) ;
446 }
447}
448
449###############################################################################
450#
451# local domains - all system accounts and aliases, in each local domain
452
453if ( $lfound || $afound )
454{
455 ########################################
456 # need the global "dash" character
457
458 unless ( $gdash )
459 {
460 open ( GD , "$vq/bin/qmail-showctl |" )
461 or die "Can\'t run qmail-showctl: $!\n" ;
462 while ( my $gdline = <GD> )
463 {
464 if ( $gdline =~ /user\-ext delimiter\: (.)/ )
465 {
466 $gdash = $1 ;
467 last ;
468 }
469 }
470 close GD ;
471 }
472}
473
474if ( $lfound )
475{
476 ########################################
477 # turn array into hash for speed
478
479 my %ig = () ;
480 map { $ig{$_} = "" } @uid_ignore ;
481
482 ########################################
483 # grab a list of system accounts
484
485 while ( my @pw = getpwent() )
486 {
487 next if ( $pw[2] < $uid_min ) ; # ignore system accounts
488 next if ( $pw[2] > $uid_max ) ; # ignore "nobody" accounts
489 next if ( exists $ig{$pw[2]} ) ; # ignore special accounts
490 next unless ( $pw[2] ) ; # no deliveries to root
491 $lusr{$pw[0]} = 1 ;
492
493 if ( opendir ( D , $pw[7] ) )
494 {
495 while ( my $f = readdir D )
496 {
497 next unless ( $f =~ /^\.qmail${gdash}(.+)/ ) ;
498 my $zu = $1 ;
499 $zu =~ s/\:/./g ;
500 $lusr{"$pw[0]${gdash}$zu"} = 1 ;
501 }
502 closedir D ;
503 }
504 }
505}
506
507if ( $showlocal && ( $lfound || $afound ) )
508{
509 ########################################
510 # grab a list of aliases
511
512 opendir ( D , "$vq/alias" )
513 or die "$vq/alias: $!\n" ;
514 while ( my $f = readdir ( D ) )
515 {
516 next unless ( $f =~ /^\.qmail${gdash}(.*)/ ) ;
517 my $u = $1 ;
518
519 if ( $u eq "default" )
520 {
521 find_ffl ( "$vq/alias/.qmail${gdash}default" ) ;
522 }
523 else
524 {
525 $u =~ s/\:/./g ;
526 $ausr{$u} = 1 ;
527 }
528 }
529 closedir D ;
530
531 ########################################
532 # if we found a fastforward file, grab those aliases as well
533
534 if ( $ffl )
535 {
536 tie ( %ACDB , "CDB_File" , $ffl )
537 or die "$ffl: $!\n" ;
538
539 for my $k ( keys %ACDB )
540 {
541 next unless ( $k =~ /^\:(.*)\@(.*)$/ ) ;
542 my ( $au , $ad ) = ( $1 , $2 ) ;
543
544 if ( $ad )
545 {
546 next unless ( exists ( $adom{$ad} )
547 || exists ( $ldom{$ad} ) ) ;
548 push ( @output , "$au\@$ad" ) ;
549 }
550 else
551 {
552 $ausr{$au} = 1 ;
553 }
554 }
555
556 untie %ACDB ;
557 }
558
559 ########################################
560 # generate output.
561 # local domains get every system user AND every alias user
562
563 for my $dd ( sort keys %ldom )
564 {
565 map { push ( @output , "$_\@$dd" ) } sort keys %lusr ;
566 map { push ( @output , "$_\@$dd" ) } sort keys %ausr ;
567 }
568
569 ########################################
570 # alias domains get every alias user
571
572 for my $dd ( sort keys %adom )
573 {
574 map { push ( @output , "$_\@$dd" ) } sort keys %ausr ;
575 }
576}
577
578###############################################################################
579#
580# virtual domains - a little more complicated.
581
582if ( $vfound )
583{
584 #######################################################################
585 #
586 # the virtualdomains file contains a mapping from the domain name to a
587 # userid, which may be a system account and may be a virtual userid
588 # defined in the $vq/users/assign file.
589 #
590 # vpopmail normally uses the domain name as the virtual userid for
591 # this purpose, but we want to be flexible enough to handle other
592 # cases as well.
593 #
594 # in order to deal with this extra layer of indirection, we need to
595 # read the users/cdb file. and because it's a cdb, we don't even need
596 # to read the whole thing- we just need to open it so that we can
597 # search it.
598
599 if ( -f "$vq/users/cdb" )
600 {
601 tie ( %UCDB , "CDB_File" , "$vq/users/cdb" )
602 or die "$vq/users/cdb: $!\n" ;
603 $need_untie = 1 ;
604 }
605 else
606 {
607 %UCDB = () ;
608 }
609
610 my $wc = ( $UCDB{""} || "" ) ;
611
612 #######################################################################
613 #
614 # now we have the list of users/assign virtual users (if any), we need
615 # to identify the home directory, real or virutal, for the user.
616
617 for my $dom ( sort keys %vdom )
618 {
619 $vdom{$dom} =~ /\:(.*)$/ ;
620 my $usr = $1 ;
621
622 my %vusr = () ;
623 my $dir = "" ;
624 my $vpopmail = 0 ;
625
626 ########################################
627 # note that in cases where a given "userid" exists as both a
628 # system userid and a virtual userid, the virtual userid takes
629 # precedence (according to the qmail-lspawn man page.)
630 # this is why we saved the home directories above.
631
632 if ( exists $UCDB{"!$usr$wc"} )
633 {
634 my @w = split ( /\0/ , $UCDB{"!$usr$wc"} ) ;
635 $dir = ( $w[3] || die "mis-formed users/cdb data:"
636 . " $usr\n" ) ;
637 $dash = ( $w[4] || "" ) ;
638 }
639 else
640 {
641 if ( my @pw = getpwnam ( $usr ) )
642 {
643 $dir = $pw[7] ;
644 }
645 }
646
647 die "ERROR: virtual user \"$usr\" not found"
648 . " (for virtualdomain \"$dom\")\n"
649 unless ( $dir ) ;
650
651 ########################################
652 # now we know which directory to look in. check for a
653 # ".qmail-default" file. if it contains "vdelievermail", we
654 # know that vpopmail is in control here... and if the
655 # vdelivermail line also has "bounce-no-mailbox", we need
656 # the list of individual users. otherwise we can just
657 # blindly accept the entire domain.
658
659 unless ( -r $dir )
660 {
661 print STDERR "Can\'t read directory $dir"
662 . " (for vpopmail domain \"$dom\")\n" ;
663 next ;
664 }
665
666 if ( -f "$dir/.qmail${dash}default" )
667 {
668 open ( V , "<$dir/.qmail${dash}default" )
669 or die "$dir/.qmail${dash}default: $!\n" ;
670
671 while ( my $line = <V> )
672 {
673 if ( $line =~ /vdelivermail.*(bounce\-no\-mailbox|delete)/ )
674 {
675 $vpopmail = 1 ;
676 }
677 }
678 close V ;
679 }
680
681 ########################################
682 # if we need the users...
683
684 if ( $vpopmail )
685 {
686 ########################################
687 # if we don't already know where it is,
688 # find the vpopmail user's "/bin" directory.
689
690 unless ( $vhome )
691 {
692 my @pw = getpwnam ( $vuser )
693 or die "getpwnam($vuser): $!\n" ;
694 $vhome = $pw[7] ;
695 $vbin = "$vhome/bin" ;
696 $vinc = "$vhome/include" ;
697
698 die "Can\'t find $vbin/vuserinfo: $!\n"
699 unless ( -e "$vbin/vuserinfo" ) ;
700 }
701
702 ########################################
703 # if we don't already know, find out if
704 # vpopmail was built with --enable-qmail-ext
705
706 if ( $vqext eq "?" )
707 {
708 $vqext = "no" ;
709 open ( VCH , "<$vinc/vpopmail_config.h" )
710 or die ( "Can\'t read "
711 . "$vinc/vpopmail_config.h: $!\n" ) ;
712
713 while ( my $vcl = <VCH> )
714 {
715 next unless ( $vcl =~ /^#define QMAIL_EXT 1/ ) ;
716 $vqext = "yes" ;
717 last ;
718 }
719 close VCH ;
720 debug "vqext=$vqext\n" ;
721 }
722
723 ########################################
724 # run "vuserinfo -D {domain}" to get a list of
725 # actual mailboxes within the domain.
726
727 debug "/----- $vbin/vuserinfo -D $dom\n" ;
728 open ( VP , "$vbin/vuserinfo -D $dom |" )
729 or die "Can\'t execute $vbin/vuserinfo: $!\n" ;
730 while ( my $line = <VP> )
731 {
732 debug $line ;
733 next unless ( $line =~ /^name\:\s+(\S+)/ ) ;
734 my $u = $1 ;
735 $vusr{$u} = $u ;
736 debug "\t[$u]" ;
737 if ( $vqext eq "yes" )
738 {
739 $vusr{"$u${dash}default"} =
740 "$u${dash}default" ;
741 debug " [$u${dash}default]" ;
742 }
743 debug "\n" ;
744 }
745 close VP ;
746 debug "\\-----\n" ;
747
748 ########################################
749 # run "valias -s {domain}" to get a list of
750 # aliases within the domain.
751
752 debug "/----- $vbin/valias -s $dom\n" ;
753 open ( VP , "$vbin/valias -s $dom |" )
754 or die "Can\'t execute $vbin/valias: $!\n" ;
755 while ( my $line = <VP> )
756 {
757 debug $line ;
758 next unless ( $line =~ /^(.+?)\@/ ) ;
759 my $u = $1 ;
760 $vusr{$u} = $u ;
761 debug "\t[$u]\n" ;
762 }
763 close VP ;
764 debug "\\-----\n" ;
765
766 ########################################
767 # read the directory itself. any .qmail-___ files are
768 # also valid aliases within the domain, even if
769 # "valias" doesn't seem to know about them.
770
771 opendir ( D , $dir )
772 or die "$dir: $!\n" ;
773 while ( my $f = readdir ( D ) )
774 {
775 if ( $f =~ /^\.qmail${dash}(.*)/ )
776 {
777 my $u = $1 ;
778 next if ( $u eq "default" ) ;
779 $u =~ s/\:/./g ;
780 $vusr{$u} = $u ;
781 }
782 }
783 closedir D ;
784
785 ########################################
786 # now %vusr contains a list of all valid email
787 # addresses within the domain.
788
789 map { push ( @output , "$_\@$dom" ) ;
790 debug "{$_\@$dom}\n" } sort keys %vusr ;
791 }
792 else
793 {
794 ########################################
795 # virtual domain, but either it's not handled by
796 # vpopmail, or there is something going on with
797 # itother than "bounce-no-mailbox", which means
798 # we don't need the full list of mailboxes.
799
800 push ( @output , "\@$dom" ) ;
801 }
802 }
803
804 if ( $need_untie )
805 {
806 untie %UCDB ;
807 $need_untie = 0 ;
808 }
809}
810
811###############################################################################
812#
813# if we make it this far, we have no errors and can print the list.
814# we need to filter out any "exclude" entries
815
816my %ex = () ;
817map { $ex{lc $_} = "" } @exclude ;
818
819for my $k ( @output )
820{
821 $k = lc $k ;
822 unless ( exists $ex{$k} )
823 {
824 print "$k\n" ;
825 }
826}