Project

General

Profile

Feature #5913 » mailer.rb

worked on 0.85 - Tudor Spinache, 2010-11-03 11:51

 
1
# of the License, or (at your option) any later version.
2
#
3
# This program is distributed in the hope that it will be useful,
4
# but WITHOUT ANY WARRANTY; without even the implied warranty of
5
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
6
# GNU General Public License for more details.
7
#
8
# You should have received a copy of the GNU General Public License
9
# along with this program; if not, write to the Free Software
10
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
11

    
12
class Mailer < ActionMailer::Base
13
  helper :application
14
  helper :issues
15
  helper :custom_fields
16

    
17
  include ActionController::UrlWriter
18

    
19
  def self.default_url_options
20
    h = Setting.host_name
21
    h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank?
22
    { :host => h, :protocol => Setting.protocol }
23
  end
24
  
25
  def issue_add(issue)
26
    redmine_headers 'Project' => issue.project.identifier,
27
                    'Issue-Id' => issue.id,
28
                    'Issue-Author' => issue.author.login
29
    redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
30
    recipients issue.recipients
31
    # ddumbugie
32
    from issue.author.mail if issue.author
33
    cc(issue.watcher_recipients - @recipients)
34
    subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
35
    body :issue => issue,
36
         :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
37
  end
38

    
39
  def issue_edit(journal)
40
    issue = journal.journalized
41
    redmine_headers 'Project' => issue.project.identifier,
42
                    'Issue-Id' => issue.id,
43
                    'Issue-Author' => issue.author.login
44
    redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
45
    @author = journal.user
46
    recipients issue.recipients
47
    # ddumbugie
48
    from journal.user.mail if journal.user
49
    # Watchers in cc
50
    cc(issue.watcher_recipients - @recipients)
51
    s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
52
    s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
53
    s << issue.subject
54
    subject s
55
    body :issue => issue,
56
         :journal => journal,
57
         :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
58
  end
59

    
60
  def reminder(user, issues, days)
61
    set_language_if_valid user.language
62
    recipients user.mail
63
    subject l(:mail_subject_reminder, issues.size)
64
    body :issues => issues,
65
         :days => days,
66
         :issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'due_date', :sort_order => 'asc')
67
  end
68

    
69
  def document_added(document)
70
    redmine_headers 'Project' => document.project.identifier
71
    recipients document.project.recipients
72
    # ddumbugie
73
    from document.attachments.first.author.mail if document.attachments.length > 1
74
    subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
75

    
76
#    added_to = ''
77
#    added_to_url = ''
78
#
79
#    if document.attachments
80
#      added_to_url = url_for(:controller => 'documents', :action => 'show', :id => document)
81
#      added_to = "#{l(:label_document)}: #{document.title}"
82
#    end
83
    body :document => document,
84
         :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
85
#,
86
#         :attachments => document.attachments,
87
#         :added_to => added_to,
88
#         :added_to_url => added_to_url
89
  end
90

    
91
  def attachments_added(attachments)
92
    # ddumbugie
93
    from attachments.first.author.mail if attachments.first.author
94
    container = attachments.first.container
95
    added_to = ''
96
    added_to_url = ''
97
    case container.class.name
98
    when 'Project'
99
      added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container)
100
      added_to = "#{l(:label_project)}: #{container}"
101
    when 'Version'
102
      added_to_url = url_for(:controller => 'projects', :action => 'list_files', :id => container.project_id)
103
      added_to = "#{l(:label_version)}: #{container.name}"
104
    when 'Document'
105
      added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
106
      added_to = "#{l(:label_document)}: #{container.title}"
107
    end
108
    redmine_headers 'Project' => container.project.identifier
109
    recipients container.project.recipients
110
    subject "[#{container.project.name}] #{l(:label_attachment_new)}"
111
    body :attachments => attachments,
112
         :added_to => added_to,
113
         :added_to_url => added_to_url
114
  end
115

    
116
  def news_added(news)
117
    # ddumbugie
118
    from news.author.mail if news.author
119
    redmine_headers 'Project' => news.project.identifier
120
    recipients news.project.recipients
121
    subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
122
    body :news => news,
123
         :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
124
  end
125

    
126
  def message_posted(message, recipients)
127
    # ddumbugie
128
    from message.author.mail if message.author
129
    redmine_headers 'Project' => message.project.identifier,
130
                    'Topic-Id' => (message.parent_id || message.id)
131
    recipients(recipients)
132
    subject "[#{message.board.project.name} - #{message.board.name}] #{message.subject}"
133
    body :message => message,
134
         :message_url => url_for(:controller => 'messages', :action => 'show', :board_id => message.board_id, :id => message.root)
135
  end
136

    
137
  def account_information(user, password)
138
    set_language_if_valid user.language
139
    recipients user.mail
140
    subject l(:mail_subject_register, Setting.app_title)
141
    body :user => user,
142
         :password => password,
143
         :login_url => url_for(:controller => 'account', :action => 'login')
144
  end
145

    
146
  def account_activation_request(user)
147
    # Send the email to all active administrators
148
    recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
149
    subject l(:mail_subject_account_activation_request, Setting.app_title)
150
    body :user => user,
151
         :url => url_for(:controller => 'users', :action => 'index', :status => User::STATUS_REGISTERED, :sort_key => 'created_on', :sort_order => 'desc')
152
  end
153

    
154
  # A registered user's account was activated by an administrator
155
  def account_activated(user)
156
    set_language_if_valid user.language
157
    recipients user.mail
158
    subject l(:mail_subject_register, Setting.app_title)
159
    body :user => user,
160
         :login_url => url_for(:controller => 'account', :action => 'login')
161
  end
162

    
163
  def lost_password(token)
164
    set_language_if_valid(token.user.language)
165
    recipients token.user.mail
166
    subject l(:mail_subject_lost_password, Setting.app_title)
167
    body :token => token,
168
         :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
169
  end
170

    
171
  def register(token)
172
    set_language_if_valid(token.user.language)
173
    recipients token.user.mail
174
    subject l(:mail_subject_register, Setting.app_title)
175
    body :token => token,
176
         :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
177
  end
178

    
179
  def test(user)
180
    set_language_if_valid(user.language)
181
    recipients user.mail
182
    subject 'Redmine test'
183
    body :url => url_for(:controller => 'welcome')
184
  end
185

    
186
  # Overrides default deliver! method to prevent from sending an email
187
  # with no recipient, cc or bcc
188
  def deliver!(mail = @mail)
189
    return false if (recipients.nil? || recipients.empty?) &&
190
                    (cc.nil? || cc.empty?) &&
191
                    (bcc.nil? || bcc.empty?)
192
    super
193
  end
194

    
195
  # Sends reminders to issue assignees
196
  # Available options:
197
  # * :days     => how many days in the future to remind about (defaults to 7)
198
  # * :tracker  => id of tracker for filtering issues (defaults to all trackers)
199
  # * :project  => id or identifier of project to process (defaults to all projects)
200
  def self.reminders(options={})
201
    days = options[:days] || 7
202
    project = options[:project] ? Project.find(options[:project]) : nil
203
    tracker = options[:tracker] ? Tracker.find(options[:tracker]) : nil
204

    
205
    s = ARCondition.new ["#{IssueStatus.table_name}.is_closed = ? AND #{Issue.table_name}.due_date <= ?", false, days.day.from_now.to_date]
206
    s << "#{Issue.table_name}.assigned_to_id IS NOT NULL"
207
    s << "#{Project.table_name}.status = #{Project::STATUS_ACTIVE}"
208
    s << "#{Issue.table_name}.project_id = #{project.id}" if project
209
    s << "#{Issue.table_name}.tracker_id = #{tracker.id}" if tracker
210

    
211
    issues_by_assignee = Issue.find(:all, :include => [:status, :assigned_to, :project, :tracker],
212
                                          :conditions => s.conditions
213
                                    ).group_by(&:assigned_to)
214
    issues_by_assignee.each do |assignee, issues|
215
      deliver_reminder(assignee, issues, days) unless assignee.nil?
216
    end
217
  end
218

    
219
  private
220
  def initialize_defaults(method_name)
221
    super
222
    set_language_if_valid Setting.default_language
223
    from Setting.mail_from
224
    
225
    # Common headers
226
    headers 'X-Mailer' => 'Redmine',
227
            'X-Redmine-Host' => Setting.host_name,
228
            'X-Redmine-Site' => Setting.app_title,
229
            'Precedence' => 'bulk',
230
            'Auto-Submitted' => 'auto-generated'
231
  end
232

    
233
  # Appends a Redmine header field (name is prepended with 'X-Redmine-')
234
  def redmine_headers(h)
235
    h.each { |k,v| headers["X-Redmine-#{k}"] = v }
236
  end
237

    
238
  # Overrides the create_mail method
239
  def create_mail
240
    # Removes the current user from the recipients and cc
241
    # if he doesn't want to receive notifications about what he does
242
    @author ||= User.current
243
    if @author.pref[:no_self_notified]
244
      recipients.delete(@author.mail) if recipients
245
      cc.delete(@author.mail) if cc
246
    end
247
    # Blind carbon copy recipients
248
    if Setting.bcc_recipients?
249
      bcc([recipients, cc].flatten.compact.uniq)
250
      recipients []
251
      cc []
252
    end
253
    super
254
  end
255

    
256
  # Renders a message with the corresponding layout
257
  def render_message(method_name, body)
258
    layout = method_name.match(%r{text\.html\.(rhtml|rxml)}) ? 'layout.text.html.rhtml' : 'layout.text.plain.rhtml'
259
    body[:content_for_layout] = render(:file => method_name, :body => body)
260
    ActionView::Base.new(template_root, body, self).render(:file => "mailer/#{layout}", :use_full_path => true)
261
  end
262

    
263
  # for the case of plain text only
264
  def body(*params)
265
    value = super(*params)
266
    if Setting.plain_text_mail?
267
      templates = Dir.glob("#{template_path}/#{@template}.text.plain.{rhtml,erb}")
268
      unless String === @body or templates.empty?
269
        template = File.basename(templates.first)
270
        @body[:content_for_layout] = render(:file => template, :body => @body)
271
        @body = ActionView::Base.new(template_root, @body, self).render(:file => "mailer/layout.text.plain.rhtml", :use_full_path => true)
272
        return @body
273
      end
274
    end
275
    return value
276
  end
277

    
278
  # Makes partial rendering work with Rails 1.2 (retro-compatibility)
279
  def self.controller_path
280
    ''
281
  end unless respond_to?('controller_path')
282
end
(1-1/4)