Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-ZEO for openSUSE:Factory 
checked in at 2022-08-30 14:49:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ZEO (Old)
 and      /work/SRC/openSUSE:Factory/.python-ZEO.new.2083 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-ZEO"

Tue Aug 30 14:49:59 2022 rev:14 rq:1000118 version:5.3.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ZEO/python-ZEO.changes    2022-02-28 
19:44:28.109961516 +0100
+++ /work/SRC/openSUSE:Factory/.python-ZEO.new.2083/python-ZEO.changes  
2022-08-30 14:50:46.720319247 +0200
@@ -1,0 +2,11 @@
+Mon Aug 29 14:52:35 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com>
+
+- update to 5.3.0 
+  * Remove tests for the asyncio/mtacceptor module, it appears unused and 
presents a maintenance
+    burden. The module will be removed in ZEO version 6.
+  * Remove GitHub Actions testing for Python 3.5, it has reached end of life.
+  * Add support for Python 3.8 and Python 3.9.
+  * Add more accurate error handling for asyncio.CancelledError. See issue 165.
+  * Fix bug related to blobs stored by ZEO #150.
+
+-------------------------------------------------------------------

Old:
----
  ZEO-5.2.3.tar.gz

New:
----
  ZEO-5.3.0.tar.gz

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

Other differences:
------------------
++++++ python-ZEO.spec ++++++
--- /var/tmp/diff_new_pack.Z35dEa/_old  2022-08-30 14:50:47.284320687 +0200
+++ /var/tmp/diff_new_pack.Z35dEa/_new  2022-08-30 14:50:47.288320697 +0200
@@ -20,7 +20,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %bcond_without python2
 Name:           python-ZEO
-Version:        5.2.3
+Version:        5.3.0
 Release:        0
 Summary:        Client-Server storage implementation for ZODB
 License:        ZPL-2.1

++++++ ZEO-5.2.3.tar.gz -> ZEO-5.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/CHANGES.rst new/ZEO-5.3.0/CHANGES.rst
--- old/ZEO-5.2.3/CHANGES.rst   2021-08-09 14:01:12.000000000 +0200
+++ new/ZEO-5.3.0/CHANGES.rst   2022-03-24 09:43:55.000000000 +0100
@@ -1,6 +1,24 @@
 Changelog
 =========
 
+5.3.0 (2022-03-24)
+------------------
+
+- Remove tests for the `asyncio/mtacceptor` module, it appears unused
+  and presents a maintenance burden. The module will be removed in
+  ZEO version 6.
+
+- Remove GitHub Actions testing for Python 3.5, it has reached end of life.
+
+- Add support for Python 3.8 and Python 3.9.
+
+- Add more accurate error handling for ``asyncio.CancelledError``.
+  See `issue 165 <https://github.com/zopefoundation/ZEO/issues/165>`_.
+
+- Fix bug related to blobs stored by ``ZEO``
+  `#150 <https://github.com/zopefoundation/ZEO/issues/150>`_.
+
+
 5.2.3 (2021-08-09)
 ------------------
 
@@ -19,7 +37,6 @@
 - Improve log message when client cache is out of sync with server.
   See `issue 142 <https://github.com/zopefoundation/ZEO/issues/142>`_.
 
-
 5.2.2 (2020-08-11)
 ------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/MANIFEST.in new/ZEO-5.3.0/MANIFEST.in
--- old/ZEO-5.2.3/MANIFEST.in   2020-07-24 12:54:39.000000000 +0200
+++ new/ZEO-5.3.0/MANIFEST.in   2022-03-24 09:44:35.000000000 +0100
@@ -3,7 +3,6 @@
 include *.py
 include buildout.cfg
 include tox.ini
-include .travis.yml
 include COPYING
 include log.ini
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/PKG-INFO new/ZEO-5.3.0/PKG-INFO
--- old/ZEO-5.2.3/PKG-INFO      2021-08-09 14:22:08.221462000 +0200
+++ new/ZEO-5.3.0/PKG-INFO      2022-03-24 09:56:54.481391700 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: ZEO
-Version: 5.2.3
+Version: 5.3.0
 Summary: ZEO - Single-server client-server database server for ZODB
 Home-page: https://github.com/zopefoundation/ZEO
 Author: Zope Foundation and Contributors
