Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
a06c029c
Commit
a06c029c
authored
Jul 29, 2011
by
Benjamin Peterson
Browse files
Options
Browse Files
Download
Plain Diff
merge heads
parents
405f32c1
63d4fb4c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
75 additions
and
22 deletions
+75
-22
Doc/library/smtplib.rst
Doc/library/smtplib.rst
+25
-8
Lib/smtplib.py
Lib/smtplib.py
+27
-13
Lib/test/mock_socket.py
Lib/test/mock_socket.py
+2
-1
Lib/test/test_smtplib.py
Lib/test/test_smtplib.py
+17
-0
Misc/NEWS
Misc/NEWS
+4
-0
No files found.
Doc/library/smtplib.rst
View file @
a06c029c
...
...
@@ -20,7 +20,7 @@ details of SMTP and ESMTP operation, consult :rfc:`821` (Simple Mail Transfer
Protocol) and :rfc:`1869` (SMTP Service Extensions).
.. class:: SMTP(host='', port=0, local_hostname=None[, timeout])
.. class:: SMTP(host='', port=0, local_hostname=None[, timeout]
, source_address=None
)
A :class:`SMTP` instance encapsulates an SMTP connection. It has methods
that support a full repertoire of SMTP and ESMTP operations. If the optional
...
...
@@ -29,7 +29,12 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
raised if the specified host doesn't respond correctly. The optional
*timeout* parameter specifies a timeout in seconds for blocking operations
like the connection attempt (if not specified, the global default timeout
setting will be used).
setting will be used). The optional source_address parameter allows to bind to some
specific source address in a machine with multiple network interfaces,
and/or to some specific source tcp port. It takes a 2-tuple (host, port),
for the socket to bind to as its source address before connecting. If
ommited (or if host or port are '' and/or 0 respectively) the OS default
behavior will be used.
For normal use, you should only require the initialization/connect,
:meth:`sendmail`, and :meth:`quit` methods. An example is included below.
...
...
@@ -48,8 +53,10 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
.. versionchanged:: 3.3
Support for the :keyword:`with` statement was added.
.. versionadded:: 3.3
source_address parameter.
.. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout], context=None)
.. class:: SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None[, timeout], context=None
, source_address=None
)
A :class:`SMTP_SSL` instance behaves exactly the same as instances of
:class:`SMTP`. :class:`SMTP_SSL` should be used for situations where SSL is
...
...
@@ -62,18 +69,28 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions).
keyfile and certfile must be None. The optional *timeout*
parameter specifies a timeout in seconds for blocking operations like the
connection attempt (if not specified, the global default timeout setting
will be used).
will be used). The optional source_address parameter allows to bind to some
specific source address in a machine with multiple network interfaces,
and/or to some specific source tcp port. It takes a 2-tuple (host, port),
for the socket to bind to as its source address before connecting. If
ommited (or if host or port are '' and/or 0 respectively) the OS default
behavior will be used.
.. versionchanged:: 3.3
*context* was added.
.. versionadded:: 3.3
source_address parameter.
.. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None)
.. class:: LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None)
The LMTP protocol, which is very similar to ESMTP, is heavily based on the
standard SMTP client. It's common to use Unix sockets for LMTP, so our :meth:`connect`
method must support that as well as a regular host:port server. To specify a
Unix socket, you must use an absolute path for *host*, starting with a '/'.
standard SMTP client. It's common to use Unix sockets for LMTP, so our
:meth:`connect` method must support that as well as a regular host:port
server. The optional parameters local_hostname and source_address has the
same meaning as that of SMTP client.To specify a Unix socket, you must use
an absolute path for *host*, starting with a '/'.
Authentication is supported, using the regular SMTP mechanism. When using a Unix
socket, LMTP generally don't support or require any authentication, but your
...
...
Lib/smtplib.py
View file @
a06c029c
...
...
@@ -215,7 +215,8 @@ class SMTP:
default_port = SMTP_PORT
def __init__(self, host='', port=0, local_hostname=None,
timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
source_address=None):
"""
Initialize
a
new
instance
.
If
specified
,
`
host
' is the name of the remote host to which to
...
...
@@ -223,11 +224,16 @@ class SMTP:
By
default
,
smtplib
.
SMTP_PORT
is
used
.
An
SMTPConnectError
is
raised
if
the
specified
`
host
' doesn'
t
respond
correctly
.
If
specified
,
`local_hostname`
is
used
as
the
FQDN
of
the
local
host
.
By
default
,
the
local
hostname
is
found
using
socket
.
getfqdn
().
the
local
hostname
is
found
using
socket
.
getfqdn
().
The
`source_address`
parameter
takes
a
2
-
tuple
(
host
,
port
)
for
the
socket
to
bind
to
as
its
source
address
before
connecting
.
If
the
host
is
''
and
port
is
0
,
the
OS
default
behavior
will
be
used
.
"""
self.timeout = timeout
self.esmtp_features = {}
self.source_address = source_address
if host:
(code, msg) = self.connect(host, port)
if code != 220:
...
...
@@ -276,10 +282,11 @@ class SMTP:
# This makes it simpler for SMTP_SSL to use the SMTP connect code
# and just alter the socket connection bit.
if self.debuglevel > 0:
print('connect:', (host, port), file=stderr)
return socket.create_connection((host, port), timeout)
print('connect: to', (host, port), self.source_address, file=stderr)
return socket.create_connection((host, port), timeout,
self.source_address)
def connect(self, host='localhost', port=0):
def connect(self, host='localhost', port=0
, source_address=None
):
"""
Connect
to
a
host
on
a
given
port
.
If
the
hostname
ends
with
a
colon
(
`
:
') followed by a number, and
...
...
@@ -290,6 +297,7 @@ class SMTP:
specified during instantiation.
"""
if source_address: self.source_address = source_address
if not port and (host.find('
:
') == host.rfind('
:
')):
i = host.rfind('
:
')
if i >= 0:
...
...
@@ -829,7 +837,8 @@ if _have_ssl:
""" This is a subclass derived from SMTP that connects over an SSL encrypted
socket (to use this class you need a socket module that was compiled with SSL
support). If host is not specified, '' (the local host) is used. If port is
omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile
omitted, the standard SMTP-over-SSL port (465) is used. The optional
source_address takes a two-tuple (host,port) for socket to bind to. keyfile and certfile
are also optional - they can contain a PEM formatted private key and
certificate chain file for the SSL connection. context also optional, can contain
a SSLContext, and is an alternative to keyfile and certfile; If it is specified both
...
...
@@ -840,7 +849,8 @@ if _have_ssl:
def
__init__
(
self
,
host
=
''
,
port
=
0
,
local_hostname
=
None
,
keyfile
=
None
,
certfile
=
None
,
timeout
=
socket
.
_GLOBAL_DEFAULT_TIMEOUT
,
context
=
None
):
timeout
=
socket
.
_GLOBAL_DEFAULT_TIMEOUT
,
source_address
=
None
,
context
=
None
):
if
context
is
not
None
and
keyfile
is
not
None
:
raise
ValueError
(
"context and keyfile arguments are mutually "
"exclusive"
)
...
...
@@ -850,12 +860,14 @@ if _have_ssl:
self
.
keyfile
=
keyfile
self
.
certfile
=
certfile
self
.
context
=
context
SMTP
.
__init__
(
self
,
host
,
port
,
local_hostname
,
timeout
)
SMTP
.
__init__
(
self
,
host
,
port
,
local_hostname
,
timeout
,
source_address
)
def
_get_socket
(
self
,
host
,
port
,
timeout
):
if
self
.
debuglevel
>
0
:
print
(
'connect:'
,
(
host
,
port
),
file
=
stderr
)
new_socket
=
socket
.
create_connection
((
host
,
port
),
timeout
)
new_socket
=
socket
.
create_connection
((
host
,
port
),
timeout
,
self
.
source_address
)
if
self
.
context
is
not
None
:
new_socket
=
self
.
context
.
wrap_socket
(
new_socket
)
else
:
...
...
@@ -884,14 +896,16 @@ class LMTP(SMTP):
ehlo_msg
=
"lhlo"
def
__init__
(
self
,
host
=
''
,
port
=
LMTP_PORT
,
local_hostname
=
None
):
def
__init__
(
self
,
host
=
''
,
port
=
LMTP_PORT
,
local_hostname
=
None
,
source_address
=
None
):
"""Initialize a new instance."""
SMTP
.
__init__
(
self
,
host
,
port
,
local_hostname
)
SMTP
.
__init__
(
self
,
host
,
port
,
local_hostname
=
local_hostname
,
source_address
=
source_address
)
def
connect
(
self
,
host
=
'localhost'
,
port
=
0
):
def
connect
(
self
,
host
=
'localhost'
,
port
=
0
,
source_address
=
None
):
"""Connect to the LMTP daemon, on either a Unix or a TCP socket."""
if
host
[
0
]
!=
'/'
:
return
SMTP
.
connect
(
self
,
host
,
port
)
return
SMTP
.
connect
(
self
,
host
,
port
,
source_address
=
source_address
)
# Handle Unix-domain sockets.
try
:
...
...
Lib/test/mock_socket.py
View file @
a06c029c
...
...
@@ -106,7 +106,8 @@ def socket(family=None, type=None, proto=None):
return
MockSocket
()
def
create_connection
(
address
,
timeout
=
socket_module
.
_GLOBAL_DEFAULT_TIMEOUT
):
def
create_connection
(
address
,
timeout
=
socket_module
.
_GLOBAL_DEFAULT_TIMEOUT
,
source_address
=
None
):
try
:
int_port
=
int
(
address
[
1
])
except
ValueError
:
...
...
Lib/test/test_smtplib.py
View file @
a06c029c
...
...
@@ -72,6 +72,14 @@ class GeneralTests(unittest.TestCase):
smtp
=
smtplib
.
SMTP
(
HOST
,
self
.
port
)
smtp
.
close
()
def
testSourceAddress
(
self
):
mock_socket
.
reply_with
(
b"220 Hola mundo"
)
# connects
smtp
=
smtplib
.
SMTP
(
HOST
,
self
.
port
,
source_address
=
(
'127.0.0.1'
,
19876
))
self
.
assertEqual
(
smtp
.
source_address
,
(
'127.0.0.1'
,
19876
))
smtp
.
close
()
def
testBasic2
(
self
):
mock_socket
.
reply_with
(
b"220 Hola mundo"
)
# connects, include port in host name
...
...
@@ -206,6 +214,15 @@ class DebuggingServerTests(unittest.TestCase):
smtp
=
smtplib
.
SMTP
(
HOST
,
self
.
port
,
local_hostname
=
'localhost'
,
timeout
=
3
)
smtp
.
quit
()
def
testSourceAddress
(
self
):
# connect
smtp
=
smtplib
.
SMTP
(
HOST
,
self
.
port
,
local_hostname
=
'localhost'
,
timeout
=
3
,
source_address
=
(
'127.0.0.1'
,
19876
))
self
.
assertEqual
(
smtp
.
source_address
,
(
'127.0.0.1'
,
19876
))
self
.
assertEqual
(
smtp
.
local_hostname
,
'localhost'
)
print
(
dir
(
smtp
))
smtp
.
quit
()
def
testNOOP
(
self
):
smtp
=
smtplib
.
SMTP
(
HOST
,
self
.
port
,
local_hostname
=
'localhost'
,
timeout
=
3
)
expected
=
(
250
,
b'Ok'
)
...
...
Misc/NEWS
View file @
a06c029c
...
...
@@ -249,6 +249,10 @@ Core and Builtins
Library
-------
- Issue #11281: smtplib.STMP gets source_address parameter, which adds the
ability to bind to specific source address on a machine with multiple
interfaces. Patch by Paulo Scardine.
- Issue #12464: tempfile.TemporaryDirectory.cleanup() should not follow
symlinks: fix it. Patch by Petri Lehtinen.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment