lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On Mon, Sep 19, 2011 at 08:03:58PM +0200, Petite Abeille wrote:
> 
> On Sep 19, 2011, at 12:33 AM, Sean Conner wrote:
> 
> > I create three files per email, the body, and two for headers. 
> 
> How do you deal with multipart? Are they all bunches together in ,B?
> 
> 
That's easy to implement if you have already have a parser that gives 
a table `headers` and a string `body`, e.g. the one in stdlib which
is basically the same as the one on LuaWiki.  See attachment. 

If the message is multipart, then `headers['content-type']` looks like this:

    multipart/mixed; boundary="_8b46a2bf-7207-48f7-b891-529cc7393c5c_"

That boundary, preceded "--", occurs on the lines that separate
the message into parts.

After that, it's recursive.

`lua5.1 mboxdemo.lua test.mbox` gives this output:

    This mailbox has 1 message
    message 1 has 5 parts
    part 1 has 2 parts
        1: length=965,  text/plain; charset="iso-8859-1"
        2: length=2800,  text/html; charset="iso-8859-1"
      2: length=551688,  application/pdf
      3: length=960,  text/plain
      4: length=143868,  application/msword
      5: length=18325,  image/pjpeg

Sorry, unlike the code, test.mbox contains copyrighted material.

For a reason that I still have to find, `lua5.2 mboxdemo.lua test.mbox`
does not work.

Dirk

local Public = {}
local strfind, strlower, gsub = string.find, string.lower, string.gsub
local strsub, tinsert = string.sub, table.insert

function Public.headers(headers_s)
    local headers = {}
    headers_s = "\n" .. headers_s .. "$$$:\n"
    local i, j = 1, 1
    local name, value, _
    while 1 do
        j = strfind(headers_s, "\n%S-:", i+1)
        if not j then break end
        _, _, name, value = strfind(strsub(headers_s, i+1, j-1), "(%S-):(.*)")
        value = gsub(value or "", "\r\n", "\n")
        value = gsub(value, "\n%s*", " ")
        name = strlower(name)
        if headers[name] then headers[name] = headers[name] .. ", " ..  value
        else headers[name] = value end
        i, j = j, i
    end
    headers["$$$"] = nil
    return headers
end

function Public.body(body,cont)
    if cont==nil then return body end
    local boundary = cont:match('multipart.*boundary=(%b"")')
    if not boundary then return body end
    boundary = boundary:sub(2,-2)
    local k,l=0,0
    local b={}
    repeat 
	local l1 = l+1
	k,l=body:find(boundary,l1,true) 
        if not l then break end
	local next = Public.message(body:sub(l1,k-1))
	if next.body~="" then b[#b+1] = next end
	until false
    return b
    end

function Public.message(message_s)
    message_s = gsub(message_s, "^.-\n", "")
    local _, headers_s, body
    _, _, headers_s, body = strfind(message_s, "^(.-\n)\n(.*)")
    local headers = Public.headers(headers_s or "")
    body = Public.body(body or "",headers['content-type'])
    return { headers = headers, body = body }
end

function Public.mbox(mbox_s)
    local mbox = {}
    mbox_s = "\n" .. mbox_s .. "\nFrom "
    local i, j = 1, 1
    while 1 do
        j = strfind(mbox_s, "\nFrom ", i + 1)
        if not j then break end
        tinsert(mbox, Public.message(strsub(mbox_s, i + 1, j - 1)))
        i, j = j, i
    end
    return mbox
end

return Public
IMF = require "mboxparser"

mboxname = assert(arg[1]) 
mboxfile = assert(io.open(mboxname))
mbox = assert(IMF.mbox(mboxfile:read("*a")))

local label = function(j)
    return ({'mailbox','message','part'})[math.min(j,3)]
    end

local indent = function(j)
    local id=''
    for i=1,j do id=id..'  ' end
    return id
    end

local plural = function(n) if n==1 then return "" else return "s" end end

function messageprint(message,tag,n)
    if #message>0 then
	if n then print	(("%s %i has %i %s"..plural(#message)):format(
	    label(tag),n,#message,label(tag+1)))
	else print (("This %s has %i %s"..plural(#message)):format(
	    label(tag),#message,label(tag+1)))    
	    end
	for j=1,#message do 
	    messageprint(message[j],tag,j)
	    end
	return
	end
    local body = message.body
    if type(body)=='string' then 
	    print(("%s%i: length=%i, %s"):format(
	    indent(tag-1),n,#body,message.headers['content-type'])) 
    else messageprint(body,tag+1,n) 
	end
    end    
    
messageprint(mbox,1)