Beispiel #1
0
def send_contact_email(contact_entry_id):
    contact_entry = models.ContactEntry.objects.filter(
        id=contact_entry_id).first()
    if contact_entry is None:
        return

    ctx = {
        "comment":
        contact_entry.comment,
        "full_name":
        contact_entry.user.get_full_name(),
        "project_name":
        contact_entry.project.name,
        "photo_url":
        get_user_photo_url(contact_entry.user),
        "user_profile_url":
        resolve_front_url("user", contact_entry.user.username),
        "project_settings_url":
        resolve_front_url("project-admin", contact_entry.project.slug),
    }
    users = contact_entry.project.get_users().exclude(id=contact_entry.user_id)
    addresses = ", ".join([u.email for u in users])
    email = mail_builder.contact_notification(addresses, ctx)
    email.extra_headers["Reply-To"] = ", ".join([contact_entry.user.email])
    email.send()
Beispiel #2
0
def send_contact_email(contact_entry_id):
    contact_entry = models.ContactEntry.objects.filter(
        id=contact_entry_id).first()
    if contact_entry is None:
        return

    ctx = {
        "comment":
        contact_entry.comment,
        "full_name":
        contact_entry.user.get_full_name(),
        "project_name":
        contact_entry.project.name,
        "photo_url":
        get_user_photo_url(contact_entry.user),
        "user_profile_url":
        resolve_front_url("user", contact_entry.user.username),
        "project_settings_url":
        resolve_front_url("project-admin", contact_entry.project.slug),
    }
    admins = contact_entry.project.get_users(
        with_admin_privileges=True).exclude(id=contact_entry.user_id)
    for admin in admins:
        email = mail_builder.contact_notification(admin.email, ctx)
        email.extra_headers["Reply-To"] = contact_entry.user.email
        email.send()
Beispiel #3
0
    def get_auth_url(cls, server, consumer_key, key_cert_data, verify=None):
        if verify is None:
            verify = server.startswith("https")

        callback_uri = resolve_front_url("project-import-jira",
                                         quote_plus(server))
        oauth = OAuth1(
            consumer_key,
            signature_method=SIGNATURE_RSA,
            rsa_key=key_cert_data,
            callback_uri=callback_uri,
        )

        r = requests.post(server + "/plugins/servlet/oauth/request-token",
                          verify=verify,
                          auth=oauth)
        if r.status_code != 200:
            raise exceptions.InvalidServiceConfiguration()
        request = dict(parse_qsl(r.text))
        request_token = request["oauth_token"]
        request_token_secret = request["oauth_token_secret"]

        return (
            request_token,
            request_token_secret,
            "{}/plugins/servlet/oauth/authorize?oauth_token={}".format(
                server, request_token),
        )
Beispiel #4
0
    def get_access_token(cls,
                         server,
                         consumer_key,
                         key_cert_data,
                         request_token,
                         request_token_secret,
                         request_verifier,
                         verify=False):
        callback_uri = resolve_front_url("project-import-jira",
                                         quote_plus(server))
        oauth = OAuth1(
            consumer_key,
            signature_method=SIGNATURE_RSA,
            callback_uri=callback_uri,
            rsa_key=key_cert_data,
            resource_owner_key=request_token,
            resource_owner_secret=request_token_secret,
            verifier=request_verifier,
        )
        r = requests.post(server + '/plugins/servlet/oauth/access-token',
                          verify=verify,
                          auth=oauth)
        access = dict(parse_qsl(r.text))

        return {
            'access_token': access['oauth_token'],
            'access_token_secret': access['oauth_token_secret'],
            'consumer_key': consumer_key,
            'key_cert': key_cert_data
        }
Beispiel #5
0
    def get_auth_url(cls):
        request_token_url = 'https://trello.com/1/OAuthGetRequestToken'
        authorize_url = 'https://trello.com/1/OAuthAuthorizeToken'
        return_url = resolve_front_url("new-project-import", "trello")
        expiration = "1day"
        scope = "read,write,account"
        trello_key = settings.IMPORTERS.get('trello', {}).get('api_key', None)
        trello_secret = settings.IMPORTERS.get('trello',
                                               {}).get('secret_key', None)
        name = "Taiga"

        session = OAuth1Session(client_key=trello_key,
                                client_secret=trello_secret)
        response = session.fetch_request_token(request_token_url)
        oauth_token, oauth_token_secret = response.get(
            'oauth_token'), response.get('oauth_token_secret')

        return (
            oauth_token, oauth_token_secret,
            "{authorize_url}?oauth_token={oauth_token}&scope={scope}&expiration={expiration}&name={name}&return_url={return_url}"
            .format(
                authorize_url=authorize_url,
                oauth_token=oauth_token,
                expiration=expiration,
                scope=scope,
                name=name,
                return_url=return_url,
            ))
