summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/JWebmail/Plugin/Helper.pm53
-rw-r--r--public/style.css10
-rw-r--r--templates/webmail/readmail.html.ep114
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>