--- loncom/interface/lonmsg.pm 2004/09/09 08:00:12 1.105 +++ loncom/interface/lonmsg.pm 2007/05/10 00:50:52 1.209 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # Routines for messaging # -# $Id: lonmsg.pm,v 1.105 2004/09/09 08:00:12 albertel Exp $ +# $Id: lonmsg.pm,v 1.209 2007/05/10 00:50:52 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,7 +26,6 @@ # http://www.lon-capa.org/ # - package Apache::lonmsg; =pod @@ -37,66 +36,23 @@ Apache::lonmsg: supports internal messag =head1 SYNOPSIS -lonmsg provides routines for sending messages, receiving messages, and -a handler to allow users to read, send, and delete messages. - -=head1 OVERVIEW - -=head2 Messaging Overview - -XLON-CAPA provides an internal messaging system similar to -email, but customized for LON-CAPA's usage. LON-CAPA implements its -own messaging system, rather then building on top of email, because of -the features LON-CAPA messages can offer that conventional e-mail can -not: - -=over 4 - -=item * B: A message the recipient B -acknowlegde receipt of before they are allowed to continue using the -system, preventing a user from claiming they never got a message - -=item * B: LON-CAPA can reliably send reciepts informing the -sender that it has been read; again, useful for preventing students -from claiming they did not see a message. (While conventional e-mail -has some reciept support, it's sporadic, e-mail client-specific, and -generally the receiver can opt to not send one, making it useless in -this case.) - -=item * B: LON-CAPA knows about the sender, such as where -they are in a course. When a student mails an instructor asking for -help on the problem, the instructor receives not just the student's -question, but all submissions the student has made up to that point, -the user's rendering of the problem, and the complete view the student -saw of the resource, including discussion up to that point. Finally, -the instructor is reading all of this inside of LON-CAPA, not their -email program, so they have full access to LON-CAPA's grading -interface, or other features they may wish to use in response to the -student's query. - -=item * B: LON-CAPA can block display of e-mails that are -sent to a student during an online exam. A course coordinator or -instructor can set an open and close date/time for scheduled online -exams in a course. If a user uses the LON-CAPA internal messaging -system to display e-mails during the scheduled blocking event, -display of all e-mail sent during the blocking period will be -suppressed, and a message of explanation, including details of the -currently active blocking periods will be displayed instead. A user -who has a course coordinator or instructor role in a course will be -unaffected by any blocking periods for the course, unless the user -also has a student role in the course, AND has selected the student role. - -=back - -Users can ask LON-CAPA to forward messages to conventional e-mail -addresses on their B screen, but generally, LON-CAPA messages -are much more useful then traditional email can be made to be, even -with HTML support. +lonmsg provides routines for sending messages. Right now, this document will cover just how to send a message, since it is likely you will not need to programmatically read messages, since lonmsg already implements that functionality. +The routines used to package messages and unpackage messages are not +only used by lonmsg when creating/extracting messages for LON-CAPA's +internal messaging system, but also by lonnotify.pm which is available +for use by Domain Coordinators to broadcast standard e-mail to specified +users in their domain. The XML packaging used in the two cases is very +similar. The differences are the use of $uname and +$udom in stored internal messages, compared +with $email in stored +Domain Coordinator e-mail for the storage of information about +recipients of the message/e-mail. + =head1 FUNCTIONS =over 4 @@ -104,24 +60,25 @@ since lonmsg already implements that fun =cut use strict; -use Apache::lonnet(); -use vars qw($msgcount); +use Apache::lonnet; use HTML::TokeParser(); -use Apache::Constants qw(:common); -use Apache::loncommon(); -use Apache::lontexconvert(); -use HTML::Entities(); -use Mail::Send; use Apache::lonlocal; -use Apache::loncommunicate; +use Mail::Send; +use LONCAPA qw(:DEFAULT :match); -# Querystring component with sorting type -my $sqs; +{ + my $uniq; + sub get_uniq { + $uniq++; + return $uniq; + } +} # ===================================================================== Package sub packagemsg { - my ($subject,$message,$citation,$baseurl,$attachmenturl)=@_; + my ($subject,$message,$citation,$baseurl,$attachmenturl, + $recuser,$recdomain,$msgid,$type,$crsmsgid,$symb,$error,$recipid)=@_; $message =&HTML::Entities::encode($message,'<>&"'); $citation=&HTML::Entities::encode($citation,'<>&"'); $subject =&HTML::Entities::encode($subject,'<>&"'); @@ -131,32 +88,58 @@ sub packagemsg { #remove machine specification $attachmenturl =~ s|^http://[^/]+/|/|; $attachmenturl =&HTML::Entities::encode($attachmenturl,'<>&"'); - + my $course_context = &get_course_context(); my $now=time; - $msgcount++; - my $partsubj=$subject; - $partsubj=&Apache::lonnet::escape($partsubj); - my $msgid=&Apache::lonnet::escape( - $now.':'.$partsubj.':'.$ENV{'user.name'}.':'. - $ENV{'user.domain'}.':'.$msgcount.':'.$$); - my $result=''.$ENV{'user.name'}.''. - ''.$ENV{'user.domain'}.''. + my $msgcount = &get_uniq(); + unless(defined($msgid)) { + $msgid = &buildmsgid($now,$subject,$env{'user.name'},$env{'user.domain'}, + $msgcount,$course_context,$symb,$error,$$); + } + my $result = ''.$env{'user.name'}.''. + ''.$env{'user.domain'}.''. ''.$subject.''. - ''. - ''.$ENV{'SERVER_NAME'}.''. + ''; + if (defined($crsmsgid)) { + $result.= ''.$course_context.''. + ''.$env{'request.course.sec'}.''. + ''.$msgid.''. + ''.$crsmsgid.''. + ''.$message.''; + return ($msgid,$result); + } + $result .= ''.$ENV{'SERVER_NAME'}.''. ''.$ENV{'HTTP_HOST'}.''. ''.$ENV{'REMOTE_ADDR'}.''. - ''.$ENV{'browser.type'}.''. - ''.$ENV{'browser.os'}.''. - ''.$ENV{'browser.version'}.''. - ''.$ENV{'browser.mathml'}.''. + ''.$env{'browser.type'}.''. + ''.$env{'browser.os'}.''. + ''.$env{'browser.version'}.''. + ''.$env{'browser.mathml'}.''. ''.$ENV{'HTTP_USER_AGENT'}.''. - ''.$ENV{'request.course.id'}.''. - ''.$ENV{'request.course.sec'}.''. - ''.$ENV{'request.role'}.''. - ''.$ENV{'request.filename'}.''. - ''.$msgid.''. - ''.$message.''; + ''.$course_context.''. + ''.$env{'request.course.sec'}.''. + ''.$env{'request.role'}.''. + ''.$env{'request.filename'}.''. + ''.$msgid.''; + if (ref($recuser) eq 'ARRAY') { + for (my $i=0; $i<@{$recuser}; $i++) { + if ($type eq 'dcmail') { + my ($username,$email) = split(/:/,$$recuser[$i]); + $username = &unescape($username); + $email = &unescape($email); + $username = &HTML::Entities::encode($username,'<>&"'); + $email = &HTML::Entities::encode($email,'<>&"'); + $result .= ''. + $email.''; + } else { + $result .= ''.$$recuser[$i].''. + ''.$$recdomain[$i].''; + } + } + } else { + $result .= ''.$recuser.''. + ''.$recdomain.''; + } + $result .= ''.$message.''; if (defined($citation)) { $result.=''.$citation.''; } @@ -166,7 +149,53 @@ sub packagemsg { if (defined($attachmenturl)) { $result.= ''.$attachmenturl.''; } - return $msgid,$result; + if (defined($symb)) { + $result.= ''.$symb.''; + if ($course_context ne '') { + if ($course_context eq $env{'request.course.id'}) { + my $resource_title = &Apache::lonnet::gettitle($symb); + if (defined($resource_title)) { + $result .= ''.$resource_title.''; + } + } + } + } + if (defined($recipid)) { + $result.= ''.$recipid.''; + } + if ($env{'form.can_reply'} eq 'N') { + $result .= '1'; + } + if ($env{'form.reply_to_addr'}) { + my ($replytoname,$replytodom) = split(/:/,$env{'form.reply_to_addr'}); + if (!($replytoname eq $env{'user.name'} && $replytodom eq $env{'user.domain'})) { + if (&Apache::lonnet::homeserver($replytoname,$replytodom) ne 'no_host') { + $result .= ''.$env{'form.reply_to_addr'}.''; + } + } + } + return ($msgid,$result); +} + +sub get_course_context { + my $course_context; + if (defined($env{'form.replyid'})) { + my ($sendtime,$shortsubj,$fromname,$fromdomain,$count,$origcid)= + split(/\:/,&unescape($env{'form.replyid'})); + $course_context = $origcid; + } + foreach my $key (keys(%env)) { + if ($key=~/^form\.(rep)?rec\_(.*)$/) { + my ($sendtime,$shortsubj,$fromname,$fromdomain,$count,$origcid) = + split(/\:/,&unescape($2)); + $course_context = $origcid; + last; + } + } + if ($course_context eq '') { + $course_context = $env{'request.course.id'}; + } + return $course_context; } # ================================================== Unpack message into a hash @@ -180,9 +209,18 @@ sub unpackagemsg { if ($token->[0] eq 'S') { my $entry=$token->[1]; my $value=$parser->get_text('/'.$entry); - $content{$entry}=$value; + if (($entry eq 'recuser') || ($entry eq 'recdomain')) { + push(@{$content{$entry}},$value); + } elsif ($entry eq 'recipient') { + my $username = $token->[2]{'username'}; + $username = &HTML::Entities::decode($username,'<>&"'); + $content{$entry}{$username} = $value; + } else { + $content{$entry}=$value; + } } } + if (!exists($content{'recuser'})) { $content{'recuser'} = []; } if ($content{'attachmenturl'}) { my ($fname)=($content{'attachmenturl'}=~m|/([^/]+)$|); if ($notoken) { @@ -200,61 +238,152 @@ sub unpackagemsg { # ======================================================= Get info out of msgid +sub buildmsgid { + my ($now,$subject,$uname,$udom,$msgcount,$course_context,$symb,$error,$pid) = @_; + $subject=&escape($subject); + $symb = &escape($symb); + return(&escape($now.':'.$subject.':'.$uname.':'. + $udom.':'.$msgcount.':'.$course_context.':'.$pid.':'.$symb.':'.$error)); +} + sub unpackmsgid { - my $msgid=&Apache::lonnet::unescape(shift); - my ($sendtime,$shortsubj,$fromname,$fromdomain)=split(/\:/, - &Apache::lonnet::unescape($msgid)); - my %status=&Apache::lonnet::get('email_status',[$msgid]); - if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } - unless ($status{$msgid}) { $status{$msgid}='new'; } - return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid}); -} + my ($msgid,$folder,$skipstatus,$status_cache)=@_; + $msgid=&unescape($msgid); + my ($sendtime,$shortsubj,$fromname,$fromdomain,$count,$fromcid, + $processid,$symb,$error) = split(/\:/,&unescape($msgid)); + $shortsubj = &unescape($shortsubj); + $shortsubj = &HTML::Entities::decode($shortsubj); + $symb = &unescape($symb); + if (!defined($processid)) { $fromcid = ''; } + my %status=(); + unless ($skipstatus) { + if (ref($status_cache)) { + $status{$msgid} = $status_cache->{$msgid}; + } else { + my $suffix=&foldersuffix($folder); + %status=&Apache::lonnet::get('email_status'.$suffix,[$msgid]); + } + if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } + unless ($status{$msgid}) { $status{$msgid}='new'; } + } + return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid},$fromcid,$symb,$error); +} sub sendemail { my ($to,$subject,$body)=@_; + my %senderemails=&Apache::loncommon::getemails(); + my $senderaddress=''; + foreach my $type ('notification','permanentemail','critnotification') { + if ($senderemails{$type}) { + $senderaddress=$senderemails{$type}; + } + } $body= "*** ".&mt('This is an automatic message generated by the LON-CAPA system.')."\n". - "*** ".&mt('Please do not reply to this address.')."\n\n".$body; + "*** ".($senderaddress?&mt('You can reply to this message'):&mt('Please do not reply to this address.')."\n*** ". + &mt('A reply will not be received by the recipient!'))."\n\n".$body; my $msg = new Mail::Send; $msg->to($to); $msg->subject('[LON-CAPA] '.$subject); - my %oldENV=%ENV; - undef(%ENV); + if ($senderaddress) { $msg->add('Reply-to',$senderaddress); $msg->add('From',$senderaddress); } if (my $fh = $msg->open()) { print $fh $body; $fh->close; } - %ENV=%oldENV; - undef(%oldENV); } # ==================================================== Send notification emails sub sendnotification { - my ($to,$touname,$toudom,$subj,$crit)=@_; - my $sender=$ENV{'environment.firstname'}.' '.$ENV{'environment.lastname'}; + my ($to,$touname,$toudom,$subj,$crit,$text,$msgid)=@_; + my $sender=$env{'environment.firstname'}.' '.$env{'environment.lastname'}; + unless ($sender=~/\w/) { + $sender=$env{'user.name'}.':'.$env{'user.domain'}; + } my $critical=($crit?' critical':''); + + $text=~s/\<\;/\/gs; my $url='http://'. - $Apache::lonnet::hostname{&Apache::lonnet::homeserver($touname,$toudom)}. + &Apache::lonnet::hostname(&Apache::lonnet::homeserver($touname,$toudom)). '/adm/email?username='.$touname.'&domain='.$toudom; - my $body=(<]+\>//gs; + } + $body = $bodybegin.$bodysubj.$sendtext.$bodyend; + } + &sendemail($addr,$subject,$body); + } + } else { + if ($blocked) { + $body = $bodybegin."\n".$blocktext."\n".$bodyend; + } else { + $text =~ s/\<\/*[^\>]+\>//gs; + $body = $bodybegin.$bodysubj.$text.$bodyend; + } + &sendemail($to,$subject,$body); + } } # ============================================================= Check for email sub newmail { - if ((time-$ENV{'user.mailcheck.time'})>300) { + if ((time-$env{'user.mailcheck.time'})>300) { my %what=&Apache::lonnet::get('email_status',['recnewemail']); &Apache::lonnet::appenv('user.mailcheck.time'=>time); if ($what{'recnewemail'}>0) { return 1; } @@ -279,12 +408,14 @@ sub author_res_msg { my $homeserver=&Apache::lonnet::homeserver($author,$domain); if ($homeserver ne 'no_host') { my $id=unpack("%32C*",$message); + $message .= "

