Parent Directory
|
Revision Log
profSendMail now always ends with a message listing all email that was not sent and the reason. It will no longer just die with an internal error message.
1 #!/usr/local/bin/webwork-perl 2 3 ## This file is profSendMail.pl 4 ## It provides a utility for professors to send mail to one or more students 5 ## using individualized emails or mass emails 6 7 use lib '.'; use webworkInit; # WeBWorKInitLine 8 9 use Global; 10 use CGI qw(:standard); 11 use Auth; 12 use Net::SMTP; 13 use HTML::Entities; 14 use strict; 15 16 #begin Timing code 17 use Benchmark; 18 my $beginTime = new Benchmark; 19 #end Timing code 20 21 my $cgi = new CGI; 22 my %inputs = $cgi->Vars(); 23 24 #for use in strings where $cgi->param is not interpolated correctly or at all 25 my $course = $cgi->param('course'); 26 my $user = $cgi->param('user'); 27 my $session_key = $cgi->param('key'); 28 my $openfilename = $cgi->param('openfilename'); 29 30 &Global::getCourseEnvironment($course); 31 32 my $scriptDirectory = $Global::scriptDirectory; 33 my $databaseDirectory = $Global::databaseDirectory; 34 my $htmlURL = $Global::htmlURL; 35 my $cgiURL = $Global::cgiWebworkURL; 36 my $courseScriptsDirectory = $Global::courseScriptsDirectory; 37 my $templateDirectory = getCourseTemplateDirectory; 38 my $emailDirectory = getCourseEmailDirectory; 39 my $scoringDirectory = getCourseScoringDirectory; 40 my $feedbackAddress = $Global::feedbackAddress; 41 my $defaultFrom = $Global::defaultFrom; 42 my $defaultReply = $Global::defaultReply; 43 my $smtpSender = $Global::smtpSender; 44 my $defaultClasslistFile = getCourseClasslistFile($course); 45 my $default_msg = 'default.msg'; 46 my $old_default_msg = 'default_old.msg'; 47 my $practiceUser = $Global::practiceUser; 48 49 require "${scriptDirectory}$Global::classlist_DBglue_pl"; 50 require "${scriptDirectory}$Global::HTMLglue_pl"; 51 require "${scriptDirectory}$Global::FILE_pl"; 52 53 # log access 54 &Global::log_info('', query_string); 55 56 my $permissionsFile = &Global::getCoursePermissionsFile($course); 57 my $permissions = &get_permissions($user, $permissionsFile); 58 my $keyFile = &Global::getCourseKeyFile($course); 59 60 61 #verify session key 62 &verify_key($user, $session_key, "$keyFile", $course); 63 64 #verify permissions are correct 65 if (($permissions != $Global::instructor_permissions) and ($permissions != $Global::TA_permissions) ) { 66 print "permissions = $permissions instructor_permissions = $Global::instructor_permissions\n"; 67 print &html_NO_PERMISSION; 68 exit(0); 69 } 70 71 #user macros that can be used in the email message 72 my $SID = ''; 73 my $FN = ''; 74 my $LN = ''; 75 my $SECTION = ''; 76 my $RECITATION = ''; 77 my $STATUS = ''; 78 my $EMAIL = ''; 79 my $LOGIN = ''; 80 my @COL = (); 81 82 my $endCol; 83 84 #hashes to hold student info 85 my %fn = (); 86 my %ln = (); 87 my %section = (); 88 my %recitation = (); 89 my %status = (); 90 my %email = (); 91 my %login = (); 92 93 #timeout parameters 94 my $timeout_sec = 15; 95 my $max_timeout_attempts = 3; 96 my $timeout_attempts = 0; 97 98 99 #keep track of email sent and not sent 100 my $emails_sent = 0; 101 my $emails_not_sent = 0; 102 103 #array for bad email addresses 104 my @bad_email_addresses = (); 105 my @unknown_problem = (); 106 my @timeout_problem = (); 107 my @exceeded_max_timeout = (); 108 my @no_record = (); 109 110 # get format information 111 112 my $format = (defined($cgi->param('format'))) ? $cgi->param('format') : 'alph'; 113 114 #get information from the classlist data base 115 my $availableStudents_ref; 116 if ((defined $format) and ($format eq 'section')) { 117 $availableStudents_ref = getAllLoginNamesSortedBySectionThenByName(); 118 } 119 elsif ((defined $format) and ($format eq 'recitation')) { 120 $availableStudents_ref = getAllLoginNamesSortedByRecitationThenByName(); 121 } 122 else { 123 $availableStudents_ref = getAllLoginNamesSortedByName(); 124 } 125 126 my @availableStudents = @$availableStudents_ref; 127 128 #my %loginName_StudentID_Hash = %{getLoginName_StudentID_Hash()}; 129 my %studentID_LoginName_Hash = %{getStudentID_LoginName_Hash()}; 130 131 132 133 #make sure message file was submitted and exists 134 my $messageFileName; 135 if (defined($openfilename) && -e "${emailDirectory}$openfilename") { 136 if ( -R "${emailDirectory}$openfilename") { 137 $messageFileName = $openfilename; 138 } else { 139 wwerror ('File is not readable', "The file 140 ${emailDirectory}$openfilename 141 is not readable by the webserver. Check that it's permissions are set correctly."); 142 } 143 } else { 144 $messageFileName = $default_msg; 145 } 146 147 148 #get row and column info if submitted 149 my $rows = (defined($cgi->param('rows'))) ? $cgi->param('rows') : $Global::editor_window_rows; 150 my $columns = (defined($cgi->param('columns'))) ? $cgi->param('columns') : $Global::editor_window_columns; 151 152 #Deal with filled out forms and various actions resulting from different buttons 153 if ( defined($cgi->param('action')) ) { 154 if (defined($cgi->param('savefilename'))) { 155 &user_error("For security reasons, you cannot save a message in any directory higher than the email directory. Please specify a file name to save under.") if ($cgi->param('savefilename') =~ /^[~.]/ || $cgi->param('savefilename') =~ /\.\./); 156 } 157 158 #if Save button was clicked 159 if (( $cgi->param('action') eq 'Save') && defined($cgi->param('body')) && defined($cgi->param('savefilename'))) { 160 161 my $temp_body = $cgi->param('body'); 162 $temp_body =~ s/\r\n/\n/g; 163 $temp_body = "From: " . $cgi->param('from') . "\n" . 164 "Reply-To: " . $cgi->param('replyTo') . "\n" . 165 "Subject: " . $cgi->param('subject') . "\n" . 166 "Message: \n" . $temp_body; 167 168 saveProblem($temp_body, $cgi->param('savefilename')); 169 $messageFileName = $cgi->param('savefilename'); 170 171 #if Save As button was clicked 172 } elsif (( $cgi->param('action') eq 'Save as') && defined($cgi->param('body')) && defined($cgi->param('savefilename'))) { 173 174 $messageFileName = $cgi->param('savefilename'); 175 176 if ($messageFileName =~ /^[~.]/ || $messageFileName =~ /\.\./) { 177 &user_error("For security reasons, you cannot specify a merge file from a directory higher than the email directory (you can't use ../blah/blah). Please specify a different file or move the needed file to the email directory"); 178 } 179 180 181 my $temp_body = $cgi->param('body'); 182 $temp_body =~ s/\r\n/\n/g; 183 $temp_body = "From: " . $cgi->param('from') . "\n" . 184 "Reply-To: " . $cgi->param('replyTo') . "\n" . 185 "Subject: " . $cgi->param('subject') . "\n" . 186 "Message: \n" . $temp_body; 187 188 saveNewProblem($temp_body, $messageFileName); 189 190 #if Save As Default button was clicked 191 } elsif (( $cgi->param('action') eq 'Save as Default') && defined($cgi->param('body'))) { 192 193 my $temp_body; 194 $temp_body = $cgi->param('body'); 195 $temp_body =~ s/\r\n/\n/g; 196 197 #get default.msg and back it up in default.old.msg 198 open DEFAULT, "$emailDirectory$default_msg"; 199 $temp_body = <DEFAULT>; 200 close DEFAULT; 201 202 if ( -e "$emailDirectory$old_default_msg") { 203 saveProblem($temp_body, $old_default_msg); 204 } else { 205 saveNewProblem($temp_body, $old_default_msg); 206 } 207 208 #save new default message as default.msg 209 $temp_body = $cgi->param('body'); 210 $temp_body =~ s/\r\n/\n/g; 211 $temp_body = "From: " . $cgi->param('from') . "\n" . 212 "Reply-To: " . $cgi->param('replyTo') . "\n" . 213 "Subject: " . $cgi->param('subject') . "\n" . 214 "Message: \n" . $temp_body; 215 216 saveProblem($temp_body, $default_msg); 217 $messageFileName = $default_msg; 218 219 #if Send Email button was clicked 220 } elsif ( $cgi->param('action') eq 'Send Email' ) { 221 222 my @studentID = (); 223 224 if ($cgi->param('To') eq 'classList' && defined($cgi->param('classList')) && $cgi->param('classList') ne 'None') { 225 my $classlist = $cgi->param('classList'); 226 my $classListFile = "$templateDirectory$classlist"; 227 my @classList = (); 228 checkClasslistFile($Global::noOfFieldsInClasslist,$classListFile); 229 open(FILE, "$classListFile") || die "can't open $classListFile"; 230 @classList=<FILE>; 231 close(FILE); 232 233 foreach (@classList) { ## read through classlist and send e-mail 234 ## message to all active students 235 unless ($_ =~ /\S/) {next;} ## skip blank lines 236 chomp; 237 my @classListRecord=&getRecord($_); 238 my ($studentID, $lastName, $firstName, $status, $comment, $section, $recitation, $email_address, $login_name) 239 = @classListRecord; 240 unless (&dropStatus($status)) { 241 push (@studentID, $studentID); 242 $fn{$studentID} = $firstName; 243 $ln{$studentID} = $lastName; 244 $section{$studentID} = $section; 245 $recitation{$studentID} = $recitation; 246 $status{$studentID} = $status; 247 $email{$studentID} = $email_address; 248 $login{$studentID} = $login_name; 249 } 250 } 251 } 252 elsif ($cgi->param('To') eq 'studentID' && defined($cgi->param('studentID'))) { 253 @studentID = $cgi->param('studentID'); 254 my ($studentID, $login_name); 255 256 foreach $studentID (@studentID) { 257 $login_name = $studentID_LoginName_Hash{$studentID}; 258 &attachCLRecord($login_name); 259 $fn{$studentID} = CL_getStudentFirstName($login_name); 260 $ln{$studentID} = CL_getStudentLastName($login_name); 261 $section{$studentID} = CL_getClassSection($login_name); 262 $recitation{$studentID} = CL_getClassRecitation($login_name); 263 $status{$studentID} = CL_getStudentStatus($login_name); 264 $email{$studentID} = CL_getStudentEmailAddress($login_name); 265 $login{$studentID} = $login_name; 266 } 267 268 } 269 elsif ($cgi->param('To') eq 'all_students') { 270 @studentID = (); 271 my ($studentID, $login_name, $status); 272 273 foreach $login_name (@availableStudents) { 274 &attachCLRecord($login_name); 275 $status = CL_getStudentStatus($login_name); 276 next if &dropStatus($status); 277 $studentID = CL_getStudentID($login_name); 278 push(@studentID,$studentID); 279 280 $fn{$studentID} = CL_getStudentFirstName($login_name); 281 $ln{$studentID} = CL_getStudentLastName($login_name); 282 $section{$studentID} = CL_getClassSection($login_name); 283 $recitation{$studentID} = CL_getClassRecitation($login_name); 284 $status{$studentID} = CL_getStudentStatus($login_name); 285 $email{$studentID} = CL_getStudentEmailAddress($login_name); 286 $login{$studentID} = $login_name; 287 } 288 } 289 else { 290 &user_error('You didn\'t select any recipients. Make sure you select either all student in the course, individual students or a whole classlist.'); 291 } 292 293 my $mergeFile = ''; 294 295 #the radio button named 'merge' determines whether to take the selected mergefile 296 #or one that was typed in. A error message is given if select one and use the other 297 $mergeFile = $scoringDirectory . $cgi->param('mergeFiles') 298 if ($cgi->param('merge') eq 'mergeFiles' && defined($cgi->param('mergeFiles')) && $cgi->param('mergeFiles') ne 'None'); 299 300 $mergeFile = $templateDirectory . $cgi->param('mergeFile') 301 if ($cgi->param('merge') eq 'mergeFile' && defined($cgi->param('mergeFile')) && $cgi->param('mergeFile') !~ m|/$|); #does not end in a / 302 303 if ($mergeFile =~ /^[~.]/ || $mergeFile =~ /\.\./) { 304 &user_error("For security reasons, you cannot specify a merge file from a directory higher than the email directory. Please specify a different file or move the needed file to the email directory"); 305 } 306 if ($cgi->param('body') =~ /(\$COL\[.*?\])/ && !(-e $mergeFile)) { 307 &user_error("In order to use the \$COL[] you must specify a merge file. The file you specified does not exist. Also, make sure you selected the right checkbox."); 308 } 309 310 311 my %mergeAArray = (); 312 unless ($mergeFile eq '') {%mergeAArray = &delim2aa($mergeFile);} 313 314 &user_error('You didn\'t enter any message.') if ($cgi->param('body') eq ''); 315 316 foreach my $studentID (@studentID) { 317 @COL =(); 318 $SID = $studentID; 319 $LN = defined $ln{$studentID} ? $ln{$studentID} :''; 320 $FN = defined $fn{$studentID} ? $fn{$studentID} :''; 321 $SECTION = defined $section{$studentID} ? $section{$studentID} :''; 322 $RECITATION = defined $recitation{$studentID} ? $recitation{$studentID} :''; 323 $EMAIL = defined $email{$studentID} ? $email{$studentID} :''; 324 $STATUS =defined $status{$studentID} ? $status{$studentID} :''; 325 $LOGIN = $login{$studentID}; 326 327 next if ($LOGIN =~ /^$practiceUser/); ## skip practice users 328 329 if ($timeout_attempts >= $max_timeout_attempts) { ## have attemped to connect to smtp server 330 ## the max allowed times. Now just collect 331 ## data on emails not sent and exit 332 ++$emails_not_sent; 333 &log_error(\@exceeded_max_timeout,$FN,$LN,$EMAIL); 334 next; 335 } 336 337 unless ((defined $mergeAArray{$studentID}) or ($mergeFile eq '')) { 338 if ($cgi->param('no_record')) { 339 ++$emails_not_sent; 340 &log_error(\@no_record,$FN,$LN,$EMAIL); 341 next; 342 } 343 } 344 345 my ($dbString, @dbArray); 346 if (defined $mergeAArray{$SID}) { 347 $dbString = $mergeAArray{$SID}; ## get sid record from merge file 348 @dbArray = &getRecord($dbString); 349 unshift(@dbArray,$SID); 350 unshift(@dbArray,""); ## note COL[1] is the first column 351 @COL= @dbArray; ## put merge fields in COL array 352 $endCol = @COL; ## \endCol-1 gives last field, etc 353 } 354 my $smtp; 355 if ($smtp = Net::SMTP->new($Global::smtpServer, Timeout => $timeout_sec)) {} else { 356 # &internal_error("Couldn't contact SMTP server."); 357 ++$emails_not_sent; 358 &log_error(\@timeout_problem,$FN,$LN,$EMAIL); 359 ++$timeout_attempts; 360 next; 361 } 362 363 $smtp->mail($smtpSender); 364 365 if ( $smtp->recipient($EMAIL)) { # this one's okay, keep going 366 if ( $smtp->data("To: $EMAIL\n" . output() ) ) { 367 ++$emails_sent; 368 } else { 369 ++$emails_not_sent; 370 &log_error(\@unknown_problem,$FN,$LN,$EMAIL); 371 next; 372 } 373 # &internal_error("Unknown problem sending message data to SMTP server."); 374 } else { # we have a problem with this address 375 $smtp->reset; 376 #&internal_error("SMTP server doesn't like this address: <$EMAIL>."); 377 ++$emails_not_sent; 378 &log_error(\@bad_email_addresses,$FN,$LN,$EMAIL); 379 } 380 $smtp->quit; 381 } 382 &success; 383 } 384 } 385 386 387 388 #Begin Page 389 print &htmlTOP("Send Mail for " . $course), 390 $cgi->a( { -href=>"${cgiURL}login.pl?user=$user&key=$session_key&course=$course" }, 391 392 $cgi->img({ -name=>'upImg', 393 -src=>"${Global::upImgUrl}", 394 -align=>'right', 395 -border=>'1', 396 -alt=>'[Up]' 397 }) 398 ), 399 $cgi->p; 400 401 print "\n", 402 $cgi->hr, $cgi->br, 403 "\n\n", $cgi->h3({ -align=>'left' }, "WeBWorK Send Mail Page for $course"), "\n", 404 $cgi->p, 405 "From this page, you can send email to students. You can opt to send email to only specific 406 students or to entire groups of students based on classlists that can be created from the 407 professor's page. Any email can contain various macros to refer to information specific to 408 each student. In particular, a merge file can be specified so that outside information, such 409 as students grades can be placed in an email. This is most easily done by selecting the file 410 titled ${course}_totals.csv from the drop down list. The information in this file is 411 obtained by specifying \$COL[n] with the number in the brackets indicating the data item from 412 the nth column of the merge file or, if n is negative, the nth column from the last column. 413 (e.g. \$COL[3] is the third column and \$COL[-2] is the <U>second</U> to last column in the merge file. 414 Messages can be saved and retrieved for later use. Save as Default will cause the current message 415 to be the one that is loadedd when first coming to this page. (The old default message will be 416 saved as default.old so that the last default can be restored manually by changing its name to 417 default.msg)", 418 $cgi->hr, "\n"; 419 420 421 my %labels =(); 422 $labels{alph} = 'Alphabetically'; 423 $labels{section} = 'by section'; 424 $labels{recitation} = 'by recitation'; 425 426 # start form with hidden entries to pass info back to profSendMail.pl 427 print $cgi->startform(-action=>"${cgiURL}profSendMail.pl"), "\n", 428 $cgi->hidden(-name=>"user", -value=>$user), "\n", 429 $cgi->hidden(-name=>"key", -value=>$session_key), "\n", 430 $cgi->hidden(-name=>"course", -value=>$course), "\n", 431 $cgi->hidden(-name=>"filename", -value=>$openfilename), "\n"; 432 433 # # get all student emails and create a list 434 print $cgi->p, $cgi->b('Send Email To: '), "\n", $cgi->br, 435 $cgi->input({-type=>'radio', -name=>'To', -value=>'all_students'}), " \n", 436 "Send e-mail to all current students in $course", 437 $cgi->br, "or",$cgi->br; 438 print $cgi->input({-type=>'radio', -name=>'To', -value=>'studentID'}), " \n", 439 "Send e-mail to individual students (select as many as you like)<BR>"; 440 441 442 my ($lastName, $firstName, $studentID, $login_name, $section, $recitation, $label, $status, @all_sids, %fullnames, ); 443 @all_sids = (); 444 foreach $login_name (@availableStudents) { 445 &attachCLRecord($login_name); 446 $status = CL_getStudentStatus($login_name); 447 next if &dropStatus($status); 448 $lastName = CL_getStudentLastName($login_name); 449 $firstName = CL_getStudentFirstName($login_name); 450 $studentID = CL_getStudentID($login_name); 451 $section = CL_getClassSection($login_name); 452 $recitation = CL_getClassRecitation($login_name); 453 454 if ($format eq 'section') { 455 $label = ", $section"; 456 } 457 elsif ($format eq 'recitation') { 458 $label = ", $recitation"; 459 } 460 else { 461 $label = ''; 462 } 463 $label = "$lastName, $firstName, $studentID, $login_name". $label; 464 push (@all_sids, $studentID); #array for values of popup_menu 465 $fullnames{$studentID} = $label; 466 } 467 468 print $cgi->popup_menu(-name=>'studentID', 469 -size=>'5', 470 -multiple=>undef, 471 -values=>\@all_sids, 472 -labels=>\%fullnames), 473 "\n", 474 $cgi->br, 475 "Order students \n", 476 $cgi->radio_group( 477 -name=>'format', 478 -values=>['alph','section','recitation'], 479 -default=>'alph', 480 -labels=>\%labels 481 ), 482 $cgi->br, 483 $cgi->submit(-value=>'Reorder list now'), 484 $cgi->br, "or",$cgi->br; 485 486 print $cgi->input({-type=>'radio', -name=>'To', -value=>'classList'}), " \n", 487 "Select a classlist to send a message to: \n", $cgi->br, 488 "(Classlist files can be created from the Professor's Page)\n", $cgi->br; 489 490 491 # get all classlist files 492 # 493 # opendir CLASSLISTDIR, $templateDirectory; # or wwerror($0, "Can't open directory $templateDirectory","",""); 494 # my @allFiles = grep !/^\./, readdir CLASSLISTDIR; 495 # closedir CLASSLISTDIR; 496 # 497 # my @classlistFiles = grep /\.lst$/, @allFiles; #all classlist files 498 # my @sortedNames = sort @classlistFiles; 499 # 500 # my $shortFileName = $defaultClasslistFile; 501 # 502 # if ($shortFileName =~ m|/| ) { 503 # $shortFileName =~ m|/([^/]*)$|; ## extract filename from full path name 504 # $shortFileName = $1; 505 # } 506 # 507 # my @newSortedNames = grep !/^$shortFileName$/, @sortedNames; 508 # 509 # if ($#newSortedNames != $#sortedNames) { 510 # unshift @newSortedNames, $shortFileName; 511 # @sortedNames = @newSortedNames; 512 # } 513 my ($ar_sortedNames, $hr_classlistLabels) = getClasslistFilesAndLabels($course); 514 my @sortedNames = @$ar_sortedNames; 515 my %classlistLabels = %$hr_classlistLabels; 516 unshift(@sortedNames, "None"); 517 $classlistLabels{None} = 'None'; 518 519 #create list of classlists 520 print $cgi->popup_menu(-name=>'classList', 521 -values=>\@sortedNames, 522 -labels=>\%classlistLabels, 523 -default=>'None'); 524 525 print $cgi->hr, $cgi->p, $cgi->b('Enter Message: '), "\n", $cgi->br; 526 #get message from given messageFileName 527 my ($text, @text); 528 my $header = ''; 529 my ($subject, $from, $replyTo); 530 if (-e "$emailDirectory$messageFileName") { 531 open FILE, "$emailDirectory$messageFileName"; 532 while ($header !~ s/Message:\s*$//m) { $header .= <FILE>; } 533 $text = join '', <FILE>; 534 $header =~ /^From:\s(.*)$/m; 535 $from = $1 or $from = $defaultFrom; #given email address or default feedback address 536 $header =~ /^Reply-To:\s(.*)$/m; 537 $replyTo = $1 or $replyTo = $defaultReply; 538 $header =~ /^Subject:\s(.*)$/m; 539 $subject = $1; 540 541 } else { 542 # wwerror($0, "Message File $emailDirectory$messageFileName does not exist!"); 543 } 544 545 # show professors's name and email address 546 print "\n", $cgi->p, $cgi->b('From: '), $cgi->textfield(-name=>"from", -size=>40, -value=>$from, -override=>1), 547 "\n", $cgi->p, $cgi->b('Reply-To: '), $cgi->textfield(-name=>"replyTo", -size=>40, -value=>$replyTo, -override=>1); 548 549 #create a textbox with the subject and a textarea with the message 550 551 print "\n", $cgi->p, $cgi->b('Subject: '), $cgi->textfield(-name=>'subject', -default=>$subject, -size=>40, -override=>1), 552 $cgi->p, 553 "\n", $cgi->p, $cgi->b('Message: '); 554 555 #show available macros 556 print $cgi->br, $cgi->popup_menu( 557 -name=>'dummyName', 558 -values=>['', '$SID', '$FN', '$LN', '$SECTION', '$RECITATION','$STATUS', '$EMAIL', '$LOGIN', '$COL[3]', '$COL[-1]'], 559 -labels=>{''=>'These macros can be used to insert student specific data:', 560 '$SID'=>'$SID - Student ID', 561 '$FN'=>'$FN - First name', 562 '$LN'=>'$LN - Last name', 563 '$SECTION'=>'$SECTION - Student\'s Section', 564 '$RECITATION'=>'$RECITATION - Student\'s Recitation', 565 '$STATUS'=>'$STATUS - C, Audit, Drop, etc.', 566 '$EMAIL'=>'$EMAIL - Email address', 567 '$LOGIN'=>'$LOGIN - Login', 568 '$COL[3]'=>'$COL[3] - Third column in merge file', 569 '$COL[-1]'=>'$COL[-1] - Last column in merge file' 570 } 571 ), "\n"; 572 573 opendir SCORINGDIR, $scoringDirectory; # or wwerror($0, "Can't open directory $scoringDirectory","",""); 574 my @allFiles = grep !/^\./, readdir SCORINGDIR; 575 closedir SCORINGDIR; 576 577 my @mergeFiles = grep /\.csv$/, @allFiles; #all classlist files 578 @sortedNames = sort @mergeFiles; 579 unshift(@sortedNames, "None"); 580 581 #print a merge file popup list 582 print $cgi->br, "\nSelect a merge file: ", 583 $cgi->input({-type=>'radio', -name=>'merge', -value=>'mergeFiles', -checked=>undef}), ' ', 584 $cgi->popup_menu(-name=>'mergeFiles', 585 -values=>\@sortedNames, 586 -default=>"None"), 587 "or type in your own "; 588 589 my $shortDirectory = $emailDirectory; 590 $shortDirectory =~ s|.*/(\w*/)$|$1|; 591 #and a textbox to type in your own merge file 592 print $cgi->input({-type=>'radio', -name=>'merge', -value=>'mergeFile'}), ' ', 593 $cgi->textfield(-name=>'mergeFile', 594 -value=>$shortDirectory); 595 print "\n", $cgi->br, $cgi->input({-type=>'checkbox', -name=>'no_record', -value=>1, }), 596 'Do not send email if there is no record in merge file.',$cgi->br; 597 598 #print actual body of message 599 print "\n", $cgi->br, $cgi->textarea(-name=>'body', -default=>$text, -rows=>$rows, -columns=>$columns, -override=>1); 600 601 602 #get all message files and create a list 603 opendir EMAILDIR, $emailDirectory; # or wwerror($0, "Can't open directory $emailDirectory","",""); 604 my @messageFiles = grep /\.msg$/, readdir EMAILDIR; #all message files 605 closedir EMAILDIR; 606 607 my @sortedMessages = sort @messageFiles; 608 609 print $cgi->p, $cgi->popup_menu(-name=>'openfilename', -values=>\@sortedMessages, -default=>$messageFileName); 610 611 612 #create all necessary action buttons 613 print $cgi->submit(-name=>'action', -value=>'Open'), "\n", $cgi->br, 614 $cgi->textfield(-name=>'savefilename', -size => 20, -value=> "$messageFileName", -override=>1), ' ', 615 $cgi->submit(-name=>'action', -value=>'Save'), " \n", 616 $cgi->submit(-name=>'action', -value=>'Save as'), " \n", 617 $cgi->submit(-name=>'action', -value=>'Save as Default'), "\n", $cgi->br, 618 'For "Save As" choose a new filename.', $cgi->br, $cgi->br, 619 $cgi->submit(-name=>'action', -value=>'Send Email'), "\n", 620 $cgi->p, $cgi->submit(-name=>'action', -value=>'Revert to original and Resize message window'), 621 " Rows: ", $cgi->textfield(-name=>'rows', -size=>3, -value=>$rows), 622 " Columns: ", $cgi->textfield(-name=>'columns', -size=>3, -value=>$columns), 623 $cgi->br, "If you resize the message window, you will lose all unsaved changes.", 624 $cgi->end_form, 625 &htmlBOTTOM("profSendMail", \%inputs, 'profSendMailHelp.html'); 626 627 # End of HTML 628 629 630 ###### SUBROUTINES ###### 631 sub saveProblem { 632 my ($body, $probFileName)= @_; 633 634 open (PROBLEM, ">${emailDirectory}$probFileName") || 635 wwerror($0, "Could not open ${emailDirectory}$probFileName for writing. 636 Check that the permissions for this problem are 660 (-rw-rw----)"); 637 print PROBLEM $body; 638 close PROBLEM; 639 chmod 0660, "${emailDirectory}${probFileName}" || 640 print "Content-type: text/html\n\n 641 CAN'T CHANGE PERMISSIONS ON FILE ${templateDirectory}${probFileName}"; 642 643 } 644 645 sub saveNewProblem { 646 my ($body, $new_file_name)= @_; 647 #######check that the new file name doesn't exist 648 if (-e "${emailDirectory}$new_file_name" ) { 649 wwerror("Can not use this file name", "The file\n". 650 "${emailDirectory}$new_file_name\n". 651 "already exists.\n" . 652 "<b>The new version was not saved.</b>\n" . 653 "Go back and choose a different file name or\, if you really want to edit\n". 654 "${templateDirectory}$new_file_name\,\n". 655 "go back and hit the \"Save updated version\" button."); 656 } 657 658 wwerror ("Invalid file name", "The file name \"$new_file_name\" does not have a \".msg\" extension. 659 All email file names must end in the extension \".msg\" 660 <b>The file was not saved.</b> 661 Go back and choose a file name with a \".msg\" extension.") unless 662 $new_file_name =~ m|\.msg$|; 663 #######copy new version to the file new_file_name 664 open (PROBLEM, ">${emailDirectory}$new_file_name") || 665 wwerror($0, "Could not open ${emailDirectory}$new_file_name for writing. 666 Check that the permissions for the directory ${emailDirectory} are 770 (drwxrwx---)"); 667 print PROBLEM $body; 668 close PROBLEM; 669 chmod 0660, "${emailDirectory}$new_file_name" || 670 print "Content-type: text/html\n\n 671 CAN'T CHANGE PERMISSIONS ON FILE ${emailDirectory}$new_file_name"; 672 673 } 674 675 sub internal_error { 676 my $msg = join " ", @_; 677 print $cgi->header, 678 $cgi->start_html('-title' => "Internal Error"), 679 $cgi->h1('Internal Error'), 680 $cgi->b(HTML::Entities::encode($msg)), 681 $cgi->p, 682 "Your message could not be sent. Please notify ", 683 "<", $cgi->a({href=>"mailto:$Global::webmaster"}, $Global::webmaster), ">. ", 684 $cgi->br, 685 "We apologize for the inconvenience.", 686 $cgi->end_html; 687 exit(1); 688 } 689 690 sub user_error { 691 my $msg = join " ", @_; 692 print $cgi->header, 693 $cgi->start_html('-title' => 'User error'), 694 $cgi->h1('User error'), 695 $cgi->p, 696 $cgi->b(HTML::Entities::encode($msg)), 697 $cgi->p, 698 "Please hit the "<B>Back</B>" button on your browser to ", 699 "try again, or notify ", $cgi->br, 700 "<", $cgi->a({href=>"mailto:$Global::webmaster"}, $Global::webmaster), "> ", 701 "if you believe this message is in error.", 702 $cgi->end_html; 703 exit(1); 704 } 705 706 sub check_destination { 707 my($address_list) = @_; 708 709 my (@address) = split(/\+*,\+*/, $address_list); 710 for (@address) { 711 &internal_error("Sorry, I'm not allowed to send mail to <$_>.") 712 if !/$Global::legalAddress/; 713 } 714 } 715 716 sub output { 717 my ($msg, $body, $tmp); 718 719 $body = $cgi->param('body'); 720 721 $tmp = $body; 722 $tmp =~ s/(\$SID)/eval($1)/ge; 723 $tmp =~ s/(\$LN)/eval($1)/ge; 724 $tmp =~ s/(\$FN)/eval($1)/ge; 725 $tmp =~ s/(\$STATUS)/eval($1)/ge; 726 $tmp =~ s/(\$SECTION)/eval($1)/ge; 727 $tmp =~ s/(\$RECITATION)/eval($1)/ge; 728 $tmp =~ s/(\$EMAIL)/eval($1)/ge; 729 $tmp =~ s/(\$LOGIN)/eval($1)/ge; 730 $tmp =~ s/\$COL\[ *-/\$COL\[$endCol-/g; 731 $tmp =~ s/(\$COL\[.*?\])/eval($1)/ge; 732 733 734 $msg = 735 # message header 736 "From: " . $cgi->param('from') . "\n" . 737 "Reply-To: " . $cgi->param('replyTo') . "\n" . 738 "Subject: ". $cgi->param('subject') . "\n" . 739 "\n" . $tmp . "\n"; 740 741 $msg =~ s/\r//g; 742 return $msg; 743 } 744 745 sub success { 746 print $cgi->header, 747 $cgi->start_html( '-title'=>'Email Sent'),"\n", 748 $cgi->h1("Your message has been sent to $emails_sent users."),"\n", 749 $cgi->br; 750 751 if ($emails_not_sent > 0) { 752 print $cgi->h1("However, emails were not sent to the following $emails_not_sent users:"),"\n", 753 $cgi->br, 754 $cgi->h2('The format below is "FirstName LastName <EmailAddress>"'); 755 756 if (scalar(@no_record) > 0) { 757 print "\n", $cgi->br, 758 $cgi->h3('The following have no record in the merge file'),"\n"; 759 foreach my $line (@no_record) {print "\n$line <BR>";} 760 } 761 if (scalar(@unknown_problem) > 0) { 762 print "\n", $cgi->br, 763 $cgi->h3('The following have an unknown problem'); 764 foreach my $line (@unknown_problem) {print "\n$line <BR>";} 765 } 766 if (scalar(@bad_email_addresses) > 0) { 767 print "\n", $cgi->br, 768 $cgi->h3('The following have a bad email address'); 769 foreach my $line (@bad_email_addresses) {print "\n$line <BR>";} 770 } 771 if (scalar(@timeout_problem) > 0) { 772 print "\n", $cgi->br, 773 $cgi->h3('Connecting to the SMTP server timed out for the following'); 774 foreach my $line (@timeout_problem) {print "\n$line <BR>";} 775 } 776 if (scalar(@exceeded_max_timeout) > 0) { 777 print "\n", $cgi->br, 778 $cgi->h3("Connecting to the SMTP server failed $max_timeout_attempts times. No attempt was made to send emails to the following"); 779 foreach my $line (@exceeded_max_timeout) {print "\n$line <BR>";} 780 } 781 } 782 print "\n", $cgi->end_html; 783 exit(0); 784 } 785 786 sub log_error { 787 my ($ra_addresses,$FN,$LN,$EMAIL) = @_; 788 my $line = "$FN $LN <${EMAIL}>"; 789 push @$ra_addresses, $line; 790 }
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |