Skip to content

Commit

Permalink
add user settings link in emails (#1418)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Jun 4, 2024
1 parent 86c714f commit 377a6e1
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 251 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ Added
- ``checkusers`` management command (#1410)
- ``SODARPageNumberPagination`` pagination class (#1313)
- Optional pagination for REST API list views (#1313)
- Email notification opt-out settings (#1417)
- Email notification opt-out settings (#1417, #1418)
- CC and BCC field support in sending generic emails (#415)
- ``SODARUserAdditionalEmail`` model (#874)
- ``is_source_site()`` and ``is_target_site()`` rule predicates
- ``settings_link`` kwarg in ``send_generic_email()`` (#1418)
- **Timeline**
- ``sodar_uuid`` field in ``TimelineEventObjectRef`` model (#1415)
- REST API views (#1350)
Expand Down
77 changes: 47 additions & 30 deletions projectroles/email.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from projectroles.app_settings import AppSettingAPI
from projectroles.models import SODARUserAdditionalEmail
from projectroles.plugins import get_app_plugin
from projectroles.utils import build_invite_url, get_display_name


Expand Down Expand Up @@ -54,6 +55,11 @@
contact {admin_name} ({admin_email}).
'''

SETTINGS_LINK = r'''
You can manage receiving of automated emails in your user settings:
{url}
'''


# Role Change Template ---------------------------------------------------------

Expand Down Expand Up @@ -277,23 +283,33 @@ def get_email_header(header):
return getattr(settings, 'PROJECTROLES_EMAIL_HEADER', None) or header


def get_email_footer():
def get_email_footer(request, settings_link=True):
"""
Return the email footer.
:param request: HttpRequest object
:param settings_link: Include link to user settings if True (optional)
:return: string
"""
footer = ''
custom_footer = getattr(settings, 'PROJECTROLES_EMAIL_FOOTER', None)
if custom_footer:
return '\n' + custom_footer
admin_recipient = settings.ADMINS[0] if settings.ADMINS else None
if admin_recipient:
return MESSAGE_FOOTER.format(
if custom_footer:
footer += '\n' + custom_footer
elif admin_recipient:
footer += MESSAGE_FOOTER.format(
site_title=SITE_TITLE,
admin_name=admin_recipient[0],
admin_email=admin_recipient[1],
)
return ''
# Add user settings link if enabled and userprofile app is active
if request and settings_link and get_app_plugin('userprofile'):
footer += SETTINGS_LINK.format(
url=request.build_absolute_uri(
reverse('userprofile:settings_update')
)
)
return footer


def get_invite_subject(project):
Expand Down Expand Up @@ -331,7 +347,7 @@ def get_role_change_subject(change_type, project):


def get_role_change_body(
change_type, project, user_name, role_name, issuer, project_url
change_type, project, user_name, role_name, issuer, request
):
"""
Return role change email body.
Expand All @@ -341,9 +357,12 @@ def get_role_change_body(
:param user_name: Name of target user
:param role_name: Name of role as string
:param issuer: User object for issuing user
:param project_url: URL for the project
:param request: HttpRequest object
:return: String
"""
project_url = request.build_absolute_uri(
reverse('projectroles:detail', kwargs={'project': project.sodar_uuid})
)
body = get_email_header(
MESSAGE_HEADER.format(recipient=user_name, site_title=SITE_TITLE)
)
Expand Down Expand Up @@ -375,7 +394,7 @@ def get_role_change_body(
)
if not issuer.email and not settings.PROJECTROLES_EMAIL_SENDER_REPLY:
body += NO_REPLY_NOTE
body += get_email_footer()
body += get_email_footer(request)
return body


Expand Down Expand Up @@ -413,7 +432,7 @@ def send_mail(
:param subject: Message subject (string)
:param message: Message body (string)
:param recipient_list: Recipients of email (list)
:param request: Request object (optional)
:param request: HttpRequest object (optional)
:param reply_to: List of emails for the "reply-to" header (optional)
:param cc: List of emails for "cc" field (optional)
:param bcc: List of emails for "bcc" field (optional)
Expand All @@ -436,7 +455,6 @@ def send_mail(
)
)
return ret

except Exception as ex:
error_msg = 'Error sending email: {}'.format(str(ex))
logger.error(error_msg)
Expand All @@ -458,20 +476,17 @@ def send_role_change_mail(change_type, project, user, role, request):
:param project: Project object
:param user: User object
:param role: Role object (can be None for deletion)
:param request: HTTP request
:param request: HttpRequest object
:return: Amount of sent email (int)
"""
project_url = request.build_absolute_uri(
reverse('projectroles:detail', kwargs={'project': project.sodar_uuid})
)
subject = get_role_change_subject(change_type, project)
message = get_role_change_body(
change_type=change_type,
project=project,
user_name=user.get_full_name(),
role_name=role.name if role else '',
issuer=request.user,
project_url=project_url,
request=request,
)
issuer_emails = get_user_addr(request.user)
return send_mail(
Expand All @@ -484,7 +499,7 @@ def send_invite_mail(invite, request):
Send an email invitation to user not yet registered in the system.
:param invite: ProjectInvite object
:param request: HTTP request
:param request: HttpRequest object
:return: Amount of sent email (int)
"""
invite_url = build_invite_url(invite, request)
Expand All @@ -498,7 +513,7 @@ def send_invite_mail(invite, request):
),
)
message += get_invite_message(invite.message)
message += get_email_footer()
message += get_email_footer(request, settings_link=False)
subject = get_invite_subject(invite.project)
issuer_emails = get_user_addr(invite.issuer)
return send_mail(subject, message, [invite.email], request, issuer_emails)
Expand All @@ -510,7 +525,7 @@ def send_accept_note(invite, request, user):
accepts the invitation.
:param invite: ProjectInvite object
:param request: HTTP request
:param request: HttpRequest object
:param user: User invited
:return: Amount of sent email (int)
"""
Expand All @@ -534,7 +549,7 @@ def send_accept_note(invite, request, user):

if not settings.PROJECTROLES_EMAIL_SENDER_REPLY:
message += NO_REPLY_NOTE
message += get_email_footer()
message += get_email_footer(request)
return send_mail(subject, message, get_user_addr(invite.issuer), request)


Expand All @@ -544,7 +559,7 @@ def send_expiry_note(invite, request, user_name):
attempts to accept an expired invitation.
:param invite: ProjectInvite object
:param request: HTTP request
:param request: HttpRequest object
:param user_name: User name of invited user
:return: Amount of sent email (int)
"""
Expand All @@ -568,7 +583,7 @@ def send_expiry_note(invite, request, user_name):

if not settings.PROJECTROLES_EMAIL_SENDER_REPLY:
message += NO_REPLY_NOTE
message += get_email_footer()
message += get_email_footer(request)
return send_mail(subject, message, get_user_addr(invite.issuer), request)


Expand All @@ -578,7 +593,7 @@ def send_project_create_mail(project, request):
they are a different user than the project creator.
:param project: Project object for the newly created project
:param request: Request object
:param request: HttpRequest object
:return: Amount of sent email (int)
"""
parent = project.parent
Expand Down Expand Up @@ -609,7 +624,7 @@ def send_project_create_mail(project, request):
)
),
)
message += get_email_footer()
message += get_email_footer(request)
return send_mail(
subject,
message,
Expand All @@ -625,7 +640,7 @@ def send_project_move_mail(project, request):
they are a different user than the project creator.
:param project: Project object for the newly created project
:param request: Request object
:param request: HttpRequest object
:return: Amount of sent email (int)
"""
parent = project.parent
Expand Down Expand Up @@ -656,7 +671,7 @@ def send_project_move_mail(project, request):
)
),
)
message += get_email_footer()
message += get_email_footer(request)
return send_mail(
subject,
message,
Expand All @@ -672,7 +687,7 @@ def send_project_archive_mail(project, action, request):
:param project: Project object
:param action: String ("archive" or "unarchive")
:param request: HTTP request
:param request: HttpRequest object
:return: Amount of sent email (int)
"""
user = request.user
Expand Down Expand Up @@ -719,7 +734,7 @@ def send_project_archive_mail(project, action, request):
message += body_final
if not settings.PROJECTROLES_EMAIL_SENDER_REPLY:
message += NO_REPLY_NOTE
message += get_email_footer()
message += get_email_footer(request)
mail_count += send_mail(subject, message, get_user_addr(user), request)
return mail_count

Expand All @@ -732,6 +747,7 @@ def send_generic_mail(
reply_to=None,
cc=None,
bcc=None,
settings_link=True,
):
"""
Send a generic mail with standard header and footer and no-reply
Expand All @@ -740,10 +756,11 @@ def send_generic_mail(
:param subject_body: Subject body without prefix (string)
:param message_body: Message body before header or footer (string)
:param recipient_list: Recipients (list of User objects or email strings)
:param request: Request object (optional)
:param request: HttpRequest object (optional)
:param reply_to: List of emails for the "reply-to" header (optional)
:param cc: List of emails for "cc" field (optional)
:param bcc: List of emails for "bcc" field (optional)
:param settings_link: Include link to user settings if True (optional)
:return: Amount of mail sent (int)
"""
subject = SUBJECT_PREFIX + subject_body
Expand All @@ -761,7 +778,7 @@ def send_generic_mail(
message += message_body
if not reply_to and not settings.PROJECTROLES_EMAIL_SENDER_REPLY:
message += NO_REPLY_NOTE
message += get_email_footer()
message += get_email_footer(request, settings_link)
ret += send_mail(
subject, message, recp_addr, request, reply_to, cc, bcc
)
Expand Down
Loading

0 comments on commit 377a6e1

Please sign in to comment.