コード例 #1
0
    def email_success(self):
        from sentry.utils.email import MessageBuilder

        # The following condition should never be true, but it's a safeguard in case someone manually calls this method
        if self.date_finished is None or self.date_expired is None or self.file is None:
            logger.warning(
                "Notification email attempted on incomplete dataset",
                extra={
                    "data_export_id": self.id,
                    "organization_id": self.organization_id
                },
            )
            return
        url = absolute_uri(
            reverse("sentry-data-export-details",
                    args=[self.organization.slug, self.id]))
        msg = MessageBuilder(
            subject="Your Download is Ready!",
            context={
                "url": url,
                "expiration": self.format_date(self.date_expired)
            },
            type="organization.export-data",
            template="sentry/emails/data-export-success.txt",
            html_template="sentry/emails/data-export-success.html",
        )
        msg.send_async([self.user.email])
        metrics.incr("dataexport.end", instance="success")
コード例 #2
0
ファイル: user.py プロジェクト: andrzej-tests-1/sentry-app
    def send_confirm_email_singular(self, email, is_new_user=False):
        from sentry import options
        from sentry.utils.email import MessageBuilder

        if not email.hash_is_valid():
            email.set_hash()
            email.save()

        context = {
            'user':
            self,
            'url':
            absolute_uri(
                reverse('sentry-account-confirm-email',
                        args=[self.id, email.validation_hash])),
            'confirm_email':
            email.email,
            'is_new_user':
            is_new_user,
        }
        msg = MessageBuilder(
            subject='%sConfirm Email' % (options.get('mail.subject-prefix'), ),
            template='sentry/emails/confirm_email.txt',
            html_template='sentry/emails/confirm_email.html',
            type='user.confirm_email',
            context=context,
        )
        msg.send_async([email.email])
コード例 #3
0
def build_message(timestamp, duration, organization, user, reports):
    start, stop = interval = _to_interval(timestamp, duration)

    duration_spec = durations[duration]
    message = MessageBuilder(
        subject="{} Report for {}: {} - {}".format(
            duration_spec.adjective.title(),
            organization.name,
            date_format(start),
            date_format(stop),
        ),
        template="sentry/emails/reports/body.txt",
        html_template="sentry/emails/reports/body.html",
        type="report.organization",
        context={
            "duration": duration_spec,
            "interval": {"start": date_format(start), "stop": date_format(stop)},
            "organization": organization,
            "personal": fetch_personal_statistics(interval, organization, user),
            "report": to_context(organization, interval, reports),
            "user": user,
        },
        headers={"X-SMTPAPI": json.dumps({"category": "organization_report_email"})},
    )

    message.add_users((user.id,))

    return message
コード例 #4
0
ファイル: pendingteammember.py プロジェクト: mortik/sentry
    def send_invite_email(self):
        from sentry.utils.email import MessageBuilder

        context = {
            'email':
            self.email,
            'team':
            self.team,
            'url':
            absolute_uri(
                reverse('sentry-accept-invite',
                        kwargs={
                            'member_id': self.id,
                            'token': self.token,
                        })),
        }

        msg = MessageBuilder(
            subject='Invite to join team: %s' % (self.team.name, ),
            template='sentry/emails/member_invite.txt',
            context=context,
        )

        try:
            msg.send([self.email])
        except Exception, e:
            logger = logging.getLogger('sentry.mail.errors')
            logger.exception(e)
コード例 #5
0
ファイル: tests.py プロジェクト: rahulchhabria/sentry-fork-rc
    def test_add_groupemailthread(self, make_msgid):
        make_msgid.return_value = "abc123"

        msg = MessageBuilder(subject="Test",
                             body="hello world",
                             html_body="<b>hello world</b>",
                             reference=self.group)
        msg.send(["*****@*****.**"])

        assert len(mail.outbox) == 1

        out = mail.outbox[0]
        assert out.to == ["*****@*****.**"]
        assert out.subject == "Test", "First message should not have Re: prefix"
        assert out.extra_headers["Message-Id"] == "abc123"
        assert "In-Reply-To" not in out.extra_headers
        assert "References" not in out.extra_headers
        assert out.body == "hello world"
        assert len(out.alternatives) == 1
        assert out.alternatives[0] == (
            "<!DOCTYPE html>\n<html><body><b>hello world</b></body></html>",
            "text/html",
        )

        # Our new EmailThread row was added
        assert GroupEmailThread.objects.count() == 1
        thread = GroupEmailThread.objects.all()[0]
        assert thread.msgid == "abc123"
        assert thread.email == "*****@*****.**"
        assert thread.group == self.group
コード例 #6
0
    def send_invite_email(self):
        from sentry.utils.email import MessageBuilder

        context = {
            'email': self.email,
            'organization': self.organization,
            'url': absolute_uri(reverse('sentry-accept-invite', kwargs={
                'member_id': self.id,
                'token': self.token,
            })),
        }

        msg = MessageBuilder(
            subject='Join %s in using Sentry' % self.organization.name,
            template='sentry/emails/member-invite.txt',
            html_template='sentry/emails/member-invite.html',
            type='organization.invite',
            context=context,
        )

        try:
            msg.send_async([self.get_email()])
        except Exception as e:
            logger = get_logger(name='sentry.mail')
            logger.exception(e)
コード例 #7
0
    def _send_mail(self,
                   subject,
                   template=None,
                   html_template=None,
                   body=None,
                   project=None,
                   headers=None,
                   context=None,
                   fail_silently=False):

        subject_prefix = self.get_option('subject_prefix',
                                         project) or self.subject_prefix

        msg = MessageBuilder(
            subject='%s%s' % (subject_prefix, subject),
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            context=context,
        )

        send_to = self._send_to

        return msg.send(to=send_to, fail_silently=fail_silently)
コード例 #8
0
ファイル: adapter.py プロジェクト: naheedk-pwc/sentry
    def _build_message(
        self,
        project,
        subject,
        template=None,
        html_template=None,
        body=None,
        reference=None,
        reply_reference=None,
        headers=None,
        context=None,
        send_to=None,
        type=None,
    ):
        if not send_to:
            logger.debug("Skipping message rendering, no users to send to.")
            return

        subject_prefix = self._build_subject_prefix(project)
        subject = force_text(subject)

        msg = MessageBuilder(
            subject=f"{subject_prefix}{subject}",
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            type=type,
            context=context,
            reference=reference,
            reply_reference=reply_reference,
        )
        msg.add_users(send_to, project=project)
        return msg
