#include <mempool_vars_internal.h>
#include "config.h"
#include "libserver/url.h"
+#include "lua/lua_common.h"
#include "libserver/cfg_file.h"
#include "mime_string.hxx"
#include "smtp_parsers.h"
{
std::ptrdiff_t date_pos = -1;
- static constexpr const auto protos_map = frozen::make_unordered_map<frozen::string, int>({
- {"smtp", RSPAMD_RECEIVED_SMTP},
- {"esmtp", RSPAMD_RECEIVED_ESMTP},
- {"esmtpa", RSPAMD_RECEIVED_ESMTPA | RSPAMD_RECEIVED_FLAG_AUTHENTICATED},
- {"esmtpsa", RSPAMD_RECEIVED_ESMTPSA | RSPAMD_RECEIVED_FLAG_SSL | RSPAMD_RECEIVED_FLAG_AUTHENTICATED},
- {"esmtps", RSPAMD_RECEIVED_ESMTPS | RSPAMD_RECEIVED_FLAG_SSL},
- {"lmtp", RSPAMD_RECEIVED_LMTP},
- {"imap", RSPAMD_RECEIVED_IMAP},
- {"imaps", RSPAMD_RECEIVED_IMAP | RSPAMD_RECEIVED_FLAG_SSL},
- {"http", RSPAMD_RECEIVED_HTTP},
- {"https", RSPAMD_RECEIVED_HTTP | RSPAMD_RECEIVED_FLAG_SSL},
- {"local", RSPAMD_RECEIVED_LOCAL}
+ static constexpr const auto protos_map = frozen::make_unordered_map<frozen::string, received_flags>({
+ {"smtp", received_flags::SMTP},
+ {"esmtp", received_flags::ESMTP},
+ {"esmtpa", received_flags::ESMTPA |
+ received_flags::AUTHENTICATED},
+ {"esmtpsa", received_flags::ESMTPSA |
+ received_flags::SSL |
+ received_flags::AUTHENTICATED},
+ {"esmtps", received_flags::ESMTPS |
+ received_flags::SSL},
+ {"lmtp", received_flags::LMTP},
+ {"imap", received_flags::IMAP},
+ {"imaps", received_flags::IMAP |
+ received_flags::SSL},
+ {"http", received_flags::HTTP},
+ {"https", received_flags::HTTP |
+ received_flags::SSL},
+ {"local", received_flags::LOCAL}
});
auto parts = received_spill(task, in, date_pos);
auto &rh = recv_chain_ptr->new_received();
- rh.flags = RSPAMD_RECEIVED_UNKNOWN;
+ rh.flags = received_flags::UNKNOWN;
rh.hdr = hdr;
for (const auto &part : parts) {
" not ours, prepend it with fake one");
auto trecv = recv_chain_ptr->new_received(received_header_chain::append_type::append_head);
- trecv.flags |= RSPAMD_RECEIVED_FLAG_ARTIFICIAL;
+ trecv.flags |= received_flags::ARTIFICIAL;
if (task->flags & RSPAMD_TASK_FLAG_SSL) {
- trecv.flags |= RSPAMD_RECEIVED_FLAG_SSL;
+ trecv.flags |= received_flags::SSL;
}
if (task->user) {
- trecv.flags |= RSPAMD_RECEIVED_FLAG_AUTHENTICATED;
+ trecv.flags |= received_flags::AUTHENTICATED;
}
trecv.real_ip.assign_copy(std::string_view(rspamd_inet_address_to_string(task->from_addr)));
return false;
}
+static auto
+received_export_to_lua(received_header_chain *chain, lua_State *L) -> bool
+{
+ if (chain == nullptr) {
+ return false;
+ }
+
+ lua_createtable(L, chain->size(), 0);
+
+ auto push_flag = [L](const received_header &rh, received_flags fl, const char *name) {
+ lua_pushboolean(L, !!(rh.flags & fl));
+ lua_setfield(L, -2, name);
+ };
+
+ auto i = 1;
+
+ for (const auto &rh : chain->as_vector()) {
+ lua_createtable (L, 0, 10);
+
+ if (rh.hdr && rh.hdr->decoded) {
+ rspamd_lua_table_set(L, "raw", rh.hdr->decoded);
+ }
+
+ lua_createtable(L, 0, 3);
+ push_flag(rh, received_flags::ARTIFICIAL, "artificial");
+ push_flag(rh, received_flags::AUTHENTICATED, "authenticated");
+ push_flag(rh, received_flags::SSL, "ssl");
+ lua_setfield(L, -2, "flags");
+
+ lua_pushlstring(L, rh.from_hostname.data(), rh.from_hostname.size());
+ lua_setfield(L, -2, "from_hostname");
+ lua_pushlstring(L, rh.real_hostname.data(), rh.real_hostname.size());
+ lua_setfield(L, -2, "real_hostname");
+ lua_pushlstring(L, rh.from_ip.data(), rh.from_ip.size());
+ lua_setfield(L, -2, "from_ip");
+ lua_pushlstring(L, rh.by_hostname.data(), rh.by_hostname.size());
+ lua_setfield(L, -2, "by_hostname");
+ lua_pushlstring(L, rh.for_mbox.data(), rh.for_mbox.size());
+ lua_setfield(L, -2, "for");
+
+ rspamd_lua_ip_push (L, rh.addr);
+ lua_setfield(L, -2, "real_ip");
+
+ const auto *proto = "unknown";
+
+ switch (received_type_apply_maks(rh.flags)) {
+ case received_flags::SMTP:
+ proto = "smtp";
+ break;
+ case received_flags::ESMTP:
+ proto = "esmtp";
+ break;
+ case received_flags::ESMTPS:
+ proto = "esmtps";
+ break;
+ case received_flags::ESMTPA:
+ proto = "esmtpa";
+ break;
+ case received_flags::ESMTPSA:
+ proto = "esmtpsa";
+ break;
+ case received_flags::LMTP:
+ proto = "lmtp";
+ break;
+ case received_flags::IMAP:
+ proto = "imap";
+ break;
+ case received_flags::HTTP:
+ proto = "http";
+ break;
+ case received_flags::LOCAL:
+ proto = "local";
+ break;
+ case received_flags::MAPI:
+ proto = "mapi";
+ break;
+ default:
+ proto = "unknown";
+ break;
+ }
+
+ lua_pushstring(L, proto);
+ lua_setfield(L, -2, "proto");
+
+ lua_pushinteger(L, rh.timestamp);
+ lua_setfield(L, -2, "timestamp");
+
+ lua_rawseti(L, -2, i++);
+ }
+
+ return true;
+}
+
} // namespace rspamd::mime
bool
{
return rspamd::mime::received_maybe_fix_task(task);
}
+
+bool
+rspamd_received_export_to_lua(struct rspamd_task *task, lua_State *L)
+{
+ return rspamd::mime::received_export_to_lua(
+ static_cast<rspamd::mime::received_header_chain *>(MESSAGE_FIELD(task, received_headers)),
+ L);
+}
\ No newline at end of file
* C bindings for C++ received code
*/
-enum rspamd_received_type {
- RSPAMD_RECEIVED_SMTP = 1u << 0u,
- RSPAMD_RECEIVED_ESMTP = 1u << 1u,
- RSPAMD_RECEIVED_ESMTPA = 1u << 2u,
- RSPAMD_RECEIVED_ESMTPS = 1u << 3u,
- RSPAMD_RECEIVED_ESMTPSA = 1u << 4u,
- RSPAMD_RECEIVED_LMTP = 1u << 5u,
- RSPAMD_RECEIVED_IMAP = 1u << 6u,
- RSPAMD_RECEIVED_LOCAL = 1u << 7u,
- RSPAMD_RECEIVED_HTTP = 1u << 8u,
- RSPAMD_RECEIVED_MAPI = 1u << 9u,
- RSPAMD_RECEIVED_UNKNOWN = 1u << 10u,
- RSPAMD_RECEIVED_FLAG_ARTIFICIAL = (1u << 11u),
- RSPAMD_RECEIVED_FLAG_SSL = (1u << 12u),
- RSPAMD_RECEIVED_FLAG_AUTHENTICATED = (1u << 13u),
-};
-
-#define RSPAMD_RECEIVED_FLAG_TYPE_MASK (RSPAMD_RECEIVED_SMTP| \
- RSPAMD_RECEIVED_ESMTP| \
- RSPAMD_RECEIVED_ESMTPA| \
- RSPAMD_RECEIVED_ESMTPS| \
- RSPAMD_RECEIVED_ESMTPSA| \
- RSPAMD_RECEIVED_LMTP| \
- RSPAMD_RECEIVED_IMAP| \
- RSPAMD_RECEIVED_LOCAL| \
- RSPAMD_RECEIVED_HTTP| \
- RSPAMD_RECEIVED_MAPI| \
- RSPAMD_RECEIVED_UNKNOWN)
-
struct rspamd_email_address;
struct rspamd_received_header_chain;
struct rspamd_mime_header;
*/
bool rspamd_received_maybe_fix_task(struct rspamd_task *task);
+struct lua_State;
+/**
+ * Push received headers chain to lua
+ * @param task
+ * @param L
+ * @return
+ */
+bool rspamd_received_export_to_lua(struct rspamd_task *task, struct lua_State *L);
+
#ifdef __cplusplus
}
#endif
return 0;
}
+enum class received_flags {
+ DEFAULT = 0,
+ SMTP = 1u << 0u,
+ ESMTP = 1u << 1u,
+ ESMTPA = 1u << 2u,
+ ESMTPS = 1u << 3u,
+ ESMTPSA = 1u << 4u,
+ LMTP = 1u << 5u,
+ IMAP = 1u << 6u,
+ LOCAL = 1u << 7u,
+ HTTP = 1u << 8u,
+ MAPI = 1u << 9u,
+ UNKNOWN = 1u << 10u,
+ ARTIFICIAL = (1u << 11u),
+ SSL = (1u << 12u),
+ AUTHENTICATED = (1u << 13u),
+};
+
+#define RSPAMD_RECEIVED_FLAG_TYPE_MASK (received_flags::SMTP| \
+ RSPAMD_RECEIVED_ESMTP| \
+ RSPAMD_RECEIVED_ESMTPA| \
+ RSPAMD_RECEIVED_ESMTPS| \
+ RSPAMD_RECEIVED_ESMTPSA| \
+ RSPAMD_RECEIVED_LMTP| \
+ RSPAMD_RECEIVED_IMAP| \
+ RSPAMD_RECEIVED_LOCAL| \
+ RSPAMD_RECEIVED_HTTP| \
+ RSPAMD_RECEIVED_MAPI| \
+ RSPAMD_RECEIVED_UNKNOWN)
+
+constexpr received_flags operator |(received_flags lhs, received_flags rhs)
+{
+ using ut = std::underlying_type<received_flags>::type;
+ return static_cast<received_flags>(static_cast<ut>(lhs) | static_cast<ut>(rhs));
+}
+
+constexpr received_flags operator |=(received_flags &lhs, const received_flags rhs)
+{
+ using ut = std::underlying_type<received_flags>::type;
+ lhs = static_cast<received_flags>(static_cast<ut>(lhs) | static_cast<ut>(rhs));
+ return lhs;
+}
+
+constexpr received_flags operator &(received_flags lhs, received_flags rhs)
+{
+ using ut = std::underlying_type<received_flags>::type;
+ return static_cast<received_flags>(static_cast<ut>(lhs) & static_cast<ut>(rhs));
+}
+
+constexpr bool operator !(received_flags fl)
+{
+ return fl == received_flags::DEFAULT;
+}
+
+constexpr received_flags received_type_apply_maks(received_flags fl) {
+ return fl & (received_flags::SMTP|
+ received_flags::ESMTP|
+ received_flags::ESMTPA|
+ received_flags::ESMTPS|
+ received_flags::ESMTPSA|
+ received_flags::IMAP|
+ received_flags::HTTP|
+ received_flags::LOCAL|
+ received_flags::MAPI|
+ received_flags::LMTP);
+}
+
struct received_header {
mime_string from_hostname;
std::string_view from_ip;
rspamd_inet_addr_t *addr = nullptr;
struct rspamd_mime_header *hdr = nullptr;
time_t timestamp = 0;
- int flags = 0; /* See enum rspamd_received_type */
+ received_flags flags = received_flags::DEFAULT; /* See enum rspamd_received_type */
received_header() noexcept
: from_hostname(received_char_filter),
return std::nullopt;
}
+ constexpr auto size() const -> std::size_t {
+ return headers.size();
+ }
+ constexpr auto as_vector() const -> const std::vector<received_header>& {
+ return headers;
+ }
private:
static auto received_header_chain_pool_dtor(void *ptr) -> void {
delete static_cast<received_header_chain *>(ptr);
#include "libserver/maps/map_helpers.h"
#include <math.h>
+#include "libmime/received.h"
/***
* @module rspamd_task
{
LUA_TRACE_POINT;
struct rspamd_task *task = lua_check_task (L, 1);
- struct rspamd_received_header *rh;
- const gchar *proto;
- guint k = 1;
if (task) {
if (!task->message) {
}
if (!lua_task_get_cached (L, task, "received")) {
- lua_createtable (L, 0, 0);
-
- DL_FOREACH (MESSAGE_FIELD (task, received), rh) {
- lua_createtable (L, 0, 10);
-
- if (rh->hdr && rh->hdr->decoded) {
- rspamd_lua_table_set (L, "raw", rh->hdr->decoded);
- }
-
- lua_pushstring (L, "flags");
- lua_createtable (L, 0, 3);
-
- lua_pushstring (L, "artificial");
- if (rh->flags & RSPAMD_RECEIVED_FLAG_ARTIFICIAL) {
- lua_pushboolean (L, true);
- }
- else {
- lua_pushboolean (L, false);
- }
- lua_settable (L, -3);
-
- lua_pushstring (L, "authenticated");
- if (rh->flags & RSPAMD_RECEIVED_FLAG_AUTHENTICATED) {
- lua_pushboolean (L, true);
- }
- else {
- lua_pushboolean (L, false);
- }
- lua_settable (L, -3);
-
- lua_pushstring (L, "ssl");
- if (rh->flags & RSPAMD_RECEIVED_FLAG_SSL) {
- lua_pushboolean (L, true);
- }
- else {
- lua_pushboolean (L, false);
- }
- lua_settable (L, -3);
-
- lua_settable (L, -3);
-
- if (G_UNLIKELY (rh->from_ip == NULL &&
- rh->real_ip == NULL &&
- rh->real_hostname == NULL &&
- rh->by_hostname == NULL && rh->timestamp == 0 &&
- rh->for_mbox == NULL)) {
- lua_rawseti (L, -2, k ++);
- continue;
- }
-
- rspamd_lua_table_set (L, "from_hostname", rh->from_hostname);
- rspamd_lua_table_set (L, "from_ip", rh->from_ip);
- rspamd_lua_table_set (L, "real_hostname", rh->real_hostname);
- lua_pushstring (L, "real_ip");
- rspamd_lua_ip_push (L, rh->addr);
- lua_settable (L, -3);
- lua_pushstring (L, "proto");
-
- switch (rh->flags & RSPAMD_RECEIVED_FLAG_TYPE_MASK) {
- case RSPAMD_RECEIVED_SMTP:
- proto = "smtp";
- break;
- case RSPAMD_RECEIVED_ESMTP:
- proto = "esmtp";
- break;
- case RSPAMD_RECEIVED_ESMTPS:
- proto = "esmtps";
- break;
- case RSPAMD_RECEIVED_ESMTPA:
- proto = "esmtpa";
- break;
- case RSPAMD_RECEIVED_ESMTPSA:
- proto = "esmtpsa";
- break;
- case RSPAMD_RECEIVED_LMTP:
- proto = "lmtp";
- break;
- case RSPAMD_RECEIVED_IMAP:
- proto = "imap";
- break;
- case RSPAMD_RECEIVED_HTTP:
- proto = "http";
- break;
- case RSPAMD_RECEIVED_LOCAL:
- proto = "local";
- break;
- case RSPAMD_RECEIVED_MAPI:
- proto = "mapi";
- break;
- case RSPAMD_RECEIVED_UNKNOWN:
- default:
- proto = "unknown";
- break;
- }
-
- lua_pushstring (L, proto);
- lua_settable (L, -3);
-
- lua_pushstring (L, "timestamp");
- lua_pushinteger (L, rh->timestamp);
- lua_settable (L, -3);
-
- rspamd_lua_table_set (L, "by_hostname", rh->by_hostname);
- rspamd_lua_table_set (L, "for", rh->for_mbox);
- lua_rawseti (L, -2, k ++);
+ if (rspamd_received_export_to_lua(task, L)) {
+ lua_task_set_cached (L, task, "received", -1);
+ }
+ else {
+ /* no received, preserve compatibility */
+ lua_newtable (L);
+ return 1;
}
-
- lua_task_set_cached (L, task, "received", -1);
}
}
else {