File tree 3 files changed +22
-2
lines changed
3 files changed +22
-2
lines changed Original file line number Diff line number Diff line change @@ -79,6 +79,12 @@ def get_localhost() -> Literal["::1", "127.0.0.1"]:
79
79
raise
80
80
81
81
82
+ @public
83
+ def is_unspecified_address (address : str ) -> bool :
84
+ unspecified_address_list = [None , '' , '0.0.0.0' , '::' ]
85
+ return address in unspecified_address_list
86
+
87
+
82
88
class _FakeServer (asyncio .StreamReaderProtocol ):
83
89
"""
84
90
Returned by _factory_invoker() in lieu of an SMTP instance in case
@@ -421,7 +427,7 @@ def _trigger_server(self):
421
427
"""
422
428
# At this point, if self.hostname is Falsy, it most likely is "" (bind to all
423
429
# addresses). In such case, it should be safe to connect to localhost)
424
- hostname = self .hostname or self ._localhost
430
+ hostname = self ._localhost if is_unspecified_address ( self . hostname ) is True else self .hostname
425
431
with ExitStack () as stk :
426
432
s = stk .enter_context (create_connection ((hostname , self .port ), 1.0 ))
427
433
if self .ssl_context :
Original file line number Diff line number Diff line change @@ -14,7 +14,7 @@ Fixed/Improved
14
14
--------------
15
15
* All Controllers now have more rationale design, as they are now composited from a Base + a Mixin
16
16
* A whole bunch of annotations
17
-
17
+ * Fix bind unspecified address controller will raise TimeoutError
18
18
19
19
1.4.2 (2021-03-08)
20
20
=====================
Original file line number Diff line number Diff line change 28
28
UnixSocketUnthreadedController ,
29
29
_FakeServer ,
30
30
get_localhost ,
31
+ is_unspecified_address ,
31
32
)
32
33
from aiosmtpd .handlers import Sink
33
34
from aiosmtpd .smtp import SMTP as Server
@@ -292,6 +293,13 @@ def test_hostname_none(self):
292
293
cont .start ()
293
294
finally :
294
295
cont .stop ()
296
+
297
+ def test_hostname_unspecified (self ):
298
+ cont = Controller (Sink (), hostname = "0.0.0.0" )
299
+ try :
300
+ cont .start ()
301
+ finally :
302
+ cont .stop ()
295
303
296
304
def test_testconn_raises (self , mocker : MockFixture ):
297
305
mocker .patch ("socket.socket.recv" , side_effect = RuntimeError ("MockError" ))
@@ -347,6 +355,12 @@ def test_getlocalhost_error(self, mocker):
347
355
assert exc .value .errno == errno .EFAULT
348
356
mock_makesock .assert_called_with (socket .AF_INET6 , socket .SOCK_STREAM )
349
357
358
+ def test_is_unspecified_address (self ):
359
+ assert is_unspecified_address ("127.0.0.1" ) is False
360
+ assert is_unspecified_address ("0.0.0.0" ) is True
361
+ assert is_unspecified_address ("::" ) is True
362
+ assert is_unspecified_address ("" ) is True
363
+
350
364
def test_stop_default (self ):
351
365
controller = Controller (Sink ())
352
366
with pytest .raises (AssertionError , match = "SMTP daemon not running" ):
You can’t perform that action at this time.
0 commit comments