diff options
Diffstat (limited to 'lib/python2.7/smtplib.py')
-rwxr-xr-x | lib/python2.7/smtplib.py | 858 |
1 files changed, 0 insertions, 858 deletions
diff --git a/lib/python2.7/smtplib.py b/lib/python2.7/smtplib.py deleted file mode 100755 index a3213b3..0000000 --- a/lib/python2.7/smtplib.py +++ /dev/null @@ -1,858 +0,0 @@ -#! /usr/bin/env python - -'''SMTP/ESMTP client class. - -This should follow RFC 821 (SMTP), RFC 1869 (ESMTP), RFC 2554 (SMTP -Authentication) and RFC 2487 (Secure SMTP over TLS). - -Notes: - -Please remember, when doing ESMTP, that the names of the SMTP service -extensions are NOT the same thing as the option keywords for the RCPT -and MAIL commands! - -Example: - - >>> import smtplib - >>> s=smtplib.SMTP("localhost") - >>> print s.help() - This is Sendmail version 8.8.4 - Topics: - HELO EHLO MAIL RCPT DATA - RSET NOOP QUIT HELP VRFY - EXPN VERB ETRN DSN - For more info use "HELP <topic>". - To report bugs in the implementation send email to - sendmail-bugs@sendmail.org. - For local information send email to Postmaster at your site. - End of HELP info - >>> s.putcmd("vrfy","someone@here") - >>> s.getreply() - (250, "Somebody OverHere <somebody@here.my.org>") - >>> s.quit() -''' - -# Author: The Dragon De Monsyne <dragondm@integral.org> -# ESMTP support, test code and doc fixes added by -# Eric S. Raymond <esr@thyrsus.com> -# Better RFC 821 compliance (MAIL and RCPT, and CRLF in data) -# by Carey Evans <c.evans@clear.net.nz>, for picky mail servers. -# RFC 2554 (authentication) support by Gerhard Haering <gerhard@bigfoot.de>. -# -# This was modified from the Python 1.5 library HTTP lib. - -import socket -import re -import email.utils -import base64 -import hmac -from email.base64mime import encode as encode_base64 -from sys import stderr - -__all__ = ["SMTPException", "SMTPServerDisconnected", "SMTPResponseException", - "SMTPSenderRefused", "SMTPRecipientsRefused", "SMTPDataError", - "SMTPConnectError", "SMTPHeloError", "SMTPAuthenticationError", - "quoteaddr", "quotedata", "SMTP"] - -SMTP_PORT = 25 -SMTP_SSL_PORT = 465 -CRLF = "\r\n" - -OLDSTYLE_AUTH = re.compile(r"auth=(.*)", re.I) - - -# Exception classes used by this module. -class SMTPException(Exception): - """Base class for all exceptions raised by this module.""" - -class SMTPServerDisconnected(SMTPException): - """Not connected to any SMTP server. - - This exception is raised when the server unexpectedly disconnects, - or when an attempt is made to use the SMTP instance before - connecting it to a server. - """ - -class SMTPResponseException(SMTPException): - """Base class for all exceptions that include an SMTP error code. - - These exceptions are generated in some instances when the SMTP - server returns an error code. The error code is stored in the - `smtp_code' attribute of the error, and the `smtp_error' attribute - is set to the error message. - """ - - def __init__(self, code, msg): - self.smtp_code = code - self.smtp_error = msg - self.args = (code, msg) - -class SMTPSenderRefused(SMTPResponseException): - """Sender address refused. - - In addition to the attributes set by on all SMTPResponseException - exceptions, this sets `sender' to the string that the SMTP refused. - """ - - def __init__(self, code, msg, sender): - self.smtp_code = code - self.smtp_error = msg - self.sender = sender - self.args = (code, msg, sender) - -class SMTPRecipientsRefused(SMTPException): - """All recipient addresses refused. - - The errors for each recipient are accessible through the attribute - 'recipients', which is a dictionary of exactly the same sort as - SMTP.sendmail() returns. - """ - - def __init__(self, recipients): - self.recipients = recipients - self.args = (recipients,) - - -class SMTPDataError(SMTPResponseException): - """The SMTP server didn't accept the data.""" - -class SMTPConnectError(SMTPResponseException): - """Error during connection establishment.""" - -class SMTPHeloError(SMTPResponseException): - """The server refused our HELO reply.""" - -class SMTPAuthenticationError(SMTPResponseException): - """Authentication error. - - Most probably the server didn't accept the username/password - combination provided. - """ - - -def quoteaddr(addr): - """Quote a subset of the email addresses defined by RFC 821. - - Should be able to handle anything rfc822.parseaddr can handle. - """ - m = (None, None) - try: - m = email.utils.parseaddr(addr)[1] - except AttributeError: - pass - if m == (None, None): # Indicates parse failure or AttributeError - # something weird here.. punt -ddm - return "<%s>" % addr - elif m is None: - # the sender wants an empty return address - return "<>" - else: - return "<%s>" % m - -def _addr_only(addrstring): - displayname, addr = email.utils.parseaddr(addrstring) - if (displayname, addr) == ('', ''): - # parseaddr couldn't parse it, so use it as is. - return addrstring - return addr - -def quotedata(data): - """Quote data for email. - - Double leading '.', and change Unix newline '\\n', or Mac '\\r' into - Internet CRLF end-of-line. - """ - return re.sub(r'(?m)^\.', '..', - re.sub(r'(?:\r\n|\n|\r(?!\n))', CRLF, data)) - - -try: - import ssl -except ImportError: - _have_ssl = False -else: - class SSLFakeFile: - """A fake file like object that really wraps a SSLObject. - - It only supports what is needed in smtplib. - """ - def __init__(self, sslobj): - self.sslobj = sslobj - - def readline(self): - str = "" - chr = None - while chr != "\n": - chr = self.sslobj.read(1) - if not chr: - break - str += chr - return str - - def close(self): - pass - - _have_ssl = True - -class SMTP: - """This class manages a connection to an SMTP or ESMTP server. - SMTP Objects: - SMTP objects have the following attributes: - helo_resp - This is the message given by the server in response to the - most recent HELO command. - - ehlo_resp - This is the message given by the server in response to the - most recent EHLO command. This is usually multiline. - - does_esmtp - This is a True value _after you do an EHLO command_, if the - server supports ESMTP. - - esmtp_features - This is a dictionary, which, if the server supports ESMTP, - will _after you do an EHLO command_, contain the names of the - SMTP service extensions this server supports, and their - parameters (if any). - - Note, all extension names are mapped to lower case in the - dictionary. - - See each method's docstrings for details. In general, there is a - method of the same name to perform each SMTP command. There is also a - method called 'sendmail' that will do an entire mail transaction. - """ - debuglevel = 0 - file = None - helo_resp = None - ehlo_msg = "ehlo" - ehlo_resp = None - does_esmtp = 0 - default_port = SMTP_PORT - - def __init__(self, host='', port=0, local_hostname=None, - timeout=socket._GLOBAL_DEFAULT_TIMEOUT): - """Initialize a new instance. - - If specified, `host' is the name of the remote host to which to - connect. If specified, `port' specifies the port to which to connect. - By default, smtplib.SMTP_PORT is used. If a host is specified the - connect method is called, and if it returns anything other than - a success code an SMTPConnectError is raised. If specified, - `local_hostname` is used as the FQDN of the local host. By default, - the local hostname is found using socket.getfqdn(). - - """ - self.timeout = timeout - self.esmtp_features = {} - if host: - (code, msg) = self.connect(host, port) - if code != 220: - raise SMTPConnectError(code, msg) - if local_hostname is not None: - self.local_hostname = local_hostname - else: - # RFC 2821 says we should use the fqdn in the EHLO/HELO verb, and - # if that can't be calculated, that we should use a domain literal - # instead (essentially an encoded IP address like [A.B.C.D]). - fqdn = socket.getfqdn() - if '.' in fqdn: - self.local_hostname = fqdn - else: - # We can't find an fqdn hostname, so use a domain literal - addr = '127.0.0.1' - try: - addr = socket.gethostbyname(socket.gethostname()) - except socket.gaierror: - pass - self.local_hostname = '[%s]' % addr - - def set_debuglevel(self, debuglevel): - """Set the debug output level. - - A non-false value results in debug messages for connection and for all - messages sent to and received from the server. - - """ - self.debuglevel = debuglevel - - def _get_socket(self, host, port, timeout): - # This makes it simpler for SMTP_SSL to use the SMTP connect code - # and just alter the socket connection bit. - if self.debuglevel > 0: - print>>stderr, 'connect:', (host, port) - return socket.create_connection((host, port), timeout) - - def connect(self, host='localhost', port=0): - """Connect to a host on a given port. - - If the hostname ends with a colon (`:') followed by a number, and - there is no port specified, that suffix will be stripped off and the - number interpreted as the port number to use. - - Note: This method is automatically invoked by __init__, if a host is - specified during instantiation. - - """ - if not port and (host.find(':') == host.rfind(':')): - i = host.rfind(':') - if i >= 0: - host, port = host[:i], host[i + 1:] - try: - port = int(port) - except ValueError: - raise socket.error, "nonnumeric port" - if not port: - port = self.default_port - if self.debuglevel > 0: - print>>stderr, 'connect:', (host, port) - self.sock = self._get_socket(host, port, self.timeout) - (code, msg) = self.getreply() - if self.debuglevel > 0: - print>>stderr, "connect:", msg - return (code, msg) - - def send(self, str): - """Send `str' to the server.""" - if self.debuglevel > 0: - print>>stderr, 'send:', repr(str) - if hasattr(self, 'sock') and self.sock: - try: - self.sock.sendall(str) - except socket.error: - self.close() - raise SMTPServerDisconnected('Server not connected') - else: - raise SMTPServerDisconnected('please run connect() first') - - def putcmd(self, cmd, args=""): - """Send a command to the server.""" - if args == "": - str = '%s%s' % (cmd, CRLF) - else: - str = '%s %s%s' % (cmd, args, CRLF) - self.send(str) - - def getreply(self): - """Get a reply from the server. - - Returns a tuple consisting of: - - - server response code (e.g. '250', or such, if all goes well) - Note: returns -1 if it can't read response code. - - - server response string corresponding to response code (multiline - responses are converted to a single, multiline string). - - Raises SMTPServerDisconnected if end-of-file is reached. - """ - resp = [] - if self.file is None: - self.file = self.sock.makefile('rb') - while 1: - try: - line = self.file.readline() - except socket.error as e: - self.close() - raise SMTPServerDisconnected("Connection unexpectedly closed: " - + str(e)) - if line == '': - self.close() - raise SMTPServerDisconnected("Connection unexpectedly closed") - if self.debuglevel > 0: - print>>stderr, 'reply:', repr(line) - resp.append(line[4:].strip()) - code = line[:3] - # Check that the error code is syntactically correct. - # Don't attempt to read a continuation line if it is broken. - try: - errcode = int(code) - except ValueError: - errcode = -1 - break - # Check if multiline response. - if line[3:4] != "-": - break - - errmsg = "\n".join(resp) - if self.debuglevel > 0: - print>>stderr, 'reply: retcode (%s); Msg: %s' % (errcode, errmsg) - return errcode, errmsg - - def docmd(self, cmd, args=""): - """Send a command, and return its response code.""" - self.putcmd(cmd, args) - return self.getreply() - - # std smtp commands - def helo(self, name=''): - """SMTP 'helo' command. - Hostname to send for this command defaults to the FQDN of the local - host. - """ - self.putcmd("helo", name or self.local_hostname) - (code, msg) = self.getreply() - self.helo_resp = msg - return (code, msg) - - def ehlo(self, name=''): - """ SMTP 'ehlo' command. - Hostname to send for this command defaults to the FQDN of the local - host. - """ - self.esmtp_features = {} - self.putcmd(self.ehlo_msg, name or self.local_hostname) - (code, msg) = self.getreply() - # According to RFC1869 some (badly written) - # MTA's will disconnect on an ehlo. Toss an exception if - # that happens -ddm - if code == -1 and len(msg) == 0: - self.close() - raise SMTPServerDisconnected("Server not connected") - self.ehlo_resp = msg - if code != 250: - return (code, msg) - self.does_esmtp = 1 - #parse the ehlo response -ddm - resp = self.ehlo_resp.split('\n') - del resp[0] - for each in resp: - # To be able to communicate with as many SMTP servers as possible, - # we have to take the old-style auth advertisement into account, - # because: - # 1) Else our SMTP feature parser gets confused. - # 2) There are some servers that only advertise the auth methods we - # support using the old style. - auth_match = OLDSTYLE_AUTH.match(each) - if auth_match: - # This doesn't remove duplicates, but that's no problem - self.esmtp_features["auth"] = self.esmtp_features.get("auth", "") \ - + " " + auth_match.groups(0)[0] - continue - - # RFC 1869 requires a space between ehlo keyword and parameters. - # It's actually stricter, in that only spaces are allowed between - # parameters, but were not going to check for that here. Note - # that the space isn't present if there are no parameters. - m = re.match(r'(?P<feature>[A-Za-z0-9][A-Za-z0-9\-]*) ?', each) - if m: - feature = m.group("feature").lower() - params = m.string[m.end("feature"):].strip() - if feature == "auth": - self.esmtp_features[feature] = self.esmtp_features.get(feature, "") \ - + " " + params - else: - self.esmtp_features[feature] = params - return (code, msg) - - def has_extn(self, opt): - """Does the server support a given SMTP service extension?""" - return opt.lower() in self.esmtp_features - - def help(self, args=''): - """SMTP 'help' command. - Returns help text from server.""" - self.putcmd("help", args) - return self.getreply()[1] - - def rset(self): - """SMTP 'rset' command -- resets session.""" - return self.docmd("rset") - - def noop(self): - """SMTP 'noop' command -- doesn't do anything :>""" - return self.docmd("noop") - - def mail(self, sender, options=[]): - """SMTP 'mail' command -- begins mail xfer session.""" - optionlist = '' - if options and self.does_esmtp: - optionlist = ' ' + ' '.join(options) - self.putcmd("mail", "FROM:%s%s" % (quoteaddr(sender), optionlist)) - return self.getreply() - - def rcpt(self, recip, options=[]): - """SMTP 'rcpt' command -- indicates 1 recipient for this mail.""" - optionlist = '' - if options and self.does_esmtp: - optionlist = ' ' + ' '.join(options) - self.putcmd("rcpt", "TO:%s%s" % (quoteaddr(recip), optionlist)) - return self.getreply() - - def data(self, msg): - """SMTP 'DATA' command -- sends message data to server. - - Automatically quotes lines beginning with a period per rfc821. - Raises SMTPDataError if there is an unexpected reply to the - DATA command; the return value from this method is the final - response code received when the all data is sent. - """ - self.putcmd("data") - (code, repl) = self.getreply() - if self.debuglevel > 0: - print>>stderr, "data:", (code, repl) - if code != 354: - raise SMTPDataError(code, repl) - else: - q = quotedata(msg) - if q[-2:] != CRLF: - q = q + CRLF - q = q + "." + CRLF - self.send(q) - (code, msg) = self.getreply() - if self.debuglevel > 0: - print>>stderr, "data:", (code, msg) - return (code, msg) - - def verify(self, address): - """SMTP 'verify' command -- checks for address validity.""" - self.putcmd("vrfy", _addr_only(address)) - return self.getreply() - # a.k.a. - vrfy = verify - - def expn(self, address): - """SMTP 'expn' command -- expands a mailing list.""" - self.putcmd("expn", _addr_only(address)) - return self.getreply() - - # some useful methods - - def ehlo_or_helo_if_needed(self): - """Call self.ehlo() and/or self.helo() if needed. - - If there has been no previous EHLO or HELO command this session, this - method tries ESMTP EHLO first. - - This method may raise the following exceptions: - - SMTPHeloError The server didn't reply properly to - the helo greeting. - """ - if self.helo_resp is None and self.ehlo_resp is None: - if not (200 <= self.ehlo()[0] <= 299): - (code, resp) = self.helo() - if not (200 <= code <= 299): - raise SMTPHeloError(code, resp) - - def login(self, user, password): - """Log in on an SMTP server that requires authentication. - - The arguments are: - - user: The user name to authenticate with. - - password: The password for the authentication. - - If there has been no previous EHLO or HELO command this session, this - method tries ESMTP EHLO first. - - This method will return normally if the authentication was successful. - - This method may raise the following exceptions: - - SMTPHeloError The server didn't reply properly to - the helo greeting. - SMTPAuthenticationError The server didn't accept the username/ - password combination. - SMTPException No suitable authentication method was - found. - """ - - def encode_cram_md5(challenge, user, password): - challenge = base64.decodestring(challenge) - response = user + " " + hmac.HMAC(password, challenge).hexdigest() - return encode_base64(response, eol="") - - def encode_plain(user, password): - return encode_base64("\0%s\0%s" % (user, password), eol="") - - - AUTH_PLAIN = "PLAIN" - AUTH_CRAM_MD5 = "CRAM-MD5" - AUTH_LOGIN = "LOGIN" - - self.ehlo_or_helo_if_needed() - - if not self.has_extn("auth"): - raise SMTPException("SMTP AUTH extension not supported by server.") - - # Authentication methods the server supports: - authlist = self.esmtp_features["auth"].split() - - # List of authentication methods we support: from preferred to - # less preferred methods. Except for the purpose of testing the weaker - # ones, we prefer stronger methods like CRAM-MD5: - preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN] - - # Determine the authentication method we'll use - authmethod = None - for method in preferred_auths: - if method in authlist: - authmethod = method - break - - if authmethod == AUTH_CRAM_MD5: - (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5) - if code == 503: - # 503 == 'Error: already authenticated' - return (code, resp) - (code, resp) = self.docmd(encode_cram_md5(resp, user, password)) - elif authmethod == AUTH_PLAIN: - (code, resp) = self.docmd("AUTH", - AUTH_PLAIN + " " + encode_plain(user, password)) - elif authmethod == AUTH_LOGIN: - (code, resp) = self.docmd("AUTH", - "%s %s" % (AUTH_LOGIN, encode_base64(user, eol=""))) - if code != 334: - raise SMTPAuthenticationError(code, resp) - (code, resp) = self.docmd(encode_base64(password, eol="")) - elif authmethod is None: - raise SMTPException("No suitable authentication method found.") - if code not in (235, 503): - # 235 == 'Authentication successful' - # 503 == 'Error: already authenticated' - raise SMTPAuthenticationError(code, resp) - return (code, resp) - - def starttls(self, keyfile=None, certfile=None): - """Puts the connection to the SMTP server into TLS mode. - - If there has been no previous EHLO or HELO command this session, this - method tries ESMTP EHLO first. - - If the server supports TLS, this will encrypt the rest of the SMTP - session. If you provide the keyfile and certfile parameters, - the identity of the SMTP server and client can be checked. This, - however, depends on whether the socket module really checks the - certificates. - - This method may raise the following exceptions: - - SMTPHeloError The server didn't reply properly to - the helo greeting. - """ - self.ehlo_or_helo_if_needed() - if not self.has_extn("starttls"): - raise SMTPException("STARTTLS extension not supported by server.") - (resp, reply) = self.docmd("STARTTLS") - if resp == 220: - if not _have_ssl: - raise RuntimeError("No SSL support included in this Python") - self.sock = ssl.wrap_socket(self.sock, keyfile, certfile) - self.file = SSLFakeFile(self.sock) - # RFC 3207: - # The client MUST discard any knowledge obtained from - # the server, such as the list of SMTP service extensions, - # which was not obtained from the TLS negotiation itself. - self.helo_resp = None - self.ehlo_resp = None - self.esmtp_features = {} - self.does_esmtp = 0 - return (resp, reply) - - def sendmail(self, from_addr, to_addrs, msg, mail_options=[], - rcpt_options=[]): - """This command performs an entire mail transaction. - - The arguments are: - - from_addr : The address sending this mail. - - to_addrs : A list of addresses to send this mail to. A bare - string will be treated as a list with 1 address. - - msg : The message to send. - - mail_options : List of ESMTP options (such as 8bitmime) for the - mail command. - - rcpt_options : List of ESMTP options (such as DSN commands) for - all the rcpt commands. - - If there has been no previous EHLO or HELO command this session, this - method tries ESMTP EHLO first. If the server does ESMTP, message size - and each of the specified options will be passed to it. If EHLO - fails, HELO will be tried and ESMTP options suppressed. - - This method will return normally if the mail is accepted for at least - one recipient. It returns a dictionary, with one entry for each - recipient that was refused. Each entry contains a tuple of the SMTP - error code and the accompanying error message sent by the server. - - This method may raise the following exceptions: - - SMTPHeloError The server didn't reply properly to - the helo greeting. - SMTPRecipientsRefused The server rejected ALL recipients - (no mail was sent). - SMTPSenderRefused The server didn't accept the from_addr. - SMTPDataError The server replied with an unexpected - error code (other than a refusal of - a recipient). - - Note: the connection will be open even after an exception is raised. - - Example: - - >>> import smtplib - >>> s=smtplib.SMTP("localhost") - >>> tolist=["one@one.org","two@two.org","three@three.org","four@four.org"] - >>> msg = '''\\ - ... From: Me@my.org - ... Subject: testin'... - ... - ... This is a test ''' - >>> s.sendmail("me@my.org",tolist,msg) - { "three@three.org" : ( 550 ,"User unknown" ) } - >>> s.quit() - - In the above example, the message was accepted for delivery to three - of the four addresses, and one was rejected, with the error code - 550. If all addresses are accepted, then the method will return an - empty dictionary. - - """ - self.ehlo_or_helo_if_needed() - esmtp_opts = [] - if self.does_esmtp: - # Hmmm? what's this? -ddm - # self.esmtp_features['7bit']="" - if self.has_extn('size'): - esmtp_opts.append("size=%d" % len(msg)) - for option in mail_options: - esmtp_opts.append(option) - - (code, resp) = self.mail(from_addr, esmtp_opts) - if code != 250: - self.rset() - raise SMTPSenderRefused(code, resp, from_addr) - senderrs = {} - if isinstance(to_addrs, basestring): - to_addrs = [to_addrs] - for each in to_addrs: - (code, resp) = self.rcpt(each, rcpt_options) - if (code != 250) and (code != 251): - senderrs[each] = (code, resp) - if len(senderrs) == len(to_addrs): - # the server refused all our recipients - self.rset() - raise SMTPRecipientsRefused(senderrs) - (code, resp) = self.data(msg) - if code != 250: - self.rset() - raise SMTPDataError(code, resp) - #if we got here then somebody got our mail - return senderrs - - - def close(self): - """Close the connection to the SMTP server.""" - if self.file: - self.file.close() - self.file = None - if self.sock: - self.sock.close() - self.sock = None - - - def quit(self): - """Terminate the SMTP session.""" - res = self.docmd("quit") - self.close() - return res - -if _have_ssl: - - class SMTP_SSL(SMTP): - """ This is a subclass derived from SMTP that connects over an SSL encrypted - socket (to use this class you need a socket module that was compiled with SSL - support). If host is not specified, '' (the local host) is used. If port is - omitted, the standard SMTP-over-SSL port (465) is used. keyfile and certfile - are also optional - they can contain a PEM formatted private key and - certificate chain file for the SSL connection. - """ - - default_port = SMTP_SSL_PORT - - def __init__(self, host='', port=0, local_hostname=None, - keyfile=None, certfile=None, - timeout=socket._GLOBAL_DEFAULT_TIMEOUT): - self.keyfile = keyfile - self.certfile = certfile - SMTP.__init__(self, host, port, local_hostname, timeout) - - def _get_socket(self, host, port, timeout): - if self.debuglevel > 0: - print>>stderr, 'connect:', (host, port) - new_socket = socket.create_connection((host, port), timeout) - new_socket = ssl.wrap_socket(new_socket, self.keyfile, self.certfile) - self.file = SSLFakeFile(new_socket) - return new_socket - - __all__.append("SMTP_SSL") - -# -# LMTP extension -# -LMTP_PORT = 2003 - -class LMTP(SMTP): - """LMTP - Local Mail Transfer Protocol - - The LMTP protocol, which is very similar to ESMTP, is heavily based - on the standard SMTP client. It's common to use Unix sockets for LMTP, - so our connect() method must support that as well as a regular - host:port server. To specify a Unix socket, you must use an absolute - path as the host, starting with a '/'. - - Authentication is supported, using the regular SMTP mechanism. When - using a Unix socket, LMTP generally don't support or require any - authentication, but your mileage might vary.""" - - ehlo_msg = "lhlo" - - def __init__(self, host='', port=LMTP_PORT, local_hostname=None): - """Initialize a new instance.""" - SMTP.__init__(self, host, port, local_hostname) - - def connect(self, host='localhost', port=0): - """Connect to the LMTP daemon, on either a Unix or a TCP socket.""" - if host[0] != '/': - return SMTP.connect(self, host, port) - - # Handle Unix-domain sockets. - try: - self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - self.sock.connect(host) - except socket.error: - if self.debuglevel > 0: - print>>stderr, 'connect fail:', host - if self.sock: - self.sock.close() - self.sock = None - raise - (code, msg) = self.getreply() - if self.debuglevel > 0: - print>>stderr, "connect:", msg - return (code, msg) - - -# Test the sendmail method, which tests most of the others. -# Note: This always sends to localhost. -if __name__ == '__main__': - import sys - - def prompt(prompt): - sys.stdout.write(prompt + ": ") - return sys.stdin.readline().strip() - - fromaddr = prompt("From") - toaddrs = prompt("To").split(',') - print "Enter message, end with ^D:" - msg = '' - while 1: - line = sys.stdin.readline() - if not line: - break - msg = msg + line - print "Message length is %d" % len(msg) - - server = SMTP('localhost') - server.set_debuglevel(1) - server.sendmail(fromaddr, toaddrs, msg) - server.quit() |