Problem with handling errors in POP3 message retrieval/deletion

cl at isbd.net cl at isbd.net
Fri Sep 11 18:33:32 CEST 2015


I have a (fairly) simple script that does 'catchall' processing on my
POP3 mailbox.  It looks for messages To: strings that *might* be for
me and then throws everything else away.

I was getting the occasional error as follows:-

    Traceback (most recent call last):
      File "/home/chris/.mutt/bin/getCatchall.py", line 59, in <module>
        popmsg = pop3.retr(i+1)
      File "/usr/lib/python2.7/poplib.py", line 232, in retr
        return self._longcmd('RETR %s' % which)
      File "/usr/lib/python2.7/poplib.py", line 167, in _longcmd
        return self._getlongresp()
      File "/usr/lib/python2.7/poplib.py", line 152, in _getlongresp
        line, o = self._getline()
      File "/usr/lib/python2.7/poplib.py", line 377, in _getline
        raise error_proto('line too long')
    poplib.error_proto: line too long


So I added a try/except round the pop3.retr() and now I get this error:-

    Traceback (most recent call last):
      File "/home/chris/.mutt/bin/getCatchall.py", line 63, in <module>
        x = pop3.dele(i+1)
      File "/usr/lib/python2.7/poplib.py", line 240, in dele
        return self._shortcmd('DELE %s' % which)
      File "/usr/lib/python2.7/poplib.py", line 160, in _shortcmd
        return self._getresp()
      File "/usr/lib/python2.7/poplib.py", line 136, in _getresp
        raise error_proto(resp)
    poplib.error_proto: Data Base /Diamond /Arm /Freeway /Pocket /Barbecue
    /Bathroom /Eyes /Train /Hat /Planet /Web /Girl /Surveyor /Rocket
    /Slave /Software /Vampire /Vacuum /Sun /Egg /Leg /Ice /Guitar
    /Post-office /Pepper /Hat /Eartupletters:10,50:
    AAMGQLMUHSMCCVXEOPQRDWUSFEJFSHPEAQWHh /Spiral /Garden /Tennis racquet
    /Banana /Spectrum /Bed /Fruit /Earth /Wheelchair /Spoon /Bee /Highway
    /God /Guitar /Sandpaper /Typewriter /Finger /Feather /Salt
    /Electricity /Pants /Sphere /Table /Comet / /Bee /Button /Map /Data
    Base /Hieroglyph /Carpet /Hose /Bank /Fire /Solid /Staircase /Eyes
    /Rope /School /Onion /Barbecue /Gemstone /Ice-cream /Nail /Alphabet
    /Feather /Compass /Bottle /Shop /Fruit /Map /Sphere /Coffee /Radar
    /Tongue /Tapestry /Radar /Sandwich /Circus /Spectrum /Aeroplane /Clock
    /Room /Stomach /Snail / Satellite /Worm /Money $$$$ /Bed /Pyramid /Boy
    /Pepper /Fruit /Junk /Bank /Bird /Pebble /Chair /Microscope /Satellite
    /Woman /Kaleidoscope /Perfume /Triangle /Sunglasses /Needle
    /Thermometer /Freeway /Man /Mist upletters:10,50:
    TQDPDUGSMYEPJGBPYCTEIKMNFXKCSNDY/Vulture /Thermometer /Treadmill
    /Pillow /Hose /Necklace /Coffee-shop /Space Shuttle /Pyramid /Rope
    /Surveyor /Spot Light /Nail /Bed /Mist /Sandwich /Family /Salt /Fan
    /Air /Maze /Mouth /Vacuum /Tongue /Bible /Gate /Wheelchair /Jet
    fighter /Bible /Tunnel /Navy /Festival /Shop /Tapestry /Shower
    /Cappuccino /Sandpaper /PaintBrush /Prison /Sex /Church /Man /Meat
    /Ring /Snail /Floodlight /Toilet /Shower /Computer /Tiger /Diamond
    /Bathroom /Boss /Leather jacket /Dress /Ship /Finger /Torpedo /Car
    /Compass /Water /Mist /Butterfly /Staircase /Child /Backpack /Umbrella
    /Tiger /School /Explosive /Restaurant /Bird /Cycle /Television
    /Cappuccino /Bible /Kaleidoscope /Drill /Church /Television
    /Hieroglyph /Game /Fungus /Sword /Gloves /Highway /Box functon /2022
    /browser /cowritten /livinglogic /ione /800 /susceptibles /psz