This error occurred on machine ". + $Apache::lonnet::perlvar{'lonHostID'}."

"; my $msgid; ($msgid,$message)=&packagemsg($filename,$message); return &Apache::lonnet::reply('put:'.$domain.':'.$author. ':nohist_res_msgs:'. - &Apache::lonnet::escape($filename.'_'.$id).'='. - &Apache::lonnet::escape($message),$homeserver); + &escape($filename.'_'.$id).'='. + &escape($message),$homeserver); } return 'no_host'; } @@ -294,7 +425,7 @@ sub author_res_msg { sub retrieve_author_res_msg { my $url=shift; $url=&Apache::lonnet::declutter($url); - my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//); + my ($domain,$author)=($url=~/^($match_domain)\/($match_username)\//); my %errormsgs=&Apache::lonnet::dump('nohist_res_msgs',$domain,$author); my $msgs=''; foreach (keys %errormsgs) { @@ -314,7 +445,7 @@ sub retrieve_author_res_msg { sub del_url_author_res_msg { my $url=shift; $url=&Apache::lonnet::declutter($url); - my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//); + my ($domain,$author)=($url=~/^($match_domain)\/($match_username)\//); my @delmsgs=(); foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) { if ($_=~/^\Q$url\E\_\d+$/) { @@ -323,7 +454,20 @@ sub del_url_author_res_msg { } return &Apache::lonnet::del('nohist_res_msgs',\@delmsgs,$domain,$author); } +# =================================== Clear out all author messages in URL path +sub clear_author_res_msg { + my $url=shift; + $url=&Apache::lonnet::declutter($url); + my ($domain,$author)=($url=~/^($match_domain)\/($match_username)\//); + my @delmsgs=(); + foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) { + if ($_=~/^\Q$url\E/) { + push (@delmsgs,$_); + } + } + return &Apache::lonnet::del('nohist_res_msgs',\@delmsgs,$domain,$author); +} # ================= Return hash with URLs for which there is a resource message sub all_url_author_res_msg { @@ -336,44 +480,72 @@ sub all_url_author_res_msg { return %returnhash; } +# ====================================== Add a comment to the User Notes screen + +sub store_instructor_comment { + my ($msg,$uname,$udom) = @_; + my $cid = $env{'request.course.id'}; + my $cnum = $env{'course.'.$cid.'.num'}; + my $cdom = $env{'course.'.$cid.'.domain'}; + my $subject= &mt('Record').' ['.$uname.':'.$udom.']'; + my $result = &user_normal_msg_raw($cnum,$cdom,$subject,$msg); + if ($result eq 'ok' || $result eq 'con_delayed') { + + } + return $result; +} + # ================================================== Critical message to a user sub user_crit_msg_raw { - my ($user,$domain,$subject,$message,$sendback)=@_; + my ($user,$domain,$subject,$message,$sendback,$toperm,$sentmessage, + $nosentstore,$recipid)=@_; # Check if allowed missing - my $status=''; + my ($status,$packed_message); my $msgid='undefined'; unless (($message)&&($user)&&($domain)) { $status='empty'; }; + my $text=$message; my $homeserver=&Apache::lonnet::homeserver($user,$domain); if ($homeserver ne 'no_host') { - ($msgid,$message)=&packagemsg($subject,$message); - if ($sendback) { $message.='true'; } + ($msgid,$packed_message)=&packagemsg($subject,$message,undef,undef, + undef,undef,undef,undef,undef,undef,undef, + undef,$recipid); + if ($sendback) { $packed_message.='true'; } $status=&Apache::lonnet::critical( 'put:'.$domain.':'.$user.':critical:'. - &Apache::lonnet::escape($msgid).'='. - &Apache::lonnet::escape($message),$homeserver); - if ($ENV{'request.course.id'}) { - &user_normal_msg_raw( - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - 'Critical ['.$user.':'.$domain.']', - $message); - } + &escape($msgid).'='. + &escape($packed_message),$homeserver); + if (defined($sentmessage)) { + $$sentmessage = $packed_message; + } + if (!$nosentstore) { + (undef,my $packed_message_no_citation) = + &packagemsg($subject,$message,undef,undef,undef,$user,$domain, + $msgid); + if ($status eq 'ok' || $status eq 'con_delayed') { + &store_sent_mail($msgid,$packed_message_no_citation); + } + } } else { $status='no_host'; } + # Notifications - my %userenv = &Apache::lonnet::get('environment',['critnotification'], - $domain,$user); + my %userenv = &Apache::loncommon::getemails($user,$domain); if ($userenv{'critnotification'}) { - &sendnotification($userenv{'critnotification'},$user,$domain,$subject,1); + &sendnotification($userenv{'critnotification'},$user,$domain,$subject,1, + $text,$msgid); + } + if ($toperm && $userenv{'permanentemail'}) { + &sendnotification($userenv{'permanentemail'},$user,$domain,$subject,1, + $text,$msgid); } # Log this &Apache::lonnet::logthis( 'Sending critical email '.$msgid. ', log status: '. - &Apache::lonnet::log($ENV{'user.domain'},$ENV{'user.name'}, - $ENV{'user.home'}, + &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, + $env{'user.home'}, 'Sending critical '.$msgid.' to '.$user.' at '.$domain.' with status: ' .$status)); return $status; @@ -383,29 +555,45 @@ sub user_crit_msg_raw { =pod -=item * B: Sends - a critical message $message to the $user at $domain. If $sendback is true, - a reciept will be sent to the current user when $user recieves the message. +=item * B: + Sends a critical message $message to the $user at $domain. If $sendback + is true, a receipt will be sent to the current user when $user receives + the message. + + Additionally it will check if the user has a Forwarding address + set, and send the message to that address instead + + returns + - in array context a list of results for each message that was sent + - in scalar context a space seperated list of results for each + message sent =cut sub user_crit_msg { - my ($user,$domain,$subject,$message,$sendback)=@_; - my $status=''; + my ($user,$domain,$subject,$message,$sendback,$toperm,$sentmessage, + $nosentstore,$recipid)=@_; + my @status; my %userenv = &Apache::lonnet::get('environment',['msgforward'], $domain,$user); my $msgforward=$userenv{'msgforward'}; if ($msgforward) { - foreach (split(/\,/,$msgforward)) { - my ($forwuser,$forwdomain)=split(/\:/,$_); - $status.= - &user_crit_msg_raw($forwuser,$forwdomain,$subject,$message, - $sendback).' '; + foreach my $addr (split(/\,/,$msgforward)) { + my ($forwuser,$forwdomain)=split(/\:/,$addr); + push(@status, + &user_crit_msg_raw($forwuser,$forwdomain,$subject,$message, + $sendback,$toperm,$sentmessage,$nosentstore, + $recipid)); } } else { - $status=&user_crit_msg_raw($user,$domain,$subject,$message,$sendback); + push(@status, + &user_crit_msg_raw($user,$domain,$subject,$message,$sendback, + $toperm,$sentmessage,$nosentstore,$recipid)); } - return $status; + if (wantarray) { + return @status; + } + return join(' ',@status); } # =================================================== Critical message received @@ -414,21 +602,31 @@ sub user_crit_received { my $msgid=shift; my %message=&Apache::lonnet::get('critical',[$msgid]); my %contents=&unpackagemsg($message{$msgid},1); + my $destname = $contents{'sendername'}; + my $destdom = $contents{'senderdomain'}; + if ($contents{'replytoaddr'}) { + my ($repname,$repdom) = split(/:/,$contents{'replytoaddr'}); + if (&Apache::lonnet::homeserver($repname,$repdom) ne 'no_host') { + $destname = $repname; + $destdom = $repdom; + } + } my $status='rec: '.($contents{'sendback'}? - &user_normal_msg($contents{'sendername'},$contents{'senderdomain'}, - &mt('Receipt').': '.$ENV{'user.name'}.' '.&mt('at').' '.$ENV{'user.domain'}.', '.$contents{'subject'}, - &mt('User').' '.$ENV{'user.name'}.' '.&mt('at').' '.$ENV{'user.domain'}. - ' acknowledged receipt of message'."\n".' "'. - $contents{'subject'}.'"'."\n".&mt('dated').' '. - $contents{'time'}.".\n" - ):'no msg req'); + &user_normal_msg($destname,$destdom,&mt('Receipt').': '.$env{'user.name'}. + ' '.&mt('at').' '.$env{'user.domain'}.', '. + $contents{'subject'},&mt('User').' '.$env{'user.name'}. + ' '.&mt('at').' '.$env{'user.domain'}. + ' acknowledged receipt of message'."\n".' "'. + $contents{'subject'}.'"'."\n".&mt('dated').' '. + $contents{'time'}.".\n" + ):'no msg req'); $status.=' trans: '. &Apache::lonnet::put( 'nohist_email',{$contents{'msgid'} => $message{$msgid}}); $status.=' del: '. &Apache::lonnet::del('critical',[$contents{'msgid'}]); - &Apache::lonnet::log($ENV{'user.domain'},$ENV{'user.name'}, - $ENV{'user.home'},'Received critical message '. + &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, + $env{'user.home'},'Received critical message '. $contents{'msgid'}. ', '.$status); return $status; @@ -437,33 +635,60 @@ sub user_crit_received { # ======================================================== Normal communication sub user_normal_msg_raw { - my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl)=@_; + my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl, + $toperm,$currid,$newid,$sentmessage,$crsmsgid,$symb,$restitle, + $error,$nosentstore,$recipid)=@_; # Check if allowed missing - my $status=''; + my ($status,$packed_message); my $msgid='undefined'; + my $text=$message; unless (($message)&&($user)&&($domain)) { $status='empty'; }; my $homeserver=&Apache::lonnet::homeserver($user,$domain); if ($homeserver ne 'no_host') { - ($msgid,$message)=&packagemsg($subject,$message,$citation,$baseurl, - $attachmenturl); + ($msgid,$packed_message)= + &packagemsg($subject,$message,$citation,$baseurl, + $attachmenturl,$user,$domain,$currid, + undef,$crsmsgid,$symb,$error,$recipid); + +# Store in user folder $status=&Apache::lonnet::critical( 'put:'.$domain.':'.$user.':nohist_email:'. - &Apache::lonnet::escape($msgid).'='. - &Apache::lonnet::escape($message),$homeserver); + &escape($msgid).'='. + &escape($packed_message),$homeserver); +# Save new message received time &Apache::lonnet::put ('email_status',{'recnewemail'=>time},$domain,$user); - } else { - $status='no_host'; - } +# Into sent-mail folder if sent mail storage required + if (!$nosentstore) { + (undef,my $packed_message_no_citation) = + &packagemsg($subject,$message,undef,$baseurl,$attachmenturl, + $user,$domain,$currid,undef,$crsmsgid,$symb,$error); + if ($status eq 'ok' || $status eq 'con_delayed') { + &store_sent_mail($msgid,$packed_message_no_citation); + } + } + if (ref($newid) eq 'SCALAR') { + $$newid = $msgid; + } + if (ref($sentmessage) eq 'SCALAR') { + $$sentmessage = $packed_message; + } # Notifications - my %userenv = &Apache::lonnet::get('environment',['notification'], - $domain,$user); - if ($userenv{'notification'}) { - &sendnotification($userenv{'notification'},$user,$domain,$subject,0); - } - &Apache::lonnet::log($ENV{'user.domain'},$ENV{'user.name'}, - $ENV{'user.home'}, - 'Sending '.$msgid.' to '.$user.' at '.$domain.' with status: '.$status); + my %userenv = &Apache::loncommon::getemails($user,$domain); + if ($userenv{'notification'}) { + &sendnotification($userenv{'notification'},$user,$domain,$subject,0, + $text,$msgid); + } + if ($toperm && $userenv{'permanentemail'}) { + &sendnotification($userenv{'permanentemail'},$user,$domain,$subject,0, + $text,$msgid); + } + &Apache::lonnet::log($env{'user.domain'},$env{'user.name'}, + $env{'user.home'}, + 'Sending '.$msgid.' to '.$user.' at '.$domain.' with status: '.$status); + } else { + $status='no_host'; + } return $status; } @@ -471,1277 +696,227 @@ sub user_normal_msg_raw { =pod -=item * B: Sends a message to the - $user at $domain, with subject $subject and message $message. +=item * B: + Sends a message to the $user at $domain, with subject $subject and message $message. + + Additionally it will check if the user has a Forwarding address + set, and send the message to that address instead + + returns + - in array context a list of results for each message that was sent + - in scalar context a space seperated list of results for each + message sent =cut sub user_normal_msg { - my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl)=@_; - my $status=''; + my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl, + $toperm,$sentmessage,$symb,$restitle,$error,$nosentstore,$recipid)=@_; + my @status; my %userenv = &Apache::lonnet::get('environment',['msgforward'], $domain,$user); my $msgforward=$userenv{'msgforward'}; if ($msgforward) { - foreach (split(/\,/,$msgforward)) { - my ($forwuser,$forwdomain)=split(/\:/,$_); - $status.= - &user_normal_msg_raw($forwuser,$forwdomain,$subject,$message, - $citation,$baseurl,$attachmenturl).' '; - } - } else { - $status=&user_normal_msg_raw($user,$domain,$subject,$message, - $citation,$baseurl,$attachmenturl); - } + foreach (split(/\,/,$msgforward)) { + my ($forwuser,$forwdomain)=split(/\:/,$_); + push(@status, + &user_normal_msg_raw($forwuser,$forwdomain,$subject,$message, + $citation,$baseurl,$attachmenturl,$toperm, + undef,undef,$sentmessage,undef,$symb, + $restitle,$error,$nosentstore,$recipid)); + } + } else { + push(@status,&user_normal_msg_raw($user,$domain,$subject,$message, + $citation,$baseurl,$attachmenturl,$toperm, + undef,undef,$sentmessage,undef,$symb, + $restitle,$error,$nosentstore,$recipid)); + } + if (wantarray) { + return @status; + } + return join(' ',@status); +} + +sub process_sent_mail { + my ($msgsubj,$subj_prefix,$numsent,$stamp,$msgname,$msgdom,$msgcount,$context,$pid,$savemsg,$recusers,$recudoms,$baseurl,$attachmenturl,$symb,$error,$senderuname,$senderdom,$senderhome) = @_; + my $sentsubj; + if ($numsent > 1) { + $sentsubj = $subj_prefix.' ('.$numsent.' sent) '.$msgsubj; + } else { + if ($subj_prefix) { + $sentsubj = $subj_prefix.' '; + } + $sentsubj .= $msgsubj; + } + $sentsubj = &HTML::Entities::encode($sentsubj,'<>&"'); + my $sentmsgid = + &buildmsgid($stamp,$sentsubj,$msgname,$msgdom,$msgcount,$context,$pid); + (undef,my $sentmessage) = + &packagemsg($msgsubj,$savemsg,undef,$baseurl,$attachmenturl,$recusers, + $recudoms,$sentmsgid,undef,undef,$symb,$error); + my $status = &store_sent_mail($sentmsgid,$sentmessage,$senderuname, + $senderdom,$senderhome); return $status; } - -# =============================================================== Status Change - -sub statuschange { - my ($msgid,$newstatus)=@_; - my %status=&Apache::lonnet::get('email_status',[$msgid]); - if ($status{$msgid}=~/^error\:/) { $status{$msgid}=''; } - unless ($status{$msgid}) { $status{$msgid}='new'; } - unless (($status{$msgid} eq 'replied') || - ($status{$msgid} eq 'forwarded')) { - &Apache::lonnet::put('email_status',{$msgid => $newstatus}); - } - if (($newstatus eq 'deleted') || ($newstatus eq 'new')) { - &Apache::lonnet::put('email_status',{$msgid => $newstatus}); - } -} - -# ======================================================= Display a course list - -sub discourse { - my $r=shift; - my %courselist=&Apache::lonnet::dump( - 'classlist', - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}); - my $now=time; - my %lt=&Apache::lonlocal::texthash('cfa' => 'Check for All', - 'cfs' => 'Check for Section/Group', - 'cfn' => 'Check for None'); - $r->print(< - -  - -  - -

