spamassassin: installation and configuration of the spamd service and spamass-milter. Support user preferences in postgreSQL.

This commit is contained in:
Andrea Dell'Amico 2020-04-04 20:13:34 +02:00
parent 0aba51911c
commit c78b5f4fdc
17 changed files with 676 additions and 1 deletions

View File

@ -1,3 +1,14 @@
# 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');
```

69
defaults/main.yml Normal file
View File

@ -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

26
files/awl_pg.sql Normal file
View File

@ -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);

119
files/bayes_pg.sql Normal file
View File

@ -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';

View File

@ -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);

27
files/txrep_pg.sql Normal file
View File

@ -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);

7
files/userpref_pg.sql Normal file
View File

@ -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);

9
handlers/main.yml Normal file
View File

@ -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

16
meta/main.yml Normal file
View File

@ -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: []

5
tasks/main.yml Normal file
View File

@ -0,0 +1,5 @@
---
- import_tasks: spamassassin.yml
when: spamassassin_install | bool
- import_tasks: spamass-milter.yml
when: spamassassin_milter_install | bool

27
tasks/spamass-milter.yml Normal file
View File

@ -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' ]

97
tasks/spamassassin.yml Normal file
View File

@ -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' ]

View File

@ -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

View File

@ -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 %}"

View File

@ -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 %}

View File

@ -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 %}

View File

@ -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 %}"