Can anyone make any suggestions as to how to overcome this issue, all
I want to do is throw away the offending message.


The code for the whole thing is as follows:-

    #!/usr/bin/python
    #
    #
    # Collect E-Mail from my catchall POP3 mailbox on tsohost, deliver anything 
    # that looks remotely useful and bin the rest
    # 
    #
    import getpass, poplib
    import email
    import mailbox
    import string
    import smtplib
    import time
    import mailLib

    home = "/home/chris"

    log = mailLib.initLog("getCatchall")
    #
    #
    # Read the filter file
    #
    fltr = {}
    f = open(home + "/.mutt/getCatchall.filter", 'r')
    for ln in f:                    # for each line in filter
        if ln[0] == '#':            # ignore comments
            continue
        #
        #
        # split the line into fields and store in a dictionary
        #
        fld = ln.split()
        fltr[fld[0]] = fld[1]
    #
    #
    # Process the messages, do a maximum of 100 at a time
    #
    while (1):
        #
        #
        # Connect to the POP3 server, get message count, exit if no messages
        #
        pop3 = poplib.POP3_SSL('pop.isbd.net')
        pop3.user('catchall at isbd.net')
        pop3.pass_('XXXXXXXX')
        numMessages = len(pop3.list()[1])
        if (numMessages == 0):
            break
        #
        #
        # Process a maximum of 100 messages
        #
        log.info(str(numMessages) + " messages")
        for i in range(min(numMessages, 100)):
            #
            #
            # Read each message into a string and then parse with the email module, if
            # there's an error retrieving the message then just throw it away
            #
            try:
                popmsg = pop3.retr(i+1)
            except:
                pop3.dele(i+1)
                continue

            log.info("Retrieved message number " + str(i+1))
            msgstr = string.join(popmsg[1], "\n")      # popmsg[1] is a list containing the lines of the message
            msg = mailbox.mboxMessage(msgstr)
            #
            #
            # Look for names from the filter file in To: and Cc:, deliver message if possibly relevant
            #
            for nm, dest in fltr.items():
                if (msg.get("To","unknown").find(nm) >= 0) or (msg.get("Cc", "unknown").find(nm) >= 0):
                    log.info( "Sending message, Subject: " + msg.get("Subject", "No subject") + ",  To: " + dest)
                    if '@' in dest:
                        try:
                            #
                            #
                            # Connect to the SMTP server and send the message
                            #
                            smtp = smtplib.SMTP('smtp.isbd.net')
                            smtp.login("catchall at isbd.net", "XXXXXXXX")
                            smtp.sendmail("catchall at isbd.net", dest, msgstr)
                            smtp.quit()
                        except:
                            #
                            #
                            # If the message can't be sent then give it to me locally
                            #
                            mailLib.deliverMboxMsg(dest, msg, log)
                    else:
                        #
                        #
                        # Put message in local mbox
                        #
                        mailLib.deliverMboxMsg(dest, msg, log)
                    break
            #
            #
            # delete the message from the POP3 mailbox
            #
            log.info("Deleting message " + msg.get("To","unknown"))
            pop3.dele(i+1)
        #
        #
        # disconnect, only when this is done do the POP3 messages actually disappear
        #
        pop3.quit()
        #
        #
        # Exit if no more messages (the normal case) otherwise wait a minute before
        # processing any more, otherwise we get zombie messages which
        # cause "poplib.error_proto: -ERR Can't open the message file - it's gone!"
        #
        if (numMessages > 100):
            time.sleep(60)
        else:
            break



-- 
Chris Green
·


More information about the Python-list mailing list