コード例 #9
0
ファイル: models.py プロジェクト: Cobbyzhang/sentry
    def _build_message(self, project, subject, template=None, html_template=None,
                   body=None, reference=None, reply_reference=None, headers=None,
                   context=None, send_to=None, type=None):
        if send_to is None:
            send_to = self.get_send_to(project)
        if not send_to:
            logger.debug('Skipping message rendering, no users to send to.')
            return

        subject_prefix = self.get_option('subject_prefix', project) or self._subject_prefix()
        subject_prefix = force_text(subject_prefix)
        subject = force_text(subject)

        msg = MessageBuilder(
            subject='%s%s' % (subject_prefix, subject),
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            type=type,
            context=context,
            reference=reference,
            reply_reference=reply_reference,
        )
        msg.add_users(send_to, project=project)
        return msg
コード例 #10
0
ファイル: reports.py プロジェクト: andrzej-tests-1/sentry-app
def build_message(timestamp, duration, organization, user, reports):
    start, stop = interval = _to_interval(timestamp, duration)

    duration_spec = durations[duration]
    message = MessageBuilder(
        subject=u'{} Report for {}: {} - {}'.format(
            duration_spec.adjective.title(),
            organization.name,
            date_format(start),
            date_format(stop),
        ),
        template='sentry/emails/reports/body.txt',
        html_template='sentry/emails/reports/body.html',
        type='report.organization',
        context={
            'duration': duration_spec,
            'interval': {
                'start': date_format(start),
                'stop': date_format(stop),
            },
            'organization': organization,
            'personal': fetch_personal_statistics(
                interval,
                organization,
                user,
            ),
            'report': to_context(organization, interval, reports),
            'user': user,
        },
    )

    message.add_users((user.id, ))

    return message
コード例 #11
0
    def send_invite_email(self):
        from sentry.utils.email import MessageBuilder

        context = {
            'email': self.email,
            'organization': self.organization,
            'url': absolute_uri(reverse('sentry-accept-invite', kwargs={
                'member_id': self.id,
                'token': self.token,
            })),
        }

        msg = MessageBuilder(
            subject='Join %s in using Sentry' % self.organization.name,
            template='sentry/emails/member-invite.txt',
            html_template='sentry/emails/member-invite.html',
            type='organization.invite',
            context=context,
        )

        try:
            msg.send_async([self.get_email()])
        except Exception as e:
            logger = get_logger(name='sentry.mail')
            logger.exception(e)
コード例 #12
0
    def _build_message(self, subject, template=None, html_template=None,
                       body=None, project=None, group=None, headers=None,
                       context=None):
        """
        Identical function to _build_message for sentry_mail, by the Sentry
        Team, except for the send_to list that is received is assigned to
        the message's list instead of appended. 
        """

        send_to = self.get_option('emails', project) or []
        if not send_to:
            logger.debug('Skipping message rendering, no users to send to.')
            return

        subject_prefix = self.get_option('subject_prefix', project) or \
                self.subject_prefix
        subject_prefix = force_text(subject_prefix)
        subject = force_text(subject)

        msg = MessageBuilder(
            subject='%s%s' % (subject_prefix, subject),
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            context=context,
            reference=group,
        )
        msg._send_to = set(send_to)

        return msg
コード例 #13
0
    def _build_message(self, project, subject, template=None, html_template=None,
                   body=None, reference=None, reply_reference=None, headers=None,
                   context=None, send_to=None, type=None):
        if send_to is None:
            send_to = self.get_send_to(project)
        if not send_to:
            logger.debug('Skipping message rendering, no users to send to.')
            return

        subject_prefix = self.get_option('subject_prefix', project) or self._subject_prefix()
        subject_prefix = force_text(subject_prefix)
        subject = force_text(subject)

        msg = MessageBuilder(
            subject='%s%s' % (subject_prefix, subject),
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            type=type,
            context=context,
            reference=reference,
            reply_reference=reply_reference,
        )
        msg.add_users(send_to, project=project)
        return msg
コード例 #14
0
def handle_project(plugin, project, stream):
    stream.write('# Project: %s\n' % project)
    from sentry.utils.email import MessageBuilder
    msg = MessageBuilder('test')
    msg.add_users(plugin.get_sendable_users(project), project)
    for email in msg._send_to:
        stream.write(email + '\n')
コード例 #15
0
ファイル: tests.py プロジェクト: Kayle009/sentry
    def test_fake_dont_send(self):
        project = self.project

        user_a = User.objects.create(email=create_fake_email('foo', 'fake'))
        user_b = User.objects.create(email=create_fake_email('bar', 'fake'))
        user_c = User.objects.create(email=create_fake_email('baz', 'fake'))

        UserOption.objects.create(
            user=user_b,
            key='alert_email',
            value=create_fake_email('fizzle', 'fake'),
        )
        UserOption.objects.create(
            user=user_c,
            project=project,
            key='mail:email',
            value=create_fake_email('bazzer', 'fake'),
        )

        msg = MessageBuilder(
            subject='Test',
            body='hello world',
            html_body='<!DOCTYPE html>\n<b>hello world</b>',
        )
        msg.add_users([user_a.id, user_b.id, user_c.id], project=project)
        msg.send()

        assert len(mail.outbox) == 0
コード例 #16
0
ファイル: tests.py プロジェクト: Kayle009/sentry
    def test_add_groupemailthread(self, make_msgid):
        make_msgid.return_value = 'abc123'

        msg = MessageBuilder(
            subject='Test',
            body='hello world',
            html_body='<b>hello world</b>',
            reference=self.group,
        )
        msg.send(['*****@*****.**'])

        assert len(mail.outbox) == 1

        out = mail.outbox[0]
        assert out.to == ['*****@*****.**']
        assert out.subject == 'Test', 'First message should not have Re: prefix'
        assert out.extra_headers['Message-Id'] == 'abc123'
        assert 'In-Reply-To' not in out.extra_headers
        assert 'References' not in out.extra_headers
        assert out.body == 'hello world'
        assert len(out.alternatives) == 1
        assert out.alternatives[0] == (
            '<!DOCTYPE html>\n<html><body><b>hello world</b></body></html>', 'text/html',
        )

        # Our new EmailThread row was added
        assert GroupEmailThread.objects.count() == 1
        thread = GroupEmailThread.objects.all()[0]
        assert thread.msgid == 'abc123'
        assert thread.email == '*****@*****.**'
        assert thread.group == self.group
