469,306 Members | 1,881 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,306 developers. It's quick & easy.

Mailbox cleaner on an IMAP basis?

Hi all!

As I saw Alex Martelli's post about a mbox cleaner based on POP3, I thought,
it could be possible to do that based on IMAP too. That way I could ask the
server for mails having attached EXE files and delete all those mails on the
server. This would save me a lot of traffic over my phone line connection.

But I'm missing one important thing: How do I get the server to tell me
about attachments.

What I've found out so far is how to get at the fields:

r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS])")

Alas, there's no such thing like 'filename' or 'attachments'.

And

r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS (Content-type)])")

doesn't show a file name either.

Any hints?

Best regards
Franz GEIGER

Jul 18 '05 #1
5 4438

"F. GEIGER" <fg*****@datec.at> wrote in message
news:3f******@news.swissonline.ch...
Hi all!

As I saw Alex Martelli's post about a mbox cleaner based on POP3, I thought, it could be possible to do that based on IMAP too. That way I could ask the server for mails having attached EXE files and delete all those mails on the server. This would save me a lot of traffic over my phone line connection.

But I'm missing one important thing: How do I get the server to tell me
about attachments.

What I've found out so far is how to get at the fields:

r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS])")

Alas, there's no such thing like 'filename' or 'attachments'.

And

r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS (Content-type)])")

doesn't show a file name either.

Any hints?
Right now, I'd simply like something that would clean out an
IMAP mailbox on a regular basis. Most of the worm generated
garbage is going into one of two boxes on my server, and I get maybe
one legitimate e-mail in those two boxes every couple of weeks.
I can stand to lose that level of e-mail, I can't stand to exceed my disk
quota and lose lots of legitimate mail every few hours.

Could you post the code you've got so far?

Thanks.

John Roth
Best regards
Franz GEIGER


Jul 18 '05 #2
Well, John,

I've stopped here, because I could not figure out how to get at the ids of
mails with attachments. And if I had that missing link, I'd run into the
next hindrance: How can I delete a single message? IMAP4::delete() deletes a
whole mailbox, not just a single mail.

So my code really is only a few lines so far:

i = IMAP4(myDomain)
i.login(myUser, myPassword)
i.select() # Select INBOX
r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS])") # Check 1st mail

Seems I have to get a book about IMAP and how to use it...

Kind regards
Franz


"John Roth" <ne********@jhrothjr.com> schrieb im Newsbeitrag
news:vm************@news.supernews.com...

"F. GEIGER" <fg*****@datec.at> wrote in message
news:3f******@news.swissonline.ch...
Hi all!

As I saw Alex Martelli's post about a mbox cleaner based on POP3, I

thought,
it could be possible to do that based on IMAP too. That way I could ask

the
server for mails having attached EXE files and delete all those mails on

the
server. This would save me a lot of traffic over my phone line connection.
But I'm missing one important thing: How do I get the server to tell me
about attachments.

What I've found out so far is how to get at the fields:

r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS])")

Alas, there's no such thing like 'filename' or 'attachments'.

And

r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS (Content-type)])")

doesn't show a file name either.

Any hints?


Right now, I'd simply like something that would clean out an
IMAP mailbox on a regular basis. Most of the worm generated
garbage is going into one of two boxes on my server, and I get maybe
one legitimate e-mail in those two boxes every couple of weeks.
I can stand to lose that level of e-mail, I can't stand to exceed my disk
quota and lose lots of legitimate mail every few hours.

Could you post the code you've got so far?

Thanks.

John Roth

Best regards
Franz GEIGER



Jul 18 '05 #3
Quoth "F. GEIGER" <fg*****@datec.at>:

| I've stopped here, because I could not figure out how to get at the ids of
| mails with attachments. And if I had that missing link, I'd run into the
| next hindrance: How can I delete a single message? IMAP4::delete() deletes a
| whole mailbox, not just a single mail.
|
| So my code really is only a few lines so far:
|
| i = IMAP4(myDomain)
| i.login(myUser, myPassword)
| i.select() # Select INBOX
| r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS])") # Check 1st mail
|
| Seems I have to get a book about IMAP and how to use it...

The IMAP4rev1 RFC of course covers these things, with examples.
2060, I think it is. A message takes two steps to delete: first,
set a \Deleted flag on it, and then invoke expunge on the folder,
which will remove all delete-flagged messages in the folder.

Donn Cave, do**@drizzle.com
Jul 18 '05 #4
> server for mails having attached EXE files and delete all those mails on the
server. This would save me a lot of traffic over my phone line connection.


I use a Python script which is run via cron every hour on
a machine with internet connectivity.

It downloads all mails, parses them and does whitelist
filtering but could be easily extentend.

All filtered mails are removed from the mailbox and
stored locally. This mbox file can then be
retrieved by scp/ftp.

Cleaning only every hour has proved to be enough.

Since my script has been running without any
trouble for almost half a year I thought it
may be a basis for ideas or customizing, so
I'll append it to this posting.

Ciao,
Dominic

