Beispiel #1
0
    def send_mail(self, template_prefix, email, context):
        subject = render_to_string(
            '{0}_subject.txt'.format(template_prefix), context
        )
        subject = " ".join(subject.splitlines()).strip()
        subject = self.format_email_subject(subject)

        # Allauth sends some additional data in the context, remove it if the
        # pieces can't be json encoded
        removed_keys = []
        for key in list(context.keys()):
            try:
                _ = json.dumps(context[key])  # noqa for F841
            except (ValueError, TypeError):
                removed_keys.append(key)
                del context[key]
        if removed_keys:
            log.debug('Removed context we were unable to serialize: %s',
                      removed_keys)

        send_email(
            recipient=email,
            subject=subject,
            template='{0}_message.txt'.format(template_prefix),
            template_html='{0}_message.html'.format(template_prefix),
            context=context
        )
Beispiel #2
0
def email_notification(version, build, email):
    """Send email notifications for build failure

    :param version: :py:cls:`Version` instance that failed
    :param build: :py:cls:`Build` instance that failed
    :param email: Email recipient address
    """
    log.debug(LOG_TEMPLATE.format(project=version.project.slug, version=version.slug,
                                  msg='sending email to: %s' % email))
    context = {'version': version,
               'project': version.project,
               'build': build,
               'build_url': 'https://{0}{1}'.format(
                   getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
                   build.get_absolute_url()),
               'unsub_url': 'https://{0}{1}'.format(
                   getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
                   reverse('projects_notifications', args=[version.project.slug])),
               }

    if build.commit:
        title = _('Failed: {project.name} ({commit})').format(commit=build.commit[:8], **context)
    else:
        title = _('Failed: {project.name} ({version.verbose_name})').format(**context)

    send_email(
        email,
        title,
        template='projects/email/build_failed.txt',
        template_html='projects/email/build_failed.html',
        context=context
    )
Beispiel #3
0
def email_notification(version, build, email):
    """Send email notifications for build failure

    :param version: :py:class:`Version` instance that failed
    :param build: :py:class:`Build` instance that failed
    :param email: Email recipient address
    """
    log.debug(
        LOG_TEMPLATE.format(project=version.project.slug, version=version.slug, msg="sending email to: %s" % email)
    )
    context = {
        "version": version,
        "project": version.project,
        "build": build,
        "build_url": "https://{0}{1}".format(
            getattr(settings, "PRODUCTION_DOMAIN", "readthedocs.org"), build.get_absolute_url()
        ),
        "unsub_url": "https://{0}{1}".format(
            getattr(settings, "PRODUCTION_DOMAIN", "readthedocs.org"),
            reverse("projects_notifications", args=[version.project.slug]),
        ),
    }

    if build.commit:
        title = _("Failed: {project.name} ({commit})").format(commit=build.commit[:8], **context)
    else:
        title = _("Failed: {project.name} ({version.verbose_name})").format(**context)

    send_email(
        email,
        title,
        template="projects/email/build_failed.txt",
        template_html="projects/email/build_failed.html",
        context=context,
    )
Beispiel #4
0
def email_notification(version, build, email):
    """
    Send email notifications for build failure.

    :param version: :py:class:`Version` instance that failed
    :param build: :py:class:`Build` instance that failed
    :param email: Email recipient address
    """
    log.debug(LOG_TEMPLATE.format(project=version.project.slug, version=version.slug,
                                  msg='sending email to: %s' % email))
    context = {'version': version,
               'project': version.project,
               'build': build,
               'build_url': 'https://{0}{1}'.format(
                   getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
                   build.get_absolute_url()),
               'unsub_url': 'https://{0}{1}'.format(
                   getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
                   reverse('projects_notifications', args=[version.project.slug])),
               }

    if build.commit:
        title = _('Failed: {project.name} ({commit})').format(commit=build.commit[:8], **context)
    else:
        title = _('Failed: {project.name} ({version.verbose_name})').format(**context)

    send_email(
        email,
        title,
        template='projects/email/build_failed.txt',
        template_html='projects/email/build_failed.html',
        context=context
    )
    def form_valid(self, form):
        """If form is valid, send emails to selected recipients

        This treats the body field as a string template, so full template tags
        are allowed in the field.  The object will be available in the template
        as the variable specified by the ``email_context_object_name`` class
        variable.
        """
        count = 0
        template = Template(form.cleaned_data['body'])
        for obj in self.get_queryset().all():
            ctx = Context()
            if self.email_context_data is not None:
                ctx.update(self.email_context_data)
            ctx[self.email_context_object_name] = obj
            for recipient in self.get_object_recipients(obj):
                send_email(
                    recipient.email,
                    subject=form.cleaned_data['subject'],
                    template='core/email/common.txt',
                    template_html='core/email/common.html',
                    context={'content': template.render(ctx)},
                    request=self.request,
                )
                count += 1
        if count == 0:
            self.message_user("No recipients to send to", level=messages.ERROR)
        else:
            self.message_user("Queued {0} messages".format(count))
        return HttpResponseRedirect(self.request.get_full_path())
