#!/usr/bin/perl -Tw use strict; use Date::Format; use Time::Local; use Text::Template; use Getopt::Std; use Net::SMTP; use Mail::Header; use Mail::Internet; use FS::Conf; use FS::UID qw(adminsuidsetup); use FS::Record qw(qsearch); use FS::cust_main; use vars qw($smtpmachine @body); #hush, perl! $FS::alerter::_template::first = ""; $FS::alerter::_template::last = ""; $FS::alerter::_template::company = ""; $FS::alerter::_template::payby = ""; $FS::alerter::_template::expdate = ""; # Set the mail program and other variables my $mail_sender = "billing\@mydomain.tld"; # or invoice_from if available my $failure_recipient = "postmaster"; # or invoice_from if available my $warning_time = 30 * 24 * 60 * 60; my $urgent_time = 15 * 24 * 60 * 60; my $panic_time = 5 * 24 * 60 * 60; my $window_time = 24 * 60 * 60; &untaint_argv; #what it sounds like (eww) #we're at now now (and later). my($_date)= $^T; # Get the current month my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($_date) )[0,1,2,3,4,5]; $mon++; # Login to the database my $user = shift or die &usage; adminsuidsetup $user; # Get the needed configuration files my $conf = new FS::Conf; $smtpmachine = $conf->config('smtpmachine'); $mail_sender = $conf->config('invoice_from') if $conf->exists('invoice_from'); $failure_recipient = $conf->config('invoice_from') if $conf->exists('invoice_from'); my(@customers)=qsearch('cust_main',{}); if (scalar(@customers) == 0) { exit 1; } # Prepare for sending email $ENV{MAILADDRESS} = $mail_sender; my $header = new Mail::Header ( [ "From: Account Processor", "To: $failure_recipient", "Sender: $mail_sender", "Reply-To: $mail_sender", "Subject: Unnotified Billing Arrangement Expirations", ] ); my @alerter_template = $conf->config('alerter_template') or die "cannot load config file alerter_template"; my $alerter = new Text::Template (TYPE => 'ARRAY', SOURCE => [ map "$_\n", @alerter_template ]) or die "can't create new Text::Template object: Text::Template::ERROR"; $alerter->compile() or die "can't compile template: Text::Template::ERROR"; # Now I can start looping foreach my $customer (@customers) { my $paydate = $customer->getfield('paydate'); next if $paydate =~ /^\s*$/; #skip empty expiration dates my $custnum = $customer->getfield('custnum'); my $first = $customer->getfield('first'); my $last = $customer->getfield('last'); my $company = $customer->getfield('company'); my $payby = $customer->getfield('payby'); my $payinfo = $customer->getfield('payinfo'); my $daytime = $customer->getfield('daytime'); my $night = $customer->getfield('night'); my ($payyear,$paymonth,$payday) = split (/-/,$paydate); my $expire_time = timelocal(0,0,0,$payday,--$paymonth,$payyear); #credit cards expire at the end of the month/year of their exp date if ($payby eq 'CARD' || $payby eq 'DCRD') { ($paymonth < 11) ? $paymonth++ : ($paymonth=0, $payyear++); $expire_time = timelocal(0,0,0,$payday,$paymonth,$payyear); $expire_time--; } if (($expire_time < $_date + $warning_time && $expire_time > $_date + $warning_time - $window_time) || ($expire_time < $_date + $urgent_time && $expire_time > $_date + $urgent_time - $window_time) || ($expire_time < $_date + $panic_time && $expire_time > $_date + $panic_time - $window_time)) { my @packages = $customer->ncancelled_pkgs; if (scalar(@packages) != 0) { my @invoicing_list = $customer->invoicing_list; if ( grep { $_ ne 'POST' } @invoicing_list ) { my $header = new Mail::Header ( [ "From: $mail_sender", "To: ". join(', ', grep { $_ ne 'POST' } @invoicing_list ), "Sender: $mail_sender", "Reply-To: $mail_sender", "Date: ". time2str("%a, %d %b %Y %X %z", time), "Subject: Billing Arrangement Expiration", ] ); $FS::alerter::_template::first = $first; $FS::alerter::_template::last = $last; $FS::alerter::_template::company = $company; if ($payby eq 'CARD' || $payby eq 'DCRD') { $FS::alerter::_template::payby = "credit card (" . substr($payinfo, 0, 2) . "xxxxxxxxxx" . substr($payinfo, -4) . ")"; }elsif ($payby eq 'COMP') { $FS::alerter::_template::payby = "complimentary account"; }else{ $FS::alerter::_template::payby = "current method"; } $FS::alerter::_template::expdate = $expire_time; my $message = new Mail::Internet ( 'Header' => $header, 'Body' => [ $alerter->fill_in( PACKAGE => 'FS::alerter::_template' ) ], ); $!=0; $message->smtpsend( Host => $smtpmachine ) or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) or die "Can't send expiration email: $!"; } elsif ( ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list ) { push @body, sprintf(qq{%5d %-32.32s %4s %10s %12s %12s}, $custnum, $first . " " . $last . " " . $company, $payby, $paydate, $daytime, $night); } } } } # Now I need to send EMAIL if (scalar(@body)) { my $message = new Mail::Internet ( 'Header' => $header, 'Body' => [ (@body) ], ); $!=0; $message->smtpsend( Host => $smtpmachine ) or $message->smtpsend( Host => $smtpmachine, Debug => 1 ) or die "can't send alerter failure email to $failure_recipient". " via server $smtpmachine with SMTP: $!"; } # subroutines sub untaint_argv { foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV $ARGV[$_] =~ /^([\w\-\/]*)$/ || die "Illegal argument \"$ARGV[$_]\""; $ARGV[$_]=$1; } } sub usage { die "Usage:\n\n freeside-expiration-alerter user\n"; } =head1 NAME freeside-expiration-alerter - Emails notifications of credit card expirations. =head1 SYNOPSIS freeside-expiration-alerter user =head1 DESCRIPTION Emails customers notice that their credit card or other billing arrangement is about to expire. Usually run as a cron job. user: From the mapsecrets file - see config.html from the base documentation =head1 VERSION $Id: freeside-expiration-alerter,v 1.5 2003-04-21 20:53:57 ivan Exp $ =head1 BUGS Yes..... Use at your own risk. No guarantees or warrantees of any kind apply to this program. Parts of this program are hacked from other GNU licensed software created mainly by Ivan Kohler. This is released under the GNU Public License. See www.gnu.org for more information regarding this license. =head1 SEE ALSO L, config.html from the base documentation =head1 AUTHOR Jeff Finucane =cut