Commit 97b2105a authored by Joshua Tauberer's avatar Joshua Tauberer

spamassassin

parent 5cef1bb6
......@@ -8,6 +8,8 @@ This draws heavily on Sovereign by Alex Payne (https://github.com/al3x/sovereign
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.
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
...
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:
......
......@@ -109,17 +109,22 @@ EOF
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
# Modify the unix socket for LMTP.
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
# Add an additional auth socket for postfix. Check if it already is
# set to make sure this is idempotent.
if grep -q "mailinabox-postfix-private-auth" /etc/dovecot/conf.d/10-master.conf; then
# already done
true;
else
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
# Create a Unix domain socket specific for postgres to connect via LMTP because
# 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
# lmtp unix socket is also listening.
cat > /etc/dovecot/conf.d/99-local.conf << EOF;
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
user = postfix
group = postfix
}
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.
......
# 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
# 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
import imaplib, os
username = "testuser@" + os.environ.get("DOMAIN", "testdomain.com")
M = imaplib.IMAP4_SSL(os.environ["INSTANCE_IP"])
M.login("testuser@testdomain.com", "testpw")
M.login(username, "testpw")
M.select()
print("Login successful.")
typ, data = M.search(None, 'ALL')
......
......@@ -4,20 +4,27 @@ import sys, re
# sanity check
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)
# parse command line arguments
filename = sys.argv[1]
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
found = set()
buf = ""
for line in open(filename):
for i in range(len(settings)):
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 this is already the setting, do nothing.
if m.group(1) == val:
......@@ -33,7 +40,7 @@ for line in open(filename):
break
# add the new setting
buf += name + "=" + val + "\n"
buf += name + delimiter + val + "\n"
# note that we've applied this option
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.
for i in range(len(settings)):
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.
with open(filename, "w") as f:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment