1 package FS::svc_forward;
4 use vars qw( @ISA $nossh_hack $conf $shellmachine @qmailmachines
8 use FS::Record qw( fields qsearch qsearchs );
14 @ISA = qw( FS::svc_Common );
16 #ask FS::UID to run this stuff for us later
17 $FS::UID::callback{'FS::svc_forward'} = sub {
19 if ( $conf->exists('qmailmachines') ) {
20 $shellmachine = $conf->config('shellmachine')
24 if ( $conf->exists('vpopmailmachines') ) {
25 @vpopmailmachines = $conf->config('vpopmailmachines');
27 @vpopmailmachines = ();
33 FS::svc_forward - Object methods for svc_forward records
39 $record = new FS::svc_forward \%hash;
40 $record = new FS::svc_forward { 'column' => 'value' };
42 $error = $record->insert;
44 $error = $new_record->replace($old_record);
46 $error = $record->delete;
48 $error = $record->check;
50 $error = $record->suspend;
52 $error = $record->unsuspend;
54 $error = $record->cancel;
58 An FS::svc_forward object represents a mail forwarding alias. FS::svc_forward
59 inherits from FS::Record. The following fields are currently supported:
63 =item svcnum - primary key (assigned automatcially for new accounts)
65 =item srcsvc - svcnum of the source of the forward (see L<FS::svc_acct>)
67 =item dstsvc - svcnum of the destination of the forward (see L<FS::svc_acct>)
69 =item dst - foreign destination (email address) - forward not local to freeside
79 Creates a new mail forwarding alias. To add the mail forwarding alias to the
80 database, see L<"insert">.
84 sub table { 'svc_forward'; }
88 Adds this mail forwarding alias to the database. If there is an error, returns
89 the error, otherwise returns false.
91 The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
92 defined. An FS::cust_svc record will be created and inserted.
94 If the configuration value (see L<FS::Conf>) vpopmailmachines exists, then
97 [ -d $vpopdir/$domain/$source ] || {
98 echo "$destination" >> $vpopdir/$domain/$username/.$qmail
99 chown $vpopuid:$vpopgid $vpopdir/$domain/$username/.$qmail
102 is executed on each vpopmailmachine via ssh (see the vpopmail documentation).
103 This behaviour can be supressed by setting $FS::svc_forward::nossh_hack true.
111 local $SIG{HUP} = 'IGNORE';
112 local $SIG{INT} = 'IGNORE';
113 local $SIG{QUIT} = 'IGNORE';
114 local $SIG{TERM} = 'IGNORE';
115 local $SIG{TSTP} = 'IGNORE';
116 local $SIG{PIPE} = 'IGNORE';
118 $error = $self->check;
119 return $error if $error;
121 $error = $self->SUPER::insert;
122 return $error if $error;
124 my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $self->srcsvc } );
125 my $username = $svc_acct->username;
126 my $domain = $svc_acct->domain;
129 my $dst_svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $self->dstsvc } );
130 $destination = $dst_svc_acct->email;
132 $destination = $self->dst;
135 foreach my $vpopmailmachine ( @vpopmailmachines ) {
136 my($machine, $vpopdir, $vpopuid, $vpopgid) = split(/\s+/, $vpopmailmachine);
137 ssh("root\@$machine","[ -d $vpopdir/$domain/$username ] || { echo \"$destination\" >> $vpopdir/$domain/$username/.qmail; chown $vpopuid:$vpopgid $vpopdir/$domain/$username/.qmail; }")
147 Deletes this mail forwarding alias from the database. If there is an error,
148 returns the error, otherwise returns false.
150 The corresponding FS::cust_svc record will be deleted as well.
152 =item replace OLD_RECORD
154 Replaces OLD_RECORD with this one in the database. If there is an error,
155 returns the error, otherwise returns false.
157 If srcsvc changes, and the configuration value vpopmailmachines exists, then
160 rm $vpopdir/$domain/$username/.qmail
162 is executed on each vpopmailmachine via ssh. This behaviour can be supressed
163 by setting $FS::svc_forward_nossh_hack true.
165 If dstsvc changes (or dstsvc is 0 and dst changes), and the configuration value
166 vpopmailmachines exists, then the command:
168 [ -d $vpopdir/$domain/$source ] || {
169 echo "$destination" >> $vpopdir/$domain/$username/.$qmail
170 chown $vpopuid:$vpopgid $vpopdir/$domain/$username/.$qmail
173 is executed on each vpopmailmachine via ssh. This behaviour can be supressed
174 by setting $FS::svc_forward_nossh_hack true.
179 my ( $new, $old ) = ( shift, shift );
181 if ( $new->srcsvc != $old->srcsvc
182 && ( $new->dstsvc != $old->dstsvc
183 || ! $new->dstsvc && $new->dst ne $old->dst
186 return "Can't change both source and destination of a mail forward!"
189 local $SIG{HUP} = 'IGNORE';
190 local $SIG{INT} = 'IGNORE';
191 local $SIG{QUIT} = 'IGNORE';
192 local $SIG{TERM} = 'IGNORE';
193 local $SIG{TSTP} = 'IGNORE';
194 local $SIG{PIPE} = 'IGNORE';
196 my $error = $new->SUPER::replace($old);
197 return $error if $error;
199 if ( $new->srcsvc != $old->srcsvc ) {
200 my $old_svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $old->srcsvc } );
201 my $old_username = $old_svc_acct->username;
202 my $old_domain = $old_svc_acct->domain;
203 foreach my $vpopmailmachine ( @vpopmailmachines ) {
204 my($machine, $vpopdir, $vpopuid, $vpopgid) =
205 split(/\s+/, $vpopmailmachine);
206 ssh("root\@$machine","rm $vpopdir/$old_domain/$old_username/.qmail")
211 #false laziness with stuff in insert, should subroutine
212 my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $new->srcsvc } );
213 my $username = $svc_acct->username;
214 my $domain = $svc_acct->domain;
217 my $dst_svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $new->dstsvc } );
218 $destination = $dst_svc_acct->email;
220 $destination = $new->dst;
223 foreach my $vpopmailmachine ( @vpopmailmachines ) {
224 my($machine, $vpopdir, $vpopuid, $vpopgid) = split(/\s+/, $vpopmailmachine);
225 ssh("root\@$machine","[ -d $vpopdir/$domain/$username ] || { echo \"$destination\" >> $vpopdir/$domain/$username/.qmail; chown $vpopuid:$vpopgid $vpopdir/$domain/$username/.qmail; }")
228 #end subroutinable bits
235 Just returns false (no error) for now.
237 Called by the suspend method of FS::cust_pkg (see L<FS::cust_pkg>).
241 Just returns false (no error) for now.
243 Called by the unsuspend method of FS::cust_pkg (see L<FS::cust_pkg>).
247 Just returns false (no error) for now.
249 Called by the cancel method of FS::cust_pkg (see L<FS::cust_pkg>).
253 Checks all fields to make sure this is a valid mail forwarding alias. If there
254 is an error, returns the error, otherwise returns false. Called by the insert
257 Sets any fixed values; see L<FS::part_svc>.
264 my $x = $self->setfixed;
265 return $x unless ref($x);
268 my $error = $self->ut_numbern('svcnum')
269 || $self->ut_number('srcsvc')
270 || $self->ut_numbern('dstsvc')
272 return $error if $error;
274 return "Unknown srcsvc" unless $self->srcsvc_acct;
276 return "Both dstsvc and dst were defined; one one can be specified"
277 if $self->dstsvc && $self->dst;
279 return "one of dstsvc or dst is required"
280 unless $self->dstsvc || $self->dst;
282 return "Unknown dstsvc" unless $self->dstsvc_acct || ! $self->dstsvc;
285 $self->dst =~ /^([\w\.\-]+)\@(([\w\-]+\.)+\w+)$/
286 or return "Illegal dst: ". $self->dst;
287 $self->dst("$1\@$2");
297 Returns the FS::svc_acct object referenced by the srcsvc column.
303 qsearchs('svc_acct', { 'svcnum' => $self->srcsvc } );
308 Returns the FS::svc_acct object referenced by the srcsvc column, or false for
309 forwards not local to freeside.
315 qsearchs('svc_acct', { 'svcnum' => $self->dstsvc } );
320 $Id: svc_forward.pm,v 1.8 2001-10-29 20:53:38 ivan Exp $
324 The remote commands should be configurable.
328 L<FS::Record>, L<FS::Conf>, L<FS::cust_svc>, L<FS::part_svc>, L<FS::cust_pkg>,
329 L<FS::svc_acct>, L<FS::svc_domain>, L<Net::SSH>, L<ssh>, L<dot-qmail>,
330 schema.html from the base documentation.