Exemplo n.º 1
0
def mail_admins_contact(request, subject, message, context, sender, to):
    """Send a message to the admins, as defined by the ADMINS setting."""
    LOGGER.info(
        'contact form from %s',
        sender,
    )
    if not to and settings.ADMINS:
        to = [a[1] for a in settings.ADMINS]
    elif not settings.ADMINS:
        messages.error(
            request,
            _('Message could not be sent to administrator!')
        )
        LOGGER.error(
            'ADMINS not configured, can not send message!'
        )
        return

    mail = EmailMultiAlternatives(
        '{0}{1}'.format(settings.EMAIL_SUBJECT_PREFIX, subject % context),
        message % context,
        to=to,
        headers={'Reply-To': sender},
    )

    mail.send(fail_silently=False)

    messages.success(
        request,
        _('Message has been sent to administrator.')
    )
Exemplo n.º 2
0
 def report_error(self, exc, request, message):
     """Wrapper for handling error situations"""
     extra = {'mt_url': self.request_url, 'mt_params': self.request_params}
     report_error(exc, request, extra, prefix='Machine translation error')
     LOGGER.error(message, self.name)
     LOGGER.info(
         'Last URL: %s, params: %s', extra['mt_url'], extra['mt_params']
     )
Exemplo n.º 3
0
def get_notification_email(language, email, notification,
                           context=None, info=None):
    """Render notification email."""
    context = context or {}
    headers = {}

    LOGGER.info(
        'sending notification %s on %s to %s',
        notification,
        info,
        email
    )

    with override('en' if language is None else language):
        # Template name
        context['subject_template'] = 'mail/{0}_subject.txt'.format(
            notification
        )
        context['LANGUAGE_CODE'] = get_language()
        context['LANGUAGE_BIDI'] = get_language_bidi()

        # Adjust context
        context['current_site_url'] = get_site_url()
        context['site_title'] = settings.SITE_TITLE

        # Render subject
        subject = render_to_string(
            context['subject_template'],
            context
        ).strip()

        # Render body
        html_body = render_to_string(
            'mail/{0}.html'.format(notification),
            context
        )
        body = html2text(html_body)

        # Define headers
        headers['Auto-Submitted'] = 'auto-generated'
        headers['X-AutoGenerated'] = 'yes'
        headers['Precedence'] = 'bulk'
        headers['X-Mailer'] = 'Weblate {0}'.format(VERSION)

        # List of recipients
        if email == 'ADMINS':
            emails = [a[1] for a in settings.ADMINS]
        else:
            emails = [email]

        # Return the mail content
        return {
            'subject': subject,
            'body': body,
            'to': emails,
            'headers': headers,
            'html_body': html_body,
        }
Exemplo n.º 4
0
    def clean_captcha(self):
        """
        Validation for captcha.
        """
        if self.tampering or not self.captcha.validate(self.cleaned_data["captcha"]):
            raise forms.ValidationError(_("Please check your math and try again."))

        mail = self.cleaned_data.get("email", "NONE")

        LOGGER.info("Passed captcha for %s (%s = %s)", mail, self.captcha.question, self.cleaned_data["captcha"])
Exemplo n.º 5
0
 def send_immediate(self, language, email, change):
     with override('en' if language is None else language):
         context = self.get_context(change)
         subject = self.render_template('_subject.txt', context)
         context['subject'] = subject
         LOGGER.info(
             'sending notification %s on %s to %s',
             self.get_name(), context['component'], email,
         )
         self.send(
             email,
             subject,
             self.render_template('.html', context),
             self.get_headers(context),
         )
Exemplo n.º 6
0
    def clean_captcha(self):
        """Validation for captcha."""
        if (self.fresh or
                not self.captcha.validate(self.cleaned_data['captcha'])):
            raise forms.ValidationError(
                _('Please check your math and try again.')
            )

        mail = self.cleaned_data.get('email', 'NONE')

        LOGGER.info(
            'Passed captcha for %s (%s = %s)',
            mail,
            self.captcha.question,
            self.cleaned_data['captcha']
        )
