# IMAPFilter Base64 UTF-8 match_field -rw-r--r-- 1.6 KiB View raw
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
-- This requires the base64 module from https://github.com/iskolbin/lbase64
-- Other base64 modules had issues working from within IMAPFilter

local methods = {}

-- Decode a field value that might be base64 encoded utf-8 (like Gmail returns)
function methods.decode_utf8_field(value, field_name)
  if value then
    local field_prefix = ''
    if field_name then
      field_prefix = ('%s: '):format(field_name)
    end
    local return_value = ''
    local value_start = value:sub(1 + field_prefix:len(), 8 + field_prefix:len())
    if value_start == '=?UTF-8?' or value_start == '=?utf-8?' then
      value = value:sub(field_prefix:len(), value:len())
      for part in string.gmatch(value, ' ?=[?][Uu][Tt][Ff][-]8[?]([BbQq][?].-)[?]=') do
        local part_type = part:sub(1, 1)
        local part_value = part:sub(3)
        if (part_type == 'B' or part_type == 'b') then
          part_value = base64.decode(part_value)
        end
        return_value = return_value .. part_value
      end
    else
      return_value = value:sub(field_prefix:len(), value:len())
    end
    return return_value
  end
end

-- Return messages that match `pattern` in the `field` header field.
-- Unlike the standard `match_field`, this one works with base64 encoded UTF-8 fields
function methods.match_utf8_field(messages, field, pattern)
  local results = {}
  for m, message in ipairs(messages) do
    local mailbox, uid = table.unpack(message)
    value = mailbox[uid]:fetch_field(field)
    value = methods.decode_utf8_field(value, field)
    if (value:match(pattern)) then
      table.insert(results, { mailbox, uid })
    end
  end
  return Set(results)
end

return methods