blob: cc46e4f49f5a1b7c5b8115a93e59f21b47d4a83f [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
Barry Warsaw2cc1f6d2007-08-30 14:28:55 +000053from email.base64mime import body_encode as encode_base64
Brett Cannone6f8a892004-07-10 23:14:30 +000054from sys import stderr
Guido van Rossumbbe323e1998-01-29 17:24:40 +000055
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +000056__all__ = ["SMTPException", "SMTPServerDisconnected", "SMTPResponseException",
57 "SMTPSenderRefused", "SMTPRecipientsRefused", "SMTPDataError",
58 "SMTPConnectError", "SMTPHeloError", "SMTPAuthenticationError",
59 "quoteaddr", "quotedata", "SMTP"]
Skip Montanaro0de65802001-02-15 22:15:14 +000060
Guido van Rossumbbe323e1998-01-29 17:24:40 +000061SMTP_PORT = 25
Thomas Wouters89f507f2006-12-13 04:49:30 +000062SMTP_SSL_PORT = 465
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +000063CRLF = "\r\n"
64bCRLF = b"\r\n"
Guido van Rossumbbe323e1998-01-29 17:24:40 +000065
Piers Lauder385a77a2002-07-27 00:38:30 +000066OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I)
67
Tim Peters495ad3c2001-01-15 01:36:40 +000068# Exception classes used by this module.
R David Murray8a345962013-04-14 06:46:35 -040069class SMTPException(OSError):
Guido van Rossum296e1431999-04-07 15:03:39 +000070 """Base class for all exceptions raised by this module."""
71
72class SMTPServerDisconnected(SMTPException):
73 """Not connected to any SMTP server.
74
75 This exception is raised when the server unexpectedly disconnects,
76 or when an attempt is made to use the SMTP instance before
77 connecting it to a server.
78 """
79
80class SMTPResponseException(SMTPException):
81 """Base class for all exceptions that include an SMTP error code.
82
83 These exceptions are generated in some instances when the SMTP
84 server returns an error code. The error code is stored in the
85 `smtp_code' attribute of the error, and the `smtp_error' attribute
86 is set to the error message.
87 """
88
89 def __init__(self, code, msg):
90 self.smtp_code = code
91 self.smtp_error = msg
92 self.args = (code, msg)
93
94class SMTPSenderRefused(SMTPResponseException):
95 """Sender address refused.
Guido van Rossumae010462001-09-11 15:57:46 +000096
Guido van Rossum296e1431999-04-07 15:03:39 +000097 In addition to the attributes set by on all SMTPResponseException
Barry Warsawd25c1b71999-11-28 17:11:06 +000098 exceptions, this sets `sender' to the string that the SMTP refused.
Guido van Rossum296e1431999-04-07 15:03:39 +000099 """
100
101 def __init__(self, code, msg, sender):
102 self.smtp_code = code
103 self.smtp_error = msg
104 self.sender = sender
105 self.args = (code, msg, sender)
106
Guido van Rossum20c92281999-04-21 16:52:20 +0000107class SMTPRecipientsRefused(SMTPException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000108 """All recipient addresses refused.
Guido van Rossumae010462001-09-11 15:57:46 +0000109
Thomas Wouters7e474022000-07-16 12:04:32 +0000110 The errors for each recipient are accessible through the attribute
Tim Peters495ad3c2001-01-15 01:36:40 +0000111 'recipients', which is a dictionary of exactly the same sort as
112 SMTP.sendmail() returns.
Guido van Rossum296e1431999-04-07 15:03:39 +0000113 """
114
115 def __init__(self, recipients):
116 self.recipients = recipients
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000117 self.args = (recipients,)
Guido van Rossum296e1431999-04-07 15:03:39 +0000118
119
Guido van Rossum296e1431999-04-07 15:03:39 +0000120class SMTPDataError(SMTPResponseException):
121 """The SMTP server didn't accept the data."""
122
123class SMTPConnectError(SMTPResponseException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000124 """Error during connection establishment."""
Guido van Rossum296e1431999-04-07 15:03:39 +0000125
126class SMTPHeloError(SMTPResponseException):
Barry Warsawd25c1b71999-11-28 17:11:06 +0000127 """The server refused our HELO reply."""
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000128
Guido van Rossumae010462001-09-11 15:57:46 +0000129class SMTPAuthenticationError(SMTPResponseException):
130 """Authentication error.
131
132 Most probably the server didn't accept the username/password
133 combination provided.
134 """
Peter Schneider-Kamp7bc82bb2000-08-10 14:02:23 +0000135
R David Murray4c14bba2011-07-18 21:59:53 -0400136def quoteaddr(addrstring):
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000137 """Quote a subset of the email addresses defined by RFC 821.
138
Georg Brandl9f0f9602008-06-12 22:23:59 +0000139 Should be able to handle anything email.utils.parseaddr can handle.
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000140 """
R David Murray4c14bba2011-07-18 21:59:53 -0400141 displayname, addr = email.utils.parseaddr(addrstring)
142 if (displayname, addr) == ('', ''):
143 # parseaddr couldn't parse it, use it as is and hope for the best.
144 if addrstring.strip().startswith('<'):
145 return addrstring
146 return "<%s>" % addrstring
147 return "<%s>" % addr
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000148
R David Murray46346762011-07-18 21:38:54 -0400149def _addr_only(addrstring):
150 displayname, addr = email.utils.parseaddr(addrstring)
151 if (displayname, addr) == ('', ''):
152 # parseaddr couldn't parse it, so use it as is.
153 return addrstring
154 return addr
155
R. David Murray7dff9e02010-11-08 17:15:13 +0000156# Legacy method kept for backward compatibility.
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000157def quotedata(data):
158 """Quote data for email.
159
Barry Warsawd25c1b71999-11-28 17:11:06 +0000160 Double leading '.', and change Unix newline '\\n', or Mac '\\r' into
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000161 Internet CRLF end-of-line.
162 """
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000163 return re.sub(r'(?m)^\.', '..',
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000164 re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data))
Guido van Rossum69a79bc1998-07-13 15:18:49 +0000165
R. David Murray7dff9e02010-11-08 17:15:13 +0000166def _quote_periods(bindata):
R David Murray0f663d02011-06-09 15:05:57 -0400167 return re.sub(br'(?m)^\.', b'..', bindata)
R. David Murray7dff9e02010-11-08 17:15:13 +0000168
169def _fix_eols(data):
170 return re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data)
171
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000172try:
173 import ssl
174except ImportError:
175 _have_ssl = False
176else:
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000177 _have_ssl = True
178
Peter Schneider-Kamp7bc82bb2000-08-10 14:02:23 +0000179
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000180class SMTP:
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000181 """This class manages a connection to an SMTP or ESMTP server.
182 SMTP Objects:
Tim Peters495ad3c2001-01-15 01:36:40 +0000183 SMTP objects have the following attributes:
184 helo_resp
185 This is the message given by the server in response to the
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000186 most recent HELO command.
Tim Peters495ad3c2001-01-15 01:36:40 +0000187
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000188 ehlo_resp
Tim Peters495ad3c2001-01-15 01:36:40 +0000189 This is the message given by the server in response to the
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000190 most recent EHLO command. This is usually multiline.
191
Tim Peters495ad3c2001-01-15 01:36:40 +0000192 does_esmtp
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000193 This is a True value _after you do an EHLO command_, if the
194 server supports ESMTP.
195
Tim Peters495ad3c2001-01-15 01:36:40 +0000196 esmtp_features
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000197 This is a dictionary, which, if the server supports ESMTP,
Barry Warsawd25c1b71999-11-28 17:11:06 +0000198 will _after you do an EHLO command_, contain the names of the
199 SMTP service extensions this server supports, and their
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000200 parameters (if any).
Barry Warsawd25c1b71999-11-28 17:11:06 +0000201
Tim Peters495ad3c2001-01-15 01:36:40 +0000202 Note, all extension names are mapped to lower case in the
203 dictionary.
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000204
Barry Warsawd25c1b71999-11-28 17:11:06 +0000205 See each method's docstrings for details. In general, there is a
206 method of the same name to perform each SMTP command. There is also a
207 method called 'sendmail' that will do an entire mail transaction.
208 """
Guido van Rossum95e6f701998-06-25 02:15:50 +0000209 debuglevel = 0
210 file = None
211 helo_resp = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000212 ehlo_msg = "ehlo"
Guido van Rossum95e6f701998-06-25 02:15:50 +0000213 ehlo_resp = None
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000214 does_esmtp = 0
Antoine Pitrouc1d52062011-05-07 19:39:37 +0200215 default_port = SMTP_PORT
Guido van Rossum95e6f701998-06-25 02:15:50 +0000216
Georg Brandlf78e02b2008-06-10 17:40:04 +0000217 def __init__(self, host='', port=0, local_hostname=None,
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800218 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
219 source_address=None):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000220 """Initialize a new instance.
221
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000222 If specified, `host' is the name of the remote host to which to
223 connect. If specified, `port' specifies the port to which to connect.
R David Murray14ee3cf2013-04-13 14:40:33 -0400224 By default, smtplib.SMTP_PORT is used. If a host is specified the
225 connect method is called, and if it returns anything other than
226 a success code an SMTPConnectError is raised. If specified,
Tim Peters863ac442002-04-16 01:38:40 +0000227 `local_hostname` is used as the FQDN of the local host. By default,
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800228 the local hostname is found using socket.getfqdn(). The
229 `source_address` parameter takes a 2-tuple (host, port) for the socket
230 to bind to as its source address before connecting. If the host is ''
231 and port is 0, the OS default behavior will be used.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000232
233 """
Guido van Rossumd8faa362007-04-27 19:54:29 +0000234 self.timeout = timeout
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000235 self.esmtp_features = {}
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800236 self.source_address = source_address
237
Guido van Rossum296e1431999-04-07 15:03:39 +0000238 if host:
239 (code, msg) = self.connect(host, port)
240 if code != 220:
241 raise SMTPConnectError(code, msg)
Raymond Hettingerf13eb552002-06-02 00:40:05 +0000242 if local_hostname is not None:
Barry Warsaw13e34f72002-03-26 20:27:35 +0000243 self.local_hostname = local_hostname
Neil Schemenauer6730f262002-03-24 15:30:40 +0000244 else:
Barry Warsaw13e34f72002-03-26 20:27:35 +0000245 # RFC 2821 says we should use the fqdn in the EHLO/HELO verb, and
246 # if that can't be calculated, that we should use a domain literal
247 # instead (essentially an encoded IP address like [A.B.C.D]).
248 fqdn = socket.getfqdn()
249 if '.' in fqdn:
250 self.local_hostname = fqdn
251 else:
252 # We can't find an fqdn hostname, so use a domain literal
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000253 addr = '127.0.0.1'
254 try:
255 addr = socket.gethostbyname(socket.gethostname())
256 except socket.gaierror:
257 pass
Barry Warsaw13e34f72002-03-26 20:27:35 +0000258 self.local_hostname = '[%s]' % addr
Tim Peters495ad3c2001-01-15 01:36:40 +0000259
Barry Warsaw1f5c9582011-03-15 15:04:44 -0400260 def __enter__(self):
261 return self
262
263 def __exit__(self, *args):
264 try:
265 code, message = self.docmd("QUIT")
266 if code != 221:
267 raise SMTPResponseException(code, message)
268 except SMTPServerDisconnected:
269 pass
270 finally:
271 self.close()
272
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000273 def set_debuglevel(self, debuglevel):
274 """Set the debug output level.
275
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000276 A non-false value results in debug messages for connection and for all
277 messages sent to and received from the server.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000278
279 """
280 self.debuglevel = debuglevel
281
Barry Warsawc9181712008-03-19 14:25:51 +0000282 def _get_socket(self, host, port, timeout):
Thomas Wouters89f507f2006-12-13 04:49:30 +0000283 # This makes it simpler for SMTP_SSL to use the SMTP connect code
284 # and just alter the socket connection bit.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000285 if self.debuglevel > 0:
Senthil Kumaranb351a482011-07-31 09:14:17 +0800286 print('connect: to', (host, port), self.source_address,
287 file=stderr)
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800288 return socket.create_connection((host, port), timeout,
289 self.source_address)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000290
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800291 def connect(self, host='localhost', port=0, source_address=None):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000292 """Connect to a host on a given port.
Guido van Rossum95e6f701998-06-25 02:15:50 +0000293
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000294 If the hostname ends with a colon (`:') followed by a number, and
295 there is no port specified, that suffix will be stripped off and the
296 number interpreted as the port number to use.
Guido van Rossum95e6f701998-06-25 02:15:50 +0000297
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000298 Note: This method is automatically invoked by __init__, if a host is
299 specified during instantiation.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000300
301 """
Senthil Kumaranb351a482011-07-31 09:14:17 +0800302
303 if source_address:
304 self.source_address = source_address
305
Martin v. Löwis4eb59402001-07-26 13:37:33 +0000306 if not port and (host.find(':') == host.rfind(':')):
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000307 i = host.rfind(':')
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000308 if i >= 0:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000309 host, port = host[:i], host[i + 1:]
310 try:
311 port = int(port)
Eric S. Raymond8d876032001-02-09 10:14:53 +0000312 except ValueError:
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200313 raise OSError("nonnumeric port")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000314 if not port:
315 port = self.default_port
316 if self.debuglevel > 0:
317 print('connect:', (host, port), file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000318 self.sock = self._get_socket(host, port, self.timeout)
Antoine Pitrouf068ab82011-06-06 19:17:09 +0200319 self.file = None
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000320 (code, msg) = self.getreply()
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000321 if self.debuglevel > 0:
322 print("connect:", msg, file=stderr)
Martin v. Löwisa43c2f82001-07-24 20:34:08 +0000323 return (code, msg)
Tim Peters495ad3c2001-01-15 01:36:40 +0000324
Guido van Rossum8a392d72007-11-21 22:09:45 +0000325 def send(self, s):
326 """Send `s' to the server."""
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000327 if self.debuglevel > 0:
328 print('send:', repr(s), file=stderr)
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000329 if hasattr(self, 'sock') and self.sock:
Guido van Rossum8a392d72007-11-21 22:09:45 +0000330 if isinstance(s, str):
331 s = s.encode("ascii")
Guido van Rossum2880f6e1998-08-10 20:07:00 +0000332 try:
Guido van Rossum8a392d72007-11-21 22:09:45 +0000333 self.sock.sendall(s)
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200334 except OSError:
Barry Warsaw76750972001-12-14 20:34:20 +0000335 self.close()
Guido van Rossum40233ea1999-01-15 03:23:55 +0000336 raise SMTPServerDisconnected('Server not connected')
Guido van Rossumfc40a831998-01-29 17:26:45 +0000337 else:
Guido van Rossum40233ea1999-01-15 03:23:55 +0000338 raise SMTPServerDisconnected('please run connect() first')
Tim Peters495ad3c2001-01-15 01:36:40 +0000339
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000340 def putcmd(self, cmd, args=""):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000341 """Send a command to the server."""
Guido van Rossumdb23d3d1999-06-09 15:13:10 +0000342 if args == "":
343 str = '%s%s' % (cmd, CRLF)
344 else:
345 str = '%s %s%s' % (cmd, args, CRLF)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000346 self.send(str)
Tim Peters495ad3c2001-01-15 01:36:40 +0000347
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000348 def getreply(self):
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000349 """Get a reply from the server.
Tim Peters495ad3c2001-01-15 01:36:40 +0000350
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000351 Returns a tuple consisting of:
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000352
353 - server response code (e.g. '250', or such, if all goes well)
354 Note: returns -1 if it can't read response code.
355
356 - server response string corresponding to response code (multiline
357 responses are converted to a single, multiline string).
Guido van Rossumf123f841999-03-29 20:33:21 +0000358
359 Raises SMTPServerDisconnected if end-of-file is reached.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000360 """
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000361 resp = []
Guido van Rossum296e1431999-04-07 15:03:39 +0000362 if self.file is None:
363 self.file = self.sock.makefile('rb')
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000364 while 1:
Benjamin Petersone1cdfd72009-01-18 21:02:37 +0000365 try:
366 line = self.file.readline()
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200367 except OSError as e:
Antoine Pitrou6b2e1602011-08-28 01:20:42 +0200368 self.close()
369 raise SMTPServerDisconnected("Connection unexpectedly closed: "
370 + str(e))
Guido van Rossum806c2462007-08-06 23:33:07 +0000371 if not line:
Guido van Rossum296e1431999-04-07 15:03:39 +0000372 self.close()
373 raise SMTPServerDisconnected("Connection unexpectedly closed")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000374 if self.debuglevel > 0:
375 print('reply:', repr(line), file=stderr)
Guido van Rossum806c2462007-08-06 23:33:07 +0000376 resp.append(line[4:].strip(b' \t\r\n'))
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000377 code = line[:3]
Guido van Rossum296e1431999-04-07 15:03:39 +0000378 # Check that the error code is syntactically correct.
379 # Don't attempt to read a continuation line if it is broken.
380 try:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000381 errcode = int(code)
Guido van Rossum296e1431999-04-07 15:03:39 +0000382 except ValueError:
383 errcode = -1
384 break
Guido van Rossumf123f841999-03-29 20:33:21 +0000385 # Check if multiline response.
Guido van Rossum806c2462007-08-06 23:33:07 +0000386 if line[3:4] != b"-":
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000387 break
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000388
Guido van Rossumc43e79f2007-06-18 18:26:36 +0000389 errmsg = b"\n".join(resp)
Tim Peters495ad3c2001-01-15 01:36:40 +0000390 if self.debuglevel > 0:
Senthil Kumaranb351a482011-07-31 09:14:17 +0800391 print('reply: retcode (%s); Msg: %s' % (errcode, errmsg),
392 file=stderr)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000393 return errcode, errmsg
Tim Peters495ad3c2001-01-15 01:36:40 +0000394
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000395 def docmd(self, cmd, args=""):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000396 """Send a command, and return its response code."""
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000397 self.putcmd(cmd, args)
Guido van Rossum296e1431999-04-07 15:03:39 +0000398 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000399
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000400 # std smtp commands
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000401 def helo(self, name=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000402 """SMTP 'helo' command.
403 Hostname to send for this command defaults to the FQDN of the local
404 host.
405 """
Neil Schemenauer6730f262002-03-24 15:30:40 +0000406 self.putcmd("helo", name or self.local_hostname)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000407 (code, msg) = self.getreply()
408 self.helo_resp = msg
409 return (code, msg)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000410
Guido van Rossum95e6f701998-06-25 02:15:50 +0000411 def ehlo(self, name=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000412 """ SMTP 'ehlo' command.
413 Hostname to send for this command defaults to the FQDN of the local
414 host.
415 """
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000416 self.esmtp_features = {}
Guido van Rossumd8faa362007-04-27 19:54:29 +0000417 self.putcmd(self.ehlo_msg, name or self.local_hostname)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000418 (code, msg) = self.getreply()
Tim Peters495ad3c2001-01-15 01:36:40 +0000419 # According to RFC1869 some (badly written)
420 # MTA's will disconnect on an ehlo. Toss an exception if
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000421 # that happens -ddm
422 if code == -1 and len(msg) == 0:
Barry Warsaw76750972001-12-14 20:34:20 +0000423 self.close()
Guido van Rossum40233ea1999-01-15 03:23:55 +0000424 raise SMTPServerDisconnected("Server not connected")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000425 self.ehlo_resp = msg
Fred Drake8152d322000-12-12 23:20:45 +0000426 if code != 250:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000427 return (code, msg)
428 self.does_esmtp = 1
Thomas Wouters7e474022000-07-16 12:04:32 +0000429 #parse the ehlo response -ddm
Guido van Rossum04110fb2007-08-24 16:32:05 +0000430 assert isinstance(self.ehlo_resp, bytes), repr(self.ehlo_resp)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000431 resp = self.ehlo_resp.decode("latin-1").split('\n')
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000432 del resp[0]
Guido van Rossum2880f6e1998-08-10 20:07:00 +0000433 for each in resp:
Piers Lauder385a77a2002-07-27 00:38:30 +0000434 # To be able to communicate with as many SMTP servers as possible,
435 # we have to take the old-style auth advertisement into account,
436 # because:
437 # 1) Else our SMTP feature parser gets confused.
438 # 2) There are some servers that only advertise the auth methods we
439 # support using the old style.
440 auth_match = OLDSTYLE_AUTH.match(each)
441 if auth_match:
442 # This doesn't remove duplicates, but that's no problem
443 self.esmtp_features["auth"] = self.esmtp_features.get("auth", "") \
444 + " " + auth_match.groups(0)[0]
445 continue
446
Barry Warsawbe22ae62002-04-15 20:03:30 +0000447 # RFC 1869 requires a space between ehlo keyword and parameters.
448 # It's actually stricter, in that only spaces are allowed between
449 # parameters, but were not going to check for that here. Note
450 # that the space isn't present if there are no parameters.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000451 m = re.match(r'(?P<feature>[A-Za-z0-9][A-Za-z0-9\-]*) ?', each)
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000452 if m:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000453 feature = m.group("feature").lower()
454 params = m.string[m.end("feature"):].strip()
Piers Lauder385a77a2002-07-27 00:38:30 +0000455 if feature == "auth":
456 self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \
457 + " " + params
458 else:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000459 self.esmtp_features[feature] = params
460 return (code, msg)
Guido van Rossum95e6f701998-06-25 02:15:50 +0000461
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000462 def has_extn(self, opt):
463 """Does the server support a given SMTP service extension?"""
Raymond Hettinger54f02222002-06-01 14:18:47 +0000464 return opt.lower() in self.esmtp_features
Guido van Rossum95e6f701998-06-25 02:15:50 +0000465
Guido van Rossum18586f41998-04-03 17:03:13 +0000466 def help(self, args=''):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000467 """SMTP 'help' command.
468 Returns help text from server."""
Guido van Rossum18586f41998-04-03 17:03:13 +0000469 self.putcmd("help", args)
Kurt B. Kaiser58bd1902005-06-26 18:27:36 +0000470 return self.getreply()[1]
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000471
472 def rset(self):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000473 """SMTP 'rset' command -- resets session."""
Guido van Rossum296e1431999-04-07 15:03:39 +0000474 return self.docmd("rset")
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000475
476 def noop(self):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000477 """SMTP 'noop' command -- doesn't do anything :>"""
Guido van Rossum296e1431999-04-07 15:03:39 +0000478 return self.docmd("noop")
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000479
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000480 def mail(self, sender, options=[]):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000481 """SMTP 'mail' command -- begins mail xfer session."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000482 optionlist = ''
483 if options and self.does_esmtp:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000484 optionlist = ' ' + ' '.join(options)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000485 self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000486 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000487
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000488 def rcpt(self, recip, options=[]):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000489 """SMTP 'rcpt' command -- indicates 1 recipient for this mail."""
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000490 optionlist = ''
491 if options and self.does_esmtp:
Eric S. Raymondc013f302001-02-09 05:40:38 +0000492 optionlist = ' ' + ' '.join(options)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000493 self.putcmd("rcpt", "TO:%s%s" % (quoteaddr(recip), optionlist))
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000494 return self.getreply()
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000495
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000496 def data(self, msg):
Tim Peters495ad3c2001-01-15 01:36:40 +0000497 """SMTP 'DATA' command -- sends message data to server.
Guido van Rossum296e1431999-04-07 15:03:39 +0000498
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000499 Automatically quotes lines beginning with a period per rfc821.
Guido van Rossum296e1431999-04-07 15:03:39 +0000500 Raises SMTPDataError if there is an unexpected reply to the
501 DATA command; the return value from this method is the final
R. David Murray7dff9e02010-11-08 17:15:13 +0000502 response code received when the all data is sent. If msg
503 is a string, lone '\r' and '\n' characters are converted to
504 '\r\n' characters. If msg is bytes, it is transmitted as is.
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000505 """
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000506 self.putcmd("data")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000507 (code, repl) = self.getreply()
508 if self.debuglevel > 0:
509 print("data:", (code, repl), file=stderr)
Fred Drake8152d322000-12-12 23:20:45 +0000510 if code != 354:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000511 raise SMTPDataError(code, repl)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000512 else:
R. David Murray7dff9e02010-11-08 17:15:13 +0000513 if isinstance(msg, str):
514 msg = _fix_eols(msg).encode('ascii')
515 q = _quote_periods(msg)
516 if q[-2:] != bCRLF:
517 q = q + bCRLF
518 q = q + b"." + bCRLF
Guido van Rossum20c92281999-04-21 16:52:20 +0000519 self.send(q)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000520 (code, msg) = self.getreply()
521 if self.debuglevel > 0:
522 print("data:", (code, msg), file=stderr)
523 return (code, msg)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000524
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000525 def verify(self, address):
Barry Warsawa7d9bdf1998-12-22 03:24:27 +0000526 """SMTP 'verify' command -- checks for address validity."""
R David Murray46346762011-07-18 21:38:54 -0400527 self.putcmd("vrfy", _addr_only(address))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000528 return self.getreply()
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000529 # a.k.a.
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000530 vrfy = verify
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000531
532 def expn(self, address):
Christian Heimes90c3d9b2008-02-23 13:18:03 +0000533 """SMTP 'expn' command -- expands a mailing list."""
R David Murray46346762011-07-18 21:38:54 -0400534 self.putcmd("expn", _addr_only(address))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000535 return self.getreply()
536
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000537 # some useful methods
Guido van Rossumae010462001-09-11 15:57:46 +0000538
Christian Heimes679db4a2008-01-18 09:56:22 +0000539 def ehlo_or_helo_if_needed(self):
540 """Call self.ehlo() and/or self.helo() if needed.
541
542 If there has been no previous EHLO or HELO command this session, this
543 method tries ESMTP EHLO first.
544
545 This method may raise the following exceptions:
546
547 SMTPHeloError The server didn't reply properly to
548 the helo greeting.
549 """
550 if self.helo_resp is None and self.ehlo_resp is None:
551 if not (200 <= self.ehlo()[0] <= 299):
552 (code, resp) = self.helo()
553 if not (200 <= code <= 299):
554 raise SMTPHeloError(code, resp)
555
Guido van Rossumae010462001-09-11 15:57:46 +0000556 def login(self, user, password):
557 """Log in on an SMTP server that requires authentication.
558
559 The arguments are:
560 - user: The user name to authenticate with.
561 - password: The password for the authentication.
562
563 If there has been no previous EHLO or HELO command this session, this
564 method tries ESMTP EHLO first.
565
566 This method will return normally if the authentication was successful.
567
568 This method may raise the following exceptions:
569
570 SMTPHeloError The server didn't reply properly to
571 the helo greeting.
572 SMTPAuthenticationError The server didn't accept the username/
573 password combination.
Fred Drake2f8f4d32001-10-13 18:35:32 +0000574 SMTPException No suitable authentication method was
Guido van Rossumae010462001-09-11 15:57:46 +0000575 found.
576 """
577
578 def encode_cram_md5(challenge, user, password):
Georg Brandl706824f2009-06-04 09:42:55 +0000579 challenge = base64.decodebytes(challenge)
R. David Murrayfb123912009-05-28 18:19:00 +0000580 response = user + " " + hmac.HMAC(password.encode('ascii'),
581 challenge).hexdigest()
582 return encode_base64(response.encode('ascii'), eol='')
Guido van Rossumae010462001-09-11 15:57:46 +0000583
584 def encode_plain(user, password):
R. David Murraycaa27b72009-05-23 18:49:56 +0000585 s = "\0%s\0%s" % (user, password)
586 return encode_base64(s.encode('ascii'), eol='')
Tim Peters469cdad2002-08-08 20:19:19 +0000587
Guido van Rossumae010462001-09-11 15:57:46 +0000588 AUTH_PLAIN = "PLAIN"
589 AUTH_CRAM_MD5 = "CRAM-MD5"
Piers Lauder385a77a2002-07-27 00:38:30 +0000590 AUTH_LOGIN = "LOGIN"
Guido van Rossumae010462001-09-11 15:57:46 +0000591
Christian Heimes679db4a2008-01-18 09:56:22 +0000592 self.ehlo_or_helo_if_needed()
Guido van Rossumae010462001-09-11 15:57:46 +0000593
594 if not self.has_extn("auth"):
595 raise SMTPException("SMTP AUTH extension not supported by server.")
596
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000597 # Authentication methods the server claims to support
598 advertised_authlist = self.esmtp_features["auth"].split()
Guido van Rossumae010462001-09-11 15:57:46 +0000599
600 # List of authentication methods we support: from preferred to
601 # less preferred methods. Except for the purpose of testing the weaker
602 # ones, we prefer stronger methods like CRAM-MD5:
Piers Lauder385a77a2002-07-27 00:38:30 +0000603 preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN]
Guido van Rossumae010462001-09-11 15:57:46 +0000604
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000605 # We try the authentication methods the server advertises, but only the
606 # ones *we* support. And in our preferred order.
607 authlist = [auth for auth in preferred_auths if auth in advertised_authlist]
608 if not authlist:
Fred Drake2f8f4d32001-10-13 18:35:32 +0000609 raise SMTPException("No suitable authentication method found.")
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000610
611 # Some servers advertise authentication methods they don't really
612 # support, so if authentication fails, we continue until we've tried
613 # all methods.
614 for authmethod in authlist:
615 if authmethod == AUTH_CRAM_MD5:
616 (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5)
617 if code == 334:
618 (code, resp) = self.docmd(encode_cram_md5(resp, user, password))
619 elif authmethod == AUTH_PLAIN:
620 (code, resp) = self.docmd("AUTH",
621 AUTH_PLAIN + " " + encode_plain(user, password))
622 elif authmethod == AUTH_LOGIN:
623 (code, resp) = self.docmd("AUTH",
624 "%s %s" % (AUTH_LOGIN, encode_base64(user.encode('ascii'), eol='')))
625 if code == 334:
626 (code, resp) = self.docmd(encode_base64(password.encode('ascii'), eol=''))
627
Guido van Rossumae010462001-09-11 15:57:46 +0000628 # 235 == 'Authentication successful'
629 # 503 == 'Error: already authenticated'
Gerhard Häring1c5471f2010-08-05 14:08:44 +0000630 if code in (235, 503):
631 return (code, resp)
632
633 # We could not login sucessfully. Return result of last attempt.
634 raise SMTPAuthenticationError(code, resp)
Guido van Rossumae010462001-09-11 15:57:46 +0000635
Antoine Pitroue0650202011-05-18 18:03:09 +0200636 def starttls(self, keyfile=None, certfile=None, context=None):
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000637 """Puts the connection to the SMTP server into TLS mode.
Tim Petersb64bec32001-09-18 02:26:39 +0000638
Christian Heimes679db4a2008-01-18 09:56:22 +0000639 If there has been no previous EHLO or HELO command this session, this
640 method tries ESMTP EHLO first.
641
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000642 If the server supports TLS, this will encrypt the rest of the SMTP
643 session. If you provide the keyfile and certfile parameters,
644 the identity of the SMTP server and client can be checked. This,
645 however, depends on whether the socket module really checks the
646 certificates.
Christian Heimes679db4a2008-01-18 09:56:22 +0000647
648 This method may raise the following exceptions:
649
650 SMTPHeloError The server didn't reply properly to
651 the helo greeting.
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000652 """
Christian Heimes679db4a2008-01-18 09:56:22 +0000653 self.ehlo_or_helo_if_needed()
654 if not self.has_extn("starttls"):
655 raise SMTPException("STARTTLS extension not supported by server.")
Tim Petersb64bec32001-09-18 02:26:39 +0000656 (resp, reply) = self.docmd("STARTTLS")
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000657 if resp == 220:
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000658 if not _have_ssl:
659 raise RuntimeError("No SSL support included in this Python")
Antoine Pitroue0650202011-05-18 18:03:09 +0200660 if context is not None and keyfile is not None:
661 raise ValueError("context and keyfile arguments are mutually "
662 "exclusive")
663 if context is not None and certfile is not None:
664 raise ValueError("context and certfile arguments are mutually "
665 "exclusive")
666 if context is not None:
667 self.sock = context.wrap_socket(self.sock)
668 else:
669 self.sock = ssl.wrap_socket(self.sock, keyfile, certfile)
Antoine Pitrouf068ab82011-06-06 19:17:09 +0200670 self.file = None
Christian Heimes679db4a2008-01-18 09:56:22 +0000671 # RFC 3207:
672 # The client MUST discard any knowledge obtained from
673 # the server, such as the list of SMTP service extensions,
674 # which was not obtained from the TLS negotiation itself.
675 self.helo_resp = None
676 self.ehlo_resp = None
677 self.esmtp_features = {}
678 self.does_esmtp = 0
Guido van Rossumf7fcf5e2001-09-14 16:08:44 +0000679 return (resp, reply)
Tim Petersb64bec32001-09-18 02:26:39 +0000680
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000681 def sendmail(self, from_addr, to_addrs, msg, mail_options=[],
Tim Peters495ad3c2001-01-15 01:36:40 +0000682 rcpt_options=[]):
683 """This command performs an entire mail transaction.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000684
Tim Peters495ad3c2001-01-15 01:36:40 +0000685 The arguments are:
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000686 - from_addr : The address sending this mail.
687 - to_addrs : A list of addresses to send this mail to. A bare
688 string will be treated as a list with 1 address.
Tim Peters495ad3c2001-01-15 01:36:40 +0000689 - msg : The message to send.
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000690 - mail_options : List of ESMTP options (such as 8bitmime) for the
691 mail command.
692 - rcpt_options : List of ESMTP options (such as DSN commands) for
693 all the rcpt commands.
694
R. David Murray7dff9e02010-11-08 17:15:13 +0000695 msg may be a string containing characters in the ASCII range, or a byte
696 string. A string is encoded to bytes using the ascii codec, and lone
R David Murrayac4e5ab2011-07-02 21:03:19 -0400697 \\r and \\n characters are converted to \\r\\n characters.
R. David Murray7dff9e02010-11-08 17:15:13 +0000698
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000699 If there has been no previous EHLO or HELO command this session, this
700 method tries ESMTP EHLO first. If the server does ESMTP, message size
701 and each of the specified options will be passed to it. If EHLO
702 fails, HELO will be tried and ESMTP options suppressed.
703
704 This method will return normally if the mail is accepted for at least
Barry Warsawd25c1b71999-11-28 17:11:06 +0000705 one recipient. It returns a dictionary, with one entry for each
706 recipient that was refused. Each entry contains a tuple of the SMTP
707 error code and the accompanying error message sent by the server.
Guido van Rossum296e1431999-04-07 15:03:39 +0000708
709 This method may raise the following exceptions:
710
711 SMTPHeloError The server didn't reply properly to
Tim Peters495ad3c2001-01-15 01:36:40 +0000712 the helo greeting.
Barry Warsawd25c1b71999-11-28 17:11:06 +0000713 SMTPRecipientsRefused The server rejected ALL recipients
Guido van Rossum296e1431999-04-07 15:03:39 +0000714 (no mail was sent).
715 SMTPSenderRefused The server didn't accept the from_addr.
716 SMTPDataError The server replied with an unexpected
717 error code (other than a refusal of
718 a recipient).
719
720 Note: the connection will be open even after an exception is raised.
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000721
Guido van Rossum95e6f701998-06-25 02:15:50 +0000722 Example:
Tim Peters495ad3c2001-01-15 01:36:40 +0000723
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000724 >>> import smtplib
725 >>> s=smtplib.SMTP("localhost")
Guido van Rossumfc40a831998-01-29 17:26:45 +0000726 >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"]
Martin v. Löwis301b1cd2002-07-28 16:52:01 +0000727 >>> msg = '''\\
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000728 ... From: Me@my.org
729 ... Subject: testin'...
730 ...
731 ... This is a test '''
732 >>> s.sendmail("me@my.org",tolist,msg)
733 { "three@three.org" : ( 550 ,"User unknown" ) }
734 >>> s.quit()
Tim Peters495ad3c2001-01-15 01:36:40 +0000735
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000736 In the above example, the message was accepted for delivery to three
737 of the four addresses, and one was rejected, with the error code
Barry Warsawd25c1b71999-11-28 17:11:06 +0000738 550. If all addresses are accepted, then the method will return an
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000739 empty dictionary.
740
741 """
Christian Heimes679db4a2008-01-18 09:56:22 +0000742 self.ehlo_or_helo_if_needed()
Guido van Rossum95e6f701998-06-25 02:15:50 +0000743 esmtp_opts = []
R. David Murray7dff9e02010-11-08 17:15:13 +0000744 if isinstance(msg, str):
745 msg = _fix_eols(msg).encode('ascii')
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000746 if self.does_esmtp:
747 # Hmmm? what's this? -ddm
748 # self.esmtp_features['7bit']=""
749 if self.has_extn('size'):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000750 esmtp_opts.append("size=%d" % len(msg))
Guido van Rossumfcfb6321998-08-04 15:29:54 +0000751 for option in mail_options:
Guido van Rossum95e6f701998-06-25 02:15:50 +0000752 esmtp_opts.append(option)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000753 (code, resp) = self.mail(from_addr, esmtp_opts)
Fred Drake8152d322000-12-12 23:20:45 +0000754 if code != 250:
R David Murrayd312c742013-03-20 20:36:14 -0400755 if code == 421:
756 self.close()
757 else:
758 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000759 raise SMTPSenderRefused(code, resp, from_addr)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000760 senderrs = {}
Guido van Rossum3172c5d2007-10-16 18:12:55 +0000761 if isinstance(to_addrs, str):
Jeremy Hylton31bb8ce1998-08-13 19:57:46 +0000762 to_addrs = [to_addrs]
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000763 for each in to_addrs:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000764 (code, resp) = self.rcpt(each, rcpt_options)
Fred Drake8152d322000-12-12 23:20:45 +0000765 if (code != 250) and (code != 251):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000766 senderrs[each] = (code, resp)
R David Murrayd312c742013-03-20 20:36:14 -0400767 if code == 421:
768 self.close()
769 raise SMTPRecipientsRefused(senderrs)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000770 if len(senderrs) == len(to_addrs):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000771 # the server refused all our recipients
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000772 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000773 raise SMTPRecipientsRefused(senderrs)
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000774 (code, resp) = self.data(msg)
Fred Drake8152d322000-12-12 23:20:45 +0000775 if code != 250:
R David Murrayd312c742013-03-20 20:36:14 -0400776 if code == 421:
777 self.close()
778 else:
779 self.rset()
Guido van Rossum296e1431999-04-07 15:03:39 +0000780 raise SMTPDataError(code, resp)
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000781 #if we got here then somebody got our mail
Tim Peters495ad3c2001-01-15 01:36:40 +0000782 return senderrs
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000783
R. David Murray7dff9e02010-11-08 17:15:13 +0000784 def send_message(self, msg, from_addr=None, to_addrs=None,
785 mail_options=[], rcpt_options={}):
786 """Converts message to a bytestring and passes it to sendmail.
787
788 The arguments are as for sendmail, except that msg is an
R David Murrayac4e5ab2011-07-02 21:03:19 -0400789 email.message.Message object. If from_addr is None or to_addrs is
790 None, these arguments are taken from the headers of the Message as
791 described in RFC 2822 (a ValueError is raised if there is more than
792 one set of 'Resent-' headers). Regardless of the values of from_addr and
793 to_addr, any Bcc field (or Resent-Bcc field, when the Message is a
794 resent) of the Message object won't be transmitted. The Message
795 object is then serialized using email.generator.BytesGenerator and
796 sendmail is called to transmit the message.
797
R. David Murray7dff9e02010-11-08 17:15:13 +0000798 """
R David Murrayac4e5ab2011-07-02 21:03:19 -0400799 # 'Resent-Date' is a mandatory field if the Message is resent (RFC 2822
800 # Section 3.6.6). In such a case, we use the 'Resent-*' fields. However,
801 # if there is more than one 'Resent-' block there's no way to
802 # unambiguously determine which one is the most recent in all cases,
803 # so rather than guess we raise a ValueError in that case.
804 #
805 # TODO implement heuristics to guess the correct Resent-* block with an
806 # option allowing the user to enable the heuristics. (It should be
807 # possible to guess correctly almost all of the time.)
Senthil Kumaranb351a482011-07-31 09:14:17 +0800808
809 resent = msg.get_all('Resent-Date')
R David Murrayac4e5ab2011-07-02 21:03:19 -0400810 if resent is None:
811 header_prefix = ''
812 elif len(resent) == 1:
813 header_prefix = 'Resent-'
814 else:
815 raise ValueError("message has more than one 'Resent-' header block")
R. David Murray7dff9e02010-11-08 17:15:13 +0000816 if from_addr is None:
R David Murrayac4e5ab2011-07-02 21:03:19 -0400817 # Prefer the sender field per RFC 2822:3.6.2.
Senthil Kumaranb351a482011-07-31 09:14:17 +0800818 from_addr = (msg[header_prefix + 'Sender']
819 if (header_prefix + 'Sender') in msg
820 else msg[header_prefix + 'From'])
R. David Murray7dff9e02010-11-08 17:15:13 +0000821 if to_addrs is None:
Senthil Kumaranb351a482011-07-31 09:14:17 +0800822 addr_fields = [f for f in (msg[header_prefix + 'To'],
823 msg[header_prefix + 'Bcc'],
824 msg[header_prefix + 'Cc']) if f is not None]
R. David Murray7dff9e02010-11-08 17:15:13 +0000825 to_addrs = [a[1] for a in email.utils.getaddresses(addr_fields)]
R David Murrayac4e5ab2011-07-02 21:03:19 -0400826 # Make a local copy so we can delete the bcc headers.
827 msg_copy = copy.copy(msg)
828 del msg_copy['Bcc']
829 del msg_copy['Resent-Bcc']
R. David Murray7dff9e02010-11-08 17:15:13 +0000830 with io.BytesIO() as bytesmsg:
831 g = email.generator.BytesGenerator(bytesmsg)
R David Murrayac4e5ab2011-07-02 21:03:19 -0400832 g.flatten(msg_copy, linesep='\r\n')
R. David Murray7dff9e02010-11-08 17:15:13 +0000833 flatmsg = bytesmsg.getvalue()
834 return self.sendmail(from_addr, to_addrs, flatmsg, mail_options,
835 rcpt_options)
836
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000837 def close(self):
838 """Close the connection to the SMTP server."""
839 if self.file:
840 self.file.close()
841 self.file = None
842 if self.sock:
843 self.sock.close()
844 self.sock = None
845
Guido van Rossumbbe323e1998-01-29 17:24:40 +0000846 def quit(self):
Guido van Rossum95e6f701998-06-25 02:15:50 +0000847 """Terminate the SMTP session."""
Christian Heimesba4af492008-03-28 00:55:15 +0000848 res = self.docmd("quit")
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000849 self.close()
Christian Heimesba4af492008-03-28 00:55:15 +0000850 return res
Guido van Rossum95e6f701998-06-25 02:15:50 +0000851
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000852if _have_ssl:
Thomas Wouters89f507f2006-12-13 04:49:30 +0000853
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000854 class SMTP_SSL(SMTP):
855 """ This is a subclass derived from SMTP that connects over an SSL encrypted
856 socket (to use this class you need a socket module that was compiled with SSL
857 support). If host is not specified, '' (the local host) is used. If port is
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800858 omitted, the standard SMTP-over-SSL port (465) is used. The optional
859 source_address takes a two-tuple (host,port) for socket to bind to. keyfile and certfile
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000860 are also optional - they can contain a PEM formatted private key and
Antoine Pitroue0650202011-05-18 18:03:09 +0200861 certificate chain file for the SSL connection. context also optional, can contain
862 a SSLContext, and is an alternative to keyfile and certfile; If it is specified both
863 keyfile and certfile must be None.
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000864 """
Antoine Pitrouc1d52062011-05-07 19:39:37 +0200865
866 default_port = SMTP_SSL_PORT
867
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000868 def __init__(self, host='', port=0, local_hostname=None,
Georg Brandlf78e02b2008-06-10 17:40:04 +0000869 keyfile=None, certfile=None,
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800870 timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
871 source_address=None, context=None):
Antoine Pitroue0650202011-05-18 18:03:09 +0200872 if context is not None and keyfile is not None:
873 raise ValueError("context and keyfile arguments are mutually "
874 "exclusive")
875 if context is not None and certfile is not None:
876 raise ValueError("context and certfile arguments are mutually "
877 "exclusive")
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000878 self.keyfile = keyfile
879 self.certfile = certfile
Antoine Pitroue0650202011-05-18 18:03:09 +0200880 self.context = context
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800881 SMTP.__init__(self, host, port, local_hostname, timeout,
882 source_address)
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000883
884 def _get_socket(self, host, port, timeout):
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000885 if self.debuglevel > 0:
886 print('connect:', (host, port), file=stderr)
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800887 new_socket = socket.create_connection((host, port), timeout,
888 self.source_address)
Antoine Pitroue0650202011-05-18 18:03:09 +0200889 if self.context is not None:
890 new_socket = self.context.wrap_socket(new_socket)
891 else:
892 new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile)
R. David Murray87e20742009-05-23 01:30:26 +0000893 return new_socket
Thomas Wouters47b49bf2007-08-30 22:15:33 +0000894
895 __all__.append("SMTP_SSL")
Barry Warsaw4c4bec81998-12-22 03:02:20 +0000896
Guido van Rossumd8faa362007-04-27 19:54:29 +0000897#
898# LMTP extension
899#
900LMTP_PORT = 2003
901
902class LMTP(SMTP):
903 """LMTP - Local Mail Transfer Protocol
904
905 The LMTP protocol, which is very similar to ESMTP, is heavily based
906 on the standard SMTP client. It's common to use Unix sockets for LMTP,
907 so our connect() method must support that as well as a regular
908 host:port server. To specify a Unix socket, you must use an absolute
909 path as the host, starting with a '/'.
910
911 Authentication is supported, using the regular SMTP mechanism. When
912 using a Unix socket, LMTP generally don't support or require any
913 authentication, but your mileage might vary."""
914
915 ehlo_msg = "lhlo"
916
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800917 def __init__(self, host='', port=LMTP_PORT, local_hostname=None,
918 source_address=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000919 """Initialize a new instance."""
Senthil Kumaranb351a482011-07-31 09:14:17 +0800920 SMTP.__init__(self, host, port, local_hostname=local_hostname,
921 source_address=source_address)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000922
Senthil Kumaran3d23fd62011-07-30 10:56:50 +0800923 def connect(self, host='localhost', port=0, source_address=None):
Guido van Rossumd8faa362007-04-27 19:54:29 +0000924 """Connect to the LMTP daemon, on either a Unix or a TCP socket."""
925 if host[0] != '/':
Senthil Kumaranb351a482011-07-31 09:14:17 +0800926 return SMTP.connect(self, host, port, source_address=source_address)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000927
928 # Handle Unix-domain sockets.
929 try:
930 self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
Antoine Pitrouf068ab82011-06-06 19:17:09 +0200931 self.file = None
Guido van Rossumd8faa362007-04-27 19:54:29 +0000932 self.sock.connect(host)
Andrew Svetlov2ade6f22012-12-17 18:57:16 +0200933 except OSError:
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000934 if self.debuglevel > 0:
935 print('connect fail:', host, file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000936 if self.sock:
937 self.sock.close()
938 self.sock = None
Andrew Svetlovb6693c42012-12-17 18:54:53 +0200939 raise
Guido van Rossumd8faa362007-04-27 19:54:29 +0000940 (code, msg) = self.getreply()
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000941 if self.debuglevel > 0:
942 print('connect:', msg, file=stderr)
Guido van Rossumd8faa362007-04-27 19:54:29 +0000943 return (code, msg)
944
945
Guido van Rossum95e6f701998-06-25 02:15:50 +0000946# Test the sendmail method, which tests most of the others.
947# Note: This always sends to localhost.
948if __name__ == '__main__':
Andrew M. Kuchling6be424f2001-08-13 14:41:39 +0000949 import sys
Guido van Rossum95e6f701998-06-25 02:15:50 +0000950
951 def prompt(prompt):
952 sys.stdout.write(prompt + ": ")
Ezio Melotti6bfecd12011-10-18 13:20:07 +0300953 sys.stdout.flush()
Eric S. Raymondc013f302001-02-09 05:40:38 +0000954 return sys.stdin.readline().strip()
Guido van Rossum95e6f701998-06-25 02:15:50 +0000955
956 fromaddr = prompt("From")
Giampaolo Rodolàbd258bd2011-02-22 15:56:20 +0000957 toaddrs = prompt("To").split(',')
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000958 print("Enter message, end with ^D:")
Guido van Rossum95e6f701998-06-25 02:15:50 +0000959 msg = ''
960 while 1:
961 line = sys.stdin.readline()
962 if not line:
963 break
964 msg = msg + line
Guido van Rossumbe19ed72007-02-09 05:37:30 +0000965 print("Message length is %d" % len(msg))
Guido van Rossum95e6f701998-06-25 02:15:50 +0000966
967 server = SMTP('localhost')
968 server.set_debuglevel(1)
969 server.sendmail(fromaddr, toaddrs, msg)
970 server.quit()