# The LearningOnline Network with CAPA # Sending messages # # $Id: lonnotify.pm,v 1.41 2014/12/11 13:15:35 raeburn 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. # # 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. # # 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 # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # package Apache::lonnotify; use strict; use Apache::lonnet; use Apache::loncommon; use Apache::courseclassifier; use LONCAPA::Enrollment; use Apache::Constants qw(:common :http); use Apache::lonlocal; use Mail::Send; use HTML::TokeParser; use HTML::Entities; use lib '/home/httpd/lib/perl/'; use LONCAPA; sub handler { my ($r) = @_; &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; if ($r->header_only) { return OK; } my $cdom = $env{'request.role.domain'}; unless (&Apache::lonnet::allowed('psa',$cdom)) { # Not allowed to broadcast e-mail system-wide $env{'user.error.msg'}="/adm/notify:psa:0:0:Cannot broadcast e-mail systemwide"; return HTTP_NOT_ACCEPTABLE; } &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['command']); my $command = $env{'form.command'}; my $origin = $env{'form.origin'}; &Apache::lonhtmlcommon::clear_breadcrumbs(); &Apache::lonhtmlcommon::add_breadcrumb ({href=>'/adm/notify', text=>"Broadcast E-mail"}); if ($command eq 'process') { &print_request_receipt($r,$command,$cdom); } elsif ($command eq 'compose') { &print_composition_form($r,$command,$cdom); } elsif ($command eq 'pick_target') { &print_selection_form($r,$command,$cdom); } elsif ($command eq 'pick_display') { &print_display_option_form($r,$command,$cdom); } elsif ($command eq 'display') { &print_display($r,$command,$cdom); } else { &print_front_page($r,'front',$cdom); } return OK; } sub add_script { my ($js) = @_; return ''; } sub start_page { my ($jscript,$bread_title,$formname) = @_; my $loadcode; if ((defined($env{'form.origin'})) && ($env{'form.command'} eq 'compose' || $env{'form.command'} eq 'pick_target' || $env{'form.command'} eq 'pick_display')) { if ($env{'form.origin'} ne '') { $loadcode = 'javascript:setFormElements(document.'.$env{'form.command'}.')'; if (($env{'form.command'} eq 'pick_target') && (($env{'form.origin'} eq 'compose') || ($env{'form.origin'} eq 'process'))) { if ($env{'form.coursepick'} eq 'category') { $loadcode .= ';javascript:setCourseCat(document.'.$env{'form.command'}.')'; } } } } my $start_page = &Apache::loncommon::start_page('Broadcast e-mail to users', $jscript, {'add_entries' => {'onload' => $loadcode,},}); my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs($bread_title, 'Broadcast_system_email'); my $output = <<"ENDONE"; $start_page $breadcrumbs
ENDONE return $output; } sub end_page { return '
'.&Apache::loncommon::end_page(); } sub print_front_page { my ($r,$formname,$cdom) = @_; my $jscript = qq| function next_page(caller) { if (caller == 'view') { document.front.command.value="pick_display" } else { document.front.command.value="pick_target" } document.front.submit() } |; my @menu= ({ categorytitle=>'Broadcast e-mail to Domain', items =>[ { linktext => 'Send e-mail to selected users', url => 'javascript:next_page('."'new'".')', permission => 1, #help => '', icon => 'mail-reply-all.png', linktitle => 'Send a new e-mail to selected users from this domain' }, { linktext => 'Display sent e-mails', url => 'javascript:next_page('."'view'".')', permission => 1, #help => '', icon => 'messalog.png', linktitle => 'Display e-mail sent by Domain Coordinators in this domain' }, ] }, ); $r->print( &start_page(&add_script($jscript), 'Broadcast e-mail to Domain', $formname) .'' .&Apache::lonhtmlcommon::generate_menu(@menu) .&end_page() ); return; } sub print_display_option_form { my ($r,$formname,$cdom) = @_; &Apache::lonhtmlcommon::add_breadcrumb({text=>"Display options"}); my $cmd = 'display'; my $submit_text = &mt('Display e-mail'); my @roles = ('dc'); my $now = time; my $startdateform = &Apache::lonhtmlcommon::date_setter($formname, 'startdate', $now); my $enddateform = &Apache::lonhtmlcommon::date_setter($formname, 'enddate', $now); my %elements = ( startdate_month => 'selectbox', startdate_hour => 'selectbox', enddate_month => 'selectbox', enddate_hour => 'selectbox', startdate_day => 'text', startdate_year => 'text', startdate_minute => 'text', startdate_second => 'text', enddate_day => 'text', enddate_year => 'text', enddate_minute => 'text', enddate_second => 'text', sender => 'checkbox', ); my $jscript = &Apache::lonhtmlcommon::set_form_elements(\%elements); my $output = &start_page(&add_script($jscript), 'Broadcast e-mail display options', $formname); $output .= &Apache::lonhtmlcommon::start_pick_box(); $output .= &Apache::lonhtmlcommon::row_title(&mt('Date range')); $output .= ''; $output .= '
'.&mt('Earliest to display:').' '. $startdateform.'
'.&mt('Latest to display:').' '.$enddateform. '
'; $output .= &Apache::lonhtmlcommon::row_closure(); $output .= &Apache::lonhtmlcommon::row_title(&mt('Choose sender(s)')); my %personnel = &Apache::lonnet::get_domain_roles($cdom,\@roles); my @domcc = (); foreach my $server (keys(%personnel)) { foreach my $user (sort(keys(%{$personnel{$server}}))) { my ($trole,$uname,$udom,$runame,$rudom,$rsec) = split(/:/,$user); unless (grep/^$uname:$udom$/,@domcc) { my %userinfo = &Apache::lonnet::get('environment',['lastname','firstname'],$udom,$uname); $output .= ' '.$userinfo{'firstname'}.' '.$userinfo{'lastname'}.'  ('.$uname.':'.$udom.')'; push (@domcc,$uname.':'.$udom); } } } $output .= &Apache::lonhtmlcommon::row_closure(); $output .= &Apache::lonhtmlcommon::submit_row(&mt('Submit'),$cmd,$submit_text); $output .= &Apache::lonhtmlcommon::end_pick_box(); $output .= qq(\n). &end_page(); $r->print($output); return; } sub print_display { my ($r,$formname,$cdom) = @_; &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:goBack('pick_display')", text=>"Display options"}, {text=>"E-mail display"}); my $msgcount = 0; my $start = &Apache::lonhtmlcommon::get_date_from_form('startdate'); my $end = &Apache::lonhtmlcommon::get_date_from_form('enddate'); my @senders = &Apache::loncommon::get_env_multiple('form.sender'); my %sentmail = &Apache::lonnet::dcmaildump($cdom,$start,$end,\@senders); my %dcmail = (); my %Sortby = (); my $jscript = <<"ENDSCRIPT"; function changeSort(caller) { document.$formname.command.value = '$formname'; document.$formname.sortby.value = caller; document.$formname.submit(); } function goBack(target) { document.$formname.command.value = target; document.$formname.submit(); } ENDSCRIPT my $output = &start_page(&add_script($jscript), 'Display Broadcast e-mail', $formname); foreach my $msgid (keys(%sentmail)) { my %content = &Apache::lonmsg::unpackagemsg($sentmail{$msgid}); $msgcount ++; %{$dcmail{$msgid}} = (); foreach my $item (keys(%content)) { if ($item eq 'recipient') { foreach my $user (keys(%{$content{recipient}})) { $dcmail{$msgid}{recipient}{$user} = $content{recipient}{$user}; } } else { $dcmail{$msgid}{$item} = $content{$item}; } } } $output .= &Apache::loncommon::start_data_table(); if ($msgcount > 0) { $output .= &Apache::loncommon::start_data_table_header_row(). ''.&mt('Date').''. ''.&mt('Subject').''. ''.&mt('Sender').''. ''.&mt('Message').''. ''.&mt('Recipients').''. &Apache::loncommon::end_data_table_header_row(); if (($env{'form.sortby'} eq 'date') || ($env{'form.sortby'} eq '') || (!defined($env{'form.sortby'})) || (($env{'form.sortby'} eq 'sender') && (@senders <= 1))) { foreach my $msgid (sort(keys(%dcmail))) { my $recipients = ''; my ($date,undef,$sname,$sdom) = &Apache::lonmsg::unpackmsgid($msgid,undef,1); $date = &Apache::lonlocal::locallocaltime($date); foreach my $user (sort(keys(%{$dcmail{$msgid}{recipient}}))) { $recipients .= $dcmail{$msgid}{recipient}{$user}.', '; } $recipients =~ s/,\s$//; $output .= &Apache::loncommon::start_data_table_row(). ''.$date.''. ''.&cr_to_br($dcmail{$msgid}{subject}).''. ''.$sname.':'.$sdom.''.&cr_to_br($dcmail{$msgid}{message}).''. ''.$recipients.''."\n". &Apache::loncommon::end_data_table_row(); } } else { foreach my $msgid (sort(keys(%dcmail))) { my ($date,undef,$sname,$sdom) = &Apache::lonmsg::unpackmsgid($msgid,undef,1); if ($env{'form.sortby'} eq 'subject') { push @{$Sortby{$dcmail{$msgid}{subject}}},$msgid; } elsif ($env{'form.sortby'} eq 'message') { push @{$Sortby{$dcmail{$msgid}{message}}},$msgid; } elsif ($env{'form.sortby'} eq 'recipients') { my $recipients =''; foreach my $user (sort(keys(%{$dcmail{$msgid}{recipient}}))) { $recipients .= $dcmail{$msgid}{recipient}{$user}.', '; } $recipients =~ s/,\s$//; push @{$Sortby{$recipients}},$msgid; } elsif ($env{'form.sortby'} eq 'sender') { if (@senders > 1) { push @{$Sortby{$sname.':'.$sdom}},$msgid; } } } foreach my $key (sort(keys(%Sortby))) { foreach my $msgid (@{$Sortby{$key}}) { my $recipients = ''; if ($env{'form.sortby'} eq 'recipients') { $recipients = $key; } else { foreach my $user (sort(keys(%{$dcmail{$msgid}{recipient}}))) { $recipients .= $dcmail{$msgid}{recipient}{$user}.', '; } $recipients =~ s/,\s$//; } my ($date,undef,$sname,$sdom) = &Apache::lonmsg::unpackmsgid($msgid,undef,1); $date = &Apache::lonlocal::locallocaltime($date); $output .= &Apache::loncommon::start_data_table_row(). ''.$date.''. ''.&cr_to_br($dcmail{$msgid}{subject}).''. ''.$sname.':'.$sdom.''. ''.&cr_to_br($dcmail{$msgid}{message}).''. ''.$recipients.''."\n". &Apache::loncommon::end_data_table_row(); } } } } else { $output .= &Apache::loncommon::start_data_table_empty_row(). ''.&mt('No mail sent matching supplied criteria').''. &Apache::loncommon::end_data_table_empty_row(); } $output .= &Apache::loncommon::end_data_table(); $output .= &Apache::lonhtmlcommon::echo_form_input(['sortby','command','origin']); my $curr_sortby; if (defined($env{'form.sortby'})) { $curr_sortby = $env{'form.sortby'}; } else { $curr_sortby = 'date'; } $output .= qq(\n); $output .= qq(\n); $output .= qq(\n); $output .= &end_page(); $r->print($output); return; } sub print_selection_form { my ($r,$formname,$cdom) = @_; my %coursecodes = (); my %codes = (); my @codetitles = (); my %cat_titles = (); my %cat_order = (); my %idlist = (); my %idnums = (); my %idlist_titles = (); my $caller = 'global'; my $totcodes = 0; my $format_reply; my $jscript = ''; my %lt=&Apache::lonlocal::texthash( 'buil' => 'Building valid e-mail address from username, if missing from preferences:', 'kerb' => 'Kerberos: enter default for each realm used in the domain, with comma separation of entries', 'infs' => 'Internal, Filesystem and Local authentication: enter single default.', 'comp' => 'Compose E-mail' ); &Apache::lonhtmlcommon::add_breadcrumb ({text=>"Select Audience"}); $totcodes = &Apache::courseclassifier::retrieve_instcodes(\%coursecodes,$cdom,$totcodes); if ($totcodes > 0) { $format_reply = &Apache::lonnet::auto_instcode_format($caller,$cdom,\%coursecodes,\%codes,\@codetitles,\%cat_titles,\%cat_order); if ($format_reply eq 'ok') { my $numtypes = @codetitles; &Apache::courseclassifier::build_code_selections(\%codes,\@codetitles,\%cat_titles,\%cat_order,\%idlist,\%idnums,\%idlist_titles); my ($scripttext,$longtitles) = &Apache::courseclassifier::javascript_definitions(\@codetitles,\%idlist,\%idlist_titles,\%idnums,\%cat_titles); my $longtitles_str = join('","',@{$longtitles}); my $allidlist = $idlist{$codetitles[0]}; $jscript .= &Apache::courseclassifier::courseset_js_start($formname,$longtitles_str,$allidlist); $jscript .= $scripttext; $jscript .= &Apache::courseclassifier::javascript_code_selections($formname,@codetitles); } } my @standardnames = &Apache::loncommon::get_standard_codeitems(); my $cb_jscript = &Apache::loncommon::coursebrowser_javascript($cdom); my %elements = ( roles => 'selectbox', types => 'selectbox', Year => 'selectbox', coursepick => 'radio', coursetotal => 'text', courselist => 'text', internal => 'text', krb4 => 'text', krb5 => 'text', localauth => 'text', unix => 'text', ); $jscript .= &Apache::lonhtmlcommon::set_form_elements(\%elements); if ($env{'form.coursepick'} eq 'category') { $jscript .= qq| function setCourseCat(formname) { if (formname.Year.options[formname.Year.selectedIndex].value == -1) { return; } courseSet('$codetitles[0]'); for (var j=0; j
  • '.$lt{'kerb'}.'
    (e.g., MSU.EDU=msu.edu, MSUE.EDU=msue.msu.edu).
  • '.$lt{'infs'}.'
  • '."\n"; my $submit_text = $lt{'comp'}; my $cmd = 'compose'; $output .= &Apache::lonhtmlcommon::role_select_row(\@roles,&mt('Roles')); $output .= &Apache::lonhtmlcommon::course_select_row(&mt('Courses'),$formname,$totcodes,\@codetitles,\%idlist,\%idlist_titles,undef,undef,\@standardnames); $output .= &Apache::lonhtmlcommon::status_select_row(\%longtypes,&mt('Access status')); $output .= &Apache::lonhtmlcommon::email_default_row(\%authtypes,&mt('Username -> E-mail conversion'),$descrip); $output .= &Apache::lonhtmlcommon::submit_row(&mt('Submit'),$cmd,$submit_text); $output .= &Apache::lonhtmlcommon::end_pick_box(); $output .= &end_page(); $r->print($output); return; } sub print_composition_form { my ($r,$formname,$cdom) = @_; &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:goBack('pick_target')", text=>"Select Audience"}, {text=>"Compose E-mail"}); my $jscript = &Apache::loncommon::check_uncheck_jscript(); $jscript .= qq| function goBack(target) { document.$formname.command.value = target; document.$formname.submit(); } |; my %lt=&Apache::lonlocal::texthash( 'nore' => 'No recipients identified', 'emad' => 'e-mail address', ); my %elements = ( subject => 'text', message => 'text', sender => 'text', recipient => 'checkbox', ); $jscript .= &Apache::lonhtmlcommon::set_form_elements(\%elements); $r->print(&start_page(&add_script($jscript), 'Broadcast e-mail to users', $formname)); my $coursefilter = $env{'form.coursepick'}; my %courses; if ($coursefilter eq 'all') { %courses = &Apache::lonnet::courseiddump($cdom,'.','.','.','.','.', undef,undef,'Course'); } elsif ($coursefilter eq 'category') { my $instcode = &Apache::courseclassifier::instcode_from_selectors($cdom); my $regexp = ''; if ($instcode eq '') { $instcode = '.'; } else { $regexp = 1; } %courses = &Apache::lonnet::courseiddump($cdom,'.','.',$instcode,'.','.', undef,undef,'Course',$regexp); } elsif ($coursefilter eq 'specific') { if ($env{'form.coursetotal'} > 1) { my @course_ids = split(/&&/,$env{'form.courselist'}); foreach my $cid (@course_ids) { $courses{$cid} = ''; } } else { $courses{$env{'form.courselist'}} = ''; } } my @types = &Apache::loncommon::get_env_multiple('form.types'); my @roles = &Apache::loncommon::get_env_multiple('form.roles'); my %longtypes = (); my %authtypes = (); my %email_defaults = (); &form_elements(\%longtypes,\%authtypes); foreach my $auth (keys(%authtypes)) { if (exists($env{'form.'.$auth})) { my $default = $env{'form.'.$auth}; $default =~ s/^,+//; $default =~ s/,+$//; if ($auth =~ /^krb/) { %{$email_defaults{$auth}} = (); if ($default =~ /,/) { my @items = split(/,/,$default); foreach my $item (@items) { my ($realm,$value) = split(/=/,$item); $email_defaults{$auth}{$realm} = $value; } } else { my ($realm,$value) = split(/=/,$default); $email_defaults{$auth}{$realm} = $value; } } else { $email_defaults{$auth} = $default; } } } my $sender = &get_user_info($env{'user.name'},%email_defaults); my %recipients = (); my %users = (); my %access = (); my @sections = (); my $totalrecip = 0; my @unmatched = (); foreach my $role (@roles) { %{$users{$role}} = (); } foreach my $type (@types) { $access{$type} = $type; } foreach my $course_id (keys(%courses)) { my %coursehash = &Apache::lonnet::coursedescription($course_id,{'one_time' => 1}); my $cdom = $coursehash{'domain'}; my $cnum = $coursehash{'num'}; &Apache::loncommon::get_course_users($cdom,$cnum,\%access,\@roles,\@sections,\%users); } foreach my $role (keys(%users)) { foreach my $user (keys(%{$users{$role}})) { unless (defined($recipients{$user})) { $recipients{$user} = &get_user_info($user,%email_defaults); if ($recipients{$user} eq '') { push @unmatched, $user; } else { $totalrecip ++; } } } } my $output; if ($totalrecip > 0) { $output .= &Apache::lonhtmlcommon::start_pick_box(); $output .= &Apache::lonhtmlcommon::row_title(&mt('Subject')); $output .= ''; $output .= &Apache::lonhtmlcommon::row_closure(); $output .= &Apache::lonhtmlcommon::row_title(&mt('Message')); $output .= ' '; $output .= &Apache::lonhtmlcommon::row_closure(); $output .= &Apache::lonhtmlcommon::row_title(&mt('Recipients')); $output .= '   
    '; $output .= &Apache::loncommon::start_data_table(); if (keys(%recipients) > 0) { $output .= &Apache::loncommon::start_data_table_header_row(); $output .= ' username:domain'.$lt{'emad'}.''; $output .= &Apache::loncommon::end_data_table_header_row(); } foreach my $username (sort(keys(%recipients))) { $output .= &Apache::loncommon::start_data_table_row(); if ($recipients{$username} =~ /\@/) { my $value=&escape($username).':'.&escape($recipients{$username}); $output .= ''.$username.''.$recipients{$username}.''; } $output .= &Apache::loncommon::end_data_table_row(); } $output .= &Apache::loncommon::end_data_table(); if (@unmatched) { $output .= '

    '.&mt('Could not determine e-mail addresses for the following users:').''; } $output .= &Apache::lonhtmlcommon::row_closure(); $output .= &Apache::lonhtmlcommon::row_title(&mt('Sender e-mail address')); $output .= ''; $output .= &Apache::lonhtmlcommon::row_closure(); $output .= &Apache::lonhtmlcommon::submit_row(&mt('Submit'),'process',&mt('Send')); $output .= &Apache::lonhtmlcommon::end_pick_box(); } else { $output .= $lt{'nore'}."\n". ''."\n"; } $output .= ''."\n"; $output .= &Apache::lonhtmlcommon::echo_form_input(['command','origin','subject','message','recipient','sender'],); $output .= &end_page(); $r->print($output); return; } sub print_request_receipt { my ($r,$formname,$dom) =@_; my @recipients = &Apache::loncommon::get_env_multiple('form.recipient'); my $subject = $env{'form.subject'}; my $message = $env{'form.message'}; my $from = $env{'form.sender'}; my $jscript = <"javascript:goBack('pick_target')", text=>"Select audience"}); &Apache::lonhtmlcommon::add_breadcrumb ({href=>"javascript:goBack('compose')", text=>"Compose E-mail"}); &Apache::lonhtmlcommon::add_breadcrumb ({href=>"/adm/notify?command=process", text=>"Outcome"}); my $output = &start_page(&add_script($jscript), 'E-mail Delivery', $formname); my @deliveries = (); &broadcast_email(\@recipients,$subject,$from,$message,\@deliveries); if (@deliveries > 0) { $output .= &Apache::loncommon::start_data_table(); &store_mail($subject,$message,$dom,\@deliveries); $output .= &Apache::loncommon::start_data_table_header_row(). ''.&mt('Status').''. ''.&mt('Subject').''. ''.&mt('Message').''. ''.&mt('Recipients').''. &Apache::loncommon::end_data_table_header_row(); $output .= &Apache::loncommon::start_data_table_row(). ''.&mt('Sent').''. ''.&cr_to_br($subject).''. ''.&cr_to_br($message).''. ''; foreach my $person (@deliveries) { my ($username,$email) = split(/:/,$person); $output .= &unescape($email).' ('.&unescape($username).')
    '."\n"; } $output .= ''. &Apache::loncommon::end_data_table_row(). &Apache::loncommon::end_data_table(); } else { $output .= &mt('No mail sent - no recipients identified'); } $output .= '
    '.&mt('Send another e-mail').''."\n"; $output .= ''."\n". ''."\n"; $output .= &Apache::lonhtmlcommon::echo_form_input(['command','origin']); $output .= &end_page(); $r->print($output); return; } sub broadcast_email { my ($recipients,$subject,$from,$message,$deliveries)=@_; # Should implement staggered delivery for large numbers of recipients?. foreach my $user (@{$recipients}) { my $msg = new Mail::Send; my ($username,$to) = split(/:/,$user); $username = &unescape($username); $to = &unescape($to); $msg->to($to); $msg->subject($subject); $msg->add('From',"$from"); $msg->add('Content-type','text/plain; charset=UTF-8'); if (my $fh = $msg->open()) { print $fh $message; $fh->close; push(@{$deliveries},$user); } } } sub get_user_info { my ($user,%email_defaults) = @_; my ($uname,$udom) = split(/:/,$user); my @emailtypes = ('permanentemail','critnotification','notification'); my %userinfo = &Apache::loncommon::getemails($uname,$udom); my $email = ''; foreach my $type (@emailtypes) { $email = $userinfo{$type}; if ($email =~ /\@/) { last; } } if ($email eq '') { my $authinfo = &Apache::lonnet::queryauthenticate($uname,$udom); my ($authtype,$autharg) = split(/:/,$authinfo); if ($authtype =~ /^krb/) { if (defined($email_defaults{$authtype}{$autharg})) { $email = $uname.'@'.$email_defaults{$authtype}{$autharg}; } } else { if ((defined($email_defaults{$authtype})) && ($email_defaults{$authtype} ne '')) { $email = $uname.'@'.$email_defaults{$authtype}; } } } return $email; } sub form_elements { my ($longtypes,$authtypes) = @_; %{$longtypes} = ( active => &mt('Currently has access'), previous => &mt('Previously had access'), future => &mt('Will have future access'), ); %{$authtypes} = ( krb4 => 'Kerberos 4', krb5 => 'Kerberos 5', internal => 'Internal (LON-CAPA)', unix => 'Filesystem (UNIX)', localauth => 'Local/Customized', ); return; } sub store_mail { my ($subject,$message,$domain,$recipients,$attachmenturl) = @_; my $msgid; ($msgid,$message) = &Apache::lonmsg::packagemsg($subject,$message,undef,undef, $attachmenturl,$recipients,undef,undef,'dcmail'); # Store in dc email db files on primary library server for domain. my $server = &Apache::lonnet::domain($domain,'primary'); if (defined($server)) { unless (&Apache::lonnet::dcmailput($domain,$msgid,$message,$server) eq 'ok') { &Apache::lonnet::logthis('Storage of dc mail failed for domain'. $domain.' for server: '. $server.'. Message ID was '.$msgid); } } else { &Apache::lonnet::logthis('Storage of dc mail failed for domain'. $domain.' as no primary server identified. Message ID was '.$msgid); } } sub cr_to_br { my $incoming = shift; $incoming =~ s/\n/\
    /g; return $incoming; } 1;