Mail Box Parsing

lua-users home
wiki

Below is a simple library to parse mailbox files, as usually found in Unix systems. The code has been tested on Lua 5.0, 5.1 and 5.2(beta).

Parsing Mail box files

Say you save the source code in the current directory (or elsewhere in your PackagePath) as mboxparser.lua. In your code, put:

parse = require "mboxparser" 

The main function, parse.mbox, receives the mailbox file contents as a string and returns a table with one entry per message. Each entry has the following structure:

message = {
    headers = {
        [["name_1"]] = "value_1",
        [["name_2"]] = "value_2",
        ...           ...
        [["name_n"]] = "value_n",
    },
    body = "message body"
}
	

Therefore, if a mailbox has the following contents:

From  whoever@tecgraf.puc-rio.br  Thu Nov 22 13:59:05 2001
Date: Thu, 22 Nov 2001 13:59:04 -0200 (EDT)
From: Whoever Smith <whoever@tecgraf.puc-rio.br>
To: Other Smith <other@tecgraf.puc-rio.br>
Subject: This is a test message
Content-Type: TEXT/PLAIN; charset=US-ASCII

Hi, This is the message body.  Regards, Diego.
	

Calling parse.mbox on it would return the following table:

messages = {
  { 
    headers = {
      from = "Whoever Smith <whoever@tecgraf.puc-rio.br>", 
      subject = "This is a test message", 
      to = "Other Smith <other@tecgraf.puc-rio.br>", 
      date = "Thu, 22 Nov 2001 13:59:04 -0200 (EDT)", 
      ["content-type"] = "TEXT/PLAIN; charset=US-ASCII", 
    }, 
    body = "Hi, This is the message body.  Regards, Diego.",
  }
}
	

Source Code

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.message(message_s)
    message_s = gsub(message_s, "^.-\n", "")
    local _, headers_s, body
    _, _, headers_s, body = strfind(message_s, "^(.-\n)\n(.*)")
    headers_s = headers_s or ""
    body = body or ""
    return { headers = Public.headers(headers_s), 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
	

Credits

The original Lua 4 code was created by DiegoNehab, and is used to test the LuaSocket[1] 1.4 SMTP code. The Lua 5 version was made by DirkLaurie.


RecentChanges · preferences
edit · history
Last edited August 5, 2011 11:01 am GMT (diff)