imapfilter makes it almost easy
Filed under: lua imapfilterDespite my issues with Lua, I managed to hack together a little Lua script for automatically filtering the multitude of mailing lists I have.
I was inspired by David Reid's script but needed a bit more since his script only deals with the List-Id header, which I found inadequate in dealing with the tons of mailing lists I subscribe to.
By automatic filtering, I mean I don't create a rule for each list, rather the script inspects the email headers and uses bits of information there to create folders and move the mail there without any intervention.
This was more painful than it needed to be since not all mailing lists carry the same headers, and even headers that might be useful (List-Id) often aren't, due to the vagaries in various mailing list software and how people configure that software.
Anyway, the script is below. Enjoy or don't. If you improve it or find bugs, please let me know here.
config.lua:
imap_acct = {
server = 'mail.yourserver.com',
username = 'username',
password = 'password',
}
function parseListId ( header )
header = header:lower ( )
header, n = header:gsub ( '[<>]', ' ' )
baseheader, n = header:gsub('.*x[-]beenthere:%s*([^%s\r\n]*).*', '%1')
if n == 0 then
baseheader, n = header:gsub('.*list[-]post:%s*([^%s\r\n;]*).*', '%1')
end
if n == 0 then
baseheader, n = header:gsub('.*list[-]id:%s*([^%s\r\n]*).*', '%1')
end
baseheader, _ = baseheader:gsub ( 'mailto:(.*)', '%1' )
if n > 0 then
parts = baseheader:find ( '@' )
if not parts then
parts = baseheader:find ( '[.]', 1 )
end
parent = baseheader:sub ( parts + 1, nil )
parent, n = parent:gsub ( '(.*[.])(.*)([.].*)', '%2' )
if n == 0 then
parent = parent:gsub ( '(.*)([.].*)', '%1' )
end
child = baseheader:sub ( 1, parts -1 )
-- now, if the parent's name exists in the child, delete that from the child
child, n = child:gsub ( parent .. '[-]', '' )
end
return parent, child
end
mailinglist = {
invert = true,
'header "X-BeenThere" ""',
'header "List-Post" ""',
'header "List-Id" ""',
}
results = match ( imap_acct, 'INBOX', mailinglist )
listids = fetchfields ( imap_acct, 'INBOX',
{ 'X-BeenThere', 'List-Post', 'List-Id' }, results ) or { }
mailboxes = { }
for message, header in pairs ( listids ) do
parent, child = parseListId ( header )
if parent and child then
mailbox = parent .. '.' .. child
if not mailboxes [ mailbox ] then
mailboxes [ mailbox ] = { }
end
table.insert ( mailboxes [ mailbox ], message )
end
end
for mailbox, messages in pairs ( mailboxes ) do
-- print ( mailbox )
move ( imap_acct, 'INBOX', imap_acct, 'Lists.' .. mailbox, messages )
end