コード例 #17
0
    def _send_mail(
        self,
        subject,
        template=None,
        html_template=None,
        body=None,
        project=None,
        headers=None,
        context=None,
        fail_silently=False,
    ):

        subject_prefix = self.get_option("subject_prefix", project) or self.subject_prefix

        msg = MessageBuilder(
            subject="%s%s" % (subject_prefix, subject),
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            context=context,
        )

        send_to = self._send_to

        return msg.send(to=send_to, fail_silently=fail_silently)
コード例 #18
0
ファイル: reports.py プロジェクト: WhoTrades/sentry
def build_message(timestamp, duration, organization, user, report):
    start, stop = interval = _to_interval(timestamp, duration)

    duration_spec = durations[duration]
    message = MessageBuilder(
        subject=u'{} Report for {}: {} - {}'.format(
            duration_spec.adjective.title(),
            organization.name,
            date_format(start),
            date_format(stop),
        ),
        template='sentry/emails/reports/body.txt',
        html_template='sentry/emails/reports/body.html',
        type='report.organization',
        context={
            'duration': duration_spec,
            'interval': {
                'start': date_format(start),
                'stop': date_format(stop),
            },
            'organization': organization,
            'personal': fetch_personal_statistics(
                interval,
                organization,
                user,
            ),
            'report': to_context(report),
            'user': user,
        },
    )

    message.add_users((user.id,))

    return message
コード例 #19
0
ファイル: tests.py プロジェクト: Kayle009/sentry
    def test_with_users(self):
        project = self.project

        user_a = User.objects.create(email='*****@*****.**')
        user_b = User.objects.create(email='*****@*****.**')
        user_c = User.objects.create(email='*****@*****.**')

        UserOption.objects.create(
            user=user_b,
            key='alert_email',
            value='*****@*****.**',
        )
        UserOption.objects.create(
            user=user_c,
            project=project,
            key='mail:email',
            value='*****@*****.**',
        )

        msg = MessageBuilder(
            subject='Test',
            body='hello world',
            html_body='<!DOCTYPE html>\n<b>hello world</b>',
        )
        msg.add_users([user_a.id, user_b.id, user_c.id], project=project)
        msg.send()

        assert len(mail.outbox) == 3

        assert sorted([out.to[0] for out in mail.outbox]) == [
            '*****@*****.**',
            '*****@*****.**',
            '*****@*****.**',
        ]
コード例 #20
0
ファイル: models.py プロジェクト: erhuabushuo/sentry
    def _send_mail(self, subject, template=None, html_template=None, body=None,
                   project=None, group=None, headers=None, context=None,
                   fail_silently=False):
        send_to = self.get_send_to(project)
        if not send_to:
            return

        subject_prefix = self.get_option('subject_prefix', project) or self.subject_prefix

        try:
            subject_prefix = subject_prefix.encode("utf-8")
            subject = subject.encode("utf-8")
        except UnicodeDecodeError:
            subject_prefix = unicode(subject_prefix, "utf-8")
            subject = unicode(subject, "utf-8")

        msg = MessageBuilder(
            subject='%s%s' % (subject_prefix, subject),
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            context=context,
            reference=group,
        )
        msg.add_users(send_to, project=project)
        return msg.send(fail_silently=fail_silently)
コード例 #21
0
ファイル: user.py プロジェクト: yogeshmangaj/sentry
    def send_confirm_email_singular(self, email, is_new_user=False):
        from sentry import options
        from sentry.utils.email import MessageBuilder

        if not email.hash_is_valid():
            email.set_hash()
            email.save()

        context = {
            'user':
            self,
            'url':
            absolute_uri(
                reverse('sentry-account-confirm-email', args=[self.id, email.validation_hash])
            ),
            'confirm_email':
            email.email,
            'is_new_user':
            is_new_user,
        }
        msg = MessageBuilder(
            subject='%sConfirm Email' % (options.get('mail.subject-prefix'), ),
            template='sentry/emails/confirm_email.txt',
            html_template='sentry/emails/confirm_email.html',
            type='user.confirm_email',
            context=context,
        )
        msg.send_async([email.email])
コード例 #22
0
    def send_approved_email(self):
        from sentry.utils.email import MessageBuilder

        user = self.member.user
        email = user.email
        organization = self.team.organization

        context = {
            'email': email,
            'name': user.get_display_name(),
            'organization': organization,
            'team': self.team,
        }

        msg = MessageBuilder(
            subject='Sentry Access Request',
            template='sentry/emails/access-approved.txt',
            html_template='sentry/emails/access-approved.html',
            context=context,
        )

        try:
            msg.send([email])
        except Exception as e:
            logger = logging.getLogger('sentry.mail.errors')
            logger.exception(e)
コード例 #23
0
    def send_request_email(self):
        from sentry.utils.email import MessageBuilder

        user = self.member.user
        email = user.email
        organization = self.team.organization

        context = {
            'email': email,
            'name': user.get_display_name(),
            'organization': organization,
            'team': self.team,
            'url': absolute_uri(reverse('sentry-organization-members', kwargs={
                'organization_slug': organization.slug,
            }) + '?ref=access-requests'),
        }

        msg = MessageBuilder(
            subject='Sentry Access Request',
            template='sentry/emails/request-team-access.txt',
            html_template='sentry/emails/request-team-access.html',
            context=context,
        )

        try:
            msg.send([email])
        except Exception as e:
            logger = logging.getLogger('sentry.mail.errors')
            logger.exception(e)
