blob: 7f49f2397c66db055e8fadf2db0e82eb955e384c [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
R David Murrayac4e5ab2011-07-02 21:03:19 -040052import copy
R David Murray0c49b892015-04-16 17:14:42 -040053import datetime
54import sys
Barry Warsaw2cc1f6d2007-08-30 14:28:55 +000055from email.base64mime import body_encode as encode_base64
Guido van Rossumbbe323e1998-01-29 17:24:40 +000056
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +000057__all__ = ["SMTPException", "SMTPServerDisconnected", "SMTPResponseException",
58 "SMTPSenderRefused", "SMTPRecipientsRefused", "SMTPDataError",
59 "SMTPConnectError", "SMTPHeloError", "SMTPAuthenticationError",
60 "quoteaddr", "quotedata", "SMTP"]
Skip Montanaro0de65802001-02-15 22:15:14 +000061
Guido van Rossumbbe323e1998-01-29 17:24:40 +000062SMTP_PORT = 25
Thomas Wouters89f507f2006-12-13 04:49:30 +000063SMTP_SSL_PORT = 465
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +000064CRLF = "\r\n"
65bCRLF = b"\r\n"
Georg Brandlb38b5c42014-02-10 22:11:21 +010066_MAXLINE = 8192 # more than 8 times larger than RFC 821, 4.5.3
Guido van Rossumbbe323e1998-01-29 17:24:40 +000067
Piers Lauder385a77a2002-07-27 00:38:30 +000068OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
69
Tim Peters495ad3c2001-01-15 01:36:40 +000070# Exception classes used by this module.
R David Murray8a345962013-04-14 06:46:35 -040071class SMTPException(OSError):
Guido van Rossum296e1431999-04-07 15:03:39 +000072 """Base class for all exceptions raised by this module."""
73
74class SMTPServerDisconnected(SMTPException):
75 """Not connected to any SMTP server.
76
77 This exception is raised when the server unexpectedly disconnects,
78 or when an attempt is made to use the SMTP instance before
79 connecting it to a server.
80 """
81
82class SMTPResponseException(SMTPException):
83 """Base class for all exceptions that include an SMTP error code.
84
85 These exceptions are generated in some instances when the SMTP
86 server returns an error code. The error code is stored in the
87 `smtp_code' attribute of the error, and the `smtp_error' attribute
88 is set to the error message.
89 """
90
91 def __init__(self, code, msg):
92 self.smtp_code = code
93 self.smtp_error = msg
94 self.args = (code, msg)
95
96class SMTPSenderRefused(SMTPResponseException):
97 """Sender address refused.
Guido van Rossumae010462001-09-11 15:57:46 +000098
Guido van Rossum296e1431999-04-07 15:03:39 +000099 In addition to the attributes set by on all SMTPResponseException
Barry Warsawd25c1b71999-11-28 17:11:06 +0000100 exceptions, this sets `sender' to the string that the SMTP refused.
Guido van Rossum296e1431999-04-07 15:03:39 +0000101 """
102
103 def __init__(self, code, msg, sender):
104 self.smtp_code = code
105 self.smtp_error = msg
106 self.sender = sender
107 self.args = (code, msg, sender)
108
Guido van Rossum20c92281999-04-21 16:52:20 +0000109class SMTPRecipientsRefused(SMTPException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000110 """All recipient addresses refused.
Guido van Rossumae010462001-09-11 15:57:46 +0000111
Thomas Wouters7e474022000-07-16 12:04:32 +0000112 The errors for each recipient are accessible through the attribute
Tim Peters495ad3c2001-01-15 01:36:40 +0000113 'recipients', which is a dictionary of exactly the same sort as
114 SMTP.sendmail() returns.
Guido van Rossum296e1431999-04-07 15:03:39 +0000115 """
116
117 def __init__(self, recipients):
118 self.recipients = recipients
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000119 self.args = (recipients,)
Guido van Rossum296e1431999-04-07 15:03:39 +0000120
121
Guido van Rossum296e1431999-04-07 15:03:39 +0000122class SMTPDataError(SMTPResponseException):
123 """The SMTP server didn't accept the data."""
124
125class SMTPConnectError(SMTPResponseException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000126 """Error during connection establishment."""
Guido van Rossum296e1431999-04-07 15:03:39 +0000127
128class SMTPHeloError(SMTPResponseException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000129 """The server refused our HELO reply."""
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000130
Guido van Rossumae010462001-09-11 15:57:46 +0000131class SMTPAuthenticationError(SMTPResponseException):
132 """Authentication error.
133
134 Most probably the server didn't accept the username/password
135 combination provided.
136 """
Peter Schneider-Kamp7bc82bb2000-08-10 14:02:23 +0000137
R David Murray4c14bba2011-07-18 21:59:53 -0400138def quoteaddr(addrstring):
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000139 """Quote a subset of the email addresses defined by RFC 821.
140
Georg Brandl9f0f9602008-06-12 22:23:59 +0000141 Should be able to handle anything email.utils.parseaddr can handle.
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000142 """
R David Murray4c14bba2011-07-18 21:59:53 -0400143 displayname, addr = email.utils.parseaddr(addrstring)
144 if (displayname, addr) == ('', ''):
145 # parseaddr couldn't parse it, use it as is and hope for the best.
146 if addrstring.strip().startswith('<'):
147 return addrstring
148 return "<%s>" % addrstring
149 return "<%s>" % addr
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000150
R David Murray46346762011-07-18 21:38:54 -0400151def _addr_only(addrstring):
152 displayname, addr = email.utils.parseaddr(addrstring)
153 if (displayname, addr) == ('', ''):
154 # parseaddr couldn't parse it, so use it as is.
155 return addrstring
156 return addr
157
R. David Murray7dff9e02010-11-08 17:15:13 +0000158# Legacy method kept for backward compatibility.
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000159def quotedata(data):
160 """Quote data for email.
161
Barry Warsawd25c1b71999-11-28 17:11:06 +0000162 Double leading '.', and change Unix newline '\\n', or Mac '\\r' into
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000163 Internet CRLF end-of-line.
164 """
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000165 return re.sub(r'(?m)^\.', '..',
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000166 re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000167
R. David Murray7dff9e02010-11-08 17:15:13 +0000168def _quote_periods(bindata):
R David Murray0f663d02011-06-09 15:05:57 -0400169 return re.sub(br'(?m)^\.', b'..', bindata)
R. David Murray7dff9e02010-11-08 17:15:13 +0000170
171def _fix_eols(data):
172 return re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data)
173
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000174try:
175 import ssl
Brett Cannoncd171c82013-07-04 17:43:24 -0400176except ImportError:
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000177 _have_ssl = False
178else:
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000179 _have_ssl = True
180
Peter Schneider-Kamp7bc82bb2000-08-10 14:02:23 +0000181
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000182class SMTP:
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000183 """This class manages a connection to an SMTP or ESMTP server.
184 SMTP Objects:
Tim Peters495ad3c2001-01-15 01:36:40 +0000185 SMTP objects have the following attributes:
186 helo_resp
187 This is the message given by the server in response to the
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000188 most recent HELO command.
Tim Peters495ad3c2001-01-15 01:36:40 +0000189
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000190 ehlo_resp
Tim Peters495ad3c2001-01-15 01:36:40 +0000191 This is the message given by the server in response to the
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000192 most recent EHLO command. This is usually multiline.
193
Tim Peters495ad3c2001-01-15 01:36:40 +0000194 does_esmtp
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000195 This is a True value _after you do an EHLO command_, if the
196 server supports ESMTP.
197
Tim Peters495ad3c2001-01-15 01:36:40 +0000198 esmtp_features
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000199 This is a dictionary, which, if the server supports ESMTP,
Barry Warsawd25c1b71999-11-28 17:11:06 +0000200 will _after you do an EHLO command_, contain the names of the
201 SMTP service extensions this server supports, and their
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000202 parameters (if any).
Barry Warsawd25c1b71999-11-28 17:11:06 +0000203
Tim Peters495ad3c2001-01-15 01:36:40 +0000204 Note, all extension names are mapped to lower case in the
205 dictionary.
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000206
Barry Warsawd25c1b71999-11-28 17:11:06 +0000207 See each method's docstrings for details. In general, there is a
208 method of the same name to perform each SMTP command. There is also a
209 method called 'sendmail' that will do an entire mail transaction.
210 """
Guido van Rossum95e6f701998-06-25 02:15:50 +0000211 debuglevel = 0
212 file = None
213 helo_resp = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000214 ehlo_msg = "ehlo"
Guido van Rossum95e6f701998-06-25 02:15:50 +0000215 ehlo_resp = None
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000216 does_esmtp = 0
Antoine Pitrouc1d52062011-05-07 19:39:37 +0200217 default_port = SMTP_PORT
Guido van Rossum95e6f701998-06-25 02:15:50 +0000218
Georg Brandlf78e02b2008-06-10 17:40:04 +0000219 def __init__(self, host='', port=0, local_hostname=None,
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800220 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
221 source_address=None):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000222 """Initialize a new instance.
223
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000224 If specified, `host' is the name of the remote host to which to
225 connect. If specified, `port' specifies the port to which to connect.
R David Murray14ee3cf2013-04-13 14:40:33 -0400226 By default, smtplib.SMTP_PORT is used. If a host is specified the
R David Murray021362d2013-06-23 16:05:44 -0400227 connect method is called, and if it returns anything other than a
228 success code an SMTPConnectError is raised. If specified,
229 `local_hostname` is used as the FQDN of the local host in the HELO/EHLO
230 command. Otherwise, the local hostname is found using
231 socket.getfqdn(). The `source_address` parameter takes a 2-tuple (host,
232 port) for the socket to bind to as its source address before
233 connecting. If the host is '' and port is 0, the OS default behavior
234 will be used.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000235
236 """
Christian Heimesa5768f72013-12-02 20:44:17 +0100237 self._host = host
Guido van Rossumd8faa362007-04-27 19:54:29 +0000238 self.timeout = timeout
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000239 self.esmtp_features = {}
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800240 self.source_address = source_address
241
Guido van Rossum296e1431999-04-07 15:03:39 +0000242 if host:
243 (code, msg) = self.connect(host, port)
244 if code != 220:
245 raise SMTPConnectError(code, msg)
Raymond Hettingerf13eb552002-06-02 00:40:05 +0000246 if local_hostname is not None:
Barry Warsaw13e34f72002-03-26 20:27:35 +0000247 self.local_hostname = local_hostname
Neil Schemenauer6730f262002-03-24 15:30:40 +0000248 else:
Barry Warsaw13e34f72002-03-26 20:27:35 +0000249 # RFC 2821 says we should use the fqdn in the EHLO/HELO verb, and
250 # if that can't be calculated, that we should use a domain literal
251 # instead (essentially an encoded IP address like [A.B.C.D]).
252 fqdn = socket.getfqdn()
253 if '.' in fqdn:
254 self.local_hostname = fqdn
255 else:
256 # We can't find an fqdn hostname, so use a domain literal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000257 addr = '127.0.0.1'
258 try:
259 addr = socket.gethostbyname(socket.gethostname())
260 except socket.gaierror:
261 pass
Barry Warsaw13e34f72002-03-26 20:27:35 +0000262 self.local_hostname = '[%s]' % addr
Tim Peters495ad3c2001-01-15 01:36:40 +0000263
Barry Warsaw1f5c9582011-03-15 15:04:44 -0400264 def __enter__(self):
265 return self
266
267 def __exit__(self, *args):
268 try:
269 code, message = self.docmd("QUIT")
270 if code != 221:
271 raise SMTPResponseException(code, message)
272 except SMTPServerDisconnected:
273 pass
274 finally:
275 self.close()
276
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000277 def set_debuglevel(self, debuglevel):
278 """Set the debug output level.
279
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000280 A non-false value results in debug messages for connection and for all
281 messages sent to and received from the server.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000282
283 """
284 self.debuglevel = debuglevel
285
R David Murray0c49b892015-04-16 17:14:42 -0400286 def _print_debug(self, *args):
287 if self.debuglevel > 1:
288 print(datetime.datetime.now().time(), *args, file=sys.stderr)
289 else:
290 print(*args, file=sys.stderr)
291
Barry Warsawc9181712008-03-19 14:25:51 +0000292 def _get_socket(self, host, port, timeout):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000293 # This makes it simpler for SMTP_SSL to use the SMTP connect code
294 # and just alter the socket connection bit.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000295 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400296 self._print_debug('connect: to', (host, port), self.source_address)
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800297 return socket.create_connection((host, port), timeout,
298 self.source_address)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000299
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800300 def connect(self, host='localhost', port=0, source_address=None):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000301 """Connect to a host on a given port.
Guido van Rossum95e6f701998-06-25 02:15:50 +0000302
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000303 If the hostname ends with a colon (`:') followed by a number, and
304 there is no port specified, that suffix will be stripped off and the
305 number interpreted as the port number to use.
Guido van Rossum95e6f701998-06-25 02:15:50 +0000306
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000307 Note: This method is automatically invoked by __init__, if a host is
308 specified during instantiation.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000309
310 """
Senthil Kumaranb351a482011-07-31 09:14:17 +0800311
312 if source_address:
313 self.source_address = source_address
314
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000315 if not port and (host.find(':') == host.rfind(':')):
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000316 i = host.rfind(':')
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000317 if i >= 0:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000318 host, port = host[:i], host[i + 1:]
319 try:
320 port = int(port)
Eric S. Raymond8d876032001-02-09 10:14:53 +0000321 except ValueError:
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200322 raise OSError("nonnumeric port")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000323 if not port:
324 port = self.default_port
325 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400326 self._print_debug('connect:', (host, port))
Guido van Rossumd8faa362007-04-27 19:54:29 +0000327 self.sock = self._get_socket(host, port, self.timeout)
Antoine Pitrouf068ab82011-06-06 19:17:09 +0200328 self.file = None
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000329 (code, msg) = self.getreply()
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000330 if self.debuglevel > 0:
R David Murray37f1ba92015-04-16 18:54:56 -0400331 self._print_debug('connect:', repr(msg))
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000332 return (code, msg)
Tim Peters495ad3c2001-01-15 01:36:40 +0000333
Guido van Rossum8a392d72007-11-21 22:09:45 +0000334 def send(self, s):
335 """Send `s' to the server."""
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000336 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400337 self._print_debug('send:', repr(s))
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000338 if hasattr(self, 'sock') and self.sock:
Guido van Rossum8a392d72007-11-21 22:09:45 +0000339 if isinstance(s, str):
340 s = s.encode("ascii")
Guido van Rossum2880f6e1998-08-10 20:07:00 +0000341 try:
Guido van Rossum8a392d72007-11-21 22:09:45 +0000342 self.sock.sendall(s)
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200343 except OSError:
Barry Warsaw76750972001-12-14 20:34:20 +0000344 self.close()
Guido van Rossum40233ea1999-01-15 03:23:55 +0000345 raise SMTPServerDisconnected('Server not connected')
Guido van Rossumfc40a831998-01-29 17:26:45 +0000346 else:
Guido van Rossum40233ea1999-01-15 03:23:55 +0000347 raise SMTPServerDisconnected('please run connect() first')
Tim Peters495ad3c2001-01-15 01:36:40 +0000348
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000349 def putcmd(self, cmd, args=""):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000350 """Send a command to the server."""
Guido van Rossumdb23d3d1999-06-09 15:13:10 +0000351 if args == "":
352 str = '%s%s' % (cmd, CRLF)
353 else:
354 str = '%s %s%s' % (cmd, args, CRLF)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000355 self.send(str)
Tim Peters495ad3c2001-01-15 01:36:40 +0000356
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000357 def getreply(self):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000358 """Get a reply from the server.
Tim Peters495ad3c2001-01-15 01:36:40 +0000359
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000360 Returns a tuple consisting of:
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000361
362 - server response code (e.g. '250', or such, if all goes well)
363 Note: returns -1 if it can't read response code.
364
365 - server response string corresponding to response code (multiline
366 responses are converted to a single, multiline string).
Guido van Rossumf123f841999-03-29 20:33:21 +0000367
368 Raises SMTPServerDisconnected if end-of-file is reached.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000369 """
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000370 resp = []
Guido van Rossum296e1431999-04-07 15:03:39 +0000371 if self.file is None:
372 self.file = self.sock.makefile('rb')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000373 while 1:
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000374 try:
Georg Brandlb38b5c42014-02-10 22:11:21 +0100375 line = self.file.readline(_MAXLINE + 1)
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200376 except OSError as e:
Antoine Pitrou6b2e1602011-08-28 01:20:42 +0200377 self.close()
378 raise SMTPServerDisconnected("Connection unexpectedly closed: "
379 + str(e))
Guido van Rossum806c2462007-08-06 23:33:07 +0000380 if not line:
Guido van Rossum296e1431999-04-07 15:03:39 +0000381 self.close()
382 raise SMTPServerDisconnected("Connection unexpectedly closed")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000383 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400384 self._print_debug('reply:', repr(line))
Georg Brandlb38b5c42014-02-10 22:11:21 +0100385 if len(line) > _MAXLINE:
Senthil Kumaran4ce118e2014-06-03 07:24:54 -0700386 self.close()
Georg Brandlb38b5c42014-02-10 22:11:21 +0100387 raise SMTPResponseException(500, "Line too long.")
Guido van Rossum806c2462007-08-06 23:33:07 +0000388 resp.append(line[4:].strip(b' \t\r\n'))
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000389 code = line[:3]
Guido van Rossum296e1431999-04-07 15:03:39 +0000390 # Check that the error code is syntactically correct.
391 # Don't attempt to read a continuation line if it is broken.
392 try:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000393 errcode = int(code)
Guido van Rossum296e1431999-04-07 15:03:39 +0000394 except ValueError:
395 errcode = -1
396 break
Guido van Rossumf123f841999-03-29 20:33:21 +0000397 # Check if multiline response.
Guido van Rossum806c2462007-08-06 23:33:07 +0000398 if line[3:4] != b"-":
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000399 break
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000400
Guido van Rossumc43e79f2007-06-18 18:26:36 +0000401 errmsg = b"\n".join(resp)
Tim Peters495ad3c2001-01-15 01:36:40 +0000402 if self.debuglevel > 0:
R David Murray37f1ba92015-04-16 18:54:56 -0400403 self._print_debug('reply: retcode (%s); Msg: %a' % (errcode, errmsg))
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000404 return errcode, errmsg
Tim Peters495ad3c2001-01-15 01:36:40 +0000405
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000406 def docmd(self, cmd, args=""):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000407 """Send a command, and return its response code."""
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000408 self.putcmd(cmd, args)
Guido van Rossum296e1431999-04-07 15:03:39 +0000409 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000410
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000411 # std smtp commands
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000412 def helo(self, name=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000413 """SMTP 'helo' command.
414 Hostname to send for this command defaults to the FQDN of the local
415 host.
416 """
Neil Schemenauer6730f262002-03-24 15:30:40 +0000417 self.putcmd("helo", name or self.local_hostname)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000418 (code, msg) = self.getreply()
419 self.helo_resp = msg
420 return (code, msg)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000421
Guido van Rossum95e6f701998-06-25 02:15:50 +0000422 def ehlo(self, name=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000423 """ SMTP 'ehlo' command.
424 Hostname to send for this command defaults to the FQDN of the local
425 host.
426 """
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000427 self.esmtp_features = {}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000428 self.putcmd(self.ehlo_msg, name or self.local_hostname)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000429 (code, msg) = self.getreply()
Tim Peters495ad3c2001-01-15 01:36:40 +0000430 # According to RFC1869 some (badly written)
431 # MTA's will disconnect on an ehlo. Toss an exception if
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000432 # that happens -ddm
433 if code == -1 and len(msg) == 0:
Barry Warsaw76750972001-12-14 20:34:20 +0000434 self.close()
Guido van Rossum40233ea1999-01-15 03:23:55 +0000435 raise SMTPServerDisconnected("Server not connected")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000436 self.ehlo_resp = msg
Fred Drake8152d322000-12-12 23:20:45 +0000437 if code != 250:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000438 return (code, msg)
439 self.does_esmtp = 1
Thomas Wouters7e474022000-07-16 12:04:32 +0000440 #parse the ehlo response -ddm
Guido van Rossum04110fb2007-08-24 16:32:05 +0000441 assert isinstance(self.ehlo_resp, bytes), repr(self.ehlo_resp)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000442 resp = self.ehlo_resp.decode("latin-1").split('\n')
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000443 del resp[0]
Guido van Rossum2880f6e1998-08-10 20:07:00 +0000444 for each in resp:
Piers Lauder385a77a2002-07-27 00:38:30 +0000445 # To be able to communicate with as many SMTP servers as possible,
446 # we have to take the old-style auth advertisement into account,
447 # because:
448 # 1) Else our SMTP feature parser gets confused.
449 # 2) There are some servers that only advertise the auth methods we
450 # support using the old style.
451 auth_match = OLDSTYLE_AUTH.match(each)
452 if auth_match:
453 # This doesn't remove duplicates, but that's no problem
454 self.esmtp_features["auth"] = self.esmtp_features.get("auth", "") \
455 + " " + auth_match.groups(0)[0]
456 continue
457
Barry Warsawbe22ae62002-04-15 20:03:30 +0000458 # RFC 1869 requires a space between ehlo keyword and parameters.
459 # It's actually stricter, in that only spaces are allowed between
460 # parameters, but were not going to check for that here. Note
461 # that the space isn't present if there are no parameters.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000462 m = re.match(r'(?P<feature>[A-Za-z0-9][A-Za-z0-9\-]*) ?', each)
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000463 if m:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000464 feature = m.group("feature").lower()
465 params = m.string[m.end("feature"):].strip()
Piers Lauder385a77a2002-07-27 00:38:30 +0000466 if feature == "auth":
467 self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \
468 + " " + params
469 else:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000470 self.esmtp_features[feature] = params
471 return (code, msg)
Guido van Rossum95e6f701998-06-25 02:15:50 +0000472
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000473 def has_extn(self, opt):
474 """Does the server support a given SMTP service extension?"""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000475 return opt.lower() in self.esmtp_features
Guido van Rossum95e6f701998-06-25 02:15:50 +0000476
Guido van Rossum18586f41998-04-03 17:03:13 +0000477 def help(self, args=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000478 """SMTP 'help' command.
479 Returns help text from server."""
Guido van Rossum18586f41998-04-03 17:03:13 +0000480 self.putcmd("help", args)
Kurt B. Kaiser58bd1902005-06-26 18:27:36 +0000481 return self.getreply()[1]
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000482
483 def rset(self):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000484 """SMTP 'rset' command -- resets session."""
Guido van Rossum296e1431999-04-07 15:03:39 +0000485 return self.docmd("rset")
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000486
R David Murrayafb151a2014-04-14 18:21:38 -0400487 def _rset(self):
488 """Internal 'rset' command which ignores any SMTPServerDisconnected error.
489
490 Used internally in the library, since the server disconnected error
491 should appear to the application when the *next* command is issued, if
492 we are doing an internal "safety" reset.
493 """
494 try:
495 self.rset()
496 except SMTPServerDisconnected:
497 pass
498
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000499 def noop(self):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000500 """SMTP 'noop' command -- doesn't do anything :>"""
Guido van Rossum296e1431999-04-07 15:03:39 +0000501 return self.docmd("noop")
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000502
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000503 def mail(self, sender, options=[]):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000504 """SMTP 'mail' command -- begins mail xfer session."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000505 optionlist = ''
506 if options and self.does_esmtp:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000507 optionlist = ' ' + ' '.join(options)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000508 self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000509 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000510
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000511 def rcpt(self, recip, options=[]):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000512 """SMTP 'rcpt' command -- indicates 1 recipient for this mail."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000513 optionlist = ''
514 if options and self.does_esmtp:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000515 optionlist = ' ' + ' '.join(options)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000516 self.putcmd("rcpt", "TO:%s%s" % (quoteaddr(recip), optionlist))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000517 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000518
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000519 def data(self, msg):
Tim Peters495ad3c2001-01-15 01:36:40 +0000520 """SMTP 'DATA' command -- sends message data to server.
Guido van Rossum296e1431999-04-07 15:03:39 +0000521
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000522 Automatically quotes lines beginning with a period per rfc821.
Guido van Rossum296e1431999-04-07 15:03:39 +0000523 Raises SMTPDataError if there is an unexpected reply to the
524 DATA command; the return value from this method is the final
R. David Murray7dff9e02010-11-08 17:15:13 +0000525 response code received when the all data is sent. If msg
Serhiy Storchaka9f8a8912015-04-03 18:12:41 +0300526 is a string, lone '\\r' and '\\n' characters are converted to
527 '\\r\\n' characters. If msg is bytes, it is transmitted as is.
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000528 """
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000529 self.putcmd("data")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000530 (code, repl) = self.getreply()
531 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400532 self._print_debug('data:', (code, repl))
Fred Drake8152d322000-12-12 23:20:45 +0000533 if code != 354:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000534 raise SMTPDataError(code, repl)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000535 else:
R. David Murray7dff9e02010-11-08 17:15:13 +0000536 if isinstance(msg, str):
537 msg = _fix_eols(msg).encode('ascii')
538 q = _quote_periods(msg)
539 if q[-2:] != bCRLF:
540 q = q + bCRLF
541 q = q + b"." + bCRLF
Guido van Rossum20c92281999-04-21 16:52:20 +0000542 self.send(q)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000543 (code, msg) = self.getreply()
544 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400545 self._print_debug('data:', (code, msg))
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000546 return (code, msg)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000547
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000548 def verify(self, address):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000549 """SMTP 'verify' command -- checks for address validity."""
R David Murray46346762011-07-18 21:38:54 -0400550 self.putcmd("vrfy", _addr_only(address))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000551 return self.getreply()
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000552 # a.k.a.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000553 vrfy = verify
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000554
555 def expn(self, address):
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000556 """SMTP 'expn' command -- expands a mailing list."""
R David Murray46346762011-07-18 21:38:54 -0400557 self.putcmd("expn", _addr_only(address))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000558 return self.getreply()
559
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000560 # some useful methods
Guido van Rossumae010462001-09-11 15:57:46 +0000561
Christian Heimes679db4a2008-01-18 09:56:22 +0000562 def ehlo_or_helo_if_needed(self):
563 """Call self.ehlo() and/or self.helo() if needed.
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 may raise the following exceptions:
569
570 SMTPHeloError The server didn't reply properly to
571 the helo greeting.
572 """
573 if self.helo_resp is None and self.ehlo_resp is None:
574 if not (200 <= self.ehlo()[0] <= 299):
575 (code, resp) = self.helo()
576 if not (200 <= code <= 299):
577 raise SMTPHeloError(code, resp)
578
R David Murray76e13c12014-07-03 14:47:46 -0400579 def auth(self, mechanism, authobject):
580 """Authentication command - requires response processing.
581
582 'mechanism' specifies which authentication mechanism is to
583 be used - the valid values are those listed in the 'auth'
584 element of 'esmtp_features'.
585
586 'authobject' must be a callable object taking a single argument:
587
588 data = authobject(challenge)
589
590 It will be called to process the server's challenge response; the
591 challenge argument it is passed will be a bytes. It should return
592 bytes data that will be base64 encoded and sent to the server.
593 """
594
595 mechanism = mechanism.upper()
596 (code, resp) = self.docmd("AUTH", mechanism)
597 # Server replies with 334 (challenge) or 535 (not supported)
598 if code == 334:
599 challenge = base64.decodebytes(resp)
600 response = encode_base64(
601 authobject(challenge).encode('ascii'), eol='')
602 (code, resp) = self.docmd(response)
603 if code in (235, 503):
604 return (code, resp)
605 raise SMTPAuthenticationError(code, resp)
606
607 def auth_cram_md5(self, challenge):
608 """ Authobject to use with CRAM-MD5 authentication. Requires self.user
609 and self.password to be set."""
610 return self.user + " " + hmac.HMAC(
611 self.password.encode('ascii'), challenge, 'md5').hexdigest()
612
613 def auth_plain(self, challenge):
614 """ Authobject to use with PLAIN authentication. Requires self.user and
615 self.password to be set."""
616 return "\0%s\0%s" % (self.user, self.password)
617
618 def auth_login(self, challenge):
619 """ Authobject to use with LOGIN authentication. Requires self.user and
620 self.password to be set."""
621 (code, resp) = self.docmd(
622 encode_base64(self.user.encode('ascii'), eol=''))
623 if code == 334:
624 return self.password
625 raise SMTPAuthenticationError(code, resp)
626
Guido van Rossumae010462001-09-11 15:57:46 +0000627 def login(self, user, password):
628 """Log in on an SMTP server that requires authentication.
629
630 The arguments are:
R David Murray76e13c12014-07-03 14:47:46 -0400631 - user: The user name to authenticate with.
632 - password: The password for the authentication.
Guido van Rossumae010462001-09-11 15:57:46 +0000633
634 If there has been no previous EHLO or HELO command this session, this
635 method tries ESMTP EHLO first.
636
637 This method will return normally if the authentication was successful.
638
639 This method may raise the following exceptions:
640
641 SMTPHeloError The server didn't reply properly to
642 the helo greeting.
643 SMTPAuthenticationError The server didn't accept the username/
644 password combination.
Fred Drake2f8f4d32001-10-13 18:35:32 +0000645 SMTPException No suitable authentication method was
Guido van Rossumae010462001-09-11 15:57:46 +0000646 found.
647 """
648
Christian Heimes679db4a2008-01-18 09:56:22 +0000649 self.ehlo_or_helo_if_needed()
Guido van Rossumae010462001-09-11 15:57:46 +0000650 if not self.has_extn("auth"):
651 raise SMTPException("SMTP AUTH extension not supported by server.")
652
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000653 # Authentication methods the server claims to support
654 advertised_authlist = self.esmtp_features["auth"].split()
Guido van Rossumae010462001-09-11 15:57:46 +0000655
R David Murray76e13c12014-07-03 14:47:46 -0400656 # Authentication methods we can handle in our preferred order:
657 preferred_auths = ['CRAM-MD5', 'PLAIN', 'LOGIN']
Guido van Rossumae010462001-09-11 15:57:46 +0000658
R David Murray76e13c12014-07-03 14:47:46 -0400659 # We try the supported authentications in our preferred order, if
660 # the server supports them.
661 authlist = [auth for auth in preferred_auths
662 if auth in advertised_authlist]
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000663 if not authlist:
Fred Drake2f8f4d32001-10-13 18:35:32 +0000664 raise SMTPException("No suitable authentication method found.")
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000665
666 # Some servers advertise authentication methods they don't really
667 # support, so if authentication fails, we continue until we've tried
668 # all methods.
R David Murray76e13c12014-07-03 14:47:46 -0400669 self.user, self.password = user, password
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000670 for authmethod in authlist:
R David Murray76e13c12014-07-03 14:47:46 -0400671 method_name = 'auth_' + authmethod.lower().replace('-', '_')
672 try:
673 (code, resp) = self.auth(authmethod, getattr(self, method_name))
674 # 235 == 'Authentication successful'
675 # 503 == 'Error: already authenticated'
676 if code in (235, 503):
677 return (code, resp)
678 except SMTPAuthenticationError as e:
679 last_exception = e
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000680
R David Murray76e13c12014-07-03 14:47:46 -0400681 # We could not login successfully. Return result of last attempt.
682 raise last_exception
Guido van Rossumae010462001-09-11 15:57:46 +0000683
Antoine Pitroue0650202011-05-18 18:03:09 +0200684 def starttls(self, keyfile=None, certfile=None, context=None):
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000685 """Puts the connection to the SMTP server into TLS mode.
Tim Petersb64bec32001-09-18 02:26:39 +0000686
Christian Heimes679db4a2008-01-18 09:56:22 +0000687 If there has been no previous EHLO or HELO command this session, this
688 method tries ESMTP EHLO first.
689
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000690 If the server supports TLS, this will encrypt the rest of the SMTP
691 session. If you provide the keyfile and certfile parameters,
692 the identity of the SMTP server and client can be checked. This,
693 however, depends on whether the socket module really checks the
694 certificates.
Christian Heimes679db4a2008-01-18 09:56:22 +0000695
696 This method may raise the following exceptions:
697
698 SMTPHeloError The server didn't reply properly to
699 the helo greeting.
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000700 """
Christian Heimes679db4a2008-01-18 09:56:22 +0000701 self.ehlo_or_helo_if_needed()
702 if not self.has_extn("starttls"):
703 raise SMTPException("STARTTLS extension not supported by server.")
Tim Petersb64bec32001-09-18 02:26:39 +0000704 (resp, reply) = self.docmd("STARTTLS")
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000705 if resp == 220:
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000706 if not _have_ssl:
707 raise RuntimeError("No SSL support included in this Python")
Antoine Pitroue0650202011-05-18 18:03:09 +0200708 if context is not None and keyfile is not None:
709 raise ValueError("context and keyfile arguments are mutually "
710 "exclusive")
711 if context is not None and certfile is not None:
712 raise ValueError("context and certfile arguments are mutually "
713 "exclusive")
Christian Heimes67986f92013-11-23 22:43:47 +0100714 if context is None:
715 context = ssl._create_stdlib_context(certfile=certfile,
716 keyfile=keyfile)
Christian Heimesa5768f72013-12-02 20:44:17 +0100717 self.sock = context.wrap_socket(self.sock,
Benjamin Peterson7243b572014-11-23 17:04:34 -0600718 server_hostname=self._host)
Antoine Pitrouf068ab82011-06-06 19:17:09 +0200719 self.file = None
Christian Heimes679db4a2008-01-18 09:56:22 +0000720 # RFC 3207:
721 # The client MUST discard any knowledge obtained from
722 # the server, such as the list of SMTP service extensions,
723 # which was not obtained from the TLS negotiation itself.
724 self.helo_resp = None
725 self.ehlo_resp = None
726 self.esmtp_features = {}
727 self.does_esmtp = 0
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000728 return (resp, reply)
Tim Petersb64bec32001-09-18 02:26:39 +0000729
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000730 def sendmail(self, from_addr, to_addrs, msg, mail_options=[],
Tim Peters495ad3c2001-01-15 01:36:40 +0000731 rcpt_options=[]):
732 """This command performs an entire mail transaction.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000733
Tim Peters495ad3c2001-01-15 01:36:40 +0000734 The arguments are:
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000735 - from_addr : The address sending this mail.
736 - to_addrs : A list of addresses to send this mail to. A bare
737 string will be treated as a list with 1 address.
Tim Peters495ad3c2001-01-15 01:36:40 +0000738 - msg : The message to send.
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000739 - mail_options : List of ESMTP options (such as 8bitmime) for the
740 mail command.
741 - rcpt_options : List of ESMTP options (such as DSN commands) for
742 all the rcpt commands.
743
R. David Murray7dff9e02010-11-08 17:15:13 +0000744 msg may be a string containing characters in the ASCII range, or a byte
745 string. A string is encoded to bytes using the ascii codec, and lone
R David Murrayac4e5ab2011-07-02 21:03:19 -0400746 \\r and \\n characters are converted to \\r\\n characters.
R. David Murray7dff9e02010-11-08 17:15:13 +0000747
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000748 If there has been no previous EHLO or HELO command this session, this
749 method tries ESMTP EHLO first. If the server does ESMTP, message size
750 and each of the specified options will be passed to it. If EHLO
751 fails, HELO will be tried and ESMTP options suppressed.
752
753 This method will return normally if the mail is accepted for at least
Barry Warsawd25c1b71999-11-28 17:11:06 +0000754 one recipient. It returns a dictionary, with one entry for each
755 recipient that was refused. Each entry contains a tuple of the SMTP
756 error code and the accompanying error message sent by the server.
Guido van Rossum296e1431999-04-07 15:03:39 +0000757
758 This method may raise the following exceptions:
759
760 SMTPHeloError The server didn't reply properly to
Tim Peters495ad3c2001-01-15 01:36:40 +0000761 the helo greeting.
Barry Warsawd25c1b71999-11-28 17:11:06 +0000762 SMTPRecipientsRefused The server rejected ALL recipients
Guido van Rossum296e1431999-04-07 15:03:39 +0000763 (no mail was sent).
764 SMTPSenderRefused The server didn't accept the from_addr.
765 SMTPDataError The server replied with an unexpected
766 error code (other than a refusal of
767 a recipient).
768
769 Note: the connection will be open even after an exception is raised.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000770
Guido van Rossum95e6f701998-06-25 02:15:50 +0000771 Example:
Tim Peters495ad3c2001-01-15 01:36:40 +0000772
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000773 >>> import smtplib
774 >>> s=smtplib.SMTP("localhost")
Guido van Rossumfc40a831998-01-29 17:26:45 +0000775 >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"]
Martin v. Löwis301b1cd2002-07-28 16:52:01 +0000776 >>> msg = '''\\
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000777 ... From: Me@my.org
778 ... Subject: testin'...
779 ...
780 ... This is a test '''
781 >>> s.sendmail("me@my.org",tolist,msg)
782 { "three@three.org" : ( 550 ,"User unknown" ) }
783 >>> s.quit()
Tim Peters495ad3c2001-01-15 01:36:40 +0000784
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000785 In the above example, the message was accepted for delivery to three
786 of the four addresses, and one was rejected, with the error code
Barry Warsawd25c1b71999-11-28 17:11:06 +0000787 550. If all addresses are accepted, then the method will return an
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000788 empty dictionary.
789
790 """
Christian Heimes679db4a2008-01-18 09:56:22 +0000791 self.ehlo_or_helo_if_needed()
Guido van Rossum95e6f701998-06-25 02:15:50 +0000792 esmtp_opts = []
R. David Murray7dff9e02010-11-08 17:15:13 +0000793 if isinstance(msg, str):
794 msg = _fix_eols(msg).encode('ascii')
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000795 if self.does_esmtp:
796 # Hmmm? what's this? -ddm
797 # self.esmtp_features['7bit']=""
798 if self.has_extn('size'):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000799 esmtp_opts.append("size=%d" % len(msg))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000800 for option in mail_options:
Guido van Rossum95e6f701998-06-25 02:15:50 +0000801 esmtp_opts.append(option)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000802 (code, resp) = self.mail(from_addr, esmtp_opts)
Fred Drake8152d322000-12-12 23:20:45 +0000803 if code != 250:
R David Murrayd312c742013-03-20 20:36:14 -0400804 if code == 421:
805 self.close()
806 else:
R David Murrayafb151a2014-04-14 18:21:38 -0400807 self._rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000808 raise SMTPSenderRefused(code, resp, from_addr)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000809 senderrs = {}
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000810 if isinstance(to_addrs, str):
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000811 to_addrs = [to_addrs]
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000812 for each in to_addrs:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000813 (code, resp) = self.rcpt(each, rcpt_options)
Fred Drake8152d322000-12-12 23:20:45 +0000814 if (code != 250) and (code != 251):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000815 senderrs[each] = (code, resp)
R David Murrayd312c742013-03-20 20:36:14 -0400816 if code == 421:
817 self.close()
818 raise SMTPRecipientsRefused(senderrs)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000819 if len(senderrs) == len(to_addrs):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000820 # the server refused all our recipients
R David Murrayafb151a2014-04-14 18:21:38 -0400821 self._rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000822 raise SMTPRecipientsRefused(senderrs)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000823 (code, resp) = self.data(msg)
Fred Drake8152d322000-12-12 23:20:45 +0000824 if code != 250:
R David Murrayd312c742013-03-20 20:36:14 -0400825 if code == 421:
826 self.close()
827 else:
R David Murrayafb151a2014-04-14 18:21:38 -0400828 self._rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000829 raise SMTPDataError(code, resp)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000830 #if we got here then somebody got our mail
Tim Peters495ad3c2001-01-15 01:36:40 +0000831 return senderrs
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000832
R. David Murray7dff9e02010-11-08 17:15:13 +0000833 def send_message(self, msg, from_addr=None, to_addrs=None,
834 mail_options=[], rcpt_options={}):
835 """Converts message to a bytestring and passes it to sendmail.
836
837 The arguments are as for sendmail, except that msg is an
R David Murrayac4e5ab2011-07-02 21:03:19 -0400838 email.message.Message object. If from_addr is None or to_addrs is
839 None, these arguments are taken from the headers of the Message as
840 described in RFC 2822 (a ValueError is raised if there is more than
841 one set of 'Resent-' headers). Regardless of the values of from_addr and
842 to_addr, any Bcc field (or Resent-Bcc field, when the Message is a
843 resent) of the Message object won't be transmitted. The Message
844 object is then serialized using email.generator.BytesGenerator and
845 sendmail is called to transmit the message.
846
R. David Murray7dff9e02010-11-08 17:15:13 +0000847 """
R David Murrayac4e5ab2011-07-02 21:03:19 -0400848 # 'Resent-Date' is a mandatory field if the Message is resent (RFC 2822
849 # Section 3.6.6). In such a case, we use the 'Resent-*' fields. However,
850 # if there is more than one 'Resent-' block there's no way to
851 # unambiguously determine which one is the most recent in all cases,
852 # so rather than guess we raise a ValueError in that case.
853 #
854 # TODO implement heuristics to guess the correct Resent-* block with an
855 # option allowing the user to enable the heuristics. (It should be
856 # possible to guess correctly almost all of the time.)
Senthil Kumaranb351a482011-07-31 09:14:17 +0800857
858 resent = msg.get_all('Resent-Date')
R David Murrayac4e5ab2011-07-02 21:03:19 -0400859 if resent is None:
860 header_prefix = ''
861 elif len(resent) == 1:
862 header_prefix = 'Resent-'
863 else:
864 raise ValueError("message has more than one 'Resent-' header block")
R. David Murray7dff9e02010-11-08 17:15:13 +0000865 if from_addr is None:
R David Murrayac4e5ab2011-07-02 21:03:19 -0400866 # Prefer the sender field per RFC 2822:3.6.2.
Senthil Kumaranb351a482011-07-31 09:14:17 +0800867 from_addr = (msg[header_prefix + 'Sender']
868 if (header_prefix + 'Sender') in msg
869 else msg[header_prefix + 'From'])
R. David Murray7dff9e02010-11-08 17:15:13 +0000870 if to_addrs is None:
Senthil Kumaranb351a482011-07-31 09:14:17 +0800871 addr_fields = [f for f in (msg[header_prefix + 'To'],
872 msg[header_prefix + 'Bcc'],
873 msg[header_prefix + 'Cc']) if f is not None]
R. David Murray7dff9e02010-11-08 17:15:13 +0000874 to_addrs = [a[1] for a in email.utils.getaddresses(addr_fields)]
R David Murrayac4e5ab2011-07-02 21:03:19 -0400875 # Make a local copy so we can delete the bcc headers.
876 msg_copy = copy.copy(msg)
877 del msg_copy['Bcc']
878 del msg_copy['Resent-Bcc']
R. David Murray7dff9e02010-11-08 17:15:13 +0000879 with io.BytesIO() as bytesmsg:
880 g = email.generator.BytesGenerator(bytesmsg)
R David Murrayac4e5ab2011-07-02 21:03:19 -0400881 g.flatten(msg_copy, linesep='\r\n')
R. David Murray7dff9e02010-11-08 17:15:13 +0000882 flatmsg = bytesmsg.getvalue()
883 return self.sendmail(from_addr, to_addrs, flatmsg, mail_options,
884 rcpt_options)
885
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000886 def close(self):
887 """Close the connection to the SMTP server."""
Serhiy Storchaka7e7a3db2015-04-10 13:24:41 +0300888 try:
889 file = self.file
890 self.file = None
891 if file:
892 file.close()
893 finally:
894 sock = self.sock
895 self.sock = None
896 if sock:
897 sock.close()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000898
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000899 def quit(self):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000900 """Terminate the SMTP session."""
Christian Heimesba4af492008-03-28 00:55:15 +0000901 res = self.docmd("quit")
R David Murray0cff49f2014-08-30 16:51:59 -0400902 # A new EHLO is required after reconnecting with connect()
903 self.ehlo_resp = self.helo_resp = None
904 self.esmtp_features = {}
905 self.does_esmtp = False
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000906 self.close()
Christian Heimesba4af492008-03-28 00:55:15 +0000907 return res
Guido van Rossum95e6f701998-06-25 02:15:50 +0000908
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000909if _have_ssl:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000910
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000911 class SMTP_SSL(SMTP):
R David Murray021362d2013-06-23 16:05:44 -0400912 """ This is a subclass derived from SMTP that connects over an SSL
913 encrypted socket (to use this class you need a socket module that was
914 compiled with SSL support). If host is not specified, '' (the local
915 host) is used. If port is omitted, the standard SMTP-over-SSL port
916 (465) is used. local_hostname and source_address have the same meaning
917 as they do in the SMTP class. keyfile and certfile are also optional -
918 they can contain a PEM formatted private key and certificate chain file
919 for the SSL connection. context also optional, can contain a
920 SSLContext, and is an alternative to keyfile and certfile; If it is
921 specified both keyfile and certfile must be None.
922
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000923 """
Antoine Pitrouc1d52062011-05-07 19:39:37 +0200924
925 default_port = SMTP_SSL_PORT
926
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000927 def __init__(self, host='', port=0, local_hostname=None,
Georg Brandlf78e02b2008-06-10 17:40:04 +0000928 keyfile=None, certfile=None,
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800929 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
930 source_address=None, context=None):
Antoine Pitroue0650202011-05-18 18:03:09 +0200931 if context is not None and keyfile is not None:
932 raise ValueError("context and keyfile arguments are mutually "
933 "exclusive")
934 if context is not None and certfile is not None:
935 raise ValueError("context and certfile arguments are mutually "
936 "exclusive")
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000937 self.keyfile = keyfile
938 self.certfile = certfile
Christian Heimes67986f92013-11-23 22:43:47 +0100939 if context is None:
940 context = ssl._create_stdlib_context(certfile=certfile,
941 keyfile=keyfile)
Antoine Pitroue0650202011-05-18 18:03:09 +0200942 self.context = context
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800943 SMTP.__init__(self, host, port, local_hostname, timeout,
944 source_address)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000945
946 def _get_socket(self, host, port, timeout):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000947 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400948 self._print_debug('connect:', (host, port))
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800949 new_socket = socket.create_connection((host, port), timeout,
950 self.source_address)
Christian Heimesa5768f72013-12-02 20:44:17 +0100951 new_socket = self.context.wrap_socket(new_socket,
Benjamin Peterson7243b572014-11-23 17:04:34 -0600952 server_hostname=self._host)
R. David Murray87e20742009-05-23 01:30:26 +0000953 return new_socket
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000954
955 __all__.append("SMTP_SSL")
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000956
Guido van Rossumd8faa362007-04-27 19:54:29 +0000957#
958# LMTP extension
959#
960LMTP_PORT = 2003
961
962class LMTP(SMTP):
963 """LMTP - Local Mail Transfer Protocol
964
965 The LMTP protocol, which is very similar to ESMTP, is heavily based
R David Murray021362d2013-06-23 16:05:44 -0400966 on the standard SMTP client. It's common to use Unix sockets for
967 LMTP, so our connect() method must support that as well as a regular
R David Murray36beb662013-06-23 15:47:50 -0400968 host:port server. local_hostname and source_address have the same
R David Murray021362d2013-06-23 16:05:44 -0400969 meaning as they do in the SMTP class. To specify a Unix socket,
970 you must use an absolute path as the host, starting with a '/'.
Guido van Rossumd8faa362007-04-27 19:54:29 +0000971
972 Authentication is supported, using the regular SMTP mechanism. When
973 using a Unix socket, LMTP generally don't support or require any
974 authentication, but your mileage might vary."""
975
976 ehlo_msg = "lhlo"
977
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800978 def __init__(self, host='', port=LMTP_PORT, local_hostname=None,
979 source_address=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000980 """Initialize a new instance."""
Senthil Kumaranb351a482011-07-31 09:14:17 +0800981 SMTP.__init__(self, host, port, local_hostname=local_hostname,
982 source_address=source_address)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000983
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800984 def connect(self, host='localhost', port=0, source_address=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000985 """Connect to the LMTP daemon, on either a Unix or a TCP socket."""
986 if host[0] != '/':
Senthil Kumaranb351a482011-07-31 09:14:17 +0800987 return SMTP.connect(self, host, port, source_address=source_address)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000988
989 # Handle Unix-domain sockets.
990 try:
991 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
Antoine Pitrouf068ab82011-06-06 19:17:09 +0200992 self.file = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000993 self.sock.connect(host)
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200994 except OSError:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000995 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -0400996 self._print_debug('connect fail:', host)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000997 if self.sock:
998 self.sock.close()
999 self.sock = None
Andrew Svetlovb6693c42012-12-17 18:54:53 +02001000 raise
Guido van Rossumd8faa362007-04-27 19:54:29 +00001001 (code, msg) = self.getreply()
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +00001002 if self.debuglevel > 0:
R David Murray0c49b892015-04-16 17:14:42 -04001003 self._print_debug('connect:', msg)
Guido van Rossumd8faa362007-04-27 19:54:29 +00001004 return (code, msg)
1005
1006
Guido van Rossum95e6f701998-06-25 02:15:50 +00001007# Test the sendmail method, which tests most of the others.
1008# Note: This always sends to localhost.
1009if __name__ == '__main__':
Andrew M. Kuchling6be424f2001-08-13 14:41:39 +00001010 import sys
Guido van Rossum95e6f701998-06-25 02:15:50 +00001011
1012 def prompt(prompt):
1013 sys.stdout.write(prompt + ": ")
Ezio Melotti6bfecd12011-10-18 13:20:07 +03001014 sys.stdout.flush()
Eric S. Raymondc013f302001-02-09 05:40:38 +00001015 return sys.stdin.readline().strip()
Guido van Rossum95e6f701998-06-25 02:15:50 +00001016
1017 fromaddr = prompt("From")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +00001018 toaddrs = prompt("To").split(',')
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001019 print("Enter message, end with ^D:")
Guido van Rossum95e6f701998-06-25 02:15:50 +00001020 msg = ''
1021 while 1:
1022 line = sys.stdin.readline()
1023 if not line:
1024 break
1025 msg = msg + line
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001026 print("Message length is %d" % len(msg))
Guido van Rossum95e6f701998-06-25 02:15:50 +00001027
1028 server = SMTP('localhost')
1029 server.set_debuglevel(1)
1030 server.sendmail(fromaddr, toaddrs, msg)
1031 server.quit()