Exemplo n.º 7
0
 def send_digest(self, language, email, changes):
     with override('en' if language is None else language):
         context = self.get_context()
         context['changes'] = changes
         subject = self.render_template(
             '_subject.txt', context, digest=True
         )
         context['subject'] = subject
         LOGGER.info(
             'sending digest notification %s on %d changes to %s',
             self.get_name(), len(changes), email,
         )
         self.send(
             email,
             subject,
             self.render_template('.html', context, digest=True),
             self.get_headers(context),
         )
Exemplo n.º 8
0
def mail_admins_contact(request, subject, message, context, sender):
    """
    Sends a message to the admins, as defined by the ADMINS setting.
    """
    LOGGER.info("contact form from %s", sender)
    if not settings.ADMINS:
        messages.error(request, _("Message could not be sent to administrator!"))
        LOGGER.error("ADMINS not configured, can not send message!")
        return

    mail = EmailMultiAlternatives(
        "%s%s" % (settings.EMAIL_SUBJECT_PREFIX, subject % context),
        message % context,
        to=[a[1] for a in settings.ADMINS],
        headers={"Reply-To": sender},
    )

    mail.send(fail_silently=False)

    messages.success(request, _("Message has been sent to administrator."))
Exemplo n.º 9
0
    def clean_captcha(self):
        """Validation for CAPTCHA."""
        if (self.fresh or
                not self.captcha.validate(self.cleaned_data['captcha'])):
            self.generate_captcha()
            rotate_token(self.request)
            raise forms.ValidationError(
                _('Please check your math and try again with new expression.')
            )

        if self.form.is_valid():
            mail = self.form.cleaned_data['email']
        else:
            mail = 'NONE'

        LOGGER.info(
            'Passed captcha for %s (%s = %s)',
            mail,
            self.captcha.question,
            self.cleaned_data['captcha']
        )
Exemplo n.º 10
0
    def clean_captcha(self):
        '''
        Validation for captcha.
        '''
        if (self.tampering or
                not self.captcha.validate(self.cleaned_data['captcha'])):
            raise forms.ValidationError(
                _('Please check your math and try again.')
            )

        if 'email' in self.cleaned_data:
            mail = self.cleaned_data['email']
        else:
            mail = 'NONE'

        LOGGER.info(
            'Passed captcha for %s (%s = %s)',
            mail,
            self.captcha.question,
            self.cleaned_data['captcha']
        )
Exemplo n.º 11
0
def get_notification_email(language,
                           email,
                           notification,
                           translation_obj=None,
                           context=None,
                           headers=None,
                           user=None,
                           info=None):
    """Render notification email."""
    context = context or {}
    headers = headers or {}
    references = None
    if 'unit' in context:
        unit = context['unit']
        references = '{0}/{1}/{2}/{3}'.format(
            unit.translation.component.project.slug,
            unit.translation.component.slug, unit.translation.language.code,
            unit.id)
    if references is not None:
        references = '<{0}@{1}>'.format(references, get_site_domain())
        headers['In-Reply-To'] = references
        headers['References'] = references

    if info is None:
        info = force_text(translation_obj)

    LOGGER.info('sending notification %s on %s to %s', notification, info,
                email)

    with django_translation.override('en' if language is None else language):
        # Template name
        context['subject_template'] = 'mail/{0}_subject.txt'.format(
            notification)
        context['LANGUAGE_CODE'] = django_translation.get_language()
        context['LANGUAGE_BIDI'] = django_translation.get_language_bidi()

        # Adjust context
        context['current_site_url'] = get_site_url()
        if translation_obj is not None:
            context['translation'] = translation_obj
            context['translation_url'] = get_site_url(
                translation_obj.get_absolute_url())
        context['site_title'] = settings.SITE_TITLE

        # Render subject
        subject = render_to_string(context['subject_template'],
                                   context).strip()

        # Render body
        body = render_to_string('mail/{0}.txt'.format(notification), context)
        html_body = render_to_string('mail/{0}.html'.format(notification),
                                     context)

        # Define headers
        headers['Auto-Submitted'] = 'auto-generated'
        headers['X-AutoGenerated'] = 'yes'
        headers['Precedence'] = 'bulk'
        headers['X-Mailer'] = 'Weblate {0}'.format(VERSION)

        # Reply to header
        if user is not None:
            headers['Reply-To'] = user.email

        # List of recipients
        if email == 'ADMINS':
            emails = [a[1] for a in settings.ADMINS]
        else:
            emails = [email]

        # Return the mail content
        return {
            'subject': subject,
            'body': body,
            'to': emails,
            'headers': headers,
            'html_body': html_body,
        }