コード例 #24
0
    def send_sso_unlink_email(self, actor, provider):
        from sentry.utils.email import MessageBuilder
        from sentry.models import LostPasswordHash

        email = self.get_email()

        recover_uri = '{path}?{query}'.format(
            path=reverse('sentry-account-recover'),
            query=urlencode({'email': email}),
        )

        context = {
            'email': email,
            'recover_url': absolute_uri(recover_uri),
            'has_password': self.user.password,
            'organization': self.organization,
            'actor': actor,
            'provider': provider,
        }

        if not self.user.password:
            password_hash = LostPasswordHash.for_user(self.user)
            context['set_password_url'] = password_hash.get_absolute_url(mode='set_password')

        msg = MessageBuilder(
            subject='Action Required for %s' % (self.organization.name, ),
            template='sentry/emails/auth-sso-disabled.txt',
            html_template='sentry/emails/auth-sso-disabled.html',
            type='organization.auth_sso_disabled',
            context=context,
        )
        msg.send_async([email])
コード例 #25
0
    def send_notification(self):
        from sentry.utils.email import MessageBuilder

        if self.type != Activity.NOTE or not self.group:
            return

        # TODO(dcramer): some of this logic is duplicated in NotificationPlugin
        # fetch access group members
        user_list = set(m.user for m in AccessGroup.objects.filter(
            projects=self.project,
            members__is_active=True,
        ).exclude(members__id=self.user_id, ))

        if self.project.team:
            # fetch team members
            user_list |= set(
                m.user for m in self.project.team.member_set.filter(
                    user__is_active=True, ).exclude(user__id=self.user_id, ))

        if not user_list:
            return

        disabled = set(
            UserOption.objects.filter(
                user__in=user_list,
                key='subscribe_comments',
                value='0',
            ).values_list('user', flat=True))

        send_to = [
            u.email for u in user_list if u.email and u.id not in disabled
        ]

        if not send_to:
            return

        author = self.user.first_name or self.user.username

        subject = '%s: %s' % (author, self.data['text'].splitlines()[0][:64])

        context = {
            'text': self.data['text'],
            'author': author,
            'group': self.group,
            'link': self.group.get_absolute_url(),
        }

        msg = MessageBuilder(
            subject=subject,
            context=context,
            template='sentry/emails/new_note.txt',
            html_template='sentry/emails/new_note.html',
        )

        try:
            msg.send(to=send_to)
        except Exception, e:
            logger = logging.getLogger('sentry.mail.errors')
            logger.exception(e)
コード例 #26
0
ファイル: tests.py プロジェクト: pasala91/test
    def test_stripped_newline(self):
        msg = MessageBuilder(subject="Foo\r\nBar",
                             body="hello world",
                             html_body="<b>hello world</b")
        msg.send(["*****@*****.**"])

        assert len(mail.outbox) == 1
        assert mail.outbox[0].subject == "Foo"
コード例 #27
0
def send_invite_request_notification_email(member_id):
    try:
        om = OrganizationMember.objects.select_related(
            "inviter", "organization").get(id=member_id)
    except OrganizationMember.DoesNotExist:
        return

    link_args = {"organization_slug": om.organization.slug}

    context = {
        "email":
        om.email,
        "organization_name":
        om.organization.name,
        "pending_requests_link":
        absolute_uri(
            reverse("sentry-organization-members-requests", kwargs=link_args)),
    }

    if om.requested_to_join:
        email_args = {
            "template": "sentry/emails/organization-join-request.txt",
            "html_template": "sentry/emails/organization-join-request.html",
        }
        context["settings_link"] = absolute_uri(
            reverse("sentry-organization-settings",
                    args=[om.organization.slug]))

    elif om.requested_to_be_invited:
        email_args = {
            "template": "sentry/emails/organization-invite-request.txt",
            "html_template": "sentry/emails/organization-invite-request.html",
        }
        context["inviter_name"] = om.inviter.get_salutation_name
    else:
        raise RuntimeError("This member is not pending invitation")

    recipients = OrganizationMember.objects.select_related("user").filter(
        organization_id=om.organization_id,
        user__isnull=False,
        invite_status=InviteStatus.APPROVED.value,
        role__in=(r.id for r in roles.get_all()
                  if r.has_scope("member:write")),
    )

    msg = MessageBuilder(
        subject=f"Access request to {om.organization.name}",
        type="organization.invite-request",
        context=context,
        **email_args,
    )

    for recipient in recipients:
        try:
            msg.send_async([recipient.get_email()])
        except Exception as e:
            logger = get_logger(name="sentry.mail")
            logger.exception(e)
コード例 #28
0
ファイル: organizationmember.py プロジェクト: qiqizjl/sentry
    def send_request_notification_email(self):
        from sentry.utils.email import MessageBuilder

        link_args = {"organization_slug": self.organization.slug}

        context = {
            "email":
            self.email,
            "inviter":
            self.inviter,
            "organization":
            self.organization,
            "organization_link":
            absolute_uri(
                reverse("sentry-organization-index",
                        args=[self.organization.slug])),
            "pending_requests_link":
            absolute_uri(
                reverse("sentry-organization-members-requests",
                        kwargs=link_args)),
        }

        if self.requested_to_join:
            email_args = {
                "template": "sentry/emails/organization-join-request.txt",
                "html_template":
                "sentry/emails/organization-join-request.html",
            }
        elif self.requested_to_be_invited:
            email_args = {
                "template": "sentry/emails/organization-invite-request.txt",
                "html_template":
                "sentry/emails/organization-invite-request.html",
            }
        else:
            raise RuntimeError("This member is not pending invitation")

        recipients = OrganizationMember.objects.select_related("user").filter(
            organization_id=self.organization_id,
            user__isnull=False,
            invite_status=InviteStatus.APPROVED.value,
            role__in=(r.id for r in roles.get_all()
                      if r.has_scope("member:write")),
        )

        msg = MessageBuilder(subject="Access request to %s" %
                             (self.organization.name, ),
                             type="organization.invite-request",
                             context=context,
                             **email_args)

        for recipient in recipients:
            try:
                msg.send_async([recipient.get_email()])
            except Exception as e:
                logger = get_logger(name="sentry.mail")
                logger.exception(e)
コード例 #29
0
ファイル: tests.py プロジェクト: pasala91/test
    def test_bcc_on_send(self):
        msg = MessageBuilder(subject="Test", body="hello world")
        msg.send(["*****@*****.**"], bcc=["*****@*****.**"])

        assert len(mail.outbox) == 1

        out = mail.outbox[0]
        assert out.to == ["*****@*****.**"]
        assert out.bcc == ["*****@*****.**"]