Beispiel #6
0
    def get_auth_url(cls):
        request_token_url = 'https://trello.com/1/OAuthGetRequestToken'
        authorize_url = 'https://trello.com/1/OAuthAuthorizeToken'
        return_url = resolve_front_url("new-project-import", "trello")
        expiration = "1day"
        scope = "read,write,account"
        trello_key = settings.IMPORTERS.get('trello', {}).get('api_key', None)
        trello_secret = settings.IMPORTERS.get('trello', {}).get('secret_key', None)
        name = "Taiga"

        session = OAuth1Session(client_key=trello_key, client_secret=trello_secret)
        response = session.fetch_request_token(request_token_url)
        oauth_token, oauth_token_secret = response.get('oauth_token'), response.get('oauth_token_secret')

        return (
            oauth_token,
            oauth_token_secret,
            "{authorize_url}?oauth_token={oauth_token}&scope={scope}&expiration={expiration}&name={name}&return_url={return_url}".format(
                authorize_url=authorize_url,
                oauth_token=oauth_token,
                expiration=expiration,
                scope=scope,
                name=name,
                return_url=return_url,
            )
        )
Beispiel #7
0
def send_contact_email(contact_entry_id):
    contact_entry = models.ContactEntry.objects.filter(id=contact_entry_id).first()
    if contact_entry is None:
        return

    ctx = {
        "comment": contact_entry.comment,
        "full_name": contact_entry.user.get_full_name(),
        "project_name": contact_entry.project.name,
        "photo_url": get_user_photo_url(contact_entry.user),
        "user_profile_url": resolve_front_url("user", contact_entry.user.username),
        "project_settings_url": resolve_front_url("project-admin", contact_entry.project.slug),
    }
    users = contact_entry.project.get_users().exclude(id=contact_entry.user_id)
    addresses = ", ".join([u.email for u in users])
    email = mail_builder.contact_notification(addresses, ctx)
    email.extra_headers["Reply-To"] = ", ".join([contact_entry.user.email])
    email.send()
Beispiel #8
0
def send_sync_notifications(notification_id):
    """
    Given changed instance, calculate the history entry and
    a complete list for users to notify, send
    email to all users.
    """

    notification = HistoryChangeNotification.objects.select_for_update().get(pk=notification_id)
    # If the last modification is too recent we ignore it for the time being
    now = timezone.now()
    time_diff = now - notification.updated_datetime
    if time_diff.seconds < settings.CHANGE_NOTIFICATIONS_MIN_INTERVAL:
        return

    history_entries = tuple(notification.history_entries.all().order_by("created_at"))
    history_entries = list(squash_history_entries(history_entries))

    # If there are no effective modifications we can delete this notification
    # without further processing
    if notification.history_type == HistoryType.change and not history_entries:
        notification.delete()
        return

    obj, _ = get_last_snapshot_for_key(notification.key)
    obj_class = get_model_from_key(obj.key)

    context = {"obj_class": obj_class,
               "snapshot": obj.snapshot,
               "project": notification.project,
               "changer": notification.owner,
               "history_entries": history_entries}

    model = get_model_from_key(notification.key)
    template_name = _resolve_template_name(model, change_type=notification.history_type)
    email = _make_template_mail(template_name)
    domain = settings.SITES["api"]["domain"].split(":")[0] or settings.SITES["api"]["domain"]

    if "ref" in obj.snapshot:
        msg_id = obj.snapshot["ref"]
    elif "slug" in obj.snapshot:
        msg_id = obj.snapshot["slug"]
    else:
        msg_id = 'taiga-system'

    now = datetime.datetime.now()
    project_name = remove_lr_cr(notification.project.name)
    format_args = {
        "unsubscribe_url": resolve_front_url('settings-mail-notifications'),
        "project_slug": notification.project.slug,
        "project_name": project_name,
        "msg_id": msg_id,
        "time": int(now.timestamp()),
        "domain": domain
    }

    headers = {
        "Message-ID": "<{project_slug}/{msg_id}/{time}@{domain}>".format(**format_args),
        "In-Reply-To": "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
        "References": "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
        "List-ID": 'Taiga/{project_name} <taiga.{project_slug}@{domain}>'.format(**format_args),
        "Thread-Index": make_ms_thread_index("<{project_slug}/{msg_id}@{domain}>".format(**format_args), now),
        "List-Unsubscribe": "<{unsubscribe_url}>".format(**format_args),
    }

    for user in notification.notify_users.distinct():
        context["user"] = user
        context["lang"] = user.lang or settings.LANGUAGE_CODE
        email.send(user.email, context, headers=headers)


    notification.delete()