P.S. You'll need the tpg-parser generator for Python.

Jul 18 '05 #5
Ok, I came up with this so far, many thanks to all who contributed!

Best regards
Franz GEIGER
import os.path, re
from imaplib import *
class Finder:
def __init__(self, text):
self._value = None
results = self._rex.findall(text)
if results:
self._value = results[0]
return

def value(self):
return self._value
class UIDfinder(Finder):

_rex = re.compile(r'UID (\d+)')
class FileNameFinder(Finder):

_rex = re.compile(r'\("application" ".+?" \("name" "(.+?)"\)')

def ft(self):
if not self._value:
return None

root, ft = os.path.splitext(self._value)
return ft
class SenderFinder(Finder):

_rex = re.compile(r'From\: (.+)\r', re.M | re.I)

class SubjectFinder(Finder):

_rex = re.compile(r'Subject\: (.+)\r', re.M | re.I)
class DateFinder(Finder):

_rex = re.compile(r'Date\: (.+)\r', re.M | re.I)
class MessageSummary:
def __init__(self, uid, fileName, text):
if not fileName:
fileName = ''

self._uid = uid
self._fileName = fileName

self._sender = ''
self._subject = ''
self._date = ''

f = SenderFinder(text)
if f.value():
self._sender = f.value()

f = SubjectFinder(text)
if f.value():
self._subject = f.value()

f = DateFinder(text)
if f.value():
self._date = f.value()

return

def __str__(self):
return self.formatted()

def formatted(self):
return "From : %s\nSubject : %s\nAttachment: %s\nFile-Name :
%s" % (self._sender, self._subject, self._date, self._fileName)

def uid(self):
return self._uid
class Deleter:
def __init__(self, server, messageSummaries):
self._server = server
self._messageSummaries = messageSummaries
self._uids = [ms.uid() for ms in self._messageSummaries]
return

def run(self):
uids = ','.join(self._uids)
r = self._server.uid("STORE", uids, "+FLAGS.SILENT", "(\Deleted)")[0]
if r in ("OK", "Ok", "ok"):
return ''
else:
return "Error - Could Not Delete Messages"
class Expunger:
def __init__(self, server):
self._server = server
return

def run(self):
self._server.expunge()
return
print "Logging in."
server = IMAP4("<myDomain>")
server.login("<myUserName>", "<myPassword>")
server.select()
print "Begin to cleanup mailbox."
messagesToDelete = []
i = 0
while (1):
i += 1

r, d = server.fetch(i, "(UID BODY)")
if r == 'NO' or d[0] is None:
break
uid = UIDfinder(d[0]).value()
fnf = FileNameFinder(d[0])
fn = fnf.value()
if not fn:
print '.',
continue

ft = fnf.ft()

r, d = server.fetch(i, "(BODY.PEEK[HEADER.FIELDS (Date From Subject)])")

ms = MessageSummary(uid, fn, d[0][1])

if ft.lower() == ".exe":
print '*',
messagesToDelete.append(ms)
else:
print '.',
if messagesToDelete:
print "\n" * 4
print "%d messages are tagged to be deleted: " % len(messagesToDelete)
for ms in messagesToDelete:
print ms.formatted()
print
print
if raw_input("Shall I delete them now (y/n)? ") == 'y':
print 'Working...'
d = Deleter(server, messagesToDelete)
d.run()
e = Expunger(server)
e.run()
print "Done. "
else:
print
print "No messages to delete. "
raw_input("Press any key to exit...")


"Donn Cave" <do**@drizzle.com> schrieb im Newsbeitrag
news:1064298380.225028@yasure...
Quoth "F. GEIGER" <fg*****@datec.at>:

| I've stopped here, because I could not figure out how to get at the ids of | mails with attachments. And if I had that missing link, I'd run into the
| next hindrance: How can I delete a single message? IMAP4::delete() deletes a | whole mailbox, not just a single mail.
|
| So my code really is only a few lines so far:
|
| i = IMAP4(myDomain)
| i.login(myUser, myPassword)
| i.select() # Select INBOX
| r, d = i.fetch(1, "(BODY.PEEK[HEADER.FIELDS])") # Check 1st mail
|
| Seems I have to get a book about IMAP and how to use it...

The IMAP4rev1 RFC of course covers these things, with examples.
2060, I think it is. A message takes two steps to delete: first,
set a \Deleted flag on it, and then invoke expunge on the folder,
which will remove all delete-flagged messages in the folder.

Donn Cave, do**@drizzle.com

Jul 18 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

9 posts views Thread by Alex Martelli | last post: by
2 posts views Thread by Lindstrom Greg - glinds | last post: by
4 posts views Thread by bill | last post: by
3 posts views Thread by WhatsPHP | last post: by
reply views Thread by jesse.k.rosenthal | last post: by
5 posts views Thread by Craig Buchanan | last post: by
1 post views Thread by CARIGAR | last post: by
1 post views Thread by Geralt96 | last post: by
reply views Thread by harlem98 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.