[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Homemade email system using LuaSocket and LuaPOP3
- From: Dirk Laurie <dpl@...>
- Date: Tue, 20 Sep 2011 11:59:16 +0200
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)