aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGareth Rees <gareth@mysociety.org>2014-03-25 12:30:55 +0000
committerGareth Rees <gareth@mysociety.org>2014-03-26 13:02:51 +0000
commitd6d8a95db5797e8e55283e0ab9e1e7c28147699c (patch)
treef6d5e1082b767da3d1aafc75b10072b6c49b085b
parent7a108776e4f45b10ef5956326fdd9c66514d1ddd (diff)
Add SpamAddress model
The volume of spam in the holding pen in WDTK has increased. Over a few weeks in January 2014 the pattern was roughly: - 8 were sent "To" the same address, which was a nearly valid old request address - correct hash, but missing the second hyphen. - 1 was sent "To" an invalid request address (nearly correct hash) - 1 was sent "BCC" a valid request address - 1 was sent "BCC" request@whatdotheyknow.com If a spam was sent "To" an old valid request address then it would be rejected. It's not entirely safe to just reject mails to old requests with any hash, because sometimes authorities miss out a digit in the request number, though perhaps simply getting a failure bounce would cause them to check. In any case that wouldn't trivially catch the most frequent case above as it doesn't have an obvious request number. --- We looked at greylisting and configuring the MTA with an RBL. Greylisting was rejected as it would slow down the responsiveness of the application when people email in. This could be revisited if/when emails are parsed through a queue system depending on how we find the performance there. An RBL is already configured, but this ticket refers more to where the email is sent rather than who it came from. --- We elected to: - Create spam_address model - Add code to RequestMailer.receive to check the list of spam addresses and silently discard an incoming mail if it's addressed to one of them - Add page to admin interface for adding/removing spam addresses --- Thanks to Ganesh Sittampalam for the research and Louise Crow for the implementation strategy.
-rw-r--r--app/models/spam_address.rb11
-rw-r--r--db/migrate/20140325120619_create_spam_addresses.rb9
-rw-r--r--spec/factories/spam_addresses.rb5
-rw-r--r--spec/models/spam_address_spec.rb49
4 files changed, 74 insertions, 0 deletions
diff --git a/app/models/spam_address.rb b/app/models/spam_address.rb
new file mode 100644
index 000000000..15c9d1ab8
--- /dev/null
+++ b/app/models/spam_address.rb
@@ -0,0 +1,11 @@
+class SpamAddress < ActiveRecord::Base
+ attr_accessible :email
+
+ validates_presence_of :email, :message => _('Please enter the email address to mark as spam')
+ validates_uniqueness_of :email, :message => _('This address is already marked as spam')
+
+ def self.spam?(email_address)
+ exists?(:email => email_address)
+ end
+
+end
diff --git a/db/migrate/20140325120619_create_spam_addresses.rb b/db/migrate/20140325120619_create_spam_addresses.rb
new file mode 100644
index 000000000..7c730a5c7
--- /dev/null
+++ b/db/migrate/20140325120619_create_spam_addresses.rb
@@ -0,0 +1,9 @@
+class CreateSpamAddresses < ActiveRecord::Migration
+ def change
+ create_table :spam_addresses do |t|
+ t.string :email, :null => false
+
+ t.timestamps
+ end
+ end
+end
diff --git a/spec/factories/spam_addresses.rb b/spec/factories/spam_addresses.rb
new file mode 100644
index 000000000..bafb7cd50
--- /dev/null
+++ b/spec/factories/spam_addresses.rb
@@ -0,0 +1,5 @@
+FactoryGirl.define do
+ factory :spam_address do
+ sequence(:email) { |n| "spam-#{ n }@example.org" }
+ end
+end
diff --git a/spec/models/spam_address_spec.rb b/spec/models/spam_address_spec.rb
new file mode 100644
index 000000000..79a1afd11
--- /dev/null
+++ b/spec/models/spam_address_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+describe SpamAddress do
+
+ describe :new do
+
+ it 'requres an email address' do
+ SpamAddress.new().should_not be_valid
+ SpamAddress.new(:email => 'spam@example.org').should be_valid
+ end
+
+ it 'must have a unique email address' do
+ existing = FactoryGirl.create(:spam_address)
+ SpamAddress.new(:email => existing.email).should_not be_valid
+ end
+
+ end
+
+ describe '.spam?' do
+
+ before(:each) do
+ @spam_address = FactoryGirl.create(:spam_address)
+ end
+
+ it 'is a spam address if the address is stored' do
+ SpamAddress.spam?(@spam_address.email).should be_true
+ end
+
+ it 'is not a spam address if the adress is not stored' do
+ SpamAddress.spam?('genuine-email@example.com').should be_false
+ end
+
+ describe 'when accepting an array of emails' do
+
+ it 'is spam if any of the emails are stored' do
+ emails = ['genuine-email@example.com', @spam_address.email]
+ SpamAddress.spam?(emails).should be_true
+ end
+
+ it 'is not spam if none of the emails are stored' do
+ emails = ['genuine-email@example.com', 'genuine-email@example.org']
+ SpamAddress.spam?(emails).should be_false
+ end
+
+ end
+
+ end
+
+end