Beispiel #9
0
    def handle(self, *args, **options):
        locale = options.get('locale')
        email_address = options.get('email')

        # Register email
        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first(),
            "cancel_token": "cancel-token"
        }

        email = mail_builder.registered_user(email_address, context)
        email.send()

        # Membership invitation
        membership = Membership.objects.order_by("?").filter(
            user__isnull=True).first()
        membership.invited_by = get_user_model().objects.all().order_by(
            "?").first()
        membership.invitation_extra_text = "Text example, Text example,\nText example,\n\nText example"

        context = {"lang": locale, "membership": membership}
        email = mail_builder.membership_invitation(email_address, context)
        email.send()

        # Membership notification
        context = {
            "lang":
            locale,
            "membership":
            Membership.objects.order_by("?").filter(
                user__isnull=False).first()
        }
        email = mail_builder.membership_notification(email_address, context)
        email.send()

        # Feedback
        context = {
            "lang": locale,
            "feedback_entry": {
                "full_name": "Test full name",
                "email": "*****@*****.**",
                "comment": "Test comment",
            },
            "extra": {
                "key1": "value1",
                "key2": "value2",
            },
        }
        email = mail_builder.feedback_notification(email_address, context)
        email.send()

        # Password recovery
        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.password_recovery(email_address, context)
        email.send()

        # Change email
        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.change_email(email_address, context)
        email.send()

        # Export/Import emails
        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first(),
            "project": Project.objects.all().order_by("?").first(),
            "error_subject": "Error generating project dump",
            "error_message": "Error generating project dump",
        }
        email = mail_builder.export_error(email_address, context)
        email.send()
        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first(),
            "error_subject": "Error importing project dump",
            "error_message": "Error importing project dump",
        }
        email = mail_builder.import_error(email_address, context)
        email.send()

        deletion_date = timezone.now() + datetime.timedelta(seconds=60 * 60 *
                                                            24)
        context = {
            "lang": locale,
            "url": "http://dummyurl.com",
            "user": get_user_model().objects.all().order_by("?").first(),
            "project": Project.objects.all().order_by("?").first(),
            "deletion_date": deletion_date,
        }
        email = mail_builder.dump_project(email_address, context)
        email.send()

        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first(),
            "project": Project.objects.all().order_by("?").first(),
        }
        email = mail_builder.load_dump(email_address, context)
        email.send()

        # Notification emails
        notification_emails = [
            ("issues.Issue", "issues/issue-change"),
            ("issues.Issue", "issues/issue-create"),
            ("issues.Issue", "issues/issue-delete"),
            ("tasks.Task", "tasks/task-change"),
            ("tasks.Task", "tasks/task-create"),
            ("tasks.Task", "tasks/task-delete"),
            ("userstories.UserStory", "userstories/userstory-change"),
            ("userstories.UserStory", "userstories/userstory-create"),
            ("userstories.UserStory", "userstories/userstory-delete"),
            ("milestones.Milestone", "milestones/milestone-change"),
            ("milestones.Milestone", "milestones/milestone-create"),
            ("milestones.Milestone", "milestones/milestone-delete"),
            ("wiki.WikiPage", "wiki/wikipage-change"),
            ("wiki.WikiPage", "wiki/wikipage-create"),
            ("wiki.WikiPage", "wiki/wikipage-delete"),
        ]

        context = {
            "lang": locale,
            "project": Project.objects.all().order_by("?").first(),
            "changer": get_user_model().objects.all().order_by("?").first(),
            "history_entries": HistoryEntry.objects.all().order_by("?")[0:5],
            "user": get_user_model().objects.all().order_by("?").first(),
        }

        for notification_email in notification_emails:
            model = apps.get_model(*notification_email[0].split("."))
            snapshot = {
                "subject": "Tests subject",
                "ref": 123123,
                "name": "Tests name",
                "slug": "test-slug"
            }
            queryset = model.objects.all().order_by("?")
            for obj in queryset:
                end = False
                entries = get_history_queryset_by_model_instance(obj).filter(
                    is_snapshot=True).order_by("?")

                for entry in entries:
                    if entry.snapshot:
                        snapshot = entry.snapshot
                        end = True
                        break
                if end:
                    break
            context["snapshot"] = snapshot

            cls = type("InlineCSSTemplateMail", (InlineCSSTemplateMail, ),
                       {"name": notification_email[1]})
            email = cls()
            email.send(email_address, context)

        # Transfer Emails
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "requester": get_user_model().objects.all().order_by("?").first(),
        }
        email = mail_builder.transfer_request(email_address, context)
        email.send()

        context = {
            "project": Project.objects.all().order_by("?").first(),
            "receiver": get_user_model().objects.all().order_by("?").first(),
            "token": "test-token",
            "reason": "Test reason"
        }
        email = mail_builder.transfer_start(email_address, context)
        email.send()

        context = {
            "project": Project.objects.all().order_by("?").first(),
            "old_owner": get_user_model().objects.all().order_by("?").first(),
            "new_owner": get_user_model().objects.all().order_by("?").first(),
            "reason": "Test reason"
        }
        email = mail_builder.transfer_accept(email_address, context)
        email.send()

        context = {
            "project": Project.objects.all().order_by("?").first(),
            "rejecter": get_user_model().objects.all().order_by("?").first(),
            "reason": "Test reason"
        }
        email = mail_builder.transfer_reject(email_address, context)
        email.send()

        # Contact with project admins email
        project = Project.objects.all().order_by("?").first()
        user = get_user_model().objects.all().order_by("?").first()
        context = {
            "full_name":
            user.get_full_name(),
            "project_name":
            project.name,
            "photo_url":
            get_user_photo_url(user),
            "user_profile_url":
            resolve_front_url("user", user.username),
            "project_settings_url":
            resolve_front_url("project-admin", project.slug),
            "comment":
            "Test comment notification."
        }
        email = mail_builder.contact_notification(email_address, context)
        email.send()

        # GitHub importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.github_import_success(email_address, context)
        email.send()

        # Jira importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.jira_import_success(email_address, context)
        email.send()

        # Trello importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.trello_import_success(email_address, context)
        email.send()

        # Asana importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.asana_import_success(email_address, context)
        email.send()

        # Error importer email
        context = {
            "user": get_user_model().objects.all().order_by("?").first(),
            "error_subject": "Error importing GitHub project",
            "error_message": "Error importing GitHub project",
            "project": 1234,
            "exception": "Exception message"
        }
        email = mail_builder.importer_import_error(email_address, context)
        email.send()
