Browse Source

Merge pull request #3464 from citrin/maillist

MAILLIST rule fixes
pull/3468/head
Vsevolod Stakhov 5 years ago
committed by GitHub
parent
commit
8aa776cb4e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 157
      src/plugins/lua/maillist.lua

157
src/plugins/lua/maillist.lua

@ -63,104 +63,100 @@ local function check_ml_ezmlm(task)
return true
end
-- MailMan (the gnu mailing list manager)
-- Precedence: bulk [or list for v2]
-- List-Help: <mailto:
-- List-Post: <mailto:
-- List-Subscribe: .*<mailto:.*=subscribe>
-- List-Unsubscribe: .*<mailto:.*=unsubscribe>
-- List-Archive:
-- X-Mailman-Version: \d
-- RFC 2919 headers exist
-- GNU Mailman
-- Two major versions currently in use and they use slightly different headers
-- Mailman2: https://code.launchpad.net/~mailman-coders/mailman/2.1
-- Mailman3: https://gitlab.com/mailman/mailman
local function check_ml_mailman(task)
-- Mailing-List
local header = task:get_header('x-mailman-version')
if not header or not string.find(header, '^%d') then
local header = task:get_header('X-Mailman-Version')
if not header then
return false
end
-- Precedence
header = task:get_header('precedence')
if not header or (header ~= 'bulk' and header ~= 'list') then
local mm_version = header:match('^([23])%.')
if not mm_version then
lua_util.debugm(N, task, 'unknown Mailman version: %s', header)
return false
end
-- For reminders we have other headers than for normal messages
header = task:get_header('x-list-administrivia')
local subject = task:get_header('subject')
if (header and string.find(header, 'yes')) or
(subject and string.find(subject, 'mailing list memberships reminder$')) then
if not task:get_header('errors-to') or not task:get_header('x-beenthere') then
return false
end
header = task:get_header('x-no-archive')
if not header or not string.find(header, 'yes') then
return false
end
return true
end
lua_util.debugm(N, task, 'checking Mailman %s headers', mm_version)
-- Other headers
header = task:get_header('list-post')
if not header or not string.find(header, '^<mailto:') then
-- XXX Some messages may not contain Precedence, but they are rare:
-- http://bazaar.launchpad.net/~mailman-coders/mailman/2.1/revision/1339
header = task:get_header('Precedence')
if not header or (header ~= 'bulk' and header ~= 'list') then
return false
end
header = task:get_header('list-help')
if not header or not string.find(header, '^<mailto:') then
-- Mailmain 3 allows to disable all List-* headers in settings, but by default it adds them.
-- In all other cases all Mailman message should have List-Id header
if not task:has_header('List-Id') then
return false
end
-- Subscribe and unsubscribe
header = task:get_header('list-subscribe')
if not header or not string.find(header, '<mailto:.*=subscribe>') then
return false
if mm_version == '2' then
-- X-BeenThere present in all Mailman2 messages
if not task:has_header('X-BeenThere') then
return false
end
-- X-List-Administrivia: is only added to messages Mailman creates and
-- sends out of its own accord
header = task:get_header('X-List-Administrivia')
if header and header == 'yes' then
-- not much elase we can check, Subjects can be changed in settings
return true
end
else -- Mailman 3
-- XXX not Mailman3 admin messages have this headers, but one
-- which don't usually have List-* headers examined below
if task:has_header('List-Administrivia') then
return true
end
end
header = task:get_header('list-unsubscribe')
if not header or not string.find(header, '<mailto:.*=unsubscribe>') then
return false
-- List-Archive and List-Post are optional, check other headers
for _, h in ipairs({'List-Help', 'List-Subscribe', 'List-Unsubscribe'}) do
header = task:get_header(h)
if not (header and header:find('<mailto:', 1, true)) then
return false
end
end
return true
end
-- Subscribe.ru
-- Precedence: normal
-- List-Id: <.*.subscribe.ru>
-- List-Help: <http://subscribe.ru/catalog/.*>
-- List-Subscribe: <mailto:.*-sub@subscribe.ru>
-- List-Unsubscribe: <mailto:.*-unsub@subscribe.ru>
-- List-Archive: <http://subscribe.ru/archive/.*>
-- List-Owner: <mailto:.*-owner@subscribe.ru>
-- List-Id: <*.subscribe.ru>
-- List-Help: <https://subscribe.ru/catalog/*>
-- List-Subscribe: <mailto:*-sub@subscribe.ru>
-- List-Unsubscribe: <mailto:*-unsub@subscribe.ru>
-- List-Archive: <https://subscribe.ru/archive/*>
-- List-Owner: <mailto:*@subscribe.ru>
-- List-Post: NO
local function check_ml_subscriberu(task)
-- List-Id
local header = task:get_header('list-id')
if not header or not string.find(header, '^<.*%.subscribe%.ru>$') then
return false
end
-- Precedence
header = task:get_header('precedence')
if not header or not string.match(header, '^normal$') then
if not (header and header:find('^<.*%.subscribe%.ru>$')) then
return false
end
-- Other headers
header = task:get_header('list-archive')
if not header or not string.find(header, '^<http://subscribe.ru/archive/.*>$') then
if not (header and header:find('^<https?://subscribe%.ru/archive/.+>$')) then
return false
end
header = task:get_header('list-owner')
if not header or not string.find(header, '^<mailto:.*-owner@subscribe.ru>$') then
if not (header and header:find('^<mailto:.+@subscribe%.ru>$')) then
return false
end
header = task:get_header('list-help')
if not header or not string.find(header, '^<http://subscribe.ru/catalog/.*>$') then
if not (header and header:find('^<https?://subscribe%.ru/catalog/.+>$')) then
return false
end
-- Subscribe and unsubscribe
header = task:get_header('list-subscribe')
if not header or not string.find(header, '^<mailto:.*-sub@subscribe.ru>$') then
if not (header and header:find('^<mailto:.+-sub@subscribe%.ru>$')) then
return false
end
header = task:get_header('list-unsubscribe')
if not header or not string.find(header, '^<mailto:.*-unsub@subscribe.ru>$') then
if not (header and header:find('^<mailto:.+-unsub@subscribe%.ru>$')) then
return false
end
@ -205,53 +201,52 @@ local function check_generic_list_headers(task)
local score = 0
local has_subscribe, has_unsubscribe
if task:get_header_count('list-id') then
lua_util.debugm(N, task, 'has header List-Id, score = %s', score)
if task:has_header('List-Id') then
score = score + 0.75
lua_util.debugm(N, task, 'has List-Id header, score = %s', score)
end
local header = task:get_header('Precedence')
if header and (header == 'list' or header == 'bulk') then
lua_util.debugm(N, task, 'has header Precedence: %s, score = %s',
header, score)
score = score + 0.25
lua_util.debugm(N, task, 'has header "Precedence: %s", score = %s',
header, score)
end
if task:get_header_count('list-archive') == 1 then
if task:has_header('List-Archive') then
score = score + 0.125
lua_util.debugm(N, task, 'has header List-Archive, score = %s',
score)
score = score + 0.125
end
if task:get_header_count('list-owner') == 1 then
if task:has_header('List-Owner') then
score = score + 0.125
lua_util.debugm(N, task, 'has header List-Owner, score = %s',
score)
score = score + 0.125
end
if task:get_header_count('list-help') == 1 then
if task:has_header('List-Help') then
score = score + 0.125
lua_util.debugm(N, task, 'has header List-Help, score = %s',
score)
score = score + 0.125
end
-- Subscribe and unsubscribe
if task:get_header_count('list-subscribe') == 1 then
if task:has_header('List-Subscribe') then
has_subscribe = true
score = score + 0.125
lua_util.debugm(N, task, 'has header List-Subscribe, score = %s',
score)
score = score + 0.125
has_subscribe = true
end
if task:get_header_count('list-unsubscribe') == 1 then
if task:has_header('List-Unsubscribe') then
has_unsubscribe = true
score = score + 0.125
lua_util.debugm(N, task, 'has header List-Unsubscribe, score = %s',
score)
score = score + 0.125
has_unsubscribe = true
end
if task:get_header_count('x-loop') == 1 then
lua_util.debugm(N, task, 'has header x-loop, score = %s',
score)
if task:has_header('X-Loop') then
score = score + 0.125
lua_util.debugm(N, task, 'has header X-Loop, score = %s',
score)
end
if has_subscribe and has_unsubscribe then
@ -270,7 +265,7 @@ end
-- RFC 2919 headers exist
local function check_maillist(task)
local score = check_generic_list_headers(task)
if score > 1 then
if score >= 1 then
if check_ml_ezmlm(task) then
task:insert_result(symbol, 1, 'ezmlm')
elseif check_ml_mailman(task) then

Loading…
Cancel
Save