[system] / trunk / webwork / system / cgi / cgi-scripts / profSendMail.pl Repository:
ViewVC logotype

View of /trunk/webwork/system/cgi/cgi-scripts/profSendMail.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 76 - (download) (as text) (annotate)
Thu Jun 28 13:33:38 2001 UTC (18 years, 5 months ago) by chris
File size: 34053 byte(s)
Fixed bug in the reading fields.  Added defaultfrom and defaultreply addresses from Global.pm

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

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9