123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- --[[
- Copyright (c) 2011-2016, Vsevolod Stakhov <vsevolod@highsecure.ru>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- ]]--
-
- -- Rules to detect forwarding
-
- local rspamd_util = require "rspamd_util"
-
- rspamd_config.FWD_GOOGLE = {
- callback = function (task)
- if not (task:has_from(1) and task:has_recipients(1)) then
- return false
- end
- local envfrom = task:get_from(1)
- local envrcpts = task:get_recipients(1)
- -- Forwarding will only be to a single recipient
- if #envrcpts > 1 then return false end
- -- Get recipient and compute VERP address
- local rcpt = envrcpts[1].addr:lower()
- local verp = rcpt:gsub('@','=')
- -- Get the user portion of the envfrom
- local ef_user = envfrom[1].user:lower()
- -- Check for a match
- if ef_user:find('+caf_=' .. verp, 1, true) then
- local _,_,user = ef_user:find('^(.+)+caf_=')
- if user then
- user = user .. '@' .. envfrom[1].domain
- return true, user
- end
- end
- return false
- end,
- score = 0.0,
- description = "Message was forwarded by Google",
- group = "forwarding"
- }
-
- rspamd_config.FWD_YANDEX = {
- callback = function (task)
- if not (task:has_from(1) and task:has_recipients(1)) then
- return false
- end
- local hostname = task:get_hostname()
- if hostname and hostname:lower():find('%.yandex%.[a-z]+$') then
- if task:get_header_raw('X-Yandex-Forward') then
- return true
- end
- end
- return false
- end,
- score = 0.0,
- description = "Message was forwarded by Yandex",
- group = "forwarding"
- }
-
- rspamd_config.FWD_MAILRU = {
- callback = function (task)
- if not (task:has_from(1) and task:has_recipients(1)) then
- return false
- end
- local hostname = task:get_hostname()
- if hostname and hostname:lower():find('%.mail%.ru$') then
- if task:get_header_raw('X-MailRu-Forward') then
- return true
- end
- end
- return false
- end,
- score = 0.0,
- description = "Message was forwarded by Mail.ru",
- group = "forwarding"
- }
-
- rspamd_config.FWD_SRS = {
- callback = function (task)
- if not (task:has_from(1) and task:has_recipients(1)) then
- return false
- end
- local envfrom = task:get_from(1)
- local envrcpts = task:get_recipients(1)
- -- Forwarding is only to a single recipient
- if #envrcpts > 1 then return false end
- -- Get recipient and compute rewritten SRS address
- local srs = '=' .. envrcpts[1].domain:lower() ..
- '=' .. envrcpts[1].user:lower()
- if envfrom[1].user:lower():find('^srs[01]=') and
- envfrom[1].user:lower():find(srs, 1, false)
- then
- return true
- end
- return false
- end,
- score = 0.0,
- description = "Message was forwarded using Sender Rewriting Scheme (SRS)",
- group = "forwarding"
- }
-
- rspamd_config.FORWARDED = {
- callback = function (task)
- local function normalize_addr(addr)
- addr = string.match(addr, '^<?([^>]*)>?$') or addr
- local cap, _,domain = string.match(addr, '^([^%+][^%+]*)(%+[^@]*)@(.*)$')
- if cap then
- addr = string.format('%s@%s', cap, domain)
- end
-
- return addr
- end
-
- if not task:has_recipients(1) then return false end
- local envrcpts = task:get_recipients(1)
- -- Forwarding will only be for single recipient messages
- if #envrcpts > 1 then return false end
- -- Get any other headers we might need
- local lu = task:get_header('List-Unsubscribe')
- local to = task:get_recipients(2)
- local matches = 0
- -- Retrieve and loop through all Received headers
- local rcvds = task:get_received_headers()
-
- if rcvds then
- for _, rcvd in ipairs(rcvds) do
- local addr = rcvd['for']
- if addr then
- addr = normalize_addr(addr)
- matches = matches + 1
- -- Check that it doesn't match the envrcpt
- if not rspamd_util.strequal_caseless(addr, envrcpts[1].addr) then
- -- Check for mailing-lists as they will have the same signature
- if matches < 2 and lu and to and rspamd_util.strequal_caseless(to[1].addr, addr) then
- return false
- else
- return true, 1.0, addr
- end
- end
- -- Prevent any other iterations as we only want
- -- process the first matching Received header
- return false
- end
- end
- end
- return false
- end,
- score = 0.0,
- description = "Message was forwarded",
- group = "forwarding"
- }
|