def __init__(self, *args, **kwargs): super(NotifyEmailAction, self).__init__(*args, **kwargs) self.form_fields = { "targetType": { "type": "mailAction", "choices": CHOICES } } self.mail_adapter = MailAdapter()
def deliver_digest(key, schedule_timestamp=None): from sentry import digests from sentry.mail.adapter import MailAdapter try: project, target_type, target_identifier = split_key(key) except Project.DoesNotExist as error: logger.info("Cannot deliver digest %r due to error: %s", key, error) digests.delete(key) return minimum_delay = ProjectOption.objects.get_value( project, get_option_key("mail", "minimum_delay")) with snuba.options_override({"consistent": True}): try: with digests.digest(key, minimum_delay=minimum_delay) as records: digest = build_digest(project, records) except InvalidState as error: logger.info("Skipped digest delivery: %s", error, exc_info=True) return if digest: MailAdapter().notify_digest(project, digest, target_type, target_identifier)
class MailPlugin(NotificationPlugin): title = "Mail" conf_key = "mail" slug = "mail" version = sentry.VERSION author = "Sentry Team" author_url = "https://github.com/getsentry/sentry" project_default_enabled = True project_conf_form = None mail_adapter = MailAdapter() def rule_notify(self, event, futures): metrics.incr("mail_plugin.rule_notify") return self.mail_adapter.rule_notify( event, futures, target_type=ActionTargetType.ISSUE_OWNERS) def get_project_url(self, project): return absolute_uri(u"/{}/{}/".format(project.organization.slug, project.slug)) def is_configured(self, project, **kwargs): # Nothing to configure here return True def should_notify(self, group, event): metrics.incr("mail_plugin.should_notify") return (not group.project.flags.has_issue_alerts_targeting and self.mail_adapter.should_notify(group)) def notify(self, notification, **kwargs): metrics.incr("mail_plugin.notify") return self.mail_adapter.notify( notification, target_type=ActionTargetType.ISSUE_OWNERS, **kwargs) def notify_digest(self, project, digest): metrics.incr("mail_plugin.notify_digest") return self.mail_adapter.notify_digest( project, digest, target_type=ActionTargetType.ISSUE_OWNERS) def notify_about_activity(self, activity): metrics.incr("mail_plugin.notify_about_activity") if activity.project.flags.has_issue_alerts_targeting: return return self.mail_adapter.notify_about_activity(activity) def handle_signal(self, name, payload, **kwargs): metrics.incr("mail_plugin.handle_signal") if name == "user-reports.created": project = kwargs.get("project") if project and not project.flags.has_issue_alerts_targeting: self.mail_adapter.handle_signal(name, payload, **kwargs) def can_configure_for_project(self, project): return (super(MailPlugin, self).can_configure_for_project(project) and not project.flags.has_issue_alerts_targeting)
class NotifyEmailAction(EventAction): form_cls = NotifyEmailForm label = "Send an email to {targetType}" prompt = "Send an email" metrics_slug = "EmailAction" def __init__(self, *args, **kwargs): super(NotifyEmailAction, self).__init__(*args, **kwargs) self.form_fields = { "targetType": { "type": "mailAction", "choices": CHOICES } } self.mail_adapter = MailAdapter() def after(self, event, state): extra = {"event_id": event.event_id} group = event.group if not self.mail_adapter.should_notify(group=group): extra["group_id"] = group.id self.logger.info("rule.fail.should_notify", extra=extra) return metrics.incr("notifications.sent", instance=self.metrics_slug, skip_internal=False) yield self.future(lambda event, futures: self.mail_adapter.rule_notify( event, futures, ActionTargetType(self.data["targetType"]), self.data.get("targetIdentifier", None), )) def get_form_instance(self): return self.form_cls(self.project, self.data)
def signal(name, payload, project_id=None, **kwargs): from sentry.mail.adapter import MailAdapter from sentry.models import Project if project_id is not None: project = Project.objects.get_from_cache(id=project_id) else: project = None for plugin in plugins.for_project(project, version=1): safe_execute(plugin.handle_signal, name=name, payload=payload, project=project) for plugin in plugins.for_project(project, version=2): safe_execute(plugin.handle_signal, name=name, payload=payload, project=project) if project and project.flags.has_issue_alerts_targeting: safe_execute(MailAdapter().handle_signal, name=name, payload=payload, project=project)
def get_activity_notifiers(project): from sentry.mail.adapter import MailAdapter from sentry.plugins.bases.notify import NotificationPlugin from sentry.plugins.base import plugins results = [] for plugin in plugins.for_project(project, version=1): if isinstance(plugin, NotificationPlugin): results.append(plugin) for plugin in plugins.for_project(project, version=2): for notifier in safe_execute(plugin.get_notifiers, _with_transaction=False) or (): results.append(notifier) if project.flags.has_issue_alerts_targeting: results.append(MailAdapter()) return results
def adapter(self): return MailAdapter()
class MailPlugin(NotificationPlugin): title = "Mail" conf_key = "mail" slug = "mail" version = sentry.VERSION author = "Sentry Team" author_url = "https://github.com/getsentry/sentry" project_default_enabled = True project_conf_form = None mail_adapter = MailAdapter() def rule_notify(self, event, futures): return self.mail_adapter.rule_notify(event, futures) def get_project_url(self, project): return absolute_uri(u"/{}/{}/".format(project.organization.slug, project.slug)) def is_configured(self, project, **kwargs): # Nothing to configure here return True def should_notify(self, group, event): return self.mail_adapter.should_notify(group) def notify(self, notification, **kwargs): return self.mail_adapter.notify(notification, **kwargs) def notify_digest(self, project, digest): return self.mail_adapter.notify_digest(project, digest) def notify_about_activity(self, activity): email_cls = emails.get(activity.type) if not email_cls: logger.debug(u"No email associated with activity type `{}`".format( activity.get_type_display())) return email = email_cls(activity) email.send() def handle_user_report(self, payload, project, **kwargs): from sentry.models import Group, GroupSubscription, GroupSubscriptionReason group = Group.objects.get(id=payload["report"]["issue"]["id"]) participants = GroupSubscription.objects.get_participants(group=group) if not participants: return org = group.organization enhanced_privacy = org.flags.enhanced_privacy context = { "project": project, "project_link": absolute_uri(u"/{}/{}/".format(project.organization.slug, project.slug)), "issue_link": absolute_uri(u"/{}/{}/issues/{}/".format( project.organization.slug, project.slug, payload["report"]["issue"]["id"])), # TODO(dcramer): we dont have permalinks to feedback yet "link": absolute_uri(u"/{}/{}/issues/{}/feedback/".format( project.organization.slug, project.slug, payload["report"]["issue"]["id"])), "group": group, "report": payload["report"], "enhanced_privacy": enhanced_privacy, } subject_prefix = self.mail_adapter._build_subject_prefix(project) subject = force_text(u"{}{} - New Feedback from {}".format( subject_prefix, group.qualified_short_id, payload["report"]["name"])) headers = {"X-Sentry-Project": project.slug} # TODO(dcramer): this is copypasta'd from activity notifications # and while it'd be nice to re-use all of that, they are currently # coupled to <Activity> instances which makes this tough for user, reason in participants.items(): context.update({ "reason": GroupSubscriptionReason.descriptions.get( reason, "are subscribed to this issue"), "unsubscribe_link": generate_signed_link( user.id, "sentry-account-email-unsubscribe-issue", kwargs={"issue_id": group.id}, ), }) msg = MessageBuilder( subject=subject, template="sentry/emails/activity/new-user-feedback.txt", html_template="sentry/emails/activity/new-user-feedback.html", headers=headers, type="notify.user-report", context=context, reference=group, ) msg.add_users([user.id], project=project) msg.send_async() def handle_signal(self, name, payload, **kwargs): if name == "user-reports.created": self.handle_user_report(payload, **kwargs) def can_configure_for_project(self, project): return (super(MailPlugin, self).can_configure_for_project(project) and not project.flags.has_issue_alerts_targeting)