"Fossies" - the Fresh Open Source Software Archive

Member "email-reminder-0.8.1/send-reminders" (19 Sep 2020, 11100 Bytes) of package /linux/privat/email-reminder-0.8.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "send-reminders": 0.8.0_vs_0.8.1.

    1 #!/usr/bin/perl -T
    2 
    3 =head1 NAME
    4 
    5 Send-reminders - send email reminders for special occasions
    6 
    7 =head1 SYNOPSIS
    8 
    9 Send emails reminders set by users for special occasions.
   10 
   11 =head1 DESCRIPTION
   12 
   13 Email-reminder allows users to define events that they want to be
   14 reminded of by email.  Possible events include birthdays,
   15 anniversaries and yearly events.  Reminders can be sent on the day of
   16 the event and a few days beforehand.
   17 
   18 This script is meant to be invoked everyday by a cron job.  It mails
   19 the actual reminders out.
   20 
   21 When run by the root user, it processes all of the spooled reminders.
   22 When run by a specific user, it only processes reminders set by that
   23 user.
   24 
   25 =head1 OPTIONS
   26 
   27 =over 6
   28 
   29 =item B<--help>
   30 
   31 Displays basic usage message.
   32 
   33 =item B<--simulate>
   34 
   35 Does not actually send any emails out.
   36 
   37 =item B<--verbose>
   38 
   39 Prints out information about what the program is doing, including the
   40 full emails being sent out.
   41 
   42 =item B<--version>
   43 
   44 Displays the version number.
   45 
   46 =back
   47 
   48 =head1 FILES
   49 
   50 F<~/.email-reminders>, F</etc/email-reminder.conf>
   51 
   52 =head1 AUTHOR
   53 
   54 Francois Marier <francois@fmarier.org>
   55 
   56 =head1 SEE ALSO
   57 
   58 email-reminder-editor, collect-reminders
   59 
   60 =head1 COPYRIGHT
   61 
   62 Copyright (C) 2004-2014 by Francois Marier
   63 
   64 Email-Reminder is free software; you can redistribute it and/or
   65 modify it under the terms of the GNU General Public License as
   66 published by the Free Software Foundation; either version 3 of the
   67 License, or (at your option) any later version.
   68 
   69 Email-Reminder is distributed in the hope that it will be useful,
   70 but WITHOUT ANY WARRANTY; without even the implied warranty of
   71 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   72 General Public License for more details.
   73 
   74 You should have received a copy of the GNU General Public License
   75 along with Email-Reminder; if not, write to the Free Software
   76 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   77 02110-1301, USA.
   78 
   79 =cut
   80 
   81 use strict;
   82 use warnings;
   83 
   84 use Encode;
   85 use Getopt::Long;
   86 use MIME::Base64;
   87 use MIME::QuotedPrint;
   88 use Pod::Usage;
   89 
   90 use EmailReminder::EventList;
   91 use EmailReminder::Utils;
   92 use Date::Manip qw(ParseDate UnixDate);
   93 
   94 binmode(STDOUT, ":utf8");
   95 binmode(STDERR, ":utf8");
   96 
   97 # Default preferences
   98 my $PREFERENCE_FILE = '/etc/email-reminder.conf';
   99 my %preferences;
  100 $preferences{"send_reminders"}   = 1;
  101 $preferences{"smtp_server"}      = 'localhost';
  102 $preferences{"smtp_ssl"}         = 0;
  103 $preferences{"smtp_username"}    = '';
  104 $preferences{"smtp_password"}    = '';
  105 $preferences{"mail_from"}        = 'root@localhost';
  106 read_config(); 
  107 
  108 # Global variables
  109 my $user_fname;
  110 my $user_lname;
  111 
  112 # Command-line parameters
  113 my $verbose  = 0;
  114 my $simulate = 0;
  115 my $version  = 0;
  116 my $help  = 0;
  117 GetOptions( "verbose"  => \$verbose,
  118             "simulate" => \$simulate,
  119             "version"  => \$version,
  120             "help"     => \$help,
  121     );
  122 
  123 # Override preferences with system values
  124 sub read_config
  125 {
  126     print "Reading preferences from '$PREFERENCE_FILE'\n" if $verbose;
  127 
  128     if (open my $config_fh, '<', $PREFERENCE_FILE) {
  129         # Stolen off of the Cookbook (section 8.16)
  130         while (<$config_fh>) {
  131             chomp;                  # no newline
  132             s/#.*//;                # no comments
  133             s/^\s+//;               # no leading white
  134             s/\s+$//;               # no trailing white
  135             next unless length;     # anything left?
  136             my ($var, $value) = split(/\s*=\s*/, $_, 2);
  137             $value = 1 if $value eq 'true' or $value eq 'yes';
  138             $value = 0 if $value eq 'false' or $value eq 'no';
  139             $preferences{$var} = $value;
  140         }
  141         close $config_fh;
  142     }
  143     else {
  144         print "Warning: cannot read configuration file at $PREFERENCE_FILE.\nMake sure that the user running $0 has read permissions on that configuration file.\n";
  145         return;
  146     }
  147     return 1;
  148 }
  149 
  150 sub send_email
  151 {
  152     my $message = shift;
  153     my $subject = shift;
  154     my $user_name = shift;
  155     my $user_email = shift;
  156 
  157     unless ($user_email) {
  158         return 0;
  159     }
  160 
  161     my $to = $user_email;
  162     $to = "$user_name <$user_email>" if ($user_name);
  163 
  164     print "--> Emailing '$to':\n$subject\n\n$message" if $verbose;
  165     
  166     unless ($simulate) {
  167         my $smtp_server = '';
  168         if ($preferences{"smtp_server"} =~ /^([A-Za-z_0-9\-\/.]+)$/) {
  169             $smtp_server = $1;
  170         }
  171         my $smtp = undef;
  172         if ($preferences{"smtp_ssl"}) {
  173             eval 'use Net::SMTP::SSL';
  174             die "Couldn't load module : $!" if ($@);
  175             $smtp = Net::SMTP::SSL->new($smtp_server, Port => 465, Debug => 0);
  176         }
  177         else {
  178             use Net::SMTP;
  179             $smtp = Net::SMTP->new($smtp_server, Debug => 0);
  180         }
  181         die "Error: couldn't connect to server '$smtp_server'\n" unless $smtp;
  182 
  183         # SMTP SASL authentication (if necessary)
  184         if ($preferences{"smtp_username"} and $preferences{"smtp_password"}) {
  185             unless ($smtp->auth($preferences{"smtp_username"}, $preferences{"smtp_password"})) {
  186                 die "Error: authentication with the SMTP server failed with error code ".$smtp->status."\n";
  187             }
  188         }
  189 
  190         unless ($smtp->mail($preferences{"mail_from"})) {
  191             die "Error: the sending address was not accepted. Try setting the 'mail_from' variable to a valid email address in the configuration file\n";
  192         }
  193 
  194         my $ok = 1;
  195         $ok = $ok && $smtp->to($to);
  196         $ok = $ok && $smtp->data();
  197         $ok = $ok && $smtp->datasend("From: Email-Reminder <" . $preferences{"mail_from"} . ">\n");
  198         
  199         # Create an RFC822 compliant date (current time)
  200         my $rfc822_format = "%a, %d %b %Y %H:%M %z";
  201         my $today         = ParseDate("Now");
  202         my $rfc822_date = UnixDate($today,$rfc822_format);
  203         $ok = $ok && $smtp->datasend("Date: $rfc822_date\n");
  204         
  205         $ok = $ok && $smtp->datasend("To: $to\n");
  206         $ok = $ok && $smtp->datasend("Subject: =?utf-8?B?".encode_base64(encode("UTF-8", $subject), '')."?=\n");
  207         $ok = $ok && $smtp->datasend("Mime-Version: 1.0\n");
  208         $ok = $ok && $smtp->datasend("Content-Type: text/plain; charset=utf-8\n");
  209         $ok = $ok && $smtp->datasend("Content-Disposition: inline\n");
  210         $ok = $ok && $smtp->datasend("Content-Transfer-Encoding: quoted-printable\n");
  211         $ok = $ok && $smtp->datasend("\n");
  212         $ok = $ok && $smtp->datasend(encode_qp(encode("UTF-8", $message)));
  213         $ok = $ok && $smtp->dataend();
  214 
  215         $smtp->quit();
  216 
  217         die "Error: could not mail the reminder out\n" unless $ok;
  218     }
  219 
  220     return 1;
  221 }
  222 
  223 sub process_file
  224 {
  225     my $file = shift;
  226 
  227     print "==> Processing $file\n" if $verbose;
  228 
  229     my $list = EmailReminder::EventList->new($file);
  230 
  231     my @fullname = $list->get_user_name();
  232     my $user_fname = $fullname[0];
  233     my $user_lname = $fullname[1];
  234     my $user_name = $user_fname;
  235     $user_name .= " " . $user_lname if defined($user_lname);
  236     my $user_email = $list->get_user_email();
  237 
  238     foreach my $event ($list->get_events()) {
  239         print '--> Processing event '.$event->get_name()."\n" if $verbose;
  240 
  241         if ($event->is_occurring()) {
  242             print '--> Event '.$event->get_name()." is occurring\n" if $verbose;
  243 
  244             eval {
  245                 if (!process_event($event, $user_name, $user_email)) {
  246                     return;
  247                 }
  248             };
  249             if($@) {
  250                 print '!!! Error while sending reminder for '.$event->get_name()."\n" if $verbose;
  251 
  252                 my $msg = 'WARNING: Due to an error, the email reminder for Event "' . $event->get_name() .
  253                     '" cannot be processed and all I could do was to let you know that there was a problem.';
  254                 $msg .= "\n\n".'Since this event is OCCURRING TODAY, you should really check your reminders manually.';
  255                 $msg .= "\n\n".'Please forward this email to the email-reminder author so that this problem can be fixed in future versions:';
  256                 $msg .= "\n\n".'  Francois Marier <francois@fmarier.org>';
  257                 $msg .= "\n\n".'Thanks!';
  258                 $msg .= "\n\n--------------------------------------------------------------";
  259                 $msg .= EmailReminder::Utils::debug_info($event, 2);
  260                 my $subject = 'Email-reminder ERROR: ' . $event->get_name();
  261 
  262                 if (!send_email($msg, $subject, $user_name, $user_email)) {
  263                     return;
  264                 }
  265             }
  266         }
  267     }
  268 
  269     return 1;
  270 }
  271 
  272 # Send reminders for an event which is occurring
  273 sub process_event
  274 {
  275     my $event = shift;
  276     my $user_name = shift;
  277     my $user_email = shift;
  278 
  279     my $subject = $event->get_subject();
  280 
  281     my @recipients = @{$event->get_recipients()};
  282     if ($#recipients > -1) {
  283         foreach my $recipient (@recipients) {
  284             my $recipient_email = shift @{$recipient};
  285             my $recipient_fname = shift @{$recipient};
  286             my $recipient_lname = shift @{$recipient};
  287 
  288             my $recipient_name = $recipient_fname;
  289             $recipient_name .= " $recipient_lname" if defined($recipient_lname);
  290 
  291             my $msg = $event->get_message($recipient_fname);
  292             if ($msg && !send_email($msg, $subject, $recipient_name, $recipient_email)) {
  293                 return;
  294             }
  295         }
  296     } else {
  297         my $msg = $event->get_message($user_fname);
  298         if ($msg && !send_email($msg, $subject, $user_name, $user_email)) {
  299             return;
  300         }
  301     }
  302 }
  303 
  304 sub main
  305 {
  306     my $running_uid = $>;
  307     if (0 == $running_uid) {
  308         print STDERR "Warning: for security reasons, this script should not be not as root.\n";
  309     }
  310 
  311     my $spool_dir = $EmailReminder::Utils::SPOOL_DIRECTORY;
  312     if (-w $spool_dir) {
  313         # Iterate through all spooled files
  314         while (defined(my $file = glob("$spool_dir/*"))) {
  315             # Untaint filename
  316             if ($file =~ /^([A-Za-z_0-9\-\/]+)$/) {
  317                 $file = $1;
  318             } else {
  319                 print STDERR "Skipped unclean filename" if $verbose;
  320                 next;
  321             }
  322 
  323             unless (process_file($file, 0, 1)) {
  324                 return;
  325             }
  326 
  327             # Delete the file once we're done with it
  328             unless (unlink($file)) {
  329                 print STDERR "Could not remove $file.\n" if $verbose;
  330             }
  331         }
  332         return 1;
  333     } else {
  334         # Normal users only get to test their own reminders
  335         my @pwinfo = getpwuid($>);
  336         my $homedir = $pwinfo[7];
  337         my $file = "$homedir/" . $EmailReminder::Utils::USER_CONFIG_FILE;
  338 
  339         if (-e $file) {
  340             return process_file($file, 0, 1);
  341         } else {
  342             print STDERR "Warning: could not find your .email-reminders file.\n";
  343             return;
  344         }
  345     }
  346 }
  347 
  348 if ($help || $version) {
  349     print "send-reminders $EmailReminder::Utils::VERSION\n";
  350     if ($help) {
  351         print "\n";
  352         pod2usage(1);
  353     }
  354 } elsif ($preferences{"send_reminders"}) {
  355     unless (main()) {
  356         print STDERR "Could not send reminders.\n";
  357     }
  358 }