blob: 213138c86e0db36267c7a61c4e461d4534565e14 [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
Guido van Rossum95e6f701998-06-25 02:15:50 +0000234
Georg Brandlf78e02b2008-06-10 17:40:04 +0000235 def __init__(self, host='', port=0, local_hostname=None,
236 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000237 """Initialize a new instance.
238
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000239 If specified, `host' is the name of the remote host to which to
240 connect. If specified, `port' specifies the port to which to connect.
Barry Warsawd25c1b71999-11-28 17:11:06 +0000241 By default, smtplib.SMTP_PORT is used. An SMTPConnectError is raised
Neil Schemenauer6730f262002-03-24 15:30:40 +0000242 if the specified `host' doesn't respond correctly. If specified,
Tim Peters863ac442002-04-16 01:38:40 +0000243 `local_hostname` is used as the FQDN of the local host. By default,
244 the local hostname is found using socket.getfqdn().
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000245
246 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000247 self.timeout = timeout
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000248 self.esmtp_features = {}
Thomas Wouters89f507f2006-12-13 04:49:30 +0000249 self.default_port = SMTP_PORT
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
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000638 def starttls(self, keyfile=None, certfile=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")
Thomas Wouters1b7f8912007-09-19 03:06:30 +0000662 self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000663 self.file = SSLFakeFile(self.sock)
Christian Heimes679db4a2008-01-18 09:56:22 +0000664 # RFC 3207:
665 # The client MUST discard any knowledge obtained from
666 # the server, such as the list of SMTP service extensions,
667 # which was not obtained from the TLS negotiation itself.
668 self.helo_resp = None
669 self.ehlo_resp = None
670 self.esmtp_features = {}
671 self.does_esmtp = 0
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000672 return (resp, reply)
Tim Petersb64bec32001-09-18 02:26:39 +0000673
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000674 def sendmail(self, from_addr, to_addrs, msg, mail_options=[],
Tim Peters495ad3c2001-01-15 01:36:40 +0000675 rcpt_options=[]):
676 """This command performs an entire mail transaction.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000677
Tim Peters495ad3c2001-01-15 01:36:40 +0000678 The arguments are:
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000679 - from_addr : The address sending this mail.
680 - to_addrs : A list of addresses to send this mail to. A bare
681 string will be treated as a list with 1 address.
Tim Peters495ad3c2001-01-15 01:36:40 +0000682 - msg : The message to send.
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000683 - mail_options : List of ESMTP options (such as 8bitmime) for the
684 mail command.
685 - rcpt_options : List of ESMTP options (such as DSN commands) for
686 all the rcpt commands.
687
R. David Murray7dff9e02010-11-08 17:15:13 +0000688 msg may be a string containing characters in the ASCII range, or a byte
689 string. A string is encoded to bytes using the ascii codec, and lone
690 \r and \n characters are converted to \r\n characters.
691
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000692 If there has been no previous EHLO or HELO command this session, this
693 method tries ESMTP EHLO first. If the server does ESMTP, message size
694 and each of the specified options will be passed to it. If EHLO
695 fails, HELO will be tried and ESMTP options suppressed.
696
697 This method will return normally if the mail is accepted for at least
Barry Warsawd25c1b71999-11-28 17:11:06 +0000698 one recipient. It returns a dictionary, with one entry for each
699 recipient that was refused. Each entry contains a tuple of the SMTP
700 error code and the accompanying error message sent by the server.
Guido van Rossum296e1431999-04-07 15:03:39 +0000701
702 This method may raise the following exceptions:
703
704 SMTPHeloError The server didn't reply properly to
Tim Peters495ad3c2001-01-15 01:36:40 +0000705 the helo greeting.
Barry Warsawd25c1b71999-11-28 17:11:06 +0000706 SMTPRecipientsRefused The server rejected ALL recipients
Guido van Rossum296e1431999-04-07 15:03:39 +0000707 (no mail was sent).
708 SMTPSenderRefused The server didn't accept the from_addr.
709 SMTPDataError The server replied with an unexpected
710 error code (other than a refusal of
711 a recipient).
712
713 Note: the connection will be open even after an exception is raised.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000714
Guido van Rossum95e6f701998-06-25 02:15:50 +0000715 Example:
Tim Peters495ad3c2001-01-15 01:36:40 +0000716
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000717 >>> import smtplib
718 >>> s=smtplib.SMTP("localhost")
Guido van Rossumfc40a831998-01-29 17:26:45 +0000719 >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"]
Martin v. Löwis301b1cd2002-07-28 16:52:01 +0000720 >>> msg = '''\\
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000721 ... From: Me@my.org
722 ... Subject: testin'...
723 ...
724 ... This is a test '''
725 >>> s.sendmail("me@my.org",tolist,msg)
726 { "three@three.org" : ( 550 ,"User unknown" ) }
727 >>> s.quit()
Tim Peters495ad3c2001-01-15 01:36:40 +0000728
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000729 In the above example, the message was accepted for delivery to three
730 of the four addresses, and one was rejected, with the error code
Barry Warsawd25c1b71999-11-28 17:11:06 +0000731 550. If all addresses are accepted, then the method will return an
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000732 empty dictionary.
733
734 """
Christian Heimes679db4a2008-01-18 09:56:22 +0000735 self.ehlo_or_helo_if_needed()
Guido van Rossum95e6f701998-06-25 02:15:50 +0000736 esmtp_opts = []
R. David Murray7dff9e02010-11-08 17:15:13 +0000737 if isinstance(msg, str):
738 msg = _fix_eols(msg).encode('ascii')
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000739 if self.does_esmtp:
740 # Hmmm? what's this? -ddm
741 # self.esmtp_features['7bit']=""
742 if self.has_extn('size'):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000743 esmtp_opts.append("size=%d" % len(msg))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000744 for option in mail_options:
Guido van Rossum95e6f701998-06-25 02:15:50 +0000745 esmtp_opts.append(option)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000746 (code, resp) = self.mail(from_addr, esmtp_opts)
Fred Drake8152d322000-12-12 23:20:45 +0000747 if code != 250:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000748 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000749 raise SMTPSenderRefused(code, resp, from_addr)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000750 senderrs = {}
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000751 if isinstance(to_addrs, str):
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000752 to_addrs = [to_addrs]
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000753 for each in to_addrs:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000754 (code, resp) = self.rcpt(each, rcpt_options)
Fred Drake8152d322000-12-12 23:20:45 +0000755 if (code != 250) and (code != 251):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000756 senderrs[each] = (code, resp)
757 if len(senderrs) == len(to_addrs):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000758 # the server refused all our recipients
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000759 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000760 raise SMTPRecipientsRefused(senderrs)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000761 (code, resp) = self.data(msg)
Fred Drake8152d322000-12-12 23:20:45 +0000762 if code != 250:
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000763 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000764 raise SMTPDataError(code, resp)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000765 #if we got here then somebody got our mail
Tim Peters495ad3c2001-01-15 01:36:40 +0000766 return senderrs
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000767
R. David Murray7dff9e02010-11-08 17:15:13 +0000768 def send_message(self, msg, from_addr=None, to_addrs=None,
769 mail_options=[], rcpt_options={}):
770 """Converts message to a bytestring and passes it to sendmail.
771
772 The arguments are as for sendmail, except that msg is an
773 email.message.Message object. If from_addr is None, the from_addr is
774 taken from the 'From' header of the Message. If to_addrs is None, its
775 value is composed from the addresses listed in the 'To', 'CC', and
776 'Bcc' fields. Regardless of the values of from_addr and to_addr, any
777 Bcc field in the Message object is deleted. The Message object is then
778 serialized using email.generator.BytesGenerator and sendmail is called
779 to transmit the message.
780 """
781 if from_addr is None:
782 from_addr = msg['From']
783 if to_addrs is None:
784 addr_fields = [f for f in (msg['To'], msg['Bcc'], msg['CC'])
785 if f is not None]
786 to_addrs = [a[1] for a in email.utils.getaddresses(addr_fields)]
787 del msg['Bcc']
788 with io.BytesIO() as bytesmsg:
789 g = email.generator.BytesGenerator(bytesmsg)
790 g.flatten(msg, linesep='\r\n')
791 flatmsg = bytesmsg.getvalue()
792 return self.sendmail(from_addr, to_addrs, flatmsg, mail_options,
793 rcpt_options)
794
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000795 def close(self):
796 """Close the connection to the SMTP server."""
797 if self.file:
798 self.file.close()
799 self.file = None
800 if self.sock:
801 self.sock.close()
802 self.sock = None
803
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000804 def quit(self):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000805 """Terminate the SMTP session."""
Christian Heimesba4af492008-03-28 00:55:15 +0000806 res = self.docmd("quit")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000807 self.close()
Christian Heimesba4af492008-03-28 00:55:15 +0000808 return res
Guido van Rossum95e6f701998-06-25 02:15:50 +0000809
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000810if _have_ssl:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000811
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000812 class SMTP_SSL(SMTP):
813 """ This is a subclass derived from SMTP that connects over an SSL encrypted
814 socket (to use this class you need a socket module that was compiled with SSL
815 support). If host is not specified, '' (the local host) is used. If port is
816 omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile
817 are also optional - they can contain a PEM formatted private key and
818 certificate chain file for the SSL connection.
819 """
820 def __init__(self, host='', port=0, local_hostname=None,
Georg Brandlf78e02b2008-06-10 17:40:04 +0000821 keyfile=None, certfile=None,
822 timeout=socket._GLOBAL_DEFAULT_TIMEOUT):
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000823 self.keyfile = keyfile
824 self.certfile = certfile
825 SMTP.__init__(self, host, port, local_hostname, timeout)
826 self.default_port = SMTP_SSL_PORT
827
828 def _get_socket(self, host, port, timeout):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000829 if self.debuglevel > 0:
830 print('connect:', (host, port), file=stderr)
R. David Murray87e20742009-05-23 01:30:26 +0000831 new_socket = socket.create_connection((host, port), timeout)
832 new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
833 self.file = SSLFakeFile(new_socket)
834 return new_socket
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000835
836 __all__.append("SMTP_SSL")
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000837
Guido van Rossumd8faa362007-04-27 19:54:29 +0000838#
839# LMTP extension
840#
841LMTP_PORT = 2003
842
843class LMTP(SMTP):
844 """LMTP - Local Mail Transfer Protocol
845
846 The LMTP protocol, which is very similar to ESMTP, is heavily based
847 on the standard SMTP client. It's common to use Unix sockets for LMTP,
848 so our connect() method must support that as well as a regular
849 host:port server. To specify a Unix socket, you must use an absolute
850 path as the host, starting with a '/'.
851
852 Authentication is supported, using the regular SMTP mechanism. When
853 using a Unix socket, LMTP generally don't support or require any
854 authentication, but your mileage might vary."""
855
856 ehlo_msg = "lhlo"
857
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000858 def __init__(self, host='', port=LMTP_PORT, local_hostname=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000859 """Initialize a new instance."""
860 SMTP.__init__(self, host, port, local_hostname)
861
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000862 def connect(self, host='localhost', port=0):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000863 """Connect to the LMTP daemon, on either a Unix or a TCP socket."""
864 if host[0] != '/':
865 return SMTP.connect(self, host, port)
866
867 # Handle Unix-domain sockets.
868 try:
869 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
870 self.sock.connect(host)
871 except socket.error as msg:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000872 if self.debuglevel > 0:
873 print('connect fail:', host, file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000874 if self.sock:
875 self.sock.close()
876 self.sock = None
877 raise socket.error(msg)
878 (code, msg) = self.getreply()
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000879 if self.debuglevel > 0:
880 print('connect:', msg, file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000881 return (code, msg)
882
883
Guido van Rossum95e6f701998-06-25 02:15:50 +0000884# Test the sendmail method, which tests most of the others.
885# Note: This always sends to localhost.
886if __name__ == '__main__':
Andrew M. Kuchling6be424f2001-08-13 14:41:39 +0000887 import sys
Guido van Rossum95e6f701998-06-25 02:15:50 +0000888
889 def prompt(prompt):
890 sys.stdout.write(prompt + ": ")
Eric S. Raymondc013f302001-02-09 05:40:38 +0000891 return sys.stdin.readline().strip()
Guido van Rossum95e6f701998-06-25 02:15:50 +0000892
893 fromaddr = prompt("From")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000894 toaddrs = prompt("To").split(',')
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000895 print("Enter message, end with ^D:")
Guido van Rossum95e6f701998-06-25 02:15:50 +0000896 msg = ''
897 while 1:
898 line = sys.stdin.readline()
899 if not line:
900 break
901 msg = msg + line
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000902 print("Message length is %d" % len(msg))
Guido van Rossum95e6f701998-06-25 02:15:50 +0000903
904 server = SMTP('localhost')
905 server.set_debuglevel(1)
906 server.sendmail(fromaddr, toaddrs, msg)
907 server.quit()