##// END OF EJS Templates
notifications: use a set initially instead of list later converted to set.
marcink -
r3273:97a79574 default
parent child Browse files
Show More
@@ -1,386 +1,385 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2011-2018 RhodeCode GmbH
3 # Copyright (C) 2011-2018 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21
21
22 """
22 """
23 Model for notifications
23 Model for notifications
24 """
24 """
25
25
26 import logging
26 import logging
27 import traceback
27 import traceback
28
28
29 from pyramid.threadlocal import get_current_request
29 from pyramid.threadlocal import get_current_request
30 from sqlalchemy.sql.expression import false, true
30 from sqlalchemy.sql.expression import false, true
31
31
32 import rhodecode
32 import rhodecode
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.model import BaseModel
34 from rhodecode.model import BaseModel
35 from rhodecode.model.db import Notification, User, UserNotification
35 from rhodecode.model.db import Notification, User, UserNotification
36 from rhodecode.model.meta import Session
36 from rhodecode.model.meta import Session
37 from rhodecode.translation import TranslationString
37 from rhodecode.translation import TranslationString
38
38
39 log = logging.getLogger(__name__)
39 log = logging.getLogger(__name__)
40
40
41
41
42 class NotificationModel(BaseModel):
42 class NotificationModel(BaseModel):
43
43
44 cls = Notification
44 cls = Notification
45
45
46 def __get_notification(self, notification):
46 def __get_notification(self, notification):
47 if isinstance(notification, Notification):
47 if isinstance(notification, Notification):
48 return notification
48 return notification
49 elif isinstance(notification, (int, long)):
49 elif isinstance(notification, (int, long)):
50 return Notification.get(notification)
50 return Notification.get(notification)
51 else:
51 else:
52 if notification:
52 if notification:
53 raise Exception('notification must be int, long or Instance'
53 raise Exception('notification must be int, long or Instance'
54 ' of Notification got %s' % type(notification))
54 ' of Notification got %s' % type(notification))
55
55
56 def create(
56 def create(
57 self, created_by, notification_subject, notification_body,
57 self, created_by, notification_subject, notification_body,
58 notification_type=Notification.TYPE_MESSAGE, recipients=None,
58 notification_type=Notification.TYPE_MESSAGE, recipients=None,
59 mention_recipients=None, with_email=True, email_kwargs=None):
59 mention_recipients=None, with_email=True, email_kwargs=None):
60 """
60 """
61
61
62 Creates notification of given type
62 Creates notification of given type
63
63
64 :param created_by: int, str or User instance. User who created this
64 :param created_by: int, str or User instance. User who created this
65 notification
65 notification
66 :param notification_subject: subject of notification itself
66 :param notification_subject: subject of notification itself
67 :param notification_body: body of notification text
67 :param notification_body: body of notification text
68 :param notification_type: type of notification, based on that we
68 :param notification_type: type of notification, based on that we
69 pick templates
69 pick templates
70
70
71 :param recipients: list of int, str or User objects, when None
71 :param recipients: list of int, str or User objects, when None
72 is given send to all admins
72 is given send to all admins
73 :param mention_recipients: list of int, str or User objects,
73 :param mention_recipients: list of int, str or User objects,
74 that were mentioned
74 that were mentioned
75 :param with_email: send email with this notification
75 :param with_email: send email with this notification
76 :param email_kwargs: dict with arguments to generate email
76 :param email_kwargs: dict with arguments to generate email
77 """
77 """
78
78
79 from rhodecode.lib.celerylib import tasks, run_task
79 from rhodecode.lib.celerylib import tasks, run_task
80
80
81 if recipients and not getattr(recipients, '__iter__', False):
81 if recipients and not getattr(recipients, '__iter__', False):
82 raise Exception('recipients must be an iterable object')
82 raise Exception('recipients must be an iterable object')
83
83
84 created_by_obj = self._get_user(created_by)
84 created_by_obj = self._get_user(created_by)
85 # default MAIN body if not given
85 # default MAIN body if not given
86 email_kwargs = email_kwargs or {'body': notification_body}
86 email_kwargs = email_kwargs or {'body': notification_body}
87 mention_recipients = mention_recipients or set()
87 mention_recipients = mention_recipients or set()
88
88
89 if not created_by_obj:
89 if not created_by_obj:
90 raise Exception('unknown user %s' % created_by)
90 raise Exception('unknown user %s' % created_by)
91
91
92 if recipients is None:
92 if recipients is None:
93 # recipients is None means to all admins
93 # recipients is None means to all admins
94 recipients_objs = User.query().filter(User.admin == true()).all()
94 recipients_objs = User.query().filter(User.admin == true()).all()
95 log.debug('sending notifications %s to admins: %s',
95 log.debug('sending notifications %s to admins: %s',
96 notification_type, recipients_objs)
96 notification_type, recipients_objs)
97 else:
97 else:
98 recipients_objs = []
98 recipients_objs = set()
99 for u in recipients:
99 for u in recipients:
100 obj = self._get_user(u)
100 obj = self._get_user(u)
101 if obj:
101 if obj:
102 recipients_objs.append(obj)
102 recipients_objs.add(obj)
103 else: # we didn't find this user, log the error and carry on
103 else: # we didn't find this user, log the error and carry on
104 log.error('cannot notify unknown user %r', u)
104 log.error('cannot notify unknown user %r', u)
105
105
106 recipients_objs = set(recipients_objs)
107 if not recipients_objs:
106 if not recipients_objs:
108 raise Exception('no valid recipients specified')
107 raise Exception('no valid recipients specified')
109
108
110 log.debug('sending notifications %s to %s',
109 log.debug('sending notifications %s to %s',
111 notification_type, recipients_objs)
110 notification_type, recipients_objs)
112
111
113 # add mentioned users into recipients
112 # add mentioned users into recipients
114 final_recipients = set(recipients_objs).union(mention_recipients)
113 final_recipients = set(recipients_objs).union(mention_recipients)
115 notification = Notification.create(
114 notification = Notification.create(
116 created_by=created_by_obj, subject=notification_subject,
115 created_by=created_by_obj, subject=notification_subject,
117 body=notification_body, recipients=final_recipients,
116 body=notification_body, recipients=final_recipients,
118 type_=notification_type
117 type_=notification_type
119 )
118 )
120
119
121 if not with_email: # skip sending email, and just create notification
120 if not with_email: # skip sending email, and just create notification
122 return notification
121 return notification
123
122
124 # don't send email to person who created this comment
123 # don't send email to person who created this comment
125 rec_objs = set(recipients_objs).difference(set([created_by_obj]))
124 rec_objs = set(recipients_objs).difference({created_by_obj})
126
125
127 # now notify all recipients in question
126 # now notify all recipients in question
128
127
129 for recipient in rec_objs.union(mention_recipients):
128 for recipient in rec_objs.union(mention_recipients):
130 # inject current recipient
129 # inject current recipient
131 email_kwargs['recipient'] = recipient
130 email_kwargs['recipient'] = recipient
132 email_kwargs['mention'] = recipient in mention_recipients
131 email_kwargs['mention'] = recipient in mention_recipients
133 (subject, headers, email_body,
132 (subject, headers, email_body,
134 email_body_plaintext) = EmailNotificationModel().render_email(
133 email_body_plaintext) = EmailNotificationModel().render_email(
135 notification_type, **email_kwargs)
134 notification_type, **email_kwargs)
136
135
137 log.debug(
136 log.debug(
138 'Creating notification email task for user:`%s`', recipient)
137 'Creating notification email task for user:`%s`', recipient)
139 task = run_task(
138 task = run_task(
140 tasks.send_email, recipient.email, subject,
139 tasks.send_email, recipient.email, subject,
141 email_body_plaintext, email_body)
140 email_body_plaintext, email_body)
142 log.debug('Created email task: %s', task)
141 log.debug('Created email task: %s', task)
143
142
144 return notification
143 return notification
145
144
146 def delete(self, user, notification):
145 def delete(self, user, notification):
147 # we don't want to remove actual notification just the assignment
146 # we don't want to remove actual notification just the assignment
148 try:
147 try:
149 notification = self.__get_notification(notification)
148 notification = self.__get_notification(notification)
150 user = self._get_user(user)
149 user = self._get_user(user)
151 if notification and user:
150 if notification and user:
152 obj = UserNotification.query()\
151 obj = UserNotification.query()\
153 .filter(UserNotification.user == user)\
152 .filter(UserNotification.user == user)\
154 .filter(UserNotification.notification == notification)\
153 .filter(UserNotification.notification == notification)\
155 .one()
154 .one()
156 Session().delete(obj)
155 Session().delete(obj)
157 return True
156 return True
158 except Exception:
157 except Exception:
159 log.error(traceback.format_exc())
158 log.error(traceback.format_exc())
160 raise
159 raise
161
160
162 def get_for_user(self, user, filter_=None):
161 def get_for_user(self, user, filter_=None):
163 """
162 """
164 Get mentions for given user, filter them if filter dict is given
163 Get mentions for given user, filter them if filter dict is given
165 """
164 """
166 user = self._get_user(user)
165 user = self._get_user(user)
167
166
168 q = UserNotification.query()\
167 q = UserNotification.query()\
169 .filter(UserNotification.user == user)\
168 .filter(UserNotification.user == user)\
170 .join((
169 .join((
171 Notification, UserNotification.notification_id ==
170 Notification, UserNotification.notification_id ==
172 Notification.notification_id))
171 Notification.notification_id))
173 if filter_ == ['all']:
172 if filter_ == ['all']:
174 q = q # no filter
173 q = q # no filter
175 elif filter_ == ['unread']:
174 elif filter_ == ['unread']:
176 q = q.filter(UserNotification.read == false())
175 q = q.filter(UserNotification.read == false())
177 elif filter_:
176 elif filter_:
178 q = q.filter(Notification.type_.in_(filter_))
177 q = q.filter(Notification.type_.in_(filter_))
179
178
180 return q
179 return q
181
180
182 def mark_read(self, user, notification):
181 def mark_read(self, user, notification):
183 try:
182 try:
184 notification = self.__get_notification(notification)
183 notification = self.__get_notification(notification)
185 user = self._get_user(user)
184 user = self._get_user(user)
186 if notification and user:
185 if notification and user:
187 obj = UserNotification.query()\
186 obj = UserNotification.query()\
188 .filter(UserNotification.user == user)\
187 .filter(UserNotification.user == user)\
189 .filter(UserNotification.notification == notification)\
188 .filter(UserNotification.notification == notification)\
190 .one()
189 .one()
191 obj.read = True
190 obj.read = True
192 Session().add(obj)
191 Session().add(obj)
193 return True
192 return True
194 except Exception:
193 except Exception:
195 log.error(traceback.format_exc())
194 log.error(traceback.format_exc())
196 raise
195 raise
197
196
198 def mark_all_read_for_user(self, user, filter_=None):
197 def mark_all_read_for_user(self, user, filter_=None):
199 user = self._get_user(user)
198 user = self._get_user(user)
200 q = UserNotification.query()\
199 q = UserNotification.query()\
201 .filter(UserNotification.user == user)\
200 .filter(UserNotification.user == user)\
202 .filter(UserNotification.read == false())\
201 .filter(UserNotification.read == false())\
203 .join((
202 .join((
204 Notification, UserNotification.notification_id ==
203 Notification, UserNotification.notification_id ==
205 Notification.notification_id))
204 Notification.notification_id))
206 if filter_ == ['unread']:
205 if filter_ == ['unread']:
207 q = q.filter(UserNotification.read == false())
206 q = q.filter(UserNotification.read == false())
208 elif filter_:
207 elif filter_:
209 q = q.filter(Notification.type_.in_(filter_))
208 q = q.filter(Notification.type_.in_(filter_))
210
209
211 # this is a little inefficient but sqlalchemy doesn't support
210 # this is a little inefficient but sqlalchemy doesn't support
212 # update on joined tables :(
211 # update on joined tables :(
213 for obj in q.all():
212 for obj in q.all():
214 obj.read = True
213 obj.read = True
215 Session().add(obj)
214 Session().add(obj)
216
215
217 def get_unread_cnt_for_user(self, user):
216 def get_unread_cnt_for_user(self, user):
218 user = self._get_user(user)
217 user = self._get_user(user)
219 return UserNotification.query()\
218 return UserNotification.query()\
220 .filter(UserNotification.read == false())\
219 .filter(UserNotification.read == false())\
221 .filter(UserNotification.user == user).count()
220 .filter(UserNotification.user == user).count()
222
221
223 def get_unread_for_user(self, user):
222 def get_unread_for_user(self, user):
224 user = self._get_user(user)
223 user = self._get_user(user)
225 return [x.notification for x in UserNotification.query()
224 return [x.notification for x in UserNotification.query()
226 .filter(UserNotification.read == false())
225 .filter(UserNotification.read == false())
227 .filter(UserNotification.user == user).all()]
226 .filter(UserNotification.user == user).all()]
228
227
229 def get_user_notification(self, user, notification):
228 def get_user_notification(self, user, notification):
230 user = self._get_user(user)
229 user = self._get_user(user)
231 notification = self.__get_notification(notification)
230 notification = self.__get_notification(notification)
232
231
233 return UserNotification.query()\
232 return UserNotification.query()\
234 .filter(UserNotification.notification == notification)\
233 .filter(UserNotification.notification == notification)\
235 .filter(UserNotification.user == user).scalar()
234 .filter(UserNotification.user == user).scalar()
236
235
237 def make_description(self, notification, translate, show_age=True):
236 def make_description(self, notification, translate, show_age=True):
238 """
237 """
239 Creates a human readable description based on properties
238 Creates a human readable description based on properties
240 of notification object
239 of notification object
241 """
240 """
242 _ = translate
241 _ = translate
243 _map = {
242 _map = {
244 notification.TYPE_CHANGESET_COMMENT: [
243 notification.TYPE_CHANGESET_COMMENT: [
245 _('%(user)s commented on commit %(date_or_age)s'),
244 _('%(user)s commented on commit %(date_or_age)s'),
246 _('%(user)s commented on commit at %(date_or_age)s'),
245 _('%(user)s commented on commit at %(date_or_age)s'),
247 ],
246 ],
248 notification.TYPE_MESSAGE: [
247 notification.TYPE_MESSAGE: [
249 _('%(user)s sent message %(date_or_age)s'),
248 _('%(user)s sent message %(date_or_age)s'),
250 _('%(user)s sent message at %(date_or_age)s'),
249 _('%(user)s sent message at %(date_or_age)s'),
251 ],
250 ],
252 notification.TYPE_MENTION: [
251 notification.TYPE_MENTION: [
253 _('%(user)s mentioned you %(date_or_age)s'),
252 _('%(user)s mentioned you %(date_or_age)s'),
254 _('%(user)s mentioned you at %(date_or_age)s'),
253 _('%(user)s mentioned you at %(date_or_age)s'),
255 ],
254 ],
256 notification.TYPE_REGISTRATION: [
255 notification.TYPE_REGISTRATION: [
257 _('%(user)s registered in RhodeCode %(date_or_age)s'),
256 _('%(user)s registered in RhodeCode %(date_or_age)s'),
258 _('%(user)s registered in RhodeCode at %(date_or_age)s'),
257 _('%(user)s registered in RhodeCode at %(date_or_age)s'),
259 ],
258 ],
260 notification.TYPE_PULL_REQUEST: [
259 notification.TYPE_PULL_REQUEST: [
261 _('%(user)s opened new pull request %(date_or_age)s'),
260 _('%(user)s opened new pull request %(date_or_age)s'),
262 _('%(user)s opened new pull request at %(date_or_age)s'),
261 _('%(user)s opened new pull request at %(date_or_age)s'),
263 ],
262 ],
264 notification.TYPE_PULL_REQUEST_COMMENT: [
263 notification.TYPE_PULL_REQUEST_COMMENT: [
265 _('%(user)s commented on pull request %(date_or_age)s'),
264 _('%(user)s commented on pull request %(date_or_age)s'),
266 _('%(user)s commented on pull request at %(date_or_age)s'),
265 _('%(user)s commented on pull request at %(date_or_age)s'),
267 ],
266 ],
268 }
267 }
269
268
270 templates = _map[notification.type_]
269 templates = _map[notification.type_]
271
270
272 if show_age:
271 if show_age:
273 template = templates[0]
272 template = templates[0]
274 date_or_age = h.age(notification.created_on)
273 date_or_age = h.age(notification.created_on)
275 if translate:
274 if translate:
276 date_or_age = translate(date_or_age)
275 date_or_age = translate(date_or_age)
277
276
278 if isinstance(date_or_age, TranslationString):
277 if isinstance(date_or_age, TranslationString):
279 date_or_age = date_or_age.interpolate()
278 date_or_age = date_or_age.interpolate()
280
279
281 else:
280 else:
282 template = templates[1]
281 template = templates[1]
283 date_or_age = h.format_date(notification.created_on)
282 date_or_age = h.format_date(notification.created_on)
284
283
285 return template % {
284 return template % {
286 'user': notification.created_by_user.username,
285 'user': notification.created_by_user.username,
287 'date_or_age': date_or_age,
286 'date_or_age': date_or_age,
288 }
287 }
289
288
290
289
291 class EmailNotificationModel(BaseModel):
290 class EmailNotificationModel(BaseModel):
292 TYPE_COMMIT_COMMENT = Notification.TYPE_CHANGESET_COMMENT
291 TYPE_COMMIT_COMMENT = Notification.TYPE_CHANGESET_COMMENT
293 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
292 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
294 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
293 TYPE_PULL_REQUEST = Notification.TYPE_PULL_REQUEST
295 TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT
294 TYPE_PULL_REQUEST_COMMENT = Notification.TYPE_PULL_REQUEST_COMMENT
296 TYPE_MAIN = Notification.TYPE_MESSAGE
295 TYPE_MAIN = Notification.TYPE_MESSAGE
297
296
298 TYPE_PASSWORD_RESET = 'password_reset'
297 TYPE_PASSWORD_RESET = 'password_reset'
299 TYPE_PASSWORD_RESET_CONFIRMATION = 'password_reset_confirmation'
298 TYPE_PASSWORD_RESET_CONFIRMATION = 'password_reset_confirmation'
300 TYPE_EMAIL_TEST = 'email_test'
299 TYPE_EMAIL_TEST = 'email_test'
301 TYPE_TEST = 'test'
300 TYPE_TEST = 'test'
302
301
303 email_types = {
302 email_types = {
304 TYPE_MAIN:
303 TYPE_MAIN:
305 'rhodecode:templates/email_templates/main.mako',
304 'rhodecode:templates/email_templates/main.mako',
306 TYPE_TEST:
305 TYPE_TEST:
307 'rhodecode:templates/email_templates/test.mako',
306 'rhodecode:templates/email_templates/test.mako',
308 TYPE_EMAIL_TEST:
307 TYPE_EMAIL_TEST:
309 'rhodecode:templates/email_templates/email_test.mako',
308 'rhodecode:templates/email_templates/email_test.mako',
310 TYPE_REGISTRATION:
309 TYPE_REGISTRATION:
311 'rhodecode:templates/email_templates/user_registration.mako',
310 'rhodecode:templates/email_templates/user_registration.mako',
312 TYPE_PASSWORD_RESET:
311 TYPE_PASSWORD_RESET:
313 'rhodecode:templates/email_templates/password_reset.mako',
312 'rhodecode:templates/email_templates/password_reset.mako',
314 TYPE_PASSWORD_RESET_CONFIRMATION:
313 TYPE_PASSWORD_RESET_CONFIRMATION:
315 'rhodecode:templates/email_templates/password_reset_confirmation.mako',
314 'rhodecode:templates/email_templates/password_reset_confirmation.mako',
316 TYPE_COMMIT_COMMENT:
315 TYPE_COMMIT_COMMENT:
317 'rhodecode:templates/email_templates/commit_comment.mako',
316 'rhodecode:templates/email_templates/commit_comment.mako',
318 TYPE_PULL_REQUEST:
317 TYPE_PULL_REQUEST:
319 'rhodecode:templates/email_templates/pull_request_review.mako',
318 'rhodecode:templates/email_templates/pull_request_review.mako',
320 TYPE_PULL_REQUEST_COMMENT:
319 TYPE_PULL_REQUEST_COMMENT:
321 'rhodecode:templates/email_templates/pull_request_comment.mako',
320 'rhodecode:templates/email_templates/pull_request_comment.mako',
322 }
321 }
323
322
324 def __init__(self):
323 def __init__(self):
325 """
324 """
326 Example usage::
325 Example usage::
327
326
328 (subject, headers, email_body,
327 (subject, headers, email_body,
329 email_body_plaintext) = EmailNotificationModel().render_email(
328 email_body_plaintext) = EmailNotificationModel().render_email(
330 EmailNotificationModel.TYPE_TEST, **email_kwargs)
329 EmailNotificationModel.TYPE_TEST, **email_kwargs)
331
330
332 """
331 """
333 super(EmailNotificationModel, self).__init__()
332 super(EmailNotificationModel, self).__init__()
334 self.rhodecode_instance_name = rhodecode.CONFIG.get('rhodecode_title')
333 self.rhodecode_instance_name = rhodecode.CONFIG.get('rhodecode_title')
335
334
336 def _update_kwargs_for_render(self, kwargs):
335 def _update_kwargs_for_render(self, kwargs):
337 """
336 """
338 Inject params required for Mako rendering
337 Inject params required for Mako rendering
339
338
340 :param kwargs:
339 :param kwargs:
341 """
340 """
342
341
343 kwargs['rhodecode_instance_name'] = self.rhodecode_instance_name
342 kwargs['rhodecode_instance_name'] = self.rhodecode_instance_name
344 instance_url = h.route_url('home')
343 instance_url = h.route_url('home')
345 _kwargs = {
344 _kwargs = {
346 'instance_url': instance_url,
345 'instance_url': instance_url,
347 'whitespace_filter': self.whitespace_filter
346 'whitespace_filter': self.whitespace_filter
348 }
347 }
349 _kwargs.update(kwargs)
348 _kwargs.update(kwargs)
350 return _kwargs
349 return _kwargs
351
350
352 def whitespace_filter(self, text):
351 def whitespace_filter(self, text):
353 return text.replace('\n', '').replace('\t', '')
352 return text.replace('\n', '').replace('\t', '')
354
353
355 def get_renderer(self, type_, request):
354 def get_renderer(self, type_, request):
356 template_name = self.email_types[type_]
355 template_name = self.email_types[type_]
357 return request.get_partial_renderer(template_name)
356 return request.get_partial_renderer(template_name)
358
357
359 def render_email(self, type_, **kwargs):
358 def render_email(self, type_, **kwargs):
360 """
359 """
361 renders template for email, and returns a tuple of
360 renders template for email, and returns a tuple of
362 (subject, email_headers, email_html_body, email_plaintext_body)
361 (subject, email_headers, email_html_body, email_plaintext_body)
363 """
362 """
364 # translator and helpers inject
363 # translator and helpers inject
365 _kwargs = self._update_kwargs_for_render(kwargs)
364 _kwargs = self._update_kwargs_for_render(kwargs)
366 request = get_current_request()
365 request = get_current_request()
367 email_template = self.get_renderer(type_, request=request)
366 email_template = self.get_renderer(type_, request=request)
368
367
369 subject = email_template.render('subject', **_kwargs)
368 subject = email_template.render('subject', **_kwargs)
370
369
371 try:
370 try:
372 headers = email_template.render('headers', **_kwargs)
371 headers = email_template.render('headers', **_kwargs)
373 except AttributeError:
372 except AttributeError:
374 # it's not defined in template, ok we can skip it
373 # it's not defined in template, ok we can skip it
375 headers = ''
374 headers = ''
376
375
377 try:
376 try:
378 body_plaintext = email_template.render('body_plaintext', **_kwargs)
377 body_plaintext = email_template.render('body_plaintext', **_kwargs)
379 except AttributeError:
378 except AttributeError:
380 # it's not defined in template, ok we can skip it
379 # it's not defined in template, ok we can skip it
381 body_plaintext = ''
380 body_plaintext = ''
382
381
383 # render WHOLE template
382 # render WHOLE template
384 body = email_template.render(None, **_kwargs)
383 body = email_template.render(None, **_kwargs)
385
384
386 return subject, headers, body, body_plaintext
385 return subject, headers, body, body_plaintext
General Comments 0
You need to be logged in to leave comments. Login now