コード例 #30
0
ファイル: tests.py プロジェクト: duanshuaimin/sentry
    def test_reply_reference(self, make_msgid):
        make_msgid.return_value = 'abc123'

        msg = MessageBuilder(
            subject='Test',
            body='hello world',
            html_body='<b>hello world</b>',
            reference=self.activity,
            reply_reference=self.group,
        )
        msg.send(['*****@*****.**'])

        assert len(mail.outbox) == 1

        out = mail.outbox[0]
        assert out.to == ['*****@*****.**']
        assert out.subject == 'Re: Test'
        assert out.extra_headers['Message-Id'] == 'abc123'
        assert 'In-Reply-To' not in out.extra_headers
        assert 'References' not in out.extra_headers
        assert out.body == 'hello world'
        assert len(out.alternatives) == 1
        assert out.alternatives[0] == (
            '<!DOCTYPE html>\n<html><body><b>hello world</b></body></html>',
            'text/html',
        )

        # Our new EmailThread row was added
        assert GroupEmailThread.objects.count() == 1
        thread = GroupEmailThread.objects.all()[0]
        assert thread.msgid == 'abc123'
        assert thread.email == '*****@*****.**'
        assert thread.group == self.group

        # new msgid for the next message
        make_msgid.return_value = '321cba'
        msg.send(['*****@*****.**'])

        assert len(mail.outbox) == 2

        out = mail.outbox[1]
        assert out.to == ['*****@*****.**']
        assert out.subject == 'Re: Test'
        assert out.extra_headers['Message-Id'] == '321cba'
        assert out.extra_headers['In-Reply-To'] == 'abc123'
        assert out.extra_headers['References'] == 'abc123'
        assert out.body == 'hello world'
        assert len(out.alternatives) == 1
        assert out.alternatives[0] == (
            '<!DOCTYPE html>\n<html><body><b>hello world</b></body></html>',
            'text/html',
        )

        # Our new GroupEmailThread row was added
        assert GroupEmailThread.objects.count() == 1, 'Should not have added a new row'
        assert GroupEmailThread.objects.all()[0].msgid == 'abc123', 'msgid should not have changed'
コード例 #31
0
    def test_stripped_newline(self):
        msg = MessageBuilder(
            subject='Foo\r\nBar',
            body='hello world',
            html_body='<b>hello world</b',
        )
        msg.send(['*****@*****.**'])

        assert len(mail.outbox) == 1
        assert mail.outbox[0].subject == 'Foo'
コード例 #32
0
ファイル: tests.py プロジェクト: pasala91/test
 def test_get_built_messages(self):
     msg = MessageBuilder(
         subject="Test",
         body="hello world",
         html_body="<b>hello world</b>",
         reference=self.activity,
         reply_reference=self.group,
     )
     results = msg.get_built_messages(["*****@*****.**"])
     assert len(results) == 1
コード例 #33
0
ファイル: tests.py プロジェクト: Kayle009/sentry
    def test_stripped_newline(self):
        msg = MessageBuilder(
            subject='Foo\r\nBar',
            body='hello world',
            html_body='<b>hello world</b',
        )
        msg.send(['*****@*****.**'])

        assert len(mail.outbox) == 1
        assert mail.outbox[0].subject == 'Foo'
コード例 #34
0
 def test_get_built_messages(self):
     msg = MessageBuilder(
         subject='Test',
         body='hello world',
         html_body='<b>hello world</b>',
         reference=self.activity,
         reply_reference=self.group,
     )
     results = msg.get_built_messages(['*****@*****.**'])
     assert len(results) == 1
コード例 #35
0
ファイル: tests.py プロジェクト: Kayle009/sentry
 def test_get_built_messages(self):
     msg = MessageBuilder(
         subject='Test',
         body='hello world',
         html_body='<b>hello world</b>',
         reference=self.activity,
         reply_reference=self.group,
     )
     results = msg.get_built_messages(['*****@*****.**'])
     assert len(results) == 1
コード例 #36
0
ファイル: base.py プロジェクト: alexandrul/sentry
    def send(self):
        if not self.should_email():
            return

        participants = self.get_participants()
        if not participants:
            return

        activity = self.activity
        project = self.project
        group = self.group

        context = self.get_base_context()
        context.update(self.get_context())

        template = self.get_template()
        html_template = self.get_html_template()
        email_type = self.get_email_type()
        headers = self.get_headers()

        for user, reason in participants.items():
            if group:
                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},
                        ),
                    }
                )
            user_context = self.get_user_context(user)
            if user_context:
                user_context.update(context)
            else:
                user_context = context

            msg = MessageBuilder(
                subject=self.get_subject_with_prefix(),
                template=template,
                html_template=html_template,
                headers=headers,
                type=email_type,
                context=user_context,
                reference=activity,
                reply_reference=group,
            )
            msg.add_users([user.id], project=project)
            msg.send_async()
コード例 #37
0
    def post(self, request, organization):
        """
        Email the organization owners asking them to install an integration.
        ````````````````````````````````````````````````````````````````````
        When a non-owner user views integrations in the integrations directory,
        they lack the ability to install them themselves. POSTing to this API
        alerts users with permission that there is demand for this integration.

        :param string providerSlug: Unique string that identifies the integration.
        :param string providerType: One of: first_party, plugin, sentry_app.
        :param string message: Optional message from the requester to the owners.
        """
        provider_type = request.data.get("providerType")
        provider_slug = request.data.get("providerSlug")
        message_option = request.data.get("message", "").strip()

        try:
            provider_name = get_provider_name(provider_type, provider_slug)
        except Exception as error:
            return Response({"detail": error.message}, status=400)

        requester = request.user
        owners_list = organization.get_owners()

        # If for some reason the user had permissions all along, silently fail.
        if requester.id in [user.id for user in owners_list]:
            return Response({"detail": "User can install integration"}, status=200)

        msg = MessageBuilder(
            subject="Your team member requested the %s integration on Sentry" % provider_name,
            template="sentry/emails/requests/organization-integration.txt",
            html_template="sentry/emails/requests/organization-integration.html",
            type="organization.integration.request",
            context={
                "integration_link": get_url(organization, provider_type, provider_slug),
                "integration_name": provider_name,
                "message": message_option,
                "organization_name": organization.name,
                "requester_name": requester.name or requester.username,
                "requester_link": absolute_uri(
                    "/settings/{organization_slug}/members/{user_id}/".format(
                        organization_slug=organization.slug, user_id=requester.id,
                    )
                ),
                "settings_link": absolute_uri(
                    reverse("sentry-organization-settings", args=[organization.slug])
                ),
            },
        )

        msg.send_async([user.email for user in owners_list])

        return Response(status=201)
コード例 #38
0
ファイル: tests.py プロジェクト: Kayle009/sentry
    def test_bcc_on_send(self):
        msg = MessageBuilder(
            subject='Test',
            body='hello world',
        )
        msg.send(['*****@*****.**'], bcc=['*****@*****.**'])

        assert len(mail.outbox) == 1

        out = mail.outbox[0]
        assert out.to == ['*****@*****.**']
        assert out.bcc == ['*****@*****.**']
コード例 #39
0
    def test_bcc_on_send(self):
        msg = MessageBuilder(
            subject='Test',
            body='hello world',
        )
        msg.send(['*****@*****.**'], bcc=['*****@*****.**'])

        assert len(mail.outbox) == 1

        out = mail.outbox[0]
        assert out.to == ['*****@*****.**']
        assert out.bcc == ['*****@*****.**']
コード例 #40
0
ファイル: auth.py プロジェクト: wangjianweiwei/sentry
 def call_to_action(self, org: Organization, user: User,
                    member: OrganizationMember):
     # send invite to setup 2fa
     email_context = {"url": member.get_invite_link(), "organization": org}
     subject = "{} {} Mandatory: Enable Two-Factor Authentication".format(
         options.get("mail.subject-prefix"), org.name.capitalize())
     message = MessageBuilder(
         subject=subject,
         template="sentry/emails/setup_2fa.txt",
         html_template="sentry/emails/setup_2fa.html",
         type="user.setup_2fa",
         context=email_context,
     )
     message.send_async([member.email])
コード例 #41
0
ファイル: auth.py プロジェクト: alexandrul/sentry
def _remove_2fa_non_compliant_member(member, org, actor=None, actor_key=None, ip_address=None):
    user = member.user
    logging_data = {
        'organization_id': org.id,
        'user_id': user.id,
        'member_id': member.id
    }

    try:
        member.email = member.get_email()
        member.user = None
        member.save()
    except (AssertionError, IntegrityError):
        logger.warning(
            'Could not remove 2FA noncompliant user from org',
            extra=logging_data
        )
    else:
        logger.info(
            '2FA noncompliant user removed from org',
            extra=logging_data
        )
        AuditLogEntry.objects.create(
            actor=actor,
            actor_key=actor_key,
            ip_address=ip_address,
            event=AuditLogEntryEvent.MEMBER_PENDING,
            data=member.get_audit_log_data(),
            organization=org,
            target_object=org.id,
            target_user=user,
        )

        # send invite to setup 2fa
        email_context = {
            'url': member.get_invite_link(),
            'organization': org
        }
        subject = u'{} {} Mandatory: Enable Two-Factor Authentication'.format(
            options.get('mail.subject-prefix'),
            org.name.capitalize(),
        )
        message = MessageBuilder(
            subject=subject,
            template='sentry/emails/setup_2fa.txt',
            html_template='sentry/emails/setup_2fa.html',
            type='user.setup_2fa',
            context=email_context,
        )
        message.send_async([member.email])
コード例 #42
0
    def send_request_email(self):
        from sentry.models import OrganizationMember
        from sentry.utils.email import MessageBuilder

        user = self.member.user
        email = user.email
        organization = self.team.organization

        context = {
            "email":
            email,
            "name":
            user.get_display_name(),
            "organization":
            organization,
            "team":
            self.team,
            "url":
            absolute_uri(
                reverse(
                    "sentry-organization-members-requests",
                    kwargs={"organization_slug": organization.slug},
                )),
        }

        if self.requester:
            context.update({"requester": self.requester.get_display_name()})

        msg = MessageBuilder(
            subject="Sentry Access Request",
            template="sentry/emails/request-team-access.txt",
            html_template="sentry/emails/request-team-access.html",
            type="team.access.request",
            context=context,
        )

        global_roles = [
            r.id for r in roles.with_scope("org:write") if r.is_global
        ]
        team_roles = [r.id for r in roles.with_scope("team:write")]

        # find members which are either team scoped or have access to all teams
        member_list = OrganizationMember.objects.filter(
            Q(role__in=global_roles) | Q(teams=self.team, role__in=team_roles),
            organization=self.team.organization,
            user__isnull=False,
        ).select_related("user")

        msg.send_async([m.user.email for m in member_list])
コード例 #43
0
    def email_failure(self, message):
        from sentry.utils.email import MessageBuilder

        msg = MessageBuilder(
            subject="Unable to Export Data",
            context={
                "error_message": message,
                "payload": json.dumps(self.payload, indent=2, sort_keys=True),
            },
            type="organization.export-data",
            template="sentry/emails/data-export-failure.txt",
            html_template="sentry/emails/data-export-failure.html",
        )
        msg.send_async([self.user.email])
        self.delete()
コード例 #44
0
ファイル: models.py プロジェクト: tonyzhu/sentry
    def _send_mail(self, subject, body, html_body=None, project=None,
                   headers=None, fail_silently=False):
        send_to = self.get_send_to(project)
        if not send_to:
            return

        subject_prefix = self.get_option('subject_prefix', project) or self.subject_prefix

        msg = MessageBuilder(
            subject='%s%s' % (subject_prefix, subject),
            body=body,
            html_body=html_body,
            headers=headers,
        )
        msg.send(send_to, fail_silently=fail_silently)
コード例 #45
0
    def send_delete_confirmation(self, audit_log_entry, countdown):
        from sentry import options
        from sentry.utils.email import MessageBuilder

        owners = self.get_owners()

        context = {
            'organization':
            self,
            'audit_log_entry':
            audit_log_entry,
            'eta':
            timezone.now() + timedelta(seconds=countdown),
            'url':
            absolute_uri(
                reverse(
                    'sentry-restore-organization',
                    args=[self.slug],
                )),
        }

        MessageBuilder(
            subject='%sOrganization Queued for Deletion' %
            (options.get('mail.subject-prefix'), ),
            template='sentry/emails/org_delete_confirm.txt',
            html_template='sentry/emails/org_delete_confirm.html',
            type='org.confirm_delete',
            context=context,
        ).send_async([o.email for o in owners])
コード例 #46
0
ファイル: organization.py プロジェクト: code-watch/sentry
    def send_delete_confirmation(self, audit_log_entry, countdown):
        from sentry import options
        from sentry.utils.email import MessageBuilder

        owners = self.get_owners()

        context = {
            "organization":
            self,
            "audit_log_entry":
            audit_log_entry,
            "eta":
            timezone.now() + timedelta(seconds=countdown),
            "url":
            absolute_uri(
                reverse("sentry-restore-organization", args=[self.slug])),
        }

        MessageBuilder(
            subject="{}Organization Queued for Deletion".format(
                options.get("mail.subject-prefix")),
            template="sentry/emails/org_delete_confirm.txt",
            html_template="sentry/emails/org_delete_confirm.html",
            type="org.confirm_delete",
            context=context,
        ).send_async([o.email for o in owners])
コード例 #47
0
def generate_security_email(account, type, actor, ip_address, context=None, current_datetime=None):
    if current_datetime is None:
        current_datetime = timezone.now()

    subject = 'Security settings changed'
    if type == 'mfa-removed':
        assert 'authenticator' in context
        template = 'sentry/emails/mfa-removed.txt'
        html_template = 'sentry/emails/mfa-removed.html'
    elif type == 'mfa-added':
        assert 'authenticator' in context
        template = 'sentry/emails/mfa-added.txt'
        html_template = 'sentry/emails/mfa-added.html'
    elif type == 'password-changed':
        template = 'sentry/emails/password-changed.txt'
        html_template = 'sentry/emails/password-changed.html'
    else:
        raise ValueError('unknown type: {}'.format(type))

    new_context = {
        'account': account,
        'actor': actor,
        'ip_address': ip_address,
        'datetime': current_datetime,
    }
    if context:
        new_context.update(context)

    return MessageBuilder(
        subject=subject,
        context=new_context,
        template=template,
        html_template=html_template,
    )
コード例 #48
0
ファイル: activity.py プロジェクト: KinKir/sentry
    def send_notification(self):
        from sentry.utils.email import MessageBuilder, group_id_to_email

        if not self.group_id:
            return

        if self.type not in (Activity.NOTE, Activity.ASSIGNED):
            return

        send_to = self.get_recipients()

        if not send_to:
            return

        author = self.user.first_name or self.user.username

        subject_prefix = self.project.get_option(
            'subject_prefix', settings.EMAIL_SUBJECT_PREFIX)
        if subject_prefix:
            subject_prefix = subject_prefix.rstrip() + ' '

        subject = '%s%s' % (subject_prefix, self.group.get_email_subject())

        context = {
            'data': self.data,
            'author': author,
            'group': self.group,
            'link': self.group.get_absolute_url(),
        }

        headers = {
            'X-Sentry-Reply-To': group_id_to_email(self.group.id),
        }

        template_name = self.get_type_display()

        msg = MessageBuilder(
            subject=subject,
            context=context,
            template='sentry/emails/activity/{}.txt'.format(template_name),
            html_template='sentry/emails/activity/{}.html'.format(template_name),
            headers=headers,
            reference=self,
            reply_reference=self.group,
        )
        msg.add_users(send_to, project=self.project)
        msg.send_async()
コード例 #49
0
def _remove_2fa_non_compliant_member(member,
                                     org,
                                     actor=None,
                                     actor_key=None,
                                     ip_address=None):
    user = member.user
    logging_data = {
        'organization_id': org.id,
        'user_id': user.id,
        'member_id': member.id
    }

    try:
        member.email = member.get_email()
        member.user = None
        member.save()
    except (AssertionError, IntegrityError):
        logger.warning('Could not remove 2FA noncompliant user from org',
                       extra=logging_data)
    else:
        logger.info('2FA noncompliant user removed from org',
                    extra=logging_data)
        AuditLogEntry.objects.create(
            actor=actor,
            actor_key=actor_key,
            ip_address=ip_address,
            event=AuditLogEntryEvent.MEMBER_PENDING,
            data=member.get_audit_log_data(),
            organization=org,
            target_object=org.id,
            target_user=user,
        )

        # send invite to setup 2fa
        email_context = {'url': member.get_invite_link(), 'organization': org}
        subject = u'{} {} Mandatory: Enable Two-Factor Authentication'.format(
            options.get('mail.subject-prefix'),
            org.name.capitalize(),
        )
        message = MessageBuilder(
            subject=subject,
            template='sentry/emails/setup_2fa.txt',
            html_template='sentry/emails/setup_2fa.html',
            type='user.setup_2fa',
            context=email_context,
        )
        message.send_async([member.email])
コード例 #50
0
    def send_request_email(self):
        from sentry.models import OrganizationMember
        from sentry.utils.email import MessageBuilder

        user = self.member.user
        email = user.email
        organization = self.team.organization

        context = {
            'email':
            email,
            'name':
            user.get_display_name(),
            'organization':
            organization,
            'team':
            self.team,
            'url':
            absolute_uri(
                reverse('sentry-organization-members',
                        kwargs={
                            'organization_slug': organization.slug,
                        }) + '?ref=access-requests'),
        }

        msg = MessageBuilder(
            subject='Sentry Access Request',
            template='sentry/emails/request-team-access.txt',
            html_template='sentry/emails/request-team-access.html',
            context=context,
        )

        roles_capable = [r.id for r in roles.with_scope('team:write')]
        non_global_roles = [
            r for r in roles_capable if not roles.get(r).is_global
            or roles.get(r).has_scope('member:write')
        ]

        # find members which are either team scoped or have access to all teams
        member_list = OrganizationMember.objects.filter(
            Q(role__in=non_global_roles)
            | Q(teams=self.team, role__in=roles_capable),
            organization=self.team.organization,
            user__isnull=False,
        ).select_related('user')

        msg.send_async([m.user.email for m in member_list])
コード例 #51
0
ファイル: base.py プロジェクト: bsergean/sentry
    def send(self):
        if not self.should_email():
            return

        users = self.get_participants()
        if not users:
            return

        activity = self.activity
        project = self.project
        group = self.group

        context = self.get_base_context()
        context.update(self.get_context())

        subject_prefix = self._get_subject_prefix()

        subject = (u'{}{}'.format(
            subject_prefix,
            self.get_subject(),
        )).encode('utf-8')
        template = self.get_template()
        html_template = self.get_html_template()
        email_type = self.get_email_type()
        headers = self.get_headers()

        for user in users:
            if group:
                context['unsubscribe_link'] = generate_signed_link(
                    user.id,
                    'sentry-account-email-unsubscribe-issue',
                    kwargs={'issue_id': group.id},
                )

            msg = MessageBuilder(
                subject=subject,
                template=template,
                html_template=html_template,
                headers=headers,
                type=email_type,
                context=context,
                reference=activity,
                reply_reference=group,
            )
            msg.add_users([user.id], project=project)
            msg.send_async()
コード例 #52
0
    def send_recover_mail(self):
        from sentry.utils.email import MessageBuilder

        context = {
            'user': self.user,
            'domain': urlparse(settings.SENTRY_URL_PREFIX).hostname,
            'url': absolute_uri(reverse(
                'sentry-account-recover-confirm',
                args=[self.user.id, self.hash]
            )),
        }
        msg = MessageBuilder(
            subject='%sPassword Recovery' % (settings.EMAIL_SUBJECT_PREFIX,),
            template='sentry/emails/recover_account.txt',
            context=context,
        )
        msg.send_async([self.user.email])
コード例 #53
0
ファイル: models.py プロジェクト: jiangge/sentry
    def email_failure(self, message):
        from sentry.utils.email import MessageBuilder

        msg = MessageBuilder(
            subject="We couldn't export your data.",
            context={
                "creation": self.format_date(self.date_added),
                "error_message": message,
                "payload": json.dumps(self.payload, indent=2, sort_keys=True),
            },
            type="organization.export-data",
            template="sentry/emails/data-export-failure.txt",
            html_template="sentry/emails/data-export-failure.html",
        )
        msg.send_async([self.user.email])
        metrics.incr("dataexport.end", instance="failure")
        self.delete()
コード例 #54
0
    def send_approved_email(self):
        from sentry.utils.email import MessageBuilder

        user = self.member.user
        email = user.email
        organization = self.team.organization

        context = {"email": email, "name": user.get_display_name(), "organization": organization, "team": self.team}

        msg = MessageBuilder(
            subject="Sentry Access Request",
            template="sentry/emails/access-approved.txt",
            html_template="sentry/emails/access-approved.html",
            context=context,
        )

        msg.send_async([email])
コード例 #55
0
    def send_sso_link_email(self):
        from sentry.utils.email import MessageBuilder

        context = {
            'email': self.email,
            'organization_name': self.organization.name,
            'url': absolute_uri(reverse('sentry-auth-link-identity', kwargs={
                'organization_slug': self.organization.slug,
            })),
        }

        msg = MessageBuilder(
            subject='Action Required for %s' % (self.organization.name,),
            template='sentry/emails/auth-link-identity.txt',
            html_template='sentry/emails/auth-link-identity.html',
            context=context,
        )
        msg.send_async([self.get_email()])
コード例 #56
0
    def send_recover_mail(self):
        from sentry import options
        from sentry.http import get_server_hostname
        from sentry.utils.email import MessageBuilder

        context = {
            'user': self.user,
            'domain': get_server_hostname(),
            'url': self.get_absolute_url(),
        }
        msg = MessageBuilder(
            subject='%sPassword Recovery' % (options.get('mail.subject-prefix'),),
            template='sentry/emails/recover_account.txt',
            html_template='sentry/emails/recover_account.html',
            type='user.password_recovery',
            context=context,
        )
        msg.send_async([self.user.email])
コード例 #57
0
ファイル: models.py プロジェクト: arty-name/sentry
    def _send_mail(self, subject, template=None, html_template=None, body=None,
                   project=None, headers=None, context=None, fail_silently=False):
        send_to = self.get_send_to(project)
        if not send_to:
            return

        subject_prefix = self.get_option('subject_prefix', project) or self.subject_prefix

        msg = MessageBuilder(
            subject='%s%s' % (subject_prefix, subject),
            template=template,
            html_template=html_template,
            body=body,
            headers=headers,
            context=context,
        )
        msg.add_users(send_to, project=project)
        return msg.send(fail_silently=fail_silently)
コード例 #58
0
ファイル: models.py プロジェクト: russelldavis/sentry
    def send_notification(self):
        from sentry.utils.email import MessageBuilder

        if self.type != Activity.NOTE or not self.group:
            return

        user_list = list(User.objects.filter(
            groupseen__group=self.group,
        ).exclude(user=self.user))
        disabled = set(UserOption.objects.filter(
            user__in=user_list, key='subscribe_comments', value='0'))

        send_to = [
            u.email for u in user_list
            if u.id not in disabled
            and u.email
        ]

        author = self.user.first_name or self.user.username

        subject = '%s: %s' % (
            author,
            self.data['text'].splitlines()[0][:64])

        context = {
            'text': self.data['text'],
            'author': author,
            'group': self.group,
            'link': self.group.get_absolute_url(),
        }

        msg = MessageBuilder(
            subject=subject,
            context=context,
            template='sentry/emails/new_note.txt',
            html_template='sentry/emails/new_note.html',
        )

        try:
            msg.send(to=send_to)
        except Exception, e:
            logger = logging.getLogger('sentry.mail.errors')
            logger.exception(e)
コード例 #59
0
ファイル: lostpasswordhash.py プロジェクト: 280185386/sentry
    def send_recover_mail(self):
        from sentry import options
        from sentry.http import get_server_hostname
        from sentry.utils.email import MessageBuilder

        context = {
            'user': self.user,
            'domain': get_server_hostname(),
            'url': absolute_uri(reverse(
                'sentry-account-recover-confirm',
                args=[self.user.id, self.hash]
            )),
        }
        msg = MessageBuilder(
            subject='%sPassword Recovery' % (options.get('mail.subject-prefix'),),
            template='sentry/emails/recover_account.txt',
            context=context,
        )
        msg.send_async([self.user.email])