diff options
-rw-r--r-- | CHANGES.md | 32 | ||||
-rw-r--r-- | lib/JWebmail.pm | 31 | ||||
-rw-r--r-- | lib/JWebmail/Controller/Webmail.pm | 54 | ||||
-rw-r--r-- | lib/JWebmail/Model/ReadMails/MockJSON.pm | 2 | ||||
-rw-r--r-- | lib/JWebmail/Plugin/Helper.pm | 10 |
5 files changed, 77 insertions, 52 deletions
@@ -107,22 +107,31 @@ Current v1.1.0 - [x] add a delete session function for s3d, maybe - [x] simply remove key from cookie - [x] add actions script -- [ ] repurpose status field in displayheader - - [x] currently just renamed +- [x] consider using more mojo functions + - [x] use Mojolicious::Types to replace File::Type + - [x] Helper + - [ ] QMailAuthuser +- [x] repurpose status column in displayheader + - [x] currently just renamed to 'Multipart' - [x] advance ini config plugin - [x] allow non-leaf nodes to be arrays - [ ] allow quotes - [ ] allow continuation over multiple lines - [ ] warn about overrides - [ ] add template support, maybe + - [ ] switch to TOML or a provided format, as INI is too basic +- [x] refactor ReadMails into a role +- [x] made languages in about clickable +- [x] make loading auth data from session easier + - how do you hide stash values? + - [ ] password is now hidden when stringified +- [x] merge read and raw (with content type) + - how does one extract the body functionality? (One does not.) +- [x] refactor templates to make use of link_to - [ ] improve i18n - [ ] add localization of dates and time - [x] refactor I18N plugin to allow independent translate provider - [ ] fix tests -- [x] consider using more mojo functions - - [x] use Mojolicious::Types to replace File::Type - - [x] Helper - - [ ] QMailAuthuser - [ ] moving mails to other folders - [ ] creating new folders - [ ] backend @@ -132,16 +141,14 @@ Current v1.1.0 - [ ] improve performance of backend, consider alternatives to Mail::Box::Manager - [ ] based on Maildir::Light - [x] reimplementation in Rust -- [x] refactor ReadMails into a role -- [x] made languages in about clickable - [ ] cache mail reads - is unlikely to work as mails can be moved freely -- [x] make loading auth data from session easier -- [ ] merge read and raw (with content type) - - how does one extract the body functionality? - [ ] add exception types - [x] added exception for QMailAuthuser - [ ] extract version for Makefile.PL from Application +- [ ] add config validation +- [ ] read and write s3d only once per request ($c->on('finish')) +- [ ] compute h-mac on the client side Future ------ @@ -169,7 +176,6 @@ Future - [ ] gif - [ ] better pagination - [ ] merge with partial templates, maybe -- [ ] add config validation - [ ] click on sender to answer - [ ] mobile optimize - [ ] download mail and attachments @@ -182,4 +188,4 @@ Future - [ ] allow changing password - [ ] think about forgot password feature - [ ] address book support - - [ ] add links on email addresses in header : click = add into addressbook + - [ ] add links on email addresses in header : click = add into address book diff --git a/lib/JWebmail.pm b/lib/JWebmail.pm index 8def434..9899b05 100644 --- a/lib/JWebmail.pm +++ b/lib/JWebmail.pm @@ -1,6 +1,6 @@ package JWebmail v1.2.0; -use Mojo::Base 'Mojolicious'; +use Mojo::Base Mojolicious; use JWebmail::Controller::Webmail; use JWebmail::Model::ReadMails::Role; @@ -8,6 +8,30 @@ use JWebmail::Model::ReadMails::QMailAuthuser; use JWebmail::Model::WriteMails; +sub nest { +} +sub validateConf { + my $self = shift; + + my $conf = $self->config; + my $v = $self->validator->validation->input($conf); + + $v->optional('secret', 'not_empty'); + + $v->optional('i18n'); + $v->required('session')->required('secure')->in(qw(none cram s3d)); + $v->required('defaults')->required('scriptadmin')->like(qr/@/); + my $dev = $v->optional('development'); + $dev->optional('read_mock', 'not_empty'); + $dev->optional('block_writes')->in(0, 1); + + for ($v->failed->@*) { + say "reasons for $_: " , $v->error($_)->@*; + } + $v->is_valid; +} + + sub startup { my $self = shift; @@ -20,6 +44,8 @@ sub startup { push @{$self->plugins->namespaces}, 'JWebmail::Plugin'; $self->plugin('INIConfig'); + #die unless $self->validateConf; + $self->plugin('ServerSideSessionData'); $self->plugin('Helper'); my $i18n_route = $self->plugin('I18N2', $self->config('i18n')); @@ -63,12 +89,11 @@ sub route { $r->get('/logout')->to('Webmail#logout'); my $a = $r->under('/')->to('Webmail#auth'); - $a->get('/home/:folder')->to('Webmail#displayheaders', folder => '')->name('displayheaders'); + $a->get('/home/*folder')->to('Webmail#displayheaders', folder => '')->name('displayheaders'); $a->get('/read/#id' => 'read')->to('Webmail#readmail'); $a->get('/write')->to('Webmail#writemail'); $a->post('/write' => 'send')-> to('Webmail#sendmail'); $a->post('/move')->to('Webmail#move'); - $a->get('/raw/#id')->to('Webmail#raw'); } diff --git a/lib/JWebmail/Controller/Webmail.pm b/lib/JWebmail/Controller/Webmail.pm index f0d45b3..d01abae 100644 --- a/lib/JWebmail/Controller/Webmail.pm +++ b/lib/JWebmail/Controller/Webmail.pm @@ -1,10 +1,15 @@ package JWebmail::Controller::Webmail; -use Mojo::Base 'Mojolicious::Controller'; +use Mojo::Base Mojolicious::Controller; + +use List::Util 'first'; use Mojolicious::Types; -use constant S_USER => 'user'; # Key for user name in active session +use constant { + S_USER => 'user', # Key for user name in active session + ST_AUTH => 'auth', +}; # no action has been taken, display login page @@ -35,7 +40,7 @@ sub auth { my $authConf = {user => $user, password => $pw}; $authConf->{challenge} = $self->app->secrets->[0] if $self->config->{session}{secure} eq 'cram'; - $self->stash(auth => $self->users->Auth($authConf)); + $self->stash(ST_AUTH() => $self->users->Auth($authConf)); return 1; } @@ -118,7 +123,7 @@ sub displayheaders { no warnings 'experimental::smartmatch'; my $self = shift; - my $auth = $self->stash('auth'); + my $auth = $self->stash(ST_AUTH); my $folders = _time { $self->users->folders($auth) } $self, 'user folders'; @@ -136,6 +141,7 @@ sub displayheaders { my $search = $v->optional('search')->param; if ($v->has_error) { + local $" = ' '; $self->render(template => 'error', error => "errors in @{ $v->failed }", status => 400); return; } @@ -178,7 +184,7 @@ sub readmail { my $mid = $self->stash('id'); - my $auth = $self->stash('auth'); + my $auth = $self->stash(ST_AUTH); my $mail; eval { $mail = $self->users->show($auth, $mid) }; @@ -190,26 +196,14 @@ sub readmail { die $@; } - $self->render(msg => $mail); -} - - -sub raw { - my $self = shift; - - my $mid = $self->stash('id'); - - my $auth = $self->stash('auth'); - - my $mail = $self->users->show($auth, $mid); - + # select a single body element my $v = $self->validation; - $v->optional('body')->like(qr/\w+/); + my $type = $v->optional('body')->like(qr(^[\w\-/; ]+$)a)->param; return if $v->has_error; - if (my $type = $self->param('body')) { + if ($type) { if ($mail->{head}{content_type} =~ '^multipart/') { - my ($content) = grep {$_->{head}{content_type} =~ $type} @{ $mail->{body} }; + my $content = first {$_->{head}{content_type} =~ $type} @{ $mail->{body} }; $self->render(text => $content->{body}); } elsif ($mail->{head}{content_type} =~ $type) { @@ -218,10 +212,13 @@ sub raw { else { $self->reply->not_found; } + return; } - else { - $self->render(json => $mail); - } + + $self->respond_to( + html => {msg => $mail}, + json => {json => $mail} + ); } @@ -242,7 +239,7 @@ sub sendmail { bcc => scalar $v->optional('bcc', 'not_empty')->check('mail_line')->every_param, reply => scalar $v->optional('back_to', 'not_empty')->check('mail_line')->param, attach => scalar $v->optional('attach', 'non_empty_ul')->upload->param, - from => scalar $self->session(S_USER), + from => scalar $self->stash(ST_AUTH)->{user}, ); $mail{attach_type} = Mojolicious::Types->new->file_type($mail{attach}->filename) if $mail{attach}; @@ -283,7 +280,7 @@ sub move { return; } - my $auth = $self->stash('auth'); + my $auth = $self->stash(ST_AUTH); my $folders = $self->users->folders($auth); my $mm = $self->every_param('mail'); @@ -351,6 +348,7 @@ Provides an overview over messages. =head2 readmail Displays a single mail. +Can also be displayed as JSON or only one body part as the appropriate content type. =head2 writemail @@ -364,10 +362,6 @@ Sends a mail written in writemail. Moves mails between mail forlders. -=head2 raw - -Displays the mail raw, ready to be downloaded. - =head1 DEPENCIES Mojolicious and File::Type diff --git a/lib/JWebmail/Model/ReadMails/MockJSON.pm b/lib/JWebmail/Model/ReadMails/MockJSON.pm index 8918040..f77cd2a 100644 --- a/lib/JWebmail/Model/ReadMails/MockJSON.pm +++ b/lib/JWebmail/Model/ReadMails/MockJSON.pm @@ -98,7 +98,7 @@ sub show { return $mail; } else { - die 'unkown mail-id'; + die 'unknown mail-id'; } } diff --git a/lib/JWebmail/Plugin/Helper.pm b/lib/JWebmail/Plugin/Helper.pm index 3281d26..be147fe 100644 --- a/lib/JWebmail/Plugin/Helper.pm +++ b/lib/JWebmail/Plugin/Helper.pm @@ -113,7 +113,7 @@ my $render_text_plain = sub { my $render_text_html = sub { my $c_ = shift; - return '<iframe src="' . $c_->url_for('rawid', id => $c_->stash('id'))->query(body => 'html') . '" class=html-mail></iframe>'; + return '<iframe src="' . $c_->url_for('read', id => $c_->stash('id'))->query(body => 'html') . '" class=html-mail></iframe>'; }; @@ -355,7 +355,7 @@ Helper - Functions used as helpers in controller and templates and additional va L<JWebmail::Helper> provides useful helper functions and validator cheks and filter for L<JWebmail::Controller::All> and various templates. -=head1 FUNCTIONS +=head1 HELPERS =head2 mail_line @@ -393,7 +393,7 @@ This is not registered by default. =head2 paginate -A helper for calculationg page bounds. +A helper for calculating page bounds. Takes the total number of items as argument. @@ -426,7 +426,7 @@ The output is valid html and should not be escaped. =head2 session_passwd -A helper used to set and get the session password. The behaivour can be altered by +A helper used to set and get the session password. The behavior can be altered by setting the config variable C<< session => {secure => 's3d'} >>. $app->helper(session_passwd => \&JWebmail::Plugin::Helper::session_passwd); @@ -454,7 +454,7 @@ data is stored on the server. Additionally the password is encrypted by an one-t =head1 DEPENDENCIES -Mojolicious, Crypt::Random and optianally Digest::HMAC_MD5. +Mojolicious and optionally Digest::HMAC_MD5, Crypt::URandom. =head1 SEE ALSO |