Hello community,

here is the log from the commit of package perl-Mojolicious for 
openSUSE:Factory checked in at 2017-02-16 16:46:13
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/perl-Mojolicious (Old)
 and      /work/SRC/openSUSE:Factory/.perl-Mojolicious.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "perl-Mojolicious"

Changes:
--------
--- /work/SRC/openSUSE:Factory/perl-Mojolicious/perl-Mojolicious.changes        
2017-02-10 09:50:13.403673770 +0100
+++ /work/SRC/openSUSE:Factory/.perl-Mojolicious.new/perl-Mojolicious.changes   
2017-02-16 16:46:14.463832425 +0100
@@ -1,0 +2,21 @@
+Mon Feb 13 10:13:54 UTC 2017 - [email protected]
+
+- updated to 7.25
+   see /usr/share/doc/packages/perl-Mojolicious/Changes
+
+  7.25  2017-02-09
+    - Fixed cleanup bugs in Mojo::IOLoop::Stream.
+
+-------------------------------------------------------------------
+Wed Feb  8 06:07:37 UTC 2017 - [email protected]
+
+- updated to 7.24
+   see /usr/share/doc/packages/perl-Mojolicious/Changes
+
+  7.24  2017-02-05
+    - Added open method to Mojo::File.
+    - Added tempfile function to Mojo::File.
+    - Fixed bug in Mojo::Asset::File where the slurp method would not work
+      correctly for very large files.
+
+-------------------------------------------------------------------

Old:
----
  Mojolicious-7.23.tar.gz

New:
----
  Mojolicious-7.25.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ perl-Mojolicious.spec ++++++
--- /var/tmp/diff_new_pack.HO0NfH/_old  2017-02-16 16:46:15.175731333 +0100
+++ /var/tmp/diff_new_pack.HO0NfH/_new  2017-02-16 16:46:15.175731333 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           perl-Mojolicious
-Version:        7.23
+Version:        7.25
 Release:        0
 %define cpan_name Mojolicious
 Summary:        Real-time web framework
@@ -67,6 +67,7 @@
 
 %files -f %{name}.files
 %defattr(-,root,root,755)
-%doc Changes examples LICENSE README.md
+%doc Changes examples README.md
+%license LICENSE
 
 %changelog

++++++ Mojolicious-7.23.tar.gz -> Mojolicious-7.25.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/Changes new/Mojolicious-7.25/Changes
--- old/Mojolicious-7.23/Changes        2017-01-29 22:33:08.000000000 +0100
+++ new/Mojolicious-7.25/Changes        2017-02-09 22:31:27.000000000 +0100
@@ -1,4 +1,13 @@
 
+7.25  2017-02-09
+  - Fixed cleanup bugs in Mojo::IOLoop::Stream.
+
+7.24  2017-02-05
+  - Added open method to Mojo::File.
+  - Added tempfile function to Mojo::File.
+  - Fixed bug in Mojo::Asset::File where the slurp method would not work
+    correctly for very large files.
+
 7.23  2017-01-29
   - Added max_request_size attribute to Mojolicious.
   - Added max_response_size attribute to Mojo::UserAgent.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/META.json 
new/Mojolicious-7.25/META.json
--- old/Mojolicious-7.23/META.json      2017-01-29 22:42:04.000000000 +0100
+++ new/Mojolicious-7.25/META.json      2017-02-09 23:50:51.000000000 +0100
@@ -58,6 +58,6 @@
       },
       "x_IRC" : "irc://irc.perl.org/#mojo"
    },
-   "version" : "7.23",
+   "version" : "7.25",
    "x_serialization_backend" : "JSON::PP version 2.27400"
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/META.yml 
new/Mojolicious-7.25/META.yml
--- old/Mojolicious-7.23/META.yml       2017-01-29 22:42:04.000000000 +0100
+++ new/Mojolicious-7.25/META.yml       2017-02-09 23:50:51.000000000 +0100
@@ -31,5 +31,5 @@
   homepage: http://mojolicious.org
   license: http://www.opensource.org/licenses/artistic-license-2.0
   repository: https://github.com/kraih/mojo.git
-version: '7.23'
+version: '7.25'
 x_serialization_backend: 'CPAN::Meta::YAML version 0.018'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/README.md 
new/Mojolicious-7.25/README.md
--- old/Mojolicious-7.23/README.md      2017-01-24 18:44:14.000000000 +0100
+++ new/Mojolicious-7.25/README.md      2017-01-29 23:52:55.000000000 +0100
@@ -79,7 +79,7 @@
 # WebSocket service used by the template to extract the title from a website
 websocket '/title' => sub ($c) {
   $c->on(message => sub ($c, $msg) {
-    my $title = $c->ua->get($msg)->res->dom->at('title')->text;
+    my $title = $c->ua->get($msg)->result->dom->at('title')->text;
     $c->send($title);
   });
 };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/examples/entities.pl 
new/Mojolicious-7.25/examples/entities.pl
--- old/Mojolicious-7.23/examples/entities.pl   2016-07-19 02:38:18.000000000 
+0200
+++ new/Mojolicious-7.25/examples/entities.pl   2017-01-29 23:44:45.000000000 
+0100
@@ -2,9 +2,8 @@
 use Mojo::UserAgent;
 
 # Extract named character references from HTML Living Standard
