package JWebmail v1.2.3; use Mojo::Base Mojolicious; use Module::Load 'load'; use JWebmail::Config 'LOGIN_SCHEME'; use JWebmail::Controller::Webmail; use JWebmail::Model::ReadMails::QMailAuthuser; use JWebmail::Model::WriteMails; sub validateConf { my $self = shift; my $conf = $self->config; exists $conf->{admin_mail} or die; $conf->{admin_mail} =~ /@/ or die; exists $conf->{i18n}{default_language} or die; $conf->{i18n}{default_language} =~ /^[\w_]+$/a or die; exists $conf->{model}{read}{virtual_user} or die; getpwnam $conf->{model}{read}{virtual_user} or die; exists $conf->{model}{read}{mailbox_path} or die; -d $conf->{model}{read}{mailbox_path} or die; exists $conf->{model}{read}{authenticator} or die; exists $conf->{model}{write}{sendmail} or die; return 1; } sub startup { my $self = shift; $self->moniker('jwebmail'); # load plugins push @{$self->plugins->namespaces}, 'JWebmail::Plugin'; $self->plugin('TOMLConfig'); $self->validateConf; if (fc LOGIN_SCHEME eq fc 'plain') { $self->plugin('ServerSideSessionData'); } $self->plugin('Paginate'); my $i18n_route = $self->plugin('I18N2', $self->config('i18n')); $self->secrets( [$self->config('secret')] ) if $self->config('secret'); delete $self->config->{secret}; # initialize models my $read_mails = JWebmail::Model::ReadMails::QMailAuthuser->new($self->config->{model}{read}); $self->helper(users => sub { $read_mails }); my $write = JWebmail::Model::WriteMails->new($self->config->{model}{write}); $self->helper(send_mail => sub { $write->sendmail($_[1]) }); $self->validator->add_check(mail_line => \&_mail_line); $self->validator->add_filter(non_empty_ul => \&_filter_empty_upload); $self->defaults(version => __PACKAGE__->VERSION); $self->sessions->cookie_name('jwebmail_session'); $self->sessions->samesite('Strict'); $self->sessions->secure(1); $self->sessions->default_expiration(30 * 60); $self->route($i18n_route); } sub route { my $self = shift; my $r = shift || $self->routes; $r->get ('/' => 'login')->to('Webmail#noaction'); $r->post('/' => 'login')->to('Webmail#login'); $r->get ('/about' )->to('Webmail#about'); $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('/read/#id' => 'read')->to('Webmail#readmail'); $a->get('/raw/#id' => 'raw' )->to('Webmail#raw'); $a->get('/write' )->to('Webmail#writemail'); $a->post('/write' => 'send' )->to('Webmail#sendmail'); $a->post('/move' )->to('Webmail#move'); $a->post('/remove/*folder' )->to('Webmail#remove', folder => ''); } ### filter and checks for mojo validator sub _mail_line { my ($v, $name, $value, @args) = @_; my $mail_addr = qr/\w+\@\w+\.\w+/; # my $unescaped_quote = qr/"(*nlb:\\)/; # greater perl version required my $unescaped_quote = qr/"(? ) | ( $mail_addr ) )$/xn; } sub _filter_empty_upload { my ($v, $name, $value) = @_; return $value->filename ? $value : undef; } 1 __END__ =encoding utf-8 =head1 NAME JWebmail - Provides a web based e-mail client meant to be used with s/qmail. =head1 SYNOPSIS hypnotoad script/jwebmail And use a server in reverse proxy configuration. =head1 DESCRIPTION =head1 CONFIGURATION Use the I file or for a specific I<$mode> the I. =head1 VALIDATOR =head2 mail_line A check for validator used in mail headers for fields containing email addresses. $app->validator->add_check(mail_line => \&JWebmail::Plugin::Helper::mail_line); my $v = $c->validation; $v->required('to', 'not_empty')->check('mail_line'); =head2 filter_empty_upload A filter for validator used to filter out empty uploads. $app->validator->add_filter(non_empty_ul => \&JWebmail::Plugin::Helper::filter_empty_upload); my $v = $c->validation; $v->required('file_upload', 'non_empty_ul'); =head1 AUTHORS Copyright (C) 2020-2022 Jannis M. Hoffmann L =head1 BASED ON IDEAS Copyright (C) 2001 Olivier Müller L (GPLv2+ project: oMail Webmail) Copyright (C) 2000 Ernie Miller (GPL project: Neomail) See the CREDITS file for project contributors. =head1 LICENSE This module is licensed under the terms of the GPLv3. Please take a look at the provided LICENSE file shipped with this module. =cut