diff options
Diffstat (limited to 'modules/smtplib.py')
| -rw-r--r-- | modules/smtplib.py | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/modules/smtplib.py b/modules/smtplib.py new file mode 100644 index 000000000..db6e3e254 --- /dev/null +++ b/modules/smtplib.py @@ -0,0 +1,104 @@ +# A quick hack. Talk to the SMTP port. +# Right now this isn't very functional. +# A lot of functionality was borrowed directly from ftplib... +# John Viega (viega@list.org) + +# >>> from smtplib import * +# >>> s = SmtpConnection('list.org') +# >>> s.helo('adder.cs.virginia.edu') +# >>> s.send(to='viega@list.org', frm='jtv2j@cs.virginia.edu', text='hello, world!') +# >>> s.quit() + +from socket import * +import string + +SMTP_PORT = 25 + +CRLF = '\r\n' + +# Exception raised when an error or invalid response is received +error_reply = 'smtplib.error_reply' # unexpected [123]xx reply +error_temp = 'smtplib.error_temp' # 4xx errors +error_perm = 'smtplib.error_perm' # 5xx errors +error_proto = 'smtplib.error_proto' # response does not begin with [1-5] + +class SmtpConnection: + def __init__(self, host=''): + self.host = host + self._file = None + self.connect() + + def connect(self): + self._sock = socket(AF_INET, SOCK_STREAM) + self._sock.connect(self.host, SMTP_PORT) + self._file = self._sock.makefile('r') + self.getresp() + + def helo(self, host): + self._sock.send('HELO %s\r\n' % host) + self.getresp() + + def quit(self): + self._sock.send('QUIT\r\n') + self.getresp() + + # text should be \n at eol, we'll add the \r. + def send(self, to, frm, text, headers=None): + if headers: + hlines = string.split(headers, '\n') + lines = string.split(text, '\n') + self._sock.send('MAIL FROM: %s\r\n' % frm) + self.getresp() + self._sock.send('RCPT TO: %s\r\n' % to) + self.getresp() + self._sock.send('DATA\r\n') + self.getresp() + if headers: + for line in hlines: + self._sock.send(line + '\r\n') + self._sock.send('\r\n') + for line in lines: + if line == '.': line = '..' + self._sock.send(line + '\r\n') + self._sock.send('.\r\n') + self.getresp() + +# Private crap from here down. + def getline(self): + line = self._file.readline() + if not line: raise EOFError + if line[-2:] == CRLF: line = line[:-2] + elif line[-1:] in CRLF: line = line[:-1] + return line + + # Internal: get a response from the server, which may possibly + # consist of multiple lines. Return a single string with no + # trailing CRLF. If the response consists of multiple lines, + # these are separated by '\n' characters in the string + def getmultiline(self): + line = self.getline() + if line[3:4] == '-': + code = line[:3] + while 1: + nextline = self.getline() + line = line + ('\n' + nextline) + if nextline[:3] == code and \ + nextline[3:4] <> '-': + break + return line + + def getresp(self): + resp = self.getmultiline() + self.lastresp = resp[:3] + c = resp[:1] + if c == '4': + raise error_temp, resp + if c == '5': + raise error_perm, resp + if c not in '123': + raise error_proto, resp + return resp + + + + |