Beispiel #10
0
 def get_permalink(self, obj):
     return resolve_front_url("epic", obj.project.slug, obj.ref)
Beispiel #11
0
 def get_permalink(self, obj):
     return resolve_front_url("user", obj.username)
Beispiel #12
0
 def get_permalink(self, obj):
     return resolve_front_url("project", obj.slug)
Beispiel #13
0
 def get_permalink(self, obj):
     return resolve_front_url("wiki", obj.project.slug, obj.slug)
Beispiel #14
0
def send_sync_notifications(notification_id):
    """
    Given changed instance, calculate the history entry and
    a complete list for users to notify, send
    email to all users.
    """

    notification = HistoryChangeNotification.objects.select_for_update().get(
        pk=notification_id)
    # If the last modification is too recent we ignore it for the time being
    now = timezone.now()
    time_diff = now - notification.updated_datetime
    if time_diff.seconds < settings.CHANGE_NOTIFICATIONS_MIN_INTERVAL:
        return

    history_entries = tuple(
        notification.history_entries.all().order_by("created_at"))
    history_entries = list(squash_history_entries(history_entries))

    # If there are no effective modifications we can delete this notification
    # without further processing
    if notification.history_type == HistoryType.change and not history_entries:
        notification.delete()
        return

    obj, _ = get_last_snapshot_for_key(notification.key)
    obj_class = get_model_from_key(obj.key)

    context = {
        "obj_class": obj_class,
        "snapshot": obj.snapshot,
        "project": notification.project,
        "changer": notification.owner,
        "history_entries": history_entries
    }

    model = get_model_from_key(notification.key)
    template_name = _resolve_template_name(
        model, change_type=notification.history_type)
    email = _make_template_mail(template_name)
    domain = settings.SITES["api"]["domain"].split(
        ":")[0] or settings.SITES["api"]["domain"]

    if "ref" in obj.snapshot:
        msg_id = obj.snapshot["ref"]
    elif "slug" in obj.snapshot:
        msg_id = obj.snapshot["slug"]
    else:
        msg_id = 'taiga-system'

    now = datetime.datetime.now()
    format_args = {
        "unsubscribe_url": resolve_front_url('settings-mail-notifications'),
        "project_slug": notification.project.slug,
        "project_name": notification.project.name,
        "msg_id": msg_id,
        "time": int(now.timestamp()),
        "domain": domain
    }

    headers = {
        "Message-ID":
        "<{project_slug}/{msg_id}/{time}@{domain}>".format(**format_args),
        "In-Reply-To":
        "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
        "References":
        "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
        "List-ID":
        'Taiga/{project_name} <taiga.{project_slug}@{domain}>'.format(
            **format_args),
        "Thread-Index":
        make_ms_thread_index(
            "<{project_slug}/{msg_id}@{domain}>".format(**format_args), now),
        "List-Unsubscribe":
        "<{unsubscribe_url}>".format(**format_args),
    }

    for user in notification.notify_users.distinct():
        context["user"] = user
        context["lang"] = user.lang or settings.LANGUAGE_CODE
        email.send(user.email, context, headers=headers)

    notification.delete()
