schedule/0040775000567100000120000000000010367553646012357 5ustar jcameronwheelschedule/images/0040775000567100000120000000000010147766255013622 5ustar jcameronwheelschedule/images/icon.gif0100644000567100000120000000334110147766255015235 0ustar jcameronwheelGIF89a00̿ƶŮɰ¯ðƫlllpppsssww{|||Ƕ¢ɹĭiiiyyyŨfff```ĵuvxMMM999333ttu000&&&ˤYYYLLL@@@μ~~\\\SSSֺ´߲䧩VVV϶҈FFFӪӰֵĿ_Κܣ__ ĵĺǴUU˥ɺrrLL뮮}&&!,00 H*\@Jd8@2(A *XI D0 B<@ 2Xа>@L!A"C '@ѡj &PqH`C2xB.^!kh(kB4#:vaW%.X$l?v(6>  "T RȉVq]y Lȑ >NvUd1`9Ht'l" $<o~@7J8/pxj?ިĈ4`p^>Y@I@^HJ,?]mn5PDY$`d PqѐAVXVD\Z8E N$@ ZlBZei\t^] A7(D_ [A@ $Cubр Q9f@OA\ @zrQh){U h JBaBDDxF$e&zMq6* l]AtqҀbYAA Ѱ C ^tA5p0u(vw!yl) ~u z\A b϶MA-`{pA8t MA 1}ػG _`p ԰kfH ;T oBdfºadDe!aHsLsH"4U@F["0"_4#JtqMCRU:KH2 %졆%TI&-,dߡ&UyX F'|R" z 46LBJ)@tEF ސ/oƼ\NssK32N3/깋MGW/7 r-4_oί|>co'VO[I8LH@;schedule/images/.xvpics/0040755000567100000120000000000010147766255015212 5ustar jcameronwheelschedule/images/.xvpics/icon.gif0100664000567100000120000000450210147766255016631 0ustar jcameronwheelP7 332 #IMGINFO:48x48 RGB (1761 bytes) #END_OF_COMMENTS 48 48 255 I$II۶IH%I۶%HI%۶ڶ%HIIڶ%HII۶I$II۶I$II۶IH%I۶%HI%۶ڶ%HIIڻ$I׶H%IIڷI$II۶IH%I۶%HI%۶ڶֺֻ׶EH)I׺I$II۶IH%I۶%HI%۶ڒֺڶ(EH)۶ַ۶I$II۶%H%I۶ڶ%HMnnqqڷڶ$I)D۶I$II۶%H%I۶ڶqr۶ڻֶ%HI)۶I$II۶%H%I۶ڶmnmnֺ$I)H۶I$II۶%H%I۶ڒriLmmmD)IEI$II۶IH%I۶%HnmmiֶI$II۶IH%I۶%HmqrI$II۶IH%I۶%mqmI$II۶IH%I۶%nqIimM׶۶I$II۶%H%I۶mnmnDI۶I$II۶%H%I۶mrMmqq(I۶I$II۶%H%IۖmqmIE(!qn%۶I$II۶%H%I۶mmq%DD$%mnqi(I$II۶IH%I۶ڷڒmmnH$$mImmImrַI$II۶IH%I۶ڷڒIImmnnmڒI$II۶IH%I۶ڷڒnInnmmnm۶mI$II۶IH%I۶%ۑmIImmnnmڶ۶I$II۶%H%IڶIqnnnmrmmImۖH%۶I$II۶%H%IڶnmmmnnHJnmnImI)۶ڷ۶ڷ۶ڷ۶۶nmnlnqmmnڶIH%۶ڷmnnnInmmnnۑ%HIIImmInmIm۶ەqMimnJlInmmڒIڶm%nqjlririmr۶ֻIImnmIm۶rrJLIiڷIےrmrڻֶuֻ۶׺YDI)۶ڷۺnJHI%۶8DI)۶mImInmm$IIIImnmImmnmImmnmImmnmImmInmmmmJmmmڷIImImmInmImmInmmmImmImIڷIImInmmmmImnmImmnmmImInmmmmImڷIImn۶۶I%H۶mImmnmImmInmmmmImInII$۶mImImImImImImH%I۶mImImImIHI%IImInmImInmmmmImImIn۶III۶I%H۶I$I۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$I۶I$II۶%H%I۶ڶ%HI%۶ڶ%HIIڶI$II۶HI$Ischedule/module.info0100664000567100000120000000044510367556161014514 0ustar jcameronwheeldesc=Scheduled Emails category=mail depends=mailbox cron usermin=1 longdesc=Schedule the automatic sending of email messages, either on a repeating schedule or a single date. desc_de=Zeitversetzter E-Mail-Versand desc_ru_RU= desc_ru_SU= version=1.191 schedule/lang/0040775000567100000120000000000010367271514013267 5ustar jcameronwheelschedule/lang/de0100644000567100000120000000264010207325645013575 0ustar jcameronwheeledit_addr=Andere E-Mail-Adresse edit_at=Datum und Zeit edit_bcc=BCC an (Blindkopie) edit_cc=CC an (Kopie) edit_cron=Unteren Zeitplan benutzen .. edit_enabled=Versand aktiviert? edit_from=Absender edit_header=Details des zeitversetzuten E-Mail-Versandes edit_mail=Nachrichtentext edit_mailfile=Nehme Text aus dieser Datei edit_mode=Zeitpunkt edit_self=Ihre E-Mail-Adresse: ($1) edit_subject=Nachrichtenbetreff edit_title1=Erzeuge zeitversetzten E-Mail-Versand edit_title2=Bearbeite zeitversetzten E-Mail-Versand edit_to=Sende an index_add=Einen neuen zeitversetzten E-Mail-Versand erzeugen index_clear=Lösche versandte E-Mails index_cleardesc=Klicken Sie auf diesen Button, um alle E-Mails, die für einen einmaligen Versand vorgesehen waren und die abgearbeitet wurden, zu löschen. index_enabled=Aktiviert? index_none=Sie haben noch keinen zeitversetzten E-Mail-Versand eingerichtet. index_ran=Gesendet index_return=Liste des zeitversetzten E-Mail-Versandes index_self=Sich selbst index_subject=Nachrichtenbetreff index_title=Zeitversetzter E-Mail-Versand index_to=Sende an index_when=Sende um save_eat=Fehlender oder ungültiger Zeitpunkt für den Versand save_efrom=Fehlende Absender-E-Mail-Adresse save_emailfile=Fehlende oder ungültige Textdatei save_err=Konnte zeitversetzten E-Mail-Versand nicht speichern save_esubject=Fehlender Nachrichtenbetreff save_eto=Fehlende Empfänger-E-Mail-Adresse schedule/lang/en0100664000567100000120000000233510367271514013614 0ustar jcameronwheelindex_title=Scheduled Emails index_none=You have not created any scheduled email messages yet. index_add=Add a new scheduled email. index_subject=Email subject index_when=Send at index_to=Send to index_enabled=Enabled? index_self=Yourself index_return=email list index_ran=Sent index_clear=Clear Sent Email index_cleardesc=Click this button to delete all scheduled emails that were set for a single time and have already been sent. edit_title1=Create Scheduled Email edit_title2=Edit Scheduled Email edit_header=Scheduled email message details edit_subject=Message subject edit_to=Send to edit_cc=Cc to edit_bcc=Bcc to edit_self=Your address ($1) edit_addr=Other address edit_from=Send from edit_mail=Message text edit_mailfile=Get text from file edit_enabled=Sending enabled? edit_mode=Send at edit_at=Time and date edit_cron=Recurring schedule below .. edit_files=Attached files edit_file=Filename edit_type=Source edit_uploaded=Uploaded edit_upload=Attach a file save_err=Failed to save scheduled email save_esubject=Missing message subject save_eto=Missing send to address save_emailfile=Missing or invalid message text file save_efrom=Missing send from address save_eat=Missing or invalid time to run at view_efile=File no longer exists schedule/lang/ru_RU0100644000567100000120000000210510320214556014227 0ustar jcameronwheelindex_title= index_none= . index_add= . index_subject= index_when= : index_to=: index_enabled=? index_self= index_return= index_ran= index_clear= index_cleardesc= , . edit_title1= edit_title2= edit_header= edit_subject= edit_to= edit_cc= edit_bcc=2 edit_self= ($1) edit_addr= edit_from= edit_mail= edit_mailfile= edit_enabled= ? edit_mode= edit_at= edit_cron= save_err= save_esubject= save_eto= save_emailfile= save_efrom= save_eat= schedule/lang/it0100644000567100000120000000207310336470025013615 0ustar jcameronwheelindex_title=invio email a scadenza index_none=non esistono email da inviare a scadenza index_add=crea nuova email a scadenza index_subject=oggetto index_when=invia da index_to=invia a index_enabled=abilitata? index_self=tes tesso index_return=lista indirizzi index_ran=inviata index_clear=elimina messaggi inviati index_cleardesc=click qui per eliminare tutte le email a scadenza impostate per n solo invio, gia' effettauto edit_title1=crea email a scadenza edit_title2=modifica email a scadenza edit_header=dettagli email a scadenza edit_subject=oggetto edit_to=invia a edit_cc=Cc edit_bcc=Bcc edit_self=te stesso ($1) edit_addr=altri indirizzi edit_from=inviato da edit_mail=messaggio edit_mailfile=leggi messaggio da file edit_enabled=invio abilitato? edit_mode=invia a edit_at=ora e data edit_cron=ripeti invio come sotto .. save_err=Failed to save scheduled email save_esubject=oggetto mancante save_eto=indirizzo destinatario mancante save_emailfile=testo mancant o non valido save_efrom=indirizzo destinataraio mancante save_eat=orario di invio mancante o non corretto schedule/atmode.pl0100775000567100000120000000073310151526354014153 0ustar jcameronwheel#!/usr/local/bin/perl # Check for one-off scheduled emails that have not run yet $no_acl_check++; $ENV{'REMOTE_USER'} = getpwuid($<); require './schedule-lib.pl'; $now = time(); foreach $s (&list_schedules()) { if ($s->{'at'} && $s->{'at'} <= $now && (!$s->{'ran'} || $s->{'ran'} < $s->{'at'})) { # Can run this one if ($s->{'enabled'}) { $mail = &make_email($s); &mailbox::send_mail($mail); $s->{'ran'} = $s->{'at'}; &save_schedule($s); } } } schedule/schedule-lib.pl0100664000567100000120000001514010367553646015252 0ustar jcameronwheel# Functions for scheduled email notification do '../web-lib.pl'; &init_config(); $cron_cmd = "$module_config_directory/email.pl"; $atmode_cmd = "$module_config_directory/atmode.pl"; if (!-x $cron_cmd && $< == 0) { &create_wrapper($cron_cmd, $module_name, "email.pl"); } if (!-x $atmode_cmd && $< == 0) { &create_wrapper($atmode_cmd, $module_name, "atmode.pl"); } &switch_to_remote_user(); &create_user_config_dirs(); &foreign_require("cron", "cron-lib.pl"); &foreign_require("mailbox", "mailbox-lib.pl"); do '../ui-lib.pl'; use Time::Local; $schedules_dir = "$user_module_config_directory/schedules"; $messages_dir = "$user_module_config_directory/messages"; $files_dir = "$user_module_config_directory/files"; $old_cron_cmd = "$user_module_config_directory/email.pl"; $old_atmode_cmd = "$user_module_config_directory/atmode.pl"; # list_schedules() # Returns a list of all scheduled messages sub list_schedules { local @rv; opendir(DIR, $schedules_dir); foreach $f (readdir(DIR)) { next if ($f eq "." || $f eq ".."); local $sched = &get_schedule($f); push(@rv, $sched) if ($sched); } closedir(DIR); return @rv; } # get_schedule(id) sub get_schedule { local $file = "$schedules_dir/$_[0]"; local %sched; &read_file($file, \%sched); $sched{'id'} = $_[0]; $sched{'file'} = $file; $sched{'mfile'} = "$messages_dir/$_[0]"; open(MAIL, $sched{'mfile'}); while() { $sched{'mail'} .= $_; } close(MAIL); return \%sched; } # save_schedule(&sched) sub save_schedule { mkdir($schedules_dir, 0700) if (!-d $schedules_dir); mkdir($messages_dir, 0700) if (!-d $messages_dir); $_[0]->{'id'} ||= time().$$; local $file = $_[0]->{'file'} || "$schedules_dir/$_[0]->{'id'}"; local %copy = %{$_[0]}; delete($copy{'mail'}); &write_file($file, \%copy); local $mfile = $_[0]->{'mfile'} || "$messages_dir/$_[0]->{'id'}"; &open_tempfile(MAIL, ">$mfile"); &print_tempfile(MAIL, $_[0]->{'mail'}); &close_tempfile(MAIL); } # delete_schedule(&sched) sub delete_schedule { unlink($_[0]->{'file'}); unlink($_[0]->{'mfile'}); system("rm -rf ".quotemeta("$files_dir/$_[0]->{'id'}")); } # list_schedule_files(&sched) # Returns a list of files attached to a scheduled email sub list_schedule_files { local ($sched) = @_; return ( ) if (!$sched->{'id'}); local @rv; opendir(DIR, "$files_dir/$sched->{'id'}"); foreach my $f (readdir(DIR)) { next if ($f eq "." || $f eq ".."); local $path = "$files_dir/$sched->{'id'}/$f"; if (-l $path) { # A server-side file push(@rv, { 'file' => readlink($path), 'id' => $f, 'type' => 0 }); } else { # An uploaded file push(@rv, { 'file' => $path, 'id' => $f, 'type' => 1 }); } } closedir(DIR); return sort { lc($a->{'id'}) cmp lc($b->{'id'}) } @rv; } # create_schedule_file(&sched, path|data, uploaded-filename) # Adds a file to a scheduled email sub create_schedule_file { local ($sched, $path, $uploaded) = @_; mkdir($files_dir, 0700) if (!-d $files_dir); mkdir("$files_dir/$sched->{'id'}", 0700) if (!-d "$files_dir/$sched->{'id'}"); if ($uploaded) { $uploaded =~ s/^(.*)[\/\\]//; &open_tempfile(FILE, ">$files_dir/$sched->{'id'}/$uploaded"); &print_tempfile(FILE, $path); &close_tempfile(FILE); } else { local $short = $path; $short =~ s/^(.*)[\/\\]//; symlink($path, "$files_dir/$sched->{'id'}/$short"); } } # delete_schedule_file(&sched, &file) sub delete_schedule_file { local ($sched, $file) = @_; unlink("$files_dir/$sched->{'id'}/$file->{'id'}"); } # find_cron_job(&sched) # Finds the cron job for some scheduled email sub find_cron_job { local @jobs = &cron::list_cron_jobs(); local ($job) = grep { $_->{'user'} eq $remote_user && ($_->{'command'} eq "$cron_cmd $_[0]->{'id'}" || $_->{'command'} eq "$old_cron_cmd $_[0]->{'id'}") } @jobs; return $job; } # my_email_address([with-name]) sub my_email_address { local ($froms, $doms) = &mailbox::list_from_addresses(); if (@$froms) { local ($fp) = &mailbox::split_addresses($froms->[0]); if ($fp) { return $_[0] ? $fp->[2] : $fp->[0]; } } return $remote_user.'@'.&get_system_hostname(); } # create_atmode_job() # If any jobs exist that are scheduled at a specific time, create a cron job # to check for them once per minute sub create_atmode_job { local @ats = grep { $_->{'at'} } &list_schedules(); if (@ats) { local @jobs = &cron::list_cron_jobs(); local ($badjob) = grep { $_->{'user'} eq $remote_user && $_->{'command'} eq $old_atmode_cmd } @jobs; if ($badjob) { &cron::delete_cron_job($badjob); } local ($job) = grep { $_->{'user'} eq $remote_user && $_->{'command'} eq $atmode_cmd } @jobs; if (!$job) { local @mins = map { $_*5 } (0 .. 11); $job = { 'command' => $atmode_cmd, 'user' => $remote_user, 'active' => 1, 'mins' => join(",", @mins), 'hours' => '*', 'days' => '*', 'months' => '*', 'weekdays' => '*' }; &cron::create_cron_job($job); } } } # make_email(&schedule) sub make_email { local ($sched) = @_; local $myaddr = &my_email_address(1); local $data = $sched->{'mail'}; if ($config{'attach'} && $sched->{'mailfile'}) { open(FILE, $sched->{'mailfile'}); while() { $data .= $_; } close(FILE); } local @attach; foreach my $file (&list_schedule_files($sched)) { local $type = &guess_mime_type($file->{'id'}, "application/octet-stream"). "; name=\"$file->{'id'}\""; local $disp = "inline; filename=\"$file->{'id'}\""; push(@attach, { 'headers' => [ [ 'Content-type', $type ], [ 'Content-Disposition', $disp ], [ 'Content-Transfer-Encoding', 'base64' ] ], 'data' => &read_file_contents($file->{'file'}) }); } return { 'headers' => [ [ 'From' => $sched->{'from'} || $myaddr ], [ 'To' => &mailbox::expand_to($sched->{'to'}) || $myaddr ], [ 'Cc' => &mailbox::expand_to($sched->{'cc'}) ], [ 'Bcc' => &mailbox::expand_to($sched->{'bcc'}) ], [ 'Subject' => $sched->{'subject'} ] ], 'attach' => [ { 'headers' => [ [ 'Content-type', 'text/plain' ] ], 'data' => $data }, @attach ] }; } # create_wrapper(wrapper-path, module, script) # Creates a wrapper script which calls a script in some module's directory # with the proper webmin environment variables set. Copied from the cron module, # so that it can be called before requireing cron-lib.pl sub create_wrapper { local $perl_path = &get_perl_path(); &open_tempfile(CMD, ">$_[0]"); &print_tempfile(CMD, <) { \$root = \$1 if (/^root=(.*)/); } close(CONF); \$ENV{'WEBMIN_CONFIG'} = "$ENV{'WEBMIN_CONFIG'}"; \$ENV{'WEBMIN_VAR'} = "$ENV{'WEBMIN_VAR'}"; chdir("\$root/$_[1]"); exec("\$root/$_[1]/$_[2]", \@ARGV) || die "Failed to run \$root/$_[1]/$_[2] : \$!"; EOF ); &close_tempfile(CMD); chmod(0755, $_[0]); } 1; schedule/index.cgi0100775000567100000120000000233310173307116014133 0ustar jcameronwheel#!/usr/local/bin/perl # Show all scheduled messages require './schedule-lib.pl'; &ui_print_header(undef, $text{'index_title'}, "", undef, 0, 1); @scheds = &list_schedules(); if (@scheds) { print "$text{'index_add'}
\n"; print &ui_columns_start([ $text{'index_subject'}, $text{'index_when'}, $text{'index_to'}, $text{'index_enabled'} ], 100); foreach $s (@scheds) { if ($s->{'at'}) { $when = localtime($s->{'at'}); } else { $when = &cron::when_text($s, 1); } print &ui_columns_row([ "". $s->{'subject'}."", $when, &html_escape($s->{'to'}) || $text{'index_self'}, $s->{'at'} && $s->{'ran'} >= $s->{'at'} ? $text{'index_ran'} : $s->{'enabled'} ? $text{'yes'} : $text{'no'} ]); $sent++ if ($s->{'at'} && $s->{'ran'} >= $s->{'at'}); } print &ui_columns_end(); } else { print "$text{'index_none'}

\n"; } print "$text{'index_add'}

\n"; if ($sent) { print "


\n"; print &ui_buttons_start(); print &ui_buttons_row("clear.cgi", $text{'index_clear'}, $text{'index_cleardesc'}); print &ui_buttons_end(); } &ui_print_footer("/", $text{'index'}); schedule/edit.cgi0100775000567100000120000000734610367272036013771 0ustar jcameronwheel#!/usr/local/bin/perl # Show a form to create or edit a scheduled email require './schedule-lib.pl'; &ReadParse(); if ($in{'new'}) { &ui_print_header(undef, $text{'edit_title1'}, ""); $sched = { 'enabled' => 1, 'at' => time() }; } else { &ui_print_header(undef, $text{'edit_title2'}, ""); $sched = &get_schedule($in{'id'}); } print &ui_form_start("save.cgi", "form-data"); print &ui_hidden("new", $in{'new'}),"\n"; print &ui_hidden("id", $in{'id'}),"\n"; print &ui_table_start($text{'edit_header'}, "width=100%", 2); print &ui_table_row($text{'edit_subject'}, &ui_textbox("subject", $sched->{'subject'}, 50)); $myaddr = &my_email_address(); if ($mailbox::config{'edit_from'} == 1) { # From address field, if allowed print &ui_table_row($text{'edit_from'}, &ui_radio("from_def", $sched->{'from'} ? 0 : 1, [ [ 1, &text('edit_self', $myaddr)."
" ], [ 0, $text{'edit_addr'} ] ])."\n". &ui_textbox("from", $sched->{'from'}, 30)." ". &mailbox::address_button("from", 0, 1)); } # To address print &ui_table_row($text{'edit_to'}, &ui_radio("to_def", $sched->{'to'} ? 0 : 1, [ [ 1, &text('edit_self', $myaddr)."
" ], [ 0, $text{'edit_addr'} ] ])."\n". &ui_textbox("to", $sched->{'to'}, 60)." ". &mailbox::address_button("to", 0)); # Cc and Bcc addresses print &ui_table_row($text{'edit_cc'}, &ui_textbox("cc", $sched->{'cc'}, 60)." ". &mailbox::address_button("cc", 0)); print &ui_table_row($text{'edit_bcc'}, &ui_textbox("bcc", $sched->{'bcc'}, 60)." ". &mailbox::address_button("bcc", 0)); print &ui_table_row($text{'edit_mail'}, &ui_textarea("mail", $sched->{'mail'}, 8, 70)."
". ($config{'attach'} ? &ui_checkbox("mail_def", 1, $text{'edit_mailfile'}, $sched->{'mailfile'} ? 1 : 0)."\n". &ui_textbox("mailfile", $sched->{'mailfile'}, 40)."\n". &file_chooser_button("mailfile") : "")); print &ui_table_hr(); if ($config{'upload'}) { # Attached files @files = &list_schedule_files($sched); if (@files) { $ftable = &ui_columns_start([ $text{'delete'}, $text{'edit_file'}, $text{'edit_type'} ]); foreach $f (@files) { $ftable .= &ui_columns_row([ &ui_checkbox("d", $f->{'id'}), "".&html_escape($f->{'id'})."", !$f->{'type'} ? "$f->{'file'}" : $text{'edit_uploaded'} ]); } $ftable .= &ui_columns_end(); print &ui_table_row($text{'edit_files'}, $ftable); } # Form to add a file print &ui_table_row($text{'edit_upload'}, &ui_upload("upload", 60)); } print &ui_table_hr(); print &ui_table_row($text{'edit_enabled'}, &ui_radio("enabled", $sched->{'enabled'}, [ [ 1, $text{'yes'} ], [ 0, $text{'no'} ] ])); @tm = $sched->{'at'} ? localtime($sched->{'at'}) : ( ); if (@tm) { $tm[1] = sprintf("%2.2d", $tm[1]); $tm[2] = sprintf("%2.2d", $tm[2]); $tm[3] = sprintf("%2.2d", $tm[3]); $tm[4] += 1; $tm[5] += 1900; } print &ui_table_row($text{'edit_mode'}, &ui_oneradio("mode", 1, $text{'edit_at'}, $sched->{'at'} ? 1 : 0)."\n". &ui_textbox("hour", $tm[2], 3).":". &ui_textbox("min", $tm[1], 3)."     ". &ui_date_input($tm[3], $tm[4], $tm[5], "day", "month", "year")." ". &date_chooser_button("day", "month", "year")."
". &ui_oneradio("mode", 0, $text{'edit_cron'}, $sched->{'at'} ? 0 : 1)); print " \n"; &cron::show_times_input($sched); print "
\n"; print &ui_table_end(); print &ui_form_end($in{'new'} ? [ [ "create", $text{'create'} ] ] : [ [ "save", $text{'save'} ], [ "delete", $text{'delete'} ] ], "100%"); &ui_print_footer("", $text{'index_return'}); schedule/email.pl0100775000567100000120000000052110264204143013756 0ustar jcameronwheel#!/usr/local/bin/perl # Send a scheduled email $no_acl_check++; $ENV{'REMOTE_USER'} = getpwuid($<); require './schedule-lib.pl'; $sched = &get_schedule($ARGV[0]); $sched->{'id'} || die "Invalid scheduled email!"; if ($sched->{'enabled'}) { # Construct and send the email $mail = &make_email($sched); &mailbox::send_mail($mail); } schedule/save.cgi0100775000567100000120000000500010367272050013757 0ustar jcameronwheel#!/usr/local/bin/perl # Create, update or delete a scheduled mail require './schedule-lib.pl'; &ReadParseMime(); if (!$in{'new'}) { $sched = &get_schedule($in{'id'}); $cron = &find_cron_job($sched); } else { $sched = { }; } if ($in{'delete'}) { # Just remove schedule &delete_schedule($sched); &cron::delete_cron_job($cron) if ($cron); } else { # Validate and store inputs &error_setup($text{'save_err'}); $in{'subject'} || &error($text{'save_esubject'}); $sched->{'subject'} = $in{'subject'}; $in{'mail'} =~ s/\r//g; if ($in{'mail'} =~ /\S/ && $in{'mail'} !~ /\n$/) { $in{'mail'} .= "\n"; } $sched->{'mail'} = $in{'mail'}; if ($config{'attach'}) { if ($in{'mail_def'}) { -r $in{'mailfile'} || &error($text{'save_emailfile'}); $sched->{'mailfile'} = $in{'mailfile'}; } else { $sched->{'mailfile'} = undef; } } if ($in{'to_def'}) { delete($sched->{'to'}); } else { $in{'to'} || &error($text{'save_eto'}); $sched->{'to'} = $in{'to'}; } if ($mailbox::config{'edit_from'} == 1) { if ($in{'from_def'}) { delete($sched->{'from'}); } else { $in{'from'} || &error($text{'save_efrom'}); $sched->{'from'} = $in{'from'}; } } $sched->{'cc'} = $in{'cc'}; $sched->{'bcc'} = $in{'bcc'}; $sched->{'enabled'} = $in{'enabled'}; if ($in{'mode'} == 1) { # At time eval { $sched->{'at'} = timelocal(0, $in{'min'}, $in{'hour'}, $in{'day'}, $in{'month'}-1, $in{'year'}-1900) }; $@ && &error($text{'save_eat'}); } else { # Cron time delete($sched->{'at'}); &cron::parse_times_input($sched, \%in); } # Create or update the schedule &save_schedule($sched); &cron::delete_cron_job($cron) if ($cron); if (!$sched->{'at'}) { $job = { "command" => "$cron_cmd $sched->{'id'}", "user" => $remote_user, "active" => 1, "special" => $sched->{'special'}, "mins" => $sched->{'mins'}, "hours" => $sched->{'hours'}, "days" => $sched->{'days'}, "months" => $sched->{'months'}, "weekdays" => $sched->{'weekdays'} }; &cron::create_cron_job($job); } if ($config{'upload'}) { # Add an attached file if ($in{'upload'}) { &create_schedule_file($sched, $in{'upload'}, $in{'upload_filename'} || "unknown"); } # Remove deleted files @files = &list_schedule_files($sched); foreach $d (split(/\0/, $in{'d'})) { ($file) = grep { $_->{'id'} eq $d } @files; &delete_schedule_file($sched, $file) if ($file); } } } # If this is a one-off job, make sure a cron job exists to detect them &create_atmode_job(); &redirect(""); schedule/CHANGELOG0100664000567100000120000000063610367272007013560 0ustar jcameronwheel---- Changes since 1.100 ---- First version of this module, which can set up automatic email messages sent on a repeating schedule or single date. ---- Changes since 1.110 ---- Added option to send message from a file. ---- Changes since 1.130 ---- Email to groups defined in the Read Mail module now works. ---- Changes since 1.180 ---- Attachments (such as images or documents) can be added to scheduled emails. schedule/config.info0100664000567100000120000000014010367267523014465 0ustar jcameronwheelattach=Allow email contents from a file?,1,1-Yes,0-No upload=Allow attached files?,1,1-Yes,0-No schedule/clear.cgi0100775000567100000120000000042710173307073014116 0ustar jcameronwheel#!/usr/local/bin/perl # Clear all sent emails require './schedule-lib.pl'; foreach $s (&list_schedules()) { if ($s->{'at'} && $s->{'ran'} >= $s->{'at'}) { &delete_schedule($s); $cron = &find_cron_job($s); &cron::delete_cron_job($cron) if ($cron); } } &redirect(""); schedule/config0100664000567100000120000000002210367267526013535 0ustar jcameronwheelattach=1 upload=1 schedule/view.cgi0100664000567100000120000000060410367271672014006 0ustar jcameronwheel#!/usr/local/bin/perl # Show an attached file require './schedule-lib.pl'; &ReadParse(); $sched = &get_schedule($in{'sched'}); @files = &list_schedule_files($sched); ($file) = grep { $_->{'id'} eq $in{'id'} } @files; $file || &error($text{'view_efile'}); print "Content-type: ",&guess_mime_type($file->{'id'}),"\n\n"; open(FILE, $file->{'file'}); while() { print; } close(FILE);