1 package FS::part_export::vpopmail;
3 use vars qw(@ISA %info @saltset $exportdir);
7 use FS::UID qw( datasrc );
10 @ISA = qw(FS::part_export);
12 tie my %options, 'Tie::IxHash',
13 #'machine' => { label=>'vpopmail machine', },
14 'dir' => { label=>'directory', }, # ?more info? default?
15 'uid' => { label=>'vpopmail uid' },
16 'gid' => { label=>'vpopmail gid' },
17 'restart' => { label=> 'vpopmail restart command',
18 default=> 'cd /home/vpopmail/domains; for domain in *; do /home/vpopmail/bin/vmkpasswd $domain; done; /var/qmail/bin/qmail-newu; killall -HUP qmail-send',
24 'desc' => 'Real-time export to vpopmail text files',
25 'options' => \%options,
26 'default_svc_class' => 'Email',
28 This export is currently unmaintained. See shellcommands_withdomain for an
29 export that uses vpopmail CLI commands instead.<BR>
31 Real time export to <a href="http://inter7.com/vpopmail/">vpopmail</a> text
32 files. <a href="http://search.cpan.org/dist/File-Rsync">File::Rsync</a>
33 must be installed, and you will need to
34 <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.9:Documentation:Administration:SSH_Keys">setup SSH for unattended operation</a>
35 to <b>vpopmail</b>@<i>export.host</i>.
39 @saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
41 sub rebless { shift; }
44 my($self, $svc_acct) = (shift, shift);
45 $self->vpopmail_queue( $svc_acct->svcnum, 'insert',
47 crypt($svc_acct->_password,$saltset[int(rand(64))].$saltset[int(rand(64))]),
55 my( $self, $new, $old ) = (shift, shift, shift);
57 my $cpassword = crypt(
58 $new->_password, $saltset[int(rand(64))].$saltset[int(rand(64))]
61 return "can't change username with vpopmail"
62 if $old->username ne $new->username;
64 #no.... if mail can't be preserved, better to disallow username changes
65 #if ($old->username ne $new->username || $old->domain ne $new->domain ) {
66 # vpopmail_queue( $svc_acct->svcnum, 'delete',
67 # $old->username, $old->domain
69 # vpopmail_queue( $svc_acct->svcnum, 'insert',
75 return '' unless $old->_password ne $new->_password;
77 $self->vpopmail_queue( $new->svcnum, 'replace',
78 $new->username, $cpassword, $new->domain, $new->quota, $new->finger );
82 my( $self, $svc_acct ) = (shift, shift);
83 $self->vpopmail_queue( $svc_acct->svcnum, 'delete',
84 $svc_acct->username, $svc_acct->domain );
87 #a good idea to queue anything that could fail or take any time
89 my( $self, $svcnum, $method ) = (shift, shift, shift);
91 my $exportdir = "%%%FREESIDE_EXPORT%%%/export." . datasrc;
92 mkdir $exportdir, 0700 or die $! unless -d $exportdir;
93 $exportdir .= "/vpopmail";
94 mkdir $exportdir, 0700 or die $! unless -d $exportdir;
95 $exportdir .= '/'. $self->machine;
96 mkdir $exportdir, 0700 or die $! unless -d $exportdir;
97 mkdir "$exportdir/domains", 0700 or die $! unless -d "$exportdir/domains";
99 my $queue = new FS::queue {
101 'job' => "FS::part_export::vpopmail::vpopmail_$method",
106 $self->option('dir'),
107 $self->option('uid'),
108 $self->option('gid'),
109 $self->option('restart'),
114 sub vpopmail_insert { #subroutine, not method
115 my( $exportdir, $machine, $dir, $uid, $gid, $restart ) = splice @_,0,6;
116 my( $username, $password, $domain, $quota, $finger ) = @_;
118 mkdir "$exportdir/domains/$domain", 0700 or die $!
119 unless -d "$exportdir/domains/$domain";
121 (open(VPASSWD, ">>$exportdir/domains/$domain/vpasswd")
122 and flock(VPASSWD,LOCK_EX)
123 ) or die "can't open vpasswd file for $username\@$domain: ".
124 "$exportdir/domains/$domain/vpasswd: $!";
125 print VPASSWD join(":",
131 "$dir/domains/$domain/$username",
132 $quota ? $quota.'S' : 'NOQUOTA',
135 flock(VPASSWD,LOCK_UN);
139 grep { ! -d $_ } map { "$exportdir/domains/$domain/$username$_" }
140 ( '', qw( /Maildir /Maildir/cur /Maildir/new /Maildir/tmp ) )
142 mkdir $mkdir, 0700 or die "can't mkdir $mkdir: $!";
145 vpopmail_sync( $exportdir, $machine, $dir, $uid, $gid, $restart );
149 sub vpopmail_replace { #subroutine, not method
150 my( $exportdir, $machine, $dir, $uid, $gid, $restart ) = splice @_,0,6;
151 my( $username, $password, $domain, $quota, $finger ) = @_;
153 (open(VPASSWD, "$exportdir/domains/$domain/vpasswd")
154 and flock(VPASSWD,LOCK_EX)
155 ) or die "can't open $exportdir/domains/$domain/vpasswd: $!";
157 open(VPASSWDTMP, ">$exportdir/domains/$domain/vpasswd.tmp")
158 or die "Can't open $exportdir/domains/$domain/vpasswd.tmp: $!";
161 my ($mailbox, $pw, $vuid, $vgid, $vfinger, $vdir, $vquota, @rest) =
163 if ( $username ne $mailbox ) {
167 print VPASSWDTMP join (':',
173 "$dir/domains/$domain/$username", #$vdir
174 $quota ? $quota.'S' : 'NOQUOTA',
180 rename "$exportdir/domains/$domain/vpasswd.tmp", "$exportdir/domains/$domain/vpasswd"
181 or die "Can't rename $exportdir/domains/$domain/vpasswd.tmp: $!";
183 flock(VPASSWD,LOCK_UN);
186 vpopmail_sync( $exportdir, $machine, $dir, $uid, $gid, $restart );
190 sub vpopmail_delete { #subroutine, not method
191 my( $exportdir, $machine, $dir, $uid, $gid, $restart ) = splice @_,0,6;
192 my( $username, $domain ) = @_;
194 (open(VPASSWD, "$exportdir/domains/$domain/vpasswd")
195 and flock(VPASSWD,LOCK_EX)
196 ) or die "can't open $exportdir/domains/$domain/vpasswd: $!";
198 open(VPASSWDTMP, ">$exportdir/domains/$domain/vpasswd.tmp")
199 or die "Can't open $exportdir/domains/$domain/vpasswd.tmp: $!";
202 my ($mailbox, $rest) = split(':', $_);
203 print VPASSWDTMP $_ unless $username eq $mailbox;
208 rename "$exportdir/domains/$domain/vpasswd.tmp",
209 "$exportdir/domains/$domain/vpasswd"
210 or die "Can't rename $exportdir/domains/$domain/vpasswd.tmp: $!";
212 flock(VPASSWD,LOCK_UN);
215 rmtree "$exportdir/domains/$domain/$username"
216 or die "can't rmtree $exportdir/domains/$domain/$username: $!";
218 vpopmail_sync( $exportdir, $machine, $dir, $uid, $gid, $restart );
222 my( $exportdir, $machine, $dir, $uid, $gid, $restart ) = splice @_,0,6;
225 # my @args = ( $rsync, "-rlpt", "-e", $ssh, "domains/",
226 # "vpopmail\@$machine:$dir/domains/" );
227 # system {$args[0]} @args;
229 eval "use File::Rsync;";
232 my $rsync = File::Rsync->new({ rsh => 'ssh' });
238 src => "$exportdir/domains/",
239 dest => "vpopmail\@$machine:$dir/domains/",
240 } ); # true/false return value from exec is not working, alas
242 die "error uploading to vpopmail\@$machine:$dir/domains/ : ".
243 'exit status: '. $rsync->status. ', '.
244 'STDERR: '. join(" / ", $rsync->err). ', '.
245 'STDOUT: '. join(" / ", $rsync->out);
248 eval "use Net::SSH qw(ssh);";
251 ssh("vpopmail\@$machine", $restart) if $restart;