Beispiel #15
0
 def get_permalink(self, obj):
     return resolve_front_url("project", obj.slug)
Beispiel #16
0
 def get_permalink(self, obj):
     return resolve_front_url("wiki", obj.project.slug, obj.slug)
Beispiel #17
0
 def get_permalink(self, obj):
     return resolve_front_url("user", obj.username)
Beispiel #18
0
 def get_permalink(self, obj):
     return resolve_front_url("epic", obj.project.slug, obj.ref)
Beispiel #19
0
def send_sync_notifications(notification_id):
    """
    Given changed instance, calculate the history entry and
    a complete list for users to notify, send
    email to all users.
    """

    notification = HistoryChangeNotification.objects.select_for_update().get(pk=notification_id)

    # Custom Hardcode Filter
    if settings.NOTIFICATIONS_CUSTOM_FILTER:
        allowed_keys = [
            "userstories.userstory",
            "epics.epic",
            "issues.issue",
        ]

        if not any([(notification.key.find(key) >= 0) for key in allowed_keys]):
            notification.delete()
            return False, []

    # If the last modification is too recent we ignore it for the time being
    now = timezone.now()
    time_diff = now - notification.updated_datetime
    if time_diff.seconds < settings.CHANGE_NOTIFICATIONS_MIN_INTERVAL:
        return False, []

    # Custom Hardcode Filter
    qs = notification.history_entries
    if settings.NOTIFICATIONS_CUSTOM_FILTER:
        queries = [
            ~Q(comment=""),
            Q(key__startswith="epics.epic", type=HistoryType.create),
            Q(Q(key__startswith="userstories.userstory"), ~Q(values__users={}), ~Q(values__users=[])),
            Q(Q(key__startswith="issues.issue"), ~Q(values__users={}), ~Q(values__users=[])),
        ]
        query = queries.pop()
        for item in queries:
            query |= item

        qs = qs.filter(query).order_by("created_at")

    else:
        qs = qs.all()

    history_entries = tuple(qs)
    history_entries = list(squash_history_entries(history_entries))

    # If there are no effective modifications we can delete this notification
    # without further processing
    if notification.history_type == HistoryType.change and not history_entries:
        notification.delete()
        return False, []

    obj, _ = get_last_snapshot_for_key(notification.key)
    obj_class = get_model_from_key(obj.key)

    context = {"obj_class": obj_class,
               "snapshot": obj.snapshot,
               "project": notification.project,
               "changer": notification.owner,
               "history_entries": history_entries}

    model = get_model_from_key(notification.key)
    template_name = _resolve_template_name(model, change_type=notification.history_type)
    email = _make_template_mail(template_name)
    domain = settings.SITES["api"]["domain"].split(":")[0] or settings.SITES["api"]["domain"]

    if "ref" in obj.snapshot:
        msg_id = obj.snapshot["ref"]
    elif "slug" in obj.snapshot:
        msg_id = obj.snapshot["slug"]
    else:
        msg_id = 'taiga-system'

    now = datetime.datetime.now()
    project_name = remove_lr_cr(notification.project.name)
    format_args = {
        "unsubscribe_url": resolve_front_url('settings-mail-notifications'),
        "project_slug": notification.project.slug,
        "project_name": project_name,
        "msg_id": msg_id,
        "time": int(now.timestamp()),
        "domain": domain
    }

    headers = {
        "Message-ID": "<{project_slug}/{msg_id}/{time}@{domain}>".format(**format_args),
        "In-Reply-To": "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
        "References": "<{project_slug}/{msg_id}@{domain}>".format(**format_args),
        "List-ID": 'Taiga/{project_name} <taiga.{project_slug}@{domain}>'.format(**format_args),
        "Thread-Index": make_ms_thread_index("<{project_slug}/{msg_id}@{domain}>".format(**format_args), now),
        "List-Unsubscribe": "<{unsubscribe_url}>".format(**format_args),
    }

    for user in notification.notify_users.distinct():
        context["user"] = user
        context["lang"] = user.lang or settings.LANGUAGE_CODE
        email.send(user.email, context, headers=headers)

    notification_id = notification.id
    notification.delete()
    return notification_id, history_entries