Exemplo n.º 12
0
def vcs_service_hook(request, service):
    """Shared code between VCS service hooks.

    Currently used for bitbucket_hook, github_hook and gitlab_hook, but should
    be usable for other VCS services (Google Code, custom coded sites, etc.)
    too.
    """
    # We support only post methods
    if not settings.ENABLE_HOOKS:
        return HttpResponseNotAllowed(())

    # Check if we got payload
    try:
        data = parse_hook_payload(request)
    except (ValueError, KeyError, UnicodeError):
        return HttpResponseBadRequest('Could not parse JSON payload!')

    # Get service helper
    hook_helper = HOOK_HANDLERS[service]

    # Send the request data to the service handler.
    try:
        service_data = hook_helper(data)
    except Exception as error:
        LOGGER.error('failed to parse service %s data', service)
        report_error(error, sys.exc_info())
        return HttpResponseBadRequest('Invalid data in json payload!')

    # This happens on ping request upon installation
    if service_data is None:
        return hook_response('Hook working')

    # Log data
    service_long_name = service_data['service_long_name']
    repos = service_data['repos']
    repo_url = service_data['repo_url']
    branch = service_data['branch']
    full_name = service_data['full_name']

    # Generate filter
    spfilter = Q(repo__in=repos) | Q(repo__iendswith=full_name)

    # We need to match also URLs which include username and password
    for repo in repos:
        if not repo.startswith('https://'):
            continue
        spfilter = spfilter | (
            Q(repo__startswith='https://') &
            Q(repo__endswith='@{0}'.format(repo[8:]))
        )

    all_components = Component.objects.filter(spfilter)

    if branch is not None:
        all_components = all_components.filter(branch=branch)

    components = all_components.filter(project__enable_hooks=True)

    LOGGER.info(
        'received %s notification on repository %s, branch %s, '
        '%d matching components, %d to process',
        service_long_name, repo_url, branch,
        all_components.count(), components.count(),
    )

    # Trigger updates
    updates = 0
    for obj in components:
        updates += 1
        LOGGER.info(
            '%s notification will update %s',
            service_long_name,
            obj
        )
        perform_update(obj)

    if updates == 0:
        return hook_response('No matching repositories found!', 'failure')

    return hook_response('Update triggered: {}'.format(
        ', '.join([obj.log_prefix for obj in components])
    ))
