diff options
Diffstat (limited to 'Lib/imaplib.py')
| -rw-r--r-- | Lib/imaplib.py | 167 |
1 files changed, 90 insertions, 77 deletions
diff --git a/Lib/imaplib.py b/Lib/imaplib.py index 129de06..8734a84 100644 --- a/Lib/imaplib.py +++ b/Lib/imaplib.py @@ -22,9 +22,9 @@ Public functions: Internaldate2tuple __version__ = "2.58" -import binascii, os, random, re, socket, sys, time +import binascii, random, re, socket, subprocess, sys, time -__all__ = ["IMAP4", "IMAP4_SSL", "IMAP4_stream", "Internaldate2tuple", +__all__ = ["IMAP4", "IMAP4_stream", "Internaldate2tuple", "Int2AP", "ParseFlags", "Time2Internaldate"] # Globals @@ -226,8 +226,7 @@ class IMAP4: """ self.host = host self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((host, port)) + self.sock = socket.create_connection((host, port)) self.file = self.sock.makefile('rb') @@ -727,7 +726,7 @@ class IMAP4: def thread(self, threading_algorithm, charset, *search_criteria): """IMAPrev1 extension THREAD command. - (type, [data]) = <instance>.thread(threading_alogrithm, charset, search_criteria, ...) + (type, [data]) = <instance>.thread(threading_algorithm, charset, search_criteria, ...) """ name = 'THREAD' typ, dat = self._simple_command(name, threading_algorithm, charset, *search_criteria) @@ -746,11 +745,13 @@ class IMAP4: if not command in Commands: raise self.error("Unknown IMAP4 UID command: %s" % command) if self.state not in Commands[command]: - raise self.error('command %s illegal in state %s' - % (command, self.state)) + raise self.error("command %s illegal in state %s, " + "only allowed in states %s" % + (command, self.state, + ', '.join(Commands[command]))) name = 'UID' typ, dat = self._simple_command(name, command, *args) - if command in ('SEARCH', 'SORT'): + if command in ('SEARCH', 'SORT', 'THREAD'): name = command else: name = 'FETCH' @@ -811,8 +812,10 @@ class IMAP4: if self.state not in Commands[name]: self.literal = None - raise self.error( - 'command %s illegal in state %s' % (name, self.state)) + raise self.error("command %s illegal in state %s, " + "only allowed in states %s" % + (name, self.state, + ', '.join(Commands[name]))) for typ in ('OK', 'NO', 'BAD'): if typ in self.untagged_responses: @@ -998,6 +1001,8 @@ class IMAP4: raise self.abort('socket error: EOF') # Protocol mandates all lines terminated by CRLF + if not line.endswith('\r\n'): + raise self.abort('socket error: unterminated line') line = line[:-2] if __debug__: @@ -1107,95 +1112,98 @@ class IMAP4: -class IMAP4_SSL(IMAP4): +try: + import ssl +except ImportError: + pass +else: + class IMAP4_SSL(IMAP4): - """IMAP4 client class over SSL connection + """IMAP4 client class over SSL connection - Instantiate with: IMAP4_SSL([host[, port[, keyfile[, certfile]]]]) + Instantiate with: IMAP4_SSL([host[, port[, keyfile[, certfile]]]]) - host - host's name (default: localhost); - port - port number (default: standard IMAP4 SSL port). - keyfile - PEM formatted file that contains your private key (default: None); - certfile - PEM formatted certificate chain file (default: None); + host - host's name (default: localhost); + port - port number (default: standard IMAP4 SSL port). + keyfile - PEM formatted file that contains your private key (default: None); + certfile - PEM formatted certificate chain file (default: None); - for more documentation see the docstring of the parent class IMAP4. - """ + for more documentation see the docstring of the parent class IMAP4. + """ - def __init__(self, host = '', port = IMAP4_SSL_PORT, keyfile = None, certfile = None): - self.keyfile = keyfile - self.certfile = certfile - IMAP4.__init__(self, host, port) + def __init__(self, host = '', port = IMAP4_SSL_PORT, keyfile = None, certfile = None): + self.keyfile = keyfile + self.certfile = certfile + IMAP4.__init__(self, host, port) - def open(self, host = '', port = IMAP4_SSL_PORT): - """Setup connection to remote server on "host:port". - (default: localhost:standard IMAP4 SSL port). - This connection will be used by the routines: - read, readline, send, shutdown. - """ - self.host = host - self.port = port - self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self.sock.connect((host, port)) - self.sslobj = socket.ssl(self.sock, self.keyfile, self.certfile) + def open(self, host = '', port = IMAP4_SSL_PORT): + """Setup connection to remote server on "host:port". + (default: localhost:standard IMAP4 SSL port). + This connection will be used by the routines: + read, readline, send, shutdown. + """ + self.host = host + self.port = port + self.sock = socket.create_connection((host, port)) + self.sslobj = ssl.wrap_socket(self.sock, self.keyfile, self.certfile) - def read(self, size): - """Read 'size' bytes from remote.""" - # sslobj.read() sometimes returns < size bytes - chunks = [] - read = 0 - while read < size: - data = self.sslobj.read(min(size-read, 16384)) - read += len(data) - chunks.append(data) + def read(self, size): + """Read 'size' bytes from remote.""" + # sslobj.read() sometimes returns < size bytes + chunks = [] + read = 0 + while read < size: + data = self.sslobj.read(min(size-read, 16384)) + read += len(data) + chunks.append(data) - return ''.join(chunks) + return ''.join(chunks) - def readline(self): - """Read line from remote.""" - # NB: socket.ssl needs a "readline" method, or perhaps a "makefile" method. - line = [] - while 1: - char = self.sslobj.read(1) - line.append(char) - if char == "\n": return ''.join(line) + def readline(self): + """Read line from remote.""" + line = [] + while 1: + char = self.sslobj.read(1) + line.append(char) + if char in ("\n", ""): return ''.join(line) - def send(self, data): - """Send data to remote.""" - # NB: socket.ssl needs a "sendall" method to match socket objects. - bytes = len(data) - while bytes > 0: - sent = self.sslobj.write(data) - if sent == bytes: - break # avoid copy - data = data[sent:] - bytes = bytes - sent + def send(self, data): + """Send data to remote.""" + bytes = len(data) + while bytes > 0: + sent = self.sslobj.write(data) + if sent == bytes: + break # avoid copy + data = data[sent:] + bytes = bytes - sent - def shutdown(self): - """Close I/O established in "open".""" - self.sock.close() + def shutdown(self): + """Close I/O established in "open".""" + self.sock.close() - def socket(self): - """Return socket instance used to connect to IMAP4 server. + def socket(self): + """Return socket instance used to connect to IMAP4 server. - socket = <instance>.socket() - """ - return self.sock + socket = <instance>.socket() + """ + return self.sock - def ssl(self): - """Return SSLObject instance used to communicate with the IMAP4 server. + def ssl(self): + """Return SSLObject instance used to communicate with the IMAP4 server. - ssl = <instance>.socket.ssl() - """ - return self.sslobj + ssl = ssl.wrap_socket(<instance>.socket) + """ + return self.sslobj + __all__.append("IMAP4_SSL") class IMAP4_stream(IMAP4): @@ -1204,7 +1212,7 @@ class IMAP4_stream(IMAP4): Instantiate with: IMAP4_stream(command) - where "command" is a string that can be passed to os.popen2() + where "command" is a string that can be passed to subprocess.Popen() for more documentation see the docstring of the parent class IMAP4. """ @@ -1224,7 +1232,11 @@ class IMAP4_stream(IMAP4): self.port = None self.sock = None self.file = None - self.writefile, self.readfile = os.popen2(self.command) + self.process = subprocess.Popen(self.command, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + shell=True, close_fds=True) + self.writefile = self.process.stdin + self.readfile = self.process.stdout def read(self, size): @@ -1247,6 +1259,7 @@ class IMAP4_stream(IMAP4): """Close I/O established in "open".""" self.readfile.close() self.writefile.close() + self.process.wait() |