Beispiel #20
0
    def handle(self, *args, **options):
        locale = options.get('locale')
        email_address = options.get('email')

        # Register email
        context = {"lang": locale,
                    "user": get_user_model().objects.all().order_by("?").first(),
                    "cancel_token": "cancel-token"}

        email = mail_builder.registered_user(email_address, context)
        email.send()

        # Membership invitation
        membership = Membership.objects.order_by("?").filter(user__isnull=True).first()
        membership.invited_by = get_user_model().objects.all().order_by("?").first()
        membership.invitation_extra_text = "Text example, Text example,\nText example,\n\nText example"

        context = {"lang": locale, "membership": membership}
        email = mail_builder.membership_invitation(email_address, context)
        email.send()

        # Membership notification
        context = {"lang": locale,
                   "membership": Membership.objects.order_by("?").filter(user__isnull=False).first()}
        email = mail_builder.membership_notification(email_address, context)
        email.send()

        # Feedback
        context = {
            "lang": locale,
            "feedback_entry": {
                "full_name": "Test full name",
                "email": "*****@*****.**",
                "comment": "Test comment",
            },
            "extra": {
                "key1": "value1",
                "key2": "value2",
            },
        }
        email = mail_builder.feedback_notification(email_address, context)
        email.send()

        # Password recovery
        context = {"lang": locale, "user": get_user_model().objects.all().order_by("?").first()}
        email = mail_builder.password_recovery(email_address, context)
        email.send()

        # Change email
        context = {"lang": locale, "user": get_user_model().objects.all().order_by("?").first()}
        email = mail_builder.change_email(email_address, context)
        email.send()

        # Export/Import emails
        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first(),
            "project": Project.objects.all().order_by("?").first(),
            "error_subject": "Error generating project dump",
            "error_message": "Error generating project dump",
        }
        email = mail_builder.export_error(email_address, context)
        email.send()
        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first(),
            "error_subject": "Error importing project dump",
            "error_message": "Error importing project dump",
        }
        email = mail_builder.import_error(email_address, context)
        email.send()

        deletion_date = timezone.now() + datetime.timedelta(seconds=60*60*24)
        context = {
            "lang": locale,
            "url": "http://dummyurl.com",
            "user": get_user_model().objects.all().order_by("?").first(),
            "project": Project.objects.all().order_by("?").first(),
            "deletion_date": deletion_date,
        }
        email = mail_builder.dump_project(email_address, context)
        email.send()

        context = {
            "lang": locale,
            "user": get_user_model().objects.all().order_by("?").first(),
            "project": Project.objects.all().order_by("?").first(),
        }
        email = mail_builder.load_dump(email_address, context)
        email.send()

        # Notification emails
        notification_emails = [
            ("issues.Issue", "issues/issue-change"),
            ("issues.Issue", "issues/issue-create"),
            ("issues.Issue", "issues/issue-delete"),
            ("tasks.Task", "tasks/task-change"),
            ("tasks.Task", "tasks/task-create"),
            ("tasks.Task", "tasks/task-delete"),
            ("userstories.UserStory", "userstories/userstory-change"),
            ("userstories.UserStory", "userstories/userstory-create"),
            ("userstories.UserStory", "userstories/userstory-delete"),
            ("milestones.Milestone", "milestones/milestone-change"),
            ("milestones.Milestone", "milestones/milestone-create"),
            ("milestones.Milestone", "milestones/milestone-delete"),
            ("wiki.WikiPage", "wiki/wikipage-change"),
            ("wiki.WikiPage", "wiki/wikipage-create"),
            ("wiki.WikiPage", "wiki/wikipage-delete"),
        ]

        context = {
            "lang": locale,
            "project": Project.objects.all().order_by("?").first(),
            "changer": get_user_model().objects.all().order_by("?").first(),
            "history_entries": HistoryEntry.objects.all().order_by("?")[0:5],
            "user": get_user_model().objects.all().order_by("?").first(),
        }

        for notification_email in notification_emails:
            model = apps.get_model(*notification_email[0].split("."))
            snapshot = {
                "subject": "Tests subject",
                "ref": 123123,
                "name": "Tests name",
                "slug": "test-slug"
            }
            queryset = model.objects.all().order_by("?")
            for obj in queryset:
                end = False
                entries = get_history_queryset_by_model_instance(obj).filter(is_snapshot=True).order_by("?")

                for entry in entries:
                    if entry.snapshot:
                        snapshot = entry.snapshot
                        end = True
                        break
                if end:
                    break
            context["snapshot"] = snapshot

            cls = type("InlineCSSTemplateMail", (InlineCSSTemplateMail,), {"name": notification_email[1]})
            email = cls()
            email.send(email_address, context)

        # Transfer Emails
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "requester": get_user_model().objects.all().order_by("?").first(),
        }
        email = mail_builder.transfer_request(email_address, context)
        email.send()

        context = {
            "project": Project.objects.all().order_by("?").first(),
            "receiver": get_user_model().objects.all().order_by("?").first(),
            "token": "test-token",
            "reason": "Test reason"
        }
        email = mail_builder.transfer_start(email_address, context)
        email.send()

        context = {
            "project": Project.objects.all().order_by("?").first(),
            "old_owner": get_user_model().objects.all().order_by("?").first(),
            "new_owner": get_user_model().objects.all().order_by("?").first(),
            "reason": "Test reason"
        }
        email = mail_builder.transfer_accept(email_address, context)
        email.send()

        context = {
            "project": Project.objects.all().order_by("?").first(),
            "rejecter": get_user_model().objects.all().order_by("?").first(),
            "reason": "Test reason"
        }
        email = mail_builder.transfer_reject(email_address, context)
        email.send()


        # Contact with project admins email
        project = Project.objects.all().order_by("?").first()
        user = get_user_model().objects.all().order_by("?").first()
        context = {
            "full_name": user.get_full_name(),
            "project_name": project.name,
            "photo_url": get_user_photo_url(user),
            "user_profile_url": resolve_front_url("user", user.username),
            "project_settings_url": resolve_front_url("project-admin", project.slug),
            "comment": "Test comment notification."
        }
        email = mail_builder.contact_notification(email_address, context)
        email.send()

        # GitHub importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.github_import_success(email_address, context)
        email.send()

        # Jira importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.jira_import_success(email_address, context)
        email.send()

        # Trello importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.trello_import_success(email_address, context)
        email.send()

        # Asana importer email
        context = {
            "project": Project.objects.all().order_by("?").first(),
            "user": get_user_model().objects.all().order_by("?").first()
        }
        email = mail_builder.asana_import_success(email_address, context)
        email.send()

        # Error importer email
        context = {
            "user": get_user_model().objects.all().order_by("?").first(),
            "error_subject": "Error importing GitHub project",
            "error_message": "Error importing GitHub project",
            "project": 1234,
            "exception": "Exception message"
        }
        email = mail_builder.importer_import_error(email_address, context)
        email.send()