use strict;
use base qw( FS::cust_main_Mixin FS::Record );
use FS::Record qw( qsearch qsearchs );
+use MIME::Parser;
use vars qw( @statuses );
=head1 NAME
$self->SUPER::check;
}
+=item entity
+
+Returns the complete message as a L<MIME::Entity>.
+
+=item parts
+
+Returns a list of the MIME parts contained in the message, as L<MIME::Entity>
+objects.
+
+=cut
+
+sub entity {
+ my $self = shift;
+ if ( !exists($self->{entity}) ) {
+ my $parser = MIME::Parser->new;
+ my $output_dir = "$FS::UID::cache_dir/cache.$FS::UID::datasrc/mimeparts";
+ mkdir($output_dir) unless -d $output_dir;
+ $parser->output_under($output_dir);
+ $self->{entity} =
+ $parser->parse_data( $self->header . "\n" . $self->body );
+ }
+ $self->{entity};
+}
+
+sub parts {
+ my $self = shift;
+ # return only the parts with bodies, not the multipart containers
+ grep { $_->bodyhandle } $self->entity->parts_DFS;
+}
+
=back
=head1 SEE ALSO
<& 'elements/search.html',
'title' => $title,
- 'name' => 'messages',
+ 'name_singular' => 'message',
'query' => $query,
'count_query' => $count_query,
'header' => [
'status',
sub { encode_entities($_[0]->error) },
],
+ 'sort_fields' => [ '_date',
+ 'msgtype',
+ 'env_to',
+ 'status',
+ 'error',
+ ],
'align' => 'rllcl',
'links' => [ ],
'link_onclicks' => [
],
'html_init' => $html_init,
'really_disable_download' => 1,
+ @_
&>
<%init>
#hmm...
if ( $cgi->param('msgtype') =~ /^(\w+)$/ ) {
push @where, "msgtype = '$1'";
}
+if ( $cgi->param('custnum') =~ /^(\d+)$/ ) {
+ push @where, "custnum = $1";
+}
my ($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi, '');
push @where, "(_date >= $beginning AND _date <= $ending)";
% if ( $view eq 'notes' || $view eq 'jumbo' ) {
-%if ( $cust_main->comments =~ /[^\s\n\r]/ ) {
-<BR><% mt('Comments') |h %>
-<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
-<TR>
- <TD BGCOLOR="#ffffff">
- <PRE><% encode_entities($cust_main->comments) %></PRE>
- </TD>
-</TR>
-</TABLE></TABLE>
-<BR><BR>
-% }
-<A NAME="notes">
-% my $notecount = scalar($cust_main->notes(0));
-% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) {
-
-% unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) {
- <BR>
- <A NAME="cust_main_note"><FONT SIZE="+2"><% mt('Notes') |h %></FONT></A><BR>
-% }
-
-% if ( $curuser->access_right('Add customer note') &&
-% ! $conf->exists('cust_main-disable_notes')
-% ) {
-
- <& /elements/popup_link-cust_main.html,
- 'label' => emt('Add customer note'),
- 'action' => $p. 'edit/cust_main_note.cgi',
- 'actionlabel' => emt('Enter customer note'),
- 'cust_main' => $cust_main,
- 'width' => 616,
- 'height' => 538, #575
- &>
-
-% }
-
-<BR>
-
-<& cust_main/notes.html, 'custnum' => $cust_main->custnum &>
-
-% }
-<BR>
-
-% if(! $conf->config('disable_cust_attachment')
-% and $curuser->access_right('Add attachment')) {
-<& /elements/popup_link-cust_main.html,
- 'label' => emt('Attach file'),
- 'action' => $p.'edit/cust_main_attach.cgi',
- 'actionlabel' => emt('Upload file'),
- 'cust_main' => $cust_main,
- 'width' => 480,
- 'height' => 296,
-&>
-% }
-% if( $curuser->access_right('View attachments') ) {
-<& cust_main/attachments.html, 'custnum' => $cust_main->custnum &>
-% if ($cgi->param('show_deleted')) {
-<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
- ($view ? ";show=$view" : '') . '#notes'
- %>"><I>(<% mt('Show active attachments') |h %>)</I></A>
-% }
-% elsif($curuser->access_right('View deleted attachments')) {
-<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
- ($view ? ";show=$view" : '') . ';show_deleted=1#notes'
- %>"><I>(<% mt('Show deleted attachments') |h %>)</I></A>
-% }
-% }
-<BR>
+<& cust_main/notes.html, 'cust_main' => $cust_main &>
% }
% if ( $view eq 'jumbo' ) {
<BR>
% }
+
<BR>
% if ( $view eq 'tickets' || $view eq 'jumbo' ) {
my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array
$query =~ /^(\d+)$/;
$custnum = $1;
+ $cgi->param('custnum', $1);
}
my $cust_main = qsearchs( {
+++ /dev/null
-% if ( scalar(@attachments) ) {
-
- <& /elements/init_overlib.html &>
-
- <& /elements/table-grid.html &>
-
- <TR>
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH>
-% if ( $conf->exists('cust_main_note-display_times') ) {
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Time') |h %></TH>
-% }
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Person') |h %></TH>
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Filename') |h %></TH>
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Description') |h %></TH>
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Type') |h %></TH>
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Size') |h %></TH>
- <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
- </TR>
-
-% my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor = '';
-% if($cgi->param('show_deleted')) {
-% if ($curuser->access_right('View deleted attachments')) {
-% @attachments = grep { $_->disabled } @attachments;
-% }
-% else {
-% @attachments = ();
-% }
-% }
-% else {
-% @attachments = grep { not $_->disabled } @attachments;
-% }
-%
-% foreach my $attach (@attachments) {
-%
-% if ( $bgcolor eq $bgcolor1 ) {
-% $bgcolor = $bgcolor2;
-% } else {
-% $bgcolor = $bgcolor1;
-% }
-%
-% my $pop = popurl(3);
-% my $attachnum = $attach->attachnum;
-% my $edit = '';
-% if($attach->disabled) { # then you can undelete it or purge it.
-% if ($curuser->access_right('Undelete attachment')) {
-% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
-% "custnum=$custnum;attachnum=$attachnum;".
-% "undelete=1",
-% emt('Undelete attachment'));
-% $edit .= linkstr($clickjs, emt('undelete'));
-% }
-% if ($curuser->access_right('Purge attachment')) {
-% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
-% "custnum=$custnum;attachnum=$attachnum;".
-% "purge=1",
-% emt('Purge attachment'),
-% emt('Permanently remove this file?') );
-% $edit .= linkstr($clickjs,emt('purge'));
-% }
-% }
-% else { # you can download or edit it
-% if ($curuser->access_right('Edit attachment') ) {
-% my $clickjs = popup('edit/cust_main_attach.cgi?'.
-% "custnum=$custnum;attachnum=$attachnum",
-% emt('Edit attachment properties'));
-% $edit .= linkstr($clickjs,emt('edit'));
-% }
-% if($curuser->access_right('Delete attachment') ) {
-% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
-% "custnum=$custnum;attachnum=$attachnum;delete=1",
-% 'Delete attachment',
-% 'Delete this file?');
-% $edit .= linkstr($clickjs,emt('delete'));
-% }
-% if ($curuser->access_right('Download attachment') ) {
-% $edit .= qq! <A HREF="!.popurl(1).'attachment.html?'.$attachnum.qq!">(!
-% . emt('download') .')</A>';
-% }
-% }
-
- <TR>
- <% note_datestr($attach,$conf,$bgcolor) %>
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $attach->usernum ? $attach->access_user->name : $attach->otaker %>
- </TD>
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $attach->filename |h %>
- </TD>
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $attach->title |h %>
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $attach->mime_type |h %>
- </TD>
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% size_units( $attach->size ) %>
- </TD>
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $edit %>
- </TD>
- </TR>
-
-% } #end display notes
-
-</TABLE>
-
-% }
-<%init>
-
-my $conf = new FS::Conf;
-my $curuser = $FS::CurrentUser::CurrentUser;
-die "access denied" if !$curuser->access_right('View attachments');
-my(%opt) = @_;
-
-my $custnum = $opt{'custnum'};
-
-my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} );
-die "Customer not found!" unless $cust_main;
-
-my (@attachments) = qsearch('cust_attachment', {'custnum' => $custnum});
-
-#subroutines
-
-sub note_datestr {
- my($note, $conf, $bgcolor) = @_ or return '';
- my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">};
- my $format = "$td%b %o, %Y</TD>";
- $format .= "$td%l:%M%P</TD>"
- if $conf->exists('cust_main_note-display_times');
- ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g;
- $strip;
-}
-
-sub linkstr {
- my ($clickjs, $label) = (shift,shift);
- ' <A HREF="javascript:void(0);" '. $clickjs . '>(' . emt($label) . ')</A>';
-}
-
-sub size_units {
- my $bytes = shift;
- return $bytes if $bytes < 1024;
- return int($bytes / 1024)."K" if $bytes < 1048576;
- return int($bytes / 1048576)."M";
-}
-
-sub popup {
- my ($url, $label, $confirm) = @_;
- my $onclick =
- include('/elements/popup_link_onclick.html',
- 'action' => popurl(2).$url,
- 'actionlabel' => $label,
- 'width' => 510,
- 'height' => 315,
- 'frame' => 'top',
- );
- $onclick = qq!if(confirm('$confirm')) { $onclick }! if $confirm;
- return qq!onclick="$onclick"!;
-}
-
-
-</%init>
-% if ( scalar(@notes) ) {
-
-<SCRIPT TYPE="text/javascript">
-
- function display_notes_classnum(classnum){
- document.getElementById('notes_'+classnum).style.display = 'block';
- document.getElementById('notes_tablink_'+classnum).style.fontWeight = 'bold';
-
- var divs = document.getElementsByTagName("div");
- var i;
- for(i=0; i < divs.length; i++){
- var d = divs[i];
- if(d.id.length > 6 && d.id.substring(0,6) == 'notes_') {
- if(divs[i].id != 'notes_'+classnum) {
- divs[i].style.display = 'none';
- }
- }
- }
-
- var as = document.getElementsByTagName("a");
- for(i=0; i < as.length; i++){
- var a = as[i];
- if(a.id.length > 14 && a.id.substring(0,14) == 'notes_tablink_') {
- if(as[i].id != 'notes_tablink_'+classnum) {
- as[i].style.fontWeight = 'normal';
- }
- }
- }
- }
-
-</SCRIPT>
-
- <& /elements/init_overlib.html &>
-
-% my $bgcolor1 = '#eeeeee';
-% my $bgcolor2 = '#ffffff';
-% my $bgcolor = '';
-% my $last_classnum = -1;
-% my $skipheader = 0;
-% my %classes = ();
-%
-% foreach my $note (@notes) {
-%
-% if ( $bgcolor eq $bgcolor1 ) {
-% $bgcolor = $bgcolor2;
-% } else {
-% $bgcolor = $bgcolor1;
-% }
-%
-% my $pop = popurl(3);
-% my $notenum = $note->notenum;
-% my $onclick = include( '/elements/popup_link_onclick.html',
-% 'action' => popurl(2).
-% 'edit/cust_main_note.cgi'.
-% "?custnum=$custnum".
-% ";notenum=$notenum",
-% 'actionlabel' => emt('Edit customer note'),
-% 'width' => 616,
-% 'height' => 538, #575
-% 'frame' => 'top',
-% );
-% my $clickjs = qq!onclick="$onclick"!;
-%
-% my $edit = '';
-% if ($curuser->access_right('Edit customer note') ) {
-% my $delete_url = $fsurl.'misc/delete-note.html?'.$notenum;
-% $edit = qq! <A HREF="javascript:void(0);" $clickjs>(!.emt('edit').')</A>'.
-% qq! <A HREF="$delete_url" !.
-% qq! onclick="return confirm('Delete this note?')">!.
-% '('.emt('delete').')</A>';
-% }
-%
-% if ( $last_classnum != $note->classnum && !$skipheader ) {
-% my $tmp_classnum = $note->classnum ? $note->classnum : 0;
-% $classes{$tmp_classnum} = $note->classname ne '' ? $note->classname
-% : emt('Other');
-% if ( $last_classnum != -1 ) {
- </TABLE>
- </DIV>
+% # Customer comments
+% if ( $cust_main->comments =~ /[^\s\n\r]/ ) {
+<BR><% mt('Comments') |h %>
+<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
+<TR>
+ <TD BGCOLOR="#ffffff">
+ <PRE><% encode_entities($cust_main->comments) %></PRE>
+ </TD>
+</TR>
+</TABLE></TABLE>
+<BR><BR>
% }
-% my $display = ($tmp_classnum == 0 || !$conf->exists('note-classes')
-% || $conf->config('note-classes') < 2)
-% ? 'block' : 'none';
- <DIV id="notes_<% $tmp_classnum %>"
- style="display:<% $display %>"
- >
- <& /elements/table-grid.html &>
- <TR>
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH>
-% if ( $conf->exists('cust_main_note-display_times') ) {
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Time') |h %></TH>
-% }
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Person') |h %></TH>
-% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) {
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Class') |h %></TH>
+
+% # Notes, if any
+<A NAME="notes">
+% my $notecount = scalar($cust_main->notes(0));
+% if ( ! $conf->exists('cust_main-disable_notes') || $notecount) {
+
+% unless ( $view eq 'notes' && $cust_main->comments !~ /[^\s\n\r]/ ) {
+<P>
+ <A NAME="cust_main_note"><FONT SIZE="+2"><% mt('Notes') |h %></FONT></A>
+</P>
+
% }
- <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Note') |h %></TH>
-% if ($curuser->access_right('Edit customer note') ) {
- <TH CLASS="grid" BGCOLOR="#cccccc"> </TH>
+
+% if ( $curuser->access_right('Add customer note') &&
+% ! $conf->exists('cust_main-disable_notes')
+% ) {
+
+ <& /elements/popup_link-cust_main.html,
+ 'label' => emt('Add customer note'),
+ 'action' => $p. 'edit/cust_main_note.cgi',
+ 'actionlabel' => emt('Enter customer note'),
+ 'cust_main' => $cust_main,
+ 'width' => 616,
+ 'height' => 538, #575
+ &>
+
% }
- </TR>
-% $skipheader = (!$conf->exists('note-classes') || $conf->config('note-classes') < 2);
-% $last_classnum = $note->classnum;
+<BR>
+
+% # actually display notes
+<& notes/notes.html, 'cust_main' => $cust_main &>
+<BR>
+% } # end of notes
+
+% # Attachments
+% # XXX at some point move all of this into notes/attachments.html
+% if( $curuser->access_right('View attachments') ) {
+% # List attachments
+<& notes/attachments.html, 'cust_main' => $cust_main &>
+% # "Attach file" link
+% if(! $conf->config('disable_cust_attachment')
+% and $curuser->access_right('Add attachment')) {
+<& /elements/popup_link-cust_main.html,
+ 'label' => emt('Attach file'),
+ 'action' => $p.'edit/cust_main_attach.cgi',
+ 'actionlabel' => emt('Upload file'),
+ 'cust_main' => $cust_main,
+ 'width' => 480,
+ 'height' => 296,
+&>
% }
- <TR>
- <% note_datestr($note,$conf,$bgcolor) %>
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $note->usernum ? $note->access_user->name : $note->otaker %>
- </TD>
-% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) {
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $note->classname %>
- </TD>
-% }
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
- <% $note->comments | defang %>
- </TD>
-% if($edit) {
- <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $edit %></TD>
-% }
- </TR>
-
-% } #end display notes
-
-</TABLE>
-</DIV>
-
-% if ( $conf->exists('note-classes') && $conf->config('note-classes') == 2 ) {
-% my($classnum,$classname);
-<% mt('Show notes of class:') |h %>
-% foreach my $classnum ( sort { $b <=> $a } (keys %classes) ) {
- <A id="notes_tablink_<% $classnum %>"
- HREF="javascript:display_notes_classnum(<% $classnum %>)"
- style="font-weight: <% $classnum == 0 ? 'bold' : 'normal' %>"
- ><% $classes{$classnum} %></A>
-% }
- <BR>
+% if ($cgi->param('show_deleted')) {
+<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
+ ($view ? ";show=$view" : '') . '#notes'
+ %>"><I>(<% mt('Show active attachments') |h %>)</I></A>
+% } elsif($curuser->access_right('View deleted attachments')) {
+<A HREF="<% $p.'view/cust_main.cgi?custnum=' . $cust_main->custnum .
+ ($view ? ";show=$view" : '') . ';show_deleted=1#notes'
+ %>"><I>(<% mt('Show deleted attachments') |h %>)</I></A>
+% }
% }
+<BR>
+% if ( $curuser->access_right('View email logs')
+% and FS::cust_msg->count("custnum = $custnum")) {
+<BR>
+% if (!$cgi->param('order_by')) {
+% my $order_by = '_date';
+% $order_by .= ' DESC' if $curuser->option('history_order') eq 'newest';
+% $cgi->param('order_by', $order_by);
+% }
+<& /search/cust_msg.html,
+ nohtmlheader => 1,
+ html_init => mt('Mail sent to this customer: '),
+&>
% }
<%init>
my(%opt) = @_;
-my $custnum = $opt{'custnum'};
-
-my $cust_main = qsearchs('cust_main', {'custnum' => $custnum} );
-die "Customer not found!" unless $cust_main;
-
-my (@notes) = $cust_main->notes($conf->exists('note-classes') && $conf->config('note-classes') == 2);
-
-#subroutines
+my $cust_main = $opt{'cust_main'};
+my $custnum = $cust_main->custnum;
-sub note_datestr {
- my($note, $conf, $bgcolor) = @_ or return '';
- my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">};
- my $format = "$td%b %o, %Y</TD>";
- $format .= "$td%l:%M%P</TD>"
- if $conf->exists('cust_main_note-display_times');
- ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g;
- $strip;
-}
+my $view = $cgi->param('show') || $curuser->default_customer_view;
</%init>
--- /dev/null
+% if ( scalar(@attachments) ) {
+
+ <& /elements/init_overlib.html &>
+
+ <& /elements/table-grid.html &>
+
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH>
+% if ( $conf->exists('cust_main_note-display_times') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Time') |h %></TH>
+% }
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Person') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Filename') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Description') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Type') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Size') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"></TH>
+ </TR>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+% if($cgi->param('show_deleted')) {
+% if ($curuser->access_right('View deleted attachments')) {
+% @attachments = grep { $_->disabled } @attachments;
+% }
+% else {
+% @attachments = ();
+% }
+% }
+% else {
+% @attachments = grep { not $_->disabled } @attachments;
+% }
+%
+% foreach my $attach (@attachments) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $pop = popurl(3);
+% my $attachnum = $attach->attachnum;
+% my $edit = '';
+% if($attach->disabled) { # then you can undelete it or purge it.
+% if ($curuser->access_right('Undelete attachment')) {
+% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum;".
+% "undelete=1",
+% emt('Undelete attachment'));
+% $edit .= linkstr($clickjs, emt('undelete'));
+% }
+% if ($curuser->access_right('Purge attachment')) {
+% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum;".
+% "purge=1",
+% emt('Purge attachment'),
+% emt('Permanently remove this file?') );
+% $edit .= linkstr($clickjs,emt('purge'));
+% }
+% }
+% else { # you can download or edit it
+% if ($curuser->access_right('Edit attachment') ) {
+% my $clickjs = popup('edit/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum",
+% emt('Edit attachment properties'));
+% $edit .= linkstr($clickjs,emt('edit'));
+% }
+% if($curuser->access_right('Delete attachment') ) {
+% my $clickjs = popup('edit/process/cust_main_attach.cgi?'.
+% "custnum=$custnum;attachnum=$attachnum;delete=1",
+% 'Delete attachment',
+% 'Delete this file?');
+% $edit .= linkstr($clickjs,emt('delete'));
+% }
+% if ($curuser->access_right('Download attachment') ) {
+% $edit .= qq! <A HREF="!.popurl(1).'attachment.html?'.$attachnum.qq!">(!
+% . emt('download') .')</A>';
+% }
+% }
+
+ <TR>
+ <% note_datestr($attach,$conf,$bgcolor) %>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $attach->usernum ? $attach->access_user->name : $attach->otaker %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $attach->filename |h %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $attach->title |h %>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $attach->mime_type |h %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% size_units( $attach->size ) %>
+ </TD>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $edit %>
+ </TD>
+ </TR>
+
+% } #end display notes
+
+</TABLE>
+
+% }
+<%init>
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+die "access denied" if !$curuser->access_right('View attachments');
+my(%opt) = @_;
+
+my $cust_main = $opt{'cust_main'};
+my $custnum = $cust_main->custnum;
+
+my (@attachments) = qsearch('cust_attachment', {'custnum' => $custnum});
+
+#subroutines
+
+sub note_datestr {
+ my($note, $conf, $bgcolor) = @_ or return '';
+ my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">};
+ my $format = "$td%b %o, %Y</TD>";
+ $format .= "$td%l:%M%P</TD>"
+ if $conf->exists('cust_main_note-display_times');
+ ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g;
+ $strip;
+}
+
+sub linkstr {
+ my ($clickjs, $label) = (shift,shift);
+ ' <A HREF="javascript:void(0);" '. $clickjs . '>(' . emt($label) . ')</A>';
+}
+
+sub size_units {
+ my $bytes = shift;
+ return $bytes if $bytes < 1024;
+ return int($bytes / 1024)."K" if $bytes < 1048576;
+ return int($bytes / 1048576)."M";
+}
+
+sub popup {
+ my ($url, $label, $confirm) = @_;
+ my $onclick =
+ include('/elements/popup_link_onclick.html',
+ 'action' => popurl(2).$url,
+ 'actionlabel' => $label,
+ 'width' => 510,
+ 'height' => 315,
+ 'frame' => 'top',
+ );
+ $onclick = qq!if(confirm('$confirm')) { $onclick }! if $confirm;
+ return qq!onclick="$onclick"!;
+}
+
+
+</%init>
--- /dev/null
+% if ( scalar(@notes) ) {
+
+<SCRIPT TYPE="text/javascript">
+
+ function display_notes_classnum(classnum){
+ document.getElementById('notes_'+classnum).style.display = 'block';
+ document.getElementById('notes_tablink_'+classnum).style.fontWeight = 'bold';
+
+ var divs = document.getElementsByTagName("div");
+ var i;
+ for(i=0; i < divs.length; i++){
+ var d = divs[i];
+ if(d.id.length > 6 && d.id.substring(0,6) == 'notes_') {
+ if(divs[i].id != 'notes_'+classnum) {
+ divs[i].style.display = 'none';
+ }
+ }
+ }
+
+ var as = document.getElementsByTagName("a");
+ for(i=0; i < as.length; i++){
+ var a = as[i];
+ if(a.id.length > 14 && a.id.substring(0,14) == 'notes_tablink_') {
+ if(as[i].id != 'notes_tablink_'+classnum) {
+ as[i].style.fontWeight = 'normal';
+ }
+ }
+ }
+ }
+
+</SCRIPT>
+
+ <& /elements/init_overlib.html &>
+
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+% my $last_classnum = -1;
+% my $skipheader = 0;
+% my %classes = ();
+%
+% foreach my $note (@notes) {
+%
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+%
+% my $pop = popurl(3);
+% my $notenum = $note->notenum;
+% my $onclick = include( '/elements/popup_link_onclick.html',
+% 'action' => popurl(2).
+% 'edit/cust_main_note.cgi'.
+% "?custnum=$custnum".
+% ";notenum=$notenum",
+% 'actionlabel' => emt('Edit customer note'),
+% 'width' => 616,
+% 'height' => 538, #575
+% 'frame' => 'top',
+% );
+% my $clickjs = qq!onclick="$onclick"!;
+%
+% my $edit = '';
+% if ($curuser->access_right('Edit customer note') ) {
+% my $delete_url = $fsurl.'misc/delete-note.html?'.$notenum;
+% $edit = qq! <A HREF="javascript:void(0);" $clickjs>(!.emt('edit').')</A>'.
+% qq! <A HREF="$delete_url" !.
+% qq! onclick="return confirm('Delete this note?')">!.
+% '('.emt('delete').')</A>';
+% }
+%
+% if ( $last_classnum != $note->classnum && !$skipheader ) {
+% my $tmp_classnum = $note->classnum ? $note->classnum : 0;
+% $classes{$tmp_classnum} = $note->classname ne '' ? $note->classname
+% : emt('Other');
+% if ( $last_classnum != -1 ) {
+ </TABLE>
+ </DIV>
+% }
+% my $display = ($tmp_classnum == 0 || !$conf->exists('note-classes')
+% || $conf->config('note-classes') < 2)
+% ? 'block' : 'none';
+ <DIV id="notes_<% $tmp_classnum %>"
+ style="display:<% $display %>"
+ >
+ <& /elements/table-grid.html &>
+ <TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Date') |h %></TH>
+% if ( $conf->exists('cust_main_note-display_times') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Time') |h %></TH>
+% }
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Person') |h %></TH>
+% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) {
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Class') |h %></TH>
+% }
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Note') |h %></TH>
+% if ($curuser->access_right('Edit customer note') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc"> </TH>
+% }
+ </TR>
+% $skipheader = (!$conf->exists('note-classes') || $conf->config('note-classes') < 2);
+% $last_classnum = $note->classnum;
+% }
+
+ <TR>
+ <% note_datestr($note,$conf,$bgcolor) %>
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $note->usernum ? $note->access_user->name : $note->otaker %>
+ </TD>
+% if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $note->classname %>
+ </TD>
+% }
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $note->comments | defang %>
+ </TD>
+% if($edit) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $edit %></TD>
+% }
+ </TR>
+
+% } #end display notes
+
+</TABLE>
+</DIV>
+
+% if ( $conf->exists('note-classes') && $conf->config('note-classes') == 2 ) {
+% my($classnum,$classname);
+<% mt('Show notes of class:') |h %>
+% foreach my $classnum ( sort { $b <=> $a } (keys %classes) ) {
+ <A id="notes_tablink_<% $classnum %>"
+ HREF="javascript:display_notes_classnum(<% $classnum %>)"
+ style="font-weight: <% $classnum == 0 ? 'bold' : 'normal' %>"
+ ><% $classes{$classnum} %></A>
+% }
+ <BR>
+% }
+
+% }
+<%init>
+
+use HTML::Defang;
+
+my $conf = new FS::Conf;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my(%opt) = @_;
+
+my $cust_main = $opt{'cust_main'};
+my $custnum = $cust_main->custnum;
+
+my (@notes) = $cust_main->notes($conf->exists('note-classes') && $conf->config('note-classes') == 2);
+
+#subroutines
+
+sub note_datestr {
+ my($note, $conf, $bgcolor) = @_ or return '';
+ my $td = qq{<TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">};
+ my $format = "$td%b %o, %Y</TD>";
+ $format .= "$td%l:%M%P</TD>"
+ if $conf->exists('cust_main_note-display_times');
+ ( my $strip = time2str($format, $note->_date) ) =~ s/ (\d)/$1/g;
+ $strip;
+}
+
+</%init>
<& /elements/header-popup.html &>
+<STYLE>
+P.pre {
+ font-family: monospace;
+ height: auto;
+ width: auto;
+ display: block;
+ white-space: pre-wrap;
+ text-align: left;
+ border: 1px solid #7e0079
+}
+</STYLE>
+
<TABLE>
<TR><TD>From:</TD><TD><% $cust_msg->env_from %></TD></TR>
<TR><TD>To:</TD><TD><% $env_to %></TD></TR>
% if ( $cust_msg->error ) {
<TR><TD>Error:</TD><TD><% encode_entities($cust_msg->error) %></TD></TR>
% }
-<TR><TD colspan=2>
-<FORM name="myform">
-<SCRIPT type="text/javascript">
-function toggle_display(obj) {
- document.getElementById('content-header').style.display =
- (obj.value == 'header' ? 'block' : 'none');
- document.getElementById('content-body').style.display =
- (obj.value == 'body' ? 'block' : 'none');
-}
-</SCRIPT>
-<INPUT type="radio" name="what_to_show" onchange="toggle_display(this)" value="header" checked> Header
-<INPUT type="radio" name="what_to_show" onchange="toggle_display(this)" value="body"> Body
-</FORM>
-</TR>
-<TR><TD colspan=2 style="text-align:left">
-<TEXTAREA id="content-header" style="font-family:monospace"
-readonly=1 cols=80 rows=20>
-<% encode_entities($cust_msg->header) %>
-</TEXTAREA>
-<TEXTAREA id="content-body" style="font-family:monospace;display:none"
-readonly=1 cols=80 rows=20>
-<% encode_entities($cust_msg->body) %>
-</TEXTAREA>
-</TD></TR>
+<& /elements/menubar.html,
+ { 'newstyle' => 1,
+ 'url_base' => $cgi->self_url . ';part=',
+ 'selected' => $selected_index,
+ },
+ map { $partnames[$_] => $_ } (0 .. scalar(@parts) - 1),
+&>
</TABLE>
+<DIV STYLE="text-align:center">
+% if ( $selected_part->isa('MIME::Entity') ) {
+% my $type = $selected_part->mime_type;
+% if ( $type =~ /^text/ ) {
+%#<TEXTAREA style="font-family:monospace" readonly=1 cols=80 rows=20>
+ <P CLASS="pre"><% encode_entities( $selected_part->bodyhandle->as_string ) %></P>
+% } else { # show a download link
+% my $url = $fsurl . "view/cust_msg_part.html?$custmsgnum+$selected_index";
+ <A HREF="<% $url %>">
+ <DIV STYLE="display: inline-block; padding: 4px; border: 2px solid #00c">
+% if ( $type =~ /^image\/\w+$/ ) {
+ <IMG SRC="<% $url %>">
+% } else {
+ <FONT SIZE="+1">Download <% $partnames[$selected_index] %></FONT>
+% }
+ </A>
+% }
+% } elsif ($selected_part->isa('MIME::Head')) {
+ <P CLASS="pre"><% encode_entities( $cust_msg->header ) %></P>
+% }
+</DIV>
<& /elements/footer.html &>
<%init>
'failed' => 'Attempted: ',
'prepared' => 'Not sent',
);
+
+my $partname = sub {
+ my %friendly_name = ( 'text/plain' => 'Text', 'text/html' => 'HTML' );
+ my $part = shift;
+ $part->head->recommended_filename
+ || $friendly_name{$part->mime_type}
+ || $part->mime_type;
+};
+
+my @parts = $cust_msg->parts;
+my @partnames = map { &{$partname}($_) } @parts;
+push @parts, $cust_msg->entity->head;
+push @partnames, mt('Header');
+
+my $selected_part;
+my $selected_index = 0;
+if ( $cgi->param('part') =~ /^(\d+)$/ ) {
+ $selected_index = $1 if $1 < scalar(@parts);
+}
+$selected_part = $parts[$selected_index];
+$cgi->delete('part'); # for self_url
+
</%init>
--- /dev/null
+<%init>
+die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('View email logs');
+# invoke this as "view/cust_msg_part.html?$custmsgnum+$partnum"
+my ($custmsgnum, $partnum) = $cgi->keywords;
+$custmsgnum =~ /^\d+$/ or die "bad custmsgnum";
+$partnum =~ /^\d+$/ or die "bad partnum";
+my $cust_msg = FS::cust_msg->by_key($custmsgnum)
+ or die "message not found";
+my $part = ($cust_msg->parts)[$partnum]
+ or die "message part $partnum does not exist";
+
+my $filename = $part->head->recommended_filename;
+if (!$filename) {
+ # for lack of a better idea
+ $part->bodyhandle->{MB_Path} =~ /.*\/(.*)/;
+ $filename = $1;
+}
+
+$m->clear_buffer;
+$r->content_type($part->mime_type || 'application/octet-stream');
+$r->headers_out->add('Content-Disposition' => 'attachment;filename=' . $filename);
+$m->print($part->bodyhandle->as_string);
+</%init>