Show More
@@ -578,8 +578,7 b' class AdminSettingsView(BaseAppView):' | |||||
578 | 'user': self._rhodecode_db_user |
|
578 | 'user': self._rhodecode_db_user | |
579 | } |
|
579 | } | |
580 |
|
580 | |||
581 | (subject, headers, email_body, |
|
581 | (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email( | |
582 | email_body_plaintext) = EmailNotificationModel().render_email( |
|
|||
583 | EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs) |
|
582 | EmailNotificationModel.TYPE_EMAIL_TEST, **email_kwargs) | |
584 |
|
583 | |||
585 | recipients = [test_email] if test_email else None |
|
584 | recipients = [test_email] if test_email else None |
@@ -376,8 +376,7 b' users: description edit fixes' | |||||
376 | } |
|
376 | } | |
377 |
|
377 | |||
378 | template_type = email_id.split('+')[0] |
|
378 | template_type = email_id.split('+')[0] | |
379 | (c.subject, c.headers, c.email_body, |
|
379 | (c.subject, c.email_body, c.email_body_plaintext) = EmailNotificationModel().render_email( | |
380 | c.email_body_plaintext) = EmailNotificationModel().render_email( |
|
|||
381 | template_type, **email_kwargs.get(email_id, {})) |
|
380 | template_type, **email_kwargs.get(email_id, {})) | |
382 |
|
381 | |||
383 | test_email = self.request.GET.get('email') |
|
382 | test_email = self.request.GET.get('email') |
@@ -29,6 +29,7 b' import time' | |||||
29 | from pyramid import compat |
|
29 | from pyramid import compat | |
30 | from pyramid_mailer.mailer import Mailer |
|
30 | from pyramid_mailer.mailer import Mailer | |
31 | from pyramid_mailer.message import Message |
|
31 | from pyramid_mailer.message import Message | |
|
32 | from email.utils import formatdate | |||
32 |
|
33 | |||
33 | import rhodecode |
|
34 | import rhodecode | |
34 | from rhodecode.lib import audit_logger |
|
35 | from rhodecode.lib import audit_logger | |
@@ -40,7 +41,8 b' from rhodecode.model.db import (' | |||||
40 |
|
41 | |||
41 |
|
42 | |||
42 | @async_task(ignore_result=True, base=RequestContextTask) |
|
43 | @async_task(ignore_result=True, base=RequestContextTask) | |
43 |
def send_email(recipients, subject, body='', html_body='', email_config=None |
|
44 | def send_email(recipients, subject, body='', html_body='', email_config=None, | |
|
45 | extra_headers=None): | |||
44 | """ |
|
46 | """ | |
45 | Sends an email with defined parameters from the .ini files. |
|
47 | Sends an email with defined parameters from the .ini files. | |
46 |
|
48 | |||
@@ -50,6 +52,7 b' def send_email(recipients, subject, body' | |||||
50 | :param body: body of the mail |
|
52 | :param body: body of the mail | |
51 | :param html_body: html version of body |
|
53 | :param html_body: html version of body | |
52 | :param email_config: specify custom configuration for mailer |
|
54 | :param email_config: specify custom configuration for mailer | |
|
55 | :param extra_headers: specify custom headers | |||
53 | """ |
|
56 | """ | |
54 | log = get_logger(send_email) |
|
57 | log = get_logger(send_email) | |
55 |
|
58 | |||
@@ -108,13 +111,23 b' def send_email(recipients, subject, body' | |||||
108 | # sendmail_template='', |
|
111 | # sendmail_template='', | |
109 | ) |
|
112 | ) | |
110 |
|
113 | |||
|
114 | if extra_headers is None: | |||
|
115 | extra_headers = {} | |||
|
116 | ||||
|
117 | extra_headers.setdefault('Date', formatdate(time.time())) | |||
|
118 | ||||
|
119 | if 'thread_ids' in extra_headers: | |||
|
120 | thread_ids = extra_headers.pop('thread_ids') | |||
|
121 | extra_headers['References'] = ' '.join('<{}>'.format(t) for t in thread_ids) | |||
|
122 | ||||
111 | try: |
|
123 | try: | |
112 | mailer = Mailer(**email_conf) |
|
124 | mailer = Mailer(**email_conf) | |
113 |
|
125 | |||
114 | message = Message(subject=subject, |
|
126 | message = Message(subject=subject, | |
115 | sender=email_conf['default_sender'], |
|
127 | sender=email_conf['default_sender'], | |
116 | recipients=recipients, |
|
128 | recipients=recipients, | |
117 |
body=body, html=html_body |
|
129 | body=body, html=html_body, | |
|
130 | extra_headers=extra_headers) | |||
118 | mailer.send_immediately(message) |
|
131 | mailer.send_immediately(message) | |
119 |
|
132 | |||
120 | except Exception: |
|
133 | except Exception: |
@@ -143,8 +143,7 b' def send_exc_email(request, exc_id, exc_' | |||||
143 | 'exc_traceback': read_exception(exc_id, prefix=None), |
|
143 | 'exc_traceback': read_exception(exc_id, prefix=None), | |
144 | } |
|
144 | } | |
145 |
|
145 | |||
146 | (subject, headers, email_body, |
|
146 | (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email( | |
147 | email_body_plaintext) = EmailNotificationModel().render_email( |
|
|||
148 | EmailNotificationModel.TYPE_EMAIL_EXCEPTION, **email_kwargs) |
|
147 | EmailNotificationModel.TYPE_EMAIL_EXCEPTION, **email_kwargs) | |
149 |
|
148 | |||
150 | run_task(tasks.send_email, recipients, subject, |
|
149 | run_task(tasks.send_email, recipients, subject, |
@@ -370,13 +370,18 b' class CommentsModel(BaseModel):' | |||||
370 | repo.repo_name, |
|
370 | repo.repo_name, | |
371 | h.route_url('repo_summary', repo_name=repo.repo_name)) |
|
371 | h.route_url('repo_summary', repo_name=repo.repo_name)) | |
372 |
|
372 | |||
|
373 | commit_url = h.route_url('repo_commit', repo_name=repo.repo_name, | |||
|
374 | commit_id=commit_id) | |||
|
375 | ||||
373 | # commit specifics |
|
376 | # commit specifics | |
374 | kwargs.update({ |
|
377 | kwargs.update({ | |
375 | 'commit': commit_obj, |
|
378 | 'commit': commit_obj, | |
376 | 'commit_message': commit_obj.message, |
|
379 | 'commit_message': commit_obj.message, | |
377 | 'commit_target_repo_url': target_repo_url, |
|
380 | 'commit_target_repo_url': target_repo_url, | |
378 | 'commit_comment_url': commit_comment_url, |
|
381 | 'commit_comment_url': commit_comment_url, | |
379 | 'commit_comment_reply_url': commit_comment_reply_url |
|
382 | 'commit_comment_reply_url': commit_comment_reply_url, | |
|
383 | 'commit_url': commit_url, | |||
|
384 | 'thread_ids': [commit_url, commit_comment_url], | |||
380 | }) |
|
385 | }) | |
381 |
|
386 | |||
382 | elif pull_request_obj: |
|
387 | elif pull_request_obj: | |
@@ -421,15 +426,14 b' class CommentsModel(BaseModel):' | |||||
421 | 'pr_comment_url': pr_comment_url, |
|
426 | 'pr_comment_url': pr_comment_url, | |
422 | 'pr_comment_reply_url': pr_comment_reply_url, |
|
427 | 'pr_comment_reply_url': pr_comment_reply_url, | |
423 | 'pr_closing': closing_pr, |
|
428 | 'pr_closing': closing_pr, | |
|
429 | 'thread_ids': [pr_url, pr_comment_url], | |||
424 | }) |
|
430 | }) | |
425 |
|
431 | |||
426 | recipients += [self._get_user(u) for u in (extra_recipients or [])] |
|
432 | recipients += [self._get_user(u) for u in (extra_recipients or [])] | |
427 |
|
433 | |||
428 | if send_email: |
|
434 | if send_email: | |
429 | # pre-generate the subject for notification itself |
|
435 | # pre-generate the subject for notification itself | |
430 | (subject, |
|
436 | (subject, _e, body_plaintext) = EmailNotificationModel().render_email( | |
431 | _h, _e, # we don't care about those |
|
|||
432 | body_plaintext) = EmailNotificationModel().render_email( |
|
|||
433 | notification_type, **kwargs) |
|
437 | notification_type, **kwargs) | |
434 |
|
438 | |||
435 | mention_recipients = set( |
|
439 | mention_recipients = set( |
@@ -131,15 +131,17 b' class NotificationModel(BaseModel):' | |||||
131 | # inject current recipient |
|
131 | # inject current recipient | |
132 | email_kwargs['recipient'] = recipient |
|
132 | email_kwargs['recipient'] = recipient | |
133 | email_kwargs['mention'] = recipient in mention_recipients |
|
133 | email_kwargs['mention'] = recipient in mention_recipients | |
134 | (subject, headers, email_body, |
|
134 | (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email( | |
135 | email_body_plaintext) = EmailNotificationModel().render_email( |
|
|||
136 | notification_type, **email_kwargs) |
|
135 | notification_type, **email_kwargs) | |
137 |
|
136 | |||
138 | log.debug( |
|
137 | extra_headers = None | |
139 | 'Creating notification email task for user:`%s`', recipient) |
|
138 | if 'thread_ids' in email_kwargs: | |
|
139 | extra_headers = {'thread_ids': email_kwargs.pop('thread_ids')} | |||
|
140 | ||||
|
141 | log.debug('Creating notification email task for user:`%s`', recipient) | |||
140 | task = run_task( |
|
142 | task = run_task( | |
141 | tasks.send_email, recipient.email, subject, |
|
143 | tasks.send_email, recipient.email, subject, | |
142 | email_body_plaintext, email_body) |
|
144 | email_body_plaintext, email_body, extra_headers=extra_headers) | |
143 | log.debug('Created email task: %s', task) |
|
145 | log.debug('Created email task: %s', task) | |
144 |
|
146 | |||
145 | return notification |
|
147 | return notification | |
@@ -342,8 +344,7 b' class EmailNotificationModel(BaseModel):' | |||||
342 | """ |
|
344 | """ | |
343 | Example usage:: |
|
345 | Example usage:: | |
344 |
|
346 | |||
345 | (subject, headers, email_body, |
|
347 | (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email( | |
346 | email_body_plaintext) = EmailNotificationModel().render_email( |
|
|||
347 | EmailNotificationModel.TYPE_TEST, **email_kwargs) |
|
348 | EmailNotificationModel.TYPE_TEST, **email_kwargs) | |
348 |
|
349 | |||
349 | """ |
|
350 | """ | |
@@ -387,12 +388,6 b' class EmailNotificationModel(BaseModel):' | |||||
387 | subject = email_template.render('subject', **_kwargs) |
|
388 | subject = email_template.render('subject', **_kwargs) | |
388 |
|
389 | |||
389 | try: |
|
390 | try: | |
390 | headers = email_template.render('headers', **_kwargs) |
|
|||
391 | except AttributeError: |
|
|||
392 | # it's not defined in template, ok we can skip it |
|
|||
393 | headers = '' |
|
|||
394 |
|
||||
395 | try: |
|
|||
396 | body_plaintext = email_template.render('body_plaintext', **_kwargs) |
|
391 | body_plaintext = email_template.render('body_plaintext', **_kwargs) | |
397 | except AttributeError: |
|
392 | except AttributeError: | |
398 | # it's not defined in template, ok we can skip it |
|
393 | # it's not defined in template, ok we can skip it | |
@@ -408,4 +403,4 b' class EmailNotificationModel(BaseModel):' | |||||
408 | log.exception('Failed to parse body with premailer') |
|
403 | log.exception('Failed to parse body with premailer') | |
409 | pass |
|
404 | pass | |
410 |
|
405 | |||
411 |
return subject, |
|
406 | return subject, body, body_plaintext |
@@ -1344,12 +1344,11 b' class PullRequestModel(BaseModel):' | |||||
1344 | 'pull_request_source_repo_url': pr_source_repo_url, |
|
1344 | 'pull_request_source_repo_url': pr_source_repo_url, | |
1345 |
|
1345 | |||
1346 | 'pull_request_url': pr_url, |
|
1346 | 'pull_request_url': pr_url, | |
|
1347 | 'thread_ids': [pr_url], | |||
1347 | } |
|
1348 | } | |
1348 |
|
1349 | |||
1349 | # pre-generate the subject for notification itself |
|
1350 | # pre-generate the subject for notification itself | |
1350 | (subject, |
|
1351 | (subject, _e, body_plaintext) = EmailNotificationModel().render_email( | |
1351 | _h, _e, # we don't care about those |
|
|||
1352 | body_plaintext) = EmailNotificationModel().render_email( |
|
|||
1353 | notification_type, **kwargs) |
|
1352 | notification_type, **kwargs) | |
1354 |
|
1353 | |||
1355 | # create notification objects, and emails |
|
1354 | # create notification objects, and emails | |
@@ -1414,11 +1413,10 b' class PullRequestModel(BaseModel):' | |||||
1414 | 'added_files': file_changes.added, |
|
1413 | 'added_files': file_changes.added, | |
1415 | 'modified_files': file_changes.modified, |
|
1414 | 'modified_files': file_changes.modified, | |
1416 | 'removed_files': file_changes.removed, |
|
1415 | 'removed_files': file_changes.removed, | |
|
1416 | 'thread_ids': [pr_url], | |||
1417 | } |
|
1417 | } | |
1418 |
|
1418 | |||
1419 | (subject, |
|
1419 | (subject, _e, body_plaintext) = EmailNotificationModel().render_email( | |
1420 | _h, _e, # we don't care about those |
|
|||
1421 | body_plaintext) = EmailNotificationModel().render_email( |
|
|||
1422 | EmailNotificationModel.TYPE_PULL_REQUEST_UPDATE, **email_kwargs) |
|
1420 | EmailNotificationModel.TYPE_PULL_REQUEST_UPDATE, **email_kwargs) | |
1423 |
|
1421 | |||
1424 | # create notification objects, and emails |
|
1422 | # create notification objects, and emails |
@@ -422,9 +422,7 b' class UserModel(BaseModel):' | |||||
422 | } |
|
422 | } | |
423 | notification_type = EmailNotificationModel.TYPE_REGISTRATION |
|
423 | notification_type = EmailNotificationModel.TYPE_REGISTRATION | |
424 | # pre-generate the subject for notification itself |
|
424 | # pre-generate the subject for notification itself | |
425 | (subject, |
|
425 | (subject, _e, body_plaintext) = EmailNotificationModel().render_email( | |
426 | _h, _e, # we don't care about those |
|
|||
427 | body_plaintext) = EmailNotificationModel().render_email( |
|
|||
428 | notification_type, **kwargs) |
|
426 | notification_type, **kwargs) | |
429 |
|
427 | |||
430 | # create notification objects, and emails |
|
428 | # create notification objects, and emails | |
@@ -659,8 +657,7 b' class UserModel(BaseModel):' | |||||
659 | 'first_admin_email': User.get_first_super_admin().email |
|
657 | 'first_admin_email': User.get_first_super_admin().email | |
660 | } |
|
658 | } | |
661 |
|
659 | |||
662 | (subject, headers, email_body, |
|
660 | (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email( | |
663 | email_body_plaintext) = EmailNotificationModel().render_email( |
|
|||
664 | EmailNotificationModel.TYPE_PASSWORD_RESET, **email_kwargs) |
|
661 | EmailNotificationModel.TYPE_PASSWORD_RESET, **email_kwargs) | |
665 |
|
662 | |||
666 | recipients = [user_email] |
|
663 | recipients = [user_email] | |
@@ -718,8 +715,7 b' class UserModel(BaseModel):' | |||||
718 | 'first_admin_email': User.get_first_super_admin().email |
|
715 | 'first_admin_email': User.get_first_super_admin().email | |
719 | } |
|
716 | } | |
720 |
|
717 | |||
721 | (subject, headers, email_body, |
|
718 | (subject, email_body, email_body_plaintext) = EmailNotificationModel().render_email( | |
722 | email_body_plaintext) = EmailNotificationModel().render_email( |
|
|||
723 | EmailNotificationModel.TYPE_PASSWORD_RESET_CONFIRMATION, |
|
719 | EmailNotificationModel.TYPE_PASSWORD_RESET_CONFIRMATION, | |
724 | **email_kwargs) |
|
720 | **email_kwargs) | |
725 |
|
721 |
@@ -8,11 +8,6 b'' | |||||
8 | SUBJECT: |
|
8 | SUBJECT: | |
9 | <pre>${c.subject}</pre> |
|
9 | <pre>${c.subject}</pre> | |
10 |
|
10 | |||
11 | HEADERS: |
|
|||
12 | <pre> |
|
|||
13 | ${c.headers} |
|
|||
14 | </pre> |
|
|||
15 |
|
||||
16 | PLAINTEXT: |
|
11 | PLAINTEXT: | |
17 | <pre> |
|
12 | <pre> | |
18 | ${c.email_body_plaintext|n} |
|
13 | ${c.email_body_plaintext|n} |
@@ -68,9 +68,6 b' text_monospace = "\'Menlo\', \'Liberation M' | |||||
68 |
|
68 | |||
69 | %> |
|
69 | %> | |
70 |
|
70 | |||
71 | ## headers we additionally can set for email |
|
|||
72 | <%def name="headers()" filter="n,trim"></%def> |
|
|||
73 |
|
||||
74 | <%def name="plaintext_footer()" filter="trim"> |
|
71 | <%def name="plaintext_footer()" filter="trim"> | |
75 | ${_('This is a notification from RhodeCode.')} ${instance_url} |
|
72 | ${_('This is a notification from RhodeCode.')} ${instance_url} | |
76 | </%def> |
|
73 | </%def> |
@@ -15,17 +15,18 b' data = {' | |||||
15 | 'comment_id': comment_id, |
|
15 | 'comment_id': comment_id, | |
16 |
|
16 | |||
17 | 'commit_id': h.show_id(commit), |
|
17 | 'commit_id': h.show_id(commit), | |
|
18 | 'mention_prefix': '[mention] ' if mention else '', | |||
18 | } |
|
19 | } | |
19 | %> |
|
20 | %> | |
20 |
|
21 | |||
21 |
|
22 | |||
22 | % if comment_file: |
|
23 | % if comment_file: | |
23 |
|
|
24 | ${_('{mention_prefix}{user} left a {comment_type} on file `{comment_file}` in commit `{commit_id}`').format(**data)} ${_('in the `{repo_name}` repository').format(**data) |n} | |
24 | % else: |
|
25 | % else: | |
25 | % if status_change: |
|
26 | % if status_change: | |
26 |
|
|
27 | ${_('{mention_prefix}[status: {status}] {user} left a {comment_type} on commit `{commit_id}`').format(**data) |n} ${_('in the `{repo_name}` repository').format(**data) |n} | |
27 | % else: |
|
28 | % else: | |
28 |
|
|
29 | ${_('{mention_prefix}{user} left a {comment_type} on commit `{commit_id}`').format(**data) |n} ${_('in the `{repo_name}` repository').format(**data) |n} | |
29 | % endif |
|
30 | % endif | |
30 | % endif |
|
31 | % endif | |
31 |
|
32 |
@@ -16,17 +16,18 b' data = {' | |||||
16 |
|
16 | |||
17 | 'pr_title': pull_request.title, |
|
17 | 'pr_title': pull_request.title, | |
18 | 'pr_id': pull_request.pull_request_id, |
|
18 | 'pr_id': pull_request.pull_request_id, | |
|
19 | 'mention_prefix': '[mention] ' if mention else '', | |||
19 | } |
|
20 | } | |
20 | %> |
|
21 | %> | |
21 |
|
22 | |||
22 |
|
23 | |||
23 | % if comment_file: |
|
24 | % if comment_file: | |
24 |
|
|
25 | ${_('{mention_prefix}{user} left a {comment_type} on file `{comment_file}` in pull request !{pr_id}: "{pr_title}"').format(**data) |n} | |
25 | % else: |
|
26 | % else: | |
26 | % if status_change: |
|
27 | % if status_change: | |
27 |
|
|
28 | ${_('{mention_prefix}[status: {status}] {user} left a {comment_type} on pull request !{pr_id}: "{pr_title}"').format(**data) |n} | |
28 | % else: |
|
29 | % else: | |
29 |
|
|
30 | ${_('{mention_prefix}{user} left a {comment_type} on pull request !{pr_id}: "{pr_title}"').format(**data) |n} | |
30 | % endif |
|
31 | % endif | |
31 | % endif |
|
32 | % endif | |
32 |
|
33 |
@@ -5,10 +5,6 b'' | |||||
5 | Test "Subject" ${_('hello "world"')|n} |
|
5 | Test "Subject" ${_('hello "world"')|n} | |
6 | </%def> |
|
6 | </%def> | |
7 |
|
7 | |||
8 | <%def name="headers()" filter="n,trim"> |
|
|||
9 | X=Y |
|
|||
10 | </%def> |
|
|||
11 |
|
||||
12 | ## plain text version of the email. Empty by default |
|
8 | ## plain text version of the email. Empty by default | |
13 | <%def name="body_plaintext()" filter="n,trim"> |
|
9 | <%def name="body_plaintext()" filter="n,trim"> | |
14 | Email Plaintext Body |
|
10 | Email Plaintext Body |
@@ -35,15 +35,12 b' def test_get_template_obj(app, request_s' | |||||
35 |
|
35 | |||
36 | def test_render_email(app, http_host_only_stub): |
|
36 | def test_render_email(app, http_host_only_stub): | |
37 | kwargs = {} |
|
37 | kwargs = {} | |
38 |
subject |
|
38 | subject, body, body_plaintext = EmailNotificationModel().render_email( | |
39 | EmailNotificationModel.TYPE_TEST, **kwargs) |
|
39 | EmailNotificationModel.TYPE_TEST, **kwargs) | |
40 |
|
40 | |||
41 | # subject |
|
41 | # subject | |
42 | assert subject == 'Test "Subject" hello "world"' |
|
42 | assert subject == 'Test "Subject" hello "world"' | |
43 |
|
43 | |||
44 | # headers |
|
|||
45 | assert headers == 'X=Y' |
|
|||
46 |
|
||||
47 | # body plaintext |
|
44 | # body plaintext | |
48 | assert body_plaintext == 'Email Plaintext Body' |
|
45 | assert body_plaintext == 'Email Plaintext Body' | |
49 |
|
46 | |||
@@ -80,7 +77,7 b' def test_render_pr_email(app, user_admin' | |||||
80 | 'pull_request_url': 'http://localhost/pr1', |
|
77 | 'pull_request_url': 'http://localhost/pr1', | |
81 | } |
|
78 | } | |
82 |
|
79 | |||
83 |
subject |
|
80 | subject, body, body_plaintext = EmailNotificationModel().render_email( | |
84 | EmailNotificationModel.TYPE_PULL_REQUEST, **kwargs) |
|
81 | EmailNotificationModel.TYPE_PULL_REQUEST, **kwargs) | |
85 |
|
82 | |||
86 | # subject |
|
83 | # subject | |
@@ -133,7 +130,7 b' def test_render_pr_update_email(app, use' | |||||
133 | 'removed_files': file_changes.removed, |
|
130 | 'removed_files': file_changes.removed, | |
134 | } |
|
131 | } | |
135 |
|
132 | |||
136 |
subject |
|
133 | subject, body, body_plaintext = EmailNotificationModel().render_email( | |
137 | EmailNotificationModel.TYPE_PULL_REQUEST_UPDATE, **kwargs) |
|
134 | EmailNotificationModel.TYPE_PULL_REQUEST_UPDATE, **kwargs) | |
138 |
|
135 | |||
139 | # subject |
|
136 | # subject | |
@@ -188,7 +185,6 b' def test_render_comment_subject_no_newli' | |||||
188 |
|
185 | |||
189 | 'pull_request_url': 'http://code.rc.com/_pr/123' |
|
186 | 'pull_request_url': 'http://code.rc.com/_pr/123' | |
190 | } |
|
187 | } | |
191 |
subject |
|
188 | subject, body, body_plaintext = EmailNotificationModel().render_email(email_type, **kwargs) | |
192 | email_type, **kwargs) |
|
|||
193 |
|
189 | |||
194 | assert '\n' not in subject |
|
190 | assert '\n' not in subject |
General Comments 0
You need to be logged in to leave comments.
Login now