@@ -31,6 +31,24 @@
         Changelog
         =========
         
+        5.3.0 (2022-03-24)
+        ------------------
+        
+        - Remove tests for the `asyncio/mtacceptor` module, it appears unused
+          and presents a maintenance burden. The module will be removed in
+          ZEO version 6.
+        
+        - Remove GitHub Actions testing for Python 3.5, it has reached end of 
life.
+        
+        - Add support for Python 3.8 and Python 3.9.
+        
+        - Add more accurate error handling for ``asyncio.CancelledError``.
+          See `issue 165 <https://github.com/zopefoundation/ZEO/issues/165>`_.
+        
+        - Fix bug related to blobs stored by ``ZEO``
+          `#150 <https://github.com/zopefoundation/ZEO/issues/150>`_.
+        
+        
         5.2.3 (2021-08-09)
         ------------------
         
@@ -49,7 +67,6 @@
         - Improve log message when client cache is out of sync with server.
           See `issue 142 <https://github.com/zopefoundation/ZEO/issues/142>`_.
         
-        
         5.2.2 (2020-08-11)
         ------------------
         
@@ -385,6 +402,8 @@
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Database
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/doc/_build/html/_sources/clients.rst.txt 
new/ZEO-5.3.0/doc/_build/html/_sources/clients.rst.txt
--- old/ZEO-5.2.3/doc/_build/html/_sources/clients.rst.txt      2021-04-29 
11:25:16.000000000 +0200
+++ new/ZEO-5.3.0/doc/_build/html/_sources/clients.rst.txt      2021-11-02 
09:52:31.000000000 +0100
@@ -140,7 +140,7 @@
 string like::
 
   <zodb>
-     cache-size-bytes 1000MB
+     cache-size 1000MB
 
      <filestorage>
        path /var/lib/Data.fs
@@ -158,7 +158,7 @@
 into ZODB.  Here's an example::
 
   <zodb>
-     cache-size-bytes 1000MB
+     cache-size 1000MB
 
      %import ZEO
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/doc/clients.rst 
new/ZEO-5.3.0/doc/clients.rst
--- old/ZEO-5.2.3/doc/clients.rst       2021-04-29 11:25:16.000000000 +0200
+++ new/ZEO-5.3.0/doc/clients.rst       2021-11-02 09:52:31.000000000 +0100
@@ -140,7 +140,7 @@
 string like::
 
   <zodb>
-     cache-size-bytes 1000MB
+     cache-size 1000MB
 
      <filestorage>
        path /var/lib/Data.fs
@@ -158,7 +158,7 @@
 into ZODB.  Here's an example::
 
   <zodb>
-     cache-size-bytes 1000MB
+     cache-size 1000MB
 
      %import ZEO
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/setup.py new/ZEO-5.3.0/setup.py
--- old/ZEO-5.2.3/setup.py      2021-08-09 13:58:38.000000000 +0200
+++ new/ZEO-5.3.0/setup.py      2022-03-24 09:44:01.000000000 +0100
@@ -11,7 +11,7 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-version = '5.2.3'
+version = '5.3.0'
 
 from setuptools import setup, find_packages
 import os
@@ -48,6 +48,8 @@
 Programming Language :: Python :: 3.5
 Programming Language :: Python :: 3.6
 Programming Language :: Python :: 3.7
+Programming Language :: Python :: 3.8
+Programming Language :: Python :: 3.9
 Programming Language :: Python :: Implementation :: CPython
 Programming Language :: Python :: Implementation :: PyPy
 Topic :: Database
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO/StorageServer.py 
new/ZEO-5.3.0/src/ZEO/StorageServer.py
--- old/ZEO-5.2.3/src/ZEO/StorageServer.py      2020-08-07 14:17:16.000000000 
+0200
+++ new/ZEO-5.3.0/src/ZEO/StorageServer.py      2022-03-24 09:43:03.000000000 
+0100
@@ -48,7 +48,10 @@
 from ZODB.serialize import referencesf
 from ZODB.utils import oid_repr, p64, u64, z64, Lock, RLock
 
+# BBB mtacceptor is unused and will be removed in ZEO version 6
 if os.environ.get("ZEO_MTACCEPTOR"): # mainly for tests