-my $tx   = Mojo::UserAgent->new->get('https://html.spec.whatwg.org');
-my $rows = $tx->res->dom('#named-character-references-table tbody > tr');
-for my $row ($rows->each) {
+my $res = Mojo::UserAgent->new->get('https://html.spec.whatwg.org')->result;
+for my $row ($res->dom('#named-character-references-table tbody > tr')->each) {
   my $entity     = $row->at('td > code')->text;
   my $codepoints = $row->children('td')->[1]->text;
   say "$entity $codepoints";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo/Asset/File.pm 
new/Mojolicious-7.25/lib/Mojo/Asset/File.pm
--- old/Mojolicious-7.23/lib/Mojo/Asset/File.pm 2017-01-09 23:48:01.000000000 
+0100
+++ new/Mojolicious-7.25/lib/Mojo/Asset/File.pm 2017-02-05 20:19:03.000000000 
+0100
@@ -2,38 +2,28 @@
 use Mojo::Base 'Mojo::Asset';
 
 use Carp 'croak';
-use Errno 'EEXIST';
-use Fcntl qw(O_APPEND O_CREAT O_EXCL O_RDONLY O_RDWR);
+use Fcntl 'SEEK_SET';
 use File::Spec::Functions ();
-use IO::File;
-use Mojo::File;
-use Mojo::Util 'md5_sum';
+use Mojo::File 'tempfile';
 
 has [qw(cleanup path)];
 has handle => sub {
   my $self = shift;
 
   # Open existing file
-  my $handle = IO::File->new;
-  my $path   = $self->path;
-  if (defined $path && -f $path) {
-    $handle->open($path, O_RDONLY) or croak qq{Can't open file "$path": $!};
-    return $handle;
-  }
-
-  # Open new or temporary file
-  my $base = Mojo::File->new($self->tmpdir, 'mojo.tmp')->to_string;
-  my $name = $path // $base;
-  until ($handle->open($name, O_APPEND | O_CREAT | O_EXCL | O_RDWR)) {
-    croak qq{Can't open file "$name": $!} if defined $path || $! != $!{EEXIST};
-    $name = "$base." . md5_sum(time . $$ . rand);
-  }
-  $self->path($name);
+  my $path = $self->path;
+  return Mojo::File->new($path)->open('<') if defined $path && -e $path;
 
-  # Enable automatic cleanup
   $self->cleanup(1) unless defined $self->cleanup;
 
-  return $handle;
+  # Create a specific file
+  return Mojo::File->new($path)->open('+>>') if defined $path;
+
+  # Create a temporary file
+  my $template = 'mojo.tmp.XXXXXXXXXXXXXXXX';
+  my $file = tempfile DIR => $self->tmpdir, TEMPLATE => $template, UNLINK => 0;
+  $self->path($file->to_string);
+  return $file->open('+>>');
 };
 has tmpdir => sub { $ENV{MOJO_TMPDIR} || File::Spec::Functions::tmpdir };
 
@@ -124,9 +114,9 @@
 sub slurp {
   my $handle = shift->handle;
   $handle->sysseek(0, SEEK_SET);
-  defined $handle->sysread(my $content, -s $handle, 0)
-    or croak qq{Can't read from asset: $!};
-  return $content;
+  my $ret = my $content = '';
+  while ($ret = $handle->sysread(my $buffer, 131072, 0)) { $content .= $buffer 
}
+  return defined $ret ? $content : croak "Can't read from asset: $!";
 }
 
 1;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo/Collection.pm 
new/Mojolicious-7.25/lib/Mojo/Collection.pm
--- old/Mojolicious-7.23/lib/Mojo/Collection.pm 2016-07-19 02:38:18.000000000 
+0200
+++ new/Mojolicious-7.25/lib/Mojo/Collection.pm 2017-02-06 00:43:08.000000000 
+0100
@@ -170,7 +170,7 @@
 string.
 
   # "0, 1, 2, 3"
-  Mojo::Collection->new(0, 1, undef, 2, '', 3)->compact->join(', ');
+  c(0, 1, undef, 2, '', 3)->compact->join(', ');
 
 =head2 each
 
@@ -217,7 +217,7 @@
 all elements.
 
   # "1, 2, 3, 4, 5, 6, 7"
-  Mojo::Collection->new(1, [2, [3, 4], 5, [6]], 7)->flatten->join(', ');
+  c(1, [2, [3, 4], 5, [6]], 7)->flatten->join(', ');
 
 =head2 grep
 
@@ -309,7 +309,7 @@
 Create a new collection with all selected elements.
 
   # "B C E"
-  Mojo::Collection->new('A', 'B', 'C', 'D', 'E')->slice(1, 2, 4)->join(' ');
+  c('A', 'B', 'C', 'D', 'E')->slice(1, 2, 4)->join(' ');
 
 =head2 shuffle
 
@@ -362,10 +362,10 @@
   my $new = $collection->uniq(sub { $_->some_method(@args) });
 
   # "foo bar baz"
-  Mojo::Collection->new('foo', 'bar', 'bar', 'baz')->uniq->join(' ');
+  c('foo', 'bar', 'bar', 'baz')->uniq->join(' ');
 
   # "[[1, 2], [2, 1]]"
-  Mojo::Collection->new([1, 2], [2, 1], [3, 2])->uniq(sub{ $_->[1] 
})->to_array;
+  c([1, 2], [2, 1], [3, 2])->uniq(sub{ $_->[1] })->to_array;
 
 =head1 SEE ALSO
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo/File.pm 
new/Mojolicious-7.25/lib/Mojo/File.pm
--- old/Mojolicious-7.23/lib/Mojo/File.pm       2017-01-25 21:14:47.000000000 
+0100
+++ new/Mojolicious-7.25/lib/Mojo/File.pm       2017-02-06 00:47:22.000000000 
+0100
@@ -16,9 +16,10 @@
 use File::Spec::Functions
   qw(abs2rel canonpath catfile file_name_is_absolute rel2abs splitdir);
 use File::Temp ();
+use IO::File   ();
 use Mojo::Collection;
 
-our @EXPORT_OK = ('path', 'tempdir');
+our @EXPORT_OK = ('path', 'tempdir', 'tempfile');
 
 sub basename { scalar File::Basename::basename ${$_[0]}, @_ }
 
@@ -76,6 +77,13 @@
   return bless \$value, ref $class || $class;
 }
 
+sub open {
+  my $self   = shift;
+  my $handle = IO::File->new;
+  $handle->open($$self, @_) or croak qq{Can't open file "$$self": $!};
+  return $handle;
+}
+
 sub path { __PACKAGE__->new(@_) }
 
 sub remove_tree {
@@ -87,7 +95,7 @@
 sub slurp {
   my $self = shift;
 
-  open my $file, '<', $$self or croak qq{Can't open file "$$self": $!};
+  CORE::open my $file, '<', $$self or croak qq{Can't open file "$$self": $!};
   my $ret = my $content = '';
   while ($ret = $file->sysread(my $buffer, 131072, 0)) { $content .= $buffer }
   croak qq{Can't read from file "$$self": $!} unless defined $ret;
@@ -97,7 +105,7 @@
 
 sub spurt {
   my ($self, $content) = (shift, join '', @_);
-  open my $file, '>', $$self or croak qq{Can't open file "$$self": $!};
+  CORE::open my $file, '>', $$self or croak qq{Can't open file "$$self": $!};
   ($file->syswrite($content) // -1) == length $content
     or croak qq{Can't write to file "$$self": $!};
   return $self;
@@ -107,6 +115,8 @@
 
 sub tempdir { __PACKAGE__->new(File::Temp->newdir(@_)) }
 
+sub tempfile { __PACKAGE__->new(File::Temp->new(@_)) }
+
 sub to_abs { $_[0]->new(rel2abs ${$_[0]}) }
 
 sub to_array { [splitdir ${shift()}] }
@@ -174,7 +184,18 @@
 L<File::Temp>.
 
   # Longer version
-  my $path = Mojo::File->new(File::Temp->newdir('tempXXXXX'));
+  my $path = path(File::Temp->newdir('tempXXXXX'));
+
+=head2 tempfile
+
+  my $path = tempfile;
+  my $path = tempfile(DIR => '/tmp');
+
+Construct a new scalar-based L<Mojo::File> object for a temporary file with
+L<File::Temp>.
+
+  # Longer version
+  my $path = path(File::Temp->new(DIR => '/tmp'));
 
 =head1 METHODS
 
@@ -188,10 +209,10 @@
 Return the last level of the path with L<File::Basename>.
 
   # ".vimrc" (on UNIX)
-  Mojo::File->new('/home/sri/.vimrc')->basename;
+  path('/home/sri/.vimrc')->basename;
 
   # "test" (on UNIX)
-  Mojo::File->new('/home/sri/test.txt')->basename('.txt');
+  path('/home/sri/test.txt')->basename('.txt');
 
 =head2 child
 
@@ -200,7 +221,7 @@
 Return a new L<Mojo::File> object relative to the path.
 
   # "/home/sri/.vimrc" (on UNIX)
-  Mojo::File->new('/home')->child('sri', '.vimrc');
+  path('/home')->child('sri', '.vimrc');
 
 =head2 dirname
 
@@ -210,7 +231,7 @@
 L<Mojo::File> object.
 
   # "/home/sri" (on UNIX)
-  Mojo::File->new('/home/sri/.vimrc')->dirname;
+  path('/home/sri/.vimrc')->dirname;
 
 =head2 is_abs
 
@@ -219,10 +240,10 @@
 Check if the path is absolute.
 
   # True (on UNIX)
-  Mojo::File->new('/home/sri/.vimrc')->is_abs;
+  path('/home/sri/.vimrc')->is_abs;
 
   # False (on UNIX)
-  Mojo::File->new('.vimrc')->is_abs;
+  path('.vimrc')->is_abs;
 
 =head2 list
 
@@ -234,7 +255,7 @@
 and C<..>.
 
   # List files
-  say for Mojo::File->new('/home/sri/myapp')->list->each;
+  say for path('/home/sri/myapp')->list->each;
 
 These options are currently available:
 
@@ -264,7 +285,7 @@
 include C<.> and C<..>.
 
   # List all templates
-  say for Mojo::File->new('/home/sri/myapp/templates')->list_tree->each;
+  say for path('/home/sri/myapp/templates')->list_tree->each;
 
 These options are currently available:
 
@@ -281,8 +302,10 @@
 =head2 make_path
 
   $path = $path->make_path;
+  $path = $path->make_path({mode => 0711});
 
-Create the directories if they don't already exist with L<File::Path>.
+Create the directories if they don't already exist, any additional arguments 
are
+passed through to L<File::Path>.
 
 =head2 move_to
 
@@ -295,6 +318,7 @@
   my $path = Mojo::File->new;
   my $path = Mojo::File->new('/home/sri/.vimrc');
   my $path = Mojo::File->new('/home', 'sri', '.vimrc');
+  my $path = Mojo::File->new(File::Temp->new);
   my $path = Mojo::File->new(File::Temp->newdir);
 
 Construct a new L<Mojo::File> object, defaults to using the current working
@@ -303,12 +327,26 @@
   # "foo/bar/baz.txt" (on UNIX)
   Mojo::File->new('foo', 'bar', 'baz.txt');
 
+=head2 open
+
+  my $handle = $path->open('+<');
+  my $handle = $path->open('r+');
+  my $handle = $path->open(O_RDWR);
+  my $handle = $path->open('<:encoding(UTF-8)');
+
+Open file with L<IO::File>.
+
+  # Combine "fcntl.h" constants
+  use Fcntl qw(O_CREAT O_EXCL O_RDWR);
+  my $handle = path('/home/sri/test.pl')->open(O_RDWR | O_CREAT | O_EXCL);
+
 =head2 remove_tree
 
   $path = $path->remove_tree;
+  $path = $path->remove_tree({keep_root => 1});
 
-Delete this directory and any files and subdirectories it may contain with
-L<File::Path>.
+Delete this directory and any files and subdirectories it may contain, any
+additional arguments are passed through to L<File::Path>.
 
 =head2 slurp
 
@@ -342,7 +380,7 @@
 Split the path on directory separators.
 
   # "home:sri:.vimrc" (on UNIX)
-  join ':', @{Mojo::File->new('/home/sri/.vimrc')->to_array};
+  join ':', @{path('/home/sri/.vimrc')->to_array};
 
 =head2 to_rel
 
@@ -352,7 +390,7 @@
 L<Mojo::File> object.
 
   # "sri/.vimrc" (on UNIX)
-  Mojo::File->new('/home/sri/.vimrc')->to_rel('/home');
+  path('/home/sri/.vimrc')->to_rel('/home');
 
 =head2 to_string
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo/IOLoop/Stream.pm 
new/Mojolicious-7.25/lib/Mojo/IOLoop/Stream.pm
--- old/Mojolicious-7.23/lib/Mojo/IOLoop/Stream.pm      2017-01-29 
22:33:08.000000000 +0100
+++ new/Mojolicious-7.25/lib/Mojo/IOLoop/Stream.pm      2017-02-09 
22:29:46.000000000 +0100
@@ -8,6 +8,8 @@
 
 has reactor => sub { Mojo::IOLoop->singleton->reactor };
 
+sub DESTROY { Mojo::Util::_global_destruction() or shift->close }
+
 sub close {
   my $self = shift;
   return unless my $reactor = $self->reactor;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo/JSON/Pointer.pm 
new/Mojolicious-7.25/lib/Mojo/JSON/Pointer.pm
--- old/Mojolicious-7.23/lib/Mojo/JSON/Pointer.pm       2016-07-19 
02:38:18.000000000 +0200
+++ new/Mojolicious-7.25/lib/Mojo/JSON/Pointer.pm       2017-02-09 
19:35:36.000000000 +0100
@@ -50,7 +50,7 @@
 
 =head1 DESCRIPTION
 
-L<Mojo::JSON::Pointer> is a relaxed implementation of
+L<Mojo::JSON::Pointer> is an implementation of
 L<RFC 6901|http://tools.ietf.org/html/rfc6901>.
 
 =head1 ATTRIBUTES
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo/Log.pm 
new/Mojolicious-7.25/lib/Mojo/Log.pm
--- old/Mojolicious-7.23/lib/Mojo/Log.pm        2017-01-26 00:07:47.000000000 
+0100
+++ new/Mojolicious-7.25/lib/Mojo/Log.pm        2017-02-05 16:58:14.000000000 
+0100
@@ -3,6 +3,7 @@
 
 use Carp 'croak';
 use Fcntl ':flock';
+use Mojo::File;
 use Mojo::Util 'encode';
 
 has format => sub { \&_format };
@@ -12,8 +13,7 @@
   return \*STDERR unless my $path = shift->path;
 
   # File
-  croak qq{Can't open log file "$path": $!} unless open my $file, '>>', $path;
-  return $file;
+  return Mojo::File->new($path)->open('>>');
 };
 has history => sub { [] };
 has level => 'debug';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo/UserAgent.pm 
new/Mojolicious-7.25/lib/Mojo/UserAgent.pm
--- old/Mojolicious-7.23/lib/Mojo/UserAgent.pm  2017-01-29 22:33:08.000000000 
+0100
+++ new/Mojolicious-7.25/lib/Mojo/UserAgent.pm  2017-02-09 16:06:55.000000000 
+0100
@@ -340,29 +340,29 @@
 
   use Mojo::UserAgent;
 
-  # Say hello to the Unicode snowman and include an Accept header
-  my $ua = Mojo::UserAgent->new;
-  say $ua->get('www.☃.net?hello=there' => {Accept => '*/*'})->res->body;
-
   # Fine grained response handling (dies on connection errors)
+  my $ua  = Mojo::UserAgent->new;
   my $res = $ua->get('mojolicious.org/perldoc')->result;
   if    ($res->is_success)  { say $res->body }
   elsif ($res->is_error)    { say $res->message }
   elsif ($res->code == 301) { say $res->headers->location }
   else                      { say 'Whatever...' }
 
+  # Say hello to the Unicode snowman and include an Accept header
+  say $ua->get('www.☃.net?hello=there' => {Accept => '*/*'})->result->body;
+
   # Extract data from HTML and XML resources with CSS selectors
-  say $ua->get('www.perl.org')->res->dom->at('title')->text;
+  say $ua->get('www.perl.org')->result->dom->at('title')->text;
 
   # Scrape the latest headlines from a news site
   say $ua->get('blogs.perl.org')
-    ->res->dom->find('h2 > a')->map('text')->join("\n");
+    ->result->dom->find('h2 > a')->map('text')->join("\n");
 
   # IPv6 PUT request with Content-Type header and content
   my $tx = $ua->put('[::1]:3000' => {'Content-Type' => 'text/plain'} => 'Hi!');
 
   # Quick JSON API request with Basic authentication
-  my $value = $ua->get('https://sri:[email protected]/test.json')->res->json;
+  my $value = $ua->get('https://sri:[email protected]/test.json')->result->json;
 
   # JSON POST (application/json) with TLS certificate authentication
   my $tx = $ua->cert('tls.crt')->key('tls.key')
@@ -371,12 +371,12 @@
   # Search DuckDuckGo anonymously through Tor
   $ua->proxy->http('socks://127.0.0.1:9050');
   say $ua->get('api.3g2upl4pq6kufc4m.onion/?q=mojolicious&format=json')
-    ->res->json('/Abstract');
+    ->result->json('/Abstract');
 
   # Follow redirects to download Mojolicious from GitHub
   $ua->max_redirects(5)
     ->get('https://www.github.com/kraih/mojo/tarball/master')
-    ->res->content->asset->move_to('/home/sri/mojo.tar.gz');
+    ->result->content->asset->move_to('/home/sri/mojo.tar.gz');
 
   # Form POST (application/x-www-form-urlencoded) with manual exception 
handling
   my $tx = $ua->post('https://metacpan.org/search' => form => {q => 'mojo'});
@@ -390,7 +390,7 @@
   # Non-blocking request
   $ua->get('mojolicious.org' => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->dom->at('title')->text;
+    say $tx->result->dom->at('title')->text;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -403,8 +403,8 @@
     },
     sub {
       my ($delay, $mojo, $cpan) = @_;
-      say $mojo->res->dom->at('title')->text;
-      say $cpan->res->dom->at('title')->text;
+      say $mojo->result->dom->at('title')->text;
+      say $cpan->result->dom->at('title')->text;
     }
   )->wait;
 
@@ -631,7 +631,7 @@
     my $c = shift;
     $c->render(json => {now => time});
   });
-  my $time = $ua->get('/time')->res->json->{now};
+  my $time = $ua->get('/time')->result->json->{now};
 
   # Change log level
   $ua->server->app->log->level('fatal');
@@ -729,7 +729,7 @@
 
   $ua->delete('http://example.com' => json => {a => 'b'} => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -749,7 +749,7 @@
 
   $ua->get('http://example.com' => json => {a => 'b'} => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -769,7 +769,7 @@
 
   $ua->head('http://example.com' => json => {a => 'b'} => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -789,7 +789,7 @@
 
   $ua->options('http://example.com' => json => {a => 'b'} => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -809,7 +809,7 @@
 
   $ua->patch('http://example.com' => json => {a => 'b'} => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -829,7 +829,7 @@
 
   $ua->post('http://example.com' => json => {a => 'b'} => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -849,7 +849,7 @@
 
   $ua->put('http://example.com' => json => {a => 'b'} => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
@@ -864,7 +864,7 @@
   my $tx = $ua->build_tx(GET => 'http://example.com');
   $ua->start($tx => sub {
     my ($ua, $tx) = @_;
-    say $tx->res->body;
+    say $tx->result->body;
   });
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojo.pm 
new/Mojolicious-7.25/lib/Mojo.pm
--- old/Mojolicious-7.23/lib/Mojo.pm    2017-01-09 18:47:43.000000000 +0100
+++ new/Mojolicious-7.25/lib/Mojo.pm    2017-01-30 22:51:48.000000000 +0100
@@ -100,7 +100,7 @@
 L<Mojo::UserAgent> object.
 
   # Perform blocking request
-  say $app->ua->get('example.com')->res->body;
+  say $app->ua->get('example.com')->result->body;
 
 =head1 METHODS
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojolicious/Command/eval.pm 
new/Mojolicious-7.25/lib/Mojolicious/Command/eval.pm
--- old/Mojolicious-7.23/lib/Mojolicious/Command/eval.pm        2017-01-19 
11:06:12.000000000 +0100
+++ new/Mojolicious-7.25/lib/Mojolicious/Command/eval.pm        2017-01-30 
22:51:20.000000000 +0100
@@ -32,7 +32,7 @@
 
   Usage: APPLICATION eval [OPTIONS] CODE
 
-    ./myapp.pl eval 'say app->ua->get("/")->res->body'
+    ./myapp.pl eval 'say app->ua->get("/")->result->body'
     ./myapp.pl eval 'say for sort keys %{app->renderer->helpers}'
     ./myapp.pl eval -v 'app->home'
     ./myapp.pl eval -V 'app->renderer->paths'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojolicious/Command/version.pm 
new/Mojolicious-7.25/lib/Mojolicious/Command/version.pm
--- old/Mojolicious-7.23/lib/Mojolicious/Command/version.pm     2017-01-19 
11:06:12.000000000 +0100
+++ new/Mojolicious-7.25/lib/Mojolicious/Command/version.pm     2017-02-09 
19:15:42.000000000 +0100
@@ -33,7 +33,7 @@
   # Check latest version on CPAN
   my $latest = eval {
     $self->app->ua->max_redirects(10)->tap(sub { $_->proxy->detect })
-      ->get('api.metacpan.org/v0/release/Mojolicious')->res->json->{version};
+      
->get('api.metacpan.org/v0/release/Mojolicious')->result->json->{version};
   } or return;
 
   my $msg = 'This version is up to date, have fun!';
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojolicious/Guides/Cookbook.pod 
new/Mojolicious-7.25/lib/Mojolicious/Guides/Cookbook.pod
--- old/Mojolicious-7.23/lib/Mojolicious/Guides/Cookbook.pod    2017-01-29 
22:33:08.000000000 +0100
+++ new/Mojolicious-7.25/lib/Mojolicious/Guides/Cookbook.pod    2017-02-09 
22:05:57.000000000 +0100
@@ -451,7 +451,7 @@
     my $c = shift;
     $c->ua->get('api.metacpan.org/v0/module/_search?q=mojolicious' => sub {
       my ($ua, $tx) = @_;
-      $c->render('metacpan', hits => $tx->res->json->{hits}{hits});
+      $c->render('metacpan', hits => $tx->result->json->{hits}{hits});
     });
   };
 
@@ -503,8 +503,8 @@
       sub {
         my ($delay, $mojo, $minion) = @_;
         $c->render(json => {
-          mojo   => $mojo->res->json('/hits/hits/0/_source/release'),
-          minion => $minion->res->json('/hits/hits/0/_source/release')
+          mojo   => $mojo->result->json('/hits/hits/0/_source/release'),
+          minion => $minion->result->json('/hits/hits/0/_source/release')
         });
       }
     );
@@ -572,7 +572,7 @@
   Mojo::IOLoop->recurring(10 => sub {
     app->ua->get('http://mojolicious.org' => sub {
       my ($ua, $tx) = @_;
-      $title = $tx->res->dom->at('title')->text;
+      $title = $tx->result->dom->at('title')->text;
     });
   });
 
@@ -833,7 +833,7 @@
 
 L<Mojolicious> contains a very sophisticated event system based on
 L<Mojo::EventEmitter>, with ready-to-use events on almost all layers, and which
-can be combined to solve some of hardest problems in web development.
+can be combined to solve some of the hardest problems in web development.
 
   use Mojolicious::Lite;
   use Scalar::Util 'weaken';
@@ -923,7 +923,7 @@
   my $ua = Mojo::UserAgent->new;
   $ua->get('api.metacpan.org/v0/module/_search?q=mojolicious' => sub {
     my ($ua, $tx) = @_;
-    $cv->send($tx->res->json('/hits/hits/0/_source/release'));
+    $cv->send($tx->result->json('/hits/hits/0/_source/release'));
   });
   say $cv->recv;
 
@@ -990,16 +990,16 @@
 
   # Fetch website
   my $ua = Mojo::UserAgent->new;
-  my $tx = $ua->get('mojolicious.org/perldoc');
+  my $res = $ua->get('mojolicious.org/perldoc')->result;
 
   # Extract title
-  say 'Title: ', $tx->res->dom->at('head > title')->text;
+  say 'Title: ', $res->dom->at('head > title')->text;
 
   # Extract headings
-  $tx->res->dom('h1, h2, h3')->each(sub { say 'Heading: ', shift->all_text });
+  $res->dom('h1, h2, h3')->each(sub { say 'Heading: ', shift->all_text });
 
   # Visit all nodes recursively to extract more than just text
-  for my $n ($tx->res->dom->descendant_nodes->each) {
+  for my $n ($res->dom->descendant_nodes->each) {
 
     # Text or CDATA node
     print $n->content if $n->type eq 'text' || $n->type eq 'cdata';
@@ -1026,7 +1026,7 @@
   # Search MetaCPAN for "mojolicious" and list latest releases
   my $url = Mojo::URL->new('http://api.metacpan.org/v0/release/_search');
   $url->query({q => 'mojolicious', sort => 'date:desc'});
-  for my $hit (@{$ua->get($url)->res->json->{hits}{hits}}) {
+  for my $hit (@{$ua->get($url)->result->json->{hits}{hits}}) {
     say "$hit->{_source}{name} ($hit->{_source}{author})";
   }
 
@@ -1038,7 +1038,7 @@
   use Mojo::UserAgent;
 
   my $ua = Mojo::UserAgent->new;
-  say $ua->get('https://sri:[email protected]/hideout')->res->body;
+  say $ua->get('https://sri:[email protected]/hideout')->result->body;
 
 =head2 Decorating follow-up requests
 
@@ -1060,7 +1060,7 @@
   });
 
   # Request that will most likely get redirected
-  say 'Title: ', $ua->get('google.com')->res->dom->at('head > title')->text;
+  say 'Title: ', $ua->get('google.com')->result->dom->at('head > title')->text;
 
 This even works for proxy C<CONNECT> requests.
 
@@ -1117,7 +1117,7 @@
   # Fetch the latest Mojolicious tarball
   my $ua = Mojo::UserAgent->new(max_redirects => 5);
   my $tx = $ua->get('https://www.github.com/kraih/mojo/tarball/master');
-  $tx->res->content->asset->move_to('mojo.tar.gz');
+  $tx->result->content->asset->move_to('mojo.tar.gz');
 
 To protect you from excessively large files there is also a limit of 2GB by
 default, which you can tweak with the attribute
@@ -1210,17 +1210,59 @@
   my $ua = Mojo::UserAgent->new;
   $ua->get('http://metacpan.org/search?q=mojo' => sub {
     my ($ua, $mojo) = @_;
-    say $mojo->res->dom->at('title')->text;
+    say $mojo->result->dom->at('title')->text;
   });
   $ua->get('http://metacpan.org/search?q=minion' => sub {
     my ($ua, $minion) = @_;
-    say $minion->res->dom->at('title')->text;
+    say $minion->result->dom->at('title')->text;
   });
 
   # Start event loop if necessary
   Mojo::IOLoop->start unless Mojo::IOLoop->is_running;
 
-You can take full control of the L<Mojo::IOLoop> event loop.
+But don't try to open too many connections to one server at the same time, it
+might get overwhelmed. Better use a queue to process requests in smaller
+batches.
+
+  use Mojo::UserAgent;
+  use Mojo::IOLoop;
+
+  my @urls = (
+    'mojolicious.org/perldoc/Mojo/DOM',  'mojolicious.org/perldoc/Mojo',
+    'mojolicious.org/perldoc/Mojo/File', 'mojolicious.org/perldoc/Mojo/URL'
+  );
+
+  # User agent with a custom name, following up to 5 redirects
+  my $ua = Mojo::UserAgent->new(max_redirects => 5);
+  $ua->transactor->name('MyParallelCrawler 1.0');
+
+  # Use a delay to keep the event loop running until we are done
+  my $delay = Mojo::IOLoop->delay;
+  my $fetch;
+  $fetch = sub {
+
+    # Stop if there are no more URLs
+    return unless my $url = shift @urls;
+
+    # Fetch the next title
+    my $end = $delay->begin;
+    $ua->get($url => sub {
+      my ($ua, $tx) = @_;
+      say "$url: ", $tx->result->dom->at('title')->text;
+      $end->();
+
+      # Next request
+      $fetch->();
+    });
+  };
+
+  # Process two requests at a time
+  $fetch->() for 1 .. 2;
+  $delay->wait;
+
+It is also strongly recommended to respect every sites C<robots.txt> file as
+well as terms of service, and to wait a little before reopening connections to
+the same host, or the operators might be forced to block your access.
 
 =head2 Concurrent blocking requests
 
@@ -1234,8 +1276,8 @@
   my $ua    = Mojo::UserAgent->new;
   my $delay = Mojo::IOLoop->delay(sub {
     my ($delay, $mojo, $minion) = @_;
-    say $mojo->res->dom->at('title')->text;
-    say $minion->res->dom->at('title')->text;
+    say $mojo->result->dom->at('title')->text;
+    say $minion->result->dom->at('title')->text;
   });
   $ua->get('http://metacpan.org/search?q=mojo'   => $delay->begin);
   $ua->get('http://metacpan.org/search?q=minion' => $delay->begin);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Mojolicious-7.23/lib/Mojolicious/Guides/Rendering.pod 
new/Mojolicious-7.25/lib/Mojolicious/Guides/Rendering.pod
--- old/Mojolicious-7.23/lib/Mojolicious/Guides/Rendering.pod   2017-01-20 
21:17:54.000000000 +0100
+++ new/Mojolicious-7.25/lib/Mojolicious/Guides/Rendering.pod   2017-02-04 
12:38:21.000000000 +0100
@@ -333,10 +333,6 @@
     Minion is a <%= $spinoffs->{minion} %>.
   % }
 
-Just be aware that too many optional stash values will make templates less
-cacheable, which can reduce performance. So passing an C<undef> value to the
-stash, instead of making it optional, is always preferable.
-
 =head2 Helpers
 
 Helpers are little functions you can use in templates as well as application
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojolicious/Guides/Routing.pod 
new/Mojolicious-7.25/lib/Mojolicious/Guides/Routing.pod
--- old/Mojolicious-7.23/lib/Mojolicious/Guides/Routing.pod     2016-08-15 
10:32:23.000000000 +0200
+++ new/Mojolicious-7.25/lib/Mojolicious/Guides/Routing.pod     2017-01-30 
20:51:27.000000000 +0100
@@ -886,21 +886,36 @@
 true value for the route to match.
 
   # A condition that randomly allows a route to match
-  $r->add_condition(
-    random => sub {
-      my ($route, $c, $captures, $num) = @_;
+  $r->add_condition(random => sub {
+    my ($route, $c, $captures, $num) = @_;
 
-      # Loser
-      return undef if int rand $num;
+    # Loser
+    return undef if int rand $num;
 
-      # Winner
-      return 1;
-    }
-  );
+    # Winner
+    return 1;
+  });
 
   # /maybe (25% chance)
   $r->get('/maybe')->over(random => 4)->to('foo#bar');
 
+Use whatever request information you need.
+
+  # A condition to check query parameters (useful for mock web services)
+  $r->add_condition(query => sub {
+    my ($route, $c, $captures, $hash) = @_;
+
+    for my $key (keys %$hash) {
+      my $param = $c->req->url->query->param($key);
+      return undef unless defined $param && $param eq $hash->{$key};
+    }
+
+    return 1;
+  });
+
+  # /hello?to=world&test=1
+  $r->get('/hello')->over(query => {test => 1, to => 'world'})->to('foo#bar');
+
 =head2 Condition plugins
 
 You can also package your conditions as reusable plugins.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojolicious/Guides/Tutorial.pod 
new/Mojolicious-7.25/lib/Mojolicious/Guides/Tutorial.pod
--- old/Mojolicious-7.23/lib/Mojolicious/Guides/Tutorial.pod    2017-01-29 
22:33:08.000000000 +0100
+++ new/Mojolicious-7.25/lib/Mojolicious/Guides/Tutorial.pod    2017-01-30 
22:49:14.000000000 +0100
@@ -852,7 +852,7 @@
   get '/headers' => sub {
     my $c   = shift;
     my $url = $c->param('url') || 'http://mojolicious.org';
-    my $dom = $c->ua->get($url)->res->dom;
+    my $dom = $c->ua->get($url)->result->dom;
     $c->render(json => $dom->find('h1, h2, h3')->map('text')->to_array);
   };
 
@@ -861,7 +861,7 @@
     my $c = shift;
     $c->ua->get('mojolicious.org' => sub {
       my ($ua, $tx) = @_;
-      $c->render(data => $tx->res->dom->at('title')->text);
+      $c->render(data => $tx->result->dom->at('title')->text);
     });
   };
 
@@ -877,8 +877,8 @@
       sub {
         my ($delay, $mojo, $cpan) = @_;
         $c->render(json => {
-          mojo => $mojo->res->dom->at('title')->text,
-          cpan => $cpan->res->dom->at('title')->text
+          mojo => $mojo->result->dom->at('title')->text,
+          cpan => $cpan->result->dom->at('title')->text
         });
       }
     );
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/Mojolicious-7.23/lib/Mojolicious/Plugin/DefaultHelpers.pm 
new/Mojolicious-7.25/lib/Mojolicious/Plugin/DefaultHelpers.pm
--- old/Mojolicious-7.23/lib/Mojolicious/Plugin/DefaultHelpers.pm       
2016-07-19 02:38:18.000000000 +0200
+++ new/Mojolicious-7.25/lib/Mojolicious/Plugin/DefaultHelpers.pm       
2017-01-30 22:48:37.000000000 +0100
@@ -324,7 +324,7 @@
     },
     sub {
       my ($delay, $tx) = @_;
-      $c->render(json => {title => $tx->res->dom->at('title')->text});
+      $c->render(json => {title => $tx->result->dom->at('title')->text});
     }
   );
 
@@ -474,7 +474,7 @@
 
 =head2 ua
 
-  %= ua->get('mojolicious.org')->res->dom->at('title')->text
+  %= ua->get('mojolicious.org')->result->dom->at('title')->text
 
 Alias for L<Mojo/"ua">.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/lib/Mojolicious.pm 
new/Mojolicious-7.25/lib/Mojolicious.pm
--- old/Mojolicious-7.23/lib/Mojolicious.pm     2017-01-29 22:33:08.000000000 
+0100
+++ new/Mojolicious-7.25/lib/Mojolicious.pm     2017-02-05 22:09:51.000000000 
+0100
@@ -58,7 +58,7 @@
 has validator => sub { Mojolicious::Validator->new };
 
 our $CODENAME = 'Doughnut';
-our $VERSION  = '7.23';
+our $VERSION  = '7.25';
 
 sub AUTOLOAD {
   my $self = shift;
@@ -791,10 +791,6 @@
 
 =over 2
 
-Abhijit Menon-Sen, C<[email protected]>
-
-Glen Hinkle, C<[email protected]>
-
 Jan Henning Thorsen, C<[email protected]>
 
 Joel Berger, C<[email protected]>
@@ -803,6 +799,16 @@
 
 =back
 
+The following members of the core team are currently on hiatus:
+
+=over 2
+
+Abhijit Menon-Sen, C<[email protected]>
+
+Glen Hinkle, C<[email protected]>
+
+=back
+
 =head1 CREDITS
 
 In alphabetical order:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Mojolicious-7.23/t/mojo/file.t 
new/Mojolicious-7.25/t/mojo/file.t
--- old/Mojolicious-7.23/t/mojo/file.t  2017-01-25 21:21:12.000000000 +0100
+++ new/Mojolicious-7.25/t/mojo/file.t  2017-02-05 12:22:59.000000000 +0100
@@ -2,10 +2,12 @@
 
 use Test::More;
 use Cwd 'getcwd';
+use Fcntl 'O_RDONLY';
 use File::Basename qw(basename dirname);
 use File::Spec::Functions qw(abs2rel canonpath catfile rel2abs splitdir);
 use File::Temp;
-use Mojo::File qw(path tempdir);
+use Mojo::File qw(path tempdir tempfile);
+use Mojo::Util 'encode';
 
 # Constructor
 is(Mojo::File->new, canonpath(getcwd), 'same path');
@@ -64,18 +66,49 @@
 undef $dir;
 ok !-d $path, 'directory does not exist anymore';
 
+# Temporary file
+$dir = tempdir;
+my $file = tempfile(DIR => $dir);
+$path = "$file";
+ok -f $path, 'file exists';
+is $file->dirname, $dir, 'same directory';
+is $file->spurt('test')->slurp, 'test', 'right result';
+undef $file;
+ok !-f $path, 'file does not exist anymore';
+
+# Open
+$file = tempfile;
+$file->spurt("test\n123\n");
+my $handle = $file->open('<');
+is_deeply [<$handle>], ["test\n", "123\n"], 'right structure';
+$handle = $file->open('r');
+is_deeply [<$handle>], ["test\n", "123\n"], 'right structure';
+$handle = $file->open(O_RDONLY);
+is_deeply [<$handle>], ["test\n", "123\n"], 'right structure';
+$file->spurt(encode('UTF-8', '♥'));
+$handle = $file->open('<:encoding(UTF-8)');
+is_deeply [<$handle>], ['♥'], 'right structure';
+
 # Make path
 $dir = tempdir;
 my $subdir = $dir->child('foo', 'bar');
 ok !-d $subdir, 'directory does not exist anymore';
 $subdir->make_path;
 ok -d $subdir, 'directory exists';
+my $nextdir = $dir->child('foo', 'foobar')->make_path({error => \my $error});
+ok -d $nextdir, 'directory exists';
+ok $error, 'directory already existed';
 
 # Remove tree
 $dir = tempdir;
 $dir->child('foo', 'bar')->make_path->child('test.txt')->spurt('test!');
 is $dir->child('foo', 'bar', 'test.txt')->slurp, 'test!', 'right content';
-ok !-e $dir->child('foo')->remove_tree->to_string, 'tree has been removed';
+$subdir = $dir->child('foo', 'foobar')->make_path;
+ok -e $subdir->child('bar')->make_path->child('test.txt')->spurt('test'),
+  'file created';
+ok -d $subdir->remove_tree({keep_root => 1}), 'directory still exists';
+ok !-e $subdir->child('bar'), 'children have been removed';
+ok !-e $dir->child('foo')->remove_tree->to_string, 'directory has been 
removed';
 
 # Move to
 $dir = tempdir;
@@ -126,8 +159,8 @@
   [@hidden, @files], 'right files';
 
 # I/O
-$dir = tempdir;
-my $file = $dir->child('test.txt')->spurt('just works!');
+$dir  = tempdir;
+$file = $dir->child('test.txt')->spurt('just works!');
 is $file->slurp, 'just works!', 'right content';
 is $file->spurt('w', 'orks', ' too!')->slurp, 'works too!', 'right content';
 {


Reply via email to