--- loncom/interface/lonmsg.pm 2001/07/28 04:16:29 1.11
+++ loncom/interface/lonmsg.pm 2004/03/26 17:13:59 1.94
@@ -1,51 +1,135 @@
# The LearningOnline Network with CAPA
-#
# Routines for messaging
#
-# (Routines to control the menu
+# $Id: lonmsg.pm,v 1.94 2004/03/26 17:13:59 www Exp $
+#
+# Copyright Michigan State University Board of Trustees
+#
+# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
+#
+# LON-CAPA is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
#
-# (TeX Conversion Module
+# LON-CAPA is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
#
-# 05/29/00,05/30 Gerd Kortemeyer)
+# You should have received a copy of the GNU General Public License
+# along with LON-CAPA; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
-# 10/05 Gerd Kortemeyer)
+# /home/httpd/html/adm/gpl.txt
#
-# 10/19,10/20,10/30,
-# 02/06/01 Gerd Kortemeyer
-# 07/27 Guy Albertelli
-# 07/27 Gerd Kortemeyer
+# http://www.lon-capa.org/
+#
+
package Apache::lonmsg;
+=pod
+
+=head1 NAME
+
+Apache::lonmsg: supports internal messaging
+
+=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.
+
+=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.
+
+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.
+
+=head1 FUNCTIONS
+
+=over 4
+
+=cut
+
use strict;
use Apache::lonnet();
use vars qw($msgcount);
-use HTML::TokeParser;
+use HTML::TokeParser();
use Apache::Constants qw(:common);
+use Apache::loncommon();
+use Apache::lontexconvert();
+use HTML::Entities();
+use Mail::Send;
+use Apache::lonlocal;
+
+# Querystring component with sorting type
+my $sqs;
# ===================================================================== Package
sub packagemsg {
- my ($subject,$message,$citation)=@_;
- $message=~s/\\<\;/g;
- $message=~s/\>/\>\;/g;
- $citation=~s/\\<\;/g;
- $citation=~s/\>/\>\;/g;
- $subject=~s/\\<\;/g;
- $subject=~s/\>/\>\;/g;
+ my ($subject,$message,$citation,$baseurl,$attachmenturl)=@_;
+ $message =&HTML::Entities::encode($message);
+ $citation=&HTML::Entities::encode($citation);
+ $subject =&HTML::Entities::encode($subject);
+ #remove machine specification
+ $baseurl =~ s|^http://[^/]+/|/|;
+ $baseurl =&HTML::Entities::encode($baseurl);
+ #remove machine specification
+ $attachmenturl =~ s|^http://[^/]+/|/|;
+ $attachmenturl =&HTML::Entities::encode($attachmenturl);
+
my $now=time;
$msgcount++;
my $partsubj=$subject;
$partsubj=&Apache::lonnet::escape($partsubj);
- $partsubj=substr($partsubj,0,50);
my $msgid=&Apache::lonnet::escape(
$now.':'.$partsubj.':'.$ENV{'user.name'}.':'.
$ENV{'user.domain'}.':'.$msgcount.':'.$$);
- return $msgid,
- ''.$ENV{'user.name'}.' '.
+ my $result=''.$ENV{'user.name'}.' '.
''.$ENV{'user.domain'}.' '.
''.$subject.' '.
- ''.localtime($now).' '.
+ ''.&Apache::lonlocal::locallocaltime($now).' '.
''.$ENV{'SERVER_NAME'}.' '.
''.$ENV{'HTTP_HOST'}.' '.
''.$ENV{'REMOTE_ADDR'}.' '.
@@ -55,17 +139,27 @@ sub packagemsg {
''.$ENV{'browser.mathml'}.' '.
''.$ENV{'HTTP_USER_AGENT'}.' '.
''.$ENV{'request.course.id'}.' '.
+ ''.$ENV{'request.course.sec'}.' '.
''.$ENV{'request.role'}.' '.
''.$ENV{'request.filename'}.' '.
''.$msgid.' '.
- ''.$message.' '.
- ''.$citation.' ';
+ ''.$message.' ';
+ if (defined($citation)) {
+ $result.=''.$citation.' ';
+ }
+ if (defined($baseurl)) {
+ $result.= ''.$baseurl.' ';
+ }
+ if (defined($attachmenturl)) {
+ $result.= ''.$attachmenturl.' ';
+ }
+ return $msgid,$result;
}
# ================================================== Unpack message into a hash
sub unpackagemsg {
- my $message=shift;
+ my ($message,$notoken)=@_;
my %content=();
my $parser=HTML::TokeParser->new(\$message);
my $token;
@@ -76,6 +170,16 @@ sub unpackagemsg {
$content{$entry}=$value;
}
}
+ if ($content{'attachmenturl'}) {
+ my ($fname,$ft)=($content{'attachmenturl'}=~/\/(\w+)\.(\w+)$/);
+ if ($notoken) {
+ $content{'message'}.=''.&mt('Attachment').': '.$fname.'.'.$ft.' ';
+ } else {
+ $content{'message'}.='
'.&mt('Attachment').': '.$fname.'.'.$ft.' ';
+ }
+ }
return %content;
}
@@ -91,8 +195,63 @@ sub unpackmsgid {
return ($sendtime,$shortsubj,$fromname,$fromdomain,$status{$msgid});
}
+
+sub sendemail {
+ my ($to,$subject,$body)=@_;
+ $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;
+ my $msg = new Mail::Send;
+ $msg->to($to);
+ $msg->subject('[LON-CAPA] '.$subject);
+ if (my $fh = $msg->open('smtp',Server => 'localhost')) {
+ print $fh $body;
+ $fh->close;
+ }
+}
+
+# ==================================================== Send notification emails
+
+sub sendnotification {
+ my ($to,$touname,$toudom,$subj,$crit)=@_;
+ my $sender=$ENV{'environment.firstname'}.' '.$ENV{'environment.lastname'};
+ my $critical=($crit?' critical':'');
+ my $url='http://'.
+ $Apache::lonnet::hostname{&Apache::lonnet::homeserver($touname,$toudom)}.
+ '/adm/email?username='.$touname.'&domain='.$toudom;
+ my $body=(<300) {
+ my %what=&Apache::lonnet::get('email_status',['recnewemail']);
+ &Apache::lonnet::appenv('user.mailcheck.time'=>time);
+ if ($what{'recnewemail'}>0) { return 1; }
+ }
+ return 0;
+}
+
# =============================== Automated message to the author of a resource
+=pod
+
+=item * B: Sends message $message to the owner
+ of the resource with the URI $filename.
+
+=cut
+
sub author_res_msg {
my ($filename,$message)=@_;
unless ($message) { return 'empty'; }
@@ -111,25 +270,86 @@ sub author_res_msg {
return 'no_host';
}
+# =========================================== Retrieve author resource messages
+
+sub retrieve_author_res_msg {
+ my $url=shift;
+ $url=&Apache::lonnet::declutter($url);
+ my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//);
+ my %errormsgs=&Apache::lonnet::dump('nohist_res_msgs',$domain,$author);
+ my $msgs='';
+ foreach (keys %errormsgs) {
+ if ($_=~/^\Q$url\E\_\d+$/) {
+ my %content=&unpackagemsg($errormsgs{$_});
+ $msgs.=''.
+ $content{'time'}.' : '.$content{'message'}.
+ '
';
+ }
+ }
+ return $msgs;
+}
+
+
+# =============================== Delete all author messages related to one URL
+
+sub del_url_author_res_msg {
+ my $url=shift;
+ $url=&Apache::lonnet::declutter($url);
+ my ($domain,$author)=($url=~/^(\w+)\/(\w+)\//);
+ my @delmsgs=();
+ foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) {
+ if ($_=~/^\Q$url\E\_\d+$/) {
+ 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 {
+ my ($author,$domain)=@_;
+ my %returnhash=();
+ foreach (&Apache::lonnet::getkeys('nohist_res_msgs',$domain,$author)) {
+ $_=~/^(.+)\_\d+/;
+ $returnhash{$1}=1;
+ }
+ return %returnhash;
+}
+
# ================================================== Critical message to a user
-sub user_crit_msg {
- my ($user,$domain,$subject,$message)=@_;
+sub user_crit_msg_raw {
+ my ($user,$domain,$subject,$message,$sendback)=@_;
# Check if allowed missing
my $status='';
my $msgid='undefined';
unless (($message)&&($user)&&($domain)) { $status='empty'; };
my $homeserver=&Apache::lonnet::homeserver($user,$domain);
if ($homeserver ne 'no_host') {
- my $msgid;
($msgid,$message)=&packagemsg($subject,$message);
+ if ($sendback) { $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);
+ }
} else {
$status='no_host';
}
+# Notifications
+ my %userenv = &Apache::lonnet::get('environment',['critnotification'],
+ $domain,$user);
+ if ($userenv{'critnotification'}) {
+ &sendnotification($userenv{'critnotification'},$user,$domain,$subject,1);
+ }
+# Log this
&Apache::lonnet::logthis(
'Sending critical email '.$msgid.
', log status: '.
@@ -140,53 +360,125 @@ sub user_crit_msg {
return $status;
}
+# New routine that respects "forward" and calls old routine
+
+=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.
+
+=cut
+
+sub user_crit_msg {
+ my ($user,$domain,$subject,$message,$sendback)=@_;
+ 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).' ';
+ }
+ } else {
+ $status=&user_crit_msg_raw($user,$domain,$subject,$message,$sendback);
+ }
+ return $status;
+}
+
# =================================================== Critical message received
sub user_crit_received {
- my $message=shift;
- my %contents=&unpackagemsg($message);
- my $status='rec: '.
+ my $msgid=shift;
+ my %message=&Apache::lonnet::get('critical',[$msgid]);
+ my %contents=&unpackagemsg($message{$msgid},1);
+ my $status='rec: '.($contents{'sendback'}?
&user_normal_msg($contents{'sendername'},$contents{'senderdomain'},
- 'Receipt: '.$ENV{'user.name'}.' at '.$ENV{'user.domain'},
- 'User '.$ENV{'user.name'}.' at '.$ENV{'user.domain'}.
- ' acknowledged receipt of message "'.
- $contents{'subject'}.'" dated '.$contents{'time'}.".\n\n"
- .'Message ID: '.$contents{'msgid'});
+ &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});
+ &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 '.
$contents{'msgid'}.
', '.$status);
+ return $status;
}
# ======================================================== Normal communication
-sub user_normal_msg {
- my ($user,$domain,$subject,$message,$citation)=@_;
+sub user_normal_msg_raw {
+ my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl)=@_;
# Check if allowed missing
my $status='';
my $msgid='undefined';
unless (($message)&&($user)&&($domain)) { $status='empty'; };
my $homeserver=&Apache::lonnet::homeserver($user,$domain);
if ($homeserver ne 'no_host') {
- my $msgid;
- ($msgid,$message)=&packagemsg($subject,$message,$citation);
+ ($msgid,$message)=&packagemsg($subject,$message,$citation,$baseurl,
+ $attachmenturl);
$status=&Apache::lonnet::critical(
'put:'.$domain.':'.$user.':nohist_email:'.
&Apache::lonnet::escape($msgid).'='.
&Apache::lonnet::escape($message),$homeserver);
+ &Apache::lonnet::put
+ ('email_status',{'recnewemail'=>time},$domain,$user);
} else {
$status='no_host';
}
+# 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);
return $status;
}
+# New routine that respects "forward" and calls old routine
+
+=pod
+
+=item * B: Sends a message to the
+ $user at $domain, with subject $subject and message $message.
+
+=cut
+
+sub user_normal_msg {
+ my ($user,$domain,$subject,$message,$citation,$baseurl,$attachmenturl)=@_;
+ 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);
+ }
+ return $status;
+}
+
+
# =============================================================== Status Change
sub statuschange {
@@ -198,143 +490,800 @@ sub statuschange {
($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});
+ }
}
-# ===================================================================== Handler
-sub handler {
+# ======================================================= 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.' ');
+ }
+ }
- return OK if $r->header_only;
+ 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);
+ }
+ }
+}
-# --------------------------- Get query string for limited number of parameters
+# ==================================================== Display Critical Message
- map {
- my ($name, $value) = split(/=/,$_);
- $value =~ tr/+/ /;
- $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C",hex($1))/eg;
- if (($name eq 'display') || ($name eq 'replyto') ||
- ($name eq 'forward') || ($name eq 'mark') ||
- ($name eq 'sendreply') || ($name eq 'compose')) {
- unless ($ENV{'form.'.$name}) {
- $ENV{'form.'.$name}=$value;
- }
- }
- } (split(/&/,$ENV{'QUERY_STRING'}));
+sub discrit {
+ my $r=shift;
+ my $header = '
'.&mt('Critical Messages').' '.
+ '');
+}
-# --------------------------------------------------------------- Render Output
-
- $r->print('EMail and Messaging ');
- $r->print(
- ' ');
- $r->print('EMail ');
- if ($ENV{'form.display'}) {
- my $msgid=$ENV{'form.display'};
- &statuschange($msgid,'read');
- my %message=&Apache::lonnet::get('nohist_email',[$msgid]);
- my %content=&unpackagemsg($message{$msgid});
- $r->print('Subject: '.$content{'subject'}.
- 'From: '.$content{'sendername'}.' at '.
- $content{'senderdomain'}.
- 'Time: '.$content{'time'}.' Functions: '.
- 'Reply '.
- $content{'message'}.' '.$content{'citation'});
- } elsif ($ENV{'form.replyto'}) {
- my $msgid=$ENV{'form.replyto'};
- my %message=&Apache::lonnet::get('nohist_email',[$msgid]);
- my %content=&unpackagemsg($message{$msgid});
- my $quotemsg='> '.$content{'message'};
- $quotemsg=~s/\r/\n/g;
- $quotemsg=~s/\f/\n/g;
- $quotemsg=~s/\n+/\n\> /g;
- my $subject='Re: '.$content{'subject'};
- my $dispcrit='';
- if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
+sub sortedmessages {
+ 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);
+ 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;
+ $r->print(<
+ function checkall() {
+ for (i=0; i
+ENDDISHEADER
+ $r->print(''.&mt('Display All Messages').' ');
+}
+
+# ============================================================== 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=
- ' Send as critical message';
- }
- $r->print(<<"ENDREPLY");
-
'."\n".
+ ' '."\n".
+ '
+$latexHelp
+$dismsg
+
$dispcrit
-
-
-ENDREPLY
- } elsif ($ENV{'form.sendreply'}) {
- my $msgid=$ENV{'form.sendreply'};
- my %message=&Apache::lonnet::get('nohist_email',[$msgid]);
- my %content=&unpackagemsg($message{$msgid});
- &statuschange($msgid,'replied');
- $r->print('Sending: '.&user_normal_msg($content{'sendername'},
- $content{'senderdomain'},
- $ENV{'form.subject'},
- $ENV{'form.message'}));
- } elsif ($ENV{'form.forward'}) {
- } elsif ($ENV{'form.mark'}) {
- } elsif ($ENV{'form.compose'}) {
- my $dispcrit='';
- if (&Apache::lonnet::allowed('srm',$ENV{'request.course.id'})) {
- $dispcrit=
- ' Send as critical message';
- }
- $r->print(<<"ENDCOMP");
-
-
-Subject:
-
-
+
+
+ENDCOMP
+ } else { # $broadcast is 'upload'
+ $r->print(<
+
+
Generate messages from a file
+
+Subject:
+
+General message text
+$dismsg
+
+
+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 disfacetoface {
+ my ($r,$user,$domain)=@_;
+ 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').' ';
+ } else {
+ $result.=''.&mt('Sent 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 '') {
+ $r->print("".&mt("No notes, face-to-face discussion records, or critical 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");
+# 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, and Critical 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'}
+
+
+
-ENDCOMP
- } elsif ($ENV{'form.sendmail'}) {
- } else {
- $r->print('  Date '.
- 'Username Domain Subject Status ');
- map {
- my ($sendtime,$shortsubj,$fromname,$fromdomain,$status)=
- &Apache::lonmsg::unpackmsgid($_);
- if ($status eq 'new') {
- $r->print('');
- } elsif ($status eq 'read') {
- $r->print(' ');
- } elsif ($status eq 'replied') {
- $r->print(' ');
- } else {
- $r->print(' ');
+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('Open '.localtime($sendtime).' '.
- $fromname.' '.$fromdomain.' '.
- &Apache::lonnet::unescape($shortsubj).' '.
- $status.' ');
- } sort split(/\&/,&Apache::lonnet::reply('keys:'.
- $ENV{'user.domain'}.':'.
- $ENV{'user.name'}.':nohist_email',
- $ENV{'user.home'}));
- $r->print('