+    warnings.warn('The mtacceptor module is deprecated and will be removed '
+                  'in ZEO version 6.', DeprecationWarning)
     from .asyncio.mtacceptor import Acceptor
 else:
     from .asyncio.server import Acceptor
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO/asyncio/base.py 
new/ZEO-5.3.0/src/ZEO/asyncio/base.py
--- old/ZEO-5.2.3/src/ZEO/asyncio/base.py       2020-07-24 12:54:39.000000000 
+0200
+++ new/ZEO-5.3.0/src/ZEO/asyncio/base.py       2022-03-16 12:00:21.000000000 
+0100
@@ -77,6 +77,9 @@
             # will be used with blobs, in which case, the individual
             # messages will be big to begin with.
             data = iter(data)
+            if paused:
+                append(data)
+                return
             for message in data:
                 writelines((pack(">I", len(message)), message))
                 if paused:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO/asyncio/client.py 
new/ZEO-5.3.0/src/ZEO/asyncio/client.py
--- old/ZEO-5.2.3/src/ZEO/asyncio/client.py     2021-04-29 11:25:08.000000000 
+0200
+++ new/ZEO-5.3.0/src/ZEO/asyncio/client.py     2022-03-19 18:53:35.000000000 
+0100
@@ -122,19 +122,25 @@
             cr = self.loop.create_unix_connection(
                 self.protocol_factory, self.addr, ssl=self.ssl)
 
+        # an ``asyncio.Future``
         self._connecting = cr = asyncio.ensure_future(cr, loop=self.loop)
 
         @cr.add_done_callback
         def done_connecting(future):
-            if future.exception() is not None:
-                logger.info("Connection to %r failed, retrying, %s",
-                            self.addr, future.exception())
-                # keep trying
-                if not self.closed:
-                    self.loop.call_later(
-                        self.connect_poll + local_random.random(),
-                        self.connect,
-                        )
+            if future.cancelled():
+                logger.info("Connection to %r cancelled", self.addr)
+            elif future.exception() is not None:
+                logger.info("Connection to %r failed, %s",
+                            (self.addr, future.exception()))
+            else: return
+            # keep trying
+            if not self.closed:
+                logger.info("retry connecting %r", self.addr)
+                self.loop.call_later(
+                    self.connect_poll + local_random.random(),
+                    self.connect,
+                    )
+
 
     def connection_made(self, transport):
         super(Protocol, self).connection_made(transport)
@@ -482,10 +488,10 @@
         self.verify_invalidation_queue = [] # See comment in init :(
 
         protocol = self.protocol
-        if server_tid is None:
-            server_tid = yield protocol.fut('lastTransaction')
-
         try:
+            if server_tid is None:
+                server_tid = yield protocol.fut('lastTransaction')
+
             cache = self.cache
             if cache:
                 cache_tid = cache.getLastTid()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO/asyncio/mtacceptor.py 
new/ZEO-5.3.0/src/ZEO/asyncio/mtacceptor.py
--- old/ZEO-5.2.3/src/ZEO/asyncio/mtacceptor.py 2020-07-24 12:54:39.000000000 
+0200
+++ new/ZEO-5.3.0/src/ZEO/asyncio/mtacceptor.py 2022-03-24 09:43:03.000000000 
+0100
@@ -13,6 +13,8 @@
 ##############################################################################
 """Multi-threaded server connectin acceptor
 
+BBB this module is unused and will be removed in ZEO version 6
+
 Each connection is run in it's own thread. Testing serveral years ago
 suggsted that this was a win, but ZODB shootout and another
 lower-level tests suggest otherwise.  It's really unclear, which is
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO/asyncio/tests.py 
new/ZEO-5.3.0/src/ZEO/asyncio/tests.py
--- old/ZEO-5.2.3/src/ZEO/asyncio/tests.py      2021-04-29 11:25:08.000000000 
+0200
+++ new/ZEO-5.3.0/src/ZEO/asyncio/tests.py      2022-03-16 12:00:21.000000000 
+0100
@@ -2,8 +2,12 @@
 
 if PY3:
     import asyncio
+    def to_byte(i):
+        return bytes([i])
 else:
     import trollius as asyncio
+    def to_byte(b):
+        return b
 
 from zope.testing import setupstack
 from concurrent.futures import Future
@@ -18,6 +22,7 @@
 
 from ..Exceptions import ClientDisconnected, ProtocolError
 
+from .base import Protocol
 from .testing import Loop
 from .client import ClientRunner, Fallback
 from .server import new_connection, best_protocol_version
@@ -869,10 +874,33 @@
         logging.getLogger().setLevel(logging.NOTSET)
 
 
+class ProtocolTests(setupstack.TestCase):
+
+    def setUp(self):
+        self.loop = loop = Loop()
+        loop.create_connection(lambda: Protocol(loop, None), sock=True)
+
+    def test_writeit(self):
+        """test https://github.com/zopefoundation/ZEO/issues/150.""";
+        loop = self.loop
+        protocol, transport = loop.protocol, loop.transport
+        transport.capacity = 1  # single message
+        def it(tag):
+            yield tag
+            yield tag
+        protocol._writeit(it(b"0"))
+        protocol._writeit(it(b"1"))
+        for b in b"0011":
+            l, t = transport.pop(2)
+            self.assertEqual(l, b"\x00\x00\x00\x01")
+            self.assertEqual(t, to_byte(b))
+
+
 def test_suite():
     suite = unittest.TestSuite()
     suite.addTest(unittest.makeSuite(ClientTests))
     suite.addTest(unittest.makeSuite(ServerTests))
     suite.addTest(unittest.makeSuite(MsgpackClientTests))
     suite.addTest(unittest.makeSuite(MsgpackServerTests))
