Using poplib to parse headers

Discussion in 'Python' started by Jean-Claude Neveu, May 26, 2008.

  1. Hello,

    I am writing a Python program to check email using POP3. I've tried
    the sample code from python.org, and it works great. In other words,
    the code below successfully prints out my emails.

    import getpass, poplib, email
    M = poplib.POP3('mail.blah.com')
    M.user('username')
    M.pass_('password')
    numMessages = len(M.list()[1])
    for i in range(numMessages):
    for j in M.retr(i+1)[1]:
    print j
    M.quit()

    However, if I understand right, the Python poplib library will also
    parse the email for me so that I can iterate through the headers,
    body, etc, of each message, and use them in my program. I think the
    method I need to use is email.message_from_file, but I'm having
    difficulty getting it to work. Can anyone explain me how I would
    extend the above example to do this?

    I tried to do this by using in the i loop the line:

    message = email.message_from_file(j)

    but I get the error: "AttributeError: 'str' object has no attribute 'readline'"

    Please forgive this very basic question. I do most of my programming
    in PHP and I'm just getting started with Python.

    Many thanks,

    J-C
     
    Jean-Claude Neveu, May 26, 2008
    #1
    1. Advertising

  2. Jean-Claude Neveu

    alex23 Guest

    On May 27, 8:39 am, Jean-Claude Neveu <>
    wrote:
    > I tried to do this by using in the i loop the line:
    >
    > message = email.message_from_file(j)
    >
    > but I get the error: "AttributeError: 'str' object has no attribute 'readline'"


    Heya,

    The email module has a second function - 'message_from_string' - which
    might be more useful here. Currently, you're passing to
    'message_from_file' a string that it tries to treat as a file, hence
    it complaining about the string object not having part of the file
    object interface.

    (I've never used email or poplib, so this is just a guess...)

    - alex23
     
    alex23, May 27, 2008
    #2
    1. Advertising

  3. On May 27, 12:39 am, Jean-Claude Neveu <>
    wrote:
    > Hello,
    >
    > I am writing a Python program to check email using POP3. I've tried
    > the sample code from python.org, and it works great. In other words,
    > the code below successfully prints out my emails.
    >
    > import getpass, poplib, email
    > M = poplib.POP3('mail.blah.com')
    > M.user('username')
    > M.pass_('password')
    > numMessages = len(M.list()[1])
    > for i in range(numMessages):
    > for j in M.retr(i+1)[1]:
    > print j
    > M.quit()
    >
    > However, if I understand right, the Python poplib library will also
    > parse the email for me so that I can iterate through the headers,
    > body, etc, of each message, and use them in my program. I think the
    > method I need to use is email.message_from_file, but I'm having
    > difficulty getting it to work. Can anyone explain me how I would
    > extend the above example to do this?
    >
    > I tried to do this by using in the i loop the line:
    >
    > message = email.message_from_file(j)
    >
    > but I get the error: "AttributeError: 'str' object has no attribute 'readline'"
    >
    > Please forgive this very basic question. I do most of my programming
    > in PHP and I'm just getting started with Python.
    >
    > Many thanks,
    >
    > J-C


    Here's something I wrote when I was learning Python:

    http://gflanagan.net/site/python/pagliacci/pagliacci.py.html

    HTH (if you can decipher it!)

    Gerard
     
    Gerard Flanagan, May 27, 2008
    #3
  4. Jean-Claude Neveu

    TheSaint Guest

    On 06:39, martedì 27 maggio 2008 Jean-Claude Neveu wrote:

    > However, if I understand right, the Python poplib library will also
    > parse the email for me so that I can iterate through the headers


    See my program at http://it.geocities.com/call_me_not_now/index.html
    You may study it.

    But for short you can use

    from email.Parser import HeaderParser
    # then you can parse the mail, body etc here below

    M = poplib.POP3('mail.blah.com')
    M.user('username')
    M.pass_('password')
    numMsgs = len(M.list()[1])
    for cnt in range(1, numMsgs +1):
    header= M.top(cnt,0)[1])

    HTH
     
    TheSaint, May 27, 2008
    #4
  5. Jean-Claude Neveu

    Tim Roberts Guest

    Jean-Claude Neveu <> wrote:
    >
    >I am writing a Python program to check email using POP3. I've tried
    >the sample code from python.org, and it works great. In other words,
    >the code below successfully prints out my emails.
    >
    >import getpass, poplib, email
    >M = poplib.POP3('mail.blah.com')
    >M.user('username')
    >M.pass_('password')
    >numMessages = len(M.list()[1])
    >for i in range(numMessages):
    > for j in M.retr(i+1)[1]:
    > print j
    >M.quit()
    >
    >However, if I understand right, the Python poplib library will also
    >parse the email for me so that I can iterate through the headers,
    >body, etc, of each message, and use them in my program. I think the
    >method I need to use is email.message_from_file, but I'm having
    >difficulty getting it to work. Can anyone explain me how I would
    >extend the above example to do this?
    >
    >I tried to do this by using in the i loop the line:
    >
    > message = email.message_from_file(j)
    >
    >but I get the error: "AttributeError: 'str' object has no attribute 'readline'"


    You've received some very confusing advice in this thread. Alex had the
    right answer, but I want to expand it a bit.

    You said "the Python poplib library will also parse the email for me". This
    is incorrect. poplib, like many of the modules of the Python standard
    library, focuses on exactly one purpose: handling the POP3 protocol. It
    will allow you to count your messages, and fetch your messages, but that's
    it, because that's all that POP3 does. It's a very simple protocol.

    Now, the standard library DOES include modules for parsing email, as you
    seem to realize. The "email" module is a very sophisticated tool for that
    purpose. However, the email module doesn't have any way to fech the mail.
    So, you need to stitch them together.

    poplib.retr gives you a string. You need to hand that string to the email
    module, and you do that using "email.message_from_string".
    --
    Tim Roberts,
    Providenza & Boekelheide, Inc.
     
    Tim Roberts, May 28, 2008
    #5
  6. Re: Using poplib to parse headers - Thank You All!

    Tim Roberts wrote:
    >You've received some very confusing advice in this thread. Alex had the
    >right answer, but I want to expand it a bit.
    >
    >[...]
    >
    >poplib.retr gives you a string. You need to hand that string to the email
    >module, and you do that using "email.message_from_string".


    This is just to thank Tim, Alex, and everyone who posted for their
    help in getting this to work. It's been more than a month since you
    answered my question and I've been having to focus on other things.
    Last week, I finally got back to this task and your answers helped me
    get it working.

    To save time for future people who might have the same question, I'm
    posting a basic script for reading mail from a POP server and passing
    the email message to the Python email library for parsing. I'm new to
    Python (but experienced in other languages) so please feel free to
    tell me if any of my syntax is clumsy, or if I did something the
    difficult way when Python has an easier or more efficient way to do
    it. I hope this will be useful for the archives.

    #
    import getpass, poplib, email

    # Set up the connection to the POP server
    popconnection = poplib.POP3('mail.blah.com')
    popconnection.user('user-name-goes-here')
    popconnection.pass_('password-goes-here')

    # Find out how many messages are waiting
    numMessages = len(popconnection.list()[1])

    # Iterate through the messages
    for i in range(numMessages):

    # retr will be called three times for each email message in the j loop below.
    #
    # The first call will return a string telling you how many bytes (i.e., octets)
    # are in the message. The string will look like this: OK <byte count> octets
    # (where <byte count> is the total number of bytes in the message).
    #
    # The second call will return a list containing the elements of the message.
    #
    # The third call will return an integer containing the total number of
    # bytes in the message

    for j in popconnection.retr(i+1):

    # We are interested only in the contents of the list. And we need to put the
    # list contents into a string, because that is what
    message_from_string expects.
    # We must also be sure to put a line break at the end of the substring that
    # represents each list element, as message_from_string relies on line breaks
    # to parse the email message. The k loop below builds the string from the list.
    if type(j) == list:
    numElements = len(j)
    outString = ""
    for k in range(numElements):
    outString += j[k]
    outString += '\n'
    message = email.message_from_string(outString)

    # Now that we have got the contents of the email into an email object, we can
    # access the logical elements of the email at will, in any order. The call to
    # get_payload() is to retrieve the body of the message.
    print message['Subject']
    print message['From']
    print message.get_payload()

    # Strictly speaking, all we need to do on quitting is to disconnect,
    but in some
    # applications it would be a good idea to delete the email from the server.
    popconnection.quit()
     
    Jean-Claude Neveu, Jul 7, 2008
    #6
  7. Jean-Claude Neveu

    Guest

    Re: Using poplib to parse headers - Thank You All!

    Hello Jean-Claude!

    Thank you for your post, it helped me a lot!
    I'm not too new to Python but still struggling to make use of that great language's features.

    I haven't tested it but since you are interested in syntactic subtleties, I think you can save one iterator (k):

    for j in popconnection.retr( i+1):
    ____if type( j) == list:
    ________outString = ""
    ________for line in j:
    ____________outString += line
    ____________outString += '\n'

    L.
     
    , Dec 10, 2012
    #7
  8. Jean-Claude Neveu

    Guest

    Re: Using poplib to parse headers - Thank You All!

    Hello Jean-Claude!

    Thank you for your post, it helped me a lot!
    I'm not too new to Python but still struggling to make use of that great language's features.

    I haven't tested it but since you are interested in syntactic subtleties, I think you can save one iterator (k):

    for j in popconnection.retr( i+1):
    ____if type( j) == list:
    ________outString = ""
    ________for line in j:
    ____________outString += line
    ____________outString += '\n'

    L.
     
    , Dec 10, 2012
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Simon Burton

    spam killing with poplib

    Simon Burton, Sep 20, 2003, in forum: Python
    Replies:
    7
    Views:
    377
    Donn Cave
    Sep 21, 2003
  2. Rybread
    Replies:
    1
    Views:
    321
    Alex Martelli
    Sep 22, 2003
  3. Elbert Lev

    poplib for multihomed machines

    Elbert Lev, Jun 28, 2004, in forum: Python
    Replies:
    8
    Views:
    365
    Jorgen Grahn
    Jul 3, 2004
  4. Replies:
    2
    Views:
    1,131
    Mike Meyer
    Jun 22, 2005
  5. SteveC
    Replies:
    2
    Views:
    449
    SteveC
    Jul 30, 2008
Loading...

Share This Page