Parent Directory
|
Revision Log
Abstracted "read directory" functions in SendMail and moved them to Instructor. The instructor calls WeBWorK::Utils::readDirectory and then filters the output according to a pattern match. Sorts as well. Also move read_scoring_file to instructor since it will need to be used in other scripts as well. --Mike
1 package WeBWorK::ContentGenerator::Instructor::SendMail; 2 use base qw(WeBWorK::ContentGenerator::Instructor); 3 4 =head1 NAME 5 6 WeBWorK::ContentGenerator::Instructor::SendMail - Entry point for User-specific data editing 7 8 =cut 9 10 use strict; 11 use warnings; 12 use CGI qw(); 13 use HTML::Entities; 14 use Mail::Sender; 15 16 sub initialize { 17 my ($self) = @_; 18 my $r = $self->{r}; 19 my $db = $self->{db}; 20 my $ce = $self->{ce}; 21 my $authz = $self->{authz}; 22 my $user = $r->param('user'); 23 24 unless ($authz->hasPermissions($user, "send_mail")) { 25 $self->{submitError} = "You are not authorized to send mail to students."; 26 return; 27 } 28 ############################################################################################# 29 # gather directory data 30 ############################################################################################# 31 my $emailDirectory = $ce->{courseDirs}->{email}; 32 my $scoringDirectory = $ce->{courseDirs}->{scoring}; 33 my $templateDirectory = $ce->{courseDirs}->{templates}; 34 35 my $action = $r->param('action'); 36 my $openfilename = $r->param('openfilename'); 37 my $savefilename = $r->param('savefilename'); 38 39 40 #FIXME get these values from global course environment (see subroutines as well) 41 my $default_msg_file = 'default.msg'; 42 my $old_default_msg_file = 'old_default.msg'; 43 44 45 # store data 46 $self->{defaultFrom} = 'FIXME from'; 47 $self->{defaultReply} = 'FIXME reply'; 48 $self->{rows} = (defined($r->param('rows'))) ? $r->param('rows') : $ce->{mail}->{editor_window_rows}; 49 $self->{columns} = (defined($r->param('columns'))) ? $r->param('columns') : $ce->{mail}->{editor_window_columns}; 50 $self->{default_msg_file} = $default_msg_file; 51 $self->{old_default_msg_file} = $old_default_msg_file; 52 $self->{merge_file} = (defined($r->param('merge_file' ))) ? $r->param('merge_file') : 'None'; 53 $self->{preview_user} = (defined($r->param('preview_user'))) ? $r->param('preview_user') : $user; 54 55 56 ############################################################################################# 57 # gather database data 58 ############################################################################################# 59 # FIXME this might be better done in body? We don't always need all of this data. or do we? 60 my @users = sort $db->listUsers; 61 my @user_records = (); 62 push(@user_records,$db->getUser($_)) foreach (@users); 63 64 # store data 65 $self->{ra_users} = \@users; 66 $self->{ra_user_records} = \@user_records; 67 68 ############################################################################################# 69 # gather list of recipients 70 ############################################################################################# 71 my @send_to = (); 72 #FIXME this (radio) is a lousy name 73 my $recipients = $r->param('radio'); 74 if (defined($recipients) and $recipients eq 'all_students') { #only active students #FIXME status check?? 75 foreach my $ur (@user_records) { 76 push(@send_to,$ur->user_id) if $ur->status eq 'C' and not($ur->user_id =~ /practice/); 77 } 78 } elsif (defined($recipients) and $recipients eq 'studentID' ) { 79 @send_to = $r->param('classList'); 80 } else { 81 # no recipients have been defined -- probably the first time on the page 82 } 83 $self->{ra_send_to} = \@send_to; 84 ################################################################# 85 # Check the validity of the input file name 86 ################################################################# 87 my $input_file = ''; 88 #make sure an input message file was submitted and exists 89 #else use the default message 90 if ( defined($openfilename) ) { 91 if ( -e "${emailDirectory}/$openfilename") { 92 if ( -R "${emailDirectory}/$openfilename") { 93 $input_file = $openfilename; 94 } else { 95 warn join("", 96 "The file ${emailDirectory}/$openfilename is not readable by the webserver.",CGI::br(), 97 "Check that it's permissions are set correctly.", 98 ); 99 } 100 } else { 101 $input_file = $default_msg_file; 102 warn join("", 103 "The file ${emailDirectory}/$openfilename cannot be found.",CGI::br(), 104 "Check whether it exists and whether the directory $emailDirectory can be read by the webserver.",CGI::br(), 105 "Using contents of the default message $default_msg_file instead.", 106 ); 107 } 108 } else { 109 $input_file = $default_msg_file; 110 } 111 $self->{input_file} =$input_file; 112 113 ################################################################# 114 # Determine the file name to save message into 115 ################################################################# 116 my $output_file = 'FIXME no output file specified'; 117 if (defined($action) and $action eq 'Save as Default') { 118 $output_file = $default_msg_file; 119 } elsif ( defined($action) and ($action =~/save/i) and defined($savefilename) ){ 120 $output_file = $savefilename; 121 } elsif ( defined($input_file) ) { 122 $output_file = $input_file; 123 } 124 # warn "FIXME savefilename $savefilename output file $output_file"; 125 ################################################################# 126 # Sanity check on save file name 127 ################################################################# 128 129 if ($output_file =~ /^[~.]/ || $output_file =~ /\.\./) { 130 $self->submission_error("For security reasons, you cannot specify a merge file from a directory", 131 "higher than the email directory (you can't use ../blah/blah). ", 132 "Please specify a different file or move the needed file to the email directory", 133 ); 134 } 135 unless ($output_file =~ m|\.msg$| ) { 136 $self->submission_error("Invalid file name.", 137 "The file name \"$output_file\" does not have a \".msg\" extension", 138 "All email file names must end in the extension \".msg\"", 139 "choose a file name with a \".msg\" extension.", 140 "The message was not saved.", 141 ); 142 } 143 $self->{output_file} = $output_file; # this is ok. It will be put back in the text input box for re-editing. 144 # FIXME $output_file can be blank if there was no savefilename 145 146 ############################################################################################# 147 # Determine input source 148 ############################################################################################# 149 my $input_source = ( defined( $r->param('body') ) and $action ne 'Open' ) ? 'form' : 'file'; 150 # warn "FIXME input source is $input_source from $input_file"; 151 ############################################################################################# 152 # Get inputs 153 ############################################################################################# 154 my($from, $replyTo, $r_text, $subject); 155 if ($input_source eq 'file') { 156 # warn "FIXME obtaining source from $emailDirectory/$input_file"; 157 ($from, $replyTo,$subject,$r_text) = $self->read_input_file("$emailDirectory/$input_file"); 158 # warn "FIXME Done reading source"; 159 160 } elsif ($input_source eq 'form') { 161 # read info from the form 162 # bail if there is no message body 163 164 $from = $r->param('from'); 165 $replyTo = $r->param('replyTo'); 166 $subject = $r->param('subject'); 167 my $body = $r->param('body'); 168 # Sanity check: body must contain non-white space 169 $self->submission_error('You didn\'t enter any message.') unless ($r->param('body') =~ /\S/); 170 $r_text = \$body; 171 172 } 173 # store data 174 $self->{from} = $from; 175 $self->{replyTo} = $replyTo; 176 $self->{subject} = $subject; 177 $self->{r_text} = $r_text; 178 179 180 181 ################################################################################### 182 #Determine the appropriate script action from the buttons 183 ################################################################################### 184 # first time actions 185 # open new file 186 # open default file 187 # choose merge file actions 188 # chose merge button 189 # option actions 190 # 'reset rows' 191 192 # save actions 193 # "save" button 194 # "save as" button 195 # "save as default" button 196 # preview actions 197 # 'preview' button 198 # email actions 199 # 'entire class' 200 # 'selected studentIDs' 201 # error actions (various) 202 203 204 ############################################################################################# 205 # if no form is submitted, gather data needed to produce the mail form and return 206 ############################################################################################# 207 my $to = $r->param('To'); 208 my $script_action = ''; 209 210 211 if(not defined($action) or $action eq 'Open' or $action eq 'Resize message window' 212 or $action eq 'Set merge file to:' ){ 213 # warn "FIXME action is |$action| no further initialization required"; 214 return ''; 215 } 216 217 218 219 220 221 ############################################################################################# 222 # If form is submitted deal with filled out forms 223 # and various actions resulting from different buttons 224 ############################################################################################# 225 226 227 if ($action eq 'Save' or $action eq 'Save as:' or $action eq 'Save as Default') { 228 229 # warn "FIXME Saving files action = $action outputFileName=$output_file"; 230 231 ################################################################# 232 # construct message body 233 ################################################################# 234 my $temp_body = ${ $r_text }; 235 $temp_body =~ s/\r\n/\n/g; 236 $temp_body = join("", 237 "From: $from \nReply-To: $replyTo\n" , 238 "Subject: $subject\n" , 239 "Message: \n $temp_body"); 240 # warn "FIXME from $from | subject $subject |reply $replyTo|msg $temp_body"; 241 ################################################################# 242 # overwrite protection 243 ################################################################# 244 if ($action eq 'Save as:' and -e "$emailDirectory/$output_file") { 245 $self->submission_error("The file $emailDirectory/$output_file already exists and cannot be overwritten", 246 "The message was not saved"); 247 return; 248 } 249 250 ################################################################# 251 # Back up existing file? 252 ################################################################# 253 if ($action eq 'Save as Default' and -e "$emailDirectory/$default_msg_file") { 254 rename("$emailDirectory/$default_msg_file","$emailDirectory/$old_default_msg_file") or 255 die "Can't rename $emailDirectory/$default_msg_file to $emailDirectory/$old_default_msg_file ", 256 "Check permissions for webserver on directory $emailDirectory. $!"; 257 $self->{message} .= "Backup file <code>$emailDirectory/$old_default_msg_file</code> created.".CGI::br(); 258 } 259 ################################################################# 260 # Save the message 261 ################################################################# 262 $self->saveProblem($temp_body, "${emailDirectory}/$output_file" ); 263 $self->{message} .= "Message saved to file <code>${emailDirectory}/$output_file</code>."; 264 # warn "FIXME saving to ${emailDirectory}/$output_file"; 265 } elsif ($action eq 'Preview') { 266 $self->{response} = 'preview'; 267 268 } elsif ($action eq 'Send Email') { 269 $self->{response} = 'send_email'; 270 271 my @recipients = @{$self->{ra_send_to}}; 272 warn "No recipients selected " unless @recipients; 273 # get merge file 274 my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; 275 my $delimiter = ','; 276 my $rh_merge_data = $self->read_scoring_file("$merge_file", "$delimiter"); 277 unless (ref($rh_merge_data) ) { 278 warn "no merge data file"; 279 $self->submission_error("Can't read merge file $merge_file. No message sent"); 280 return; 281 } ; 282 283 284 foreach my $recipient (@recipients) { 285 #warn "FIXME sending email to $recipient"; 286 my $ur = $self->{db}->getUser($recipient); 287 my ($msg, $preview_header); 288 eval{ ($msg,$preview_header) = $self->process_message($ur,$rh_merge_data); }; 289 warn "There were errors in processing user $ur, merge file $merge_file. $@" if $@; 290 my $mailer = Mail::Sender->new({ 291 from => $from, 292 to => $ur->email_address, 293 smtp => $ce->{mail}->{smtpServer}, 294 subject => $subject, 295 headers => "X-Remote-Host: ".$r->get_remote_host(), 296 }); 297 unless (ref $mailer) { 298 warn "Failed to create a mailer: $Mail::Sender::Error"; 299 next; 300 } 301 unless (ref $mailer->Open()) { 302 warn "Failed to open the mailer: $Mail::Sender::Error"; 303 next; 304 } 305 my $MAIL = $mailer->GetHandle() or warn "Couldn't get handle"; 306 print $MAIL $msg || warn "Couldn't print to $MAIL"; 307 close $MAIL || warn "Couldn't close $MAIL"; 308 #warn "FIXME mailed to ", $ur->email_address, "from $from subject $subject"; 309 310 } 311 312 } else { 313 warn "Didn't recognize button $action"; 314 } 315 316 317 318 } #end initialize 319 320 321 sub title { 322 my $self = shift; 323 return 'Send mail to ' .$self->{ce}->{courseName}; 324 } 325 326 sub path { 327 my $self = shift; 328 my $args = $_[-1]; 329 330 my $ce = $self->{ce}; 331 my $root = $ce->{webworkURLs}->{root}; 332 my $courseName = $ce->{courseName}; 333 return $self->pathMacro($args, 334 "Home" => "$root", 335 $courseName => "$root/$courseName", 336 'instructor' => "$root/$courseName/instructor", 337 "Send Mail to: $courseName" => '', 338 ); 339 } 340 341 sub body { 342 my ($self, $setID) = @_; 343 my $response = (defined($self->{response}))? $self->{response} : ''; 344 if ($response eq 'preview') { 345 $self->print_preview($setID); 346 } elsif (($response eq 'send_email')){ 347 $self->{message} .= CGI::h3("Email sent to "). join(" ", @{$self->{ra_send_to}}); 348 $self->print_form($setID); 349 } else { 350 $self->print_form($setID); 351 } 352 353 } 354 sub print_preview { 355 my ($self, $setID) = @_; 356 # get preview user 357 my $ur = $self->{db}->getUser($self->{preview_user}); 358 359 # get merge file 360 my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; 361 my $delimiter = ','; 362 my $rh_merge_data = $self->read_scoring_file("$merge_file", "$delimiter"); 363 364 my ($msg, $preview_header) = $self->process_message($ur,$rh_merge_data); 365 366 my $recipients = join(" ",@{$self->{ra_send_to} }); 367 my $errorMessage = defined($self->{submitError}) ? CGI::h3($self->{submitError} ) : '' ; 368 $msg = join("", 369 $errorMessage, 370 $preview_header, 371 "To: " , $ur->email_address,"\n", 372 "From: " , $self->{from} , "\n" , 373 "Reply-To: " , $self->{replyTo} , "\n" , 374 "Subject: " , $self->{subject} , "\n" ,"\n" , 375 $msg , "\n" 376 ); 377 378 return join("", '<pre>',$msg,"\n","\n", 379 '</pre>', 380 CGI::p('Use browser back button to return from preview mode'), 381 CGI::h3('Emails to be sent to the following:'), 382 $recipients, "\n", 383 384 ); 385 386 } 387 sub print_form { 388 my ($self, $setID) = @_; 389 my $r = $self->{r}; 390 my $authz = $self->{authz}; 391 my $user = $r->param('user'); 392 my $db = $self->{db}; 393 my $ce = $self->{ce}; 394 my $root = $ce->{webworkURLs}->{root}; 395 my $courseName = $ce->{courseName}; 396 397 return CGI::em("You are not authorized to access the Instructor tools.") unless $authz->hasPermissions($user, "access_instructor_tools"); 398 399 my $userTemplate = $db->newUser; 400 my $permissionLevelTemplate = $db->newPermissionLevel; 401 402 # This code will require changing if the permission and user tables ever have different keys. 403 my @users = @{ $self->{ra_users} }; 404 my $ra_user_records = $self->{ra_user_records}; 405 my %classlistLabels = ();# %$hr_classlistLabels; 406 foreach my $ur (@{ $ra_user_records }) { 407 $classlistLabels{$ur->user_id} = $ur->user_id.' '.$ur->last_name. ', '. $ur->first_name.' - '.$ur->section; 408 } 409 410 411 ############################################################################################################## 412 413 414 my $from = $self->{from}; 415 my $subject = $self->{subject}; 416 my $replyTo = $self->{replyTo}; 417 my $columns = $self->{columns}; 418 my $rows = $self->{rows}; 419 my $text = defined($self->{r_text}) ? ${ $self->{r_text} }: 'FIXME no text was produced by initialization!!'; 420 my $input_file = $self->{input_file}; 421 my $output_file = $self->{output_file}; 422 my @sorted_messages = $self->get_message_file_names; 423 my @sorted_merge_files = $self->get_merge_file_names; 424 my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None'; 425 my $delimiter = ','; 426 my $rh_merge_data = $self->read_scoring_file("$merge_file", "$delimiter"); 427 my @merge_keys = keys %$rh_merge_data; 428 my $preview_user = $self->{preview_user}; 429 my $preview_record = $db->getUser($preview_user); 430 431 ############################################################################################# 432 433 print CGI::start_form({method=>"post", action=>$r->uri()}); 434 print $self->hidden_authen_fields(); 435 ############################################################################################# 436 # begin upper table 437 ############################################################################################# 438 439 print CGI::start_table({-border=>'2', -cellpadding=>'4'}); 440 print CGI::Tr({-align=>'left',-valign=>'VCENTER'}, 441 ############################################################################################# 442 # first column 443 ############################################################################################# 444 445 CGI::td("Message file: $input_file","\n",CGI::br(), 446 CGI::submit(-name=>'action', -value=>'Open'), ' ',"\n", 447 CGI::popup_menu(-name=>'openfilename', 448 -values=>\@sorted_messages, 449 -default=>$input_file 450 ), "\n",CGI::br(), 451 452 "Save file to: $output_file","\n",CGI::br(), 453 "\n", 'From:',' ', CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1), 454 "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1), 455 "\n", CGI::br(),'Subject: ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>30, -override=>1), 456 ), 457 ############################################################################################# 458 # second column 459 ############################################################################################# 460 CGI::td({-align=>'left'}, 461 CGI::radio_group(-name=>'radio', -values=>['all_students','studentID'], 462 -labels=>{all_students=>'All active students',studentID => 'Select recipients'}, 463 -default=>'studentID', 464 -linebreak=>1), 465 CGI::br(), 466 CGI::popup_menu(-name=>'classList', 467 -values=>\@users, 468 -labels=>\%classlistLabels, 469 -size => 10, 470 -multiple => 1, 471 -default=>$user 472 ), 473 474 475 ), 476 ############################################################################################# 477 # third column 478 ############################################################################################# 479 CGI::td({align=>'left'}, 480 "Merge file is: $merge_file", CGI::br(), 481 CGI::submit(-name=>'action', -value=>'Set merge file to:'),CGI::br(), 482 CGI::popup_menu(-name=>'merge_file', 483 -values=>\@sorted_merge_files, 484 -default=>$merge_file, 485 ), "\n",CGI::hr(),CGI::br(), 486 CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview')," email to ", 487 CGI::popup_menu(-name=>'preview_user', 488 -values=>\@users, 489 #-labels=>\%classlistLabels, 490 -default=>$preview_user, 491 ), 492 CGI::hr(), 493 CGI::submit(-name=>'action', -value=>'resize', -label=>'Resize message window'),CGI::br(), 494 " Rows: ", CGI::textfield(-name=>'rows', -size=>3, -value=>$rows), 495 " Columns: ", CGI::textfield(-name=>'columns', -size=>3, -value=>$columns), 496 CGI::br(),CGI::br(), 497 #show available macros 498 CGI::popup_menu( 499 -name=>'dummyName', 500 -values=>['', '$SID', '$FN', '$LN', '$SECTION', '$RECITATION','$STATUS', '$EMAIL', '$LOGIN', '$COL[3]', '$COL[-1]'], 501 -labels=>{''=>'list of insertable macros', 502 '$SID'=>'$SID - Student ID', 503 '$FN'=>'$FN - First name', 504 '$LN'=>'$LN - Last name', 505 '$SECTION'=>'$SECTION', 506 '$RECITATION'=>'$RECITATION', 507 '$STATUS'=>'$STATUS - C, Audit, Drop, etc.', 508 '$EMAIL'=>'$EMAIL - Email address', 509 '$LOGIN'=>'$LOGIN - Login', 510 '$COL[3]'=>'$COL[3] - 3rd col', 511 '$COL[-1]'=>'$COL[-1] - Last column' 512 } 513 ), "\n", 514 ), 515 516 ); # end Tr 517 print CGI::end_table(); 518 ############################################################################################# 519 # end upper table 520 ############################################################################################# 521 522 # show merge file 523 # print "<pre>",(map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} 0..8),"</pre>"; 524 # print CGI::popup_menu( 525 # -name=>'dummyName2', 526 # -values=>\@merge_keys, 527 # -labels=>$rh_merge_data, 528 # -multiple=>1, 529 # -size =>2, 530 # 531 # ), "\n",CGI::br(); 532 # warn "merge keys ", join( " ",@merge_keys); 533 ############################################################################################# 534 # merge file fragment and message text area field 535 ############################################################################################# 536 my @tmp2; 537 eval{ @tmp2= @{$rh_merge_data->{ $db->getUser($preview_user)->student_id } };}; 538 if ($@) { 539 # print CGI::p( "Couldn't get merge data for $preview_user", CGI::br(), $@) ; 540 print "No merge data for $preview_user in merge file: <$merge_file>",CGI::br(); 541 } else { 542 print CGI::pre("",data_format(0..($#tmp2)),"\n", data_format(@tmp2)); 543 } 544 #create a textbox with the subject and a textarea with the message 545 #print actual body of message 546 547 print "\n", CGI::p( $self->{message}) if defined($self->{message}); 548 print "\n", CGI::p( CGI::textarea(-name=>'body', -default=>$text, -rows=>$rows, -columns=>$columns, -override=>1)); 549 550 ############################################################################################# 551 # action button table 552 ############################################################################################# 553 print CGI::table( { -border=>2,-cellpadding=>4}, 554 CGI::Tr( 555 CGI::td( CGI::submit(-name=>'action', -value=>'Send Email') ), "\n", 556 CGI::td(CGI::submit(-name=>'action', -value=>'Save')," to $output_file"), " \n", 557 CGI::td(CGI::submit(-name=>'action', -value=>'Save as:'), 558 CGI::textfield(-name=>'savefilename', -size => 20, -value=> "$output_file", -override=>1) 559 ), "\n", 560 CGI::td(CGI::submit(-name=>'action', -value=>'Save as Default')), 561 ) 562 ); 563 564 ############################################################################################################## 565 566 print CGI::end_form(); 567 return ""; 568 } 569 570 ############################################################################## 571 # Utility methods 572 ############################################################################## 573 sub submission_error { 574 my $self = shift; 575 my $msg = join( " ", @_); 576 $self->{submitError} .= CGI::br().$msg; #CGI::b(HTML::Entities::encode($msg)); 577 # qq{Please hit the "<B>Back</B>" button on your browser to 578 # try again, or notify your web master 579 # if you believe this message is in error. 580 # }; 581 return; 582 } 583 584 sub saveProblem { 585 my $self = shift; 586 my ($body, $probFileName)= @_; 587 local(*PROBLEM); 588 open (PROBLEM, ">$probFileName") || 589 $self->submission_error("Could not open $probFileName for writing. 590 Check that the permissions for this problem are 660 (-rw-rw----)"); 591 print PROBLEM $body; 592 close PROBLEM; 593 chmod 0660, "$probFileName" || 594 $self->submission_error(" 595 CAN'T CHANGE PERMISSIONS ON FILE $probFileName"); 596 } 597 598 sub read_input_file { 599 my $self = shift; 600 my $filePath = shift; 601 my ($text, @text); 602 my $header = ''; 603 my ($subject, $from, $replyTo); 604 local(*FILE); 605 if (-e "$filePath" and -r "$filePath") { 606 open FILE, "$filePath" || do { $self->submission_error("Can't open $filePath"); return}; 607 while ($header !~ s/Message:\s*$//m and not eof(FILE)) { 608 $header .= <FILE>; 609 } 610 $text = join( '', <FILE>); 611 $text =~ s/^\s*//; # remove initial white space if any. 612 $header =~ /^From:\s(.*)$/m; 613 $from = $1 or $from = $self->{defaultFrom}; 614 615 $header =~ /^Reply-To:\s(.*)$/m; 616 $replyTo = $1 or $replyTo = $self->{defaultReply}; 617 618 $header =~ /^Subject:\s(.*)$/m; 619 $subject = $1; 620 621 } else { 622 $from = $self->{defaultFrom}; 623 $replyTo = $self->{defaultReply}; 624 $text = (-e "$filePath") ? "FIXME file $filePath can't be read" :"FIXME file $filePath doesn't exist"; 625 $subject = "FIXME default subject"; 626 } 627 return ($from, $replyTo, $subject, \$text); 628 } 629 630 631 sub get_message_file_names { 632 my $self = shift; 633 return $self->read_dir($self->{ce}->{courseDirs}->{email}, '\\.msg$'); 634 } 635 sub get_merge_file_names { 636 my $self = shift; 637 return 'None', $self->read_dir($self->{ce}->{courseDirs}->{scoring}, '\\.csv$'); 638 } 639 640 641 sub getRecord { 642 my $self = shift; 643 my $line = shift; 644 my $delimiter = shift; 645 $delimiter = ',' unless defined($delimiter); 646 647 # Takes a delimited line as a parameter and returns an 648 # array. Note that all white space is removed. If the 649 # last field is empty, the last element of the returned 650 # array is also empty (unlike what the perl split command 651 # would return). E.G. @lineArray=&getRecord(\$delimitedLine). 652 653 my(@lineArray); 654 $line.=$delimiter; # add 'A' to end of line so that 655 # last field is never empty 656 @lineArray = split(/\s*${delimiter}\s*/,$line); 657 $lineArray[0] =~s/^\s*//; # remove white space from first element 658 @lineArray; 659 } 660 661 sub process_message { 662 my $self = shift; 663 my $ur = shift; 664 my $rh_merge_data = shift; 665 my $text = defined($self->{r_text}) ? ${ $self->{r_text} }: 666 'FIXME no text was produced by initialization!!'; 667 #user macros that can be used in the email message 668 my $SID = $ur->student_id; 669 my $FN = $ur->first_name; 670 my $LN = $ur->last_name; 671 my $SECTION = $ur->section; 672 my $RECITATION = $ur->recitation; 673 my $STATUS = $ur->status; 674 my $EMAIL = $ur->email_address; 675 my $LOGIN = $ur->user_id; 676 # get record from merge file 677 # FIXME this is inefficient. The info should be cached 678 my @COL = defined($rh_merge_data->{$SID}) ? @{$rh_merge_data->{$SID} } : (); 679 $self->submission_error( "No merge data for $SID $FN $LN $LOGIN") unless defined($rh_merge_data->{$SID}); 680 681 my $endCol = @COL; 682 # for safety, only evaluate special variables 683 my $msg = $text; 684 $msg =~ s/(\$SID)/eval($1)/ge; 685 $msg =~ s/(\$LN)/eval($1)/ge; 686 $msg =~ s/(\$FN)/eval($1)/ge; 687 $msg =~ s/(\$STATUS)/eval($1)/ge; 688 $msg =~ s/(\$SECTION)/eval($1)/ge; 689 $msg =~ s/(\$RECITATION)/eval($1)/ge; 690 $msg =~ s/(\$EMAIL)/eval($1)/ge; 691 $msg =~ s/(\$LOGIN)/eval($1)/ge; 692 $msg =~ s/\$COL\[ *-/\$COL\[$endCol-/g; 693 $msg =~ s/(\$COL\[.*?\])/eval($1)/ge; 694 695 $msg =~ s/\r//g; 696 697 my $preview_header = CGI::pre("",data_format(0..($#COL)),"\n", data_format(@COL)). 698 CGI::h3( "This sample mail would be sent to $EMAIL"); 699 700 701 return $msg, $preview_header; 702 } 703 sub data_format { 704 map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} @_; 705 } 706 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |