Exemple #1
0
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)
Exemple #2
0
 def __init__(self, *args, **kwargs):
     super(NotifyEmailAction, self).__init__(*args, **kwargs)
     self.form_fields = {
         "targetType": {
             "type": "mailAction",
             "choices": CHOICES
         }
     }
     self.mail_adapter = MailAdapter()
Exemple #3
0
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)
Exemple #4
0
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)
Exemple #5
0
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
Exemple #6
0
 def adapter(self):
     return MailAdapter()
Exemple #7
0
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)