##// END OF EJS Templates
Adds cc and bcc to email log messages (#12090)....
Jean-Philippe Lang -
r10472:f09be6832327
parent child
Show More
@@ -1,149 +1,167
1 require 'active_record'
1 require 'active_record'
2
2
3 module ActiveRecord
3 module ActiveRecord
4 class Base
4 class Base
5 include Redmine::I18n
5 include Redmine::I18n
6 # Translate attribute names for validation errors display
6 # Translate attribute names for validation errors display
7 def self.human_attribute_name(attr, *args)
7 def self.human_attribute_name(attr, *args)
8 attr = attr.to_s.sub(/_id$/, '')
8 attr = attr.to_s.sub(/_id$/, '')
9
9
10 l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr])
10 l("field_#{name.underscore.gsub('/', '_')}_#{attr}", :default => ["field_#{attr}".to_sym, attr])
11 end
11 end
12 end
12 end
13
13
14 # Undefines private Kernel#open method to allow using `open` scopes in models.
14 # Undefines private Kernel#open method to allow using `open` scopes in models.
15 # See Defect #11545 (http://www.redmine.org/issues/11545) for details.
15 # See Defect #11545 (http://www.redmine.org/issues/11545) for details.
16 class Base
16 class Base
17 class << self
17 class << self
18 undef open
18 undef open
19 end
19 end
20 end
20 end
21 class Relation ; undef open ; end
21 class Relation ; undef open ; end
22 end
22 end
23
23
24 module ActionView
24 module ActionView
25 module Helpers
25 module Helpers
26 module DateHelper
26 module DateHelper
27 # distance_of_time_in_words breaks when difference is greater than 30 years
27 # distance_of_time_in_words breaks when difference is greater than 30 years
28 def distance_of_date_in_words(from_date, to_date = 0, options = {})
28 def distance_of_date_in_words(from_date, to_date = 0, options = {})
29 from_date = from_date.to_date if from_date.respond_to?(:to_date)
29 from_date = from_date.to_date if from_date.respond_to?(:to_date)
30 to_date = to_date.to_date if to_date.respond_to?(:to_date)
30 to_date = to_date.to_date if to_date.respond_to?(:to_date)
31 distance_in_days = (to_date - from_date).abs
31 distance_in_days = (to_date - from_date).abs
32
32
33 I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
33 I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
34 case distance_in_days
34 case distance_in_days
35 when 0..60 then locale.t :x_days, :count => distance_in_days.round
35 when 0..60 then locale.t :x_days, :count => distance_in_days.round
36 when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round
36 when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round
37 else locale.t :over_x_years, :count => (distance_in_days / 365).floor
37 else locale.t :over_x_years, :count => (distance_in_days / 365).floor
38 end
38 end
39 end
39 end
40 end
40 end
41 end
41 end
42 end
42 end
43
43
44 class Resolver
44 class Resolver
45 def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
45 def find_all(name, prefix=nil, partial=false, details={}, key=nil, locals=[])
46 cached(key, [name, prefix, partial], details, locals) do
46 cached(key, [name, prefix, partial], details, locals) do
47 if details[:formats] & [:xml, :json]
47 if details[:formats] & [:xml, :json]
48 details = details.dup
48 details = details.dup
49 details[:formats] = details[:formats].dup + [:api]
49 details[:formats] = details[:formats].dup + [:api]
50 end
50 end
51 find_templates(name, prefix, partial, details)
51 find_templates(name, prefix, partial, details)
52 end
52 end
53 end
53 end
54 end
54 end
55 end
55 end
56
56
57 # Do not HTML escape text templates
57 # Do not HTML escape text templates
58 module ActionView
58 module ActionView
59 class Template
59 class Template
60 module Handlers
60 module Handlers
61 class ERB
61 class ERB
62 def call(template)
62 def call(template)
63 if template.source.encoding_aware?
63 if template.source.encoding_aware?
64 # First, convert to BINARY, so in case the encoding is
64 # First, convert to BINARY, so in case the encoding is
65 # wrong, we can still find an encoding tag
65 # wrong, we can still find an encoding tag
66 # (<%# encoding %>) inside the String using a regular
66 # (<%# encoding %>) inside the String using a regular
67 # expression
67 # expression
68 template_source = template.source.dup.force_encoding("BINARY")
68 template_source = template.source.dup.force_encoding("BINARY")
69
69
70 erb = template_source.gsub(ENCODING_TAG, '')
70 erb = template_source.gsub(ENCODING_TAG, '')
71 encoding = $2
71 encoding = $2
72
72
73 erb.force_encoding valid_encoding(template.source.dup, encoding)
73 erb.force_encoding valid_encoding(template.source.dup, encoding)
74
74
75 # Always make sure we return a String in the default_internal
75 # Always make sure we return a String in the default_internal
76 erb.encode!
76 erb.encode!
77 else
77 else
78 erb = template.source.dup
78 erb = template.source.dup
79 end
79 end
80
80
81 self.class.erb_implementation.new(
81 self.class.erb_implementation.new(
82 erb,
82 erb,
83 :trim => (self.class.erb_trim_mode == "-"),
83 :trim => (self.class.erb_trim_mode == "-"),
84 :escape => template.identifier =~ /\.text/ # only escape HTML templates
84 :escape => template.identifier =~ /\.text/ # only escape HTML templates
85 ).src
85 ).src
86 end
86 end
87 end
87 end
88 end
88 end
89 end
89 end
90 end
90 end
91
91
92 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe }
92 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| html_tag || ''.html_safe }
93
93
94 require 'mail'
94 require 'mail'
95
95
96 module DeliveryMethods
96 module DeliveryMethods
97 class AsyncSMTP < ::Mail::SMTP
97 class AsyncSMTP < ::Mail::SMTP
98 def deliver!(*args)
98 def deliver!(*args)
99 Thread.start do
99 Thread.start do
100 super *args
100 super *args
101 end
101 end
102 end
102 end
103 end
103 end
104
104
105 class AsyncSendmail < ::Mail::Sendmail
105 class AsyncSendmail < ::Mail::Sendmail
106 def deliver!(*args)
106 def deliver!(*args)
107 Thread.start do
107 Thread.start do
108 super *args
108 super *args
109 end
109 end
110 end
110 end
111 end
111 end
112
112
113 class TmpFile
113 class TmpFile
114 def initialize(*args); end
114 def initialize(*args); end
115
115
116 def deliver!(mail)
116 def deliver!(mail)
117 dest_dir = File.join(Rails.root, 'tmp', 'emails')
117 dest_dir = File.join(Rails.root, 'tmp', 'emails')
118 Dir.mkdir(dest_dir) unless File.directory?(dest_dir)
118 Dir.mkdir(dest_dir) unless File.directory?(dest_dir)
119 File.open(File.join(dest_dir, mail.message_id.gsub(/[<>]/, '') + '.eml'), 'wb') {|f| f.write(mail.encoded) }
119 File.open(File.join(dest_dir, mail.message_id.gsub(/[<>]/, '') + '.eml'), 'wb') {|f| f.write(mail.encoded) }
120 end
120 end
121 end
121 end
122 end
122 end
123
123
124 ActionMailer::Base.add_delivery_method :async_smtp, DeliveryMethods::AsyncSMTP
124 ActionMailer::Base.add_delivery_method :async_smtp, DeliveryMethods::AsyncSMTP
125 ActionMailer::Base.add_delivery_method :async_sendmail, DeliveryMethods::AsyncSendmail
125 ActionMailer::Base.add_delivery_method :async_sendmail, DeliveryMethods::AsyncSendmail
126 ActionMailer::Base.add_delivery_method :tmp_file, DeliveryMethods::TmpFile
126 ActionMailer::Base.add_delivery_method :tmp_file, DeliveryMethods::TmpFile
127
127
128 # Changes how sent emails are logged
129 # Rails doesn't log cc and bcc which is misleading when using bcc only (#12090)
130 module ActionMailer
131 class LogSubscriber < ActiveSupport::LogSubscriber
132 def deliver(event)
133 recipients = [:to, :cc, :bcc].inject("") do |s, header|
134 r = Array.wrap(event.payload[header])
135 if r.any?
136 s << "\n #{header}: #{r.join(', ')}"
137 end
138 s
139 end
140 info("\nSent email \"#{event.payload[:subject]}\" (%1.fms)#{recipients}" % event.duration)
141 debug(event.payload[:mail])
142 end
143 end
144 end
145
128 module ActionController
146 module ActionController
129 module MimeResponds
147 module MimeResponds
130 class Collector
148 class Collector
131 def api(&block)
149 def api(&block)
132 any(:xml, :json, &block)
150 any(:xml, :json, &block)
133 end
151 end
134 end
152 end
135 end
153 end
136 end
154 end
137
155
138 module ActionController
156 module ActionController
139 class Base
157 class Base
140 # Displays an explicit message instead of a NoMethodError exception
158 # Displays an explicit message instead of a NoMethodError exception
141 # when trying to start Redmine with an old session_store.rb
159 # when trying to start Redmine with an old session_store.rb
142 # TODO: remove it in a later version
160 # TODO: remove it in a later version
143 def self.session=(*args)
161 def self.session=(*args)
144 $stderr.puts "Please remove config/initializers/session_store.rb and run `rake generate_secret_token`.\n" +
162 $stderr.puts "Please remove config/initializers/session_store.rb and run `rake generate_secret_token`.\n" +
145 "Setting the session secret with ActionController.session= is no longer supported in Rails 3."
163 "Setting the session secret with ActionController.session= is no longer supported in Rails 3."
146 exit 1
164 exit 1
147 end
165 end
148 end
166 end
149 end
167 end
General Comments 0
You need to be logged in to leave comments. Login now