LUA_FUNCTION_DEF (task, call_rspamd_function);
LUA_FUNCTION_DEF (task, get_recipients);
LUA_FUNCTION_DEF (task, get_from);
+LUA_FUNCTION_DEF (task, get_recipients_headers);
+LUA_FUNCTION_DEF (task, get_from_headers);
LUA_FUNCTION_DEF (task, get_from_ip);
LUA_FUNCTION_DEF (task, get_from_ip_num);
LUA_FUNCTION_DEF (task, get_client_ip_num);
LUA_INTERFACE_DEF (task, call_rspamd_function),
LUA_INTERFACE_DEF (task, get_recipients),
LUA_INTERFACE_DEF (task, get_from),
+ LUA_INTERFACE_DEF (task, get_recipients_headers),
+ LUA_INTERFACE_DEF (task, get_from_headers),
LUA_INTERFACE_DEF (task, get_from_ip),
LUA_INTERFACE_DEF (task, get_from_ip_num),
LUA_INTERFACE_DEF (task, get_client_ip_num),
}
+
+
+/*
+ * Push internet addresses to lua as a table
+ */
+static void
+lua_push_internet_address (lua_State *L, InternetAddressList *addrs)
+{
+ InternetAddress *ia;
+ gint idx = 1;
+
+#ifndef GMIME24
+ /* Gmime 2.2 version */
+ InternetAddressList *cur;
+
+ lua_newtable (L);
+ cur = addrs;
+ while (cur) {
+ ia = internet_address_list_get_address (cur);
+ lua_newtable (L);
+ lua_set_table_index (L, "name", internet_address_get_name (ia));
+ lua_set_table_index (L, "addr", internet_address_get_addr (ia));
+ msg_info ("name: %s, addr: %s", internet_address_get_name (ia), internet_address_get_addr (ia));
+ lua_rawseti (L, -2, idx++);
+ cur = internet_address_list_next (cur);
+ }
+#else
+ /* Gmime 2.4 version */
+ gsize len, i;
+ InternetAddressMailbox *iamb;
+
+ lua_newtable (L);
+ len = internet_address_list_length (list);
+ for (i = 0; i < len; i ++) {
+ ia = internet_address_list_get_address (list, i);
+ if (ia) {
+ lua_newtable (L);
+ iamb = INTERNET_ADDRESS_MAILBOX (ia);
+ lua_set_table_index (L, "name", internet_address_get_name (ia));
+ lua_set_table_index (L, "addr", internet_address_mailbox_get_addr (iamb));
+ lua_rawseti (L, -2, idx++);
+ }
+ }
+#endif
+}
+
static gint
lua_task_get_recipients (lua_State *L)
{
struct worker_task *task = lua_check_task (L);
- gint i = 1;
GList *cur;
+ InternetAddressList *addrs;
if (task) {
cur = task->rcpt;
if (cur != NULL) {
- lua_newtable (L);
while (cur) {
- lua_pushstring (L, (gchar *)cur->data);
- lua_rawseti (L, -2, i++);
+#ifndef GMIME24
+ addrs = internet_address_parse_string (cur->data);
+#else
+ addrs = internet_address_list_parse_string (cur->data);
+#endif
+ lua_push_internet_address (L, addrs);
+#ifndef GMIME24
+ internet_address_list_destroy (addrs);
+#else
+ g_object_unref (addrs);
+#endif
cur = g_list_next (cur);
}
return 1;
lua_task_get_from (lua_State *L)
{
struct worker_task *task = lua_check_task (L);
+ InternetAddressList *addrs;
if (task) {
if (task->from != NULL) {
- lua_pushstring (L, (gchar *)task->from);
+#ifndef GMIME24
+ addrs = internet_address_parse_string (task->from);
+#else
+ addrs = internet_address_list_parse_string (task->from);
+#endif
+ lua_push_internet_address (L, addrs);
+#ifndef GMIME24
+ internet_address_list_destroy (addrs);
+#else
+ g_object_unref (addrs);
+#endif
return 1;
}
}
return 1;
}
+/*
+ * Headers versions
+ */
+static gint
+lua_task_get_recipients_headers (lua_State *L)
+{
+ struct worker_task *task = lua_check_task (L);
+ InternetAddressList *addrs;
+
+ if (task) {
+ addrs = g_mime_message_get_all_recipients(task->message);
+ lua_push_internet_address (L, addrs);
+#ifndef GMIME24
+ internet_address_list_destroy (addrs);
+#else
+ g_object_unref (addrs);
+#endif
+ return 1;
+ }
+
+ lua_pushnil (L);
+ return 1;
+}
+
+static gint
+lua_task_get_from_headers (lua_State *L)
+{
+ struct worker_task *task = lua_check_task (L);
+ InternetAddressList *addrs;
+
+ if (task) {
+#ifndef GMIME24
+ addrs = internet_address_parse_string (g_mime_message_get_sender (task->message));
+#else
+ addrs = internet_address_list_parse_string (g_mime_message_get_sender (task->message));
+#endif
+ lua_push_internet_address (L, addrs);
+#ifndef GMIME24
+ internet_address_list_destroy (addrs);
+#else
+ g_object_unref (addrs);
+#endif
+ return 1;
+ }
+
+ lua_pushnil (L);
+ return 1;
+}
+
static gint
lua_task_get_from_ip (lua_State *L)
{
HEADER_UNKNOWN
};
-
+/*
+ * Iterate throught all headers and make a list
+ */
#ifndef GMIME24
static void
header_iterate (memory_pool_t * pool, struct gmime_raw_header *h, GList ** ret, const gchar *field, gboolean strong)
static void
header_iterate (memory_pool_t * pool, GMimeHeaderList * ls, GList ** ret, const gchar *field, gboolean strong)
{
+ /* Use iterator in case of gmime 2.4 */
GMimeHeaderIter *iter;
const gchar *name;
iter = g_mime_header_iter_new ();
if (g_mime_header_list_get_iter (ls, iter) && g_mime_header_iter_first (iter)) {
+ /* Iterate throught headers */
while (g_mime_header_iter_is_valid (iter)) {
name = g_mime_header_iter_get_name (iter);
if (G_LIKELY (!strong)) {
local res = false
if smtp_rcpt then
- local mime_rcpt = msg:get_header('To')
- local mime_cc = msg:get_header('Cc')
- local count = 0
- if mime_rcpt then
- count = table.maxn(mime_rcpt)
- end
- if mime_cc then
- count = count + table.maxn(mime_cc)
- end
- -- Check recipients count
+ local mime_rcpt = task:get_recipients_headers()
+ local count = table.maxn(mime_rcpt)
if count < table.maxn(smtp_rcpt) then
task:insert_result(symbol_rcpt, 1)
else
-- Find pair for each smtp recipient recipient in To or Cc headers
for _,sr in ipairs(smtp_rcpt) do
- if sr:sub(1,1) == '<' then
- -- Trim brackets
- sr = string.sub(sr, 2, -2)
- end
if mime_rcpt then
for _,mr in ipairs(mime_rcpt) do
- local i = string.find(mr, '<', 1, true)
- if i then
- local j = string.find(mr, '>', i, true)
- if j then
- mr = string.sub(mr, i+1, j-1)
- end
- end
-
- if string.lower(mr) == string.lower(sr) then
+ if string.lower(mr['addr']) == string.lower(sr['addr']) then
res = true
break
end
end
end
- if mime_cc then
- for _,mr in ipairs(mime_cc) do
- local i = string.find(mr, '<', 1, true)
- if i then
- local j = string.find(mr, '>', i, true)
- if j then
- mr = string.sub(mr, i+1, j-1)
- end
- end
- if string.lower(mr) == string.lower(sr) then
- res = true
- break
- end
- end
- end
-
if not res then
task:insert_result(symbol_rcpt, 1)
break
-- Check sender
local smtp_from = task:get_from()
if smtp_form then
- local mime_from = msg:get_header('From')
- local i = string.find(mime_from[0], '<', 1, true)
- if i then
- local j = string.find(mime_from[0], '>', i, true)
- if j then
- mime_from[0] = string.sub(mime_from[0], i+1, j-1)
- end
- end
- if not mime_from or not (string.lower(mime_from[0]) == string.lower(smtp_from)) then
+ local mime_from = task:get_from_headers()
+ if not mime_from or not (string.lower(mime_from[1]['addr']) == string.lower(smtp_from[1]['addr'])) then
task:insert_result(symbol_sender, 1)
end
end
local rbl_str = o4 .. '.' .. o3 .. '.' .. o2 .. '.' .. o1 .. '.' .. rule['map']
task:resolve_dns_a(rbl_str, 'multimap_rbl_cb')
end
+ elseif rule['type'] == 'rcpt' then
+ -- First try to get rcpt field
+ local rcpts = task:get_recipients()
+ if rcpts then
+ for _,r in ipairs(rcpts) do
+ if r['addr'] then
+ if rule['pattern'] then
+ -- extract a part from header
+ local _,_,ext = string.find(r['addr'], rule['pattern'])
+ if ext then
+ if rule['hash']:get_key(ext) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ else
+ if rule['hash']:get_key(r['addr']) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ end
+ end
+ else
+ -- Get from headers
+ local rcpts = task:get_recipients_headers()
+ if rcpts then
+ for _,r in ipairs(rcpts) do
+ if r['addr'] then
+ if rule['pattern'] then
+ -- extract a part from header
+ local _,_,ext = string.find(r['addr'], rule['pattern'])
+ if ext then
+ if rule['hash']:get_key(ext) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ else
+ if rule['hash']:get_key(r['addr']) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ end
+ end
+ end
+ end
+ elseif rule['type'] == 'from' then
+ -- First try to get from field
+ local from = task:get_from()
+ if from then
+ for _,r in ipairs(from) do
+ if r['addr'] then
+ if rule['pattern'] then
+ -- extract a part from header
+ local _,_,ext = string.find(r['addr'], rule['pattern'])
+ if ext then
+ if rule['hash']:get_key(ext) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ else
+ if rule['hash']:get_key(r['addr']) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ end
+ end
+ else
+ -- Get from headers
+ local from = task:get_from_headers()
+ if from then
+ for _,r in ipairs(from) do
+ if r['addr'] then
+ if rule['pattern'] then
+ -- extract a part from header
+ local _,_,ext = string.find(r['addr'], rule['pattern'])
+ if ext then
+ if rule['hash']:get_key(ext) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ else
+ if rule['hash']:get_key(r['addr']) then
+ task:insert_result(rule['symbol'], 1)
+ end
+ end
+ end
+ end
+ end
+ end
end
end
end
newrule['type'] = 'dnsbl'
elseif value == 'header' then
newrule['type'] = 'header'
+ elseif value == 'rcpt' then
+ newrule['type'] = 'rcpt'
+ elseif value == 'from' then
+ newrule['type'] = 'from'
else
rspamd_logger:err('invalid rule type: '.. value)
return nil
end
end
- if not newrule['symbol'] or not newrule['map'] or not newrule['symbol'] then
+ if not newrule['symbol'] or not newrule['map'] then
rspamd_logger:err('incomplete rule')
return nil
end
if newrule['type'] == 'ip' then
newrule['ips'] = rspamd_config:add_radix_map (newrule['map'])
- elseif newrule['type'] == 'header' then
+ elseif newrule['type'] == 'header' or newrule['type'] == 'rcpt' or newrule['type'] == 'from' then
newrule['hash'] = rspamd_config:add_hash_map (newrule['map'])
end
table.insert(rules, newrule)