POP - Client-side POP3

POP a python class that implements the client-side of POP3 as defined by RFC1939 (or STD53.)

Author ramblings

It all started when I decided that I wanted a POP3 client to watch my mail, unfortunately I didn't find libpop by Konrad Hinsen modified by Andy Dustman so I went ahead and reinvented the wheel.

I must thank the authors of libpop for the idea's I borrowed from them, which was the methods __delitem__, __getitem__ and __len__. The functionality was there before, but not convenient way of thinking about messages as entries in an array.

What is it

This implementation tries to be fully RFC1939 compliant, it also includes some timeouts that might speed things up when networks or something is on holiday.

Please have a look the code and tell me where my code can use improvment, or what more I need in documentation, or my spelling, or whatever.

P:son <pson@pson.pp.se>

Why should I use it

There is an implementation of POP3 (poplib) included in the distrubution, why should anyone want to use this instead of that?


Examples

In all examples I will use the user popcorn on the host mail-drop.python.net, which is not a real user, with the password mjukost (which have nothing to do with any password that i normally use, neither in content nor in style.)

List the headers of all messages

Python> from pop import POP
Python> pop = POP('mail-drop.python.net')
Python> pop.user('popcorn', 'mjukost')
Python> for id in range(1, len(pop)+1) :
Python>     print ; print id
Python>     for line in pop.top(id) :
Python>         print line
Python>     print
Python> pop.quit()

Delete all messages from spam-central.com

Python> import re
Python> from pop import POP
Python> pop = POP('mail-drop.python.net')
Python> pop.user('popcorn', 'mjukost')
Python> spam = re.compile("^From:.*spam-central.com.*")
Python> for id in range(1, len(pop)+1) :
Python>     for line in pop.top(id) :
Python>         if spam.match(line) :
Python>             del pop[id]; break
Python> pop.quit()

Delete all messages larger than 2 megabytes

Python> from pop import POP
Python> pop = POP('mail-drop.python.net')
Python> pop.user('popcorn', 'mjukost')
Python> for (id, size) in pop.list() :
Python>     if size > 2 * 1024 * 1024 :
Python>         del pop[id]
Python> pop.quit()

Methods and functions

The names of functions and methods should be written in a strong way, arguments and exceptions vill be written with emphasized text and command to the POP-server will be viewed as code.

Functions in module

timeout(sig, frame) Function sent to signal to raise Timeout exception that can be caught within the class.

kill_large(pop, the_size = 209715152, verbose = 0) Finds and deletes large messages that you don't want to haul over to you local mail-reader. The first argument is an already active POP class.

fetch_mail(host, user, password, mailfile) Connects to a mail-drop and appends all the messages to an mbox-file. This function returns a triplet with the host-name, user and password.

poll_mail(host, user, password, mailfile) This function does calls fetch_mail over and over again.

__main__ Starts poll_mail, usage: pop.py <user>@<maildrop> <password or secret phrase>.

Methods

__init__(self, HOST = '', PORT = 110, DEBUG = 0) Tries to open a connection and initializes the class, if DEBUG is set then the POP will be very verbose (on standard out.)

__del__(self) Tries to shut things down nicely.

__getitem__(self, id) Only an alias for retrieve.

__delitem__(self, id) Only an alias for delete.

__len__(self) Same as self.status()[0].

multiline(self, ALARM = 600) Returns an array of lines (without any trace of <CRLF> at the end) with the termination-octet striped from any lines that start with one, description in RFC1939, page 3.

command(self, COMMAND, ALARM = 60) Sends a command, and returns the response line.

triad(self) If a user is active returns a triple containing host, user, password (or secret)

connect(self, HOST, PORT = 110) Connects to a host

close(self, rset = 1) Shuts down any active user, and closes the socket. If rset then sends a RSET to undo any deletions.

reconnect(self) Close down the current connection, then opens a new connection to the same host. No user will be active after the call even if one was before.

user(self, NAME, PASSWORD) Activates user. It first tries with APOP using PASSWORD as the secret phrase and if that does not work it uses the commands USER and PASSWORD.

quit(self) Closes down without reseting things first, which deletes all messages that was marked for deletion.

list(self, msg = 0) Returns id and size for one message, or if msg is zero a list of all available id's and their sizes.

list_all(self) Auxilliary method used by list, guess what is does.

uidl(self, msg = 0) Returns a id and unique-id pair for one message, or if msg is zero a list of all available id's and their uid's. For a better description of uid's see RFC1939 page 12.

uidl_all(self) Auxilliary method used by uidl, guess what is does.

noop(self) Sends a NOOP.

retrive(self, msg, delete = 0) Fetches a message from the maildrop, and might mark it for deletion. Returned as an array of lines.

reset(self) Sends a RSET that undoes all marked deletions

delete(self, msg) Mark a message for deletion, messages will not be deleted until a the quit method is used.

top(self, msg, lines = 0) Get the header-lines, and the first lines of the message. Returned as an array of lines.

status(self) Get a pair that contains the number of messages not marked for deletion, and their total size.