How to save a email message?

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sat Jul 2 09:08:35 EDT 2011


TheSaint wrote:

> Hello,
> I'm trying to gather some mail and save it. I don't get why it isn't saved
> as expected.

Short answer: you need to seek the fp file object back to the start of the
file by calling fp.seek(0). Otherwise, when you add it to the mail box, if
gets EOF immediately and nothing gets added.

More comments below:


> ==========================================================================
> 
>>>> import poplib, socket, sys
>>>> from configparser import Error as ProtocolError
>>>> args= sys.argv[1:] # this is fake but is here as example


It makes it very hard for us to run your code when you paste the interactive
session. For small snippets, it's okay to just post the interactive
session, but for more substantial code, it is best to past the function
definition ready for us to copy and paste:

def foo():
    pass

>>> foo("arg")
>>>



>>>> def Pop3_access(*args):
>>>>    '''Accessing a pop server, doing a function and return a result'''
>>>>    func= args[0]; args= args[1:]

Why don't you declare func as a named argument? 

def Pop3_access(func, *args):


>>>>    try:
>>>>       pop= poplib.POP3(srv_info[0])
>>>>       pop.user(srv_info[1])
>>>>       pop.pass_(srv_info[2])
>>>>    except (poplib.error_proto):
>>>>       raise ProtocolError
>>>>    except (socket.timeout,socket.gaierror):
>>>>       try: pop.quit()
>>>>       except NameError: pass # it wasn't started
>>>>       return
>>>>    result= func(pop, args)
>>>>    pop.quit()
>>>>    return result
> 
>>>> def func(pop, N):
> ...    return pop.retr(N)
> ...
>>>> msg= Pop3_access(func, 4)
>>>> from io import BytesIO as B
>>>> fp= B()
>>>> for l in msg[1]:
> ...    fp.write(l)
> ...    fp.write('\n'.encode())
> ...
> 34
> 1
> 50
> 1
[...]


For those wondering, as I was, what all these numbers are, the
BytesIO.write() method returns the number of bytes written. 

At this point, fp is a file-like object containing a number of bytes, but
the file pointer is at the end of the file, so when you read from it, it
immediately gets EOF (i.e. empty). 

>>> from io import BytesIO as B
>>> x = B()
>>> x.write(bytes("hello", 'ascii'))
5
>>> x.read()
b''

But if you seek back to the beginning:

>>> x.seek(0)
0
>>> x.read()
b'hello'



>>>> from mailbox import mbox as Mbx

*raises eyebrow*

Do you need to rename mbox? You don't even save a keypress:
shift-m b x and m b o x both take 4 keypresses.


-- 
Steven




More information about the Python-list mailing list