spamassassin: installation and configuration of the spamd service and spamass-milter. Support user preferences in postgreSQL.
This commit is contained in:
parent
0aba51911c
commit
c78b5f4fdc
13
README.md
13
README.md
|
@ -1,3 +1,14 @@
|
||||||
# ansible-role-spamassassin
|
# ansible-role-spamassassin
|
||||||
|
|
||||||
Install and configures spamassassin, https://spamassassin.apache.org
|
Installs and configures spamassassin, <https://spamassassin.apache.org>
|
||||||
|
|
||||||
|
* We actually support PostgreSQL as remote backend
|
||||||
|
* The sql present in the `files` directory is valid on spamassassin 3.4
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
* Clean the txrep stale data regulary, running the following query (PostgreSQL)
|
||||||
|
|
||||||
|
``` sql
|
||||||
|
DELETE FROM txrep WHERE last_hit <= (now() - INTERVAL '120 day');
|
||||||
|
```
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
---
|
||||||
|
spamassassin_install: True
|
||||||
|
spamassassin_spamd_enabled: True
|
||||||
|
spamassassin_sql_backend: False
|
||||||
|
spamassassin_required_hits: 5
|
||||||
|
spamassassin_report_safe: 0
|
||||||
|
spamassassin_rewrite_subject: "[SPAM]"
|
||||||
|
spamassassin_user: spamassassin
|
||||||
|
spamassassin_group: '{{ spamassassin_user }}'
|
||||||
|
spamassassin_home: /etc/mail/spamassassin
|
||||||
|
|
||||||
|
spamassassin_rh_packages:
|
||||||
|
- spamassassin
|
||||||
|
- spamassassin-iXhash2
|
||||||
|
|
||||||
|
spamassassin_sql_rh_packages:
|
||||||
|
- perl-DBD-Pg
|
||||||
|
- perl-DBI
|
||||||
|
|
||||||
|
spamassassin_spamd_port: 783
|
||||||
|
spamassassin_conf_dir: '/etc/mail/spamassassin'
|
||||||
|
spamassassin_sysconfig_file: '/etc/sysconfig/spamassassin'
|
||||||
|
# Only postgresql support for the time being
|
||||||
|
spamassassin_db_user_config: True
|
||||||
|
spamassassin_spamd_sql_opts: '-q -x '
|
||||||
|
spamassassin_db_name: 'spamassassin'
|
||||||
|
spamassassin_db_user: 'spamassassin_u'
|
||||||
|
# spamassassin_db_pwd: 'use a vault file'
|
||||||
|
spamassassin_db_host: 'localhost'
|
||||||
|
spamassassin_db_external_host: '{{ spamassassin_db_host }}'
|
||||||
|
spamassassin_db_port: 5432
|
||||||
|
spamassassin_db_sql_file: 'spamassassin-pg-3.4.sql'
|
||||||
|
spamassassin_db_allowed_hosts:
|
||||||
|
- '127.0.0.1'
|
||||||
|
- '{{ ansible_fqdn }}'
|
||||||
|
|
||||||
|
spamassassin_use_bayes: False
|
||||||
|
spamassassin_bayes_sql_db: '{{ spamassassin_db_user_config }}'
|
||||||
|
spamassassin_use_bayes_autolearn: '0'
|
||||||
|
spamassassin_use_bayes_auto_expire: '1'
|
||||||
|
spamassassin_auto_whitelist: False
|
||||||
|
spamassassin_auto_whitelist_sql_db: '{{ spamassassin_db_user_config }}'
|
||||||
|
|
||||||
|
spamassassin_spamd_ssl_enabled: True
|
||||||
|
spamassassin_spamd_ssl_opts: '-u {{ spamassassin_user }} -g {{ spamassassin_group }} --ssl --server-key {{ spamassassin_home }}/client-key.pem --server-cert {{ spamassassin_home }}/client-cert.pem'
|
||||||
|
|
||||||
|
psql_db_data:
|
||||||
|
- { name: '{{ spamassassin_db_name }}', encoding: 'UTF8', user: '{{ spamassassin_db_user }}', roles: 'NOCREATEDB,NOSUPERUSER', pwd: '{{ spamassassin_db_pwd }}', managedb: True, allowed_hosts: '{{ spamassassin_db_allowed_hosts }}', extensions: [ '' ], schema_file: '/srv/spamassassin.sql' }
|
||||||
|
|
||||||
|
## Spamassassin milter settings
|
||||||
|
spamassassin_milter_install: False
|
||||||
|
spamassassin_rh_milter_packages:
|
||||||
|
- spamass-milter
|
||||||
|
- spamass-milter-postfix
|
||||||
|
|
||||||
|
spamassassin_milter_set_pref_dom_and_user: False
|
||||||
|
spamassassin_milter_pref_default_domain: 'localhost'
|
||||||
|
spamassassin_milter_pref_default_user: 'root'
|
||||||
|
spamassassin_milter_reject_code: '5.7.1'
|
||||||
|
spamassassin_milter_reject_message: 'Blocked by SpamAssassin'
|
||||||
|
spamassassin_milter_connect_to_external_spamd: False
|
||||||
|
spamassassin_milter_external_spamd_host: '127.0.0.1'
|
||||||
|
spamassassin_milter_external_spamd_port: '{{ spamassassin_spamd_port }}'
|
||||||
|
spamassassin_milter_exclude_whitelisted_networks: False
|
||||||
|
# Separate with commas
|
||||||
|
spamassassin_milter_whitelisted_networks: '127.0.0.1/8'
|
||||||
|
spamassassin_milter_reject_limit: 15
|
||||||
|
spamassassin_milter_change_headers: True
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
CREATE TABLE awl (
|
||||||
|
username varchar(100) NOT NULL default '',
|
||||||
|
email varchar(255) NOT NULL default '',
|
||||||
|
ip varchar(40) NOT NULL default '',
|
||||||
|
msgcount bigint NOT NULL default '0',
|
||||||
|
totscore float NOT NULL default '0',
|
||||||
|
signedby varchar(255) NOT NULL default '',
|
||||||
|
last_hit timestamp NOT NULL default CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (username,email,signedby,ip)
|
||||||
|
);
|
||||||
|
|
||||||
|
create index awl_last_hit on awl (last_hit);
|
||||||
|
|
||||||
|
create OR REPLACE function update_awl_last_hit()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.last_hit = CURRENT_TIMESTAMP;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ language 'plpgsql';
|
||||||
|
|
||||||
|
create TRIGGER update_awl_update_last_hit BEFORE UPDATE
|
||||||
|
ON awl FOR EACH ROW EXECUTE PROCEDURE
|
||||||
|
update_awl_last_hit();
|
||||||
|
|
||||||
|
ALTER TABLE awl SET (fillfactor=95);
|
|
@ -0,0 +1,119 @@
|
||||||
|
|
||||||
|
CREATE TABLE bayes_expire (
|
||||||
|
id integer NOT NULL default '0',
|
||||||
|
runtime integer NOT NULL default '0'
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE INDEX bayes_expire_idx1 ON bayes_expire (id);
|
||||||
|
|
||||||
|
CREATE TABLE bayes_global_vars (
|
||||||
|
variable varchar(30) NOT NULL default '',
|
||||||
|
value varchar(200) NOT NULL default '',
|
||||||
|
PRIMARY KEY (variable)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
INSERT INTO bayes_global_vars VALUES ('VERSION','3');
|
||||||
|
|
||||||
|
CREATE TABLE bayes_seen (
|
||||||
|
id integer NOT NULL default '0',
|
||||||
|
msgid varchar(200) NOT NULL default '',
|
||||||
|
flag character(1) NOT NULL default '',
|
||||||
|
PRIMARY KEY (id,msgid)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE TABLE bayes_token (
|
||||||
|
id integer NOT NULL default '0',
|
||||||
|
token bytea NOT NULL default '',
|
||||||
|
spam_count integer NOT NULL default '0',
|
||||||
|
ham_count integer NOT NULL default '0',
|
||||||
|
atime integer NOT NULL default '0',
|
||||||
|
PRIMARY KEY (id,token)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE INDEX bayes_token_idx1 ON bayes_token (token);
|
||||||
|
|
||||||
|
ALTER TABLE bayes_token SET (fillfactor=95);
|
||||||
|
|
||||||
|
CREATE TABLE bayes_vars (
|
||||||
|
id serial NOT NULL,
|
||||||
|
username varchar(200) NOT NULL default '',
|
||||||
|
spam_count integer NOT NULL default '0',
|
||||||
|
ham_count integer NOT NULL default '0',
|
||||||
|
token_count integer NOT NULL default '0',
|
||||||
|
last_expire integer NOT NULL default '0',
|
||||||
|
last_atime_delta integer NOT NULL default '0',
|
||||||
|
last_expire_reduce integer NOT NULL default '0',
|
||||||
|
oldest_token_age integer NOT NULL default '2147483647',
|
||||||
|
newest_token_age integer NOT NULL default '0',
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX bayes_vars_idx1 ON bayes_vars (username);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION greatest_int (integer, integer)
|
||||||
|
RETURNS INTEGER
|
||||||
|
IMMUTABLE STRICT
|
||||||
|
AS 'SELECT CASE WHEN $1 < $2 THEN $2 ELSE $1 END;'
|
||||||
|
LANGUAGE SQL;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION least_int (integer, integer)
|
||||||
|
RETURNS INTEGER
|
||||||
|
IMMUTABLE STRICT
|
||||||
|
AS 'SELECT CASE WHEN $1 < $2 THEN $1 ELSE $2 END;'
|
||||||
|
LANGUAGE SQL;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION put_tokens(INTEGER,
|
||||||
|
BYTEA[],
|
||||||
|
INTEGER,
|
||||||
|
INTEGER,
|
||||||
|
INTEGER)
|
||||||
|
RETURNS VOID AS '
|
||||||
|
DECLARE
|
||||||
|
inuserid ALIAS FOR $1;
|
||||||
|
intokenary ALIAS FOR $2;
|
||||||
|
inspam_count ALIAS FOR $3;
|
||||||
|
inham_count ALIAS FOR $4;
|
||||||
|
inatime ALIAS FOR $5;
|
||||||
|
_token BYTEA;
|
||||||
|
new_tokens INTEGER := 0;
|
||||||
|
BEGIN
|
||||||
|
for i in array_lower(intokenary, 1) .. array_upper(intokenary, 1)
|
||||||
|
LOOP
|
||||||
|
_token := intokenary[i];
|
||||||
|
UPDATE bayes_token
|
||||||
|
SET spam_count = greatest_int(spam_count + inspam_count, 0),
|
||||||
|
ham_count = greatest_int(ham_count + inham_count, 0),
|
||||||
|
atime = greatest_int(atime, inatime)
|
||||||
|
WHERE id = inuserid
|
||||||
|
AND token = _token;
|
||||||
|
IF NOT FOUND THEN
|
||||||
|
-- we do not insert negative counts, just return true
|
||||||
|
IF NOT (inspam_count < 0 OR inham_count < 0) THEN
|
||||||
|
INSERT INTO bayes_token (id, token, spam_count, ham_count, atime)
|
||||||
|
VALUES (inuserid, _token, inspam_count, inham_count, inatime);
|
||||||
|
IF FOUND THEN
|
||||||
|
new_tokens := new_tokens + 1;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
IF new_tokens > 0 AND inatime > 0 THEN
|
||||||
|
UPDATE bayes_vars
|
||||||
|
SET token_count = token_count + new_tokens,
|
||||||
|
newest_token_age = greatest_int(newest_token_age, inatime),
|
||||||
|
oldest_token_age = least_int(oldest_token_age, inatime)
|
||||||
|
WHERE id = inuserid;
|
||||||
|
ELSIF new_tokens > 0 AND NOT inatime > 0 THEN
|
||||||
|
UPDATE bayes_vars
|
||||||
|
SET token_count = token_count + new_tokens
|
||||||
|
WHERE id = inuserid;
|
||||||
|
ELSIF NOT new_tokens > 0 AND inatime > 0 THEN
|
||||||
|
UPDATE bayes_vars
|
||||||
|
SET newest_token_age = greatest_int(newest_token_age, inatime),
|
||||||
|
oldest_token_age = least_int(oldest_token_age, inatime)
|
||||||
|
WHERE id = inuserid;
|
||||||
|
END IF;
|
||||||
|
RETURN;
|
||||||
|
END;
|
||||||
|
' LANGUAGE 'plpgsql';
|
|
@ -0,0 +1,179 @@
|
||||||
|
CREATE TABLE userpref (
|
||||||
|
prefid bigserial NOT NULL unique primary key,
|
||||||
|
username varchar(100) NOT NULL,
|
||||||
|
preference varchar(50) NOT NULL,
|
||||||
|
value varchar(100) NOT NULL
|
||||||
|
);
|
||||||
|
CREATE INDEX userpref_username_idx ON userpref(username);
|
||||||
|
CREATE TABLE awl (
|
||||||
|
username varchar(100) NOT NULL default '',
|
||||||
|
email varchar(255) NOT NULL default '',
|
||||||
|
ip varchar(40) NOT NULL default '',
|
||||||
|
msgcount bigint NOT NULL default '0',
|
||||||
|
totscore float NOT NULL default '0',
|
||||||
|
signedby varchar(255) NOT NULL default '',
|
||||||
|
last_hit timestamp NOT NULL default CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (username,email,signedby,ip)
|
||||||
|
);
|
||||||
|
|
||||||
|
create index awl_last_hit on awl (last_hit);
|
||||||
|
|
||||||
|
create OR REPLACE function update_awl_last_hit()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.last_hit = CURRENT_TIMESTAMP;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ language 'plpgsql';
|
||||||
|
|
||||||
|
create TRIGGER update_awl_update_last_hit BEFORE UPDATE
|
||||||
|
ON awl FOR EACH ROW EXECUTE PROCEDURE
|
||||||
|
update_awl_last_hit();
|
||||||
|
|
||||||
|
ALTER TABLE awl SET (fillfactor=95);
|
||||||
|
|
||||||
|
CREATE TABLE bayes_expire (
|
||||||
|
id integer NOT NULL default '0',
|
||||||
|
runtime integer NOT NULL default '0'
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE INDEX bayes_expire_idx1 ON bayes_expire (id);
|
||||||
|
|
||||||
|
CREATE TABLE bayes_global_vars (
|
||||||
|
variable varchar(30) NOT NULL default '',
|
||||||
|
value varchar(200) NOT NULL default '',
|
||||||
|
PRIMARY KEY (variable)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
INSERT INTO bayes_global_vars VALUES ('VERSION','3');
|
||||||
|
|
||||||
|
CREATE TABLE bayes_seen (
|
||||||
|
id integer NOT NULL default '0',
|
||||||
|
msgid varchar(200) NOT NULL default '',
|
||||||
|
flag character(1) NOT NULL default '',
|
||||||
|
PRIMARY KEY (id,msgid)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE TABLE bayes_token (
|
||||||
|
id integer NOT NULL default '0',
|
||||||
|
token bytea NOT NULL default '',
|
||||||
|
spam_count integer NOT NULL default '0',
|
||||||
|
ham_count integer NOT NULL default '0',
|
||||||
|
atime integer NOT NULL default '0',
|
||||||
|
PRIMARY KEY (id,token)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE INDEX bayes_token_idx1 ON bayes_token (token);
|
||||||
|
|
||||||
|
ALTER TABLE bayes_token SET (fillfactor=95);
|
||||||
|
|
||||||
|
CREATE TABLE bayes_vars (
|
||||||
|
id serial NOT NULL,
|
||||||
|
username varchar(200) NOT NULL default '',
|
||||||
|
spam_count integer NOT NULL default '0',
|
||||||
|
ham_count integer NOT NULL default '0',
|
||||||
|
token_count integer NOT NULL default '0',
|
||||||
|
last_expire integer NOT NULL default '0',
|
||||||
|
last_atime_delta integer NOT NULL default '0',
|
||||||
|
last_expire_reduce integer NOT NULL default '0',
|
||||||
|
oldest_token_age integer NOT NULL default '2147483647',
|
||||||
|
newest_token_age integer NOT NULL default '0',
|
||||||
|
PRIMARY KEY (id)
|
||||||
|
) WITHOUT OIDS;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX bayes_vars_idx1 ON bayes_vars (username);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION greatest_int (integer, integer)
|
||||||
|
RETURNS INTEGER
|
||||||
|
IMMUTABLE STRICT
|
||||||
|
AS 'SELECT CASE WHEN $1 < $2 THEN $2 ELSE $1 END;'
|
||||||
|
LANGUAGE SQL;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION least_int (integer, integer)
|
||||||
|
RETURNS INTEGER
|
||||||
|
IMMUTABLE STRICT
|
||||||
|
AS 'SELECT CASE WHEN $1 < $2 THEN $1 ELSE $2 END;'
|
||||||
|
LANGUAGE SQL;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION put_tokens(INTEGER,
|
||||||
|
BYTEA[],
|
||||||
|
INTEGER,
|
||||||
|
INTEGER,
|
||||||
|
INTEGER)
|
||||||
|
RETURNS VOID AS '
|
||||||
|
DECLARE
|
||||||
|
inuserid ALIAS FOR $1;
|
||||||
|
intokenary ALIAS FOR $2;
|
||||||
|
inspam_count ALIAS FOR $3;
|
||||||
|
inham_count ALIAS FOR $4;
|
||||||
|
inatime ALIAS FOR $5;
|
||||||
|
_token BYTEA;
|
||||||
|
new_tokens INTEGER := 0;
|
||||||
|
BEGIN
|
||||||
|
for i in array_lower(intokenary, 1) .. array_upper(intokenary, 1)
|
||||||
|
LOOP
|
||||||
|
_token := intokenary[i];
|
||||||
|
UPDATE bayes_token
|
||||||
|
SET spam_count = greatest_int(spam_count + inspam_count, 0),
|
||||||
|
ham_count = greatest_int(ham_count + inham_count, 0),
|
||||||
|
atime = greatest_int(atime, inatime)
|
||||||
|
WHERE id = inuserid
|
||||||
|
AND token = _token;
|
||||||
|
IF NOT FOUND THEN
|
||||||
|
-- we do not insert negative counts, just return true
|
||||||
|
IF NOT (inspam_count < 0 OR inham_count < 0) THEN
|
||||||
|
INSERT INTO bayes_token (id, token, spam_count, ham_count, atime)
|
||||||
|
VALUES (inuserid, _token, inspam_count, inham_count, inatime);
|
||||||
|
IF FOUND THEN
|
||||||
|
new_tokens := new_tokens + 1;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
|
||||||
|
IF new_tokens > 0 AND inatime > 0 THEN
|
||||||
|
UPDATE bayes_vars
|
||||||
|
SET token_count = token_count + new_tokens,
|
||||||
|
newest_token_age = greatest_int(newest_token_age, inatime),
|
||||||
|
oldest_token_age = least_int(oldest_token_age, inatime)
|
||||||
|
WHERE id = inuserid;
|
||||||
|
ELSIF new_tokens > 0 AND NOT inatime > 0 THEN
|
||||||
|
UPDATE bayes_vars
|
||||||
|
SET token_count = token_count + new_tokens
|
||||||
|
WHERE id = inuserid;
|
||||||
|
ELSIF NOT new_tokens > 0 AND inatime > 0 THEN
|
||||||
|
UPDATE bayes_vars
|
||||||
|
SET newest_token_age = greatest_int(newest_token_age, inatime),
|
||||||
|
oldest_token_age = least_int(oldest_token_age, inatime)
|
||||||
|
WHERE id = inuserid;
|
||||||
|
END IF;
|
||||||
|
RETURN;
|
||||||
|
END;
|
||||||
|
' LANGUAGE 'plpgsql';
|
||||||
|
CREATE TABLE txrep (
|
||||||
|
username varchar(100) NOT NULL default '',
|
||||||
|
email varchar(255) NOT NULL default '',
|
||||||
|
ip varchar(40) NOT NULL default '',
|
||||||
|
msgcount bigint NOT NULL default '0',
|
||||||
|
totscore float NOT NULL default '0',
|
||||||
|
signedby varchar(255) NOT NULL default '',
|
||||||
|
last_hit timestamp NOT NULL default CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (username,email,signedby,ip)
|
||||||
|
);
|
||||||
|
|
||||||
|
create index txrep_last_hit on txrep (last_hit);
|
||||||
|
|
||||||
|
create OR REPLACE function update_txrep_last_hit()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.last_hit = CURRENT_TIMESTAMP;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ language 'plpgsql';
|
||||||
|
|
||||||
|
create TRIGGER update_txrep_update_last_hit BEFORE UPDATE
|
||||||
|
ON txrep FOR EACH ROW EXECUTE PROCEDURE
|
||||||
|
update_txrep_last_hit();
|
||||||
|
|
||||||
|
ALTER TABLE txrep SET (fillfactor=95);
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
CREATE TABLE txrep (
|
||||||
|
username varchar(100) NOT NULL default '',
|
||||||
|
email varchar(255) NOT NULL default '',
|
||||||
|
ip varchar(40) NOT NULL default '',
|
||||||
|
msgcount bigint NOT NULL default '0',
|
||||||
|
totscore float NOT NULL default '0',
|
||||||
|
signedby varchar(255) NOT NULL default '',
|
||||||
|
last_hit timestamp NOT NULL default CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (username,email,signedby,ip)
|
||||||
|
);
|
||||||
|
|
||||||
|
create index txrep_last_hit on txrep (last_hit);
|
||||||
|
|
||||||
|
create OR REPLACE function update_txrep_last_hit()
|
||||||
|
RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
NEW.last_hit = CURRENT_TIMESTAMP;
|
||||||
|
RETURN NEW;
|
||||||
|
END;
|
||||||
|
$$ language 'plpgsql';
|
||||||
|
|
||||||
|
create TRIGGER update_txrep_update_last_hit BEFORE UPDATE
|
||||||
|
ON txrep FOR EACH ROW EXECUTE PROCEDURE
|
||||||
|
update_txrep_last_hit();
|
||||||
|
|
||||||
|
ALTER TABLE txrep SET (fillfactor=95);
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
CREATE TABLE userpref (
|
||||||
|
prefid bigserial NOT NULL unique primary key,
|
||||||
|
username varchar(100) NOT NULL,
|
||||||
|
preference varchar(50) NOT NULL,
|
||||||
|
value varchar(100) NOT NULL
|
||||||
|
);
|
||||||
|
CREATE INDEX userpref_username_idx ON userpref(username);
|
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
- name: Reload spamassassin
|
||||||
|
service: name=spamassassin state=restarted
|
||||||
|
|
||||||
|
- name: Restart spamassassin
|
||||||
|
service: name=spamassassin state=restarted
|
||||||
|
|
||||||
|
- name: Restart spamass-milter
|
||||||
|
service: name=spamass-milter state=restarted
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: adellam
|
||||||
|
description: SpamAssassin 3 installation and configuration
|
||||||
|
company: ISTI-CNR
|
||||||
|
license: license (EUPL)
|
||||||
|
min_ansible_version: 2.7
|
||||||
|
platforms:
|
||||||
|
- name: EL
|
||||||
|
versions:
|
||||||
|
- 7
|
||||||
|
galaxy_tags:
|
||||||
|
- mail
|
||||||
|
- antispam
|
||||||
|
|
||||||
|
dependencies: []
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
- import_tasks: spamassassin.yml
|
||||||
|
when: spamassassin_install | bool
|
||||||
|
- import_tasks: spamass-milter.yml
|
||||||
|
when: spamassassin_milter_install | bool
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
- name: Install the Spamassassin milter packages
|
||||||
|
block:
|
||||||
|
- name: spamassassin milter packages, RH/CentOS
|
||||||
|
yum: pkg={{ spamassassin_rh_milter_packages }} state=present
|
||||||
|
|
||||||
|
when: ansible_distribution_file_variety == "RedHat"
|
||||||
|
tags: [ 'spamassassin', 'spamass_milter' ]
|
||||||
|
|
||||||
|
- name: Manage the spamassassin milter service
|
||||||
|
block:
|
||||||
|
- name: Install the spamassassin milter startup options
|
||||||
|
template: src=spamass-milter_sysconfig.j2 dest=/etc/sysconfig/spamass-milter owner=root group=root mode=0444
|
||||||
|
notify: Restart spamass-milter
|
||||||
|
|
||||||
|
- name: Ensure that the spamassassin service is started and enabled
|
||||||
|
service: name=spamass-milter state=started enabled=yes
|
||||||
|
|
||||||
|
tags: [ 'spamassassin', 'spamassassin_conf', 'spamassassin_service' ]
|
||||||
|
|
||||||
|
- name: Manage the spamassassin service
|
||||||
|
block:
|
||||||
|
- name: Shut down the spamassassin service if it is meant to be remote
|
||||||
|
service: name=spamassassin state=stopped enabled=no
|
||||||
|
|
||||||
|
when: not spamassassin_install | bool
|
||||||
|
tags: [ 'spamassassin', 'spamassassin_conf', 'spamassassin_service' ]
|
|
@ -0,0 +1,97 @@
|
||||||
|
---
|
||||||
|
- name: Create the spamassasin user and install the Spamassassin packages
|
||||||
|
block:
|
||||||
|
- name: Create the spamassassin user
|
||||||
|
user: name={{ spamassassin_user }} home={{ spamassassin_home }} comment="Spamassassin Service Account" createhome=no shell=/usr/sbin/nologin system=yes
|
||||||
|
|
||||||
|
- name: spamassassin packages, RH/CentOS
|
||||||
|
yum: pkg={{ spamassassin_rh_packages }} state=present
|
||||||
|
|
||||||
|
- name: spamassassin perl DB* packages, RH/CentOS
|
||||||
|
yum: pkg={{ spamassassin_sql_rh_packages }} state=present
|
||||||
|
when: spamassassin_db_user_config | bool
|
||||||
|
|
||||||
|
- name: Set some SELinux booleans related to spamassassin
|
||||||
|
seboolean: name={{ item }} state=yes persistent=yes
|
||||||
|
with_items:
|
||||||
|
- 'spamassassin_can_network'
|
||||||
|
- 'spamd_update_can_network'
|
||||||
|
|
||||||
|
when: ansible_distribution_file_variety == "RedHat"
|
||||||
|
tags: [ 'spamassassin' ]
|
||||||
|
|
||||||
|
- name: Manage the letsencrypt configuration
|
||||||
|
block:
|
||||||
|
- name: Check if the letsencrypt certificates are in place
|
||||||
|
stat: path={{ letsencrypt_acme_certs_dir }}/privkey
|
||||||
|
register: letsencrypt_keyfile
|
||||||
|
|
||||||
|
- name: Copy the letsencrypt certificate key into the right place
|
||||||
|
copy: src={{ letsencrypt_acme_certs_dir }}/privkey dest={{ spamassassin_home }}/client-key.pem owner={{ spamassassin_user }} group={{ spamassassin_group }} mode=0400 remote_src=yes force=yes
|
||||||
|
when: letsencrypt_keyfile.stat.exists is defined and letsencrypt_keyfile.stat.exists | bool
|
||||||
|
notify: Restart spamassassin
|
||||||
|
|
||||||
|
- name: Copy the letsencrypt public certificate into the right place
|
||||||
|
copy: src={{ letsencrypt_acme_certs_dir }}/fullchain dest={{ spamassassin_home }}/client-cert.pem owner={{ spamassassin_user }} group={{ spamassassin_group }} mode=0444 remote_src=yes force=yes
|
||||||
|
when: letsencrypt_keyfile.stat.exists is defined and letsencrypt_keyfile.stat.exists | bool
|
||||||
|
notify: Restart spamassassin
|
||||||
|
|
||||||
|
- name: Create the acme hooks directory if it does not yet exist
|
||||||
|
file: dest={{ letsencrypt_acme_sh_services_scripts_dir }} state=directory owner=root group=root
|
||||||
|
|
||||||
|
- name: Install a script that fix the letsencrypt certificate for mysql and then reload the service
|
||||||
|
template: src=letsencrypt-spamassassin-hook.sh.j2 dest={{ letsencrypt_acme_sh_services_scripts_dir }}/spamassassin owner=root group=root mode=4555
|
||||||
|
|
||||||
|
when:
|
||||||
|
- letsencrypt_acme_sh_install is defined and letsencrypt_acme_sh_install | bool
|
||||||
|
- spamassassin_spamd_ssl_enabled | bool
|
||||||
|
tags: [ 'spamassassin', 'letsencrypt', 'spamassassin_letsencrypt' ]
|
||||||
|
|
||||||
|
- name: Install the Spamassassin base configuration
|
||||||
|
block:
|
||||||
|
- name: spamassassin local config
|
||||||
|
template: src=spamassassin-local.cf.j2 dest={{ spamassassin_conf_dir }}/local.cf owner=root group={{ spamassassin_group }} mode=0440
|
||||||
|
notify: Reload spamassassin
|
||||||
|
|
||||||
|
- name: spamassassin spamd defaults
|
||||||
|
template: src=spamassassin_sysconfig.j2 dest=/etc/sysconfig/spamassassin owner=root group=root mode=0444
|
||||||
|
notify: Reload spamassassin
|
||||||
|
|
||||||
|
tags: [ 'spamassassin', 'spamassassin_conf' ]
|
||||||
|
|
||||||
|
- name: Install the Spamassassin DB configuration
|
||||||
|
block:
|
||||||
|
- name: spamassassin db config
|
||||||
|
template: src=spamassassin-db.cf.j2 dest={{ spamassassin_conf_dir }}/db.cf owner=root group={{ spamassassin_group }} mode=0440
|
||||||
|
notify: Reload spamassassin
|
||||||
|
|
||||||
|
when: spamassassin_db_user_config | bool
|
||||||
|
tags: [ 'spamassassin', 'spamassassin_conf' ]
|
||||||
|
|
||||||
|
- name: Install the Spamassassin DB configuration
|
||||||
|
block:
|
||||||
|
- name: Copy the spamassassin postgresql sql schema files
|
||||||
|
copy: src={{ spamassassin_db_sql_file }} dest={{ item.schema_file }} force=no
|
||||||
|
with_items: '{{ psql_db_data }}'
|
||||||
|
register: pdns_schema
|
||||||
|
when: item.schema_file is defined
|
||||||
|
|
||||||
|
- name: Install the spamassassin schema file
|
||||||
|
postgresql_db: name={{ item.name }} login_host='localhost' login_user={{ item.user }} login_password={{ item.pwd }} state=restore target={{ item.schema_file }} port={{ psql_db_port }}
|
||||||
|
with_items: '{{ psql_db_data }}'
|
||||||
|
when:
|
||||||
|
- pdns_schema is changed
|
||||||
|
- item.schema_file is defined
|
||||||
|
|
||||||
|
delegate_to: '{{ spamassassin_db_external_host }}'
|
||||||
|
run_once: True
|
||||||
|
when: spamassassin_db_user_config | bool
|
||||||
|
tags: [ 'spamassassin', 'spamassassin_conf' ]
|
||||||
|
|
||||||
|
- name: Manage the spamassassin service
|
||||||
|
block:
|
||||||
|
- name: Ensure that the spamassassin service is started and enabled
|
||||||
|
service: name=spamassassin state=started enabled=yes
|
||||||
|
|
||||||
|
when: spamassassin_install | bool
|
||||||
|
tags: [ 'spamassassin', 'spamassassin_conf', 'spamassassin_service' ]
|
|
@ -0,0 +1,35 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
LE_SERVICES_SCRIPT_DIR=/usr/lib/acme/hooks
|
||||||
|
LE_CERTS_DIR={{ letsencrypt_acme_certs_dir }}
|
||||||
|
LE_LOG_DIR=/var/log/acme
|
||||||
|
LE_LOG_FILE="$LE_LOG_DIR"/spamassassin.log
|
||||||
|
SPAMASSASSIN_CERTDIR={{ spamassassin_home }}
|
||||||
|
RETVAL=
|
||||||
|
|
||||||
|
DATE=$( date )
|
||||||
|
|
||||||
|
echo "$DATE" >> "$LE_LOG_FILE"
|
||||||
|
|
||||||
|
echo "Check if the certificate changed" >> "$LE_LOG_FILE"
|
||||||
|
diff "${LE_CERTS_DIR}/fullchain" "$SPAMASSASSIN_CERTDIR"/client-cert.pem > /dev/null
|
||||||
|
RETVAL=$?
|
||||||
|
if [ $RETVAL -eq 0 ] ; then
|
||||||
|
echo "Certificate did not change, exiting." >> "$LE_LOG_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Copying the new certificate files" >> "$LE_LOG_FILE"
|
||||||
|
cp -u "${LE_CERTS_DIR}/fullchain" "$SPAMASSASSIN_CERTDIR"/client-cert.pem
|
||||||
|
cp -u "${LE_CERTS_DIR}/privkey" "$SPAMASSASSIN_CERTDIR"/client-key.pem
|
||||||
|
chmod 444 "$SPAMASSASSIN_CERTDIR"/client-cert.pem
|
||||||
|
chown {{ spamassassin_user }}:{{ spamassassin_group }} "$SPAMASSASSIN_CERTDIR"/client-cert.pem
|
||||||
|
chmod 400 "$SPAMASSASSIN_CERTDIR"/client-key.pem
|
||||||
|
chown {{ spamassassin_user }}:{{ spamassassin_group }} "$SPAMASSASSIN_CERTDIR"/client-key.pem
|
||||||
|
|
||||||
|
echo "Restart the spamassassin service" >> "$LE_LOG_FILE"
|
||||||
|
if [ -x /bin/systemctl ] ; then
|
||||||
|
systemctl restart spamassassin >> "$LE_LOG_FILE" 2>&1
|
||||||
|
else
|
||||||
|
service spamassassin restart >> "$LE_LOG_FILE" 2>&1
|
||||||
|
fi
|
|
@ -0,0 +1,8 @@
|
||||||
|
### You may add configuration parameters here, see spamass-milter(1)
|
||||||
|
###
|
||||||
|
### Note that the -x option for expanding aliases and virtusertable entries
|
||||||
|
### only works if spamass-milter is run as root; you will need to use
|
||||||
|
### spamass-milter-root.service instead of spamass-milter.service if you
|
||||||
|
### wish to do this but otherwise it's best to run as the unprivileged user
|
||||||
|
### sa-milt by using the normal spamass-milter.service
|
||||||
|
EXTRA_FLAGS="{% if not spamassassin_milter_change_headers %}-m {% endif %}{% if spamassassin_milter_set_pref_dom_and_user %}-e {{ spamassassin_milter_pref_default_domain }} -u {{ spamassassin_milter_pref_default_user }}{% endif %} -r {{ spamassassin_milter_reject_limit }} -C {{ spamassassin_milter_reject_code }} -R '{{ spamassassin_milter_reject_message }}' {% if spamassassin_milter_exclude_whitelisted_networks %}-i {{ spamassassin_milter_whitelisted_networks }}{% endif %} {% if spamassassin_milter_connect_to_external_spamd %}-- -d {{ spamassassin_milter_external_spamd_host }}:{{ spamassassin_milter_external_spamd_port }}{% endif %}"
|
|
@ -0,0 +1,19 @@
|
||||||
|
user_scores_dsn DBI:Pg:dbname={{ spamassassin_db_name }};host={{ spamassassin_db_host }};port={{ spamassassin_db_port }}
|
||||||
|
user_scores_sql_username {{ spamassassin_db_user }}
|
||||||
|
user_scores_sql_password {{ spamassassin_db_pwd }}
|
||||||
|
{% if spamassassin_use_bayes and spamassassin_bayes_sql_db %}
|
||||||
|
bayes_store_module Mail::SpamAssassin::BayesStore::PgSQL
|
||||||
|
bayes_sql_dsn DBI:Pg:dbname={{ spamassassin_db_name }};host={{ spamassassin_db_host }};port={{ spamassassin_db_port }}
|
||||||
|
bayes_sql_username {{ spamassassin_db_user }}
|
||||||
|
bayes_sql_password {{ spamassassin_db_pwd }}
|
||||||
|
{% endif %}
|
||||||
|
{% if spamassassin_auto_whitelist and spamassassin_auto_whitelist_sql_db %}
|
||||||
|
# awl should be deprecated in favor of txrep, but the perl plugin is missing
|
||||||
|
#loadplugin Mail::SpamAssassin::Plugin::TxRep
|
||||||
|
#txrep_factory Mail::SpamAssassin::SQLBasedAddrList
|
||||||
|
loadplugin Mail::SpamAssassin::Plugin::AWL
|
||||||
|
auto_whitelist_factory Mail::SpamAssassin::SQLBasedAddrList
|
||||||
|
user_awl_dsn DBI:Pg:dbname={{ spamassassin_db_name }};host={{ spamassassin_db_host }};port={{ spamassassin_db_port }}
|
||||||
|
user_awl_sql_username {{ spamassassin_db_user }}
|
||||||
|
user_awl_sql_password {{ spamassassin_db_pwd }}
|
||||||
|
{% endif %}
|
|
@ -0,0 +1,19 @@
|
||||||
|
# These values can be overridden by editing ~/.spamassassin/user_prefs.cf
|
||||||
|
# (see spamassassin(1) for details)
|
||||||
|
|
||||||
|
# These should be safe assumptions and allow for simple visual sifting
|
||||||
|
# without risking lost emails.
|
||||||
|
|
||||||
|
required_hits {{ spamassassin_required_hits }}
|
||||||
|
report_safe {{ spamassassin_report_safe }}
|
||||||
|
rewrite_header Subject {{ spamassassin_rewrite_subject }}
|
||||||
|
{% if spamassassin_use_bayes %}
|
||||||
|
use_bayes 1
|
||||||
|
bayes_auto_learn {{ spamassassin_use_bayes_autolearn }}
|
||||||
|
bayes_auto_expire {{ spamassassin_use_bayes_auto_expire }}
|
||||||
|
{% else %}
|
||||||
|
use_bayes 0
|
||||||
|
{% endif %}
|
||||||
|
{% if spamassassin_auto_whitelist %}
|
||||||
|
use_auto_whitelist 1
|
||||||
|
{% endif %}
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Options to spamd
|
||||||
|
SPAMDOPTIONS="-d -m5 -H {% if spamassassin_db_user_config %}{{ spamassassin_spamd_sql_opts }}{% else %} -c{% endif %} {% if spamassassin_spamd_ssl_enabled %}{{ spamassassin_spamd_ssl_opts }}{% endif %}"
|
Loading…
Reference in New Issue