Exemplo n.º 13
0
def vcs_service_hook(request, service):
    '''
    Shared code between VCS service hooks.

    Currently used for bitbucket_hook, github_hook and gitlab_hook, but should
    be usable for other VCS services (Google Code, custom coded sites, etc.)
    too.
    '''
    # Check for enabled hooks
    if appsettings.ENABLE_HOOKS:
        allowed_methods = ('POST', )
    else:
        allowed_methods = ()

    # We support only post methods
    if not appsettings.ENABLE_HOOKS or request.method not in allowed_methods:
        return HttpResponseNotAllowed(allowed_methods)

    # Check if we got payload
    try:
        # GitLab sends json as application/json
        if request.META['CONTENT_TYPE'] == 'application/json':
            data = json.loads(request.body)
        # Bitbucket and GitHub sends json as x-www-form-data
        else:
            data = json.loads(request.POST['payload'])
    except (ValueError, KeyError):
        return HttpResponseBadRequest('Could not parse JSON payload!')

    # Get service helper
    if service not in HOOK_HANDLERS:
        LOGGER.error('service %s is not supported', service)
        return HttpResponseBadRequest('invalid service')
    hook_helper = HOOK_HANDLERS[service]

    # Send the request data to the service handler.
    try:
        service_data = hook_helper(data)
    except KeyError:
        LOGGER.error('failed to parse service %s data', service)
        return HttpResponseBadRequest('Invalid data in json payload!')

    # Log data
    service_long_name = service_data['service_long_name']
    repos = service_data['repos']
    repo_url = service_data['repo_url']
    branch = service_data['branch']

    LOGGER.info('received %s notification on repository %s, branch %s',
                service_long_name, repo_url, branch)

    subprojects = SubProject.objects.filter(repo__in=repos)

    if branch is not None:
        subprojects = subprojects.filter(branch=branch)

    # Trigger updates
    for obj in subprojects:
        if not obj.project.enable_hooks:
            continue
        LOGGER.info('%s notification will update %s', service_long_name, obj)
        perform_update(obj)

    return hook_response()
Exemplo n.º 14
0
 def log_info(self, msg, *args):
     return LOGGER.info(
         self.log_prefix + msg, *args
     )
Exemplo n.º 15
0
 def log(self, *args):
     if self.component:
         self.component.log_info(*args)
     else:
         LOGGER.info(*args)
Exemplo n.º 16
0
def vcs_service_hook(request, service):
    """Shared code between VCS service hooks.

    Currently used for bitbucket_hook, github_hook and gitlab_hook, but should be usable
    for other VCS services (Google Code, custom coded sites, etc.) too.
    """
    # We support only post methods
    if not settings.ENABLE_HOOKS:
        return HttpResponseNotAllowed(())

    # Check if we got payload
    try:
        data = parse_hook_payload(request)
    except (ValueError, KeyError):
        return HttpResponseBadRequest("Could not parse JSON payload!")

    if not data:
        return HttpResponseBadRequest("Invalid data in json payload!")

    # Get service helper
    hook_helper = HOOK_HANDLERS[service]

    # Send the request data to the service handler.
    try:
        service_data = hook_helper(data, request)
    except Exception:
        LOGGER.error("failed to parse service %s data", service)
        report_error()
        return HttpResponseBadRequest("Invalid data in json payload!")

    # This happens on ping request upon installation
    if service_data is None:
        return hook_response("Hook working", status=201)

    # Log data
    service_long_name = service_data["service_long_name"]
    repos = service_data["repos"]
    repo_url = service_data["repo_url"]
    branch = service_data["branch"]
    full_name = service_data["full_name"]

    # Generate filter
    spfilter = Q(repo__in=repos) | Q(repo__iendswith=full_name)

    # We need to match also URLs which include username and password
    for repo in repos:
        if repo.startswith("http://"):
            spfilter = spfilter | (Q(repo__startswith="http://")
                                   & Q(repo__endswith="@{0}".format(repo[7:])))
        elif repo.startswith("https://"):
            spfilter = spfilter | (Q(repo__startswith="https://")
                                   & Q(repo__endswith="@{0}".format(repo[8:])))

    all_components = Component.objects.filter(spfilter)

    if branch is not None:
        all_components = all_components.filter(branch=branch)

    components = all_components.filter(project__enable_hooks=True)

    LOGGER.info(
        "received %s notification on repository %s, branch %s, "
        "%d matching components, %d to process, %d linked",
        service_long_name,
        repo_url,
        branch,
        all_components.count(),
        components.count(),
        Component.objects.filter(linked_component__in=components).count(),
    )

    # Trigger updates
    updates = 0
    for obj in components:
        updates += 1
        LOGGER.info("%s notification will update %s", service_long_name, obj)
        Change.objects.create(component=obj,
                              action=Change.ACTION_HOOK,
                              details=service_data)
        perform_update.delay("Component", obj.pk)

    if updates == 0:
        return hook_response("No matching repositories found!",
                             "failure",
                             status=202)

    return hook_response("Update triggered: {}".format(", ".join(
        obj.full_slug for obj in components)))
