diff options
Diffstat (limited to 'app/models')
-rw-r--r-- | app/models/application_mailer.rb | 3 | ||||
-rw-r--r-- | app/models/incoming_message.rb | 25 | ||||
-rw-r--r-- | app/models/info_request.rb | 52 | ||||
-rw-r--r-- | app/models/info_request_event.rb | 7 | ||||
-rw-r--r-- | app/models/public_body.rb | 55 | ||||
-rw-r--r-- | app/models/raw_email.rb | 2 | ||||
-rw-r--r-- | app/models/request_mailer.rb | 5 | ||||
-rw-r--r-- | app/models/track_mailer.rb | 2 | ||||
-rw-r--r-- | app/models/track_thing.rb | 58 | ||||
-rw-r--r-- | app/models/user_mailer.rb | 4 |
10 files changed, 145 insertions, 68 deletions
diff --git a/app/models/application_mailer.rb b/app/models/application_mailer.rb index 508ff2016..9628d7339 100644 --- a/app/models/application_mailer.rb +++ b/app/models/application_mailer.rb @@ -28,5 +28,8 @@ class ApplicationMailer < ActionMailer::Base # views (for links) and mailers (for use in emails), so include them into # all of all. include LinkToHelper + + # Site-wide access to configuration settings + include ConfigHelper end diff --git a/app/models/incoming_message.rb b/app/models/incoming_message.rb index 581c73f8b..ae7d1201e 100644 --- a/app/models/incoming_message.rb +++ b/app/models/incoming_message.rb @@ -431,7 +431,7 @@ class IncomingMessage < ActiveRecord::Base text.gsub!(self.info_request.public_body.request_email, "[" + self.info_request.public_body.short_or_long_name + " request email]") end text.gsub!(self.info_request.incoming_email, "[FOI #" + self.info_request.id.to_s + " email]") - text.gsub!(MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost'), "[WhatDoTheyKnow contact email]") + text.gsub!(MySociety::Config.get("CONTACT_EMAIL", 'contact@localhost'), "[#{MySociety::Config.get('SITE_NAME', 'Alaveteli')} contact email]") end # Replaces all email addresses in (possibly binary data) with equal length alternative ones. @@ -461,11 +461,23 @@ class IncomingMessage < ActiveRecord::Base if censored_uncompressed_text != uncompressed_text # then use the altered file (recompressed) recompressed_text = nil - IO.popen("/usr/bin/pdftk - output - compress", "r+") do |child| + if MySociety::Config.get('USE_GHOSTSCRIPT_COMPRESSION') == true + command = "gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dQUIET -dBATCH -sOutputFile=- -" + else + command = "/usr/bin/pdftk - output - compress" + end + IO.popen(command, "r+") do |child| child.write(censored_uncompressed_text) child.close_write() recompressed_text = child.read() end + if recompressed_text.nil? || recompressed_text.empty? + # buggy versions of pdftk sometimes fail on + # compression, I don't see it's a disaster in + # these cases to save an uncompressed version? + recompressed_text = censored_uncompressed_text + logger.warn "Unable to compress PDF; problem with your pdftk version?" + end if !recompressed_text.nil? && !recompressed_text.empty? text[0..-1] = recompressed_text # [0..-1] makes it change the 'text' string in place end @@ -850,7 +862,9 @@ class IncomingMessage < ActiveRecord::Base text = Iconv.conv('utf-8', 'windows-1252', text) rescue Iconv::IllegalSequence # Text looks like unlabelled nonsense, strip out anything that isn't UTF-8 - text = Iconv.conv('utf-8//IGNORE', 'utf-8', text) + "\n\n[ WhatDoTheyKnow note: The above text was badly encoded, and has had strange characters removed. ]" + text = Iconv.conv('utf-8//IGNORE', 'utf-8', text) + + _("\n\n[ {{site_name}} note: The above text was badly encoded, and has had strange characters removed. ]", + :site_name => MySociety::Config.get('SITE_NAME', 'Alaveteli')) end end end @@ -1119,7 +1133,7 @@ class IncomingMessage < ActiveRecord::Base external_command("/usr/bin/catdoc", tempfile.path, :append_to => text) elsif content_type == 'text/html' # lynx wordwraps links in its output, which then don't get formatted properly - # by WhatDoTheyKnow. We use elinks instead, which doesn't do that. + # by Alaveteli. We use elinks instead, which doesn't do that. external_command("/usr/bin/elinks", "-dump-charset", "utf-8", "-force-html", "-dump", tempfile.path, :append_to => text) elsif content_type == 'application/vnd.ms-excel' @@ -1237,9 +1251,8 @@ class IncomingMessage < ActiveRecord::Base info_request_event.track_things_sent_emails.each { |a| a.destroy } info_request_event.user_info_request_sent_alerts.each { |a| a.destroy } info_request_event.destroy - raw_email = self.raw_email + self.raw_email.destroy_file_representation! self.destroy - self.raw_email.destroy end end diff --git a/app/models/info_request.rb b/app/models/info_request.rb index 209954b16..419546c99 100644 --- a/app/models/info_request.rb +++ b/app/models/info_request.rb @@ -17,7 +17,6 @@ # allow_new_responses_from :string(255) default("anybody"), not null # handle_rejected_responses :string(255) default("bounce"), not null # - # models/info_request.rb: # A Freedom of Information request. # @@ -309,13 +308,20 @@ public # Return list of info requests which *might* be right given email address # e.g. For the id-hash email addresses, don't match the hash. - def InfoRequest.guess_by_incoming_email(incoming_email) - id, hash = InfoRequest._extract_id_hash_from_email(incoming_email) - begin - return [InfoRequest.find(id)] - rescue ActiveRecord::RecordNotFound - return [] + def InfoRequest.guess_by_incoming_email(incoming_message) + guesses = [] + # 1. Try to guess based on the email address(es) + addresses = + (incoming_message.mail.to || []) + + (incoming_message.mail.cc || []) + + (incoming_message.mail.envelope_to || []) + addresses.uniq! + for address in addresses + id, hash = InfoRequest._extract_id_hash_from_email(address) + guesses.push(InfoRequest.find_by_id(id)) + guesses.push(InfoRequest.find_by_idhash(hash)) end + return guesses.select{|x| !x.nil?}.uniq end # Internal function used by find_by_magic_email and guess_by_incoming_email @@ -326,7 +332,7 @@ public # The optional bounce- dates from when we used to have separate emails for the envelope from. # (that was abandoned because councils would send hand written responses to them, not just # bounce messages) - incoming_email =~ /request-(?:bounce-)?(\d+)-([a-z0-9]+)/ + incoming_email =~ /request-(?:bounce-)?([a-z0-9]+)-([a-z0-9]+)/ id = $1.to_i hash = $2 @@ -379,21 +385,24 @@ public end # A new incoming email to this request - def receive(email, raw_email_data, override_stop_new_responses = false) + def receive(email, raw_email_data, override_stop_new_responses = false, rejected_reason = "") if !override_stop_new_responses allow = nil - + reason = nil # See if new responses are prevented for spam reasons if self.allow_new_responses_from == 'nobody' allow = false + reason = _('This request has been set by an administrator to "allow new responses from nobody"') elsif self.allow_new_responses_from == 'anybody' allow = true elsif self.allow_new_responses_from == 'authority_only' if email.from_addrs.nil? || email.from_addrs.size == 0 allow = false + reason = _('Only the authority can reply to this request, but there is no "From" address to check against') else sender_email = email.from_addrs[0].spec sender_domain = PublicBody.extract_domain_from_email(sender_email) + reason = _("Only the authority can reply to this request, and I don't recognise the address this reply was sent from") allow = false # Allow any domain that has already sent reply for row in self.who_can_followup_to @@ -411,7 +420,7 @@ public if self.handle_rejected_responses == 'bounce' RequestMailer.deliver_stopped_responses(self, email, raw_email_data) elsif self.handle_rejected_responses == 'holding_pen' - InfoRequest.holding_pen_request.receive(email, raw_email_data) + InfoRequest.holding_pen_request.receive(email, raw_email_data, false, reason) elsif self.handle_rejected_responses == 'blackhole' # do nothing - just lose the message (Note: a copy will be # in the backup mailbox if the server is configured to send @@ -435,7 +444,11 @@ public raw_email.save! self.awaiting_description = true - self.log_event("response", { :incoming_message_id => incoming_message.id }) + params = { :incoming_message_id => incoming_message.id } + if !rejected_reason.empty? + params[:rejected_reason] = rejected_reason + end + self.log_event("response", params) self.save! end @@ -671,6 +684,7 @@ public end end return nil + end def get_last_response_event for e in self.info_request_events.reverse @@ -831,15 +845,25 @@ public def InfoRequest.magic_email_for_id(prefix_part, id) magic_email = MySociety::Config.get("INCOMING_EMAIL_PREFIX", "") magic_email += prefix_part + id.to_s - magic_email += "-" + Digest::SHA1.hexdigest(id.to_s + MySociety::Config.get("INCOMING_EMAIL_SECRET", 'dummysecret'))[0,8] + magic_email += "-" + InfoRequest.hash_from_id(id) magic_email += "@" + MySociety::Config.get("INCOMING_EMAIL_DOMAIN", "localhost") return magic_email end + before_validation :compute_idhash + + def compute_idhash + self.idhash = InfoRequest.hash_from_id(self.id) + end + + def InfoRequest.hash_from_id(id) + return Digest::SHA1.hexdigest(id.to_s + MySociety::Config.get("INCOMING_EMAIL_SECRET", 'dummysecret'))[0,8] + end + # Called by find_by_incoming_email - and used to be called by separate # function for envelope from address, until we abandoned it. def InfoRequest.find_by_magic_email(id, hash) - expected_hash = Digest::SHA1.hexdigest(id.to_s + MySociety::Config.get("INCOMING_EMAIL_SECRET", 'dummysecret'))[0,8] + expected_hash = InfoRequest.hash_from_id(id) #print "expected: " + expected_hash + "\nhash: " + hash + "\n" if hash != expected_hash return nil diff --git a/app/models/info_request_event.rb b/app/models/info_request_event.rb index 02b9a34ac..d79647c98 100644 --- a/app/models/info_request_event.rb +++ b/app/models/info_request_event.rb @@ -121,7 +121,12 @@ class InfoRequestEvent < ActiveRecord::Base self.info_request.user.url_name end def requested_from - self.info_request.public_body.url_name + # acts_as_xapian will detect translated fields via Globalize and add all the + # available locales to the index. But 'requested_from' is not translated directly, + # although it relies on a translated field in PublicBody. Hence, we need to + # manually add all the localized values to the index (Xapian can handle a list + # of values in a term, btw) + self.info_request.public_body.translations.map {|t| t.url_name} end def commented_by if self.event_type == 'comment' diff --git a/app/models/public_body.rb b/app/models/public_body.rb index 0e32a5164..ef1d60e26 100644 --- a/app/models/public_body.rb +++ b/app/models/public_body.rb @@ -310,29 +310,39 @@ class PublicBody < ActiveRecord::Base # Import from CSV. Just tests things and returns messages if dry_run is true. # Returns an array of [array of errors, array of notes]. If there are errors, # always rolls back (as with dry_run). - def self.import_csv(csv, tag, dry_run, editor) + def self.import_csv(csv, tag, dry_run, editor, additional_locales = []) errors = [] notes = [] begin ActiveRecord::Base.transaction do - existing_bodies = PublicBody.find_by_tag(tag) - + # Use the default locale when retrieving existing bodies; otherwise + # matching names won't work afterwards, and we'll create new bodies instead + # of updating them bodies_by_name = {} set_of_existing = Set.new() - for existing_body in existing_bodies - bodies_by_name[existing_body.name] = existing_body - set_of_existing.add(existing_body.name) + PublicBody.with_locale(I18n.default_locale) do + for existing_body in PublicBody.find_by_tag(tag) + bodies_by_name[existing_body.name] = existing_body + set_of_existing.add(existing_body.name) + end end - + set_of_importing = Set.new() + field_names = { 'name'=>1, 'email'=>2 } # Default values in case no field list is given line = 0 - CSV::Reader.parse(csv) do |row| line = line + 1 - name = row[1] - email = row[2] + # Parse the first line as a field list if it starts with '#' + if line==1 and row.to_s =~ /^#(.*)$/ + row[0] = row[0][1..-1] # Remove the # sign on first field + row.each_with_index {|field, i| field_names[field] = i} + next + end + + name = row[field_names['name']] + email = row[field_names['email']] next if name.nil? if email.nil? email = '' # unknown/bad contact is empty string @@ -353,15 +363,38 @@ class PublicBody < ActiveRecord::Base notes.push "line " + line.to_s + ": updating email for '" + name + "' from " + public_body.request_email + " to " + email public_body.request_email = email public_body.last_edit_editor = editor - public_body.last_edit_comment = 'Updated from spreadsheet' + public_body.last_edit_comment = 'Updated from spreadsheet' public_body.save! end + + additional_locales.each do |locale| + localized_name = field_names["name.#{locale}"] && row[field_names["name.#{locale}"]] + PublicBody.with_locale(locale) do + if !localized_name.nil? and public_body.name != localized_name + notes.push "line " + line.to_s + ": updating name for '#{name}' from '#{public_body.name}' to '#{localized_name}' (locale: #{locale})." + public_body.name = localized_name + public_body.save! + end + end + end else # New public body notes.push "line " + line.to_s + ": new authority '" + name + "' with email " + email public_body = PublicBody.new(:name => name, :request_email => email, :short_name => "", :home_page => "", :publication_scheme => "", :notes => "", :last_edit_editor => editor, :last_edit_comment => 'Created from spreadsheet') public_body.tag_string = tag public_body.save! + + additional_locales.each do |locale| + localized_name = field_names["name.#{locale}"] && row[field_names["name.#{locale}"]] + if !localized_name.nil? + PublicBody.with_locale(locale) do + notes.push "line " + line.to_s + ": (aka '#{localized_name}' in locale #{locale})" + public_body.name = localized_name + public_body.publication_scheme = "" + public_body.save! + end + end + end end set_of_importing.add(name) diff --git a/app/models/raw_email.rb b/app/models/raw_email.rb index eb36053c1..c6066cbf4 100644 --- a/app/models/raw_email.rb +++ b/app/models/raw_email.rb @@ -20,8 +20,6 @@ class RawEmail < ActiveRecord::Base has_one :incoming_message - before_destroy :destroy_file_representation! - # We keep the old data_text field (which is of type text) for backwards # compatibility. We use the new data_binary field because only it works # properly in recent versions of PostgreSQL (get seg faults escaping diff --git a/app/models/request_mailer.rb b/app/models/request_mailer.rb index e73b153b9..fc317d20d 100644 --- a/app/models/request_mailer.rb +++ b/app/models/request_mailer.rb @@ -205,10 +205,11 @@ class RequestMailer < ApplicationMailer def receive(email, raw_email) # Find which info requests the email is for reply_info_requests = self.requests_matching_email(email) - # Nothing found, so save in holding pen if reply_info_requests.size == 0 - InfoRequest.holding_pen_request.receive(email, raw_email) + reason = _("Could not identify the request from the email address") + request = InfoRequest.holding_pen_request + request.receive(email, raw_email, false, reason) return end diff --git a/app/models/track_mailer.rb b/app/models/track_mailer.rb index 6901a834d..4b7c603a7 100644 --- a/app/models/track_mailer.rb +++ b/app/models/track_mailer.rb @@ -22,7 +22,7 @@ class TrackMailer < ApplicationMailer # etc. don't decide we are spammers.) @recipients = user.name_and_email - @subject = "Your WhatDoTheyKnow.com email alert" + @subject = _("Your {{site_name}} email alert", :site_name => site_name) @body = { :user => user, :email_about_things => email_about_things, :unsubscribe_url => unsubscribe_url } end diff --git a/app/models/track_thing.rb b/app/models/track_thing.rb index aee1ed1da..16a0dab87 100644 --- a/app/models/track_thing.rb +++ b/app/models/track_thing.rb @@ -120,8 +120,8 @@ class TrackThing < ActiveRecord::Base @params = { # Website :list_description => "'<a href=\"/request/" + CGI.escapeHTML(self.info_request.url_title) + "\">" + CGI.escapeHTML(self.info_request.title) + "</a>', a request", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how - :verb_on_page => "Track this request by email", - :verb_on_page_already => "You are already tracking this request by email", + :verb_on_page => _("Track this request by email"), + :verb_on_page_already => _("You are already tracking this request by email"), # Email :title_in_email => "New updates for the request '" + self.info_request.title + "'", :title_in_rss => "New updates for the request '" + self.info_request.title + "'", @@ -135,23 +135,23 @@ class TrackThing < ActiveRecord::Base elsif self.track_type == 'all_new_requests' @params = { # Website - :list_description => "any <a href=\"/list\">new requests</a>", - :verb_on_page => "Email me when there are new requests", - :verb_on_page_already => "You are being emailed when there are new requests", + :list_description => _("any <a href=\"/list\">new requests</a>"), + :verb_on_page => _("Email me when there are new requests"), + :verb_on_page_already => _("You are being emailed when there are new requests"), # Email - :title_in_email => "New Freedom of Information requests", - :title_in_rss => "New Freedom of Information requests", + :title_in_email => _("New Freedom of Information requests"), + :title_in_rss => _("New Freedom of Information requests"), # Authentication - :web => "To be emailed about any new requests", - :email => "Then you will be emailed whenever anyone makes a new FOI request.", - :email_subject => "Confirm you want to be emailed about new requests", + :web => _("To be emailed about any new requests"), + :email => _("Then you will be emailed whenever anyone makes a new FOI request."), + :email_subject => _("Confirm you want to be emailed about new requests"), # RSS sorting :feed_sortby => 'newest' } elsif self.track_type == 'all_successful_requests' @params = { # Website - :list_description => "any <a href=\"/list/successful\">successful requests</a>", + :list_description => _("any <a href=\"/list/successful\">successful requests</a>"), :verb_on_page => _("Email me new successful responses "), :verb_on_page_already => _("You are being emailed about any new successful responses"), # Email @@ -172,14 +172,14 @@ class TrackThing < ActiveRecord::Base # Website :list_description => "'<a href=\"/body/" + CGI.escapeHTML(self.public_body.url_name) + "\">" + CGI.escapeHTML(self.public_body.name) + "</a>', a public authority", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how :verb_on_page => _("Track requests to {{public_body_name}} by email",:public_body_name=>CGI.escapeHTML(self.public_body.name)), - :verb_on_page_already => "You are already tracking requests to " + CGI.escapeHTML(self.public_body.name) + " by email", + :verb_on_page_already => _("You are already tracking requests to {{public_body_name}} by email", :public_body_name=>CGI.escapeHTML(self.public_body.name)), # Email :title_in_email => self.public_body.law_only_short + " requests to '" + self.public_body.name + "'", :title_in_rss => self.public_body.law_only_short + " requests to '" + self.public_body.name + "'", # Authentication - :web => "To be emailed about requests made using WhatDoTheyKnow to the public authority '" + CGI.escapeHTML(self.public_body.name) + "'", - :email => "Then you will be emailed whenever someone requests something or gets a response from '" + CGI.escapeHTML(self.public_body.name) + "'.", - :email_subject => "Confirm you want to be emailed about requests to '" + self.public_body.name + "'", + :web => _("To be emailed about requests made using {{site_name}} to the public authority '{{public_body_name}}'", :site_name=>MySociety::Config.get('SITE_NAME', 'Alaveteli'), :public_body_name=>CGI.escapeHTML(self.public_body.name)), + :email => _("Then you will be emailed whenever someone requests something or gets a response from '{{public_body_name}}'.", :public_body_name=>CGI.escapeHTML(self.public_body.name)), + :email_subject => _("Confirm you want to be emailed about requests to '{{public_body_name}}'", :public_body_name=>self.public_body.name), # RSS sorting :feed_sortby => 'newest' } @@ -187,15 +187,15 @@ class TrackThing < ActiveRecord::Base @params = { # Website :list_description => "'<a href=\"/user/" + CGI.escapeHTML(self.tracked_user.url_name) + "\">" + CGI.escapeHTML(self.tracked_user.name) + "</a>', a person", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how - :verb_on_page => "Track this person by email", - :verb_on_page_already => "You are already tracking this person by email", + :verb_on_page => _("Track this person by email"), + :verb_on_page_already => _("You are already tracking this person by email"), # Email - :title_in_email => "FOI requests by '" + self.tracked_user.name + "'", - :title_in_rss => "FOI requests by '" + self.tracked_user.name + "'", + :title_in_email => _("FOI requests by '{{user_name}}'", :user_name=>self.tracked_user.name), + :title_in_rss => _("FOI requests by '{{user_name}}'", :user_name=>self.tracked_user.name), # Authentication - :web => "To be emailed about requests by '" + CGI.escapeHTML(self.tracked_user.name) + "'", - :email => "Then you will be emailed whenever '" + CGI.escapeHTML(self.tracked_user.name) + "' requests something or gets a response.", - :email_subject => "Confirm you want to be emailed about requests by '" + self.tracked_user.name + "'", + :web => _("To be emailed about requests by '{{user_name}}'", :user_name=>CGI.escapeHTML(self.tracked_user.name)), + :email => _("Then you will be emailed whenever '{{user_name}}' requests something or gets a response.", :user_name=>CGI.escapeHTML(self.tracked_user.name)), + :email_subject => _("Confirm you want to be emailed about requests by '{{user_name}}'", :user_name=>self.tracked_user.name), # RSS sorting :feed_sortby => 'newest' } @@ -203,15 +203,15 @@ class TrackThing < ActiveRecord::Base @params = { # Website :list_description => "'<a href=\"/search/" + CGI.escapeHTML(self.track_query) + "/newest\">" + CGI.escapeHTML(self.track_query) + "</a>' in new requests/responses", # XXX yeuch, sometimes I just want to call view helpers from the model, sorry! can't work out how - :verb_on_page => "Track things matching '" + CGI.escapeHTML(self.track_query) + "' by email", - :verb_on_page_already => "You are already tracking things matching '" + CGI.escapeHTML(self.track_query) + "' by email", + :verb_on_page => _("Track things matching '{{query}}' by email", :query=>CGI.escapeHTML(self.track_query)), + :verb_on_page_already => _("You are already tracking things matching '{{query}}' by email", :query=>CGI.escapeHTML(self.track_query)), # Email - :title_in_email => "Requests or responses matching '" + self.track_query + "'", - :title_in_rss => "Requests or responses matching '" + self.track_query + "'", + :title_in_email => _("Requests or responses matching '{{query}}'", :query=>self.track_query), + :title_in_rss => _("Requests or responses matching '{{query}}'", :query=>self.track_query), # Authentication - :web => "To follow requests and responses matching '" + CGI.escapeHTML(self.track_query) + "'", - :email => "Then you will be emailed whenever a new request or response matches '" + CGI.escapeHTML(self.track_query) + "'.", - :email_subject => "Confirm you want to be emailed about new requests or responses matching '" + self.track_query + "'", + :web => _("To follow requests and responses matching '{{query}}'", :query=>CGI.escapeHTML(self.track_query)), + :email => _("Then you will be emailed whenever a new request or response matches '{{query}}'.", :query=>CGI.escapeHTML(self.track_query)), + :email_subject => _("Confirm you want to be emailed about new requests or responses matching '{{query}}'", :query=>self.track_query), # RSS sorting - XXX hmmm, we don't really know which to use # here for sorting. Might be a query term (e.g. 'cctv'), in # which case newest is good, or might be something like diff --git a/app/models/user_mailer.rb b/app/models/user_mailer.rb index f164f684e..0972e167d 100644 --- a/app/models/user_mailer.rb +++ b/app/models/user_mailer.rb @@ -31,7 +31,7 @@ class UserMailer < ApplicationMailer @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from # we don't care about bounces when people are fiddling with their account @recipients = new_email - @subject = _("Confirm your new email address on WhatDoTheyKnow.com") + @subject = _("Confirm your new email address on {{site_name}}", :site_name=>site_name) @body[:name] = user.name @body[:url] = url @body[:old_email] = user.email @@ -42,7 +42,7 @@ class UserMailer < ApplicationMailer @from = contact_from_name_and_email headers 'Return-Path' => blackhole_email, 'Reply-To' => @from # we don't care about bounces when people are fiddling with their account @recipients = new_email - @subject = _("Unable to change email address on WhatDoTheyKnow.com") + @subject = _("Unable to change email address on {{site_name}}", :site_name=>site_name) @body[:old_email] = old_email @body[:new_email] = new_email end |