From: ivan Date: Mon, 19 May 2003 12:00:45 +0000 (+0000) Subject: maintenance: X-Git-Tag: freeside_1_5_0pre2~13 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=fd9138f66cf7f3ab9557e0beebb4e2657a59e34c maintenance: - add FS::Misc with send_email subroutine, remove all duplicate code from various modules - move the realtime_bop from cust_bill to cust_main & change usage slightly. invnum is no longer required. FS::cust_bill::realtime_bop remains as a wrapper. self-service: - fix some syntax errors, make payment UI (step one) really should be working now --- diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index c750ada46..a64cfb5d7 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -167,7 +167,7 @@ sub payment_info { }; my $_date = time; - $return{paybatch} = 'webui-MyAccount-$_date-$$-". rand() * 2**32 + $return{paybatch} = "webui-MyAccount-$_date-$$-". rand() * 2**32; return { 'error' => '', %return, @@ -175,6 +175,20 @@ sub payment_info { }; +sub make_payment{ + my $p = shift; + + my $session = $cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my %return; + + my $custnum = $session->{'custnum'}; + + + +} + sub invoice { my $p = shift; my $session = $cache->get($p->{'session_id'}) diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm new file mode 100644 index 000000000..56dc72e36 --- /dev/null +++ b/FS/FS/Misc.pm @@ -0,0 +1,95 @@ +package FS::Misc; + +use strict; +use vars qw ( @ISA @EXPORT_OK ); +use Exporter; + +@ISA = qw( Exporter ); +@EXPORT_OK = qw( send_email ); + +=head1 NAME + +FS::Misc - Miscellaneous subroutines + +=head1 SYNOPSIS + + use FS::Misc qw(send_email); + + send_email(); + +=head1 DESCRIPTION + +Miscellaneous subroutines. This module contains miscellaneous subroutines +called from multiple other modules. These are not OO or necessarily related, +but are collected here to elimiate code duplication. + +=head1 SUBROUTINES + +=over 4 + +=item send_email OPTION => VALUE ... + +Options: + +I - (required) + +I - (required) comma-separated scalar or arrayref of recipients + +I - (required) + +I - (optional) MIME type + +I - (required) arrayref of body text lines + +=cut + +use vars qw( $conf ); +use Date::Format; +use Mail::Header; +use Mail::Internet 1.44; +use FS::UID; + +FS::UID->install_callback( sub { + $conf = new FS::Conf; +} ); + +sub send_email { + my(%options) = shift; + + $ENV{MAILADDRESS} = $options{'from'}; + my $to = ref($options{to}) ? join(', ', @{ $options{to} } ) : $options{to}; + my @header = ( + 'From: '. $options{'from'}, + 'To: '. $to, + 'Sender: '. $options{'from'}, + 'Reply-To: '. $options{'from'}, + 'Date: '. time2str("%a, %d %b %Y %X %z", time), + 'Subject: '. $options{'subject'}, + ); + push @header, 'Content-Type: '. $options{'content-type'} + if exists($options{'content-type'}); + my $header = new Mail::Header ( \@header ); + + my $message = new Mail::Internet ( + 'Header' => $header, + 'Body' => $options{'body'}, + ); + + my $smtpmachine = $conf->config('smtpmachine'); + $!=0; + $message->smtpsend( 'Host' => $smtpmachine ) + or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) + or return "can't send email to $to via server $smtpmachine with SMTP: $!"; +} + +=head1 BUGS + +This package exists. + +=head1 SEE ALSO + +L, L, L, the base documentation. + +=cut + +1; diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index a0634d918..a22f44b24 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -2,18 +2,12 @@ package FS::cust_bill; use strict; use vars qw( @ISA $conf $money_char ); -use vars qw( $lpr $invoice_from $smtpmachine ); -use vars qw( $xaction $E_NoErr ); -use vars qw( $bop_processor $bop_login $bop_password $bop_action @bop_options ); -use vars qw( $ach_processor $ach_login $ach_password $ach_action @ach_options ); use vars qw( $invoice_lines @buf ); #yuck -use vars qw( $quiet ); use Date::Format; -use Mail::Internet 1.44; -use Mail::Header; use Text::Template; use FS::UID qw( datasrc ); use FS::Record qw( qsearch qsearchs ); +use FS::Misc qw( send_email ); use FS::cust_main; use FS::cust_bill_pkg; use FS::cust_credit; @@ -26,46 +20,10 @@ use FS::cust_bill_event; @ISA = qw( FS::Record ); #ask FS::UID to run this stuff for us later -$FS::UID::callback{'FS::cust_bill'} = sub { - +FS::UID->install_callback( sub { $conf = new FS::Conf; - $money_char = $conf->config('money_char') || '$'; - - $lpr = $conf->config('lpr'); - $invoice_from = $conf->config('invoice_from'); - $smtpmachine = $conf->config('smtpmachine'); - - ( $bop_processor,$bop_login, $bop_password, $bop_action ) = ( '', '', '', ''); - @bop_options = (); - ( $ach_processor,$ach_login, $ach_password, $ach_action ) = ( '', '', '', ''); - @ach_options = (); - - if ( $conf->exists('business-onlinepayment') ) { - ( $bop_processor, - $bop_login, - $bop_password, - $bop_action, - @bop_options - ) = $conf->config('business-onlinepayment'); - $bop_action ||= 'normal authorization'; - ( $ach_processor, $ach_login, $ach_password, $ach_action, @ach_options ) = - ( $bop_processor, $bop_login, $bop_password, $bop_action, @bop_options ); - eval "use Business::OnlinePayment"; - } - - if ( $conf->exists('business-onlinepayment-ach') ) { - ( $ach_processor, - $ach_login, - $ach_password, - $ach_action, - @ach_options - ) = $conf->config('business-onlinepayment-ach'); - $ach_action ||= 'normal authorization'; - eval "use Business::OnlinePayment"; - } - -}; +} ); =head1 NAME @@ -373,33 +331,20 @@ sub send { if ( grep { $_ ne 'POST' } @invoicing_list or !@invoicing_list ) { #email #better to notify this person than silence - @invoicing_list = ($invoice_from) unless @invoicing_list; - - #false laziness w/FS::cust_pay::delete & fs_signup_server && ::realtime_card - #$ENV{SMTPHOSTS} = $smtpmachine; - $ENV{MAILADDRESS} = $invoice_from; - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: Invoice", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ @print_text ], #( date) + @invoicing_list = ($conf->config('invoice_from')) unless @invoicing_list; + + my $error = send_email( + 'from' => $conf->config('invoice_from'), + 'to' => [ grep { $_ ne 'POST' } @invoicing_list ], + 'subject' => 'Invoice', + 'body' => \@print_text, ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or return "(customer # ". $self->custnum. ") can't send invoice email". - " to ". join(', ', grep { $_ ne 'POST' } @invoicing_list ). - " via server $smtpmachine with SMTP: $!"; + return "can't send invoice: $error" if $error; } if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal + my $lpr = $conf->config('lpr'); open(LPR, "|$lpr") or return "Can't open pipe to $lpr: $!"; print LPR @print_text; @@ -610,15 +555,7 @@ for supported processors. sub realtime_card { my $self = shift; - $self->realtime_bop( - 'CC', - $bop_processor, - $bop_login, - $bop_password, - $bop_action, - \@bop_options, - @_ - ); + $self->realtime_bop( 'CC', @_ ); } =item realtime_ach @@ -632,15 +569,7 @@ for supported processors. sub realtime_ach { my $self = shift; - $self->realtime_bop( - 'ECHECK', - $ach_processor, - $ach_login, - $ach_password, - $ach_action, - \@ach_options, - @_ - ); + $self->realtime_bop( 'ECHECK', @_ ); } =item realtime_lec @@ -654,53 +583,15 @@ for supported processors. sub realtime_lec { my $self = shift; - $self->realtime_bop( - 'LEC', - $bop_processor, - $bop_login, - $bop_password, - $bop_action, - \@bop_options, - @_ - ); + $self->realtime_bop( 'LEC', @_ ); } sub realtime_bop { - my( $self, $method, $processor, $login, $password, $action, $options ) = @_; - - #trim an extraneous blank line - pop @$options if scalar(@$options) % 2 && $options->[-1] =~ /^\s*$/; + my( $self, $method ) = @_; my $cust_main = $self->cust_main; my $amount = $self->owed; - my $address = $cust_main->address1; - $address .= ", ". $cust_main->address2 if $cust_main->address2; - - my($payname, $payfirst, $paylast); - if ( $cust_main->payname && $method ne 'ECHECK' ) { - $payname = $cust_main->payname; - $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ - or do { - #$dbh->rollback if $oldAutoCommit; - return "Illegal payname $payname"; - }; - ($payfirst, $paylast) = ($1, $2); - } else { - $payfirst = $cust_main->getfield('first'); - $paylast = $cust_main->getfield('last'); - $payname = "$payfirst $paylast"; - } - - my @invoicing_list = grep { $_ ne 'POST' } $cust_main->invoicing_list; - if ( $conf->exists('emailinvoiceauto') - || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) { - push @invoicing_list, $cust_main->all_emails; - } - my $email = $invoicing_list[0]; - - my( $action1, $action2 ) = split(/\s*\,\s*/, $action ); - my $description = 'Internet Services'; if ( $conf->exists('business-onlinepayment-description') ) { my $dtempl = $conf->config('business-onlinepayment-description'); @@ -714,163 +605,12 @@ sub realtime_bop { grep { $_->pkgnum } $self->cust_bill_pkg ); $description = eval qq("$dtempl"); - } - my %content; - if ( $method eq 'CC' ) { - $content{card_number} = $cust_main->payinfo; - $cust_main->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; - $content{expiration} = "$2/$1"; - } elsif ( $method eq 'ECHECK' ) { - my($account_number,$routing_code) = $cust_main->payinfo; - ( $content{account_number}, $content{routing_code} ) = - split('@', $cust_main->payinfo); - $content{bank_name} = $cust_main->payname; - } elsif ( $method eq 'LEC' ) { - $content{phone} = $cust_main->payinfo; - } - - my $transaction = - new Business::OnlinePayment( $processor, @$options ); - $transaction->content( - 'type' => $method, - 'login' => $login, - 'password' => $password, - 'action' => $action1, - 'description' => $description, - 'amount' => $amount, - 'invoice_number' => $self->invnum, - 'customer_id' => $self->custnum, - 'last_name' => $paylast, - 'first_name' => $payfirst, - 'name' => $payname, - 'address' => $address, - 'city' => $cust_main->city, - 'state' => $cust_main->state, - 'zip' => $cust_main->zip, - 'country' => $cust_main->country, - 'referer' => 'http://cleanwhisker.420.am/', - 'email' => $email, - 'phone' => $cust_main->daytime || $cust_main->night, - %content, #after + $cust_main->realtime_bop($method, $amount, + 'description' => $description, + 'invnum' => $self->invnum, ); - $transaction->submit(); - - if ( $transaction->is_success() && $action2 ) { - my $auth = $transaction->authorization; - my $ordernum = $transaction->can('order_number') - ? $transaction->order_number - : ''; - - #warn "********* $auth ***********\n"; - #warn "********* $ordernum ***********\n"; - my $capture = - new Business::OnlinePayment( $processor, @$options ); - - my %capture = ( - %content, - type => $method, - action => $action2, - login => $login, - password => $password, - order_number => $ordernum, - amount => $amount, - authorization => $auth, - description => $description, - ); - - foreach my $field (qw( authorization_source_code returned_ACI transaction_identifier validation_code - transaction_sequence_num local_transaction_date - local_transaction_time AVS_result_code )) { - $capture{$field} = $transaction->$field() if $transaction->can($field); - } - - $capture->content( %capture ); - - $capture->submit(); - - unless ( $capture->is_success ) { - my $e = "Authorization sucessful but capture failed, invnum #". - $self->invnum. ': '. $capture->result_code. - ": ". $capture->error_message; - warn $e; - return $e; - } - - } - - if ( $transaction->is_success() ) { - - my %method2payby = ( - 'CC' => 'CARD', - 'ECHECK' => 'CHEK', - 'LEC' => 'LECB', - ); - - my $cust_pay = new FS::cust_pay ( { - 'invnum' => $self->invnum, - 'paid' => $amount, - '_date' => '', - 'payby' => $method2payby{$method}, - 'payinfo' => $cust_main->payinfo, - 'paybatch' => "$processor:". $transaction->authorization, - } ); - my $error = $cust_pay->insert; - if ( $error ) { - # gah, even with transactions. - my $e = 'WARNING: Card/ACH debited but database not updated - '. - 'error applying payment, invnum #' . $self->invnum. - " ($processor): $error"; - warn $e; - return $e; - } else { - return ''; - } - #} elsif ( $options{'report_badcard'} ) { - } else { - - my $perror = "$processor error, invnum #". $self->invnum. ': '. - $transaction->result_code. ": ". $transaction->error_message; - - if ( !$quiet && $conf->exists('emaildecline') - && grep { $_ ne 'POST' } $cust_main->invoicing_list - ) { - my @templ = $conf->config('declinetemplate'); - my $template = new Text::Template ( - TYPE => 'ARRAY', - SOURCE => [ map "$_\n", @templ ], - ) or return "($perror) can't create template: $Text::Template::ERROR"; - $template->compile() - or return "($perror) can't compile template: $Text::Template::ERROR"; - - my $templ_hash = { error => $transaction->error_message }; - - #false laziness w/FS::cust_pay::delete & fs_signup_server && ::send - $ENV{MAILADDRESS} = $invoice_from; - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: Your payment could not be processed", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ $template->fill_in(HASH => $templ_hash) ], - ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or return "($perror) (customer # ". $self->custnum. - ") can't send card decline email to ". - join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list ). - " via server $smtpmachine with SMTP: $!"; - } - - return $perror; - } } diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 608c5e3cb..b162622a4 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -10,6 +10,7 @@ use Date::Format; use Business::CreditCard; use FS::UID qw( getotaker dbh ); use FS::Record qw( qsearchs qsearch dbdef ); +use FS::Misc qw( send_email ); use FS::cust_pkg; use FS::cust_bill; use FS::cust_bill_pkg; @@ -1408,6 +1409,221 @@ sub collect { } +=item realtime_bop METHOD AMOUNT [ OPTION => VALUE ... ] + + +Runs a realtime credit card, ACH (electronic check) or phone bill transaction +via a Business::OnlinePayment realtime gateway. See +L for supported gateways. + +Available methods are: I, I and I + +Available options are: I, I, I + +I is a free-text field passed to the gateway. It defaults to +"Internet services". + +If an I is specified, this payment (if sucessful) is applied to the +specified invoice. If you don't specify an I you might want to +call the B method. + +I can be set true to surpress email decline notices. + +(moved from cust_bill) (probably should get realtime_{card,ach,lec} here too) + +=cut + +sub realtime_bop { + my( $self, $method, $amount, %options ) = @_; + $options{'description'} ||= 'Internet services'; + + #pre-requisites + die "Real-time processing not enabled\n" + unless $conf->exists('business-onlinepayment'); + eval "use Business::OnlinePayment"; + die $@ if $@; + + #load up config + my $bop_config = 'business-onlinepayment'; + $bop_config .= '-ach' + if $method eq 'ECHECK' && $conf->exists($bop_config. '-ach'); + my ( $processor, $login, $password, $action, @bop_options ) = + $conf->config($bop_config); + $action ||= 'normal authorization'; + pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/; + + #massage data + + my $address = $self->address1; + $address .= ", ". $self->address2 if $self->address2; + + my($payname, $payfirst, $paylast); + if ( $self->payname && $method ne 'ECHECK' ) { + $payname = $self->payname; + $payname =~ /^\s*([\w \,\.\-\']*)?\s+([\w\,\.\-\']+)\s*$/ + or return "Illegal payname $payname"; + ($payfirst, $paylast) = ($1, $2); + } else { + $payfirst = $self->getfield('first'); + $paylast = $self->getfield('last'); + $payname = "$payfirst $paylast"; + } + + my @invoicing_list = grep { $_ ne 'POST' } $self->invoicing_list; + if ( $conf->exists('emailinvoiceauto') + || ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) { + push @invoicing_list, $self->all_emails; + } + my $email = $invoicing_list[0]; + + my %content; + if ( $method eq 'CC' ) { + $content{card_number} = $self->payinfo; + $self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; + $content{expiration} = "$2/$1"; + } elsif ( $method eq 'ECHECK' ) { + my($account_number,$routing_code) = $self->payinfo; + ( $content{account_number}, $content{routing_code} ) = + split('@', $self->payinfo); + $content{bank_name} = $self->payname; + } elsif ( $method eq 'LEC' ) { + $content{phone} = $self->payinfo; + } + + #transaction(s) + + my( $action1, $action2 ) = split(/\s*\,\s*/, $action ); + + my $transaction = + new Business::OnlinePayment( $processor, @bop_options ); + $transaction->content( + 'type' => $method, + 'login' => $login, + 'password' => $password, + 'action' => $action1, + 'description' => $options{'description'}, + 'amount' => $amount, + 'invoice_number' => $options{'invnum'}, + 'customer_id' => $self->custnum, + 'last_name' => $paylast, + 'first_name' => $payfirst, + 'name' => $payname, + 'address' => $address, + 'city' => $self->city, + 'state' => $self->state, + 'zip' => $self->zip, + 'country' => $self->country, + 'referer' => 'http://cleanwhisker.420.am/', + 'email' => $email, + 'phone' => $self->daytime || $self->night, + %content, #after + ); + $transaction->submit(); + + if ( $transaction->is_success() && $action2 ) { + my $auth = $transaction->authorization; + my $ordernum = $transaction->can('order_number') + ? $transaction->order_number + : ''; + + my $capture = + new Business::OnlinePayment( $processor, @bop_options ); + + my %capture = ( + %content, + type => $method, + action => $action2, + login => $login, + password => $password, + order_number => $ordernum, + amount => $amount, + authorization => $auth, + description => $options{'description'}, + ); + + foreach my $field (qw( authorization_source_code returned_ACI transaction_identifier validation_code + transaction_sequence_num local_transaction_date + local_transaction_time AVS_result_code )) { + $capture{$field} = $transaction->$field() if $transaction->can($field); + } + + $capture->content( %capture ); + + $capture->submit(); + + unless ( $capture->is_success ) { + my $e = "Authorization sucessful but capture failed, custnum #". + $self->custnum. ': '. $capture->result_code. + ": ". $capture->error_message; + warn $e; + return $e; + } + + } + + #result handling + if ( $transaction->is_success() ) { + + my %method2payby = ( + 'CC' => 'CARD', + 'ECHECK' => 'CHEK', + 'LEC' => 'LECB', + ); + + my $cust_pay = new FS::cust_pay ( { + 'invnum' => $self->invnum, #!!!!!!!! + 'paid' => $amount, + '_date' => '', + 'payby' => $method2payby{$method}, + 'payinfo' => $self->payinfo, + 'paybatch' => "$processor:". $transaction->authorization, + } ); + my $error = $cust_pay->insert; + if ( $error ) { + # gah, even with transactions. + my $e = 'WARNING: Card/ACH debited but database not updated - '. + 'error applying payment, invnum #' . $self->invnum. + " ($processor): $error"; + warn $e; + return $e; + } else { + return ''; + } + + } else { + + my $perror = "$processor error: ". $transaction->error_message; + + if ( !$options{'quiet'} && $conf->exists('emaildecline') + && grep { $_ ne 'POST' } $self->invoicing_list + ) { + my @templ = $conf->config('declinetemplate'); + my $template = new Text::Template ( + TYPE => 'ARRAY', + SOURCE => [ map "$_\n", @templ ], + ) or return "($perror) can't create template: $Text::Template::ERROR"; + $template->compile() + or return "($perror) can't compile template: $Text::Template::ERROR"; + + my $templ_hash = { error => $transaction->error_message }; + + my $error = send_email( + 'from' => $conf->config('invoice_from'), + 'to' => [ grep { $_ ne 'POST' } $self->invoicing_list ], + 'subject' => 'Your payment could not be processed', + 'body' => [ $template->fill_in(HASH => $templ_hash) ], + ); + + $perror .= " (also received error sending decline notification: $error)" + if $error; + + } + + return $perror; + } + +} + =item total_owed Returns the total owed for this customer on all invoices diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index 79cf82755..55f2fc4a3 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -1,13 +1,12 @@ package FS::cust_pay; use strict; -use vars qw( @ISA $conf $unsuspendauto $smtpmachine $invoice_from ); +use vars qw( @ISA $conf $unsuspendauto ); use Date::Format; -use Mail::Header; -use Mail::Internet 1.44; use Business::CreditCard; use FS::UID qw( dbh ); use FS::Record qw( dbh qsearch qsearchs dbh ); +use FS::Misc qw(send_email); use FS::cust_bill; use FS::cust_bill_pay; use FS::cust_main; @@ -15,14 +14,10 @@ use FS::cust_main; @ISA = qw( FS::Record ); #ask FS::UID to run this stuff for us later -$FS::UID::callback{'FS::cust_pay'} = sub { - +FS::UID->install_callback( sub { $conf = new FS::Conf; $unsuspendauto = $conf->exists('unsuspendauto'); - $smtpmachine = $conf->config('smtpmachine'); - $invoice_from = $conf->config('invoice_from'); - -}; +} ); =head1 NAME @@ -265,19 +260,12 @@ sub delete { if ( $conf->config('deletepayments') ne '' ) { my $cust_main = qsearchs('cust_main',{ 'custnum' => $self->custnum }); - #false laziness w/FS::cust_bill::send & fs_signup_server - $ENV{MAILADDRESS} = $invoice_from; #??? well as good as any - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". $conf->config('deletepayments'), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: FREESIDE NOTIFICATION: Payment deleted", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ + + my $error = send_email( + 'from' => $conf->config('invoice_from'), #??? well as good as any + 'to' => $conf->config('deletepayments'), + 'subject' => 'FREESIDE NOTIFICATION: Payment deleted', + 'body' => [ "This is an automatic message from your Freeside installation\n", "informing you that the following payment has been deleted:\n", "\n", @@ -291,16 +279,12 @@ sub delete { 'paybatch: '. $self->paybatch. "\n", ], ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or do { - $dbh->rollback if $oldAutoCommit; - return "(customer # ". $self->custnum. - ") can't send payment deletion email to ". - $conf->config('deletepayments'). - " via server $smtpmachine with SMTP: $!"; - }; + + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "can't send payment deletion notification: $error"; + } + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -406,7 +390,7 @@ sub unapplied { =head1 VERSION -$Id: cust_pay.pm,v 1.23 2002-11-19 09:51:58 ivan Exp $ +$Id: cust_pay.pm,v 1.24 2003-05-19 12:00:44 ivan Exp $ =head1 BUGS diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index bd3d1f503..9ab269503 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -5,6 +5,7 @@ use vars qw(@ISA $disable_agentcheck); use vars qw( $quiet ); use FS::UID qw( getotaker dbh ); use FS::Record qw( qsearch qsearchs ); +use FS::Misc qw( send_email ); use FS::cust_svc; use FS::part_pkg; use FS::cust_main; @@ -20,12 +21,8 @@ use FS::svc_domain; use FS::svc_www; use FS::svc_forward; -# need all this for sending cancel emails in sub cancel - +# for sending cancel emails in sub cancel use FS::Conf; -use Date::Format; -use Mail::Internet 1.44; -use Mail::Header; @ISA = qw( FS::Record ); @@ -304,38 +301,16 @@ sub cancel { $dbh->commit or die $dbh->errstr if $oldAutoCommit; my $conf = new FS::Conf; - - if ( !$quiet && $conf->exists('emailcancel') - && grep { $_ ne 'POST' } $self->cust_main->invoicing_list) { - - my @invoicing_list = $self->cust_main->invoicing_list; - - my $invoice_from = $conf->config('invoice_from'); - my @print_text = map "$_\n", $conf->config('cancelmessage'); - my $subject = $conf->config('cancelsubject'); - my $smtpmachine = $conf->config('smtpmachine'); - - if ( grep { $_ ne 'POST' } @invoicing_list ) { #email invoice - #false laziness w/FS::cust_pay::delete & fs_signup_server && ::realtime_card - #$ENV{SMTPHOSTS} = $smtpmachine; - $ENV{MAILADDRESS} = $invoice_from; - my $header = new Mail::Header ( [ - "From: $invoice_from", - "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ), - "Sender: $invoice_from", - "Reply-To: $invoice_from", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: $subject", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ @print_text ], - ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ); - #should this return an error? - } + my @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list; + if ( !$quiet && $conf->exists('emailcancel') && @invoicing_list ) { + my $conf = new FS::Conf; + my $error = send_email( + 'from' => $conf->config('invoice_from'), + 'to' => \@invoicing_list, + 'subject' => $conf->config('cancelsubject'), + 'body' => [ map "$_\n", $conf->config('cancelmessage') ], + ); + #should this do something on errors? } ''; #no errors diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index 8f2861bfd..497e59c94 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -1024,36 +1024,28 @@ sub radius_groups { =item send_email +This is the FS::svc_acct job-queue-able version. It still uses +FS::Misc::send_email under-the-hood. + =cut sub send_email { my %opt = @_; - use Date::Format; - use Mail::Internet 1.44; - use Mail::Header; + eval "use FS::Misc qw(send_email)"; + die $@ if $@; $opt{mimetype} ||= 'text/plain'; $opt{mimetype} .= '; charset="iso-8859-1"' unless $opt{mimetype} =~ /charset/; - $ENV{MAILADDRESS} = $opt{from}; - my $header = new Mail::Header ( [ - "From: $opt{from}", - "To: $opt{to}", - "Sender: $opt{from}", - "Reply-To: $opt{from}", - "Date: ". time2str("%a, %d %b %Y %X %z", time), - "Subject: $opt{subject}", - "Content-Type: $opt{mimetype}", - ] ); - my $message = new Mail::Internet ( - 'Header' => $header, - 'Body' => [ map "$_\n", split("\n", $opt{body}) ], + my $error = send_email( + 'from' => $opt{from}, + 'to' => $opt{to}, + 'subject' => $opt{subject}, + 'content-type' => $opt{mimetype}, + 'body' => [ map "$_\n", split("\n", $opt{body}) ], ); - $!=0; - $message->smtpsend( Host => $smtpmachine ) - or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) - or die "can't send email to $opt{to} via $smtpmachine with SMTP: $!"; + die $error if $error; } =item check_and_rebuild_fuzzyfiles diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm index 81edc337e..2e8866a56 100644 --- a/FS/FS/svc_domain.pm +++ b/FS/FS/svc_domain.pm @@ -1,13 +1,11 @@ package FS::svc_domain; use strict; -use vars qw( @ISA $whois_hack $conf $smtpmachine +use vars qw( @ISA $whois_hack $conf @defaultrecords $soadefaultttl $soaemail $soaexpire $soamachine $soarefresh $soaretry ); use Carp; -use Mail::Internet 1.44; -use Mail::Header; use Date::Format; use Net::Whois 1.0; use FS::Record qw(fields qsearch qsearchs dbh); @@ -26,8 +24,6 @@ use FS::queue; $FS::UID::callback{'FS::domain'} = sub { $conf = new FS::Conf; - $smtpmachine = $conf->config('smtpmachine'); - @defaultrecords = $conf->config('defaultrecords'); $soadefaultttl = $conf->config('soadefaultttl'); $soaemail = $conf->config('soaemail'); diff --git a/FS/MANIFEST b/FS/MANIFEST index 6397cc411..272b5b731 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -36,6 +36,7 @@ FS/ClientAPI/passwd.pm FS/ClientAPI/MyAccount.pm FS/Conf.pm FS/ConfItem.pm +FS/Misc.pm FS/Record.pm FS/SearchCache.pm FS/UI/Base.pm @@ -125,6 +126,7 @@ t/InitHandler.t t/ClientAPI.t t/Conf.t t/ConfItem.t +t/Misc.t t/Record.t t/UID.t t/Msgcat.t diff --git a/FS/t/Misc.t b/FS/t/Misc.t new file mode 100644 index 000000000..cc7751ab6 --- /dev/null +++ b/FS/t/Misc.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::Misc; +$loaded=1; +print "ok 1\n";