Beispiel #6
0
def email_notification(version, build, email):
    """
    Send email notifications for build failure.

    :param version: :py:class:`Version` instance that failed
    :param build: :py:class:`Build` instance that failed
    :param email: Email recipient address
    """
    log.debug(
        LOG_TEMPLATE.format(
            project=version.project.slug,
            version=version.slug,
            msg='sending email to: %s' % email,
        ),
    )

    # We send only what we need from the Django model objects here to avoid
    # serialization problems in the ``readthedocs.core.tasks.send_email_task``
    context = {
        'version': {
            'verbose_name': version.verbose_name,
        },
        'project': {
            'name': version.project.name,
        },
        'build': {
            'pk': build.pk,
            'error': build.error,
        },
        'build_url': 'https://{}{}'.format(
            getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
            build.get_absolute_url(),
        ),
        'unsub_url': 'https://{}{}'.format(
            getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
            reverse('projects_notifications', args=[version.project.slug]),
        ),
    }

    if build.commit:
        title = _(
            'Failed: {project[name]} ({commit})',
        ).format(commit=build.commit[:8], **context)
    else:
        title = _('Failed: {project[name]} ({version[verbose_name]})').format(
            **context
        )

    send_email(
        email,
        title,
        template='projects/email/build_failed.txt',
        template_html='projects/email/build_failed.html',
        context=context,
    )
Beispiel #7
0
 def send(self, notification):
     if notification.level >= REQUIREMENT:
         send_email(
             recipient=notification.user.email,
             subject=notification.get_subject(),
             template='core/email/common.txt',
             template_html='core/email/common.html',
             context={
                 'content': notification.render(self.name, source_format=HTML),
             },
             request=self.request,
         )
Beispiel #8
0
    def send_email(self, email):
        """Send email notifications for build failures."""
        # We send only what we need from the Django model objects here to avoid
        # serialization problems in the ``readthedocs.core.tasks.send_email_task``
        protocol = 'http' if settings.DEBUG else 'https'
        context = {
            'version': {
                'verbose_name': self.version.verbose_name,
            },
            'project': {
                'name': self.project.name,
            },
            'build': {
                'pk': self.build.pk,
                'error': self.build.error,
            },
            'build_url':
            '{}://{}{}'.format(
                protocol,
                settings.PRODUCTION_DOMAIN,
                self.build.get_absolute_url(),
            ),
            'unsubscribe_url':
            '{}://{}{}'.format(
                protocol,
                settings.PRODUCTION_DOMAIN,
                reverse('projects_notifications', args=[self.project.slug]),
            ),
        }

        if self.build.commit:
            title = _('Failed: {project[name]} ({commit})').format(
                commit=self.build.commit[:8],
                **context,
            )
        else:
            title = _('Failed: {project[name]} ({version[verbose_name]})'
                      ).format(**context)

        log.info(
            'Sending email notification.',
            email=email,
            project_slug=self.project.slug,
            version_slug=self.version.slug,
            build_id=self.build.id,
        )
        send_email(
            email,
            title,
            template='projects/email/build_failed.txt',
            template_html='projects/email/build_failed.html',
            context=context,
        )
Beispiel #9
0
def weekly_subscription_stats_email(recipients=None):
    """
    Weekly email to communicate stats about subscriptions.

    :param list recipients: List of emails to send the stats to.
    """
    if not recipients:
        log.info('No recipients to send stats to.')
        return

    last_week = timezone.now() - datetime.timedelta(weeks=1)
    yesterday = timezone.now() - datetime.timedelta(days=1)

    projects = Project.objects.filter(pub_date__gte=last_week).count()
    builds = Build.objects.filter(date__gte=last_week).count()
    organizations = Organization.objects.filter(pub_date__gte=last_week).count()
    domains = Domain.objects.filter(created__gte=last_week).count()
    organizations_to_disable = Organization.objects.disable_soon(days=30).count()
    users = User.objects.filter(date_joined__gte=last_week).count()
    subscriptions = (
        Subscription.objects
        .filter(
            trial_end_date__gte=last_week,
            trial_end_date__lte=yesterday,
        )
        .values('status', 'plan__name')
        .annotate(total_status=Count('status'))
        .order_by('status')
    )
    context = {
        'projects': projects,
        'builds': builds,
        'organizations': organizations,
        'domains': domains,
        'organizations_to_disable': organizations_to_disable,
        'users': users,
        'subscriptions': list(subscriptions),
    }

    log.info('Sending weekly subscription stats email.')
    send_email(
        from_email='Read the Docs <*****@*****.**>',
        subject='Weekly subscription stats',
        recipient=recipients[0],
        template='subscriptions/notifications/subscription_stats_email.txt',
        template_html=None,
        context=context,
        # Use ``cc`` here because our ``send_email`` does not accept a list of recipients
        cc=recipients[1:],
    )
