Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make email footer line configurable #8326

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/OrganizationController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class OrganizationController @Inject()(
mail = if (requestedPlan == PricingPlan.Team) {
defaultMails.upgradePricingPlanToTeamMail _
} else {
defaultMails.upgradePricingPlanToTeamMail _
defaultMails.upgradePricingPlanToPowerMail _
}
_ = Mailer ! Send(mail(request.identity, userEmail))
_ = Mailer ! Send(
Expand Down
70 changes: 44 additions & 26 deletions app/mail/DefaultMails.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class DefaultMails @Inject()(conf: WkConf) {
private val uri = conf.Http.uri
private val defaultSender = conf.Mail.defaultSender
private val newOrganizationMailingList = conf.WebKnossos.newOrganizationMailingList
private val additionalFooter = conf.Mail.additionalFooter
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Consider adding tests for the footer configuration

The codebase appears to lack dedicated tests for email templates. Since this change affects all email templates through configuration, adding tests would help ensure the footer functionality works correctly across the application.

Key areas to test:

  • Configuration loading and parsing
  • Footer inclusion in email templates
  • Proper HTML rendering with the footer
🔗 Analysis chain

Consider adding tests for the footer configuration.

Since this change affects all email templates, it would be valuable to add tests verifying that:

  1. The footer content is correctly read from the configuration
  2. The footer is properly included in the generated email HTML
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if there are any existing tests for email templates
rg -l "test.*Mail" "test/"

Length of output: 26


Script:

#!/bin/bash
# Search for test files in various common test directories with different patterns
fd -t f "test" -t f "spec"

# Search for email-related code to understand the implementation structure
rg -l "Mail" --type scala

Length of output: 957


Script:

#!/bin/bash
# Search for test files in the correct Play Framework test directory
fd . "test" -t d

# Search for any file containing both "test" and "mail" (case insensitive)
rg -i -l "test.*mail|mail.*test"

# Look for test configurations that might contain email settings
rg -l "mail" "conf/test" "conf/application.test" "conf/application.conf"

Length of output: 325


def registerAdminNotifierMail(name: String,
email: String,
Expand All @@ -24,51 +25,56 @@ class DefaultMails @Inject()(conf: WkConf) {
from = defaultSender,
subject =
s"WEBKNOSSOS | A new user ($name, $email) registered on $uri for ${organization.name} (${organization._id})",
bodyHtml = html.mail.notifyAdminNewUser(name, uri, autoActivate).body,
bodyHtml = html.mail.notifyAdminNewUser(name, uri, autoActivate, additionalFooter).body,
recipients = List(recipient)
)

def overLimitMail(user: User, projectName: String, taskId: String, annotationId: String, projectOwner: String): Mail =
Mail(
from = defaultSender,
subject = s"WEBKNOSSOS | Time limit reached. ${user.abbreviatedName} in $projectName",
bodyHtml = html.mail.notifyAdminTimeLimit(user.name, projectName, taskId, annotationId, uri).body,
bodyHtml =
html.mail.notifyAdminTimeLimit(user.name, projectName, taskId, annotationId, uri, additionalFooter).body,
recipients = List(projectOwner)
)

def newUserMail(name: String, recipient: String, enableAutoVerify: Boolean): Mail =
Mail(
from = defaultSender,
subject = "Welcome to WEBKNOSSOS",
bodyHtml = html.mail.newUser(name, enableAutoVerify).body,
bodyHtml = html.mail.newUser(name, enableAutoVerify, additionalFooter).body,
recipients = List(recipient)
)

def activatedMail(name: String, recipient: String): Mail =
Mail(from = defaultSender,
subject = "WEBKNOSSOS | Account activated",
bodyHtml = html.mail.validateUser(name, uri).body,
recipients = List(recipient))
Mail(
from = defaultSender,
subject = "WEBKNOSSOS | Account activated",
bodyHtml = html.mail.validateUser(name, uri, additionalFooter).body,
recipients = List(recipient)
)

def changePasswordMail(name: String, recipient: String): Mail =
Mail(from = defaultSender,
subject = "WEBKNOSSOS | Password changed",
bodyHtml = html.mail.passwordChanged(name, uri).body,
recipients = List(recipient))
Mail(
from = defaultSender,
subject = "WEBKNOSSOS | Password changed",
bodyHtml = html.mail.passwordChanged(name, uri, additionalFooter).body,
recipients = List(recipient)
)

def resetPasswordMail(name: String, recipient: String, token: String): Mail =
Mail(
from = defaultSender,
subject = "WEBKNOSSOS | Password Reset",
bodyHtml = html.mail.resetPassword(name, uri, token).body,
bodyHtml = html.mail.resetPassword(name, uri, token, additionalFooter).body,
recipients = List(recipient)
)

def newOrganizationMail(organizationName: String, creatorEmail: String, domain: String): Mail =
Mail(
from = defaultSender,
subject = s"WEBKNOSSOS | New Organization created on $domain",
bodyHtml = html.mail.notifyAdminNewOrganization(organizationName, creatorEmail, domain).body,
bodyHtml = html.mail.notifyAdminNewOrganization(organizationName, creatorEmail, domain, additionalFooter).body,
recipients = List(newOrganizationMailingList)
)

Expand All @@ -81,7 +87,8 @@ class DefaultMails @Inject()(conf: WkConf) {
Mail(
from = defaultSender,
subject = s"$senderName invited you to join their WEBKNOSSOS organization at $host",
bodyHtml = html.mail.invite(senderName, organizationName, inviteTokenValue, uri, autoVerify).body,
bodyHtml =
html.mail.invite(senderName, organizationName, inviteTokenValue, uri, autoVerify, additionalFooter).body,
recipients = List(recipient)
)
}
Expand All @@ -90,39 +97,47 @@ class DefaultMails @Inject()(conf: WkConf) {
Mail(
from = defaultSender,
subject = "Help requested // Feedback provided",
bodyHtml = html.mail.help(user.name, organizationName, message, currentUrl).body,
bodyHtml = html.mail.help(user.name, organizationName, message, currentUrl, additionalFooter).body,
recipients = List("hello@webknossos.org", userEmail)
)

def extendPricingPlanMail(user: User, userEmail: String): Mail =
Mail(
from = defaultSender,
subject = "WEBKNOSSOS Plan Extension Request",
bodyHtml = html.mail.extendPricingPlan(user.name).body,
bodyHtml = html.mail.extendPricingPlan(user.name, additionalFooter).body,
recipients = List(userEmail)
)

def upgradePricingPlanToTeamMail(user: User, userEmail: String): Mail =
Mail(
from = defaultSender,
subject = "WEBKNOSSOS Plan Upgrade Request",
bodyHtml = html.mail.upgradePricingPlanToTeam(user.name).body,
bodyHtml = html.mail.upgradePricingPlanToTeam(user.name, additionalFooter).body,
recipients = List(userEmail)
)

def upgradePricingPlanToPowerMail(user: User, userEmail: String): Mail =
Mail(
from = defaultSender,
subject = "WEBKNOSSOS Plan Upgrade Request",
bodyHtml = html.mail.upgradePricingPlanToPower(user.name, additionalFooter).body,
recipients = List(userEmail)
)

def upgradePricingPlanUsersMail(user: User, userEmail: String, requestedUsers: Int): Mail =
Mail(
from = defaultSender,
subject = "Request to upgrade WEBKNOSSOS users",
bodyHtml = html.mail.upgradePricingPlanUsers(user.name, requestedUsers).body,
bodyHtml = html.mail.upgradePricingPlanUsers(user.name, requestedUsers, additionalFooter).body,
recipients = List(userEmail)
)

def upgradePricingPlanStorageMail(user: User, userEmail: String, requestedStorage: Int): Mail =
Mail(
from = defaultSender,
subject = "Request to upgrade WEBKNOSSOS storage",
bodyHtml = html.mail.upgradePricingPlanStorage(user.name, requestedStorage).body,
bodyHtml = html.mail.upgradePricingPlanStorage(user.name, requestedStorage, additionalFooter).body,
recipients = List(userEmail)
)

Expand All @@ -133,7 +148,8 @@ class DefaultMails @Inject()(conf: WkConf) {
Mail(
from = defaultSender,
subject = "Request to upgrade WEBKNOSSOS plan",
bodyHtml = html.mail.upgradePricingPlanRequest(user.name, userEmail, organizationName, messageBody).body,
bodyHtml =
html.mail.upgradePricingPlanRequest(user.name, userEmail, organizationName, messageBody, additionalFooter).body,
recipients = List("hello@webknossos.org")
)

Expand All @@ -146,15 +162,17 @@ class DefaultMails @Inject()(conf: WkConf) {
Mail(
from = defaultSender,
subject = s"$jobTitle is ready",
bodyHtml = html.mail.jobSuccessfulGeneric(user.name, datasetName, jobLink, jobTitle, jobDescription).body,
bodyHtml = html.mail
.jobSuccessfulGeneric(user.name, datasetName, jobLink, jobTitle, jobDescription, additionalFooter)
.body,
recipients = List(userEmail)
)

def jobSuccessfulUploadConvertMail(user: User, userEmail: String, datasetName: String, jobLink: String): Mail =
Mail(
from = defaultSender,
subject = "Your dataset is ready",
bodyHtml = html.mail.jobSuccessfulUploadConvert(user.name, datasetName, jobLink).body,
bodyHtml = html.mail.jobSuccessfulUploadConvert(user.name, datasetName, jobLink, additionalFooter).body,
recipients = List(userEmail)
)

Expand All @@ -166,23 +184,23 @@ class DefaultMails @Inject()(conf: WkConf) {
Mail(
from = defaultSender,
subject = s"Your $jobTitle is ready",
bodyHtml = html.mail.jobSuccessfulSegmentation(user.name, datasetName, jobLink, jobTitle).body,
bodyHtml = html.mail.jobSuccessfulSegmentation(user.name, datasetName, jobLink, jobTitle, additionalFooter).body,
recipients = List(userEmail)
)

def jobFailedGenericMail(user: User, userEmail: String, datasetName: String, jobTitle: String): Mail =
Mail(
from = defaultSender,
subject = "Oops. Your WEBKNOSSOS job failed",
bodyHtml = html.mail.jobFailedGeneric(user.name, datasetName, jobTitle).body,
bodyHtml = html.mail.jobFailedGeneric(user.name, datasetName, jobTitle, additionalFooter).body,
recipients = List(userEmail)
)

def jobFailedUploadConvertMail(user: User, userEmail: String, datasetName: String): Mail =
Mail(
from = defaultSender,
subject = "Oops. Your dataset upload & conversion failed",
bodyHtml = html.mail.jobFailedUploadConvert(user.name, datasetName).body,
bodyHtml = html.mail.jobFailedUploadConvert(user.name, datasetName, additionalFooter).body,
recipients = List(userEmail)
)

Expand All @@ -193,7 +211,7 @@ class DefaultMails @Inject()(conf: WkConf) {
Mail(
from = defaultSender,
subject = "Verify Your Email at WEBKNOSSOS",
bodyHtml = html.mail.verifyEmail(user.name, key, linkExpiry).body,
bodyHtml = html.mail.verifyEmail(user.name, key, linkExpiry, additionalFooter).body,
recipients = List(userEmail)
)
}
Expand Down
1 change: 1 addition & 0 deletions app/utils/WkConf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ class WkConf @Inject()(configuration: Configuration) extends ConfigReader with L
}

val defaultSender: String = get[String]("mail.defaultSender")
def additionalFooter: String = get[String]("mail.additionalFooter")

object Mailchimp {
val host: String = get[String]("mail.mailchimp.host")
Expand Down
7 changes: 3 additions & 4 deletions app/views/mail/emailBaseTemplate.scala.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@()(content:Html)
@(additionalFooter: String)(content:Html)
<html>

<body>
Expand Down Expand Up @@ -46,11 +46,10 @@
cancel your account at any time.
</p>
<p style="color: #888; font-size: 0.6rem;">
<a href="https://webknossos.org" style="color: #888;">webknossos.org</a> is a service by
<a href="https://scalableminds.com">scalable minds</a> &bull; <a href="mailto:hello@@webknossos.org" style="color: #888;">hello@@webknossos.org</a>
@Html(additionalFooter)
fm3 marked this conversation as resolved.
Show resolved Hide resolved
</p>
<div style="height: 60px;">&nbsp;</div>
</div>
</body>

</html>
</html>
6 changes: 3 additions & 3 deletions app/views/mail/extendPricingPlan.scala.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
@( name: String)
@( name: String, additionalFooter: String )

@emailBaseTemplate() {
@emailBaseTemplate(additionalFooter) {
<p>Hi @{name}</p>
<p>Thank you for requesting to extend your current WEBKNOSSOS plan. Our sales team will be in contact with
you shortly with a formal offer.</p>

<p>With best regards,<br />the WEBKNOSSOS team</p>
}
}
4 changes: 2 additions & 2 deletions app/views/mail/help.scala.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@( name: String, organizationName: String, message: String, currentUrl: String)
@( name: String, organizationName: String, message: String, currentUrl: String, additionalFooter: String)

@emailBaseTemplate() {
@emailBaseTemplate(additionalFooter) {
<p>Hi WEBKNOSSOS team</p>
<p>I have a question or feedback for you:</p>
<p>
Expand Down
4 changes: 2 additions & 2 deletions app/views/mail/invite.scala.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@(senderName: String, organizationName: String, inviteTokenValue: String, uri: String, autoVerify: Boolean )
@(senderName: String, organizationName: String, inviteTokenValue: String, uri: String, autoVerify: Boolean, additionalFooter: String )

@emailBaseTemplate() {
@emailBaseTemplate(additionalFooter) {

<p>Hello,</p>

Expand Down
10 changes: 5 additions & 5 deletions app/views/mail/jobFailedGeneric.scala.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
@(name: String, datasetName: String, jobTitle: String)
@(name: String, datasetName: String, jobTitle: String, additionalFooter: String)

@emailBaseTemplate() {
@emailBaseTemplate(additionalFooter) {
<p>Hi @{name},</p>

<p>
oops, something unexpected went wrong when working on your WEBKNOSSOS @{jobTitle} job for the <i>@{datasetName}</i> dataset.
This should not have happened and we are sorry about the inconvenience. Our engineers will investigate and fix the problem as soon as possible.
This should not have happened and we are sorry about the inconvenience. Our engineers will investigate and fix the problem as soon as possible.
</p>
<p>
Feel free to contact us via email for assistance or please try again later.
Expand All @@ -16,8 +16,8 @@
<div style="text-align: center;">
<img src="https://static.webknossos.org/mails/email-drawing-failed-job.png"
srcset="https://static.webknossos.org/mails/email-drawing-failed-job.svg"
alt="A person dismayed about an unsuccessful WEBKNOSSOS job"
alt="A person dismayed about an unsuccessful WEBKNOSSOS job"
style="width: 460px; height: 258px; margin-top: 10px; margin-bottom: 20px" />
</div>

}
}
8 changes: 4 additions & 4 deletions app/views/mail/jobFailedUploadConvert.scala.html
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
@(name: String, datasetName: String)
@(name: String, datasetName: String, additionalFooter: String)

@emailBaseTemplate() {
@emailBaseTemplate(additionalFooter) {
<p>Hi @{name},</p>

<p>
oops, unfortunately WEBKNOSSOS could not upload and convert your dataset <i>@{datasetName}</i> automatically.
oops, unfortunately WEBKNOSSOS could not upload and convert your dataset <i>@{datasetName}</i> automatically.
This should not have happened and we are sorry about the inconvenience. Our engineers will investigate and fix the
problem as soon as possible.
</p>
Expand All @@ -30,4 +30,4 @@
alt="A person dismayed about an unsuccessful WEBKNOSSOS dataset upload job"
style="width: 460px; height: 258px; margin-top: 10px; margin-bottom: 20px" />
</div>
}
}
14 changes: 7 additions & 7 deletions app/views/mail/jobSuccessfulGeneric.scala.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
@(name: String, datasetName: String, jobLink: String, jobTitle: String, jobDescription: String)
@(name: String, datasetName: String, jobLink: String, jobTitle: String, jobDescription: String, additionalFooter: String)

@emailBaseTemplate() {
@emailBaseTemplate(additionalFooter) {
<p>Hi @{name},</p>

<p>We wanted to let you know that WEBKNOSSOS has finished your background job for the dataset <i>@{datasetName}</i>.
<p>We wanted to let you know that WEBKNOSSOS has finished your background job for the dataset <i>@{datasetName}</i>.
<p>@{jobDescription}</p>

<div style="text-align: center;">
Expand All @@ -28,9 +28,9 @@
<p>With best regards,<br />the WEBKNOSSOS team</p>

<div style="text-align: center;">
<img src="https://static.webknossos.org/mails/email-drawing-successful-job.png"
srcset="https://static.webknossos.org/mails/email-drawing-successful-job.svg"
alt="A person celebrating a successful WEBKNOSSOS job"
<img src="https://static.webknossos.org/mails/email-drawing-successful-job.png"
srcset="https://static.webknossos.org/mails/email-drawing-successful-job.svg"
alt="A person celebrating a successful WEBKNOSSOS job"
style="width: 460px; height: 307px; margin-top: 10px; margin-bottom: 20px;"/>
</div>
}
}
12 changes: 6 additions & 6 deletions app/views/mail/jobSuccessfulSegmentation.scala.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
@(name: String, datasetName: String, jobLink: String, jobTitle: String)
@(name: String, datasetName: String, jobLink: String, jobTitle: String, additionalFooter: String)
fm3 marked this conversation as resolved.
Show resolved Hide resolved

@emailBaseTemplate() {
@emailBaseTemplate(additionalFooter) {
<p>Hi @{name},</p>

<p>
Your @{jobTitle} is ready for exploration.
WEBKNOSSOS successfully applied our machine learning models on the specific subset of the <i>@{datasetName}</i> dataset.
Your @{jobTitle} is ready for exploration.
WEBKNOSSOS successfully applied our machine learning models on the specific subset of the <i>@{datasetName}</i> dataset.
Click the button below to open the dataset or find it amongst your other dataset in the WEBKNOSSOS dashboard.
</p>

Expand Down Expand Up @@ -41,10 +41,10 @@
Do you want to make corrections to the automated segmentation? Use the easy-to-use, built-in <a href="https://docs.webknossos.org/webknossos/proofreading/tools.html">proof-reading tools in WEBKNOSSOS</a> (requires Power plan).
</p>
<div style="text-align: center; margin-bottom: 20px;">
<img src="https://static.webknossos.org/mails/email-proofreading-preview.600.jpg"
<img src="https://static.webknossos.org/mails/email-proofreading-preview.600.jpg"
alt="A preview of the proofreading tools for a segmentation of a WEBKNOSSOS dataset"
style="width: 600px; height: 300px;" />
</div>

<p>With best regards,<br />the WEBKNOSSOS team</p>
}
}
Loading