[system] / trunk / webwork2 / lib / WeBWorK / ContentGenerator / Instructor / SendMail.pm Repository:
ViewVC logotype

Annotation of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/SendMail.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1375 - (view) (download) (as text)

1 : gage 1368 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 : gage 1370 use HTML::Entities;
14 : gage 1373 use Mail::Sender;
15 : gage 1368
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 : gage 1369 #############################################################################################
29 :     # gather directory data
30 :     #############################################################################################
31 :     my $emailDirectory = $ce->{courseDirs}->{email};
32 :     my $scoringDirectory = $ce->{courseDirs}->{scoring};
33 :     my $templateDirectory = $ce->{courseDirs}->{templates};
34 : gage 1368
35 : gage 1369 my $action = $r->param('action');
36 :     my $openfilename = $r->param('openfilename');
37 :     my $savefilename = $r->param('savefilename');
38 : gage 1370
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 : gage 1372
45 : gage 1370 # 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 : gage 1372 $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') : 'Yourself';
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 : gage 1375 if (defined($recipients) and $recipients eq 'all_students') { #only active students #FIXME status check??
75 : gage 1372 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 : gage 1375 } elsif (defined($recipients) and $recipients eq 'studentID' ) {
79 : gage 1372 @send_to = $r->param('classList');
80 :     } else {
81 : gage 1375 # no recipients have been defined -- probably the first time on the page
82 : gage 1372 }
83 :     $self->{ra_send_to} = \@send_to;
84 : gage 1370 #################################################################
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 : gage 1369 } else {
95 : gage 1370 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 : gage 1369 }
100 :     } else {
101 : gage 1370 $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 : gage 1369 }
108 : gage 1370 } else {
109 : gage 1372 $input_file = $default_msg_file;
110 : gage 1370 }
111 : gage 1372 $self->{input_file} =$input_file;
112 : gage 1370
113 :     #################################################################
114 :     # Determine the file name to save message into
115 :     #################################################################
116 : gage 1371 my $output_file = 'FIXME no output file specified';
117 : gage 1370 if (defined($action) and $action eq 'Save as Default') {
118 :     $output_file = $default_msg_file;
119 : gage 1371 } elsif ( defined($action) and ($action =~/save/i) and defined($savefilename) ){
120 : gage 1370 $output_file = $savefilename;
121 :     } elsif ( defined($input_file) ) {
122 :     $output_file = $input_file;
123 :     }
124 : gage 1371 # warn "FIXME savefilename $savefilename output file $output_file";
125 : gage 1370 #################################################################
126 :     # Sanity check on save file name
127 :     #################################################################
128 :    
129 :     if ($output_file =~ /^[~.]/ || $output_file =~ /\.\./) {
130 : gage 1371 $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 : gage 1370 }
135 : gage 1371 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 : gage 1370 # 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 : gage 1371 # warn "FIXME obtaining source from $emailDirectory/$input_file";
157 : gage 1370 ($from, $replyTo,$subject,$r_text) = $self->read_input_file("$emailDirectory/$input_file");
158 : gage 1371 # warn "FIXME Done reading source";
159 : gage 1370
160 :     } elsif ($input_source eq 'form') {
161 :     # read info from the form
162 :     # bail if there is no message body
163 : gage 1369
164 : gage 1370 $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 : gage 1369
172 : gage 1370 }
173 :     # store data
174 :     $self->{from} = $from;
175 :     $self->{replyTo} = $replyTo;
176 :     $self->{subject} = $subject;
177 :     $self->{r_text} = $r_text;
178 :    
179 :    
180 : gage 1372
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 : gage 1369 #############################################################################################
205 : gage 1370 # if no form is submitted, gather data needed to produce the mail form and return
206 : gage 1369 #############################################################################################
207 : gage 1372 my $to = $r->param('To');
208 :     my $script_action = '';
209 :    
210 :    
211 : gage 1371 if(not defined($action) or $action eq 'Open' or $action eq 'Resize message window'
212 : gage 1375 or $action eq 'Set merge file to:' ){
213 : gage 1370 # warn "FIXME action is |$action| no further initialization required";
214 : gage 1369 return '';
215 :     }
216 :    
217 :    
218 :    
219 :    
220 :    
221 :     #############################################################################################
222 : gage 1370 # If form is submitted deal with filled out forms
223 : gage 1369 # and various actions resulting from different buttons
224 :     #############################################################################################
225 :    
226 : gage 1370
227 : gage 1372
228 : gage 1369 # user_errors
229 :     # save
230 :     # save as
231 :     # save as default
232 :     # send mail
233 :     # set defaults
234 :    
235 : gage 1370 if ($action eq 'Save' or $action eq 'Save as:' or $action eq 'Save as Default') {
236 :    
237 :     # warn "FIXME Saving files action = $action outputFileName=$output_file";
238 : gage 1369
239 : gage 1370 #################################################################
240 :     # construct message body
241 :     #################################################################
242 :     my $temp_body = ${ $r_text };
243 :     $temp_body =~ s/\r\n/\n/g;
244 :     $temp_body = join("",
245 :     "From: $from \nReply-To: $replyTo\n" ,
246 :     "Subject: $subject\n" ,
247 :     "Message: \n $temp_body");
248 :     # warn "FIXME from $from | subject $subject |reply $replyTo|msg $temp_body";
249 :     #################################################################
250 :     # overwrite protection
251 :     #################################################################
252 :     if ($action eq 'Save as:' and -e "$emailDirectory/$output_file") {
253 : gage 1371 $self->submission_error("The file $emailDirectory/$output_file already exists and cannot be overwritten",
254 :     "The message was not saved");
255 : gage 1370 return;
256 :     }
257 :    
258 :     #################################################################
259 :     # Back up existing file?
260 :     #################################################################
261 : gage 1371 if ($action eq 'Save as Default' and -e "$emailDirectory/$default_msg_file") {
262 :     rename("$emailDirectory/$default_msg_file","$emailDirectory/$old_default_msg_file") or
263 :     die "Can't rename $emailDirectory/$default_msg_file to $emailDirectory/$old_default_msg_file ",
264 :     "Check permissions for webserver on directory $emailDirectory. $!";
265 :     $self->{message} .= "Backup file <code>$emailDirectory/$old_default_msg_file</code> created.".CGI::br();
266 : gage 1370 }
267 :     #################################################################
268 :     # Save the message
269 :     #################################################################
270 :     $self->saveProblem($temp_body, "${emailDirectory}/$output_file" );
271 : gage 1371 $self->{message} .= "Message saved to file <code>${emailDirectory}/$output_file</code>.";
272 : gage 1370 # warn "FIXME saving to ${emailDirectory}/$output_file";
273 : gage 1372 } elsif ($action eq 'Preview') {
274 :     $self->{response} = 'preview';
275 : gage 1370
276 :     } elsif ($action eq 'Send Email') {
277 : gage 1373 $self->{response} = 'send_email';
278 :    
279 :     my @recipients = @{$self->{ra_send_to}};
280 :     warn "No recipients selected " unless @recipients;
281 :     # get merge file
282 :     my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
283 :     my $delimiter = ',';
284 :     my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter");
285 :     warn "No data for merge file $merge_file" unless ref($rh_merge_data);
286 :    
287 :     foreach my $recipient (@recipients) {
288 :     #warn "FIXME sending email to $recipient";
289 :     my $ur = $self->{db}->getUser($recipient);
290 :     my ($msg, $preview_header);
291 :     eval{ ($msg,$preview_header) = $self->process_message($ur,$rh_merge_data); };
292 :     warn "There were errors in processing user $ur, merge file $merge_file. $@" if $@;
293 :     my $mailer = Mail::Sender->new({
294 :     from => $from,
295 :     to => $ur->email_address,
296 :     smtp => $ce->{mail}->{smtpServer},
297 :     subject => $subject,
298 :     headers => "X-Remote-Host: ".$r->get_remote_host(),
299 :     });
300 :     unless (ref $mailer) {
301 :     warn "Failed to create a mailer: $Mail::Sender::Error";
302 :     next;
303 :     }
304 :     unless (ref $mailer->Open()) {
305 :     warn "Failed to open the mailer: $Mail::Sender::Error";
306 :     next;
307 :     }
308 :     my $MAIL = $mailer->GetHandle() or warn "Couldn't get handle";
309 :     $msg = 'Hi ' . $msg;
310 :     print $MAIL $msg || warn "Couldn't print to $MAIL";
311 :     close $MAIL || warn "Couldn't close $MAIL";
312 :     #warn "FIXME mailed to ", $ur->email_address, "from $from subject $subject";
313 :    
314 :     }
315 :    
316 :    
317 :     #&success;
318 : gage 1370
319 :    
320 :     } else {
321 : gage 1373 warn "Didn't recognize button $action";
322 : gage 1370 }
323 : gage 1369
324 :    
325 :    
326 :     } #end initialize
327 :    
328 : gage 1368
329 :     sub title {
330 :     my $self = shift;
331 :     return 'Send mail to ' .$self->{ce}->{courseName};
332 :     }
333 :    
334 :     sub path {
335 :     my $self = shift;
336 :     my $args = $_[-1];
337 :    
338 :     my $ce = $self->{ce};
339 :     my $root = $ce->{webworkURLs}->{root};
340 :     my $courseName = $ce->{courseName};
341 :     return $self->pathMacro($args,
342 :     "Home" => "$root",
343 :     $courseName => "$root/$courseName",
344 :     'instructor' => "$root/$courseName/instructor",
345 :     "Send Mail to: $courseName" => '',
346 :     );
347 :     }
348 :    
349 :     sub body {
350 : gage 1372 my ($self, $setID) = @_;
351 :     my $response = (defined($self->{response}))? $self->{response} : '';
352 :     if ($response eq 'preview') {
353 :     $self->print_preview($setID);
354 : gage 1373 } elsif (($response eq 'send_email')){
355 :     $self->{message} .= CGI::h3("Email sent to "). join(" ", @{$self->{ra_send_to}});
356 : gage 1372 $self->print_form($setID);
357 : gage 1375 } else {
358 :     $self->print_form($setID);
359 : gage 1372 }
360 :    
361 :     }
362 :     sub print_preview {
363 :     my ($self, $setID) = @_;
364 :     # get preview user
365 :     my $ur = $self->{db}->getUser($self->{preview_user});
366 :    
367 :     # get merge file
368 :     my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
369 :     my $delimiter = ',';
370 :     my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter");
371 :    
372 :     my ($msg, $preview_header) = $self->process_message($ur,$rh_merge_data);
373 :    
374 :     my $recipients = join(" ",@{$self->{ra_send_to} });
375 : gage 1373 my $errorMessage = defined($self->{submitError}) ? CGI::h3($self->{submitError} ) : '' ;
376 :     $msg = join("",
377 :     $errorMessage,
378 :     $preview_header,
379 :     "To: " , $ur->email_address,"\n",
380 :     "From: " , $self->{from} , "\n" ,
381 :     "Reply-To: " , $self->{replyTo} , "\n" ,
382 :     "Subject: " , $self->{subject} , "\n" ,"\n" ,
383 :     $msg , "\n"
384 :     );
385 : gage 1372
386 : gage 1373 return join("", '<pre>',$msg,"\n","\n",
387 : gage 1372 '</pre>',
388 :     CGI::p('Use browser back button to return from preview mode'),
389 :     CGI::h3('Emails to be sent to the following:'),
390 :     $recipients, "\n",
391 :    
392 :     );
393 :    
394 :     }
395 :     sub print_form {
396 : gage 1368 my ($self, $setID) = @_;
397 :     my $r = $self->{r};
398 :     my $authz = $self->{authz};
399 :     my $user = $r->param('user');
400 :     my $db = $self->{db};
401 :     my $ce = $self->{ce};
402 :     my $root = $ce->{webworkURLs}->{root};
403 :     my $courseName = $ce->{courseName};
404 :    
405 :     return CGI::em("You are not authorized to access the Instructor tools.") unless $authz->hasPermissions($user, "access_instructor_tools");
406 :    
407 :     my $userTemplate = $db->newUser;
408 :     my $permissionLevelTemplate = $db->newPermissionLevel;
409 :    
410 :     # This code will require changing if the permission and user tables ever have different keys.
411 : gage 1372 my @users = @{ $self->{ra_users} };
412 :     my $ra_user_records = $self->{ra_user_records};
413 :     my %classlistLabels = ();# %$hr_classlistLabels;
414 :     foreach my $ur (@{ $ra_user_records }) {
415 :     $classlistLabels{$ur->user_id} = $ur->user_id.' '.$ur->last_name. ', '. $ur->first_name.' - '.$ur->section;
416 :     }
417 : gage 1368
418 :    
419 :     ##############################################################################################################
420 :    
421 : gage 1372
422 : gage 1369 my $from = $self->{from};
423 :     my $subject = $self->{subject};
424 :     my $replyTo = $self->{replyTo};
425 :     my $columns = $self->{columns};
426 :     my $rows = $self->{rows};
427 : gage 1370 my $text = defined($self->{r_text}) ? ${ $self->{r_text} }: 'FIXME no text was produced by initialization!!';
428 :     my $input_file = $self->{input_file};
429 :     my $output_file = $self->{output_file};
430 : gage 1371 my @sorted_messages = $self->get_message_file_names;
431 :     my @sorted_merge_files = $self->get_merge_file_names;
432 :     my $merge_file = ( defined($self->{merge_file}) ) ? $self->{merge_file} : 'None';
433 : gage 1372 my $delimiter = ',';
434 :     my $rh_merge_data = $self->read_merge_file("$merge_file", "$delimiter");
435 :     my @merge_keys = keys %$rh_merge_data;
436 :     my $preview_user = $self->{preview_user};
437 :     my $preview_record = $db->getUser($preview_user);
438 :    
439 :     #############################################################################################
440 :    
441 : gage 1369 print CGI::start_form({method=>"post", action=>$r->uri()});
442 : gage 1372 print $self->hidden_authen_fields();
443 :     #############################################################################################
444 :     # begin upper table
445 :     #############################################################################################
446 :    
447 : gage 1368 print CGI::start_table({-border=>'2', -cellpadding=>'4'});
448 : gage 1370 print CGI::Tr({-align=>'left',-valign=>'VCENTER'},
449 : gage 1372 #############################################################################################
450 :     # first column
451 :     #############################################################################################
452 :    
453 : gage 1371 CGI::td("Message file: $input_file","\n",CGI::br(),
454 :     CGI::submit(-name=>'action', -value=>'Open'), '&nbsp;&nbsp;&nbsp;&nbsp;',"\n",
455 :     CGI::popup_menu(-name=>'openfilename',
456 :     -values=>\@sorted_messages,
457 :     -default=>$input_file
458 :     ), "\n",CGI::br(),
459 :    
460 :     "Save file to: $output_file","\n",CGI::br(),
461 : gage 1370 "\n", 'From:','&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', CGI::textfield(-name=>"from", -size=>30, -value=>$from, -override=>1),
462 :     "\n", CGI::br(),'Reply-To: ', CGI::textfield(-name=>"replyTo", -size=>30, -value=>$replyTo, -override=>1),
463 : gage 1372 "\n", CGI::br(),'Subject: ', CGI::br(), CGI::textarea(-name=>'subject', -default=>$subject, -rows=>3,-columns=>35, -override=>1),
464 : gage 1370 ),
465 : gage 1372 #############################################################################################
466 :     # second column
467 :     #############################################################################################
468 : gage 1370 CGI::td({-align=>'left'},
469 :     CGI::radio_group(-name=>'radio', -values=>['all_students','studentID'],
470 :     -labels=>{all_students=>'All active students',studentID => 'Select recipients'},
471 :     -default=>'studentID',
472 :     -linebreak=>1),
473 :     CGI::br(),
474 :     CGI::popup_menu(-name=>'classList',
475 :     -values=>\@users,
476 :     -labels=>\%classlistLabels,
477 :     -size => 10,
478 :     -multiple => 1,
479 : gage 1372 -default=>$user
480 : gage 1370 ),
481 :    
482 :    
483 :     ),
484 : gage 1372 #############################################################################################
485 :     # third column
486 :     #############################################################################################
487 : gage 1370 CGI::td({align=>'left'},
488 : gage 1372 "Merge file is: $merge_file", CGI::br(),
489 : gage 1375 CGI::submit(-name=>'action', -value=>'Set merge file to:'),CGI::br(),
490 : gage 1371 CGI::popup_menu(-name=>'merge_file',
491 :     -values=>\@sorted_merge_files,
492 :     -default=>$merge_file,
493 : gage 1372 ), "\n",CGI::hr(),CGI::br(),
494 :     CGI::submit(-name=>'action', -value=>'preview',-label=>'Preview')," email to ",
495 :     CGI::popup_menu(-name=>'preview_user',
496 : gage 1370 -values=>\@users,
497 : gage 1372 #-labels=>\%classlistLabels,
498 :     -default=>$preview_user,
499 : gage 1369 ),
500 : gage 1372 CGI::hr(),
501 : gage 1370 CGI::submit(-name=>'action', -value=>'resize', -label=>'Resize message window'),CGI::br(),
502 :     " Rows: ", CGI::textfield(-name=>'rows', -size=>3, -value=>$rows),
503 :     " Columns: ", CGI::textfield(-name=>'columns', -size=>3, -value=>$columns),
504 :     CGI::br(),CGI::br(),
505 :     #show available macros
506 :     CGI::popup_menu(
507 :     -name=>'dummyName',
508 :     -values=>['', '$SID', '$FN', '$LN', '$SECTION', '$RECITATION','$STATUS', '$EMAIL', '$LOGIN', '$COL[3]', '$COL[-1]'],
509 :     -labels=>{''=>'list of insertable macros',
510 :     '$SID'=>'$SID - Student ID',
511 :     '$FN'=>'$FN - First name',
512 :     '$LN'=>'$LN - Last name',
513 : gage 1372 '$SECTION'=>'$SECTION',
514 : gage 1370 '$RECITATION'=>'$RECITATION',
515 :     '$STATUS'=>'$STATUS - C, Audit, Drop, etc.',
516 :     '$EMAIL'=>'$EMAIL - Email address',
517 :     '$LOGIN'=>'$LOGIN - Login',
518 : gage 1372 '$COL[3]'=>'$COL[3] - 3rd col',
519 : gage 1370 '$COL[-1]'=>'$COL[-1] - Last column'
520 :     }
521 :     ), "\n",
522 :     ),
523 : gage 1368
524 : gage 1370 ); # end Tr
525 : gage 1372 print CGI::end_table();
526 :     #############################################################################################
527 :     # end upper table
528 :     #############################################################################################
529 :    
530 :     # show merge file
531 :     # print "<pre>",(map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} 0..8),"</pre>";
532 :     # print CGI::popup_menu(
533 :     # -name=>'dummyName2',
534 :     # -values=>\@merge_keys,
535 :     # -labels=>$rh_merge_data,
536 :     # -multiple=>1,
537 :     # -size =>2,
538 :     #
539 :     # ), "\n",CGI::br();
540 :     # warn "merge keys ", join( " ",@merge_keys);
541 :     #############################################################################################
542 :     # merge file fragment and message text area field
543 :     #############################################################################################
544 : gage 1373 my @tmp2;
545 :     eval{ @tmp2= @{$rh_merge_data->{ $db->getUser($preview_user)->student_id } };};
546 :     if ($@) {
547 :     print CGI::p( "Couldn't get merge data for $preview_user", CGI::br(), $@) ;
548 :     } else {
549 :     print CGI::pre("",data_format(0..($#tmp2)),"\n", data_format(@tmp2));
550 :     }
551 : gage 1368 #create a textbox with the subject and a textarea with the message
552 :     #print actual body of message
553 : gage 1369
554 : gage 1370 print "\n", CGI::p( $self->{message}) if defined($self->{message});
555 : gage 1369 print "\n", CGI::p( CGI::textarea(-name=>'body', -default=>$text, -rows=>$rows, -columns=>$columns, -override=>1));
556 : gage 1372
557 :     #############################################################################################
558 :     # action button table
559 :     #############################################################################################
560 : gage 1370 print CGI::table( { -border=>2,-cellpadding=>4},
561 :     CGI::Tr(
562 :     CGI::td( CGI::submit(-name=>'action', -value=>'Send Email') ), "\n",
563 :     CGI::td(CGI::submit(-name=>'action', -value=>'Save')," to $output_file"), " \n",
564 :     CGI::td(CGI::submit(-name=>'action', -value=>'Save as:'),
565 :     CGI::textfield(-name=>'savefilename', -size => 20, -value=> "$output_file", -override=>1)
566 :     ), "\n",
567 :     CGI::td(CGI::submit(-name=>'action', -value=>'Save as Default')),
568 :     )
569 :     );
570 : gage 1368
571 :     ##############################################################################################################
572 : gage 1369
573 :     print CGI::end_form();
574 : gage 1368 return "";
575 :     }
576 :    
577 : gage 1369 ##############################################################################
578 :     # Utility methods
579 :     ##############################################################################
580 : gage 1370 sub submission_error {
581 : gage 1369 my $self = shift;
582 : gage 1371 my $msg = join( " ", @_);
583 :     $self->{submitError}= $msg; #CGI::b(HTML::Entities::encode($msg));
584 :     # qq{Please hit the &quot;<B>Back</B>&quot; button on your browser to
585 :     # try again, or notify your web master
586 :     # if you believe this message is in error.
587 :     # };
588 : gage 1369 return;
589 :     }
590 :    
591 : gage 1370 sub saveProblem {
592 :     my $self = shift;
593 :     my ($body, $probFileName)= @_;
594 :     local(*PROBLEM);
595 :     open (PROBLEM, ">$probFileName") ||
596 :     $self->submission_error("Could not open $probFileName for writing.
597 :     Check that the permissions for this problem are 660 (-rw-rw----)");
598 :     print PROBLEM $body;
599 :     close PROBLEM;
600 :     chmod 0660, "$probFileName" ||
601 :     $self->submission_error("
602 :     CAN'T CHANGE PERMISSIONS ON FILE $probFileName");
603 :     }
604 :    
605 :     sub read_input_file {
606 :     my $self = shift;
607 :     my $filePath = shift;
608 :     my ($text, @text);
609 :     my $header = '';
610 :     my ($subject, $from, $replyTo);
611 :     local(*FILE);
612 : gage 1371 if (-e "$filePath" and -r "$filePath") {
613 :     open FILE, "$filePath" || do { $self->submission_error("Can't open $filePath"); return};
614 :     while ($header !~ s/Message:\s*$//m and not eof(FILE)) {
615 : gage 1370 $header .= <FILE>;
616 :     }
617 :     $text = join( '', <FILE>);
618 :     $text =~ s/^\s*//; # remove initial white space if any.
619 :     $header =~ /^From:\s(.*)$/m;
620 :     $from = $1 or $from = $self->{defaultFrom};
621 :    
622 :     $header =~ /^Reply-To:\s(.*)$/m;
623 :     $replyTo = $1 or $replyTo = $self->{defaultReply};
624 :    
625 :     $header =~ /^Subject:\s(.*)$/m;
626 :     $subject = $1;
627 :    
628 :     } else {
629 :     $from = $self->{defaultFrom};
630 :     $replyTo = $self->{defaultReply};
631 : gage 1371 $text = (-e "$filePath") ? "FIXME file $filePath can't be read" :"FIXME file $filePath doesn't exist";
632 : gage 1370 $subject = "FIXME default subject";
633 :     }
634 :     return ($from, $replyTo, $subject, \$text);
635 :     }
636 : gage 1371
637 :     sub get_message_file_names {
638 :     my $self = shift;
639 :     my $emailDirectory = $self->{ce}->{courseDirs}->{email};
640 :     #get all message files and create a list
641 :     local(*EMAILDIR);
642 :     opendir( EMAILDIR, $emailDirectory )|| die "Can't access directory $emailDirectory. Please check that webserver has permission to read this directory.";
643 :     my @messageFiles = grep /\.msg$/, readdir EMAILDIR; #all message files
644 :     closedir EMAILDIR;
645 :    
646 :     return sort @messageFiles;
647 :     }
648 :     sub get_merge_file_names {
649 :     my $self = shift;
650 :     my $scoringDirectory = $self->{ce}->{courseDirs}->{scoring};
651 :     #get all message files and create a list
652 :     local(*SCORINGDIR);
653 :     opendir( SCORINGDIR, $scoringDirectory )|| die "Can't access directory $scoringDirectory.",
654 :     "Please check that webserver has permission to read this directory.";
655 :     my @mergeFiles = grep( /\.csv$/, readdir SCORINGDIR); #all message files
656 :     closedir SCORINGDIR;
657 :     @mergeFiles = sort @mergeFiles;
658 :     # warn "FIXME scoring directory $scoringDirectory merge Files", join(" ", @mergeFiles);
659 :     unshift(@mergeFiles, 'None');
660 :     return @mergeFiles;
661 :     }
662 : gage 1372
663 :     sub read_merge_file {
664 :     my $self = shift;
665 :     my $fileName = shift;
666 :     my $delimiter = shift;
667 :     $delimiter = ',' unless defined($delimiter);
668 :     my $scoringDirectory= $self->{ce}->{courseDirs}->{scoring};
669 :     my $filePath = "$scoringDirectory/$fileName";
670 :     # Takes a delimited file as a parameter and returns an
671 :     # associative array with the first field as the key.
672 :     # Blank lines are skipped. White space is removed
673 : gage 1375 my(@dbArray,$key,$dbString);
674 :     my %assocArray = ();
675 :     return
676 : gage 1372 local(*FILE);
677 : gage 1375 if ($fileName eq 'None') {
678 :     # do nothing
679 :     }elsif ( open(FILE, "$filePath") ) {
680 :     my $index=0;
681 :     while (<FILE>){
682 :     unless ($_ =~ /\S/) {next;} ## skip blank lines
683 :     chomp;
684 :     @{$dbArray[$index]} =$self->getRecord($_,$delimiter);
685 :     $key =$dbArray[$index][0];
686 :     #@dbArray = map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} @dbArray;
687 :     #$dbString = join(" | ",@dbArray);
688 :     $assocArray{$key}=$dbArray[$index];
689 :     $index++;
690 :     }
691 :     close(FILE);
692 :     } else {
693 :     warn "Couldn't read file $filePath";
694 :     }
695 :     return \%assocArray;
696 : gage 1372 }
697 :     sub getRecord {
698 :     my $self = shift;
699 :     my $line = shift;
700 :     my $delimiter = shift;
701 :     $delimiter = ',' unless defined($delimiter);
702 :    
703 :     # Takes a delimited line as a parameter and returns an
704 :     # array. Note that all white space is removed. If the
705 :     # last field is empty, the last element of the returned
706 :     # array is also empty (unlike what the perl split command
707 :     # would return). E.G. @lineArray=&getRecord(\$delimitedLine).
708 :    
709 :     my(@lineArray);
710 :     $line.=$delimiter; # add 'A' to end of line so that
711 :     # last field is never empty
712 :     @lineArray = split(/\s*${delimiter}\s*/,$line);
713 :     $lineArray[0] =~s/^\s*//; # remove white space from first element
714 :     @lineArray;
715 :     }
716 :    
717 :     sub process_message {
718 :     my $self = shift;
719 :     my $ur = shift;
720 :     my $rh_merge_data = shift;
721 :     my $text = defined($self->{r_text}) ? ${ $self->{r_text} }:
722 :     'FIXME no text was produced by initialization!!';
723 :     #user macros that can be used in the email message
724 :     my $SID = $ur->student_id;
725 :     my $FN = $ur->first_name;
726 :     my $LN = $ur->last_name;
727 :     my $SECTION = $ur->section;
728 :     my $RECITATION = $ur->recitation;
729 :     my $STATUS = $ur->status;
730 :     my $EMAIL = $ur->email_address;
731 :     my $LOGIN = $ur->user_id;
732 :     # get record from merge file
733 :     # FIXME this is inefficient. The info should be cached
734 : gage 1373 my @COL = defined($rh_merge_data->{$SID}) ? @{$rh_merge_data->{$SID} } : ();
735 :     $self->submission_error( "No merge data for $SID $FN $LN $LOGIN") unless defined($rh_merge_data->{$SID});
736 : gage 1372
737 :     my $endCol = @COL;
738 :     # for safety, only evaluate special variables
739 : gage 1373 my $msg = $text;
740 :     $msg =~ s/(\$SID)/eval($1)/ge;
741 :     $msg =~ s/(\$LN)/eval($1)/ge;
742 :     $msg =~ s/(\$FN)/eval($1)/ge;
743 :     $msg =~ s/(\$STATUS)/eval($1)/ge;
744 :     $msg =~ s/(\$SECTION)/eval($1)/ge;
745 :     $msg =~ s/(\$RECITATION)/eval($1)/ge;
746 :     $msg =~ s/(\$EMAIL)/eval($1)/ge;
747 :     $msg =~ s/(\$LOGIN)/eval($1)/ge;
748 :     $msg =~ s/\$COL\[ *-/\$COL\[$endCol-/g;
749 :     $msg =~ s/(\$COL\[.*?\])/eval($1)/ge;
750 :    
751 :     $msg =~ s/\r//g;
752 : gage 1372
753 :     my $preview_header = CGI::pre("",data_format(0..($#COL)),"\n", data_format(@COL)).
754 :     CGI::h3( "This sample mail would be sent to $EMAIL");
755 :    
756 :    
757 :     return $msg, $preview_header;
758 :     }
759 :     sub data_format {
760 :     map {$_ =~s/\s/\./g;$_} map {sprintf('%-8.8s',$_);} @_;
761 :     }
762 : gage 1368 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9