framework support + content for OTP & add-member email

This commit is contained in:
hmacr
2025-07-22 16:43:17 +05:30
parent c35a7cc09b
commit bf3efea98d
7 changed files with 67 additions and 0 deletions
@@ -120,6 +120,11 @@
</head>
<body>
<div style="display: none; overflow: hidden; max-height: 0; max-width: 0; opacity: 0; line-height: 1px;">
{{preview}}
<div>{{previewWhitespace}}</div>
</div>
<div class="main">
<table>
<tr>
@@ -121,6 +121,11 @@
<body style="direction: {{direction}}">
<div style="display: none; overflow: hidden; max-height: 0; max-width: 0; opacity: 0; line-height: 1px;">
{{preview}}
<div>{{previewWhitespace}}</div>
</div>
<div style="max-width:650px; word-wrap: break-word; overflow-wrap: break-word;
word-break: normal; margin:0 auto;">
<table style="margin-top: 32px">
+2
View File
@@ -29,6 +29,7 @@
"emails.sessionAlert.thanks": "Thanks,",
"emails.sessionAlert.signature": "{{project}} team",
"emails.otpSession.subject": "OTP for {{project}} Login",
"emails.otpSession.preview": "Use OTP {{otp}} to sign in to {{project}}",
"emails.otpSession.hello": "Hello {{user}},",
"emails.otpSession.description": "Enter the following verification code when prompted to securely sign in to your {{b}}{{project}}{{/b}} account. This code will expire in 15 minutes.",
"emails.otpSession.clientInfo": "This sign in was requested using {{b}}{{agentClient}}{{/b}} on {{b}}{{agentDevice}}{{/b}} {{b}}{{agentOs}}{{/b}}. If you didn't request the sign in, you can safely ignore this email.",
@@ -49,6 +50,7 @@
"emails.recovery.buttonText": "Reset password",
"emails.recovery.signature": "{{project}} team",
"emails.invitation.subject": "Invitation to %s Team at %s",
"emails.invitation.preview": "{{owner}} invited you to join {{team}} at {{project}}",
"emails.invitation.hello": "Hello {{user}},",
"emails.invitation.body": "This mail was sent to you because {{b}}{{owner}}{{/b}} wanted to invite you to become a member of the {{b}}{{team}}{{/b}} team at {{b}}{{project}}{{/b}}.",
"emails.invitation.footer": "If you are not interested, you can ignore this message.",
+2
View File
@@ -2254,6 +2254,7 @@ App::post('/v1/account/tokens/email')
$dbForProject->purgeCachedDocument('users', $user->getId());
$subject = $locale->getText("emails.otpSession.subject");
$preview = $locale->getText("emails.otpSession.preview");
$customTemplate = $project->getAttribute('templates', [])['email.otpSession-' . $locale->default] ?? [];
$detector = new Detector($request->getUserAgent('UNKNOWN'));
@@ -2339,6 +2340,7 @@ App::post('/v1/account/tokens/email')
$queueForMails
->setSubject($subject)
->setPreview($preview)
->setBody($body)
->setVariables($emailVariables)
->setRecipient($email)
+2
View File
@@ -657,6 +657,7 @@ App::post('/v1/teams/:teamId/memberships')
$projectName = $project->isEmpty() ? 'Console' : $project->getAttribute('name', '[APP-NAME]');
$body = $locale->getText("emails.invitation.body");
$preview = $locale->getText("emails.invitation.preview");
$subject = \sprintf($locale->getText("emails.invitation.subject"), $team->getAttribute('name'), $projectName);
$customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? [];
@@ -729,6 +730,7 @@ App::post('/v1/teams/:teamId/memberships')
$queueForMails
->setSubject($subject)
->setBody($body)
->setPreview($preview)
->setRecipient($invitee->getAttribute('email'))
->setName($invitee->getAttribute('name', ''))
->setVariables($emailVariables)
+24
View File
@@ -10,6 +10,7 @@ class Mail extends Event
protected string $name = '';
protected string $subject = '';
protected string $body = '';
protected string $preview = '';
protected array $smtp = [];
protected array $variables = [];
protected string $bodyTemplate = '';
@@ -93,6 +94,28 @@ class Mail extends Event
return $this->body;
}
/**
* Sets preview for the mail event.
*
* @return string
*/
public function setPreview(string $preview): self
{
$this->preview = $preview;
return $this;
}
/**
* Returns preview for the mail event.
*
* @return string
*/
public function getPreview(string $preview): string
{
return $this->preview;
}
/**
* Sets name for the mail event.
*
@@ -409,6 +432,7 @@ class Mail extends Event
'subject' => $this->subject,
'bodyTemplate' => $this->bodyTemplate,
'body' => $this->body,
'preview' => $this->preview,
'smtp' => $this->smtp,
'variables' => $this->variables,
'attachment' => $this->attachment,
+27
View File
@@ -14,6 +14,11 @@ use Utopia\System\System;
class Mails extends Action
{
protected int $previewMaxLen = 150;
protected string $whitespaceCodes = '&#xa0;&#x200C;&#x200B;&#x200D;&#x200E;&#x200F;&#xFEFF;';
public static function getName(): string
{
return 'mails';
@@ -74,6 +79,7 @@ class Mails extends Action
$variables['host'] = $protocol . '://' . $hostname;
$name = $payload['name'];
$body = $payload['body'];
$preview = $payload['preview'] ?? '';
$variables['subject'] = $subject;
$variables['year'] = date("Y");
@@ -92,6 +98,27 @@ class Mails extends Action
foreach ($this->richTextParams as $key => $value) {
$bodyTemplate->setParam('{{' . $key . '}}', $value, escapeHtml: false);
}
$previewWhitespace = '';
if (!empty($preview)) {
$previewTemplate = Template::fromString($preview);
foreach ($variables as $key => $value) {
$previewTemplate->setParam('{{' . $key . '}}', $value);
}
// render() will return the subject in <p> tags, so use strip_tags() to remove them
$preview = \strip_tags($previewTemplate->render());
$previewLen = strlen($preview);
if ($previewLen < $this->previewMaxLen) {
$previewWhitespace = str_repeat($this->whitespaceCodes, $this->previewMaxLen - $previewLen);
}
}
$bodyTemplate->setParam('{{preview}}', $preview);
$bodyTemplate->setParam('{{previewWhitespace}}', $previewWhitespace, false);
$body = $bodyTemplate->render();
$subjectTemplate = Template::fromString($subject);