-
Notifications
You must be signed in to change notification settings - Fork 296
/
Copy pathtasks.py
152 lines (130 loc) · 6.07 KB
/
tasks.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
from socket import gaierror
from celery.utils.log import get_task_logger
from django.conf import settings
from django.core.mail import BadHeaderError, get_connection, send_mail
from django.utils.html import strip_tags
from apps.alerts.models import AlertGroup
from apps.base.utils import live_settings
from apps.email.alert_rendering import build_subject_and_message
from apps.email.models import EmailMessage
from apps.user_management.models import User
from common.custom_celery_tasks import shared_dedicated_queue_retry_task
MAX_RETRIES = 1 if settings.DEBUG else 10
logger = get_task_logger(__name__)
def get_from_email(user):
if live_settings.EMAIL_FROM_ADDRESS:
return live_settings.EMAIL_FROM_ADDRESS
if settings.LICENSE == settings.CLOUD_LICENSE_NAME:
return "oncall@{}.{}".format(user.organization.stack_slug, settings.EMAIL_FROM_DOMAIN)
return live_settings.EMAIL_HOST_USER
@shared_dedicated_queue_retry_task(autoretry_for=(Exception,), retry_backoff=True, max_retries=MAX_RETRIES)
def notify_user_async(user_pk, alert_group_pk, notification_policy_pk):
# imported here to avoid circular import error
from apps.base.models import UserNotificationPolicy, UserNotificationPolicyLogRecord
try:
user = User.objects.get(pk=user_pk)
except User.DoesNotExist:
logger.warning(f"User {user_pk} does not exist")
return
try:
alert_group = AlertGroup.objects.get(pk=alert_group_pk)
except AlertGroup.DoesNotExist:
logger.warning(f"Alert group {alert_group_pk} does not exist")
return
using_fallback_default_notification_policy_step = False
if notification_policy_pk is None:
# NOTE: `notification_policy_pk` may be None if the user has no notification policies defined, as
# email is the default backend used. see `UserNotificationPolicy.get_default_fallback_policy` for more details
notification_policy = UserNotificationPolicy.get_default_fallback_policy(user)
using_fallback_default_notification_policy_step = True
else:
try:
notification_policy = UserNotificationPolicy.objects.get(pk=notification_policy_pk)
except UserNotificationPolicy.DoesNotExist:
logger.warning(f"User notification policy {notification_policy_pk} does not exist")
return
def _create_user_notification_policy_log_record(**kwargs):
return UserNotificationPolicyLogRecord.objects.create(
**kwargs, using_fallback_default_notification_policy_step=using_fallback_default_notification_policy_step
)
def _create_email_message(**kwargs):
return EmailMessage.objects.create(
**kwargs, using_fallback_default_notification_policy_step=using_fallback_default_notification_policy_step
)
# create an error log in case EMAIL_HOST is not specified
if not live_settings.EMAIL_HOST:
_create_user_notification_policy_log_record(
author=user,
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
notification_policy=notification_policy,
alert_group=alert_group,
reason="Error while sending email",
notification_step=notification_policy.step,
notification_channel=notification_policy.notify_by,
)
logger.error("Error while sending email: empty EMAIL_HOST env variable")
return
emails_left = user.organization.emails_left(user)
if emails_left <= 0:
_create_user_notification_policy_log_record(
author=user,
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
notification_policy=notification_policy,
alert_group=alert_group,
reason="Error while sending email",
notification_step=notification_policy.step,
notification_channel=notification_policy.notify_by,
notification_error_code=UserNotificationPolicyLogRecord.ERROR_NOTIFICATION_MAIL_LIMIT_EXCEEDED,
)
_create_email_message(
represents_alert_group=alert_group,
notification_policy=notification_policy,
receiver=user,
exceeded_limit=True,
)
return
subject, html_message = build_subject_and_message(alert_group, emails_left)
message = strip_tags(html_message)
from_email = get_from_email(user)
recipient_list = [user.email]
connection = get_connection(
host=live_settings.EMAIL_HOST,
port=live_settings.EMAIL_PORT,
username=live_settings.EMAIL_HOST_USER,
password=live_settings.EMAIL_HOST_PASSWORD,
use_tls=live_settings.EMAIL_USE_TLS,
use_ssl=live_settings.EMAIL_USE_SSL,
fail_silently=False,
timeout=5,
)
try:
send_mail(subject, message, from_email, recipient_list, html_message=html_message, connection=connection)
_create_email_message(
represents_alert_group=alert_group,
notification_policy=notification_policy,
receiver=user,
exceeded_limit=False,
)
except (gaierror, BadHeaderError) as e:
# gaierror is raised when EMAIL_HOST is invalid
# BadHeaderError is raised when there's newlines in the subject
_create_user_notification_policy_log_record(
author=user,
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_FAILED,
notification_policy=notification_policy,
alert_group=alert_group,
reason="Error while sending email",
notification_step=notification_policy.step,
notification_channel=notification_policy.notify_by,
)
logger.error(f"Error while sending email: {e}")
return
# record success log
_create_user_notification_policy_log_record(
author=user,
type=UserNotificationPolicyLogRecord.TYPE_PERSONAL_NOTIFICATION_SUCCESS,
notification_policy=notification_policy,
alert_group=alert_group,
notification_step=notification_policy.step,
notification_channel=notification_policy.notify_by,
)