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()
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()
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), )
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 }
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, ))
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, ) )
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()
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()
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()
def get_permalink(self, obj): return resolve_front_url("epic", obj.project.slug, obj.ref)
def get_permalink(self, obj): return resolve_front_url("user", obj.username)
def get_permalink(self, obj): return resolve_front_url("project", obj.slug)
def get_permalink(self, obj): return resolve_front_url("wiki", obj.project.slug, obj.slug)
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()
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
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()