blob: f724b9f268f3884aa8bd72b9a649d7000712f691 [file] [log] [blame]
Benjamin Peterson90f5ba52010-03-11 22:53:45 +00001#! /usr/bin/env python3
Barry Warsaw4c4bec81998-12-22 03:02:20 +00002
Barry Warsawa1ae8842000-07-09 21:24:31 +00003'''SMTP/ESMTP client class.
Guido van Rossumbbe323e1998-01-29 17:24:40 +00004
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +00005This should follow RFC 821 (SMTP), RFC 1869 (ESMTP), RFC 2554 (SMTP
6Authentication) and RFC 2487 (Secure SMTP over TLS).
Guido van Rossumbbe323e1998-01-29 17:24:40 +00007
Guido van Rossumfcfb6321998-08-04 15:29:54 +00008Notes:
9
10Please remember, when doing ESMTP, that the names of the SMTP service
Barry Warsaw4c4bec81998-12-22 03:02:20 +000011extensions are NOT the same thing as the option keywords for the RCPT
Guido van Rossumfcfb6321998-08-04 15:29:54 +000012and MAIL commands!
13
Guido van Rossumbbe323e1998-01-29 17:24:40 +000014Example:
15
Barry Warsawa7d9bdf1998-12-22 03:24:27 +000016 >>> import smtplib
17 >>> s=smtplib.SMTP("localhost")
Guido van Rossum7131f842007-02-09 20:13:25 +000018 >>> print(s.help())
Barry Warsawa7d9bdf1998-12-22 03:24:27 +000019 This is Sendmail version 8.8.4
20 Topics:
21 HELO EHLO MAIL RCPT DATA
22 RSET NOOP QUIT HELP VRFY
23 EXPN VERB ETRN DSN
24 For more info use "HELP <topic>".
25 To report bugs in the implementation send email to
26 sendmail-bugs@sendmail.org.
27 For local information send email to Postmaster at your site.
28 End of HELP info
29 >>> s.putcmd("vrfy","someone@here")
30 >>> s.getreply()
31 (250, "Somebody OverHere <somebody@here.my.org>")
32 >>> s.quit()
Barry Warsawa1ae8842000-07-09 21:24:31 +000033'''
Guido van Rossumbbe323e1998-01-29 17:24:40 +000034
Guido van Rossum98d9fd32000-02-28 15:12:25 +000035# Author: The Dragon De Monsyne <dragondm@integral.org>
36# ESMTP support, test code and doc fixes added by
37# Eric S. Raymond <esr@thyrsus.com>
38# Better RFC 821 compliance (MAIL and RCPT, and CRLF in data)
39# by Carey Evans <c.evans@clear.net.nz>, for picky mail servers.
Guido van Rossumae010462001-09-11 15:57:46 +000040# RFC 2554 (authentication) support by Gerhard Haering <gerhard@bigfoot.de>.
Tim Peters495ad3c2001-01-15 01:36:40 +000041#
Guido van Rossum98d9fd32000-02-28 15:12:25 +000042# This was modified from the Python 1.5 library HTTP lib.
43
Guido van Rossumbbe323e1998-01-29 17:24:40 +000044import socket
R. David Murray7dff9e02010-11-08 17:15:13 +000045import io
Barry Warsaw07201771998-12-22 20:37:36 +000046import re
Thomas Woutersb2137042007-02-01 18:02:27 +000047import email.utils
R. David Murray7dff9e02010-11-08 17:15:13 +000048import email.message
49import email.generator
Guido van Rossumae010462001-09-11 15:57:46 +000050import base64
51import hmac
Barry Warsaw2cc1f6d2007-08-30 14:28:55 +000052from email.base64mime import body_encode as encode_base64
Brett Cannone6f8a892004-07-10 23:14:30 +000053from sys import stderr
Guido van Rossumbbe323e1998-01-29 17:24:40 +000054
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +000055__all__ = ["SMTPException", "SMTPServerDisconnected", "SMTPResponseException",
56 "SMTPSenderRefused", "SMTPRecipientsRefused", "SMTPDataError",
57 "SMTPConnectError", "SMTPHeloError", "SMTPAuthenticationError",
58 "quoteaddr", "quotedata", "SMTP"]
Skip Montanaro0de65802001-02-15 22:15:14 +000059
Guido van Rossumbbe323e1998-01-29 17:24:40 +000060SMTP_PORT = 25
Thomas Wouters89f507f2006-12-13 04:49:30 +000061SMTP_SSL_PORT = 465
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +000062CRLF = "\r\n"
63bCRLF = b"\r\n"
Guido van Rossumbbe323e1998-01-29 17:24:40 +000064
Piers Lauder385a77a2002-07-27 00:38:30 +000065OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
66
Tim Peters495ad3c2001-01-15 01:36:40 +000067# Exception classes used by this module.
Guido van Rossum296e1431999-04-07 15:03:39 +000068class SMTPException(Exception):
69 """Base class for all exceptions raised by this module."""
70
71class SMTPServerDisconnected(SMTPException):
72 """Not connected to any SMTP server.
73
74 This exception is raised when the server unexpectedly disconnects,
75 or when an attempt is made to use the SMTP instance before
76 connecting it to a server.
77 """
78
79class SMTPResponseException(SMTPException):
80 """Base class for all exceptions that include an SMTP error code.
81
82 These exceptions are generated in some instances when the SMTP
83 server returns an error code. The error code is stored in the
84 `smtp_code' attribute of the error, and the `smtp_error' attribute
85 is set to the error message.
86 """
87
88 def __init__(self, code, msg):
89 self.smtp_code = code
90 self.smtp_error = msg
91 self.args = (code, msg)
92
93class SMTPSenderRefused(SMTPResponseException):
94 """Sender address refused.
Guido van Rossumae010462001-09-11 15:57:46 +000095
Guido van Rossum296e1431999-04-07 15:03:39 +000096 In addition to the attributes set by on all SMTPResponseException
Barry Warsawd25c1b71999-11-28 17:11:06 +000097 exceptions, this sets `sender' to the string that the SMTP refused.
Guido van Rossum296e1431999-04-07 15:03:39 +000098 """
99
100 def __init__(self, code, msg, sender):
101 self.smtp_code = code
102 self.smtp_error = msg
103 self.sender = sender
104 self.args = (code, msg, sender)
105
Guido van Rossum20c92281999-04-21 16:52:20 +0000106class SMTPRecipientsRefused(SMTPException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000107 """All recipient addresses refused.
Guido van Rossumae010462001-09-11 15:57:46 +0000108
Thomas Wouters7e474022000-07-16 12:04:32 +0000109 The errors for each recipient are accessible through the attribute
Tim Peters495ad3c2001-01-15 01:36:40 +0000110 'recipients', which is a dictionary of exactly the same sort as
111 SMTP.sendmail() returns.
Guido van Rossum296e1431999-04-07 15:03:39 +0000112 """
113
114 def __init__(self, recipients):
115 self.recipients = recipients
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000116 self.args = (recipients,)
Guido van Rossum296e1431999-04-07 15:03:39 +0000117
118
Guido van Rossum296e1431999-04-07 15:03:39 +0000119class SMTPDataError(SMTPResponseException):
120 """The SMTP server didn't accept the data."""
121
122class SMTPConnectError(SMTPResponseException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000123 """Error during connection establishment."""
Guido van Rossum296e1431999-04-07 15:03:39 +0000124
125class SMTPHeloError(SMTPResponseException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000126 """The server refused our HELO reply."""
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000127
Guido van Rossumae010462001-09-11 15:57:46 +0000128class SMTPAuthenticationError(SMTPResponseException):
129 """Authentication error.
130
131 Most probably the server didn't accept the username/password
132 combination provided.
133 """
Peter Schneider-Kamp7bc82bb2000-08-10 14:02:23 +0000134
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000135def quoteaddr(addr):
136 """Quote a subset of the email addresses defined by RFC 821.
137
Georg Brandl9f0f9602008-06-12 22:23:59 +0000138 Should be able to handle anything email.utils.parseaddr can handle.
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000139 """
Raymond Hettinger342456d2002-09-05 01:14:07 +0000140 m = (None, None)
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000141 try:
Thomas Woutersb2137042007-02-01 18:02:27 +0000142 m = email.utils.parseaddr(addr)[1]
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000143 except AttributeError:
144 pass
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000145 if m == (None, None): # Indicates parse failure or AttributeError
Georg Brandlbd3bc4d2006-02-17 09:52:53 +0000146 # something weird here.. punt -ddm
Raymond Hettinger342456d2002-09-05 01:14:07 +0000147 return "<%s>" % addr
Georg Brandlbd3bc4d2006-02-17 09:52:53 +0000148 elif m is None:
149 # the sender wants an empty return address
150 return "<>"
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000151 else:
152 return "<%s>" % m
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000153
R. David Murray7dff9e02010-11-08 17:15:13 +0000154# Legacy method kept for backward compatibility.
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000155def quotedata(data):
156 """Quote data for email.
157
Barry Warsawd25c1b71999-11-28 17:11:06 +0000158 Double leading '.', and change Unix newline '\\n', or Mac '\\r' into
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000159 Internet CRLF end-of-line.
160 """
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000161 return re.sub(r'(?m)^\.', '..',
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000162 re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000163
R. David Murray7dff9e02010-11-08 17:15:13 +0000164def _quote_periods(bindata):
165 return re.sub(br'(?m)^\.', '..', bindata)
166
167def _fix_eols(data):
168 return re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data)
169
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000170try:
171 import ssl
172except ImportError:
173 _have_ssl = False
174else:
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000175 class SSLFakeFile:
176 """A fake file like object that really wraps a SSLObject.
177
178 It only supports what is needed in smtplib.
179 """
180 def __init__(self, sslobj):
181 self.sslobj = sslobj
182
183 def readline(self):
184 str = b""
185 chr = None
186 while chr != b"\n":
187 chr = self.sslobj.read(1)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000188 if not chr:
189 break
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000190 str += chr
191 return str
192
193 def close(self):
194 pass
195
196 _have_ssl = True
197
Peter Schneider-Kamp7bc82bb2000-08-10 14:02:23 +0000198
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000199class SMTP:
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000200 """This class manages a connection to an SMTP or ESMTP server.
201 SMTP Objects:
Tim Peters495ad3c2001-01-15 01:36:40 +0000202 SMTP objects have the following attributes:
203 helo_resp
204 This is the message given by the server in response to the
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000205 most recent HELO command.
Tim Peters495ad3c2001-01-15 01:36:40 +0000206
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000207 ehlo_resp
Tim Peters495ad3c2001-01-15 01:36:40 +0000208 This is the message given by the server in response to the
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000209 most recent EHLO command. This is usually multiline.
210
Tim Peters495ad3c2001-01-15 01:36:40 +0000211 does_esmtp
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000212 This is a True value _after you do an EHLO command_, if the
213 server supports ESMTP.
214
Tim Peters495ad3c2001-01-15 01:36:40 +0000215 esmtp_features
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000216 This is a dictionary, which, if the server supports ESMTP,
Barry Warsawd25c1b71999-11-28 17:11:06 +0000217 will _after you do an EHLO command_, contain the names of the
218 SMTP service extensions this server supports, and their
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000219 parameters (if any).
Barry Warsawd25c1b71999-11-28 17:11:06 +0000220
Tim Peters495ad3c2001-01-15 01:36:40 +0000221 Note, all extension names are mapped to lower case in the
222 dictionary.
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000223
Barry Warsawd25c1b71999-11-28 17:11:06 +0000224 See each method's docstrings for details. In general, there is a
225 method of the same name to perform each SMTP command. There is also a
226 method called 'sendmail' that will do an entire mail transaction.
227 """
Guido van Rossum95e6f701998-06-25 02:15:50 +0000228 debuglevel = 0
229 file = None
230 helo_resp = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000231 ehlo_msg = "ehlo"
Guido van Rossum95e6f701998-06-25 02:15:50 +0000232 ehlo_resp = None
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000233 does_esmtp = 0
Antoine Pitrouc1d52062011-05-07 19:39:37 +0200234 default_port = SMTP_PORT
Guido van Rossum95e6f701998-06-25 02:15:50 +0000235
Georg Brandlf78e02b2008-06-10 17:40:04 +0000236 def __init__(self, host='', port=0, local_hostname=None,
237 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000238 """Initialize a new instance.
239
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000240 If specified, `host' is the name of the remote host to which to
241 connect. If specified, `port' specifies the port to which to connect.
Barry Warsawd25c1b71999-11-28 17:11:06 +0000242 By default, smtplib.SMTP_PORT is used. An SMTPConnectError is raised
Neil Schemenauer6730f262002-03-24 15:30:40 +0000243 if the specified `host' doesn't respond correctly. If specified,
Tim Peters863ac442002-04-16 01:38:40 +0000244 `local_hostname` is used as the FQDN of the local host. By default,
245 the local hostname is found using socket.getfqdn().
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000246
247 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000248 self.timeout = timeout
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000249 self.esmtp_features = {}
Guido van Rossum296e1431999-04-07 15:03:39 +0000250 if host:
251 (code, msg) = self.connect(host, port)
252 if code != 220:
253 raise SMTPConnectError(code, msg)
Raymond Hettingerf13eb552002-06-02 00:40:05 +0000254 if local_hostname is not None:
Barry Warsaw13e34f72002-03-26 20:27:35 +0000255 self.local_hostname = local_hostname
Neil Schemenauer6730f262002-03-24 15:30:40 +0000256 else:
Barry Warsaw13e34f72002-03-26 20:27:35 +0000257 # RFC 2821 says we should use the fqdn in the EHLO/HELO verb, and
258 # if that can't be calculated, that we should use a domain literal
259 # instead (essentially an encoded IP address like [A.B.C.D]).
260 fqdn = socket.getfqdn()
261 if '.' in fqdn:
262 self.local_hostname = fqdn
263 else:
264 # We can't find an fqdn hostname, so use a domain literal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000265 addr = '127.0.0.1'
266 try:
267 addr = socket.gethostbyname(socket.gethostname())
268 except socket.gaierror:
269 pass
Barry Warsaw13e34f72002-03-26 20:27:35 +0000270 self.local_hostname = '[%s]' % addr
Tim Peters495ad3c2001-01-15 01:36:40 +0000271
Barry Warsaw1f5c9582011-03-15 15:04:44 -0400272 def __enter__(self):
273 return self
274
275 def __exit__(self, *args):
276 try:
277 code, message = self.docmd("QUIT")
278 if code != 221:
279 raise SMTPResponseException(code, message)
280 except SMTPServerDisconnected:
281 pass
282 finally:
283 self.close()
284
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000285 def set_debuglevel(self, debuglevel):
286 """Set the debug output level.
287
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000288 A non-false value results in debug messages for connection and for all
289 messages sent to and received from the server.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000290
291 """
292 self.debuglevel = debuglevel
293
Barry Warsawc9181712008-03-19 14:25:51 +0000294 def _get_socket(self, host, port, timeout):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000295 # This makes it simpler for SMTP_SSL to use the SMTP connect code
296 # and just alter the socket connection bit.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000297 if self.debuglevel > 0:
298 print('connect:', (host, port), file=stderr)
Barry Warsawc9181712008-03-19 14:25:51 +0000299 return socket.create_connection((host, port), timeout)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000300
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000301 def connect(self, host='localhost', port=0):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000302 """Connect to a host on a given port.
Guido van Rossum95e6f701998-06-25 02:15:50 +0000303
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000304 If the hostname ends with a colon (`:') followed by a number, and
305 there is no port specified, that suffix will be stripped off and the
306 number interpreted as the port number to use.
Guido van Rossum95e6f701998-06-25 02:15:50 +0000307
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000308 Note: This method is automatically invoked by __init__, if a host is
309 specified during instantiation.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000310
311 """
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000312 if not port and (host.find(':') == host.rfind(':')):
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000313 i = host.rfind(':')
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000314 if i >= 0:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000315 host, port = host[:i], host[i + 1:]
316 try:
317 port = int(port)
Eric S. Raymond8d876032001-02-09 10:14:53 +0000318 except ValueError:
Guido van Rossumd8faa362007-04-27 19:54:29 +0000319 raise socket.error("nonnumeric port")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000320 if not port:
321 port = self.default_port
322 if self.debuglevel > 0:
323 print('connect:', (host, port), file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000324 self.sock = self._get_socket(host, port, self.timeout)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000325 (code, msg) = self.getreply()
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000326 if self.debuglevel > 0:
327 print("connect:", msg, file=stderr)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000328 return (code, msg)
Tim Peters495ad3c2001-01-15 01:36:40 +0000329
Guido van Rossum8a392d72007-11-21 22:09:45 +0000330 def send(self, s):
331 """Send `s' to the server."""
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000332 if self.debuglevel > 0:
333 print('send:', repr(s), file=stderr)
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000334 if hasattr(self, 'sock') and self.sock:
Guido van Rossum8a392d72007-11-21 22:09:45 +0000335 if isinstance(s, str):
336 s = s.encode("ascii")
Guido van Rossum2880f6e1998-08-10 20:07:00 +0000337 try:
Guido van Rossum8a392d72007-11-21 22:09:45 +0000338 self.sock.sendall(s)
Guido van Rossum2880f6e1998-08-10 20:07:00 +0000339 except socket.error:
Barry Warsaw76750972001-12-14 20:34:20 +0000340 self.close()
Guido van Rossum40233ea1999-01-15 03:23:55 +0000341 raise SMTPServerDisconnected('Server not connected')
Guido van Rossumfc40a831998-01-29 17:26:45 +0000342 else:
Guido van Rossum40233ea1999-01-15 03:23:55 +0000343 raise SMTPServerDisconnected('please run connect() first')
Tim Peters495ad3c2001-01-15 01:36:40 +0000344
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000345 def putcmd(self, cmd, args=""):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000346 """Send a command to the server."""
Guido van Rossumdb23d3d1999-06-09 15:13:10 +0000347 if args == "":
348 str = '%s%s' % (cmd, CRLF)
349 else:
350 str = '%s %s%s' % (cmd, args, CRLF)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000351 self.send(str)
Tim Peters495ad3c2001-01-15 01:36:40 +0000352
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000353 def getreply(self):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000354 """Get a reply from the server.
Tim Peters495ad3c2001-01-15 01:36:40 +0000355
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000356 Returns a tuple consisting of:
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000357
358 - server response code (e.g. '250', or such, if all goes well)
359 Note: returns -1 if it can't read response code.
360
361 - server response string corresponding to response code (multiline
362 responses are converted to a single, multiline string).
Guido van Rossumf123f841999-03-29 20:33:21 +0000363
364 Raises SMTPServerDisconnected if end-of-file is reached.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000365 """
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000366 resp = []
Guido van Rossum296e1431999-04-07 15:03:39 +0000367 if self.file is None:
368 self.file = self.sock.makefile('rb')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000369 while 1:
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000370 try:
371 line = self.file.readline()
372 except socket.error:
373 line = ''
Guido van Rossum806c2462007-08-06 23:33:07 +0000374 if not line:
Guido van Rossum296e1431999-04-07 15:03:39 +0000375 self.close()
376 raise SMTPServerDisconnected("Connection unexpectedly closed")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000377 if self.debuglevel > 0:
378 print('reply:', repr(line), file=stderr)
Guido van Rossum806c2462007-08-06 23:33:07 +0000379 resp.append(line[4:].strip(b' \t\r\n'))
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000380 code = line[:3]
Guido van Rossum296e1431999-04-07 15:03:39 +0000381 # Check that the error code is syntactically correct.
382 # Don't attempt to read a continuation line if it is broken.
383 try:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000384 errcode = int(code)
Guido van Rossum296e1431999-04-07 15:03:39 +0000385 except ValueError:
386 errcode = -1
387 break
Guido van Rossumf123f841999-03-29 20:33:21 +0000388 # Check if multiline response.
Guido van Rossum806c2462007-08-06 23:33:07 +0000389 if line[3:4] != b"-":
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000390 break
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000391
Guido van Rossumc43e79f2007-06-18 18:26:36 +0000392 errmsg = b"\n".join(resp)
Tim Peters495ad3c2001-01-15 01:36:40 +0000393 if self.debuglevel > 0:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000394 print('reply: retcode (%s); Msg: %s' % (errcode, errmsg), file=stderr)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000395 return errcode, errmsg
Tim Peters495ad3c2001-01-15 01:36:40 +0000396
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000397 def docmd(self, cmd, args=""):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000398 """Send a command, and return its response code."""
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000399 self.putcmd(cmd, args)
Guido van Rossum296e1431999-04-07 15:03:39 +0000400 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000401
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000402 # std smtp commands
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000403 def helo(self, name=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000404 """SMTP 'helo' command.
405 Hostname to send for this command defaults to the FQDN of the local
406 host.
407 """
Neil Schemenauer6730f262002-03-24 15:30:40 +0000408 self.putcmd("helo", name or self.local_hostname)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000409 (code, msg) = self.getreply()
410 self.helo_resp = msg
411 return (code, msg)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000412
Guido van Rossum95e6f701998-06-25 02:15:50 +0000413 def ehlo(self, name=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000414 """ SMTP 'ehlo' command.
415 Hostname to send for this command defaults to the FQDN of the local
416 host.
417 """
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000418 self.esmtp_features = {}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000419 self.putcmd(self.ehlo_msg, name or self.local_hostname)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000420 (code, msg) = self.getreply()
Tim Peters495ad3c2001-01-15 01:36:40 +0000421 # According to RFC1869 some (badly written)
422 # MTA's will disconnect on an ehlo. Toss an exception if
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000423 # that happens -ddm
424 if code == -1 and len(msg) == 0:
Barry Warsaw76750972001-12-14 20:34:20 +0000425 self.close()
Guido van Rossum40233ea1999-01-15 03:23:55 +0000426 raise SMTPServerDisconnected("Server not connected")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000427 self.ehlo_resp = msg
Fred Drake8152d322000-12-12 23:20:45 +0000428 if code != 250:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000429 return (code, msg)
430 self.does_esmtp = 1
Thomas Wouters7e474022000-07-16 12:04:32 +0000431 #parse the ehlo response -ddm
Guido van Rossum04110fb2007-08-24 16:32:05 +0000432 assert isinstance(self.ehlo_resp, bytes), repr(self.ehlo_resp)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000433 resp = self.ehlo_resp.decode("latin-1").split('\n')
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000434 del resp[0]
Guido van Rossum2880f6e1998-08-10 20:07:00 +0000435 for each in resp:
Piers Lauder385a77a2002-07-27 00:38:30 +0000436 # To be able to communicate with as many SMTP servers as possible,
437 # we have to take the old-style auth advertisement into account,
438 # because:
439 # 1) Else our SMTP feature parser gets confused.
440 # 2) There are some servers that only advertise the auth methods we
441 # support using the old style.
442 auth_match = OLDSTYLE_AUTH.match(each)
443 if auth_match:
444 # This doesn't remove duplicates, but that's no problem
445 self.esmtp_features["auth"] = self.esmtp_features.get("auth", "") \
446 + " " + auth_match.groups(0)[0]
447 continue
448
Barry Warsawbe22ae62002-04-15 20:03:30 +0000449 # RFC 1869 requires a space between ehlo keyword and parameters.
450 # It's actually stricter, in that only spaces are allowed between
451 # parameters, but were not going to check for that here. Note
452 # that the space isn't present if there are no parameters.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000453 m = re.match(r'(?P<feature>[A-Za-z0-9][A-Za-z0-9\-]*) ?', each)
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000454 if m:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000455 feature = m.group("feature").lower()
456 params = m.string[m.end("feature"):].strip()
Piers Lauder385a77a2002-07-27 00:38:30 +0000457 if feature == "auth":
458 self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \
459 + " " + params
460 else:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000461 self.esmtp_features[feature] = params
462 return (code, msg)
Guido van Rossum95e6f701998-06-25 02:15:50 +0000463
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000464 def has_extn(self, opt):
465 """Does the server support a given SMTP service extension?"""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000466 return opt.lower() in self.esmtp_features
Guido van Rossum95e6f701998-06-25 02:15:50 +0000467
Guido van Rossum18586f41998-04-03 17:03:13 +0000468 def help(self, args=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000469 """SMTP 'help' command.
470 Returns help text from server."""
Guido van Rossum18586f41998-04-03 17:03:13 +0000471 self.putcmd("help", args)
Kurt B. Kaiser58bd1902005-06-26 18:27:36 +0000472 return self.getreply()[1]
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000473
474 def rset(self):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000475 """SMTP 'rset' command -- resets session."""
Guido van Rossum296e1431999-04-07 15:03:39 +0000476 return self.docmd("rset")
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000477
478 def noop(self):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000479 """SMTP 'noop' command -- doesn't do anything :>"""
Guido van Rossum296e1431999-04-07 15:03:39 +0000480 return self.docmd("noop")
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000481
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000482 def mail(self, sender, options=[]):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000483 """SMTP 'mail' command -- begins mail xfer session."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000484 optionlist = ''
485 if options and self.does_esmtp:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000486 optionlist = ' ' + ' '.join(options)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000487 self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000488 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000489
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000490 def rcpt(self, recip, options=[]):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000491 """SMTP 'rcpt' command -- indicates 1 recipient for this mail."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000492 optionlist = ''
493 if options and self.does_esmtp:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000494 optionlist = ' ' + ' '.join(options)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000495 self.putcmd("rcpt", "TO:%s%s" % (quoteaddr(recip), optionlist))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000496 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000497
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000498 def data(self, msg):
Tim Peters495ad3c2001-01-15 01:36:40 +0000499 """SMTP 'DATA' command -- sends message data to server.
Guido van Rossum296e1431999-04-07 15:03:39 +0000500
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000501 Automatically quotes lines beginning with a period per rfc821.
Guido van Rossum296e1431999-04-07 15:03:39 +0000502 Raises SMTPDataError if there is an unexpected reply to the
503 DATA command; the return value from this method is the final
R. David Murray7dff9e02010-11-08 17:15:13 +0000504 response code received when the all data is sent. If msg
505 is a string, lone '\r' and '\n' characters are converted to
506 '\r\n' characters. If msg is bytes, it is transmitted as is.
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000507 """
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000508 self.putcmd("data")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000509 (code, repl) = self.getreply()
510 if self.debuglevel > 0:
511 print("data:", (code, repl), file=stderr)
Fred Drake8152d322000-12-12 23:20:45 +0000512 if code != 354:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000513 raise SMTPDataError(code, repl)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000514 else:
R. David Murray7dff9e02010-11-08 17:15:13 +0000515 if isinstance(msg, str):
516 msg = _fix_eols(msg).encode('ascii')
517 q = _quote_periods(msg)
518 if q[-2:] != bCRLF:
519 q = q + bCRLF
520 q = q + b"." + bCRLF
Guido van Rossum20c92281999-04-21 16:52:20 +0000521 self.send(q)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000522 (code, msg) = self.getreply()
523 if self.debuglevel > 0:
524 print("data:", (code, msg), file=stderr)
525 return (code, msg)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000526
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000527 def verify(self, address):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000528 """SMTP 'verify' command -- checks for address validity."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000529 self.putcmd("vrfy", quoteaddr(address))
530 return self.getreply()
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000531 # a.k.a.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000532 vrfy = verify
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000533
534 def expn(self, address):
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000535 """SMTP 'expn' command -- expands a mailing list."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000536 self.putcmd("expn", quoteaddr(address))
537 return self.getreply()
538
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000539 # some useful methods
Guido van Rossumae010462001-09-11 15:57:46 +0000540
Christian Heimes679db4a2008-01-18 09:56:22 +0000541 def ehlo_or_helo_if_needed(self):
542 """Call self.ehlo() and/or self.helo() if needed.
543
544 If there has been no previous EHLO or HELO command this session, this
545 method tries ESMTP EHLO first.
546
547 This method may raise the following exceptions:
548
549 SMTPHeloError The server didn't reply properly to
550 the helo greeting.
551 """
552 if self.helo_resp is None and self.ehlo_resp is None:
553 if not (200 <= self.ehlo()[0] <= 299):
554 (code, resp) = self.helo()
555 if not (200 <= code <= 299):
556 raise SMTPHeloError(code, resp)
557
Guido van Rossumae010462001-09-11 15:57:46 +0000558 def login(self, user, password):
559 """Log in on an SMTP server that requires authentication.
560
561 The arguments are:
562 - user: The user name to authenticate with.
563 - password: The password for the authentication.
564
565 If there has been no previous EHLO or HELO command this session, this
566 method tries ESMTP EHLO first.
567
568 This method will return normally if the authentication was successful.
569
570 This method may raise the following exceptions:
571
572 SMTPHeloError The server didn't reply properly to
573 the helo greeting.
574 SMTPAuthenticationError The server didn't accept the username/
575 password combination.
Fred Drake2f8f4d32001-10-13 18:35:32 +0000576 SMTPException No suitable authentication method was
Guido van Rossumae010462001-09-11 15:57:46 +0000577 found.
578 """
579
580 def encode_cram_md5(challenge, user, password):
Georg Brandl706824f2009-06-04 09:42:55 +0000581 challenge = base64.decodebytes(challenge)
R. David Murrayfb123912009-05-28 18:19:00 +0000582 response = user + " " + hmac.HMAC(password.encode('ascii'),
583 challenge).hexdigest()
584 return encode_base64(response.encode('ascii'), eol='')
Guido van Rossumae010462001-09-11 15:57:46 +0000585
586 def encode_plain(user, password):
R. David Murraycaa27b72009-05-23 18:49:56 +0000587 s = "\0%s\0%s" % (user, password)
588 return encode_base64(s.encode('ascii'), eol='')
Tim Peters469cdad2002-08-08 20:19:19 +0000589
Guido van Rossumae010462001-09-11 15:57:46 +0000590 AUTH_PLAIN = "PLAIN"
591 AUTH_CRAM_MD5 = "CRAM-MD5"
Piers Lauder385a77a2002-07-27 00:38:30 +0000592 AUTH_LOGIN = "LOGIN"
Guido van Rossumae010462001-09-11 15:57:46 +0000593
Christian Heimes679db4a2008-01-18 09:56:22 +0000594 self.ehlo_or_helo_if_needed()
Guido van Rossumae010462001-09-11 15:57:46 +0000595
596 if not self.has_extn("auth"):
597 raise SMTPException("SMTP AUTH extension not supported by server.")
598
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000599 # Authentication methods the server claims to support
600 advertised_authlist = self.esmtp_features["auth"].split()
Guido van Rossumae010462001-09-11 15:57:46 +0000601
602 # List of authentication methods we support: from preferred to
603 # less preferred methods. Except for the purpose of testing the weaker
604 # ones, we prefer stronger methods like CRAM-MD5:
Piers Lauder385a77a2002-07-27 00:38:30 +0000605 preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN]
Guido van Rossumae010462001-09-11 15:57:46 +0000606
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000607 # We try the authentication methods the server advertises, but only the
608 # ones *we* support. And in our preferred order.
609 authlist = [auth for auth in preferred_auths if auth in advertised_authlist]
610 if not authlist:
Fred Drake2f8f4d32001-10-13 18:35:32 +0000611 raise SMTPException("No suitable authentication method found.")
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000612
613 # Some servers advertise authentication methods they don't really
614 # support, so if authentication fails, we continue until we've tried
615 # all methods.
616 for authmethod in authlist:
617 if authmethod == AUTH_CRAM_MD5:
618 (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5)
619 if code == 334:
620 (code, resp) = self.docmd(encode_cram_md5(resp, user, password))
621 elif authmethod == AUTH_PLAIN:
622 (code, resp) = self.docmd("AUTH",
623 AUTH_PLAIN + " " + encode_plain(user, password))
624 elif authmethod == AUTH_LOGIN:
625 (code, resp) = self.docmd("AUTH",
626 "%s %s" % (AUTH_LOGIN, encode_base64(user.encode('ascii'), eol='')))
627 if code == 334:
628 (code, resp) = self.docmd(encode_base64(password.encode('ascii'), eol=''))
629
Guido van Rossumae010462001-09-11 15:57:46 +0000630 # 235 == 'Authentication successful'
631 # 503 == 'Error: already authenticated'
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000632 if code in (235, 503):
633 return (code, resp)
634
635 # We could not login sucessfully. Return result of last attempt.
636 raise SMTPAuthenticationError(code, resp)
Guido van Rossumae010462001-09-11 15:57:46 +0000637
Antoine Pitroue0650202011-05-18 18:03:09 +0200638 def starttls(self, keyfile=None, certfile=None, context=None):
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000639 """Puts the connection to the SMTP server into TLS mode.
Tim Petersb64bec32001-09-18 02:26:39 +0000640
Christian Heimes679db4a2008-01-18 09:56:22 +0000641 If there has been no previous EHLO or HELO command this session, this
642 method tries ESMTP EHLO first.
643
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000644 If the server supports TLS, this will encrypt the rest of the SMTP
645 session. If you provide the keyfile and certfile parameters,
646 the identity of the SMTP server and client can be checked. This,
647 however, depends on whether the socket module really checks the
648 certificates.
Christian Heimes679db4a2008-01-18 09:56:22 +0000649
650 This method may raise the following exceptions:
651
652 SMTPHeloError The server didn't reply properly to
653 the helo greeting.
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000654 """
Christian Heimes679db4a2008-01-18 09:56:22 +0000655 self.ehlo_or_helo_if_needed()
656 if not self.has_extn("starttls"):
657 raise SMTPException("STARTTLS extension not supported by server.")
Tim Petersb64bec32001-09-18 02:26:39 +0000658 (resp, reply) = self.docmd("STARTTLS")
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000659 if resp == 220:
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000660 if not _have_ssl:
661 raise RuntimeError("No SSL support included in this Python")
Antoine Pitroue0650202011-05-18 18:03:09 +0200662 if context is not None and keyfile is not None:
663 raise ValueError("context and keyfile arguments are mutually "
664 "exclusive")
665 if context is not None and certfile is not None:
666 raise ValueError("context and certfile arguments are mutually "
667 "exclusive")
668 if context is not None:
669 self.sock = context.wrap_socket(self.sock)
670 else:
671 self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000672 self.file = SSLFakeFile(self.sock)
Christian Heimes679db4a2008-01-18 09:56:22 +0000673 # RFC 3207:
674 # The client MUST discard any knowledge obtained from
675 # the server, such as the list of SMTP service extensions,
676 # which was not obtained from the TLS negotiation itself.
677 self.helo_resp = None
678 self.ehlo_resp = None
679 self.esmtp_features = {}
680 self.does_esmtp = 0
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000681 return (resp, reply)
Tim Petersb64bec32001-09-18 02:26:39 +0000682
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000683 def sendmail(self, from_addr, to_addrs, msg, mail_options=[],
Tim Peters495ad3c2001-01-15 01:36:40 +0000684 rcpt_options=[]):
685 """This command performs an entire mail transaction.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000686
Tim Peters495ad3c2001-01-15 01:36:40 +0000687 The arguments are:
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000688 - from_addr : The address sending this mail.
689 - to_addrs : A list of addresses to send this mail to. A bare
690 string will be treated as a list with 1 address.
Tim Peters495ad3c2001-01-15 01:36:40 +0000691 - msg : The message to send.
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000692 - mail_options : List of ESMTP options (such as 8bitmime) for the
693 mail command.
694 - rcpt_options : List of ESMTP options (such as DSN commands) for
695 all the rcpt commands.
696
R. David Murray7dff9e02010-11-08 17:15:13 +0000697 msg may be a string containing characters in the ASCII range, or a byte
698 string. A string is encoded to bytes using the ascii codec, and lone
699 \r and \n characters are converted to \r\n characters.
700
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000701 If there has been no previous EHLO or HELO command this session, this
702 method tries ESMTP EHLO first. If the server does ESMTP, message size
703 and each of the specified options will be passed to it. If EHLO
704 fails, HELO will be tried and ESMTP options suppressed.
705
706 This method will return normally if the mail is accepted for at least
Barry Warsawd25c1b71999-11-28 17:11:06 +0000707 one recipient. It returns a dictionary, with one entry for each
708 recipient that was refused. Each entry contains a tuple of the SMTP
709 error code and the accompanying error message sent by the server.
Guido van Rossum296e1431999-04-07 15:03:39 +0000710
711 This method may raise the following exceptions:
712
713 SMTPHeloError The server didn't reply properly to
Tim Peters495ad3c2001-01-15 01:36:40 +0000714 the helo greeting.
Barry Warsawd25c1b71999-11-28 17:11:06 +0000715 SMTPRecipientsRefused The server rejected ALL recipients
Guido van Rossum296e1431999-04-07 15:03:39 +0000716 (no mail was sent).
717 SMTPSenderRefused The server didn't accept the from_addr.
718 SMTPDataError The server replied with an unexpected
719 error code (other than a refusal of
720 a recipient).
721
722 Note: the connection will be open even after an exception is raised.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000723
Guido van Rossum95e6f701998-06-25 02:15:50 +0000724 Example:
Tim Peters495ad3c2001-01-15 01:36:40 +0000725
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000726 >>> import smtplib
727 >>> s=smtplib.SMTP("localhost")
Guido van Rossumfc40a831998-01-29 17:26:45 +0000728 >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"]
Martin v. Löwis301b1cd2002-07-28 16:52:01 +0000729 >>> msg = '''\\
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000730 ... From: Me@my.org
731 ... Subject: testin'...
732 ...
733 ... This is a test '''
734 >>> s.sendmail("me@my.org",tolist,msg)
735 { "three@three.org" : ( 550 ,"User unknown" ) }
736 >>> s.quit()
Tim Peters495ad3c2001-01-15 01:36:40 +0000737
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000738 In the above example, the message was accepted for delivery to three
739 of the four addresses, and one was rejected, with the error code
Barry Warsawd25c1b71999-11-28 17:11:06 +0000740 550. If all addresses are accepted, then the method will return an
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000741 empty dictionary.
742
743 """
Christian Heimes679db4a2008-01-18 09:56:22 +0000744 self.ehlo_or_helo_if_needed()
Guido van Rossum95e6f701998-06-25 02:15:50 +0000745 esmtp_opts = []
R. David Murray7dff9e02010-11-08 17:15:13 +0000746 if isinstance(msg, str):
747 msg = _fix_eols(msg).encode('ascii')
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000748 if self.does_esmtp:
749 # Hmmm? what's this? -ddm
750 # self.esmtp_features['7bit']=""
751 if self.has_extn('size'):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000752 esmtp_opts.append("size=%d" % len(msg))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000753 for option in mail_options:
Guido van Rossum95e6f701998-06-25 02:15:50 +0000754 esmtp_opts.append(option)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000755 (code, resp) = self.mail(from_addr, esmtp_opts)
Fred Drake8152d322000-12-12 23:20:45 +0000756 if code != 250:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000757 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000758 raise SMTPSenderRefused(code, resp, from_addr)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000759 senderrs = {}
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000760 if isinstance(to_addrs, str):
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000761 to_addrs = [to_addrs]
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000762 for each in to_addrs:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000763 (code, resp) = self.rcpt(each, rcpt_options)
Fred Drake8152d322000-12-12 23:20:45 +0000764 if (code != 250) and (code != 251):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000765 senderrs[each] = (code, resp)
766 if len(senderrs) == len(to_addrs):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000767 # the server refused all our recipients
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000768 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000769 raise SMTPRecipientsRefused(senderrs)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000770 (code, resp) = self.data(msg)
Fred Drake8152d322000-12-12 23:20:45 +0000771 if code != 250:
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000772 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000773 raise SMTPDataError(code, resp)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000774 #if we got here then somebody got our mail
Tim Peters495ad3c2001-01-15 01:36:40 +0000775 return senderrs
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000776
R. David Murray7dff9e02010-11-08 17:15:13 +0000777 def send_message(self, msg, from_addr=None, to_addrs=None,
778 mail_options=[], rcpt_options={}):
779 """Converts message to a bytestring and passes it to sendmail.
780
781 The arguments are as for sendmail, except that msg is an
782 email.message.Message object. If from_addr is None, the from_addr is
783 taken from the 'From' header of the Message. If to_addrs is None, its
784 value is composed from the addresses listed in the 'To', 'CC', and
785 'Bcc' fields. Regardless of the values of from_addr and to_addr, any
786 Bcc field in the Message object is deleted. The Message object is then
787 serialized using email.generator.BytesGenerator and sendmail is called
788 to transmit the message.
789 """
790 if from_addr is None:
791 from_addr = msg['From']
792 if to_addrs is None:
793 addr_fields = [f for f in (msg['To'], msg['Bcc'], msg['CC'])
794 if f is not None]
795 to_addrs = [a[1] for a in email.utils.getaddresses(addr_fields)]
796 del msg['Bcc']
797 with io.BytesIO() as bytesmsg:
798 g = email.generator.BytesGenerator(bytesmsg)
799 g.flatten(msg, linesep='\r\n')
800 flatmsg = bytesmsg.getvalue()
801 return self.sendmail(from_addr, to_addrs, flatmsg, mail_options,
802 rcpt_options)
803
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000804 def close(self):
805 """Close the connection to the SMTP server."""
806 if self.file:
807 self.file.close()
808 self.file = None
809 if self.sock:
810 self.sock.close()
811 self.sock = None
812
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000813 def quit(self):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000814 """Terminate the SMTP session."""
Christian Heimesba4af492008-03-28 00:55:15 +0000815 res = self.docmd("quit")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000816 self.close()
Christian Heimesba4af492008-03-28 00:55:15 +0000817 return res
Guido van Rossum95e6f701998-06-25 02:15:50 +0000818
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000819if _have_ssl:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000820
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000821 class SMTP_SSL(SMTP):
822 """ This is a subclass derived from SMTP that connects over an SSL encrypted
823 socket (to use this class you need a socket module that was compiled with SSL
824 support). If host is not specified, '' (the local host) is used. If port is
825 omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile
826 are also optional - they can contain a PEM formatted private key and
Antoine Pitroue0650202011-05-18 18:03:09 +0200827 certificate chain file for the SSL connection. context also optional, can contain
828 a SSLContext, and is an alternative to keyfile and certfile; If it is specified both
829 keyfile and certfile must be None.
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000830 """
Antoine Pitrouc1d52062011-05-07 19:39:37 +0200831
832 default_port = SMTP_SSL_PORT
833
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000834 def __init__(self, host='', port=0, local_hostname=None,
Georg Brandlf78e02b2008-06-10 17:40:04 +0000835 keyfile=None, certfile=None,
Antoine Pitroue0650202011-05-18 18:03:09 +0200836 timeout=socket._GLOBAL_DEFAULT_TIMEOUT, context=None):
837 if context is not None and keyfile is not None:
838 raise ValueError("context and keyfile arguments are mutually "
839 "exclusive")
840 if context is not None and certfile is not None:
841 raise ValueError("context and certfile arguments are mutually "
842 "exclusive")
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000843 self.keyfile = keyfile
844 self.certfile = certfile
Antoine Pitroue0650202011-05-18 18:03:09 +0200845 self.context = context
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000846 SMTP.__init__(self, host, port, local_hostname, timeout)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000847
848 def _get_socket(self, host, port, timeout):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000849 if self.debuglevel > 0:
850 print('connect:', (host, port), file=stderr)
R. David Murray87e20742009-05-23 01:30:26 +0000851 new_socket = socket.create_connection((host, port), timeout)
Antoine Pitroue0650202011-05-18 18:03:09 +0200852 if self.context is not None:
853 new_socket = self.context.wrap_socket(new_socket)
854 else:
855 new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
R. David Murray87e20742009-05-23 01:30:26 +0000856 self.file = SSLFakeFile(new_socket)
857 return new_socket
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000858
859 __all__.append("SMTP_SSL")
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000860
Guido van Rossumd8faa362007-04-27 19:54:29 +0000861#
862# LMTP extension
863#
864LMTP_PORT = 2003
865
866class LMTP(SMTP):
867 """LMTP - Local Mail Transfer Protocol
868
869 The LMTP protocol, which is very similar to ESMTP, is heavily based
870 on the standard SMTP client. It's common to use Unix sockets for LMTP,
871 so our connect() method must support that as well as a regular
872 host:port server. To specify a Unix socket, you must use an absolute
873 path as the host, starting with a '/'.
874
875 Authentication is supported, using the regular SMTP mechanism. When
876 using a Unix socket, LMTP generally don't support or require any
877 authentication, but your mileage might vary."""
878
879 ehlo_msg = "lhlo"
880
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000881 def __init__(self, host='', port=LMTP_PORT, local_hostname=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000882 """Initialize a new instance."""
883 SMTP.__init__(self, host, port, local_hostname)
884
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000885 def connect(self, host='localhost', port=0):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000886 """Connect to the LMTP daemon, on either a Unix or a TCP socket."""
887 if host[0] != '/':
888 return SMTP.connect(self, host, port)
889
890 # Handle Unix-domain sockets.
891 try:
892 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
893 self.sock.connect(host)
894 except socket.error as msg:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000895 if self.debuglevel > 0:
896 print('connect fail:', host, file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000897 if self.sock:
898 self.sock.close()
899 self.sock = None
900 raise socket.error(msg)
901 (code, msg) = self.getreply()
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000902 if self.debuglevel > 0:
903 print('connect:', msg, file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000904 return (code, msg)
905
906
Guido van Rossum95e6f701998-06-25 02:15:50 +0000907# Test the sendmail method, which tests most of the others.
908# Note: This always sends to localhost.
909if __name__ == '__main__':
Andrew M. Kuchling6be424f2001-08-13 14:41:39 +0000910 import sys
Guido van Rossum95e6f701998-06-25 02:15:50 +0000911
912 def prompt(prompt):
913 sys.stdout.write(prompt + ": ")
Eric S. Raymondc013f302001-02-09 05:40:38 +0000914 return sys.stdin.readline().strip()
Guido van Rossum95e6f701998-06-25 02:15:50 +0000915
916 fromaddr = prompt("From")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000917 toaddrs = prompt("To").split(',')
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000918 print("Enter message, end with ^D:")
Guido van Rossum95e6f701998-06-25 02:15:50 +0000919 msg = ''
920 while 1:
921 line = sys.stdin.readline()
922 if not line:
923 break
924 msg = msg + line
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000925 print("Message length is %d" % len(msg))
Guido van Rossum95e6f701998-06-25 02:15:50 +0000926
927 server = SMTP('localhost')
928 server.set_debuglevel(1)
929 server.sendmail(fromaddr, toaddrs, msg)
930 server.quit()