Using poplib to parse headers

J

Jean-Claude Neveu

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
 
A

alex23

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
 
G

Gerard Flanagan

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
 
T

TheSaint

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
 
T

Tim Roberts

Jean-Claude Neveu said:
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".
 
J

Jean-Claude Neveu

Tim said:
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()
 
A

asklucas

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.
 
A

asklucas

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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top