Beispiel #10
0
def send_team_invite_email(invite, request):
    """Send an organization team invite email."""
    log.info('Sending team invite.', team=invite.team, email=invite.email)
    send_email(
        invite.email,
        subject='Join your team at Read the Docs',
        template='organizations/email/team_invite.txt',
        template_html='organizations/email/team_invite.html',
        context={
            'invite_hash': invite.hash,
            'sender_full_name': request.user.get_full_name(),
            'sender_username': request.user.username,
            'organization_name': invite.organization.name,
        },
        request=request,
    )
Beispiel #11
0
def email_notification(version, build, email):
    """
    Send email notifications for build failure.

    :param version: :py:class:`Version` instance that failed
    :param build: :py:class:`Build` instance that failed
    :param email: Email recipient address
    """
    log.debug(LOG_TEMPLATE.format(project=version.project.slug, version=version.slug,
                                  msg='sending email to: %s' % email))

    # We send only what we need from the Django model objects here to avoid
    # serialization problems in the ``readthedocs.core.tasks.send_email_task``
    context = {
        'version': {
            'verbose_name': version.verbose_name,
        },
        'project': {
            'name': version.project.name,
        },
        'build': {
            'pk': build.pk,
            'error': build.error,
        },
        'build_url': 'https://{0}{1}'.format(
            getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
            build.get_absolute_url(),
        ),
        'unsub_url': 'https://{0}{1}'.format(
            getattr(settings, 'PRODUCTION_DOMAIN', 'readthedocs.org'),
            reverse('projects_notifications', args=[version.project.slug]),
        ),
    }

    if build.commit:
        title = _('Failed: {project[name]} ({commit})').format(commit=build.commit[:8], **context)
    else:
        title = _('Failed: {project[name]} ({version[verbose_name]})').format(**context)

    send_email(
        email,
        title,
        template='projects/email/build_failed.txt',
        template_html='projects/email/build_failed.html',
        context=context,
    )
Beispiel #12
0
 def form_valid(self, form):
     """If form is valid, send emails to selected users"""
     count = 0
     for user in self.get_queryset().all():
         send_email(
             user.email,
             subject=form.cleaned_data['subject'],
             template='core/email/common.txt',
             template_html='core/email/common.html',
             context={'user': user, 'content': form.cleaned_data['body']},
             request=self.request,
         )
         count += 1
     if count == 0:
         self.message_user("No recipients to send to", level=messages.ERROR)
     else:
         self.message_user("Queued {0} messages".format(count))
     return HttpResponseRedirect(self.request.get_full_path())
 def send(self, notification):
     # FIXME: if the level is an ERROR an email is received and sometimes
     # it's not necessary. This behavior should be clearly documented in the
     # code
     if notification.level >= REQUIREMENT:
         send_email(
             recipient=notification.user.email,
             subject=notification.get_subject(),
             template='core/email/common.txt',
             template_html='core/email/common.html',
             context={
                 'content':
                 notification.render(
                     self.name,
                     source_format=HTML,
                 ),
             },
             request=self.request,
         )
Beispiel #14
0
def send_team_add_email(team_member, request):
    """Send an organization team add email."""
    log.info(
        'Sending team add notification.',
        team=team_member.team,
        email=team_member.member.email,
    )
    send_email(
        team_member.member.email,
        subject='Join your team at Read the Docs',
        template='organizations/email/team_add.txt',
        template_html='organizations/email/team_add.html',
        context={
            'sender_full_name': request.user.get_full_name(),
            'sender_username': request.user.username,
            'organization_name': team_member.team.organization.name,
            'organization_slug': team_member.team.organization.slug,
        },
        request=request,
    )
Beispiel #15
0
 def send(self, notification):
     if not notification.send_email:
         return
     # FIXME: if the level is an ERROR an email is received and sometimes
     # it's not necessary. This behavior should be clearly documented in the
     # code
     if notification.level >= REQUIREMENT:
         send_email(
             recipient=notification.user.email,
             subject=notification.get_subject(),
             template='core/email/common.txt',
             template_html='core/email/common.html',
             context={
                 'content': notification.render(
                     self.name,
                     source_format=HTML,
                 ),
             },
             request=self.request,
         )
Beispiel #16
0
 def form_valid(self, form):
     """If form is valid, send emails to selected users"""
     count = 0
     for user in self.get_queryset().all():
         send_email(
             user.email,
             subject=form.cleaned_data['subject'],
             template='core/email/common.txt',
             template_html='core/email/common.html',
             context={
                 'user': user,
                 'content': form.cleaned_data['body']
             },
             request=self.request,
         )
         count += 1
     if count == 0:
         self.message_user("No receipients to send to",
                           level=messages.ERROR)
     else:
         self.message_user("Queued {0} messages".format(count))
     return HttpResponseRedirect(self.request.get_full_path())