0

I've configured postfix on the email server with .forward file which saves a copy of email and invokes a python script. These emails are stored in Maildir format.

I want to use this Python script to send a reply to the sender acknowledging that the email has been received. I was wondering if there is any way I can open/access that e-mail, get the header info and sender address and send email back.

I looked at several examples of Maildir functions of Python, but they mostly add/delete e-mails. How can I open the latest e-mail received in Maildir/new and get the required information?

The program I have so far:

md =  mailbox.Maildir('/home/abcd/Maildir')
message = md.iterkeys().next()
#print message
#for msg in md:
#    subject = msg.get('Subject',"")
#    print subject
print message
sender = message.get('From',"")
print sender

When I execute this, I do get the sender name. But It is rather the oldest email arrived in Maildir/new folder not the latest one.

Also, if I use get_date function, what if two (or more) e-mails arrive on the same day?

Anthon
  • 69,918
  • 32
  • 186
  • 246
Papps
  • 174
  • 1
  • 19

2 Answers2

1

The MaildirMessage's method .get_date() gets you the timestamp of the message file on disc. Depending on your filesystem, this may have anywhere between two second and nanosecond accuracy. The changes of two messages giving the same value with .get_date() are vastly smaller than when this actually returned a date only.

However if the message files were touched for some reason the return from .get_date() would not be relevant at all. Dovecot e.g. explicitly states that a files mtime should not be changed.

There are several dates associated with a MaildirMessage:

  1. The arrival time timestamp, as encoded in the name of message (the part before the first dot, these are "whole" seconds). If the part between the first and second dot has a segment of the form Mn than n is the microsecond arrival time, and be used to improve the resolution of the timestamp.
  2. The timestamp of the file on disc
  3. The 'Date:' header field as set by the sending program (or added by some MTA)
  4. The dates added by intermediate MTA in the 'Received:' header field

The last of these might not be available e.g. if you and the sender are on the same mail server. The third can be easily faked/incorrect (ever got spam in your inbox dated many years ago?). And the second is incorrect if the file ever got touched.

That leaves selecting on the first option:

d = {}
for name in md.keys():
    d.setdefault(int(name.split('.', 1)[0]), []).append(name)
result = sorted(d.items())[-1][1]
assert len(result) == 1  # might fail
msg = md.get_message(result[0])

If you are lucky result is a list with a single item. But this value has only second resolution, so you might have multiple emails and then you have to decide on how to decide which message to select based on one of the other values (e.g. by sorting using the files timestamp .get_date()) or just select the first, randomly select one. (If you have the log file, you can search for the result messages' keys in there to determine which one arrived latest).

If you wouldn't convert to int, and have old emails (i.e. before 2001-09-09 03:46:40) a string comparison would probably not give you the message with the latest arrival time.

Anthon
  • 69,918
  • 32
  • 186
  • 246
0

Some hints for this:

  • You can open a Maildir with the mailbox.Maildir class (see the Documentation for mailbox)
  • You can iterate over all the mails in a Maildir via the method itervalues
  • Now you get all the mails in the Maildir. One of them is the most recent one.
  • The mails are objects of the class MaildirMessage, which is a subclass of Message. For these classes, also a documentation exists (on the same page as mailbox, currently)
  • With the method "get_date" on those objects, you can find out, which one is the most recent one. You still have to select it yourself.

So much as beginners help: A little bit you should also do by yourself.

You should make yourself familiar with the Python documentation - I agree, that it is not easy to find the right packages and how to use them, but you can try them directly in the Python shell.

Ok, here another code snippet:

newest = None
for message in md.itervalues():
   if newest == None or message.get_date() > newest.get_date():
      newest = message
# now newest should contain the newest message

Did not see your last question: get_date does not only contain the date, but also the time, because it gives the number of seconds since (normally) 1970.

Juergen
  • 12,378
  • 7
  • 39
  • 55
  • Thanks! It helped to a certain extent. Although get_date didn't work for me, I used time.mktime() to implement your logic and it worked. – Papps Feb 21 '15 at 03:09