+    suite.addTest(unittest.makeSuite(ProtocolTests))
     return suite
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO/runzeo.py 
new/ZEO-5.3.0/src/ZEO/runzeo.py
--- old/ZEO-5.2.3/src/ZEO/runzeo.py     2020-07-24 12:54:39.000000000 +0200
+++ new/ZEO-5.3.0/src/ZEO/runzeo.py     2022-03-19 18:53:35.000000000 +0100
@@ -251,12 +251,18 @@
     def loop_forever(self):
         if self.options.testing_exit_immediately:
             print("testing exit immediately")
+            sys.stdout.flush()  # ensure truthful output order
         else:
             self.server.loop()
 
     def close_server(self):
         if self.server is not None:
             self.server.close()
+            if getattr(self.options, "testing_exit_immediately", False):
+                acceptor = self.server.acceptor
+                if hasattr(acceptor, "event_loop"):
+                    # usually, this happens automatically - but not for testing
+                    acceptor.event_loop.close()
 
     def handle_sigterm(self):
         log("terminated by SIGTERM")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/ZEO-5.2.3/src/ZEO/tests/drop_cache_rather_than_verify.txt 
new/ZEO-5.3.0/src/ZEO/tests/drop_cache_rather_than_verify.txt
--- old/ZEO-5.2.3/src/ZEO/tests/drop_cache_rather_than_verify.txt       
2020-07-24 12:54:40.000000000 +0200
+++ new/ZEO-5.3.0/src/ZEO/tests/drop_cache_rather_than_verify.txt       
2022-03-16 12:02:29.000000000 +0100
@@ -59,7 +59,7 @@
     >>> def event_handler(e):
     ...   if hasattr(e, 'storage'):
     ...     events.append((
-    ...       len(e.storage._server.client.cache), str(handler), 
e.__class__.__name__))
+    ...       len(e.storage._cache), str(handler), e.__class__.__name__))
 
     >>> old_notify = ZODB.event.notify
     >>> ZODB.event.notify = event_handler
@@ -141,7 +141,7 @@
 (When a database is created, it checks to make sure the root object is
 in the database, which is why we get 1, rather than 0 objects in the cache.)
 
-- Publishes a stake-cache event.
+- Publishes a stale-cache event.
 
     >>> for e in events:
     ...     print(e)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO/tests/testZEO.py 