Exemplo n.º 17
0
 def log_info(self, msg, *args):
     self.log_hook('INFO', msg, *args)
     return LOGGER.info(': '.join((self.full_slug, msg)), *args)
Exemplo n.º 18
0
 def log_info(self, msg, *args):
     return LOGGER.info(self.log_prefix + msg, *args)
Exemplo n.º 19
0
def vcs_service_hook(request, service):
    """Shared code between VCS service hooks.

    Currently used for bitbucket_hook, github_hook and gitlab_hook, but should
    be usable for other VCS services (Google Code, custom coded sites, etc.)
    too.
    """
    # We support only post methods
    if not settings.ENABLE_HOOKS:
        return HttpResponseNotAllowed(())

    # Check if we got payload
    try:
        data = parse_hook_payload(request)
    except (ValueError, KeyError, UnicodeError):
        return HttpResponseBadRequest('Could not parse JSON payload!')

    if not data:
        return HttpResponseBadRequest('Invalid data in json payload!')

    # Get service helper
    hook_helper = HOOK_HANDLERS[service]

    # Send the request data to the service handler.
    try:
        service_data = hook_helper(data)
    except Exception as error:
        LOGGER.error('failed to parse service %s data', service)
        report_error(error, request)
        return HttpResponseBadRequest('Invalid data in json payload!')

    # This happens on ping request upon installation
    if service_data is None:
        return hook_response('Hook working')

    # Log data
    service_long_name = service_data['service_long_name']
    repos = service_data['repos']
    repo_url = service_data['repo_url']
    branch = service_data['branch']
    full_name = service_data['full_name']

    # Generate filter
    spfilter = Q(repo__in=repos) | Q(repo__iendswith=full_name)

    # We need to match also URLs which include username and password
    for repo in repos:
        if not repo.startswith('https://'):
            continue
        spfilter = spfilter | (Q(repo__startswith='https://')
                               & Q(repo__endswith='@{0}'.format(repo[8:])))

    all_components = Component.objects.filter(spfilter)

    if branch is not None:
        all_components = all_components.filter(branch=branch)

    components = all_components.filter(project__enable_hooks=True)

    LOGGER.info(
        'received %s notification on repository %s, branch %s, '
        '%d matching components, %d to process',
        service_long_name,
        repo_url,
        branch,
        all_components.count(),
        components.count(),
    )

    # Trigger updates
    updates = 0
    for obj in components:
        updates += 1
        LOGGER.info('%s notification will update %s', service_long_name, obj)
        perform_update.delay('Component', obj.pk)

    if updates == 0:
        return hook_response('No matching repositories found!', 'failure')

    return hook_response('Update triggered: {}'.format(', '.join(
        [obj.full_slug for obj in components])))
Exemplo n.º 20
0
 def log_info(self, msg, *args):
     self.log_hook('INFO', msg, *args)
     return LOGGER.info(
         ': '.join((self.full_slug, msg)), *args
     )
Exemplo n.º 21
0
 def log(self, *args):
     if self.component:
         self.component.log_info(*args)
     else:
         LOGGER.info(*args)