-ENDDISHEADER - my %coursepersonnel= - &Apache::lonnet::get_course_adv_roles(); - foreach my $role (sort keys %coursepersonnel) { - foreach (split(/\,/,$coursepersonnel{$role})) { - my ($puname,$pudom)=split(/\:/,$_); - $r->print( - '
'. - &Apache::loncommon::plainname($puname, - $pudom).' ('.$_.'), '.$role.''); - } - } - - foreach (sort keys %courselist) { - my ($end,$start)=split(/\:/,$courselist{$_}); - my $active=1; - if (($end) && ($now>$end)) { $active=0; } - if ($active) { - my ($sname,$sdom)=split(/\:/,$_); - my %reply=&Apache::lonnet::get('environment', - ['firstname','middlename','lastname','generation'], - $sdom,$sname); - my $section=&Apache::lonnet::usection - ($sdom,$sname,$ENV{'request.course.id'}); - $r->print( - '
'. - $reply{'firstname'}.' '. - $reply{'middlename'}.' '. - $reply{'lastname'}.' '. - $reply{'generation'}. - ' ('.$_.') '.$section); - } - } -} - -# ==================================================== Display Critical Message - -sub discrit { - my $r=shift; - my $header = '

'.&mt('Critical Messages').'

'. - '
'. - ''; - my %what=&Apache::lonnet::dump('critical'); - my $result = ''; - foreach (sort keys %what) { - my %content=&unpackagemsg($what{$_}); - next if ($content{'senderdomain'} eq ''); - $content{'message'}=~s/\n/\/g; - $result.='
'.&mt('From').': '. -&Apache::loncommon::aboutmewrapper( - &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).' ('. -$content{'sendername'}.'@'. - $content{'senderdomain'}.') '.$content{'time'}. - '
'.&mt('Subject').': '.$content{'subject'}. - '
'. - &Apache::lontexconvert::msgtexconverted($content{'message'}). - '
'. -&mt('You have to confirm that you received this message. After confirmation, this message will be moved to your regular inbox'). - '
'. - ''. - ''; - } - # Check to see if there were any messages. - if ($result eq '') { - $result = "

".&mt('You have no critical messages.')."

". - ''.&mt('Select a course').''; - } else { - $r->print($header); - } - $r->print($result); - $r->print(''); -} - -sub sortedmessages { - my ($blocked,$startblock,$endblock,$numblocked) = @_; - my @messages = &Apache::lonnet::getkeys('nohist_email'); - #unpack the varibles and repack into temp for sorting - my @temp; - foreach (@messages) { - my $msgid=&Apache::lonnet::escape($_); - my ($sendtime,$shortsubj,$fromname,$fromdomain,$status)= - &Apache::lonmsg::unpackmsgid($msgid); - my @temp1 = ($sendtime,$shortsubj,$fromname,$fromdomain,$status, - $msgid); - # Check whether message was sent during blocking period. - if ($sendtime >= $startblock && ($sendtime <= $endblock && $endblock > 0) ) { - my $escid = &Apache::lonnet::unescape($msgid); - $$blocked{$escid} = 'ON'; - $$numblocked ++; - } else { - push @temp ,\@temp1; - } - } - #default sort - @temp = sort {$a->[0] <=> $b->[0]} @temp; - if ($ENV{'form.sortedby'} eq "date"){ - @temp = sort {$a->[0] <=> $b->[0]} @temp; - } - if ($ENV{'form.sortedby'} eq "revdate"){ - @temp = sort {$b->[0] <=> $a->[0]} @temp; - } - if ($ENV{'form.sortedby'} eq "user"){ - @temp = sort {lc($a->[2]) cmp lc($b->[2])} @temp; - } - if ($ENV{'form.sortedby'} eq "revuser"){ - @temp = sort {lc($b->[2]) cmp lc($a->[2])} @temp; - } - if ($ENV{'form.sortedby'} eq "domain"){ - @temp = sort {$a->[3] cmp $b->[3]} @temp; - } - if ($ENV{'form.sortedby'} eq "revdomain"){ - @temp = sort {$b->[3] cmp $a->[3]} @temp; - } - if ($ENV{'form.sortedby'} eq "subject"){ - @temp = sort {lc($a->[1]) cmp lc($b->[1])} @temp; - } - if ($ENV{'form.sortedby'} eq "revsubject"){ - @temp = sort {lc($b->[1]) cmp lc($a->[1])} @temp; - } - if ($ENV{'form.sortedby'} eq "status"){ - @temp = sort {$a->[4] cmp $b->[4]} @temp; - } - if ($ENV{'form.sortedby'} eq "revstatus"){ - @temp = sort {$b->[4] cmp $a->[4]} @temp; - } - return @temp; -} - -# ======================================================== Display all messages - -sub disall { - my $r=shift; - my %blocked = (); - my %setters = (); - my $startblock; - my $endblock; - my $numblocked = 0; - &blockcheck(\%setters,\$startblock,\$endblock); - $r->print(< - function checkall() { - for (i=0; i -ENDDISHEADER - $r->print('

'.&mt('Display All Messages').'

'. - ''); - } else { - $r->print(''.&mt('Date').''); - } - $r->print(''); - } else { - $r->print(''.&mt('Status').''); - } - $r->print(''); - my @temp=sortedmessages(\%blocked,$startblock,$endblock,\$numblocked); - foreach (@temp){ - my ($sendtime,$shortsubj,$fromname,$fromdomain,$status,$origID)= @$_; - if (($status ne 'deleted') && defined($sendtime) && $sendtime!~/error/) { - if ($status eq 'new') { - $r->print(''); - } elsif ($status eq 'read') { - $r->print(''); - } elsif ($status eq 'replied') { - $r->print(''); - } else { - $r->print(''); - } - $r->print(''. - ''); - } - } - $r->print('
 '); - if ($ENV{'form.sortedby'} eq "revdate") { - $r->print(''.&mt('Date').''); - if ($ENV{'form.sortedby'} eq "revuser") { - $r->print(''.&mt('Username').''); - } else { - $r->print(''.&mt('Username').''); - } - $r->print(''); - if ($ENV{'form.sortedby'} eq "revdomain") { - $r->print(''.&mt('Domain').''); - } else { - $r->print(''.&mt('Domain').''); - } - $r->print(''); - if ($ENV{'form.sortedby'} eq "revsubject") { - $r->print(''.&mt('Subject').''); - } else { - $r->print(''.&mt('Subject').''); - } - $r->print(''); - if ($ENV{'form.sortedby'} eq "revstatus") { - $r->print(''.&mt('Status').'
'.&mt('Open').''.&mt('Delete').''.&Apache::lonlocal::locallocaltime($sendtime).''. - $fromname.''.$fromdomain.''. - &Apache::lonnet::unescape($shortsubj).''. - $status.'

'. - ''.&mt('Check All').' '. - ''.&mt('Uncheck All').'

'. - ''. - ''. - '

'); - if ($numblocked > 0) { - my $beginblock = &Apache::lonlocal::locallocaltime($startblock); - my $finishblock = &Apache::lonlocal::locallocaltime($endblock); - $r->print('

'. - $numblocked.' '.&mt('message(s) is/are not viewable because display of LON-CAPA messages sent to you by other students between').' '.$beginblock.' '.&mt('and').' '.$finishblock.' '.&mt('is currently being blocked because of online exams.')); - &build_block_table($r,$startblock,$endblock,\%setters); - } - $r->print(''); -} - -# ============================================================== Compose output - -sub compout { - my ($r,$forwarding,$replying,$broadcast,$replycrit)=@_; - - if ($broadcast eq 'individual') { - &printheader($r,'/adm/email?compose=individual', - 'Send a Message'); - } elsif ($broadcast) { - &printheader($r,'/adm/email?compose=group', - 'Broadcast Message'); - } elsif ($forwarding) { - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/email?display=".&Apache::lonnet::escape($forwarding), - text=>"Display Message"}); - &printheader($r,'/adm/email?forward='.&Apache::lonnet::escape($forwarding), - 'Forwarding a Message'); - } elsif ($replying) { - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/email?display=".&Apache::lonnet::escape($replying), - text=>"Display Message"}); - &printheader($r,'/adm/email?replyto='.&Apache::lonnet::escape($replying), - 'Replying to a Message'); - } elsif ($replycrit) { - $r->print('

'.&mt('Replying to a Critical Message').'

'); - $replying=$replycrit; - } else { - &printheader($r,'/adm/email?compose=upload', - 'Distribute from Uploaded File'); - } - - my $dispcrit=''; - my $dissub=''; - my $dismsg=''; - my $func=&mt('Send New'); - my %lt=&Apache::lonlocal::texthash('us' => 'Username', - 'do' => 'Domain', - 'ad' => 'Additional Recipients', - 'sb' => 'Subject', - 'ca' => 'Cancel', - 'ma' => 'Mail'); - - if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { - my $crithelp = Apache::loncommon::help_open_topic("Course_Critical_Message"); - $dispcrit= - ' '.&mt('Send as critical message').' ' . $crithelp . - '
'. - ' '.&mt('Send as critical message').' ' . - &mt('and return receipt') . $crithelp . '

'; - } - my %message; - my %content; - my $defdom=$ENV{'user.domain'}; - if ($forwarding) { - %message=&Apache::lonnet::get('nohist_email',[$forwarding]); - %content=&unpackagemsg($message{$forwarding}); - $dispcrit.=''; - $func=&mt('Forward'); - - $dissub=&mt('Forwarding').': '.$content{'subject'}; - $dismsg=&mt('Forwarded message from').' '. - $content{'sendername'}.' '.&mt('at').' '.$content{'senderdomain'}; - } - if ($replying) { - %message=&Apache::lonnet::get('nohist_email',[$replying]); - %content=&unpackagemsg($message{$replying}); - $dispcrit.=''; - $func=&mt('Replying to'); - - $dissub=&mt('Reply').': '.$content{'subject'}; - $dismsg='> '.$content{'message'}; - $dismsg=~s/\r/\n/g; - $dismsg=~s/\f/\n/g; - $dismsg=~s/\n+/\n\> /g; - } - if ($ENV{'form.recdom'}) { $defdom=$ENV{'form.recdom'}; } - $r->print( - '

'."\n". - ''."\n". - ''); - unless (($broadcast eq 'group') || ($broadcast eq 'upload')) { - if ($replying) { - $r->print(''); - } else { - my $domform = &Apache::loncommon::select_dom_form($defdom,'recdomain'); - my $selectlink=&Apache::loncommon::selectstudent_link - ('compemail','recuname','recdomain'); - $r->print(<<"ENDREC"); - - - -ENDREC - } - } - my $latexHelp = Apache::loncommon::helpLatexCheatsheet(); - if ($broadcast ne 'upload') { - $r->print(<<"ENDCOMP"); - -
'.&mt('Replying to').' '. - &Apache::loncommon::aboutmewrapper( - &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).' ('. - $content{'sendername'}.'@'. - $content{'senderdomain'}.')'. - ''. - ''. - '
$lt{'us'}:$selectlink
$lt{'do'}:$domform
$lt{'ad'}
username\@domain,username\@domain, ... -
-
$lt{'sb'}: -
-$latexHelp -


-$dispcrit - - -ENDCOMP - } else { # $broadcast is 'upload' - $r->print(< - -

Generate messages from a file

-

-Subject: -

-

General message text
-

-

-The file format for the uploaded portion of the message is: -

-username1\@domain1: text
-username2\@domain2: text
-username3\@domain1: text
-
-

-

-The messages will be assembled from all lines with the respective -username\@domain, and appended to the general message text.

-

-

-$dispcrit -

-ENDUPLOAD - } - if ($broadcast eq 'group') { - &discourse; - } - $r->print(''); -} - -# ---------------------------------------------------- Display all face to face - -sub retrieve_instructor_comments { - my ($user,$domain)=@_; - my $target=$ENV{'form.grade_target'}; - if (! $ENV{'request.course.id'}) { return; } - if (! &Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { - return; - } - my %records=&Apache::lonnet::dump('nohist_email', - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, - '%255b'.$user.'%253a'.$domain.'%255d'); - my $result=''; - foreach (sort(keys(%records))) { - my %content=&unpackagemsg($records{$_}); - next if ($content{'senderdomain'} eq ''); - next if ($content{'subject'} !~ /^Record/); - # $content{'message'}=~s/\n/\/g; - $result.='Recorded by '. - $content{'sendername'}.'@'.$content{'senderdomain'}."\n"; - $result.= - &Apache::lontexconvert::msgtexconverted($content{'message'})."\n"; - } - return $result; -} - -sub disfacetoface { - my ($r,$user,$domain)=@_; - my $target=$ENV{'form.grade_target'}; - unless ($ENV{'request.course.id'}) { return; } - unless (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { - return; - } - my %records=&Apache::lonnet::dump('nohist_email', - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, - '%255b'.$user.'%253a'.$domain.'%255d'); - my $result=''; - foreach (sort keys %records) { - my %content=&unpackagemsg($records{$_}); - next if ($content{'senderdomain'} eq ''); - $content{'message'}=~s/\n/\/g; - if ($content{'subject'}=~/^Record/) { - $result.='

'.&mt('Record').'

'; - } elsif ($content{'subject'}=~/^Broadcast/) { - $result .='

'.&mt('Broadcast Message').'

'; - } else { - $result.='

'.&mt('Critical Message').'

'; - %content=&unpackagemsg($content{'message'}); - $content{'message'}= - ''.&mt('Subject').': '.$content{'subject'}.'
'. - $content{'message'}; - } - $result.=&mt('By').': '. -&Apache::loncommon::aboutmewrapper( - &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}),$content{'sendername'},$content{'senderdomain'}).' ('. -$content{'sendername'}.'@'. - $content{'senderdomain'}.') '.$content{'time'}. - '
'. - &Apache::lontexconvert::msgtexconverted($content{'message'}). - '
'; - } - # Check to see if there were any messages. - if ($result eq '') { - if ($target ne 'tex') { - $r->print("

".&mt("No notes, face-to-face discussion records, critical messages, or broadcast messages in this course.")."

"); - } else { - $r->print('\textbf{'.&mt("No notes, face-to-face discussion records, critical messages or broadcast messages in this course.").'}\\\\'); - } - } else { - $r->print($result); - } -} - -# ---------------------------------------------------------------- Face to face - -sub facetoface { - my ($r,$stage)=@_; - unless (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { - return; - } - &printheader($r, - '/adm/email?recordftf=query', - "User Notes, Face-to-Face, Critical Messages, Broadcast Messages"); -# from query string - - if ($ENV{'form.recname'}) { $ENV{'form.recuname'}=$ENV{'form.recname'}; } - if ($ENV{'form.recdom'}) { $ENV{'form.recdomain'}=$ENV{'form.recdom'}; } - - my $defdom=$ENV{'user.domain'}; -# already filled in - if ($ENV{'form.recdomain'}) { $defdom=$ENV{'form.recdomain'}; } -# generate output - my $domform = &Apache::loncommon::select_dom_form($defdom,'recdomain'); - my $stdbrws = &Apache::loncommon::selectstudent_link - ('stdselect','recuname','recdomain'); - my %lt=&Apache::lonlocal::texthash('user' => 'Username', - 'dom' => 'Domain', - 'head' => 'User Notes, Records of Face-To-Face Discussions, Critical Messages, and Broadcast Messages in Course', - 'subm' => 'Retrieve discussion and message records', - 'newr' => 'New Record (record is visible to course faculty and staff)', - 'post' => 'Post this Record'); - $r->print(<<"ENDTREC"); -

$lt{'head'}

-
- - - - - - - -
$lt{'user'}: -$stdbrws -
$lt{'dom'}:$domform
-
-ENDTREC - if (($stage ne 'query') && - ($ENV{'form.recdomain'}) && ($ENV{'form.recuname'})) { - chomp($ENV{'form.newrecord'}); - if ($ENV{'form.newrecord'}) { - &user_normal_msg_raw( - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - &mt('Record'). - ' ['.$ENV{'form.recuname'}.':'.$ENV{'form.recdomain'}.']', - $ENV{'form.newrecord'}); - } - $r->print('

'.&Apache::loncommon::plainname($ENV{'form.recuname'}, - $ENV{'form.recdomain'}).'

'); - &disfacetoface($r,$ENV{'form.recuname'},$ENV{'form.recdomain'}); - $r->print(< - - -ENDRHEAD - $r->print(<$lt{'newr'}
- -
- - - -ENDBFORM - } -} - -# ----------------------------------------------------------- Blocking during exams - -sub examblock { - my ($r,$action) = @_; - unless ($ENV{'request.course.id'}) { return;} - unless (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) { $r->print('Not allowed'); } - my %lt=&Apache::lonlocal::texthash( - 'comb' => 'Communication Blocking', - 'cbds' => 'Communication blocking during scheduled exams', - 'desc' => 'You can use communication blocking to prevent students enrolled in this course from displaying LON-CAPA messages sent by other students during an online exam. As blocking of communication could potentially interrupt legitimate communication between students who are also both enrolled in a different LON-CAPA course, please be careful that you select the correct start and end times for your scheduled exam when setting or modifying these parameters.', - 'mecb' => 'Modify existing communication blocking periods', - 'ncbc' => 'No communication blocks currently stored' - ); - - my %ltext = &Apache::lonlocal::texthash( - 'dura' => 'Duration', - 'setb' => 'Set by', - 'even' => 'Event', - 'actn' => 'Action', - 'star' => 'Start', - 'endd' => 'End' - ); - - &printheader($r,'/adm/email?block=display',$lt{'comb'}); - $r->print('

'.$lt{'cbds'}.'

'); - - if ($action eq 'store') { - &blockstore($r); - } - - $r->print($lt{'desc'}.'

-
- '); - - $r->print('

'.$lt{'mecb'}.'

'); - my %records = (); - my $blockcount = 0; - my $parmcount = 0; - &get_blockdates(\%records,\$blockcount); - if ($blockcount > 0) { - $parmcount = &display_blocker_status($r,\%records,\%ltext); - } else { - $r->print($lt{'ncbc'}.'

'); - } - &display_addblocker_table($r,$parmcount,\%ltext); - $r->print(<<"END"); -
- - -
- - -END - return; -} - -sub blockstore { - my $r = shift; - my %lt=&Apache::lonlocal::texthash( - 'tfcm' => 'The following changes were made', - 'cbps' => 'communication blocking period(s)', - 'werm' => 'was/were removed', - 'wemo' => 'was/were modified', - 'wead' => 'was/were added', - 'ncwm' => 'No changes were made.' - ); - my %adds = (); - my %removals = (); - my %cancels = (); - my $modtotal = 0; - my $canceltotal = 0; - my $addtotal = 0; - my %blocking = (); - $r->print('

'.$lt{'head'}.'

'); - foreach (keys %ENV) { - if ($_ =~ m/^form\.modify_(\w+)$/) { - $adds{$1} = $1; - $removals{$1} = $1; - $modtotal ++; - } elsif ($_ =~ m/^form\.cancel_(\d+)$/) { - $cancels{$1} = $1; - unless ( defined($removals{$1}) ) { - $removals{$1} = $1; - $canceltotal ++; - } - } elsif ($_ =~ m/^form\.add_(\d+)$/) { - $adds{$1} = $1; - $addtotal ++; - } - } - - foreach (keys %removals) { - my $hashkey = $ENV{'form.key_'.$_}; - &Apache::lonnet::del('comm_block',["$hashkey"], - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'} - ); - } - foreach (keys %adds) { - unless ( defined($cancels{$_}) ) { - my ($newstart,$newend) = &get_dates_from_form($_); - my $newkey = $newstart.'____'.$newend; - $blocking{$newkey} = $ENV{'user.name'}.'@'.$ENV{'user.domain'}.':'.$ENV{'form.title_'.$_}; - } - } - if ($addtotal + $modtotal > 0) { - &Apache::lonnet::put('comm_block',\%blocking, - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'} - ); - } - my $chgestotal = $canceltotal + $modtotal + $addtotal; - if ($chgestotal > 0) { - $r->print($lt{'tfcm'}.'
    '); - if ($canceltotal > 0) { - $r->print('
  • '.$canceltotal.' '.$lt{'cbps'},' '.$lt{'werm'}.'
  • '); - } - if ($modtotal > 0) { - $r->print('
  • '.$modtotal.' '.$lt{'cbps'},' '.$lt{'wemo'}.'
  • '); - } - if ($addtotal > 0) { - $r->print('
  • '.$addtotal.' '.$lt{'cbps'},' '.$lt{'wead'}.'
  • '); - } - $r->print('
'); - } else { - $r->print($lt{'ncwm'}); - } - $r->print('
'); - return; -} - -sub get_dates_from_form { - my $item = shift; - my $startdate = &Apache::lonhtmlcommon::get_date_from_form('startdate_'.$item); - my $enddate = &Apache::lonhtmlcommon::get_date_from_form('enddate_'.$item); - return ($startdate,$enddate); -} - -sub get_blockdates { - my ($records,$blockcount) = @_; - $$blockcount = 0; - %{$records} = &Apache::lonnet::dump('comm_block', - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.num'} - ); - $$blockcount = keys %{$records}; - - foreach (keys %{$records}) { - if ($_ eq 'error: 2 tie(GDBM) Failed while attempting dump') { - $$blockcount = 0; - last; - } - } +sub store_sent_mail { + my ($msgid,$message,$senderuname,$senderdom,$senderhome) = @_; + if ($senderuname eq '') { + $senderuname = $env{'user.name'}; + } + if ($senderdom eq '') { + $senderdom = $env{'user.domain'}; + } + if ($senderhome eq '') { + $senderhome = $env{'user.home'}; + } + my $status =' '.&Apache::lonnet::critical( + 'put:'.$senderdom.':'.$senderuname.':nohist_email_sent:'. + &escape($msgid).'='.&escape($message),$senderhome); + return $status; } -sub display_blocker_status { - my ($r,$records,$ltext) = @_; - my $parmcount = 0; - my @bgcols = ("#eeeeee","#dddddd"); - my $function = &Apache::loncommon::get_users_function(); - my $color = &Apache::loncommon::designparm($function.'.tabbg', - $ENV{'user.domain'}); - my %lt = &Apache::lonlocal::texthash( - 'modi' => 'Modify', - 'canc' => 'Cancel', - ); - $r->print(<<"END"); - - - - -
- - - - -
- - - - - - - -END - foreach (sort keys %{$records}) { - my $iter = $parmcount%2; - my $onchange = 'onFocus="javascript:window.document.forms['. - "'blockform'].elements['modify_".$parmcount."'].". - 'checked=true;"'; - my ($start,$end) = split/____/,$_; - my $startform = &Apache::lonhtmlcommon::date_setter('blockform','startdate_'.$parmcount,$start,$onchange); - my $endform = &Apache::lonhtmlcommon::date_setter('blockform','enddate_'.$parmcount,$end,$onchange); - my ($setter,$title) = split/:/,$$records{$_}; - my ($setuname,$setudom) = split/@/,$setter; - my $settername = &Apache::loncommon::plainname($setuname,$setudom); - $r->print(<<"END"); - - - - - -END - $parmcount ++; - } - $r->print(<<"END"); -
$$ltext{'dura'}$$ltext{'setb'}$$ltext{'even'}$$ltext{'actn'}?
$$ltext{'star'}: $startform
$$ltext{'endd'}:  $endform
$settername$lt{'modi'}? 
$lt{'canc'}?   -
-
-
-
-
-END - return $parmcount; -} - -sub display_addblocker_table { - my ($r,$parmcount,$ltext) = @_; - my $start = time; - my $end = $start + (60 * 60 * 2); #Default is an exam of 2 hours duration. - my $onchange = 'onFocus="javascript:window.document.forms['. - "'blockform'].elements['add_".$parmcount."'].". - 'checked=true;"'; - my $startform = &Apache::lonhtmlcommon::date_setter('blockform','startdate_'.$parmcount,$start,$onchange); - my $endform = &Apache::lonhtmlcommon::date_setter('blockform','enddate_'.$parmcount,$end,$onchange); - my $function = &Apache::loncommon::get_users_function(); - my $color = &Apache::loncommon::designparm($function.'.tabbg', - $ENV{'user.domain'}); - my %lt = &Apache::lonlocal::texthash( - 'addb' => 'Add block', - 'exam' => 'e.g., Exam 1', - 'addn' => 'Add new communication blocking periods' - ); - $r->print(<<"END"); -

$lt{'addn'}

- - - - -
- - - - -
- - - - - - - - - - - -
$$ltext{'dura'}$$ltext{'even'} $lt{'exam'}$$ltext{'actn'}?
$$ltext{'star'}: $startform
$$ltext{'endd'}:  $endform
$lt{'addb'}? 
-
-
-END - return; -} - -sub blockcheck { - my ($setters,$startblock,$endblock) = @_; - # Retrieve active student roles and active course coordinator/instructor roles - my @livecses = (); - my @staffcses = (); - $$startblock = 0; - $$endblock = 0; - foreach (keys %ENV) { - if ($_ =~ m-^user\.role\.(st|cc|in)\./(.+)$-) { - my $role = $1; - my $cse = $2; - $cse =~ s|/|_|; - if ($ENV{$_} =~ m/^(\d*)\.(\d*)$/) { - unless (($2 > 0 && $2 < time) || ($1 > time)) { - if ($role eq 'st') { - push @livecses, $cse; - } else { - unless (grep/^$cse$/,@staffcses) { - push @staffcses, $cse; - } - } +sub store_recipients { + my ($subject,$sendername,$senderdom,$reciphash) = @_; + my $context = &get_course_context(); + my $now = time(); + my $msgcount = &get_uniq(); + my $recipid = + &buildmsgid($now,$subject,$sendername,$senderdom,$msgcount,$context,$$); + my %recipinfo = ( + $recipid => $reciphash, + ); + my $status = &Apache::lonnet::put('nohist_emailrecip',\%recipinfo, + $senderdom,$sendername); + if ($status eq 'ok') { + return ($recipid,$status); + } else { + return (undef,$status); + } +} + +# =============================================================== Folder suffix + +sub foldersuffix { + my $folder=shift; + unless ($folder) { return ''; } + my $suffix; + my %folderhash = &get_user_folders($folder); + if (ref($folderhash{$folder}) eq 'HASH') { + $suffix = '_'.&escape($folderhash{$folder}{'id'}); + } else { + $suffix = '_'.&escape($folder); + } + return $suffix; +} + +# ========================================================= User-defined folders + +sub get_user_folders { + my ($folder) = @_; + my %userfolders = + &Apache::lonnet::dump('email_folders',undef,undef,$folder); + my $lock = "\0".'lock_counter'; # locks db while counter incremented + my $counter = "\0".'idcount'; # used in suffix for email db files + if (defined($userfolders{$lock})) { + delete($userfolders{$lock}); + } + if (defined($userfolders{$counter})) { + delete($userfolders{$counter}); + } + return %userfolders; +} + +sub secapply { + my $rec=shift; + my $defaultflag=shift; + $rec=~s/\s+//g; + $rec=~s/\@/\:/g; + my ($adr,$sections_or_groups)=($rec=~/^([^\(]+)\(([^\)]+)\)/); + if ($sections_or_groups) { + foreach my $item (split(/\;/,$sections_or_groups)) { + if (($item eq $env{'request.course.sec'}) || + ($defaultflag && ($item eq '*'))) { + return $adr; + } elsif ($env{'request.course.groups'}) { + my @usersgroups = split(/:/,$env{'request.course.groups'}); + if (grep(/^\Q$item\E$/,@usersgroups)) { + return $adr; } - } - } elsif ($_ =~ m-user\.role\.cr/(\w+)/(\w+)/([^/]+)\./(.+)$- ) { - my $rolepriv = $ENV{'user.role..rolesdef_'.$3}; - } - } - # Retrieve blocking times and identity of blocker for active courses for students. - if (@livecses > 0) { - foreach my $cse (@livecses) { - my ($cdom,$crs) = split/_/,$cse; - if ( (grep/^$cse$/,@staffcses) && ($ENV{'request.role'} !~ m-^st\./$cdom/$crs$-) ) { - next; - } else { - %{$$setters{$cse}} = (); - @{$$setters{$cse}{'staff'}} = (); - @{$$setters{$cse}{'times'}} = (); - my %records = &Apache::lonnet::dump('comm_block',$cdom,$crs); - foreach (keys %records) { - if ($_ =~ m/^(\d+)____(\d+)$/) { - if ($1 <= time && $2 >= time) { - my ($staff,$title) = split/:/,$records{$_}; - push @{$$setters{$cse}{'staff'}}, $staff; - push @{$$setters{$cse}{'times'}}, $_; - if ( ($$startblock == 0) || ($$startblock > $1) ) { - $$startblock = $1; - } - if ( ($$endblock == 0) || ($$endblock < $2) ) { - $$endblock = $2; - } - } - } - } - } + } } + } else { + return $rec; } + return ''; } -sub build_block_table { - my ($r,$startblock,$endblock,$setters) = @_; - my $function = &Apache::loncommon::get_users_function(); - my $color = &Apache::loncommon::designparm($function.'.tabbg', - $ENV{'user.domain'}); - my %lt = &Apache::lonlocal::texthash( - 'cacb' => 'Currently active communication blocks', - 'cour' => 'Course', - 'dura' => 'Duration', - 'blse' => 'Block set by' - ); - $r->print(<<"END"); -
$lt{'cacb'}:

- - -
- - -
- - - - - - -END - foreach (keys %{$setters}) { - my %courseinfo=&Apache::lonnet::coursedescription($_); - for (my $i=0; $i<@{$$setters{$_}{staff}}; $i++) { - my ($uname,$udom) = split/\@/,$$setters{$_}{staff}[$i]; - my $fullname = &Apache::loncommon::plainname($uname,$udom); - my ($openblock,$closeblock) = split/____/,$$setters{$_}{times}[$i]; - $openblock = &Apache::lonlocal::locallocaltime($openblock); - $closeblock= &Apache::lonlocal::locallocaltime($closeblock); - $r->print(''. - ''. - ''); - } - } - $r->print('
$lt{'cour'}$lt{'dura'}$lt{'blse'}
'.$courseinfo{'description'}.''.$openblock.' to '.$closeblock.''.$fullname.' ('.$uname.'@'.$udom. - ')
'); -} +=pod + +=item * B: + +Arguments + $feedurl - /res/ url of resource (only need if $author is true) + $author,$question,$course,$policy - all true/false parameters + if true will attempt to find the addresses of user that should receive + this type of feedback (author - feedback to author of resource $feedurl, + $question 'Resource Content Questions', $course 'Course Content Question', + $policy 'Course Policy') + (Additionally it also checks $env for whether the corresponding form. + element exists, for ease of use in a html response context) + + $defaultflag - (internal should be left blank) if true gather addresses + that aren't for a section even if I have a section + (used for reccursion internally, first we look for + addresses for our specific section then we recurse + and look for non section addresses) + +Returns + $typestyle - string of html text, describing what addresses were found + %to - a hash, which keys are addresses of users to send messages to + the keys will look like name:domain -# ----------------------------------------------------------- Display a message +=cut -sub displaymessage { - my ($r,$msgid)=@_; - my %blocked = (); - my %setters = (); - my $startblock = 0; - my $endblock = 0; - my $numblocked = 0; -# info to generate "next" and "previous" buttons and check if message is blocked - &blockcheck(\%setters,\$startblock,\$endblock); - my @messages=&sortedmessages(\%blocked,$startblock,$endblock,\$numblocked); - if ( $blocked{$msgid} eq 'ON' ) { - &printheader($r,'/adm/email',&mt('Display a Message')); - $r->print(&mt('You attempted to display a message that is currently blocked because you are enrolled in one or more courses for which there is an ongoing online exam.')); - &build_block_table($r,$startblock,$endblock,\%setters); - return; - } - &statuschange($msgid,'read'); - my %message=&Apache::lonnet::get('nohist_email',[$msgid]); - my %content=&unpackagemsg($message{$msgid}); - my $counter=0; - $r->print('
');
-    my $escmsgid=&Apache::lonnet::escape($msgid);
-    foreach (@messages) {
-	if ($_->[5] eq $escmsgid){
-	    last;
-	}
-	$counter++;
+sub decide_receiver {
+    my ($feedurl,$author,$question,$course,$policy,$defaultflag) = @_;
+    &Apache::lonenc::check_decrypt(\$feedurl);
+    my $typestyle='';
+    my %to=();
+    if ($env{'form.discuss'} eq 'author' ||$author) {
+	$typestyle.='Submitting as Author Feedback
'; + $feedurl=~ m{^/res/($LONCAPA::domain_re)/($LONCAPA::username_re)/}; + $to{$2.':'.$1}=1; + } + my $cid = $env{'request.course.id'}; + if ($env{'form.discuss'} eq 'question' ||$question) { + $typestyle.=&mt('Submitting as Question').'
'; + foreach my $item (split(/\,/,$env{'course.'.$cid.'.question.email'})) { + my $rec=&secapply($item,$defaultflag); + if ($rec) { $to{$rec}=1; } + } + } + if ($env{'form.discuss'} eq 'course' ||$course) { + $typestyle.=&mt('Submitting as Comment').'
'; + foreach my $item (split(/\,/,$env{'course.'.$cid.'.comment.email'})) { + my $rec=&secapply($item,$defaultflag); + if ($rec) { $to{$rec}=1; } + } + } + if ($env{'form.discuss'} eq 'policy' ||$policy) { + $typestyle.=&mt('Submitting as Policy Feedback').'
'; + foreach my $item (split(/\,/,$env{'course.'.$cid.'.policy.email'})) { + my $rec=&secapply($item,$defaultflag); + if ($rec) { $to{$rec}=1; } + } + } + if ((scalar(%to) eq '0') && (!$defaultflag)) { + ($typestyle,%to)= + &decide_receiver($feedurl,$author,$question,$course,$policy,1); } - $r->print('
'); - my $number_of_messages = scalar(@messages); #subtract 1 for last index -# start output - &printheader($r,'/adm/email?display='.&Apache::lonnet::escape($msgid),'Display a Message','',$content{'baseurl'}); - my %courseinfo=&Apache::lonnet::coursedescription($content{'courseid'}); -# Functions - $r->print(''. - ''. - ''. - ''. - ''. - ''); - if ($counter > 0){ - $r->print(''); - } - if ($counter < $number_of_messages - 1){ - $r->print(''); - } - $r->print('
'.&mt('Functions').':'.&mt('Reply').''.&mt('Forward').''.&mt('Mark Unread').'Delete'.&mt('Display all Messages').''.&mt('Previous').''.&mt('Next').'
'); - $r->print('
'.&mt('Subject').': '.$content{'subject'}. - '
'.&mt('From').': '. - &Apache::loncommon::aboutmewrapper( - &Apache::loncommon::plainname($content{'sendername'},$content{'senderdomain'}), - $content{'sendername'},$content{'senderdomain'}).' ('. - $content{'sendername'}.' at '. - $content{'senderdomain'}.') '. - ($content{'courseid'}?'
'.&mt('Course').': '.$courseinfo{'description'}. - ($content{'coursesec'}?' ('.&mt('Group/Section').': '.$content{'coursesec'}.')':''):''). - '
'.&mt('Time').': '.$content{'time'}. - '

'.
-	      &Apache::lontexconvert::msgtexconverted($content{'message'},1).
-	      '

'.$content{'citation'}.'

'); - return; -} - -# ================================================================== The Header - -sub header { - my ($r,$title,$baseurl)=@_; - $r->print('Communication and Messages'); - if ($baseurl) { - $r->print(""); - } - $r->print(&Apache::loncommon::studentbrowser_javascript().''. - &Apache::loncommon::bodytag('Communication and Messages')); - $r->print(&Apache::lonhtmlcommon::breadcrumbs - (undef,($title?$title:'Communication and Messages'))); - -} - -# ---------------------------------------------------------------- Print header - -sub printheader { - my ($r,$url,$desc,$title,$baseurl)=@_; - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>$url, - text=>$desc}); - &header($r,$title,$baseurl); -} - - -# ===================================================================== Handler - -sub handler { - my $r=shift; - -# ----------------------------------------------------------- Set document type - - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; - - return OK if $r->header_only; - -# --------------------------- Get query string for limited number of parameters - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['display','replyto','forward','markread','markdel','markunread', - 'sendreply','compose','sendmail','critical','recname','recdom', - 'recordftf','sortedby','block']); - $sqs='&sortedby='.$ENV{'form.sortedby'}; -# ------------------------------------------------------ They checked for email - unless ($ENV{'form.block'}) { - &Apache::lonnet::put('email_status',{'recnewemail'=>0}); - } - -# ----------------------------------------------------------------- Breadcrumbs - - &Apache::lonhtmlcommon::clear_breadcrumbs(); - &Apache::lonhtmlcommon::add_breadcrumb - ({href=>"/adm/communicate", - text=>"Communication/Messages", - faq=>12,bug=>'Communication Tools',}); - -# --------------------------------------------------------------- Render Output - - if ($ENV{'form.display'}) { - &displaymessage($r,$ENV{'form.display'}); - } elsif ($ENV{'form.replyto'}) { - &compout($r,'',$ENV{'form.replyto'}); - } elsif ($ENV{'form.confirm'}) { - &printheader($r,'','Confirmed Receipt'); - foreach (keys %ENV) { - if ($_=~/^form\.rec\_(.*)$/) { - $r->print(''.&mt('Confirming Receipt').': '. - &user_crit_received($1).'
'); - } - if ($_=~/^form\.reprec\_(.*)$/) { - my $msgid=$1; - $r->print(''.&mt('Confirming Receipt').': '. - &user_crit_received($msgid).'
'); - &compout($r,'','','',$msgid); - } - } - &discrit($r); - } elsif ($ENV{'form.critical'}) { - &printheader($r,'','Displaying Critical Messages'); - &discrit($r); - } elsif ($ENV{'form.forward'}) { - &compout($r,$ENV{'form.forward'}); - } elsif ($ENV{'form.markdel'}) { - &printheader($r,'','Deleted Message'); - &statuschange($ENV{'form.markdel'},'deleted'); - &disall($r); - } elsif ($ENV{'form.markeddel'}) { - my $total=0; - foreach (keys %ENV) { - if ($_=~/^form\.delmark_(.*)$/) { - &statuschange(&Apache::lonnet::unescape($1),'deleted'); - $total++; - } - } - &printheader($r,'','Deleted Messages'); - $r->print('Deleted '.$total.' message(s)

'); - &disall($r); - } elsif ($ENV{'form.markunread'}) { - &printheader($r,'','Marked Message as Unread'); - &statuschange($ENV{'form.markunread'},'new'); - &disall($r); - } elsif ($ENV{'form.compose'}) { - &compout($r,'','',$ENV{'form.compose'}); - } elsif ($ENV{'form.recordftf'}) { - &facetoface($r,$ENV{'form.recordftf'}); - } elsif ($ENV{'form.block'}) { - &examblock($r,$ENV{'form.block'}); - } elsif ($ENV{'form.sendmail'}) { - my $sendstatus=''; - if ($ENV{'form.send'}) { - &printheader($r,'','Messages being sent.'); - $r->rflush(); - my %content=(); - undef %content; - if ($ENV{'form.forwid'}) { - my $msgid=$ENV{'form.forwid'}; - my %message=&Apache::lonnet::get('nohist_email',[$msgid]); - %content=&unpackagemsg($message{$msgid},1); - &statuschange($msgid,'forwarded'); - $ENV{'form.message'}.="\n\n-- Forwarded message --\n\n". - $content{'message'}; - } - if ($ENV{'form.replyid'}) { - my $msgid=$ENV{'form.replyid'}; - my %message=&Apache::lonnet::get('nohist_email',[$msgid]); - %content=&unpackagemsg($message{$msgid},1); - &statuschange($msgid,'replied'); - } - my %toaddr=(); - undef %toaddr; - if ($ENV{'form.sendmode'} eq 'group') { - foreach (keys %ENV) { - if ($_=~/^form\.send\_to\_\&\&\&[^\&]*\&\&\&\_(.+)$/) { - $toaddr{$1}=''; - } - } - } elsif ($ENV{'form.sendmode'} eq 'upload') { - foreach (split(/[\n\r\f]+/,$ENV{'form.upfile'})) { - my ($rec,$txt)=split(/\s*\:\s*/,$_); - if ($txt) { - $rec=~s/\@/\:/; - $toaddr{$rec}.=$txt."\n"; - } - } - } else { - $toaddr{$ENV{'form.recuname'}.':'.$ENV{'form.recdomain'}}=''; - } - if ($ENV{'form.additionalrec'}) { - foreach (split(/\,/,$ENV{'form.additionalrec'})) { - my ($auname,$audom)=split(/\@/,$_); - $toaddr{$auname.':'.$audom}=''; - } - } - - foreach (keys %toaddr) { - my ($recuname,$recdomain)=split(/\:/,$_); - my $msgtxt=&Apache::lonfeedback::clear_out_html($ENV{'form.message'}); - if ($toaddr{$_}) { $msgtxt.='


'.$toaddr{$_}; } - my $thismsg; - if ((($ENV{'form.critmsg'}) || ($ENV{'form.sendbck'})) && - (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'}))) { - $r->print(&mt('Sending critical message').' '.$recuname.'@'.$recdomain.': '); - $thismsg=&user_crit_msg($recuname,$recdomain, - &Apache::lonfeedback::clear_out_html($ENV{'form.subject'}), - $msgtxt, - $ENV{'form.sendbck'}); - } else { - $r->print(&mt('Sending').' '.$recuname.'@'.$recdomain.': '); - $thismsg=&user_normal_msg($recuname,$recdomain, - &Apache::lonfeedback::clear_out_html($ENV{'form.subject'}), - $msgtxt, - $content{'citation'}); - if (($ENV{'request.course.id'}) && ($ENV{'form.sendmode'} eq 'group')) { - &user_normal_msg_raw( - $ENV{'course.'.$ENV{'request.course.id'}.'.num'}, - $ENV{'course.'.$ENV{'request.course.id'}.'.domain'}, - 'Broadcast ['.$recuname.':'.$recdomain.']', - $msgtxt); - } - } - $r->print($thismsg.'
'); - $sendstatus.=' '.$thismsg; - } - } else { - &printheader($r,'','No messages sent.'); - } - if ($sendstatus=~/^(\s*(?:ok|con_delayed)\s*)*$/) { - $r->print('
'.&mt('Completed.').''); - if ($ENV{'form.displayedcrit'}) { - &discrit($r); - } else { - &Apache::loncommunicate::menu($r); - } - } else { - $r->print( - '

'.&mt('Could not deliver message').'

'. - &mt('Please use the browser "Back" button and correct the recipient addresses') - ); - } - } else { - &printheader($r,'','Display All Messages'); - &disall($r); - } - $r->print(''); - return OK; -} -# ================================================= Main program, reset counter - -BEGIN { - $msgcount=0; + return ($typestyle,%to); } =pod @@ -1750,13 +925,6 @@ BEGIN { =cut -1; - +1; __END__ - - - - - -