new/ZEO-5.3.0/src/ZEO/tests/testZEO.py
--- old/ZEO-5.2.3/src/ZEO/tests/testZEO.py      2021-04-29 11:25:08.000000000 
+0200
+++ new/ZEO-5.3.0/src/ZEO/tests/testZEO.py      2022-03-19 18:53:35.000000000 
+0100
@@ -1221,7 +1221,7 @@
     """
 
 def runzeo_without_configfile():
-    """
+    r"""
     >>> with open('runzeo', 'w') as r:
     ...     _ = r.write('''
     ... import sys
@@ -1231,10 +1231,13 @@
     ... ''' % sys.path)
 
     >>> import subprocess, re
-    >>> print(re.sub(br'\d\d+|[:]', b'', subprocess.Popen(
+    >>> proc = subprocess.Popen(
     ...     [sys.executable, 'runzeo', '-a:0', '-ft', '--test'],
     ...     stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
-    ...     ).stdout.read()).decode('ascii'))
+    ...     )
+    >>> proc.wait()
+    0
+    >>> print(re.sub(br'\d\d+|[:]', b'', proc.stdout.read()).decode('ascii'))
     ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
     ------
     --T INFO ZEO.runzeo () opening storage '1' using FileStorage
@@ -1242,9 +1245,10 @@
     --T INFO ZEO.StorageServer StorageServer created RW with storages 1RWt
     ------
     --T INFO ZEO.asyncio... listening on ...
+    testing exit immediately
     ------
     --T INFO ZEO.StorageServer closing storage '1'
-    testing exit immediately
+    >>> proc.stdout.close()
     """
 
 def close_client_storage_w_invalidations():
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/src/ZEO.egg-info/PKG-INFO 
new/ZEO-5.3.0/src/ZEO.egg-info/PKG-INFO
--- old/ZEO-5.2.3/src/ZEO.egg-info/PKG-INFO     2021-08-09 14:22:07.000000000 
+0200
+++ new/ZEO-5.3.0/src/ZEO.egg-info/PKG-INFO     2022-03-24 09:56:54.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: ZEO
-Version: 5.2.3
+Version: 5.3.0
 Summary: ZEO - Single-server client-server database server for ZODB
 Home-page: https://github.com/zopefoundation/ZEO
 Author: Zope Foundation and Contributors
@@ -31,6 +31,24 @@
         Changelog
         =========
         
+        5.3.0 (2022-03-24)
+        ------------------
+        
+        - Remove tests for the `asyncio/mtacceptor` module, it appears unused
+          and presents a maintenance burden. The module will be removed in
+          ZEO version 6.
+        
+        - Remove GitHub Actions testing for Python 3.5, it has reached end of 
life.
+        
+        - Add support for Python 3.8 and Python 3.9.
+        
+        - Add more accurate error handling for ``asyncio.CancelledError``.
+          See `issue 165 <https://github.com/zopefoundation/ZEO/issues/165>`_.
+        
+        - Fix bug related to blobs stored by ``ZEO``
+          `#150 <https://github.com/zopefoundation/ZEO/issues/150>`_.
+        
+        
         5.2.3 (2021-08-09)
         ------------------
         
@@ -49,7 +67,6 @@
         - Improve log message when client cache is out of sync with server.
           See `issue 142 <https://github.com/zopefoundation/ZEO/issues/142>`_.
         
-        
         5.2.2 (2020-08-11)
         ------------------
         
@@ -385,6 +402,8 @@
 Classifier: Programming Language :: Python :: 3.5
 Classifier: Programming Language :: Python :: 3.6
 Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: Implementation :: CPython
 Classifier: Programming Language :: Python :: Implementation :: PyPy
 Classifier: Topic :: Database
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/ZEO-5.2.3/tox.ini new/ZEO-5.3.0/tox.ini
--- old/ZEO-5.2.3/tox.ini       2021-04-29 11:25:08.000000000 +0200
+++ new/ZEO-5.3.0/tox.ini       2022-03-24 09:43:03.000000000 +0100
@@ -4,6 +4,8 @@
     py35
     py36
     py37
+    py38
+    py39
     pypy
     pypy3
     simple
@@ -36,20 +38,19 @@
 setenv =
     !py27-!pypy: PYTHONWARNINGS=ignore::ResourceWarning
     msgpack1: ZEO_MSGPACK=1
-    mtacceptor: ZEO_MTACCEPTOR=1
     zeo4: ZEO4_SERVER=1
 
 [testenv:simple]
 # Test that 'setup.py test' works
 basepython =
-    python3.6
+    python3
 commands =
     python setup.py -q test -q
 deps = {[testenv]deps}
 
 [testenv:docs]
 basepython =
-    python3.6
+    python3
 commands =
     sphinx-build -b html doc doc/_build/html
 extras =

Reply via email to