diff options
Diffstat (limited to 'app/mailers/track_mailer.rb')
-rw-r--r-- | app/mailers/track_mailer.rb | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/app/mailers/track_mailer.rb b/app/mailers/track_mailer.rb new file mode 100644 index 000000000..391143214 --- /dev/null +++ b/app/mailers/track_mailer.rb @@ -0,0 +1,135 @@ +# models/track_mailer.rb: +# Emails which go to users who are tracking things. +# +# Copyright (c) 2008 UK Citizens Online Democracy. All rights reserved. +# Email: hello@mysociety.org; WWW: http://www.mysociety.org/ + +class TrackMailer < ApplicationMailer + def event_digest(user, email_about_things) + @user, @email_about_things = user, email_about_things + + post_redirect = PostRedirect.new( + :uri => user_url(user) + "#email_subscriptions", + :user_id => user.id) + post_redirect.save! + @unsubscribe_url = confirm_url(:email_token => post_redirect.email_token) + + headers('Auto-Submitted' => 'auto-generated', # http://tools.ietf.org/html/rfc3834 + 'Precedence' => 'bulk')# http://www.vbulletin.com/forum/project.php?issueid=27687 (Exchange hack) + # 'Return-Path' => blackhole_email, 'Reply-To' => @from # we don't care about bounces for tracks + # (We let it return bounces for now, so we can manually kill the tracks that bounce so Yahoo + # etc. don't decide we are spammers.) + + mail(:from => contact_from_name_and_email, + :to => user.name_and_email, + :subject => _("Your {{site_name}} email alert", :site_name => site_name)) + end + + def contact_from_name_and_email + "#{AlaveteliConfiguration::track_sender_name} <#{AlaveteliConfiguration::track_sender_email}>" + end + + # Send email alerts for tracked things. Never more than one email + # a day, nor about events which are more than a week old, nor + # events about which emails have been sent within the last two + # weeks. + + # Useful query to run by hand to see how many alerts are due: + # User.find(:all, :conditions => [ "last_daily_track_email < ?", Time.now - 1.day ]).size + def self.alert_tracks + done_something = false + now = Time.now() + users = User.find(:all, :conditions => [ "last_daily_track_email < ?", now - 1.day ]) + if users.empty? + return done_something + end + for user in users + next if !user.should_be_emailed? || !user.receive_email_alerts + + email_about_things = [] + track_things = TrackThing.find(:all, :conditions => [ "tracking_user_id = ? and track_medium = ?", user.id, 'email_daily' ]) + for track_thing in track_things + # What have we alerted on already? + # + # We only use track_things_sent_emails records which are less than 14 days old. + # In the search query loop below, we also only use items described in last 7 days. + # An item described that recently definitely can't appear in track_things_sent_emails + # earlier, so this is safe (with a week long margin of error). If the alerts break + # for a whole week, then they will miss some items. Tough. + done_info_request_events = {} + tt_sent = track_thing.track_things_sent_emails.find(:all, :conditions => ['created_at > ?', now - 14.days]) + for t in tt_sent + if not t.info_request_event_id.nil? + done_info_request_events[t.info_request_event_id] = 1 + end + end + + # Query for things in this track. We use described_at for the + # ordering, so we catch anything new (before described), or + # anything whose new status has been described. + xapian_object = InfoRequest.full_search([InfoRequestEvent], track_thing.track_query, 'described_at', true, nil, 100, 1) + # Go through looking for unalerted things + alert_results = [] + for result in xapian_object.results + if result[:model].class.to_s != "InfoRequestEvent" + raise "need to add other types to TrackMailer.alert_tracks (unalerted)" + end + + next if track_thing.created_at >= result[:model].described_at # made before the track was created + next if result[:model].described_at < now - 7.days # older than 1 week (see 14 days / 7 days in comment above) + next if done_info_request_events.include?(result[:model].id) # definitely already done + + # OK alert this one + alert_results.push(result) + end + # If there were more alerts for this track, then store them + if alert_results.size > 0 + email_about_things.push([track_thing, alert_results, xapian_object]) + end + end + + # If we have anything to send, then send everything for the user in one mail + if email_about_things.size > 0 + # Send the email + + I18n.with_locale(user.get_locale) do + TrackMailer.event_digest(user, email_about_things).deliver + end + end + + # Record that we've now sent those alerts to that user + for track_thing, alert_results in email_about_things + for result in alert_results + track_things_sent_email = TrackThingsSentEmail.new + track_things_sent_email.track_thing_id = track_thing.id + if result[:model].class.to_s == "InfoRequestEvent" + track_things_sent_email.info_request_event_id = result[:model].id + else + raise "need to add other types to TrackMailer.alert_tracks (mark alerted)" + end + track_things_sent_email.save! + end + end + user.last_daily_track_email = now + user.no_xapian_reindex = true + user.save! + done_something = true + end + return done_something + end + + def self.alert_tracks_loop + # Run alert_tracks in an endless loop, sleeping when there is nothing to do + while true + sleep_seconds = 1 + while !alert_tracks + sleep sleep_seconds + sleep_seconds *= 2 + sleep_seconds = 300 if sleep_seconds > 300 + end + end + end + +end + + |