Exemplo n.º 22
0
def get_notification_email(language,
                           email,
                           notification,
                           translation_obj=None,
                           context=None,
                           headers=None,
                           user=None,
                           info=None):
    """Render notification email."""
    cur_language = django_translation.get_language()
    context = context or {}
    headers = headers or {}
    references = None
    if 'unit' in context:
        unit = context['unit']
        references = '{0}/{1}/{2}/{3}'.format(
            unit.translation.subproject.project.slug,
            unit.translation.subproject.slug, unit.translation.language.code,
            unit.id)
    if references is not None:
        references = '<{0}@{1}>'.format(references, get_site_domain())
        headers['In-Reply-To'] = references
        headers['References'] = references
    try:
        if info is None:
            info = force_text(translation_obj)
        LOGGER.info('sending notification %s on %s to %s', notification, info,
                    email)

        # Load user language
        if language is not None:
            django_translation.activate(language)

        # Template name
        context['subject_template'] = 'mail/{0}_subject.txt'.format(
            notification)

        # Adjust context
        context['current_site_url'] = get_site_url()
        if translation_obj is not None:
            context['translation'] = translation_obj
            context['translation_url'] = get_site_url(
                translation_obj.get_absolute_url())
        context['site_title'] = settings.SITE_TITLE

        # Render subject
        subject = render_to_string(context['subject_template'],
                                   context).strip()

        # Render body
        body = render_to_string('mail/{0}.txt'.format(notification), context)
        html_body = render_to_string('mail/{0}.html'.format(notification),
                                     context)

        # Define headers
        headers['Auto-Submitted'] = 'auto-generated'
        headers['X-AutoGenerated'] = 'yes'
        headers['Precedence'] = 'bulk'
        headers['X-Mailer'] = 'Weblate {0}'.format(VERSION)

        # Reply to header
        if user is not None:
            headers['Reply-To'] = user.email

        # List of recipients
        if email == 'ADMINS':
            emails = [a[1] for a in settings.ADMINS]
        else:
            emails = [email]

        # Create message
        email = EmailMultiAlternatives(
            settings.EMAIL_SUBJECT_PREFIX + subject,
            body,
            to=emails,
            headers=headers,
        )
        email.attach_alternative(html_body, 'text/html')

        # Return the mail
        return email
    finally:
        django_translation.activate(cur_language)
Exemplo n.º 23
0
 def log_info(self, msg, *args):
     return LOGGER.info(": ".join((self.log_prefix, msg)), *args)
Exemplo n.º 24
0
 def log_info(self, msg, *args):
     self.log_hook("INFO", msg, *args)
     return LOGGER.info(": ".join((self.full_slug, msg)), *args)
Exemplo n.º 25
0
 def log_info(self, msg, *args):
     return LOGGER.info(
         ': '.join((self.full_slug, msg)), *args
     )
Exemplo n.º 26
0
 def report_error(self, exc, message):
     """Wrapper for handling error situations"""
     report_error(exc, prefix='Machinery error')
     LOGGER.error(message, self.name)
     LOGGER.info('Last URL: %s, params: %s', self.request_url,
                 self.request_params)
