]> granicus.if.org Git - python/commitdiff
Fixes (accepts patch) issue1339 - http://bugs.python.org/issue1339
authorGregory P. Smith <greg@mad-scientist.com>
Thu, 17 Jan 2008 08:35:49 +0000 (08:35 +0000)
committerGregory P. Smith <greg@mad-scientist.com>
Thu, 17 Jan 2008 08:35:49 +0000 (08:35 +0000)
- Factor out the duplication of EHLO/HELO in login() and sendmail() to
  a new function, ehlo_or_helo_if_needed().
- Use ehlo_or_helo_if_needed() in starttls()
- Check for the starttls exception in starttls() in the same way as
  login() checks for the auth extension.
Contributed by Bill Fenner.

Doc/library/smtplib.rst
Lib/smtplib.py
Misc/NEWS

index 162e77bdd2271eaa06f8895774c1357b2d9eae92..0aea80ab8ba15dcb0117c64ea6c878aa600a1b91 100644 (file)
@@ -191,6 +191,16 @@ An :class:`SMTP` instance has the following methods:
    necessary to call this method explicitly.  It will be implicitly called by
    :meth:`sendmail` when necessary.
 
+.. method:: SMTP.ehlo_or_helo_if_needed()
+
+   This method call :meth:`ehlo` and or :meth:`helo` if there has been no
+   previous ``EHLO`` or ``HELO`` command this session.  It tries ESMTP ``EHLO``
+   first.
+
+   :exc:SMTPHeloError
+     The server didn't reply properly to the ``HELO`` greeting.
+
+   .. versionadded:: 2.6
 
 .. method:: SMTP.has_extn(name)
 
@@ -237,6 +247,22 @@ An :class:`SMTP` instance has the following methods:
    If *keyfile* and *certfile* are provided, these are passed to the :mod:`socket`
    module's :func:`ssl` function.
 
+   If there has been no previous ``EHLO`` or ``HELO`` command this session,
+   this method tries ESMTP ``EHLO`` first.
+
+   .. versionchanged:: 2.6
+
+   :exc:`SMTPHeloError`
+      The server didn't reply properly to the ``HELO`` greeting.
+
+   :exc:`SMTPException`
+     The server does not support the STARTTLS extension.
+
+   .. versionchanged:: 2.6
+
+   :exc:`RuntimeError`
+     SSL/TLS support is not available to your python interpreter.
+
 
 .. method:: SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
 
index 97b1e20b29b05fa5c089e7f95296c79cff158c2c..bb9c239a2764cf1ead04a6acfeaf4912d7831789 100755 (executable)
@@ -492,6 +492,23 @@ class SMTP:
 
     # some useful methods
 
+    def ehlo_or_helo_if_needed(self):
+        """Call self.ehlo() and/or self.helo() if needed.
+
+        If there has been no previous EHLO or HELO command this session, this
+        method tries ESMTP EHLO first.
+
+        This method may raise the following exceptions:
+
+         SMTPHeloError            The server didn't reply properly to
+                                  the helo greeting.
+        """
+        if self.helo_resp is None and self.ehlo_resp is None:
+            if not (200 <= self.ehlo()[0] <= 299):
+                (code, resp) = self.helo()
+                if not (200 <= code <= 299):
+                    raise SMTPHeloError(code, resp)
+
     def login(self, user, password):
         """Log in on an SMTP server that requires authentication.
 
@@ -527,11 +544,7 @@ class SMTP:
         AUTH_CRAM_MD5 = "CRAM-MD5"
         AUTH_LOGIN = "LOGIN"
 
-        if self.helo_resp is None and self.ehlo_resp is None:
-            if not (200 <= self.ehlo()[0] <= 299):
-                (code, resp) = self.helo()
-                if not (200 <= code <= 299):
-                    raise SMTPHeloError(code, resp)
+        self.ehlo_or_helo_if_needed()
 
         if not self.has_extn("auth"):
             raise SMTPException("SMTP AUTH extension not supported by server.")
@@ -577,12 +590,23 @@ class SMTP:
     def starttls(self, keyfile = None, certfile = None):
         """Puts the connection to the SMTP server into TLS mode.
 
+        If there has been no previous EHLO or HELO command this session, this
+        method tries ESMTP EHLO first.
+
         If the server supports TLS, this will encrypt the rest of the SMTP
         session. If you provide the keyfile and certfile parameters,
         the identity of the SMTP server and client can be checked. This,
         however, depends on whether the socket module really checks the
         certificates.
+
+        This method may raise the following exceptions:
+
+         SMTPHeloError            The server didn't reply properly to
+                                  the helo greeting.
         """
+        self.ehlo_or_helo_if_needed()
+        if not self.has_extn("starttls"):
+            raise SMTPException("STARTTLS extension not supported by server.")
         (resp, reply) = self.docmd("STARTTLS")
         if resp == 220:
             if not _have_ssl:
@@ -656,11 +680,7 @@ class SMTP:
         empty dictionary.
 
         """
-        if self.helo_resp is None and self.ehlo_resp is None:
-            if not (200 <= self.ehlo()[0] <= 299):
-                (code,resp) = self.helo()
-                if not (200 <= code <= 299):
-                    raise SMTPHeloError(code, resp)
+        self.ehlo_or_helo_if_needed()
         esmtp_opts = []
         if self.does_esmtp:
             # Hmmm? what's this? -ddm
index 4a494a8326ae26bc1c7bff94a2f970ec0aaa4770..828aab275df5a55ca4f122e22ce8f602152b4f29 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -990,6 +990,12 @@ Library
   RFC 3207 and forgets any knowledge obtained from the server not obtained
   from the TLS negotiation itself.  Patch contributed by Bill Fenner.
 
+- Issue1339: The smtplib.SMTP class has been refactored a bit such
+  that the SMTP.starttls() caller no longer needs to call ehlo()
+  beforehand.  SMTP.starttls() now raises an exception of the server
+  does not claim to support starttls.  Adds the SMTP.ehlo_or_helo_if_needed()
+  method.  Patch contributed by Bill Fenner.
+
 Extension Modules
 -----------------