diff options
-rw-r--r-- | lib/JWebmail/Plugin/Helper.pm | 53 | ||||
-rw-r--r-- | public/style.css | 10 | ||||
-rw-r--r-- | templates/webmail/readmail.html.ep | 114 |
3 files changed, 113 insertions, 64 deletions
diff --git a/lib/JWebmail/Plugin/Helper.pm b/lib/JWebmail/Plugin/Helper.pm index ed2c31b..a98f245 100644 --- a/lib/JWebmail/Plugin/Helper.pm +++ b/lib/JWebmail/Plugin/Helper.pm @@ -2,7 +2,7 @@ package JWebmail::Plugin::Helper; use Mojo::Base Mojolicious::Plugin; -use List::Util qw(all min max); +use List::Util qw(all any min max); use Carp 'carp'; use POSIX qw(floor round log ceil); @@ -36,13 +36,13 @@ sub mail_line { /xn; } - sub filter_empty_upload { my ($v, $name, $value) = @_; return $value->filename ? $value : undef; } + ### template formatting functions sub print_sizes10 { @@ -62,7 +62,6 @@ sub print_sizes10 { return sprintf('%.0f %s', $var / (10**$expo), $PREFIX[$i]); } - sub print_sizes2 { my $var = shift || return '0 Byte'; @@ -80,7 +79,6 @@ sub print_sizes2 { return round($var / (2**$expo)) . " $pref"; } - my sub dgt { "([[:digit:]]{$_[0]})" } sub parse_iso_date { @@ -100,6 +98,14 @@ sub parse_iso_date { }; } +sub to_mime_type { + my $c = shift; + my ($mime_head) = @_; + + return "$mime_head->{content_maintype}/$mime_head->{content_subtype}"; +} + + ### mime type html render functions my $render_text_plain = sub { @@ -111,29 +117,27 @@ my $render_text_plain = sub { return $content; }; - my $render_text_html = sub { my $c_ = shift; return '<iframe src="' . $c_->url_for('read', id => $c_->stash('id'))->query(body => 'html') . '" class=html-mail></iframe>'; }; - our %MIME_Render_Subs = ( 'text/plain' => $render_text_plain, 'text/html' => $render_text_html, ); - sub mime_render { my ($c, $enc, $cont) = @_; ($enc) = $enc =~ m<^(\w+/\w+);?>; - my $renderer = $MIME_Render_Subs{$enc} // return ''; + my $renderer = $MIME_Render_Subs{$enc} // return; return $renderer->($c, $cont); }; + ### session password handling use constant { S_PASSWD => 'pw', S_OTP_S3D_PW => 'otp_s3d_pw' }; @@ -212,6 +216,7 @@ sub warn_crypt { } } + ### pagination sub _clamp { @@ -268,7 +273,7 @@ sub _paginate { sub paginate { my $c = shift; - my $count = shift; + my ($count) = @_; my $v = $c->validation; my $start = $v->optional('start')->num(0, undef)->param // 0; @@ -286,6 +291,7 @@ sub paginate { return $start, $end; } + ### registering sub register { @@ -293,29 +299,32 @@ sub register { $conf //= {}; if (ref $conf->{import} eq 'ARRAY' and my @import = @{ $conf->{import} }) { - no warnings 'experimental::smartmatch'; + my sub contains { any { $_[0] eq $_ } @import } # selective import - $app->helper(print_sizes10 => sub { shift; print_sizes10(@_) }) - if 'print_sizes10' ~~ @import; + $app->helper(print_sizes10 => sub { shift; print_sizes10(@_) }) + if contains 'print_sizes10'; $app->helper(parse_iso_date => sub { shift; parse_iso_date(@_) }) - if 'parse_iso_date' ~~ @import; - $app->helper(print_sizes2 => sub { shift; print_sizes2(@_) }) - if 'print_sizes2' ~~ @import; - $app->helper(mime_render => \&mime_render) - if 'mime_render' ~~ @import; + if contains 'parse_iso_date'; + $app->helper(print_sizes2 => sub { shift; print_sizes2(@_) }) + if contains 'print_sizes2'; + $app->helper(to_mime_type => \&to_mime_type) + if contains 'to_mime_type'; + $app->helper(mime_render => \&mime_render) + if contains 'mime_render'; $app->helper(session_passwd => \&session_passwd) - if 'session_passwd' ~~ @import; + if contains 'session_passwd'; $app->helper(paginate => \&paginate) - if 'paginate' ~~ @import; + if contains 'paginate'; $app->validator->add_check(mail_line => \&mail_line) - if 'mail_line' ~~ @import; + if contains 'mail_line'; $app->validator->add_filter(non_empty_ul => \&filter_empty_upload) - if 'non_empty_ul' ~~ @import; + if contains 'non_empty_ul'; } elsif (!$conf->{import}) { # default imports $app->helper(print_sizes10 => sub { shift; print_sizes10(@_) }); $app->helper(parse_iso_date => sub { shift; parse_iso_date(@_) }); + $app->helper(to_mime_type => \&to_mime_type); $app->helper(mime_render => \&mime_render); $app->helper(session_passwd => \&session_passwd); $app->helper(paginate => \&paginate); @@ -469,5 +478,3 @@ L<JWebmail>, L<JWebmail::Controller::All>, L<Mojolicious>, L<Mojolicious::Contro =head1 NOTICE This package is part of JWebmail. - -=cut diff --git a/public/style.css b/public/style.css index 81841e2..16bc419 100644 --- a/public/style.css +++ b/public/style.css @@ -1,6 +1,7 @@ :root { --jwm-color-back: #eee; --jwm-color-front: #ddd; + --jwm-color-alt: #dede95; } body { @@ -47,6 +48,7 @@ footer { background-color: var(--jwm-color-back); border-radius: 5px; padding: 0 1rem; + margin: 10px 0; } .jwm-mail-header { @@ -56,7 +58,8 @@ footer { .jwm-mail-body { width: 80%; - margin: 0rem auto; + margin: 1rem auto; + padding: 10px; } .jwm-mail-body > iframe.html-mail { @@ -64,6 +67,10 @@ footer { height: 400px; } +.jwm-mail-body-text-plain { + background-color: var(--jwm-color-alt); +} + /* make sure this lines up with pure-md class */ @media screen and (max-width: 48em) { .hide-small { @@ -79,6 +86,7 @@ footer { #mail-headers { width: 100%; + margin: 15px 0; } #empty-folder { diff --git a/templates/webmail/readmail.html.ep b/templates/webmail/readmail.html.ep index b5b48a1..e1f299d 100644 --- a/templates/webmail/readmail.html.ep +++ b/templates/webmail/readmail.html.ep @@ -1,68 +1,102 @@ % layout 'mainlayout'; + % my $mail_fmt = begin - % my ($category, $value) = @_; - % if (ref $value eq 'ARRAY' && $value->@*) { +% my ($category, $value) = @_; +% if (ref $value eq 'ARRAY' && $value->@*) { <dt> <%= uc l $category %> </dt> - % for ($value->@*) { +% for ($value->@*) { <dd> - %= $_->{name} ? qq("$_->{name}" <$_->{address}>) : "$_->{address}" +%= $_->{display_name} ? qq("$_->{display_name}" <$_->{address}>) : "$_->{address}" </dd> - % } - % } +% } +% } % end -<div class="jwm-base"> - - <h1>Read Mail</h1> - - <dl class="jwm-mail-header"> - <dt> <%= uc l 'subject' %> </dt> - <dd> <%= $msg->{head}{subject} %> </dd> - - %= $mail_fmt->(from => $msg->{head}{from}) - %= $mail_fmt->(to => $msg->{head}{to}) - %= $mail_fmt->(cc => $msg->{head}{cc}) - %= $mail_fmt->(bcc => $msg->{head}{bcc}) - <dt> <%= uc l 'date' %> </dt> - <dd> <%= $msg->{head}{date} %> </dd> +% my $format_mail = begin +% my ($msg) = @_; +% my $body = $msg->{body}; +% my $content_type = to_mime_type $msg->{head}{mime}; - % my $content_type = $msg->{head}{mime}{content_maintype} . '/' . $msg->{head}{mime}{content_subtype}; - <dt> <%= uc l 'content-type' %> </dt> - <dd> <%= $content_type %> </dd> - </dl> + <div clas="jwm-mail"> -% my $body = $msg->{body}; + <dl class="jwm-mail-header"> + <dt> <%= uc l 'subject' %> </dt> + <dd> <%= $msg->{head}{subject} %> </dd> +%= $mail_fmt->(from => $msg->{head}{from}) +%= $mail_fmt->(to => $msg->{head}{to}) +%= $mail_fmt->(cc => $msg->{head}{cc}) +%= $mail_fmt->(bcc => $msg->{head}{bcc}) + <dt> <%= uc l 'date' %> </dt> + <dd> <%= $msg->{head}{date} %> </dd> + <dt> <%= uc l 'content-type' %> </dt> + <dd> <%= $content_type %> </dd> + </dl> % if ($content_type eq 'multipart/alternative') { -% for (reverse @{$body->{parts}}) { - <div class=jwm-mail-body> -% my $x = mime_render($_->{head}{content_maintype}.'/'.$_->{head}{content_subtype}, $_->{body}); - %== $x; - </div> -% last if $x; +% my $end; +% for (reverse $body->{parts}->@*) { +% if (!$end) { + <div class="jwm-mail-body <%= to_mime_type($_->{head}) eq 'text/plain' ? 'jwm-mail-body-text-plain' : '' %>" > +% my $x = mime_render(to_mime_type($_->{head}), $_->{body}); +%== $x; + </div> +% $end = 1 if $x; +% } +% else { + <details class="jwm-mail-body <%= to_mime_type($_->{head}) eq 'text/plain' ? 'jwm-mail-body-text-plain' : '' %>" > + <summary> +%= to_mime_type $_->{head} + </summary> +%== mime_render(to_mime_type($_->{head}), $_->{body}) + </details> +% } % } % } % elsif ($msg->{head}{mime}{content_maintype} eq 'multipart') { -% for (@{$body->{parts}}) { - <div class=jwm-mail-body> - %== mime_render($_->{head}{content_maintype}.'/'.$_->{head}{content_subtype}, $_->{body}); - </div> +% for ($body->{parts}->@*) { +% if ( !$_->{head}{content_disposition} +% || lc $_->{head}{content_disposition} eq 'none' +% || lc $_->{head}{content_disposition} eq 'inline') { + <div class="jwm-mail-body <%= to_mime_type($_->{head}) eq 'text/plain' ? 'jwm-mail-body-text-plain' : '' %>" > +%== mime_render(to_mime_type($_->{head}), $_->{body}) // "Can not render mime-part of type <code>$_->{head}{content_maintype}/$_->{head}{content_subtype}</code>." + </div> +% } +% elsif (lc $_->{head}{content_disposition} eq 'attachment') { + <p> + Attachment <%= $_->{head}{filename} %> of type +%= to_mime_type $_->{head} + </p> +% } +% else { +% die "unknown Content-Disposition '$_->{head}{content_disposition}'" +% } % } % } % elsif ($msg->{head}{mime}{content_maintype} eq 'message') { -% die "not implemented" +% die "not implemented" unless $msg->{head}{mime}{content_subtype} eq 'rfc822'; + <p>not implemented</p> % } % else { - <div class=jwm-mail-body> - %== mime_render($content_type, $body); - </div> + <div class="jwm-mail-body <%= $content_type eq 'text/plain' ? 'jwm-mail-body-text-plain' : '' %>" > +%== mime_render($content_type, $body) // $content_type + </div> % } + </div> +% end + + +<div class="jwm-base"> + + <h1>Read Mail</h1> + +%= $format_mail->($msg) + <nav> <a href="javascript:history.back()" class="pure-button"> - %= l 'back' +%= l 'back' </a> </nav> |