summaryrefslogtreecommitdiff
path: root/lib/JWebmail/Plugin
diff options
context:
space:
mode:
Diffstat (limited to 'lib/JWebmail/Plugin')
-rw-r--r--lib/JWebmail/Plugin/Helper.pm68
-rw-r--r--lib/JWebmail/Plugin/RenderMail.pm182
2 files changed, 189 insertions, 61 deletions
diff --git a/lib/JWebmail/Plugin/Helper.pm b/lib/JWebmail/Plugin/Helper.pm
index a98f245..b298a17 100644
--- a/lib/JWebmail/Plugin/Helper.pm
+++ b/lib/JWebmail/Plugin/Helper.pm
@@ -98,45 +98,6 @@ 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 {
- my ($c, $content) = @_;
-
- $content = xml_escape($content);
- $content =~ s/\n/<br>/g;
-
- 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;
- return $renderer->($c, $cont);
-};
-
### session password handling
@@ -210,7 +171,7 @@ sub warn_crypt {
state $once = 0;
- if ( !TRUE_RANDOM && !$once && lc($c->config->{session}{secure}) eq 's3d' ) {
+ if ( !TRUE_RANDOM && !$once && lc $c->config->{session}{secure} eq 's3d' ) {
$c->log->warn("Falling back to pseudo random generation. Please install Crypt::URandom");
$once = 1;
}
@@ -308,8 +269,6 @@ sub register {
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)
@@ -324,7 +283,6 @@ sub register {
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);
@@ -333,6 +291,9 @@ sub register {
$app->validator->add_filter(non_empty_ul => \&filter_empty_upload);
}
+ else {
+ die 'unkown value for "import"'
+ }
}
@@ -350,16 +311,10 @@ Helper - Functions used as helpers in controller and templates and additional va
use Mojo::Base 'Mojolicious';
- use JWebmail::Plugin::Helper;
-
sub startup($self) {
- $self->helper(mime_render => \&JWebmail::Plugin::Helper::mime_render);
+ $app->plugin('Helper');
}
- # or
-
- $app->plugin('Helper');
-
=head1 DESCRIPTION
L<JWebmail::Helper> provides useful helper functions and validator cheks and filter for
@@ -425,15 +380,6 @@ Sets the stash values (all 1 based inclusive):
next_page
last_page
-=head2 mime_render
-
-A helper for templates used to display the content of a mail for the browser.
-The output is valid html and should not be escaped.
-
- $app->helper(mime_render => \&JWebmail::Plugin::Helper::mime_render);
-
- %== mime_render 'text/plain' $content
-
=head2 session_passwd
A helper used to set and get the session password. The behavior can be altered by
@@ -469,11 +415,11 @@ On log-in it is transfered plainly.
=head1 DEPENDENCIES
-Mojolicious and optionally Digest::HMAC_MD5, Crypt::URandom.
+Mojolicious and recommended Crypt::URandom.
=head1 SEE ALSO
-L<JWebmail>, L<JWebmail::Controller::All>, L<Mojolicious>, L<Mojolicious::Controller>
+L<JWebmail>
=head1 NOTICE
diff --git a/lib/JWebmail/Plugin/RenderMail.pm b/lib/JWebmail/Plugin/RenderMail.pm
new file mode 100644
index 0000000..4417fae
--- /dev/null
+++ b/lib/JWebmail/Plugin/RenderMail.pm
@@ -0,0 +1,182 @@
+package JWebmail::Plugin::RenderMail;
+
+use Mojo::Base 'Mojolicious::Plugin';
+
+use Mojo::ByteStream;
+use Mojo::Util 'xml_escape';
+
+
+sub render_text_plain {
+ my ($_c, $_subtype, $content, $_path) = @_;
+
+ $content = xml_escape($content);
+ $content =~ s/\n/<br>/g;
+
+ return qq'<div class="jwm-mail-body jwm-mail-body-text-plain">\n $content </div>\n';
+}
+
+sub render_text_html {
+ my ($c, $_subtype, $_content, $path) = @_;
+
+ my $url = $c->url_for('raw', id => $c->stash('id'));
+ $url = $url->query(path => join('.', @$path)) if @$path;
+
+ return qq'<iframe src="$url" class="jwm-mail-body-text-html" ></iframe>\n';
+}
+
+sub render_multipart_alternative {
+ my ($c, $_subtype, $content, $path) = @_;
+
+ my $parts = $content->{parts};
+ my $R = qq'<div class="jwm-mail-body jwm-mail-body-multipart-alternative"\n>';
+ my $i = 0;
+ my $end;
+
+ for (reverse @$parts) {
+ if (!$end) {
+ my $x = mime_render($c, to_mime_types($_->{head}), $_->{body}, [@$path, $#$parts-$i]);
+ if ($x) {
+ $R .= $x;
+ $end = 1;
+ }
+ }
+ else {
+ $R .= '<details class="jwm-mail-body-multipart-alternative-extra" >';
+ $R .= '<summary>';
+ $R .= to_mime_type($_->{head});
+ $R .= "</summary>\n";
+ $R .= mime_render($c, to_mime_types($_->{head}), $_->{body}, [@$path, $#$parts-$i]);
+ $R .= "</details>\n";
+ }
+ ++$i;
+ }
+ return $R . "</div>\n";
+}
+
+sub render_multipart {
+ my ($c, $_subtype, $content, $path) = @_;
+
+ my $parts = $content->{parts};
+ my $R = qq'<div class="jwm-mail-body jwm-mail-body-multipart"\n>';
+ my $i = 0;
+
+ for (@$parts) {
+ if ( !$_->{head}{content_disposition}
+ || lc $_->{head}{content_disposition} eq 'none'
+ || lc $_->{head}{content_disposition} eq 'inline') {
+
+ $R .= mime_render($c, to_mime_types($_->{head}), $_->{body}, [@$path, $i]);
+ }
+ elsif (lc $_->{head}{content_disposition} eq 'attachment') {
+ $R .= '<p>';
+ $R .= $c->link_to($c->url_for(raw => id => $c->stash('id'))->query(path => join('.', @$path, $i))->to_abs, (download => $_->{head}{filename}) => sub {
+ 'Attachment ' . xml_escape($_->{head}{filename}) . ' of type ' . to_mime_type($c, $_->{head});
+ });
+ $R .= "</p>\n";
+ }
+ else {
+ warn "unknown Content-Disposition '$_->{head}{content_disposition}'";
+ $R .= "<p>unknown Content-Disposition '$_->{head}{content_disposition}'</p>\n";
+ }
+ ++$i;
+ }
+ return $R . "</div>\n";
+}
+
+sub _format_header {
+ my ($c, $category, $value) = @_;
+
+ my $R = '';
+
+ if (ref $value eq 'ARRAY' && $value->@*) {
+ $R .= '<dt>' . xml_escape(uc $c->l($category)) . "</dt>\n";
+ for ($value->@*) {
+ $R .= '<dd>';
+ $R .= xml_escape($_->{display_name} ? qq("$_->{display_name}" <$_->{address}>) : "$_->{address}");
+ $R .= "<dd>\n";
+ }
+ }
+ return $R;
+}
+
+sub render_message {
+ my ($c, $subtype, $msg, $path) = @_;
+
+ warn "unkown mime-subtype $subtype" unless $subtype eq 'rfc822';
+
+ my $R .= '<div clas="jwm-mail">';
+
+ $R .= '<dl class="jwm-mail-header">';
+ $R .= '<dt>' . xml_escape(uc $c->l('subject')) . '</dt>';
+ $R .= '<dd>' . xml_escape($msg->{head}{subject}) . "</dd>\n";
+ $R .= _format_header($c, from => $msg->{head}{from});
+ $R .= _format_header($c, to => $msg->{head}{to});
+ $R .= _format_header($c, cc => $msg->{head}{cc});
+ $R .= _format_header($c, bcc => $msg->{head}{bcc});
+ $R .= '<dt>' . xml_escape(uc $c->l('date')) . '</dt>';
+ $R .= '<dd>' . xml_escape($msg->{head}{date}) . "</dd>\n";
+ $R .= '<dt>' . xml_escape(uc $c->l('content-type')) . '</dt>';
+ $R .= '<dd>' . to_mime_type($msg->{head}{mime}) . "</dd>\n";
+ $R .= "</dl>\n";
+
+ #my $content = ref $msg->{body} && exists $msg->{body}{parts} ? $msg->{body}{parts} : $msg->{body};
+
+ $R .= mime_render($c, to_mime_types($msg->{head}{mime}), $msg->{body}, [@$path, 0]);
+
+ return $R . "</div>\n";
+}
+
+our %MIME_Render_Subs = (
+ 'text/plain' => \&render_text_plain,
+ 'text/html' => \&render_text_html,
+ 'multipart/alternative' => \&render_multipart_alternative,
+ 'multipart' => \&render_multipart,
+ 'message' => \&render_message,
+);
+
+sub mime_render {
+ my ($c, $maintype, $subtype, $content, $path) = @_;
+
+ my $renderer = $MIME_Render_Subs{"$maintype/$subtype"} || $MIME_Render_Subs{$maintype};
+
+ unless ($renderer) {
+ return "<p>Unsupported MIME type of <code>$maintype/$subtype</code>.</p>\n";
+ }
+
+ return $renderer->($c, $subtype, $content, $path);
+}
+
+
+sub to_mime_type { lc xml_escape("$_[0]->{content_maintype}/$_[0]->{content_subtype}") }
+sub to_mime_types { return xml_escape($_[0]->{content_maintype}), xml_escape($_[0]->{content_subtype}) }
+
+
+sub register {
+ my ($self, $app, $conf) = @_;
+ $conf //= {};
+
+ $app->helper('render_mail.format_mail' => sub { Mojo::ByteStream->new(mime_render($_[0], 'message', 'rfc822', $_[1], [])) });
+ $app->helper(to_mime_type => sub { shift; to_mime_type(@_) });
+}
+
+1
+
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+JWebmail::Plugin::RenderMail - Does the heavy lifting of converting an E-Mail to HTML
+
+=head1 HELPERS
+
+=head2 render_mail.format_mail
+
+Renders a mail to html recursively.
+
+=head2 to_mime_type
+
+Combines the content_maintype and content_subtype attributes into the regular MIME description.
+These attributes are found in a mail head mime section or as head for multipart messages.
+