mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-24 02:37:05 +00:00
spamassassin
This commit is contained in:
parent
5cef1bb63d
commit
97b2105a1f
@ -8,6 +8,8 @@ This draws heavily on Sovereign by Alex Payne (https://github.com/al3x/sovereign
|
|||||||
Deploying to EC2 from the command line
|
Deploying to EC2 from the command line
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
|
Amazon's EC2 isn't a great place to host a mail server. Do you still need to request permission to send email first? And you don't know if you'll get an IP address with a bad reputation from its previous owner. But it makes deployment easy, so it may at least be useful for testing.
|
||||||
|
|
||||||
Sign up for Amazon Web Services.
|
Sign up for Amazon Web Services.
|
||||||
|
|
||||||
Create an Access Key at https://console.aws.amazon.com/iam/home?#security_credential. Download the key and save the information somewhere secure.
|
Create an Access Key at https://console.aws.amazon.com/iam/home?#security_credential. Download the key and save the information somewhere secure.
|
||||||
@ -53,6 +55,8 @@ Somehow download these files.
|
|||||||
sh scripts/index.sh
|
sh scripts/index.sh
|
||||||
...
|
...
|
||||||
logout
|
logout
|
||||||
|
|
||||||
|
You'll also want to set reverse DNS (PTR), which is something your hosting provider will probably have a control panel for.
|
||||||
|
|
||||||
Terminate your instance with:
|
Terminate your instance with:
|
||||||
|
|
||||||
|
@ -109,17 +109,22 @@ EOF
|
|||||||
sed -i "s/#port = 143/port = 0/" /etc/dovecot/conf.d/10-master.conf
|
sed -i "s/#port = 143/port = 0/" /etc/dovecot/conf.d/10-master.conf
|
||||||
sed -i "s/#port = 110/port = 0/" /etc/dovecot/conf.d/10-master.conf
|
sed -i "s/#port = 110/port = 0/" /etc/dovecot/conf.d/10-master.conf
|
||||||
|
|
||||||
# Modify the unix socket for LMTP.
|
# Create a Unix domain socket specific for postgres to connect via LMTP because
|
||||||
sed -i "s/unix_listener lmtp \(.*\)/unix_listener \/var\/spool\/postfix\/private\/dovecot-lmtp \1\n user = postfix\n group = postfix\n/" /etc/dovecot/conf.d/10-master.conf
|
# postgres is already configured to use this location, and create a TCP socket
|
||||||
|
# for spampd to inject mail on (if it's configured later). dovecot's standard
|
||||||
# Add an additional auth socket for postfix. Check if it already is
|
# lmtp unix socket is also listening.
|
||||||
# set to make sure this is idempotent.
|
cat > /etc/dovecot/conf.d/99-local.conf << EOF;
|
||||||
if grep -q "mailinabox-postfix-private-auth" /etc/dovecot/conf.d/10-master.conf; then
|
service lmtp {
|
||||||
# already done
|
unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
||||||
true;
|
user = postfix
|
||||||
else
|
group = postfix
|
||||||
sed -i "s/\(\s*unix_listener auth-userdb\)/ unix_listener \/var\/spool\/postfix\/private\/auth \{ # mailinabox-postfix-private-auth\n mode = 0666\n user = postfix\n group = postfix\n \}\n\1/" /etc/dovecot/conf.d/10-master.conf
|
}
|
||||||
fi
|
inet_listener lmtp {
|
||||||
|
address = 127.0.0.1
|
||||||
|
port = 10026
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
# Drew Crawford sets the auth-worker process to run as the mail user, but we don't care if it runs as root.
|
# Drew Crawford sets the auth-worker process to run as the mail user, but we don't care if it runs as root.
|
||||||
|
|
||||||
|
48
scripts/spamassassin.sh
Normal file
48
scripts/spamassassin.sh
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Spam filtering with spamassassin via spampd.
|
||||||
|
|
||||||
|
apt-get -q -y install spampd dovecot-antispam
|
||||||
|
|
||||||
|
# Hook into postfix. Replace dovecot with spampd as the mail delivery agent.
|
||||||
|
tools/editconf.py /etc/postfix/main.cf virtual_transport=lmtp:[127.0.0.1]:10025
|
||||||
|
|
||||||
|
# Hook into dovecot. This is actually the default but we don't want to lose track of it.
|
||||||
|
tools/editconf.py /etc/default/spampd DESTPORT=10026
|
||||||
|
|
||||||
|
# Automatically move spam into a folder called Spam. Enable the sieve plugin.
|
||||||
|
# (Note: Be careful if we want to use multiple plugins later.)
|
||||||
|
# The sieve scripts are installed by users_update.sh.
|
||||||
|
sudo sed -i "s/#mail_plugins = .*/mail_plugins = \$mail_plugins sieve/" /etc/dovecot/conf.d/20-lmtp.conf
|
||||||
|
|
||||||
|
# Enable the antispam plugin to detect when a message moves between folders so we can
|
||||||
|
# pass it to sa-learn for training. (Be careful if we use multiple plugins later.)
|
||||||
|
sudo sed -i "s/#mail_plugins = .*/mail_plugins = \$mail_plugins antispam/" /etc/dovecot/conf.d/20-imap.conf
|
||||||
|
|
||||||
|
# When mail is moved in or out of the dovecot Spam folder, re-train.
|
||||||
|
# from http://wiki2.dovecot.org/Plugins/Antispam
|
||||||
|
cat > /usr/bin/sa-learn-pipe.sh << EOF;
|
||||||
|
cat<&0 >> /tmp/sendmail-msg-\$\$.txt
|
||||||
|
/usr/bin/sa-learn \$* /tmp/sendmail-msg-\$\$.txt > /dev/null
|
||||||
|
rm -f /tmp/sendmail-msg-\$\$.txt
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod a+x /usr/bin/sa-learn-pipe.sh
|
||||||
|
|
||||||
|
cat > /etc/dovecot/conf.d/99-local-spampd.conf << EOF;
|
||||||
|
plugin {
|
||||||
|
antispam_backend = pipe
|
||||||
|
antispam_spam_pattern_ignorecase = SPAM
|
||||||
|
antispam_allow_append_to_spam = yes
|
||||||
|
antispam_pipe_program_spam_arg = /usr/bin/sa-learn-pipe.sh --spam
|
||||||
|
antispam_pipe_program_notspam_arg = /usr/bin/sa-learn-pipe.sh --ham
|
||||||
|
antispam_pipe_program = /bin/bash
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Initial training?
|
||||||
|
# sa-learn --ham storage/mail/mailboxes/*/*/cur/
|
||||||
|
# sa-learn --spam storage/mail/mailboxes/*/*/.Spam/cur/
|
||||||
|
|
||||||
|
sudo service spampd restart
|
||||||
|
sudo service dovecot restart
|
||||||
|
|
22
scripts/users_update.sh
Normal file
22
scripts/users_update.sh
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
# Install dovecot sieve scripts to automatically move spam into the Spam folder.
|
||||||
|
|
||||||
|
db_path=$STORAGE_ROOT/mail/users.sqlite
|
||||||
|
|
||||||
|
for user in `echo "SELECT email FROM users;" | sqlite3 $db_path`; do
|
||||||
|
maildir=`echo $user | sed "s/\(.*\)@\(.*\)/\2\/\1/"`
|
||||||
|
|
||||||
|
# Write the sieve file to move mail classified as spam into the spam folder.
|
||||||
|
mkdir -p $STORAGE_ROOT/mail/mailboxes/$maildir; # in case user has not received any mail
|
||||||
|
cat > $STORAGE_ROOT/mail/mailboxes/$maildir/.dovecot.sieve << EOF;
|
||||||
|
require ["regex", "fileinto", "imap4flags"];
|
||||||
|
|
||||||
|
if allof (header :regex "X-Spam-Status" "^Yes") {
|
||||||
|
setflag "\\\\Seen";
|
||||||
|
fileinto "Spam";
|
||||||
|
stop;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
done
|
||||||
|
|
@ -1,7 +1,9 @@
|
|||||||
import imaplib, os
|
import imaplib, os
|
||||||
|
|
||||||
|
username = "testuser@" + os.environ.get("DOMAIN", "testdomain.com")
|
||||||
|
|
||||||
M = imaplib.IMAP4_SSL(os.environ["INSTANCE_IP"])
|
M = imaplib.IMAP4_SSL(os.environ["INSTANCE_IP"])
|
||||||
M.login("testuser@testdomain.com", "testpw")
|
M.login(username, "testpw")
|
||||||
M.select()
|
M.select()
|
||||||
print("Login successful.")
|
print("Login successful.")
|
||||||
typ, data = M.search(None, 'ALL')
|
typ, data = M.search(None, 'ALL')
|
||||||
|
@ -4,20 +4,27 @@ import sys, re
|
|||||||
|
|
||||||
# sanity check
|
# sanity check
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print("usage: python3 editconf.py /etc/file.conf NAME=VAL [NAME=VAL ...]")
|
print("usage: python3 editconf.py /etc/file.conf [-s] NAME=VAL [NAME=VAL ...]")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# parse command line arguments
|
# parse command line arguments
|
||||||
filename = sys.argv[1]
|
filename = sys.argv[1]
|
||||||
settings = sys.argv[2:]
|
settings = sys.argv[2:]
|
||||||
|
|
||||||
|
delimiter = "="
|
||||||
|
delimiter_re = r"\s*=\s*"
|
||||||
|
if settings[0] == "-s":
|
||||||
|
settings.pop(0)
|
||||||
|
delimiter = " "
|
||||||
|
delimiter_re = r"\s+"
|
||||||
|
|
||||||
# create the new config file in memory
|
# create the new config file in memory
|
||||||
found = set()
|
found = set()
|
||||||
buf = ""
|
buf = ""
|
||||||
for line in open(filename):
|
for line in open(filename):
|
||||||
for i in range(len(settings)):
|
for i in range(len(settings)):
|
||||||
name, val = settings[i].split("=", 1)
|
name, val = settings[i].split("=", 1)
|
||||||
m = re.match("\s*" + re.escape(name) + "\s*=\s*(.*?)\s*$", line)
|
m = re.match("\s*" + re.escape(name) + delimiter_re + "(.*?)\s*$", line)
|
||||||
if m:
|
if m:
|
||||||
# If this is already the setting, do nothing.
|
# If this is already the setting, do nothing.
|
||||||
if m.group(1) == val:
|
if m.group(1) == val:
|
||||||
@ -33,7 +40,7 @@ for line in open(filename):
|
|||||||
break
|
break
|
||||||
|
|
||||||
# add the new setting
|
# add the new setting
|
||||||
buf += name + "=" + val + "\n"
|
buf += name + delimiter + val + "\n"
|
||||||
|
|
||||||
# note that we've applied this option
|
# note that we've applied this option
|
||||||
found.add(i)
|
found.add(i)
|
||||||
@ -46,7 +53,8 @@ for line in open(filename):
|
|||||||
# Put any settings we didn't see at the end of the file.
|
# Put any settings we didn't see at the end of the file.
|
||||||
for i in range(len(settings)):
|
for i in range(len(settings)):
|
||||||
if i not in found:
|
if i not in found:
|
||||||
buf += settings[i] + "\n"
|
name, val = settings[i].split("=", 1)
|
||||||
|
buf += name + delimiter + val + "\n"
|
||||||
|
|
||||||
# Write out the new file.
|
# Write out the new file.
|
||||||
with open(filename, "w") as f:
|
with open(filename, "w") as f:
|
||||||
|
Loading…
Reference in New Issue
Block a user