--- loncom/interface/lonnotify.pm 2005/08/02 05:03:10 1.1 +++ loncom/interface/lonnotify.pm 2005/10/14 19:10:20 1.6 @@ -31,6 +31,9 @@ use Apache::lonsupportreq; use LONCAPA::Enrollment; use Apache::Constants qw(:common :http); use Apache::lonlocal; +use Mail::Send; +use HTML::TokeParser; +use HTML::Entities; sub handler { my ($r) = @_; @@ -40,31 +43,315 @@ sub handler { if ($r->header_only) { return OK; } -# my $codedom = $env{'request.role.domain'}; - my $cdom = 'northwood5'; - unless (&Apache::lonnet::allowed('psa',$env{'request.role.domain'})) { + my $cdom = $env{'request.role.domain'}; + unless (&Apache::lonnet::allowed('psa',$cdom)) { # Not allowed to broadcast e-mail system-wide $env{'user.error.msg'}="/adm/notify:psa:0:0:Cannot broadcast e-mail systemwide"; return HTTP_NOT_ACCEPTABLE; } + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['command']); my $command = $env{'form.command'}; &Apache::lonhtmlcommon::clear_breadcrumbs(); + my %ltext=&Apache::lonlocal::texthash( + 'note' => 'Notification E-mail', + ); + my $function = &Apache::loncommon::get_users_function(); + my $tablecolor = &Apache::loncommon::designparm($function.'.tabbg'); + my $bodytag = &Apache::loncommon::bodytag('Broadcast e-mail to users'); + my $html=&Apache::lonxml::xmlbegin(); &Apache::lonhtmlcommon::add_breadcrumb ({href=>'/adm/notify', - text=>"Broadcast e-mail"}); + text=>"Broadcast E-mail"}); if ($command eq 'process') { - &print_request_receipt($r,$cdom); + &print_request_receipt($r,$cdom,$tablecolor,$bodytag,$html,\%ltext); } elsif ($command eq 'compose') { - &print_composition_form($r,$cdom); + &print_composition_form($r,$cdom,$tablecolor,$bodytag,$html,\%ltext); + } elsif ($command eq 'pick_target') { + &print_selection_form($r,$cdom,$tablecolor,$bodytag,$html,\%ltext); + } elsif ($command eq 'pick_display') { + &print_display_option_form($r,$cdom,$tablecolor,$bodytag,$html,\%ltext); + } elsif ($command eq 'display') { + &print_display($r,$cdom,$tablecolor,$bodytag,$html,\%ltext); } else { - &print_selection_form($r,$cdom); + &print_front_page($r,$cdom,$tablecolor,$bodytag,$html,\%ltext); } return OK; } +sub print_front_page { + my ($r,$cdom,$tablecolor,$bodytag,$html,$ltext) = @_; + my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs + (undef,'Broadcast e-mail to Domain','Broadcast_system_email'); + my $jscript = qq| +function next_page(caller) { + if (caller == 'view') { + document.front.command.value="pick_display" + } + else { + document.front.command.value="pick_target" + } + document.front.submit() +} + |; + my %lt=&Apache::lonlocal::texthash( + 'note' => 'Notification E-mail', + ); + my $output = <<"ENDONE"; +$html +<head> + <title>LON-CAPA $lt{'note'}</title> +<script type"text/javascript"> +$jscript +</script> +</head> +$bodytag +$breadcrumbs +<br /> +ENDONE + $output .= '<form name="front" method="post">'. + '<input type="hidden" name="command" />'; + $output .= &Apache::lonhtmlcommon::start_pick_box(); + $output .= '<table cellspacing="8" cellpadding="8">'. + '<tr><td><a href="javascript:next_page('."'new'".')">'. + 'Send a new e-mail message to selected users from this domain</a></td></tr><tr>'. + '<td><a href="javascript:next_page('."'view'".')">'. + 'Display e-mail sent by Domain Coordinators in this domain'. + '</a></td></tr></table>'; + $output .= &Apache::lonhtmlcommon::end_pick_box(); + $output .= qq( +</form> +</body> +</html>); + $r->print($output); + return; +} + +sub print_display_option_form { + my ($r,$cdom,$tablecolor,$bodytag,$html,$ltext) = @_; + &Apache::lonhtmlcommon::add_breadcrumb + ({text=>"Display options"}); + my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs + (undef,'Broadcast e-mail display options','Broadcast_system_email'); + my $table_width = ''; + my $col_width = '200'; + my $formname = 'display_options'; + my $cmd = 'display'; + my $submit_text = 'Display e-mail'; + my @roles = ('dc'); + my $now = time; + my %lt=&Apache::lonlocal::texthash( + 'note' => 'Notification E-mail', + ); + my $startdateform = &Apache::lonhtmlcommon::date_setter($formname, + 'startdate', + $now); + my $enddateform = &Apache::lonhtmlcommon::date_setter($formname, + 'enddate', + $now); + my $jscript; + my $output = <<"ENDONE"; +$html +<head> + <title>LON-CAPA $lt{'note'}</title> +<script type"text/javascript"> +$jscript +</script> +</head> +$bodytag +$breadcrumbs +<br /> +<form method="post" name="$formname"> +ENDONE + $output .= &Apache::lonhtmlcommon::start_pick_box($table_width); + $output .= &Apache::lonhtmlcommon::row_title($col_width,$tablecolor,&mt('Date range')); + $output .= '<td><table><tr><td>Earliest to display: </td><td>'. + $startdateform.'</td></tr>'; + $output .= '<tr><td>Latest to display: </td><td>'.$enddateform. + '</td></tr></table></td>'; + $output .= &Apache::lonhtmlcommon::row_closure(); + $output .= &Apache::lonhtmlcommon::row_title($col_width,$tablecolor,&mt('Choose sender(s)')); + my %personnel = &Apache::lonnet::get_domain_roles($cdom,\@roles); + $output .= '<td>'; + my @domcc = (); + foreach my $server (keys %personnel) { + foreach my $user (sort(keys %{$personnel{$server}})) { + my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user); + unless (grep/^$uname:$udom$/,@domcc) { + my %userinfo = &Apache::lonnet::get('environment',['lastname','firstname'],$udom,$uname); + $output .= '<input type="checkbox" name="sender" value="'.$uname.':'.$udom.'" /> '.$userinfo{firstname}.' '.$userinfo{lastname}.' ('.$uname.':'.$udom.')'; + push (@domcc,$uname.':'.$udom); + } + } + } + $output .= '</td>'; + $output .= &Apache::lonhtmlcommon::row_closure(); + $output .= &Apache::lonhtmlcommon::submit_row($col_width,$tablecolor,&mt('Submit'),$cmd,$submit_text); + $output .= &Apache::lonhtmlcommon::end_pick_box(); + $output .= qq( +<input type="hidden" name="sortby" value="date" /> +</form> +</body> +</html>); + $r->print($output); + return; +} + +sub print_display { + my ($r,$cdom,$tablecolor,$bodytag,$html,$ltext) = @_; + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/notify?command=pick_display', + text=>"Display options"}, + {text=>"E-mail display"}); + my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs + (undef,'Display Broadcast e-mail','Broadcast_system_email'); + my $table_width = ''; + my $col_width = '200'; + my $rowColor1 = "#ffffff"; + my $rowColor2 = "#eeeeee"; + my $rowColor; + my $msgcount = 0; + my $formname = 'display_sent'; + my $start = &Apache::lonhtmlcommon::get_date_from_form('startdate'); + my $end = &Apache::lonhtmlcommon::get_date_from_form('enddate'); + my @senders = &Apache::loncommon::get_env_multiple('form.sender'); + my %sentmail = &Apache::lonnet::dcmaildump($cdom,$start,$end,\@senders); + my %dcmail = (); + my %Sortby = (); + my $jscript = <<"ENDSCRIPT"; +function changeSort(caller) { + document.$formname.sortby.value = caller; + document.$formname.submit(); +} +ENDSCRIPT + my $output = <<"ENDONE"; +$html +<head> + <title>LON-CAPA $$ltext{'note'}</title> + <script type"text/javascript"> +$jscript + </script> +</head> +$bodytag +$breadcrumbs +<br /> +<form method="post" name="$formname"> +ENDONE + + foreach my $server (keys(%sentmail)) { + foreach my $msgid (keys(%{$sentmail{$server}})) { + my %content = &unpackagemail($sentmail{$server}{$msgid}); + if (defined($dcmail{$msgid})) { + foreach my $user (keys(%{$content{'recipients'}})) { + $dcmail{$msgid}{recipients}{$user} = $content{recipients}{$user}; + } + } else { + $msgcount ++; + %{$dcmail{$msgid}} = (); + foreach my $item (keys(%content)) { + if ($item eq 'recipients') { + foreach my $user (keys(%{$content{recipients}})) { + $dcmail{$msgid}{recipients}{$user} = $content{recipients}{$user}; + } + } else { + $dcmail{$msgid}{$item} = $content{$item}; + } + } + } + } + } + $output .= &Apache::lonhtmlcommon::start_pick_box(); + if ($msgcount > 0) { + my $rowNum = 0; + $output .= '<tr><td><table cellpadding="4" cellspacing="2" width="100%"> + <tr bgcolor="'.$tablecolor.'" align="center"> + <td><b><a href="javascript:changeSort('."'date'".')">Date</a></b></td> + <td><b><a href="javascript:changeSort('."'subject'".')">Subject</a></b></td> + <td><b><a href="javascript:changeSort('."'sender'".')">Sender</a></b></td> + <td><b><a href="javascript:changeSort('."'message'".')">Message</a></b></td> + <td><b><a href="javascript:changeSort('."'recipients'".')">Recipients</a></b></td> + </tr>'; + if (($env{'form.sortby'} eq 'date') || ($env{'form.sortby'} eq '') || (!defined($env{'form.sortby'})) || (($env{'form.sortby'} eq 'sender') && (@senders <= 1))) { + foreach my $msgid (sort(keys(%dcmail))) { + if ($rowNum %2 == 1) { + $rowColor = $rowColor1; + } else { + $rowColor = $rowColor2; + } + my $recipients = ''; + my ($date,$subj,$sname,$sdom,$cdom) = split(/:/,$msgid,5); + $date = &Apache::lonlocal::locallocaltime($date); + foreach my $user (sort(keys(%{$dcmail{$msgid}{recipients}}))) { + $recipients .= $dcmail{$msgid}{recipients}{$user}.', '; + } + $recipients =~ s/,\s$//; + $output .= '<tr bgcolor="'.$rowColor.'"><td><small>'.$date.'</small></td><td><small>'.&cr_to_br($dcmail{$msgid}{subject}).'</small></td><td><small>'.$sname.':'.$sdom.'</small></td><td><small>'.&cr_to_br($dcmail{$msgid}{message}).'</small></td><td><small>'.$recipients.'</small></td></tr>'."\n"; + $rowNum ++; + } + } else { + foreach my $msgid (sort(keys(%dcmail))) { + my ($date,$subj,$sname,$sdom,$cdom) = split(/:/,$msgid,5); + if ($env{'form.sortby'} eq 'subject') { + push @{$Sortby{$dcmail{$msgid}{subject}}},$msgid; + } elsif ($env{'form.sortby'} eq 'message') { + push @{$Sortby{$dcmail{$msgid}{message}}},$msgid; + } elsif ($env{'form.sortby'} eq 'recipients') { + my $recipients =''; + foreach my $user (sort(keys(%{$dcmail{$msgid}{recipients}}))) { + $recipients .= $dcmail{$msgid}{recipients}{$user}.', '; + } + $recipients =~ s/,\s$//; + push @{$Sortby{$recipients}},$msgid; + } elsif ($env{'form.sortby'} eq 'sender') { + if (@senders > 1) { + push @{$Sortby{$sname.':'.$sdom}},$msgid; + } + } + } + foreach my $key (sort(keys(%Sortby))) { + foreach my $msgid (@{$Sortby{$key}}) { + if ($rowNum %2 == 1) { + $rowColor = $rowColor1; + } else { + $rowColor = $rowColor2; + } + my $recipients = ''; + if ($env{'form.sortby'} eq 'recipients') { + $recipients = $key; + } else { + foreach my $user (sort(keys(%{$dcmail{$msgid}{recipients}}))) { + $recipients .= $dcmail{$msgid}{recipients}{$user}.', '; + } + $recipients =~ s/,\s$//; + } + + my ($date,$subj,$sname,$sdom,$cdom) = split(/:/,$msgid,5); + $date = &Apache::lonlocal::locallocaltime($date); + $output .= '<tr bgcolor="'.$rowColor.'"><td><small>'.$date.'</small></td><td><small>'.&cr_to_br($dcmail{$msgid}{subject}).'</small></td><td><small>'.$sname.':'.$sdom.'</small></td><td><small>'.&cr_to_br($dcmail{$msgid}{message}).'</small></td><td><small>'.$recipients.'</small></td></tr>'."\n"; + $rowNum ++; + } + } + } + $output .= '</table></td></tr>'; + } else { + $output .= '<tr bgcolor="#ffffff"><td> </td><td><br><center><i><b><small> No mail sent matching supplied criteria </small><br><br></b></i></td><td> </td></tr>'; + } + $output .= &Apache::lonhtmlcommon::end_pick_box(); + $output .= &echo_form_input(); + unless (defined($env{'form.sortby'})) { + $output .= qq(<input type="hidden" name="sortby" value="date" />\n); + } + $output .= qq( +</form> +</body> +</html>); + $r->print($output); + return; +} + sub print_selection_form { - my ($r,$cdom) = @_; + my ($r,$cdom,$tablecolor,$bodytag,$html,$ltext) = @_; my %coursecodes = (); my %codes = (); my @codetitles = (); @@ -77,211 +364,97 @@ sub print_selection_form { my $totcodes = 0; my $format_reply; my $jscript = ''; + my $formname = 'rolefilter'; + my $table_width = '100%'; + my $col_width = '200'; + my %lt=&Apache::lonlocal::texthash( + 'note' => 'Notification E-mail', + 'buil' => 'Building valid e-mail address from username, if missing from preferences:', + 'kerb' => 'Kerberos: enter default for each realm used in the domain, with comma separation of entries', + 'infs' => 'Internal, Filesystem and Local authentication: enter single default.', + 'comp' => 'Compose Message' + ); my $loaditems = qq| function initialize_codes() { return; } |; + &Apache::lonhtmlcommon::add_breadcrumb + ({text=>"Select Audience"}); + $totcodes = &Apache::lonsupportreq::retrieve_instcodes(\%coursecodes,$cdom,$totcodes); if ($totcodes > 0) { $format_reply = &Apache::lonnet::auto_instcode_format($caller,$cdom,\%coursecodes,\%codes,\@codetitles,\%cat_titles,\%cat_order); if ($format_reply eq 'ok') { my $numtypes = @codetitles; &Apache::lonsupportreq::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles); - &Apache::lonsupportreq::javascript_code_selections($numtypes,\%cat_titles,\$jscript,\%idlist,\%idnums,\%idlist_titles,\@codetitles); + &Apache::lonsupportreq::javascript_code_selections($formname,$numtypes,\%cat_titles,\$jscript,\%idlist,\%idnums,\%idlist_titles,\@codetitles); $loaditems = ''; } } - my $function = &Apache::loncommon::get_users_function(); - my $tablecolor = &Apache::loncommon::designparm($function.'.tabbg'); - my $bodytag = &Apache::loncommon::bodytag('Broadcast e-mail to users'); - my $html=&Apache::lonxml::xmlbegin(); my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs - (undef,'Broadcast e-mail to users','Broadcast_system_email'); - $r->print(<<ENDONE); + (undef,'Choose e-mail audience','Broadcast_system_email'); + my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom); + my $output = <<"ENDONE"; $html <head> - <title>LON-CAPA Notification E-mail</title> + <title>LON-CAPA $lt{'note'}</title> <script type"text/javascript"> $jscript </script> +$cb_jscript </head> $bodytag $breadcrumbs <br /> -<form method="post" name="logproblem"> - <table width="580" border="0" cellpadding="0" cellspacing="0" bgcolor="#000000"> - <tr> - <td> - <table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#000000"> - <tr> - <td> - <table width="100%" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff"> - <tr> - <td> - <table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#ffffff"> - <tr> - <td width="140" bgcolor="$tablecolor"> - <table width="140" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td align="right"><b>Roles:</b> - </td> - </tr> - </table> - </td> - <td width="100%" valign="top"> - <table width="100%" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td> - <select name="roles" multiple> +<form method="post" name="$formname"> ENDONE - foreach ('cc','in','ta','ep','ad') { - my $plrole=&Apache::lonnet::plaintext($_); - $r->print(' <option value="'.$_.'">'.$plrole.'</option>'); - } - $r->print(<<ENDTWO); - </select> - </td> - </tr> - </table> - </td> - </tr> - <tr> - <td width="140" bgcolor="$tablecolor"> - <table width="140" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td align="right"><b>Courses:</b> - </td> - </tr> - </table> - </td> - <td width="100%" valign="top"> - <table width="100%" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td> -ENDTWO - if ($totcodes > 0) { - my $numtitles = @codetitles; - if ($numtitles == 0) { - $r->print('No institutional course code categories found.<br />Can not select courses to receive e-mail.'); - } else { - $r->print('<table><tr><td>'.$codetitles[0].'<br />'."\n". - '<select name="'.$codetitles[0]. - '" onChange="courseSet('."'$codetitles[0]'".')">'."\n". - ' <option value="-1" />Select'."\n"); - my @items = (); - my @longitems = (); - if ($idlist{$codetitles[0]} =~ /","/) { - @items = split/","/,$idlist{$codetitles[0]}; - } else { - $items[0] = $idlist{$codetitles[0]}; - } - if (defined($idlist_titles{$codetitles[0]})) { - if ($idlist_titles{$codetitles[0]} =~ /","/) { - @longitems = split/","/,$idlist_titles{$codetitles[0]}; - } else { - $longitems[0] = $idlist_titles{$codetitles[0]}; - } - for (my $i=0; $i<@longitems; $i++) { - if ($longitems[$i] eq '') { - $longitems[$i] = $items[$i]; - } - } - } else { - @longitems = @items; - } - for (my $i=0; $i<@items; $i++) { - $r->print(' <option value="'.$items[$i].'">'.$longitems[$i].'</option>'); - } - $r->print('</select></td>'); - for (my $i=1; $i<$numtitles; $i++) { - $r->print('<td>'.$codetitles[$i].'<br />'."\n". - '<select name="'.$codetitles[$i]. - '" onChange="courseSet('."'$codetitles[$i]'".')">'."\n". - '<option value="-1"><-Pick '.$codetitles[$i-1].'</option>'."\n". - '</select>'."\n". - '</td>' - ); - } - $r->print('</tr></table>'); - } - } - $r->print(<<END); - </td> - </tr> - </table> - </td> - </tr> - <tr> - <td width="140" bgcolor="$tablecolor"> - <table width="140" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td align="right"><b>Submit:</b> - </td> - </tr> - </table> - </td> - <td width="100%" valign="top" align="right"> - <br /> - <input type="hidden" name="command" value="compose" /> - <input type="submit" value="Compose Message"/> - <br /><br /> - </td> - </tr> - </table> - </td> - </tr> - </table> - </td> - </tr> - </table> - </td> - </tr> - </table> + $output .= &Apache::lonhtmlcommon::start_pick_box($table_width); + my @roles = ('ow','cc','in','ta','ep','ad','st','cr'); + my %longtypes = (); + my %authtypes = (); + &form_elements(\%longtypes,\%authtypes); + my $descrip = $lt{'buil'}.' +<ul> +<li>'.$lt{'kerb'}.'<br />(e.g., MSU.EDU=msu.edu, MSUE.EDU=msue.msu.edu).</li> +<li>'.$lt{'infs'}.'</li> +</ul>'."\n"; + my $submit_text = $lt{'comp'}; + my $cmd = 'compose'; + $output .= &Apache::lonhtmlcommon::role_select_row(\@roles,$col_width,$tablecolor,'Roles'); + $output .= &Apache::lonhtmlcommon::course_select_row($col_width,$tablecolor,'Courses',$formname,$totcodes,\@codetitles,\%idlist,\%idlist_titles); + $output .= &Apache::lonhtmlcommon::status_select_row(\%longtypes,$col_width,$tablecolor,&mt('Access status')); + $output .= &Apache::lonhtmlcommon::email_default_row(\%authtypes,$col_width,$tablecolor,&mt('Username -> Email conversion'),$descrip); + $output .= &Apache::lonhtmlcommon::submit_row($col_width,$tablecolor,&mt('Submit'),$cmd,$submit_text); + $output .= &Apache::lonhtmlcommon::end_pick_box(); + $output .= qq( </form> </body> -</html> -END +</html>); + $r->print($output); return; } sub print_composition_form { - my ($r,$cdom) = @_; - my $function = &Apache::loncommon::get_users_function(); - my $tablecolor = &Apache::loncommon::designparm($function.'.tabbg'); - my $bodytag = &Apache::loncommon::bodytag('Broadcast e-mail to users'); - my $html=&Apache::lonxml::xmlbegin(); + my ($r,$cdom,$tablecolor,$bodytag,$html,$ltext) = @_; &Apache::lonhtmlcommon::add_breadcrumb - ({href=>'/adm/notify?command=compose', - text=>"Compose Message"}); - my $jscript = <<"END"; -function checkAll(field) { - if (field.length > 0) { - for (i = 0; i < field.length; i++) { - field[i].checked = true ; - } - } else { - field.checked = true - } -} - -function uncheckAll(field) { - if (field.length > 0) { - for (i = 0; i < field.length; i++) { - field[i].checked = false ; - } } else { - field.checked = false ; - } -} -END + ({href=>'/adm/notify?command=pick_target', + text=>"Select Audience"}, + {text=>"Compose Message"}); + my $jscript = &Apache::loncommon::check_uncheck_jscript(); my $breadcrumbs = (&Apache::lonhtmlcommon::breadcrumbs (undef,'Broadcast e-mail to users','Broadcast_system_email')); + my %lt=&Apache::lonlocal::texthash( + 'note' => 'Notification E-mail', + 'nore' => 'No recipients identified', + 'emad' => 'e-mail address', + ); $r->print(<<ENDONE); $html <head> - <title>LON-CAPA Notification E-mail</title> + <title>LON-CAPA $lt{'note'}</title> <script type"text/javascript"> $jscript </script> @@ -289,155 +462,172 @@ $jscript $bodytag $breadcrumbs <br /> ENDONE - my $instcode = ''; - my @cats = ('Semester','Year','Department','Number'); - foreach my $category (@cats) { - if (defined($env{'form.'.$category})) { - unless ($env{'form.'.$category} eq '-1') { - $instcode .= $env{'form.'.$category}; + my $coursefilter = $env{'form.coursepick'}; + my %courses = (); + if ($coursefilter eq 'all') { + %courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.'); + } elsif ($coursefilter eq 'category') { + my $instcode = ''; + my @cats = ('Semester','Year','Department','Number'); + foreach my $category (@cats) { + if (defined($env{'form.'.$category})) { + unless ($env{'form.'.$category} eq '-1') { + $instcode .= $env{'form.'.$category}; + } } } + if ($instcode eq '') { + $instcode = '.'; + } + %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.'); + } elsif ($coursefilter eq 'specific') { + if ($env{'form.coursetotal'} > 1) { + my @course_ids = split(/&&/,$env{'form.courselist'}); + foreach (@course_ids) { + $courses{$_} = ''; + } + } else { + $courses{$env{'form.courselist'}} = ''; + } } - if ($instcode eq '') { - $instcode = '.'; - } - my %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.'); + + my @types = &Apache::loncommon::get_env_multiple('form.types'); my @roles = &Apache::loncommon::get_env_multiple('form.roles'); + + my %longtypes = (); + my %authtypes = (); + my %email_defaults = (); + my $table_width = '100%'; + my $col_width = '200'; + + &form_elements(\%longtypes,\%authtypes); + foreach my $auth (keys(%authtypes)) { + if (exists($env{'form.'.$auth})) { + my $default = $env{'form.'.$auth}; + $default =~ s/^,+//; + $default =~ s/,+$//; + if ($auth =~ /^krb/) { + %{$email_defaults{$auth}} = (); + if ($default =~ /,/) { + my @items = split(/,/,$default); + foreach my $item (@items) { + my ($realm,$value) = split(/=/,$item); + $email_defaults{$auth}{$realm} = $value; + } + } else { + my ($realm,$value) = split(/=/,$default); + $email_defaults{$auth}{$realm} = $value; + } + } else { + $email_defaults{$auth} = $default; + } + } + } + + my $sender = &get_user_info($env{'user.name'},%email_defaults); + my %recipients = (); - foreach my $course_id (keys %courses) { - &get_active_users($course_id,\@roles,\%recipients); + my %users = (); + my %access = (); + my $totalrecip = 0; + my @unmatched = (); + foreach my $role (@roles) { + %{$users{$role}} = (); + } + foreach my $type (@types) { + $access{$type} = $type; + } + foreach my $course_id (keys(%courses)) { + my ($cdom,$cnum) = split(/_/,$course_id); + &Apache::loncommon::get_course_users($cdom,$cnum,\%access,\@roles,\%users); + } + foreach my $role (keys(%users)) { + foreach my $user (keys(%{$users{$role}})) { + unless (defined($recipients{$user})) { + $recipients{$user} = &get_user_info($user,%email_defaults); + if ($recipients{$user} eq '') { + push @unmatched, $user; + } else { + $totalrecip ++; + } + } + } } - if (%recipients) { - $r->print('<form name="compose" method="post"> -<input type="hidden" command="process" /> - <table width="580" border="0" cellpadding="0" cellspacing="0" bgcolor="#000000"> - <tr> - <td> - <table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#000000"> - <tr> - <td> - <table width="100%" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff"> - <tr> - <td> - <table width="100%" border="0" cellpadding="0" cellspacing="1" bgcolor="#ffffff"> - <tr> - <td width="140" bgcolor="'.$tablecolor.'"> - <table width="140" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td align="right"><b>Subject:</b> - </td> - </tr> - </table> - </td> - <td width="100%" valign="top"> - <table width="100%" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td><input type="text" name="subject" size="30" /> - </td> - </tr> - </table> - </td> - </tr> - <tr> - <td width="140" bgcolor="'.$tablecolor.'"> - <table width="140" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td align="right">Message:</td> - </td> - </tr> - </table> - </td> - <td width="100%" valign="top"> - <table width="100%" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td> - <textarea name="message" id="message" - cols="60" rows="10" wrap="hard"></textarea> - </td> - </tr> - </table> - </td> - </tr> - <tr> - <td width="140" bgcolor="'.$tablecolor.'"> - <table width="140" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td align="right"><b>Recipients:</b> - </td> - </tr> - </table> - </td> - <td width="100%" valign="top"> - <table width="100%" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td> - <input type="button" value="check all" -onclick="javascript:checkAll(document.compose.email)" /> - <input type="button" value="uncheck all" -onclick="javascript:uncheckAll(document.compose.email)" /><br /> - <table border="0">'); - foreach my $username (sort keys %recipients) { + my $output = '<form name="compose" method="post">'."\n"; + + if ($totalrecip > 0) { + $output .= &Apache::lonhtmlcommon::start_pick_box($table_width); + $output .= &Apache::lonhtmlcommon::row_title($col_width,$tablecolor,&mt('Subject')); + $output .= ' <td><input type="text" name="subject" size="30" /></td>'; + $output .= &Apache::lonhtmlcommon::row_closure(); + $output .= &Apache::lonhtmlcommon::row_title($col_width,$tablecolor,&mt('Message')); + $output .= ' <td><textarea name="message" id="message" + cols="60" rows="10" wrap="hard"></textarea></td>'; + $output .= &Apache::lonhtmlcommon::row_closure(); + $output .= &Apache::lonhtmlcommon::row_title($col_width,$tablecolor,&mt('Recipients')); + $output .= '<td><input type="button" value="check all" + onclick="javascript:checkAll(document.compose.recipient)" /> + <input type="button" value="uncheck all" + onclick="javascript:uncheckAll(document.compose.recipient)" /> + <br /><table border="0">'; + if (keys(%recipients) > 0) { + $output .= '<tr><td> </td><td><small><b>username:domain</b></small></td><td> </td><td><small><b>'.$lt{'emad'}.'</b></small></td></tr>'; + } + foreach my $username (sort(keys(%recipients))) { if ($recipients{$username} =~ /\@/) { my $value=&Apache::lonnet::escape($username).':'.&Apache::lonnet::escape($recipients{$username}); - $r->print('<tr><td><input type="checkbox" name="email" value="'.$value.'" checked="checked" /></td><td>'.$username.'</td><td>'.$recipients{$username}.'</td></tr>'); - $numrecep ++; + $output .= '<tr><td><input type="checkbox" name="recipient" value="'.$value.'" checked="checked" /></td><td>'.$username.'</td><td> </td><td>'.$recipients{$username}.'</td></tr>'; } } - $r->print(' - </table> - </td> - </tr> - </table> - </td> - </tr> - <tr> - <td width="140" bgcolor="'.$tablecolor.'"> - <table width="140" border="0" cellpadding="8" cellspacing="0"> - <tr> - <td align="right"><b>Submit:</b> - </td> - </tr> - </table> - </td> - <td width="100%" valign="top" align="right"> - <br /> - <input type="hidden" name="command" value="compose" /> - <input type="submit" name="sendemail" value="Send Message"/> - <br /><br /> - </td> - </tr> - </table> - </td> - </tr> - </table> - </td> - </tr> - </table> - </td> - </tr> - </table> -</form>'); + $output .= '</table>'; + if (@unmatched) { + $output .= '<br /><br />'.&mt('Could not determine e-mail addresses for the following users:').'<ul>'; + foreach my $username (sort @unmatched) { + $output .= '<li>'.$username.'</li>'; + } + $output .= '</ul>'; + } + $output .= '</td>'; + $output .= &Apache::lonhtmlcommon::row_closure(); + $output .= &Apache::lonhtmlcommon::row_title($col_width,$tablecolor,&mt('Sender e-mail address')); + $output .= '<td><input type="text" name="sender" value="'.$sender.'" /></td>'; + $output .= &Apache::lonhtmlcommon::row_closure(); + $output .= &Apache::lonhtmlcommon::submit_row($col_width,$tablecolor,&mt('Submit'),'process',&mt('Send Message')); + $output .= &Apache::lonhtmlcommon::end_pick_box(); } else { - $r->print('No recipients identified'); + $output .= $lt{'nore'}; } - $r->print('</body></html>'); + $output .= &echo_form_input('command'); + $output .= '</form></body></html>'; + $r->print($output); return; } sub print_request_receipt { - my ($r,$dom) =@_; - my @recipients = &Apache::loncommon::get_env_multiple('recipients'); + my ($r,$dom,$tablecolor,$bodytag,$html,$ltext) =@_; + my @recipients = &Apache::loncommon::get_env_multiple('form.recipient'); my $subject = $env{'form.subject'}; my $message = $env{'form.message'}; - my $function = &Apache::loncommon::get_users_function(); - my $tablecolor = &Apache::loncommon::designparm($function.'.tabbg'); - my $bodytag = &Apache::loncommon::bodytag('Broadcast e-mail to users'); - my $html=&Apache::lonxml::xmlbegin(); - my $jscript; + my $from = $env{'form.sender'}; + my $jscript = <<ENDSCRIPT; +function showCompose() { + document.goback.command.value = 'compose'; + document.goback.submit(); +} +ENDSCRIPT + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/notify?command=pick_target', + text=>"Select audience"}); + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'javascript:showCompose()', + text=>"Compose Message"}); + &Apache::lonhtmlcommon::add_breadcrumb + ({href=>'/adm/notify?command=process', + text=>"Outcome"}); my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs - (undef,'Broadcast e-mail to users','Broadcast_system_email'); - $r->print(<<ENDONE); + (undef,'E-mail Delivery','Broadcast_system_email'); + my $output = <<ENDONE; $html <head> <title>LON-CAPA Notification E-mail</title> @@ -447,51 +637,238 @@ $jscript </head> $bodytag $breadcrumbs +<br /> +<form name="goback" method="post"> ENDONE - $r->print($subject.'<br /><br />'); - $r->print($message.'<br /><br />'); - foreach my $person (@recipients) { - my ($username,$email) = split/:/,$person; - $r->print('user: '.&Apache::lonnet::unescape($username).' email: '.&Apache::lonnet::unescape($email).'<br />'); + $output .= &Apache::lonhtmlcommon::start_pick_box(); + my @deliveries = (); + &broadcast_email(\@recipients,$subject,$from,$message,\@deliveries); + if (@deliveries > 0) { + &store_mail($subject,$message,$dom,\@deliveries); + $output .= '<tr> + <td> + <table cellpadding="4" cellspacing="2" width="100%"> + <tr bgcolor="'.$tablecolor.'" align="center"> + <td><b>Status</b></td> + <td><b>Subject</b></td> + <td><b>Message</b></td> + <td><b>Recipients</b></td> + </tr> + <tr bgcolor="#eeeeee"> + <td valign="middle">Sent</td> + <td valign="middle">'.&cr_to_br($subject).'</td> + <td valign="middle">'.&cr_to_br($message).'</td> + <td>'; + foreach my $person (@deliveries) { + my ($username,$email) = split(/:/,$person); + $output .= &Apache::lonnet::unescape($email).' ('.&Apache::lonnet::unescape($username).')<br />'."\n"; + } + $output .= '</td> + </tr> + </table> + </td> + </tr>'; + &store_mail($subject,$message,$dom,\@deliveries); + } else { + $output .= 'No mail sent - no recipients identified'; } + $output .= &Apache::lonhtmlcommon::end_pick_box(); + $output .= '<br /><a href="/adm/notify">Send another message?</a>'."\n"; + $output .= &echo_form_input(); + $output .= ' +</form> +</body> +</html>'; + $r->print($output); return; } -sub get_active_users { - my ($course_id,$roles,$recipients) = @_; - if (@{$roles} > 0) { - my ($cdom,$cnum) = split/_/,$course_id; - my @coursepersonnel = &Apache::lonnet::getkeys('nohist_userroles',$cdom,$cnum); - foreach my $person (@coursepersonnel) { - my ($role,$user) = ($person =~ /^([^:]*):(.+)$/); - if (($role) && (grep/^$role$/,@{$roles})) { - unless (exists($$recipients{$user})) { - my ($uname,$udom) = split/:/,$user; - if ($uname ne '' && $udom ne '') { - if (&LONCAPA::Enrollment::check_user_status($udom,$uname,$cdom,$cnum,$role) eq 'ok') { - my %userinfo = &Apache::lonnet::get('environment',['permanenetemail','notification','critnotification',],$udom,$uname); - my @emailtypes = ('permanentemail','critnotification','notification'); - my $email = ''; - foreach (@emailtypes) { - $email = $userinfo{$_}; - if ($email =~ /\@/) { - last; - } - } - if ($email eq '') { - my $authinfo = &Apache::lonnet::queryauthenticate($uname,$udom); - my ($authtype,$autharg) = split/:/,$authinfo; - if (($authtype =~ /^krb/) && ($autharg =~ /^MSU/)) { - $email = $uname.'@msu.edu'; - } - } - $$recipients{$user} = $email; - } +sub broadcast_email { + my ($recipients,$subject,$from,$message,$deliveries,$ltext)=@_; +# find some way to spread out delivery for large numbers of recipients. + foreach my $user (@{$recipients}) { + my $msg = new Mail::Send; + my ($username,$to) = split(/:/,$user); + $username = &Apache::lonnet::unescape($username); + $to = &Apache::lonnet::unescape($to); + $msg->to($to); + $msg->subject($subject); + $msg->add('From',"$from"); + if (my $fh = $msg->open()) { + print $fh $message; + $fh->close; + push(@{$deliveries},$user); + } + } +} + +sub get_user_info { + my ($user,%email_defaults) = @_; + my ($uname,$udom) = split(/:/,$user); + my @emailtypes = ('permanentemail','critnotification','notification'); + my %userinfo = &Apache::lonnet::get('environment',\@emailtypes,$udom,$uname); + my $email = ''; + foreach my $type (@emailtypes) { + $email = $userinfo{$type}; + if ($email =~ /\@/) { + last; + } + } + if ($email eq '') { + my $authinfo = &Apache::lonnet::queryauthenticate($uname,$udom); + my ($authtype,$autharg) = split(/:/,$authinfo); + if ($authtype =~ /^krb/) { + if (defined($email_defaults{$authtype}{$autharg})) { + $email = $uname.'@'.$email_defaults{$authtype}{$autharg}; + } + } else { + if ((defined($email_defaults{$authtype})) && ($email_defaults{$authtype} ne '')) { + $email = $uname.'@'.$email_defaults{$authtype}; + } + } + } + return $email; +} + +sub form_elements { + my ($longtypes,$authtypes,$ltext) = @_; + %{$longtypes} = ( + active => 'Currently has access', + previous => 'Previously had access', + future => 'Will have future access', + ); + %{$authtypes} = ( + krb4 => 'Kerberos 4', + krb5 => 'Kerberos 5', + internal => 'Internal (LON-CAPA)', + unix => 'Filesystem (UNIX)', + local => 'Local/Customized', + ); + return; +} + +sub store_mail { + my ($subject,$message,$domain,$recipients,$attachmenturl,$ltext) = @_; + my %servers = (); + my $msgid=&packagemail($subject,$message,$domain, + $recipients,\%servers,$attachmenturl); +# Store in dc email db files on appropriate servers. + foreach my $server (keys(%servers)) { + unless (&Apache::lonnet::dcmailput($domain,$msgid,\%servers,$server) eq 'ok') { + &Apache::lonnet::logthis('Storage of dc mail failed for domain'.$domain.' for server: '. + $server.'. Message ID was '.$msgid); + } + } +} + +sub packagemail { + my ($subject,$message,$dom,$recipients,$servers,$attachmenturl,$ltext) = @_; + my %record = (); + my $partsubj=$subject; + $partsubj=&Apache::lonnet::escape($partsubj); + $message =&HTML::Entities::encode($message,'<>&"'); + $subject =&HTML::Entities::encode($subject,'<>&"'); + #remove machine specification + $attachmenturl =~ s|^http://[^/]+/|/|; + $attachmenturl =&HTML::Entities::encode($attachmenturl,'<>&"'); + my $now=time; + my $msgid= &Apache::lonnet::escape($now).':'.$partsubj.':'. + &Apache::lonnet::escape($env{'user.name'}).':'. + &Apache::lonnet::escape($env{'user.domain'}).':'. + &Apache::lonnet::escape($dom).':'.$$; + my $result='<sendername>'.$env{'user.name'}.'</sendername>'. + '<senderdomain>'.$env{'user.domain'}.'</senderdomain>'. + '<time>'.&Apache::lonlocal::locallocaltime($now).'</time>'. + '<servername>'.$ENV{'SERVER_NAME'}.'</servername>'. + '<host>'.$ENV{'HTTP_HOST'}.'</host>'. + '<client>'.$ENV{'REMOTE_ADDR'}.'</client>'. + '<msgid>'.$msgid.'</msgid>'. + '<dcdomain>'.$dom.'</dcdomain>'. + '<subject>'.$subject.'</subject>'. + '<message>'.$message.'</message>'."\n"; + if (defined($attachmenturl)) { + $result.= '<attachmenturl>'.$attachmenturl.'</attachmenturl>'; + } + foreach my $recip (@{$recipients}) { + my ($username,$email) = split(/:/,$recip); + $username = &Apache::lonnet::unescape($username); + $email = &Apache::lonnet::unescape($email); + my ($uname,$udom) = split(/:/,$username); + my $uhom=&Apache::lonnet::homeserver($uname,$udom); + if ($uhom ne 'no_host') { + $username = &HTML::Entities::encode($username,'<>&"'); + $email = &HTML::Entities::encode($email,'<>&"'); + $record{$uhom} .= '<recipient username="'.$username.'">'. + $email.'</recipient>'; + } + } + foreach my $server (keys(%record)) { + $$servers{$server} = $result.$record{$server}; + } + return $msgid; +} + +sub unpackagemail { + my ($message,$notoken,$ltext)=@_; + my $parser=HTML::TokeParser->new(\$message); + my $token; + my %content=(); + %{$content{recipients}} = (); + while ($token=$parser->get_token()) { + if ($token->[0] eq 'S') { + my $entry=$token->[1]; + my $value=$parser->get_text('/'.$entry); + my ($username,$email); + if ($entry eq 'recipient') { + $username = $token->[2]{'username'}; + $username = &HTML::Entities::decode($username,'<>&"'); + $content{recipients}{$username} = + &HTML::Entities::decode($value,'<>&"'); + } elsif ($entry eq 'subject' || $entry eq 'message') { + $content{$entry}=&HTML::Entities::decode($value,'<>&"'); + } else { + $content{$entry}=$value; + } + } + } + if ($content{'attachmenturl'}) { + my ($fname)=($content{'attachmenturl'}=~m|/([^/]+)$|); + if ($notoken) { + $content{'message'}.='<p>'.&mt('Attachment').': <tt>'.$fname.'</tt>'; } else { + &Apache::lonnet::allowuploaded('/adm/notify', + $content{'attachmenturl'}); + $content{'message'}.='<p>'.&mt('Attachment'). + ': <a href="'.$content{'attachmenturl'}.'"><tt>'. + $fname.'</tt></a>'; + } + } + return %content; +} + +sub echo_form_input { + my (@excluded) = @_; + my $output = ''; + foreach my $key (keys(%env)) { + if ($key =~ /^form\.(.+)$/) { + if ((!@excluded) || (!grep/^$1$/,@excluded)) { + if (ref($env{$key})) { + foreach my $value (@{$env{$key}}) { + $output .= qq(<input type="hidden" name="$1" value="$value" />\n); } + } else { + $output .= qq(<input type="hidden" name="$1" value="$env{$key}" />\n); } } } } + return $output; } +sub cr_to_br { + my $incoming = shift; + $incoming =~ s/\n/\<br \/\>/g; + return $incoming; +} + + 1;