--- loncom/interface/lonmsgdisplay.pm 2006/04/23 04:04:38 1.8
+++ loncom/interface/lonmsgdisplay.pm 2023/09/15 22:32:46 1.200
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Routines for messaging display
#
-# $Id: lonmsgdisplay.pm,v 1.8 2006/04/23 04:04:38 albertel Exp $
+# $Id: lonmsgdisplay.pm,v 1.200 2023/09/15 22:32:46 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,12 +33,13 @@ package Apache::lonmsgdisplay;
=head1 NAME
-Apache::lonmsg: supports internal messaging
+Apache::lonmsgdisplay: 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.
+lonmsgdisplay provides a handler to allow users to read, send,
+and delete messages, and to create and delete message folders,
+and to move messages between folders.
=head1 OVERVIEW
@@ -74,8 +75,8 @@ email program, so they have full access
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
+=item * B: LON-CAPA can block selected communication
+features for students 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,
@@ -93,25 +94,6 @@ addresses on their B screen, but g
are much more useful than 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.
-
-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
-
=cut
use strict;
@@ -119,54 +101,227 @@ use Apache::lonnet;
use HTML::TokeParser();
use Apache::Constants qw(:common);
use Apache::loncommon();
+use Apache::lonhtmlcommon();
+use Apache::longroup;
+use Apache::lonnavmaps;
use Apache::lontexconvert();
use HTML::Entities();
use Apache::lonlocal;
use Apache::loncommunicate;
use Apache::lonfeedback;
use Apache::lonrss();
+use Apache::lonselstudent();
+use Apache::lonenc();
+use lib '/home/httpd/lib/perl/';
+use LONCAPA qw(:DEFAULT :match);
# Querystring component with sorting type
-my $sqs;
-my $startdis;
-my $interdis;
+my $sqs='';
+my $startdis='';
# ============================================================ List all folders
sub folderlist {
- my $folder=shift;
- my @allfolders=&Apache::lonnet::getkeys('email_folders');
- if ($allfolders[0]=~/^error:/) { @allfolders=(); }
- return '':'');
+ ''.
+ ($folder=~/^critical/?'':'');
+ return $output;
+}
+
+sub get_permanent_folders {
+ my %permfolders =
+ &Apache::lonlocal::texthash('' => 'INBOX',
+ 'trash' => 'TRASH',
+ 'critical' => 'CRITICAL',
+ 'sent' => 'SENT MESSAGES',
+ );
+ return %permfolders;
+}
+
+sub get_msgstatus_types {
+ # Don't translate here!
+ my %statushash = (
+ '' => 'Any',
+ 'new' => 'Unread',
+ 'read' => 'Read',
+ 'replied' => 'Replied to',
+ 'forwarded' => 'Forwarded',
+ );
+ return %statushash;
}
sub scrollbuttons {
- my ($start,$maxdis,$first,$finish,$total)=@_;
+ my ($start,$maxdis,$first,$finish,$total,$msgstatus)=@_;
unless ($total>0) { return ''; }
$start++; $maxdis++;$first++;$finish++;
- return
- &mt('Page').': '.
- ''.
- ''.
- ' of '.$maxdis.
- ''.
- ' '.
- &mt('Showing messages [_1] through [_2] of [_3]',$first,$finish,$total).'';
+
+ my %statushash = &get_msgstatus_types();
+ my $status;
+ if ($msgstatus eq '') {
+ $status = 'All'; # Don't translate here!
+ } else {
+ $status = $statushash{$msgstatus};
+ }
+ my $output = ''.&mt('Page:').' ';
+ if ($maxdis == 1) {
+ # No buttons if only one page is displayed
+ $output .= '1/1';
+ } else {
+ $output .=
+ ''.
+ ''.
+ ' / '.$maxdis.' '.
+ ''.
+ '';
+ }
+ $output .=
+ '
'
+ .''.&mt($status.' messages:').' '
+ .&mt('showing messages [_1] through [_2] of [_3].',
+ $first,$finish,$total)
+ .'
'
+ .'';
+
+ return $output;
}
# =============================================================== Status Change
@@ -184,21 +339,134 @@ sub statuschange {
&Apache::lonnet::put('email_status'.$suffix,{$msgid => $newstatus});
}
if ($newstatus eq 'deleted') {
- &movemsg(&Apache::lonnet::unescape($msgid),$folder,'trash');
- }
+ return &movemsg($msgid,$folder,'trash');
+ }
+ return ;
}
# ============================================================= Make new folder
sub makefolder {
- my ($newfolder)=@_;
- if (($newfolder eq 'sent')
- || ($newfolder eq 'critical')
- || ($newfolder eq 'trash')
- || ($newfolder eq 'new')) { return; }
- &Apache::lonnet::put('email_folders',{$newfolder => time});
+ my ($newfolder) = @_;
+ my %permfolders = &get_permanent_folders();
+ my %userfolders = &Apache::lonmsg::get_user_folders();
+ my ($outcome,$warning);
+ if (defined($userfolders{$newfolder})) {
+ return &mt('The folder name: "[_1]" is already in use for an existing folder.',$newfolder);
+ }
+ foreach my $perm (keys(%permfolders)) {
+ if ($permfolders{$perm} eq $newfolder) {
+ return &mt('The folder name: "[_1]" is already used for one of the folders automatically generated by the system.',$newfolder);
+ }
+ }
+ if (&get_msgfolder_lock() eq 'ok') {
+ my %counter_hash = &Apache::lonnet::get('email_folders',["\0".'idcount']);
+ my $lastcount = $counter_hash{"\0".'idcount'};
+ my $folder_id = $lastcount + 1;
+ while (defined($userfolders{$folder_id})) {
+ $folder_id ++;
+ }
+ my %folderinfo = ( id => $folder_id,
+ created => time, );
+ $outcome =
+ &Apache::lonnet::put('email_folders',{$newfolder => \%folderinfo,
+ "\0".'idcount' => $folder_id});
+ my $releaseresult = &release_msgfolder_lock();
+ if ($releaseresult ne 'ok') {
+ $warning = $releaseresult;
+ }
+ } else {
+ $outcome =
+ &mt('Error - could not obtain lock on message folders record.');
+ }
+ return ($outcome,$warning);
+}
+
+# ============================================================= Delete folder
+
+sub deletefolder {
+ my ($folder)=@_;
+ my %permfolders = &get_permanent_folders();
+ if (defined($permfolders{$folder})) {
+ return &mt('The folder "[_1]" may not be deleted.',$permfolders{$folder});
+ }
+ my %userfolders = &Apache::lonmsg::get_user_folders();
+ if (!defined($userfolders{$folder})) {
+ return &mt('The folder "[_1]" does not exist so deletion is not required.',
+ $folder);
+ }
+ # check folder is empty;
+ my $suffix=&Apache::lonmsg::foldersuffix($folder);
+ my @messages = &Apache::lonnet::getkeys('nohist_email'.$suffix);
+ if (@messages > 0) {
+ return &mt('The folder "[_1]" contains messages so it may not be deleted.',$folder).
+ ' '.
+ &mt('Delete or move the messages to a different folder first.');
+ }
+ my $delresult = &Apache::lonnet::del('email_folders',[$folder]);
+ return $delresult;
+}
+
+sub renamefolder {
+ my ($folder) = @_;
+ my $newname = $env{'form.renamed'};
+ my %permfolders = &get_permanent_folders();
+ if ($env{'form.renamed'} eq '') {
+ return &mt('The folder "[_1]" may not be renamed to "[_2]" as the new name you requested is an invalid name.',$folder,$newname);
+ }
+ if (defined($permfolders{$folder})) {
+ return &mt('The folder "[_1]" may not be renamed as it is a folder provided by the system.',$folder);
+ }
+ if (defined($permfolders{$newname})) {
+ return &mt('The folder "[_1]" may not be renamed to "[_2]" as the new name you requested is reserved for folders provided automatically by the system.',$folder,$newname);
+ }
+ my %userfolders = &Apache::lonmsg::get_user_folders();
+ if (defined($userfolders{$newname})) {
+ return &mt('The folder "[_1]" may not be renamed to "[_2]" because the new name you requested is already being used for an existing folder.',$folder,$newname);
+ }
+ if (!defined($userfolders{$folder})) {
+ return &mt('The folder "[_1]" could not be renamed to "[_2]" because the folder does not exist.',$folder,$newname);
+ }
+ my %folderinfo;
+ if (ref($userfolders{$folder}) eq 'HASH') {
+ %folderinfo = %{$userfolders{$folder}};
+ } else {
+ %folderinfo = ( id => $folder,
+ created => $userfolders{$folder},);
+ }
+ my $outcome =
+ &Apache::lonnet::put('email_folders',{$newname => \%folderinfo});
+ if ($outcome eq 'ok') {
+ $outcome = &Apache::lonnet::del('email_folders',[$folder]);
+ }
+ return $outcome;
+}
+
+sub get_msgfolder_lock {
+ # get lock for mail folder counter.
+ my $lockhash = { "\0".'lock_counter' => time, };
+ my $tries = 0;
+ my $gotlock = &Apache::lonnet::newput('email_folders',$lockhash);
+ while (($gotlock ne 'ok') && $tries <3) {
+ $tries ++;
+ sleep(1);
+ $gotlock = &Apache::lonnet::newput('email_folders',$lockhash);
+ }
+ return $gotlock;
+}
+
+sub release_msgfolder_lock {
+ # remove lock
+ my @del_lock = ("\0".'lock_counter');
+ my $dellockoutcome=&Apache::lonnet::del('email_folders',\@del_lock);
+ if ($dellockoutcome ne 'ok') {
+ return (' '.&mt('Warning: failed to release lock for counter').' ');
+ } else {
+ return 'ok';
+ }
}
+
# ======================================================== Move between folders
sub movemsg {
@@ -206,141 +474,437 @@ sub movemsg {
if ($srcfolder eq 'new') { $srcfolder=''; }
my $srcsuffix=&Apache::lonmsg::foldersuffix($srcfolder);
my $trgsuffix=&Apache::lonmsg::foldersuffix($trgfolder);
+ if ($srcsuffix eq $trgsuffix) {
+ return (0,&mt('Message not moved, Attempted to move message to the same folder as it already is in.'));
+ }
# Copy message
my %message=&Apache::lonnet::get('nohist_email'.$srcsuffix,[$msgid]);
- &Apache::lonnet::put('nohist_email'.$trgsuffix,{$msgid => $message{$msgid}});
+ if (!exists($message{$msgid}) || $message{$msgid} eq '') {
+ if (&Apache::lonnet::error(%message)) {
+ return (0,&mt('Message not moved, A network error occurred.'));
+ } else {
+ return (0,&mt('Message not moved as the message is no longer in the source folder.'));
+ }
+ }
+
+ my $result =&Apache::lonnet::put('nohist_email'.$trgsuffix,
+ {$msgid => $message{$msgid}});
+ if (&Apache::lonnet::error($result)) {
+ return (0,&mt('Message not moved, A network error occurred.'));
+ }
# Copy status
unless ($trgfolder eq 'trash') {
- my %status=&Apache::lonnet::get('email_status'.$srcsuffix,[$msgid]);
- &Apache::lonnet::put('email_status'.$trgsuffix,{$msgid => $status{$msgid}});
+ my %status=&Apache::lonnet::get('email_status'.$srcsuffix,[$msgid]);
+ # a non-existant status is the mark of an unread msg
+ if (&Apache::lonnet::error(%status)) {
+ return (0,&mt('Message copied to new folder but status was not, A network error occurred.'));
+ }
+ my $result=&Apache::lonnet::put('email_status'.$trgsuffix,
+ {$msgid => $status{$msgid}});
+ if (&Apache::lonnet::error($result)) {
+ return (0,&mt('Message copied to new folder but status was not, A network error occurred.'));
+ }
}
+
# Delete orginals
- &Apache::lonnet::del('nohist_email'.$srcsuffix,[$msgid]);
- &Apache::lonnet::del('email_status'.$srcsuffix,[$msgid]);
+ my $result_del_msg =
+ &Apache::lonnet::del('nohist_email'.$srcsuffix,[$msgid]);
+ my $result_del_stat =
+ &Apache::lonnet::del('email_status'.$srcsuffix,[$msgid]);
+ if (&Apache::lonnet::error($result_del_msg)) {
+ return (0,&mt('Message copied, but unable to delete the original from the source folder.'));
+ }
+ if (&Apache::lonnet::error($result_del_stat)) {
+ return (0,&mt('Message copied, but unable to delete the original status from the source folder.'));
+ }
+
+ return (1);
}
# ======================================================= Display a course list
sub discourse {
- my $r=shift;
- my $classlist = &Apache::loncoursedata::get_classlist();
- my $now=time;
- my %lt=&Apache::lonlocal::texthash('cfa' => 'Check All',
- 'cfs' => 'Check Section/Group',
- 'cfn' => 'Uncheck All');
- $r->print(<
-
-
-
-
-
-
-ENDDISHEADER
- my %coursepersonnel=&Apache::lonnet::get_course_adv_roles();
- $r->print('
');
- foreach my $role (sort keys %coursepersonnel) {
- foreach (split(/\,/,$coursepersonnel{$role})) {
- my ($puname,$pudom)=split(/\:/,$_);
- $r->print('
'.
- '
('.$_.'),
'.$role.'
');
- }
- }
- $r->print('
');
- my $sort = sub {
- my $aname=lc($classlist->{$a}[&Apache::loncoursedata::CL_FULLNAME()]);
- if (!$aname) { $aname=$a; }
- my $bname=lc($classlist->{$b}[&Apache::loncoursedata::CL_FULLNAME()]);
- if (!$bname) { $bname=$b; }
- return $aname cmp $bname;
- };
- foreach my $student (sort $sort (keys(%{$classlist}))) {
- my $info=$classlist->{$student};
- my ($sname,$sdom,$status,$fullname,$section) =
- (@{$info}[&Apache::loncoursedata::CL_SNAME(),
- &Apache::loncoursedata::CL_SDOM(),
- &Apache::loncoursedata::CL_STATUS(),
- &Apache::loncoursedata::CL_FULLNAME(),
- &Apache::loncoursedata::CL_SECTION()]);
- next if ($status ne 'Active');
- next if ($env{'request.course.sec'} &&
- $section ne $env{'request.course.sec'});
- my $key = 'send_to_&&&'.$section.'&&&_'.$student;
- if (! defined($fullname) || $fullname eq '') { $fullname = $sname; }
- $r->print('
'.
- '');
if ($numblocked > 0) {
+ $r->print(&blocked_in_folder($numblocked,$startblock,$endblock,
+ $by_ip,$clientip,$blockdom,\%setters));
+ }
+}
+
+sub blocked_in_folder {
+ my ($numblocked,$startblock,$endblock,$by_ip,$clientip,$blockdom,$setters) = @_;
+ my $output;
+ if ($by_ip) {
+ $output = '
'.
+ &mt('[quant,_1,message is, messages are] not viewable because display of LON-CAPA messages is blocked for your current IP address: [_2].',$numblocked,$clientip).' '.
+ &mt('Note: communication is being blocked for certain IP address(es).');
+ } else {
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);
+ $output = '
'.
+ &mt('[quant,_1,message is, messages are] not viewable because display of LON-CAPA messages sent to you by other students between [_2] and [_3] is currently being blocked because of online exams.',$numblocked,$beginblock,$finishblock);
}
+ #$output .= &Apache::loncommon::build_block_table($startblock,$endblock,
+ # $setters);
+ my ($blocked, $blocktext) = &Apache::loncommon::blocking_status("com",$clientip);
+ $output .="
".$blocktext;
+
+ return $output;
}
# ============================================================== Compose output
sub compout {
- my ($r,$forwarding,$replying,$broadcast,$replycrit,$folder,$dismode)=@_;
+ my ($r,$forwarding,$replying,$broadcast,$replycrit,$folder,$dismode,
+ $multiforward)=@_;
+ my $clientip = &Apache::lonnet::get_requestor_ip($r);
+ my %setters;
+ my ($startblock,$endblock,$triggerblock,$by_ip,$blockdom) =
+ &Apache::loncommon::blockcheck(\%setters,'com',$clientip);
+ if ($by_ip) {
+ my $showdom = &Apache::lonnet::domain($blockdom);
+ if ($showdom eq '') {
+ $showdom = $blockdom;
+ }
+ $r->print(&Apache::loncommon::start_page('Messages'));
+ $r->print(&Apache::lonhtmlcommon::breadcrumbs('Send and display messages'));
+ $r->print('
'.
+ &mt('Sending of LON-CAPA messages is blocked for your current IP address: [_1].',$clientip).'
'.
+ '
'.
+ &mt('Note: communication is being blocked for certain IP address(es).').
+ '
'.
+ &mt('This restriction was set by an administrator in the [_1] LON-CAPA domain.',$showdom).
+ '
';
+ }
if (&Apache::lonnet::allowed('srm',$env{'request.course.id'})
|| &Apache::lonnet::allowed('srm',$env{'request.course.id'}.
'/'.$env{'request.course.sec'})) {
+ my $crstype = &Apache::loncommon::course_type();
my $crithelp = Apache::loncommon::help_open_topic("Course_Critical_Message");
+ my $rsstxt;
+ if (&Apache::loncommon::course_type() eq 'Community') {
+ $rsstxt = &mt('Include in community RSS newsfeed');
+ } else {
+ $rsstxt = &mt('Include in course RSS newsfeed');
+ }
$dispcrit=
- '
' . $crithelp .
- '
'.
- '' . $crithelp .
- '
'.
-'';
- }
+ ''.$crithelp.' '.&mt('Require return receipt?').' '.
+ ' '.
+' ';
+ }
+ if ($broadcast ne 'group') {
+ if (&Apache::lonnet::allowed('dff',$env{'request.course.id'}) ||
+ &Apache::lonnet::allowed('dff',$env{'request.course.id'}.
+ '/'.$env{'request.course.sec'})) {
+
+ my $rectxt;
+ if (&Apache::loncommon::course_type() eq 'Community') {
+ $rectxt = &mt("Include in community's 'User records' for recipient(s)");
+ } else {
+ $rectxt = &mt("Include in course's 'User records' for recipient(s)");
+ }
+
+ $dispcrit.=' ';
+ }
+ }
+
my %message;
my %content;
+ my ($hasfloat,$broadcast_js,$sendmode,$can_grp_broadcast);
my $defdom=$env{'user.domain'};
+ if ($broadcast eq 'group') {
+ my %access_status = (
+ active => 0,
+ previous => 0,
+ future => 0,
+ );
+
+ if ($group eq '') {
+ my $studentsel = &discourse(\%access_status);
+ if ($studentsel) {
+ $r->print('
'.$studentsel.'
');
+ $hasfloat = 1;
+ }
+ } else {
+ $can_grp_broadcast = &check_group_priv($group);
+ if ($can_grp_broadcast) {
+ $hasfloat = &disgroup($r,$cdom,$cnum,$group,\%access_status);
+ }
+ }
+ if ($hasfloat) {
+ $sendmode = ''."\n";
+ $broadcast_js = qq|
+
+
+|;
+ }
+ }
if ($forwarding) {
%message=&Apache::lonnet::get('nohist_email'.$suffix,[$forwarding]);
%content=&Apache::lonmsg::unpackagemsg($message{$forwarding},$folder);
$dispcrit.='';
- $func=&mt('Forward');
+ $func1='Forward'; # do not translate here!
$dissub=&mt('Forwarding').': '.$content{'subject'};
$dismsg=&mt('Forwarded message from').' '.
$content{'sendername'}.' '.&mt('at').' '.$content{'senderdomain'};
if ($content{'baseurl'}) {
- $disbase='';
+ $disbase='';
}
}
if ($replying) {
@@ -766,7 +1574,7 @@ sub compout {
%content=&Apache::lonmsg::unpackagemsg($message{$replying},$folder);
$dispcrit.='';
- $func=&mt('Send Reply to');
+ $func1='Send Reply to'; # do not translate here!
$dissub=&mt('Reply').': '.$content{'subject'};
$dismsg='> '.$content{'message'};
@@ -774,96 +1582,332 @@ sub compout {
$dismsg=~s/\f/\n/g;
$dismsg=~s/\n+/\n\> /g;
if ($content{'baseurl'}) {
- $disbase='';
+ $disbase='';
if ($env{'user.adv'}) {
- $disbase.='
');
- return;
+ return $broadcast_link;
}
# =========================================================== Show the citation
@@ -1534,9 +2705,22 @@ sub displayresource {
#
if (($env{'request.course.id'} eq $content{'courseid'})
&& (&Apache::lonnet::allowed('vgr',$content{'courseid'}))) {
- my $symb=&Apache::lonnet::symbread($content{'baseurl'});
+ my $symb;
+ if (defined($content{'symb'})) {
+ $symb = &Apache::lonenc::check_decrypt($content{'symb'});
+ } elsif (defined($content{'baseurl'})) {
+ $symb =
+ &Apache::lonnet::symbread(&Apache::lonenc::check_decrypt($content{'baseurl'}));
+ }
# Could not get a symb, give up
unless ($symb) { return $content{'citation'}; }
+ if ($symb =~ /ext\.tool$/) {
+ return '
'.&mt('Current transactions for student (if applicable)').'
'.
+ &Apache::loncommon::get_previous_attempt($symb,
+ $content{'sendername'},
+ $content{'senderdomain'},
+ $content{'courseid'});
+ }
# Have a symb, can render
return '
'.&mt('Current attempts of student (if applicable)').'
'.
&Apache::loncommon::get_previous_attempt($symb,
@@ -1562,27 +2746,30 @@ sub displayresource {
# ================================================================== The Header
sub header {
- my ($r,$title,$baseurl)=@_;
-
+ my ($r,$title,$baseurl,$head_extra)=@_;
my $extra = &Apache::loncommon::studentbrowser_javascript();
if ($baseurl) {
- $extra .= "";
+ $extra .= "";
+ }
+ $extra .= '';
+ if ($head_extra) {
+ $extra .= "\n$head_extra";
}
- $r->print(&Apache::loncommon::start_page('Communication and Messages',
- $extra));
+ $r->print(&Apache::loncommon::start_page('Messages',
+ $extra));
$r->print(&Apache::lonhtmlcommon::breadcrumbs
- (undef,($title?$title:'Communication and Messages')));
-
+ (($title?$title:'Send and display messages')));
}
# ---------------------------------------------------------------- Print header
sub printheader {
- my ($r,$url,$desc,$title,$baseurl)=@_;
+ my ($r,$url,$desc,$title,$baseurl,$head_extra)=@_;
&Apache::lonhtmlcommon::add_breadcrumb
({href=>$url,
text=>$desc});
- &header($r,$title,$baseurl);
+ &header($r,$title,$baseurl,$head_extra);
}
# ------------------------------------------------------------ Store the comment
@@ -1591,31 +2778,31 @@ sub storecomment {
my ($r)=@_;
my $msgtxt=&Apache::lonfeedback::clear_out_html($env{'form.message'});
my $cleanmsgtxt='';
- foreach (split(/[\n\r]/,$msgtxt)) {
- unless ($_=~/^\s*(\>|\>\;)/) {
- $cleanmsgtxt.=$_."\n";
+ foreach my $line (split(/[\n\r]/,$msgtxt)) {
+ unless ($line=~/^\s*(\>|\>\;)/) {
+ $cleanmsgtxt.=$line."\n";
}
}
- my $key=&Apache::lonnet::escape($env{'form.baseurl'}).'___'.time;
+ my $key=&escape($env{'form.baseurl'}).'___'.time;
&Apache::lonnet::put('nohist_stored_comments',{ $key => $cleanmsgtxt });
}
sub storedcommentlisting {
my ($r)=@_;
my %msgs=&Apache::lonnet::dump('nohist_stored_comments',undef,undef,
- '^'.&Apache::lonnet::escape(&Apache::lonnet::escape($env{'form.showcommentbaseurl'})));
- $r->print(&Apache::loncommon::start_page('Stored Comment Listing',undef,
+ '^'.&escape(&escape($env{'form.showcommentbaseurl'})));
+ $r->print(&Apache::loncommon::start_page('Saved Comment Listing',undef,
{'onlybody' => 1}));
- if ((keys %msgs)[0]=~/^error\:/) {
- $r->print(&mt('No stored comments yet.'));
+ if ((keys(%msgs))[0]=~/^error\:/) {
+ $r->print(&mt('No saved comments yet.'));
} else {
my $found=0;
- foreach (sort keys %msgs) {
- $r->print("\n".$msgs{$_}."");
+ foreach my $key (sort(keys(%msgs))) {
+ $r->print("\n".$msgs{$key}."");
$found=1;
}
unless ($found) {
- $r->print(&mt('No stored comments yet for this resource.'));
+ $r->print(&mt('No saved comments yet for this resource.'));
}
}
}
@@ -1626,20 +2813,47 @@ sub sendoffmail {
my ($r,$folder)=@_;
my $suffix=&Apache::lonmsg::foldersuffix($folder);
my $sendstatus='';
- my %specialmsg_status;
- my $numspecial = 0;
- if ($env{'form.send'}) {
- &printheader($r,'','Messages being sent.');
+ my %msg_status;
+ my $numsent = 0;
+ my $nosentstore = 1;
+ my $attachmenturl;
+ my $now = time;
+ my ($cdom,$cnum,$group);
+ if (exists($env{'form.group'})) {
+ $group = $env{'form.group'};
+ }
+ if (exists($env{'request.course.id'})) {
+ $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ }
+ my $clientip = &Apache::lonnet::get_requestor_ip($r);
+ my %setters;
+ my ($startblock,$endblock,$triggerblock,$by_ip,$blockdom) =
+ &Apache::loncommon::blockcheck(\%setters,'com',$clientip);
+ if ($by_ip) {
+ &printheader($r,'','Sending messages blocked from your location.');
+ return 'blocked';
+ } elsif ($env{'form.send'}) {
+ if (!$env{'form.multiforward'}) {
+ if ($group eq '') {
+ &printheader($r,'','Messages being sent.');
+ } else {
+ $r->print(&groupmail_header('sending',$group));
+ }
+ }
$r->rflush();
my %content=();
undef %content;
if ($env{'form.forwid'}) {
my $msgid=$env{'form.forwid'};
my %message=&Apache::lonnet::get('nohist_email'.$suffix,[$msgid]);
- %content=&Apache::lonmsg::unpackagemsg($message{$msgid},1);
+ %content=&Apache::lonmsg::unpackagemsg($message{$msgid},1,1);
&statuschange($msgid,'forwarded',$folder);
- $env{'form.message'}.="\n\n-- Forwarded message --\n\n".
- $content{'message'};
+ if ($content{'attachmenturl'} ne '') {
+ $attachmenturl = $content{'attachmenturl'};
+ }
+ $env{'form.message'} .= "\n\n-- Forwarded message --\n\n".
+ $content{'message'};
}
if ($env{'form.replyid'}) {
my $msgid=$env{'form.replyid'};
@@ -1647,32 +2861,185 @@ sub sendoffmail {
%content=&Apache::lonmsg::unpackagemsg($message{$msgid},1);
&statuschange($msgid,'replied',$folder);
}
- 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*/,$_);
+
+ my $mode = $env{'form.sendmode'};
+ my (%toaddr,$tos,$cc,$bcc,$broadcast);
+ my (%willtrust,%trustchecked,%disallowed);
+ my $serverdefdom = &Apache::lonnet::default_login_domain();
+
+ if ($mode eq 'group') {
+ if (defined($env{'form.courserecips'})) {
+ my $courseusers = $env{'form.courserecips'};
+ $courseusers =~ s/^_\&\&\&_//;
+ my @to = split('_&&&_',$courseusers);
+ foreach my $dest (@to) {
+ my ($user,$domain) = split(/:/, $dest);
+ if (($user ne '') && ($domain ne '')) {
+ unless ($trustchecked{$domain}) {
+ $willtrust{$domain} = &Apache::lonnet::will_trust('msg',$serverdefdom,$domain);
+ $trustchecked{$domain} = 1;
+ }
+ if ($willtrust{$domain}) {
+ my $rec = $user.":".$domain;
+ $toaddr{$rec} = '';
+ $broadcast->{$rec} = '';
+ } else {
+ $disallowed{'to'}{$user.":".$domain} = 1;
+ }
+ }
+ }
+ }
+ } elsif ($mode eq 'upload') {
+ $nosentstore = 0;
+ foreach my $line (split(/[\n\r\f]+/,$env{'form.upfile'})) {
+ my ($rec,$txt) = ($line =~ /^([^:]+:[^:]+):(.*)$/);
if ($txt) {
- $rec=~s/\@/\:/;
- $toaddr{$rec}.=$txt."\n";
+ $rec =~ s/^\s+//;
+ $rec =~ s/\s+$//;
+ my ($recuname,$recudom) = split(/:/,$rec);
+ unless ($trustchecked{$recudom}) {
+ $willtrust{$recudom} = &Apache::lonnet::will_trust('msg',$serverdefdom,$recudom);
+ $trustchecked{$recudom} = 1;
+ }
+ if ($willtrust{$recudom}) {
+ $toaddr{$rec}.=$txt."\n";
+ $broadcast->{$rec} = '';
+ } else {
+ $disallowed{'to'}{$rec} = 1;
+ }
}
}
} else {
- $toaddr{$env{'form.recuname'}.':'.$env{'form.recdomain'}}='';
+ if (($env{'form.recuname'} ne '') && ($env{'form.recdomain'} ne '')) {
+ unless ($trustchecked{$env{'form.recdomain'}}) {
+ $willtrust{$env{'form.recdomain'}} = &Apache::lonnet::will_trust('msg',$serverdefdom,$env{'form.recdomain'});
+ $trustchecked{$env{'form.recdomain'}} = 1;
+ }
+ if ($willtrust{$env{'form.recdomain'}}) {
+ $toaddr{$env{'form.recuname'}.':'.$env{'form.recdomain'}}='';
+ $tos->{$env{'form.recuname'}.':'.$env{'form.recdomain'}}='';
+ } else {
+ $disallowed{'to'}{$env{'form.recuname'}.':'.$env{'form.recdomain'}};
+ }
+ }
}
- if ($env{'form.additionalrec'}) {
- foreach (split(/\,/,$env{'form.additionalrec'})) {
- my ($auname,$audom)=split(/\@/,$_);
- $toaddr{$auname.':'.$audom}='';
+ if ($env{'form.additionalrec_to'}) {
+ foreach my $rec (split(/\s*,\s*/,$env{'form.additionalrec_to'})) {
+ my ($auname,$audom)=split(/:/,$rec);
+ if (($auname ne "") && ($audom ne "")) {
+ unless ($trustchecked{$audom}) {
+ $willtrust{$audom} = &Apache::lonnet::will_trust('msg',$serverdefdom,$audom);
+ $trustchecked{$audom} = 1;
+ }
+ if ($willtrust{$audom}) {
+ $toaddr{$auname.':'.$audom}='';
+ $tos->{$auname.':'.$audom}='';
+ } else {
+ $disallowed{'to'}{$auname.':'.$audom};
+ }
+ }
+ }
+ }
+ if ($env{'form.replying_to'}) {
+ my @toreplies =
+ &Apache::loncommon::get_env_multiple('form.replying_to');
+ foreach my $rec (@toreplies) {
+ my ($auname,$audom)=split(/:/,$rec);
+ if (($auname ne "") && ($audom ne "")) {
+ unless ($trustchecked{$audom}) {
+ $willtrust{$audom} = &Apache::lonnet::will_trust('msg',$serverdefdom,$audom);
+ $trustchecked{$audom} = 1;
+ }
+ if ($willtrust{$audom}) {
+ $toaddr{$auname.':'.$audom}='';
+ $tos->{$auname.':'.$audom}='';
+ } else {
+ $disallowed{'to'}{$auname.':'.$audom};
+ }
+ }
+ }
+ }
+ if ($env{'form.additionalrec_cc'}) {
+ foreach my $rec (split(/\s*,\s*/,$env{'form.additionalrec_cc'})) {
+ my ($auname,$audom)=split(/:/,$rec);
+ if (($auname ne "") && ($audom ne "")) {
+ if (!defined($tos->{$auname.':'.$audom})) {
+ unless ($trustchecked{$audom}) {
+ $willtrust{$audom} = &Apache::lonnet::will_trust('msg',$serverdefdom,$audom);
+ $trustchecked{$audom} = 1;
+ }
+ if ($willtrust{$audom}) {
+ $toaddr{$auname.':'.$audom}='';
+ $cc->{$auname.':'.$audom}='';
+ } else {
+ $disallowed{'cc'}{$auname.':'.$audom};
+ }
+ }
+ }
}
}
-
+ if ($env{'form.replying_cc'}) {
+ my @ccreplies =
+ &Apache::loncommon::get_env_multiple('form.replying_cc');
+ foreach my $rec (@ccreplies) {
+ my ($auname,$audom)=split(/:/,$rec);
+ if (($auname ne "") && ($audom ne "")) {
+ if (!defined($tos->{$auname.':'.$audom})) {
+ unless ($trustchecked{$audom}) {
+ $willtrust{$audom} = &Apache::lonnet::will_trust('msg',$serverdefdom,$audom);
+ $trustchecked{$audom} = 1;
+ }
+ if ($willtrust{$audom}) {
+ $toaddr{$auname.':'.$audom}='';
+ $cc->{$auname.':'.$audom}='';
+ } else {
+ $disallowed{'cc'}{$auname.':'.$audom} = 1;
+ }
+ }
+ }
+ }
+ }
+ if ($env{'form.replying_groupcc'}) {
+ my @groupreplies =
+ &Apache::loncommon::get_env_multiple('form.replying_groupcc');
+ foreach my $rec (@groupreplies) {
+ my ($auname,$audom)=split(/:/,$rec);
+ if (($auname ne "") && ($audom ne "")) {
+ if (!defined($tos->{$auname.':'.$audom})) {
+ unless ($trustchecked{$audom}) {
+ $willtrust{$audom} = &Apache::lonnet::will_trust('msg',$serverdefdom,$audom);
+ $trustchecked{$audom} = 1;
+ }
+ if ($willtrust{$audom}) {
+ $toaddr{$auname.':'.$audom}='';
+ $broadcast->{$auname.':'.$audom}='';
+ } else {
+ $disallowed{'to'}{$auname.':'.$audom} = 1;
+ }
+ }
+ }
+ }
+ }
+ if ($env{'form.additionalrec_bcc'}) {
+ foreach my $rec (split(/\s*,\s*/,$env{'form.additionalrec_bcc'})) {
+ my ($auname,$audom)=split(/:/,$rec);
+ if (($auname ne "") && ($audom ne "")) {
+ if ((!defined($tos->{$auname.':'.$audom})) &&
+ (!defined($cc->{$auname.':'.$audom}))) {
+ unless ($trustchecked{$audom}) {
+ $willtrust{$audom} = &Apache::lonnet::will_trust('msg',$serverdefdom,$audom);
+ $trustchecked{$audom} = 1;
+ }
+ if ($willtrust{$audom}) {
+ $toaddr{$auname.':'.$audom}='';
+ $bcc->{$auname.':'.$audom}='';
+ } else {
+ $disallowed{'bcc'}{$auname.':'.$audom} = 1;
+ }
+ }
+ }
+ }
+ }
my $savemsg;
my $msgtype;
my %sentmessage;
@@ -1688,107 +3055,201 @@ sub sendoffmail {
} else {
$savemsg=&Apache::lonfeedback::clear_out_html($env{'form.message'});
}
-
- foreach (keys %toaddr) {
- my ($recuname,$recdomain)=split(/\:/,$_);
+ my ($recipid, @recusers, @recudoms, %permresults);
+ if (keys(%toaddr) > 0) {
+ my %reciphash = (
+ to => $tos,
+ cc => $cc,
+ bcc => $bcc,
+ );
+ if ($mode eq 'group') {
+ if ($group eq '') {
+ $reciphash{'course_broadcast'} = $broadcast;
+ } else {
+ if ($env{'form.groupmail'} eq 'cc') {
+ $reciphash{'group_cc_broadcast'} = $broadcast;
+ } else {
+ $reciphash{'group_bcc_broadcast'} = $broadcast;
+ }
+ }
+ }
+ ($recipid,my $recipstatus) =
+ &Apache::lonmsg::store_recipients($msgsubj,$env{'user.name'},
+ $env{'user.domain'},\%reciphash);
+ if ($recipstatus ne 'ok') {
+ &Apache::lonnet::logthis('Failed to store To, Bcc and Cc recipients for '.$env{'user.name'}.':'.$env{'user.domain'});
+ }
+ if ($env{'form.attachment'}) {
+ if (length($env{'form.attachment'}) <= 1048576) {
+ $attachmenturl=&Apache::lonnet::userfileupload('attachment',undef,'feedback/'.$now);
+ } else {
+ $r->print('
'.&mt('Attachment not included - exceeded permitted length').'
');
+ }
+ } elsif ($env{'form.multiforward'}) {
+ if ($env{'form.attachmenturl'} ne '') {
+ $attachmenturl = $env{'form.attachmenturl'};
+ }
+ }
+ }
+ foreach my $address (sort(keys(%toaddr))) {
+ my ($recuname,$recdomain)=split(/\:/,$address);
my $msgtxt = $savemsg;
- if ($toaddr{$_}) { $msgtxt.=''.$toaddr{$_}; }
- my $thismsg;
- if ((($env{'form.critmsg'}) || ($env{'form.sendbck'})) &&
- (&Apache::lonnet::allowed('srm',$env{'request.course.id'})
- || &Apache::lonnet::allowed('srm',$env{'request.course.id'}.
- '/'.$env{'request.course.sec'}))) {
- $r->print(&mt('Sending critical message').' '.$recuname.'@'.$recdomain.': ');
- $thismsg=&Apache::lonmsg::user_crit_msg($recuname,$recdomain,$msgsubj,$msgtxt,
- $env{'form.sendbck'},$env{'form.permanent'},
- \$sentmessage{$_});
+ if ($toaddr{$address}) {
+ $msgtxt.="\n".''."\n".$toaddr{$address};
+ }
+ my @thismsg;
+ if ($msgtype eq 'critical') {
+ $r->print(&mt('Sending critical message').' '.
+ $recuname.':'.$recdomain.': ');
+ @thismsg=
+ &Apache::lonmsg::user_crit_msg($recuname,$recdomain,
+ $msgsubj,$msgtxt,
+ $env{'form.sendbck'},
+ $env{'form.permanent'},
+ \$sentmessage{$address},
+ $nosentstore,$recipid,
+ $attachmenturl,\%permresults);
} else {
- $r->print(&mt('Sending').' '.$recuname.'@'.$recdomain.': ');
- $thismsg=&Apache::lonmsg::user_normal_msg($recuname,$recdomain,$msgsubj,$msgtxt,
- $content{'citation'},undef,undef,$env{'form.permanent'},\$sentmessage{$_});
- }
- if (($env{'request.course.id'}) && (($msgtype eq 'critical') ||
- ($env{'form.sendmode'} eq 'group'))) {
- $specialmsg_status{$recuname.':'.$recdomain} = $thismsg;
- if ($thismsg eq 'ok') {
- $numspecial ++;
+ $r->print(&mt('Sending').' '.$recuname.':'.$recdomain.': ');
+ @thismsg=
+ &Apache::lonmsg::user_normal_msg($recuname,$recdomain,
+ $msgsubj,$msgtxt,
+ $content{'citation'},
+ undef,$attachmenturl,
+ $env{'form.permanent'},
+ \$sentmessage{$address},
+ undef,undef,undef,
+ $nosentstore,$recipid,
+ \%permresults);
+ }
+ $msg_status{$recuname.':'.$recdomain}=join(' ',@thismsg);
+ if ($msg_status{$recuname.':'.$recdomain} =~ /(ok|con_delayed)/) {
+ $numsent++;
+ push(@recusers,$recuname);
+ push(@recudoms,$recdomain);
+ if ($1 eq 'ok') {
+ $r->print('ok ');
+ }
+ if ($permresults{$recuname.':'.$recdomain}) {
+ $r->print(' (email) ');
}
}
- $r->print($thismsg.' ');
- $sendstatus.=' '.$thismsg;
+ $sendstatus.=' '.join(' ',@thismsg);
}
- if (($env{'request.course.id'}) && (($env{'form.sendmode'} eq 'group')
- || ($msgtype eq 'critical'))) {
- my $subj_prefix;
- if ($msgtype eq 'critical') {
- $subj_prefix = 'Critical.';
+ my $subj_prefix;
+ if ($numsent > 0) {
+ if (($env{'request.course.id'}) &&
+ (($mode eq 'group') ||
+ ($env{'form.courserecord'}) ||
+ ($msgtype eq 'critical')) ||
+ ($env{'form.replyid'} &&
+ (($content{'courseid'} ne '') &&
+ ($mode eq 'group')))) {
+ if ($msgtype eq 'critical') {
+ $subj_prefix = 'Critical.';
+ } elsif ($mode eq 'group') {
+ $subj_prefix = 'Broadcast.';
+ } else {
+ $subj_prefix = 'Archive';
+ }
+ my ($specialmsgid,$specialresult);
+ my $course_str;
+ if ($env{'form.replyid'}) {
+ if ($content{'courseid'} ne '') {
+ my %crsdesc =
+ &Apache::lonnet::coursedescription($content{'courseid'},
+ {'one_time' => 1});
+ $course_str = &escape('['.$crsdesc{'num'}.':'.$crsdesc{'domain'}.']');
+ }
+ } elsif ($env{'request.course.id'}) {
+ $course_str = &escape('['.$cnum.':'.$cdom.']');
+ }
+ $specialresult =
+ &Apache::lonmsg::user_normal_msg_raw($cnum,$cdom,
+ $subj_prefix.' '.$course_str,$savemsg,undef,undef,
+ $attachmenturl,undef,undef,\$specialmsgid,undef,undef,undef,
+ undef,undef,1);
+ $specialmsgid = &unescape($specialmsgid);
+ if ($specialresult eq 'ok') {
+ my ($stamp,$crssubj,$msgname,$msgdom,$msgcount,$context,$pid) =
+ split(/\:/,&unescape($specialmsgid));
+
+ foreach my $recipient (sort(keys(%toaddr))) {
+ if ($msg_status{$recipient} =~ /\s*(ok|con_delayed)\s*/) {
+ my $usersubj = $subj_prefix.'['.$recipient.']';
+ my $usermsgid =
+ &Apache::lonmsg::buildmsgid($stamp,$usersubj,
+ $msgname,$msgdom,
+ $msgcount,$context,
+ $pid);
+ &Apache::lonmsg::user_normal_msg_raw($cnum,$cdom,
+ $subj_prefix.' ['.$recipient.']',$msgsubj,
+ undef,undef,$attachmenturl,undef,$usermsgid,undef,
+ undef,$specialmsgid,undef,undef,undef,1);
+ }
+ }
+ if (($mode ne 'upload') && (@recusers > 0)) {
+ &Apache::lonmsg::process_sent_mail($msgsubj,
+ $subj_prefix,$numsent,$stamp,$msgname,$msgdom,
+ $msgcount,$context,$pid,$savemsg,\@recusers,
+ \@recudoms,undef,$attachmenturl,'','','','',$recipid);
+ }
+ } else {
+ &Apache::lonnet::logthis('Failed to create record of critical, broadcast or archived message in '.$env{'course.'.$env{'request.course.id'}.'.num'}.' '&mt('at').' '.$env{'course.'.$env{'request.course.id'}.'.domain'}.' - no msgid generated');
+ }
} else {
- $subj_prefix = 'Broadcast.';
+ my $stamp = time;
+ my $msgcount = &Apache::lonmsg::get_uniq();
+ my $context = &Apache::lonmsg::get_course_context();
+ &Apache::lonmsg::process_sent_mail($msgsubj,$subj_prefix,
+ $numsent,$stamp,$env{'user.name'},
+ $env{'user.domain'},$msgcount,$context,
+ $$,$savemsg,\@recusers,\@recudoms,undef,$attachmenturl,
+ '','','','',$recipid);
}
- my ($specialmsgid,$specialresult);
- my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
- my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
- my $course_str = &Apache::lonnet::escape('['.$cnum.':'.$cdom.']');
-
- if ($numspecial) {
- $specialresult = &Apache::lonmsg::user_normal_msg_raw($cnum,$cdom,$subj_prefix.
- ' '.$course_str,$savemsg,undef,undef,undef,
- undef,undef,\$specialmsgid);
- $specialmsgid = &Apache::lonnet::unescape($specialmsgid);
- }
- if ($specialresult eq 'ok') {
- my $record_sent;
- my @recusers = ();
- my @recudoms = ();
- my ($stamp,$crssubj,$msgname,$msgdom,$msgcount,$context,$pid) =
- split(/\:/,&Apache::lonnet::unescape($specialmsgid));
- foreach my $recipient (sort(keys(%toaddr))) {
- if ($specialmsg_status{$recipient} eq 'ok') {
- my $usersubj = $subj_prefix.'['.$recipient.']';
- my $usermsgid =
- &Apache::lonmsg::buildmsgid($stamp,$usersubj,
- $msgname,$msgdom,
- $msgcount,$context,
- $pid);
- &Apache::lonmsg::user_normal_msg_raw($cnum,$cdom,$subj_prefix.
- ' ['.$recipient.']',$msgsubj,undef,
- undef,undef,undef,$usermsgid,undef,undef,$specialmsgid);
- my ($uname,$udom) = split/:/,$recipient;
- push(@recusers,$uname);
- push(@recudoms,$udom);
- }
- }
- if (@recusers) {
- my $specialmessage;
- my $sentsubj = $subj_prefix.' ('.$numspecial.' sent) '.
- $msgsubj;
- $sentsubj = &HTML::Entities::encode($sentsubj,'<>&"');
- my $sentmsgid =
- &Apache::lonmsg::buildmsgid($stamp,$sentsubj,$msgname,
- $msgdom,$msgcount,$context,
- $pid);
- ($specialmsgid,$specialmessage) = &Apache::lonmsg::packagemsg($msgsubj,$savemsg,
- undef,undef,undef,\@recusers,\@recudoms,$sentmsgid);
- $record_sent = &Apache::lonmsg::store_sent_mail($specialmsgid,$specialmessage);
+ }
+ if (!$env{'form.multiforward'}) {
+ if ($sendstatus=~/^(\s*(?:ok|con_delayed)\s*)*$/) {
+ my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Completed.'));
+ $message = &Apache::loncommon::confirmwrapper($message);
+ $r->print($message);
+ if ($env{'form.displayedcrit'}) {
+ &discrit($r);
}
+ if ($group ne '') {
+ $r->print(&groupmail_sent($group,$cdom,$cnum));
+ } else {
+ &Apache::loncommunicate::menu($r);
+ }
} else {
- &Apache::lonnet::logthis('Failed to create record of critical message or broadcast in '.$env{'course.'.$env{'request.course.id'}.'.num'}.' at '.$env{'course.'.$env{'request.course.id'}.'.domain'}.' - no msgid generated');
+ my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Could not deliver message'),1);
+ $message .= ' '.&mt('Please use the browser "Back" button and correct the recipient addresses ([_1]).',$sendstatus);
+ $message = &Apache::loncommon::confirmwrapper($message);
+ $r->print($message);
+ }
+ }
+ if (keys(%disallowed)) {
+ if ((ref($disallowed{'to'}) eq 'HASH') && (keys(%{$disallowed{'to'}}) > 0)) {
+ $r->print(&mt("The following recipients were excluded because the user's domain does not accept messages from server's domain:").'
'.
+ join("
\n",sort(keys(%{$disallowed{'to'}}))).
+ '
');
+ }
+ if (ref($disallowed{'cc'}) eq 'HASH') {
+ $r->print(&mt("The following CCs were excluded because the user's domain does not accept messages from server's domain:").'
'.
+ join("
\n",sort(keys(%{$disallowed{'cc'}}))).
+ '
');
+ }
+ if (ref($disallowed{'bcc'}) eq 'HASH') {
+ $r->print(&mt("The following BCCs were excluded because the user's domain does not accept messages from server's domain:").'