Exemplo n.º 27
0
def vcs_service_hook(request, service):
    '''
    Shared code between VCS service hooks.

    Currently used for bitbucket_hook, github_hook and gitlab_hook, but should
    be usable for other VCS services (Google Code, custom coded sites, etc.)
    too.
    '''
    # Check for enabled hooks
    if appsettings.ENABLE_HOOKS:
        allowed_methods = ('POST',)
    else:
        allowed_methods = ()

    # We support only post methods
    if not appsettings.ENABLE_HOOKS or request.method not in allowed_methods:
        return HttpResponseNotAllowed(allowed_methods)

    # Check if we got payload
    try:
        # GitLab sends json as application/json
        if request.META['CONTENT_TYPE'] == 'application/json':
            data = json.loads(request.body)
        # Bitbucket and GitHub sends json as x-www-form-data
        else:
            data = json.loads(request.POST['payload'])
    except (ValueError, KeyError):
        return HttpResponseBadRequest('Could not parse JSON payload!')

    # Get service helper
    if service not in HOOK_HANDLERS:
        LOGGER.error('service %s is not supported', service)
        return HttpResponseBadRequest('invalid service')
    hook_helper = HOOK_HANDLERS[service]

    # Send the request data to the service handler.
    try:
        service_data = hook_helper(data)
    except KeyError:
        LOGGER.error('failed to parse service %s data', service)
        return HttpResponseBadRequest('Invalid data in json payload!')

    # Log data
    service_long_name = service_data['service_long_name']
    repos = service_data['repos']
    repo_url = service_data['repo_url']
    branch = service_data['branch']

    LOGGER.info(
        'received %s notification on repository %s, branch %s',
        service_long_name, repo_url, branch
    )

    subprojects = SubProject.objects.filter(repo__in=repos)

    if branch is not None:
        subprojects = subprojects.filter(branch=branch)

    # Trigger updates
    for obj in subprojects:
        if not obj.project.enable_hooks:
            continue
        LOGGER.info(
            '%s notification will update %s',
            service_long_name,
            obj
        )
        perform_update(obj)

    return hook_response()
Exemplo n.º 28
0
 def log_info(self, msg, *args):
     return LOGGER.info(
         ': '.join((self.log_prefix, msg)), *args
     )
Exemplo n.º 29
0
def get_notification_email(language, email, notification,
                           translation_obj=None, context=None, headers=None,
                           user=None, info=None):
    '''
    Renders notification email.
    '''
    cur_language = django_translation.get_language()
    context = context or {}
    headers = headers or {}
    references = None
    if 'unit' in context:
        unit = context['unit']
        references = '{0}/{1}/{2}/{3}'.format(
            unit.translation.subproject.project.slug,
            unit.translation.subproject.slug,
            unit.translation.language.code,
            unit.id
        )
    if references is not None:
        references = '<{0}@{1}>'.format(references, get_site_domain())
        headers['In-Reply-To'] = references
        headers['References'] = references
    try:
        if info is None:
            info = translation_obj.__unicode__()
        LOGGER.info(
            'sending notification %s on %s to %s',
            notification,
            info,
            email
        )

        # Load user language
        if language is not None:
            django_translation.activate(language)

        # Template name
        context['subject_template'] = 'mail/{}_subject.txt'.format(
            notification
        )

        # Adjust context
        context['current_site_url'] = get_site_url()
        if translation_obj is not None:
            context['translation'] = translation_obj
            context['translation_url'] = get_site_url(
                translation_obj.get_absolute_url()
            )
        context['site_title'] = SITE_TITLE

        # Render subject
        subject = render_to_string(
            context['subject_template'],
            context
        ).strip()

        # Render body
        body = render_to_string(
            'mail/{}.txt'.format(notification),
            context
        )
        html_body = render_to_string(
            'mail/{}.html'.format(notification),
            context
        )

        # Define headers
        headers['Auto-Submitted'] = 'auto-generated'
        headers['X-AutoGenerated'] = 'yes'
        headers['Precedence'] = 'bulk'
        headers['X-Mailer'] = 'Weblate {}'.format(VERSION)

        # Reply to header
        if user is not None:
            headers['Reply-To'] = user.email

        # List of recipients
        if email == 'ADMINS':
            emails = [a[1] for a in settings.ADMINS]
        else:
            emails = [email]

        # Create message
        email = EmailMultiAlternatives(
            settings.EMAIL_SUBJECT_PREFIX + subject,
            body,
            to=emails,
            headers=headers,
        )
        email.attach_alternative(
            html_body,
            'text/html'
        )

        # Return the mail
        return email
    finally:
        django_translation.activate(cur_language)
Exemplo n.º 30
0
 def log_info(self, msg, *args):
     return LOGGER.info(': '.join((self.full_slug, msg)), *args)