♻️ Refactored emails

This commit is contained in:
2025-11-09 14:06:12 +08:00
parent 6c8ad05872
commit 6101de741f
17 changed files with 765 additions and 587 deletions

View File

@@ -447,10 +447,10 @@ public class AccountService(
}
await mailer
.SendTemplatedEmailAsync<Emails.VerificationEmail, VerificationEmailModel>(
.SendTemplatedEmailAsync<Emails.FactorCodeEmail, VerificationEmailModel>(
account.Nick,
contact.Content,
emailLocalizer["EmailCodeTitle"],
emailLocalizer["CodeEmailTitle"],
new VerificationEmailModel
{
Name = account.Name,

View File

@@ -94,10 +94,10 @@ public class MagicSpellService(
switch (spell.Type)
{
case MagicSpellType.AccountActivation:
await email.SendTemplatedEmailAsync<LandingEmail, LandingEmailModel>(
await email.SendTemplatedEmailAsync<RegistrationConfirmEmail, LandingEmailModel>(
contact.Account.Nick,
contact.Content,
localizer["EmailLandingTitle"],
localizer["RegConfirmTitle"],
new LandingEmailModel
{
Name = contact.Account.Name,
@@ -109,7 +109,7 @@ public class MagicSpellService(
await email.SendTemplatedEmailAsync<AccountDeletionEmail, AccountDeletionEmailModel>(
contact.Account.Nick,
contact.Content,
localizer["EmailAccountDeletionTitle"],
localizer["AccountDeletionTitle"],
new AccountDeletionEmailModel
{
Name = contact.Account.Name,
@@ -121,7 +121,7 @@ public class MagicSpellService(
await email.SendTemplatedEmailAsync<PasswordResetEmail, PasswordResetEmailModel>(
contact.Account.Nick,
contact.Content,
localizer["EmailPasswordResetTitle"],
localizer["PasswordResetTitle"],
new PasswordResetEmailModel
{
Name = contact.Account.Name,
@@ -135,7 +135,7 @@ public class MagicSpellService(
await email.SendTemplatedEmailAsync<ContactVerificationEmail, ContactVerificationEmailModel>(
contact.Account.Nick,
contactMethod!,
localizer["EmailContactVerificationTitle"],
localizer["ContractVerificationTitle"],
new ContactVerificationEmailModel
{
Name = contact.Account.Name,

View File

@@ -2,36 +2,106 @@
@using Microsoft.Extensions.Localization
<EmailLayout>
<tr>
<td class="wrapper">
<p class="font-bold">@(Localizer["AccountDeletionHeader"])</p>
<p>@(Localizer["AccountDeletionPara1"]) @@@Name,</p>
<p>@(Localizer["AccountDeletionPara2"])</p>
<p>@(Localizer["AccountDeletionPara3"])</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<div style="display: none">
@Localizer["AccountDeletionHeader"]
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
</div>
<div role="article" aria-roledescription="email" aria-label lang="en">
<div class="sm-px-4"
style="background-color: #f8fafc; font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif">
<table align="center" style="margin: 0 auto" cellpadding="0" cellspacing="0" role="none">
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<td style="width: 552px; max-width: 100%">
<div role="separator" style="line-height: 24px">&zwj;</div>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td>
<a href="@Link" target="_blank">
@(Localizer["AccountDeletionButton"])
<td class="sm-p-6"
style="border-radius: 8px; background-color: #fffffe; padding: 24px 36px; border: 1px solid #e2e8f0">
<a href="https://solian.app">
<img src="https://solian.app/favicon.png" width="70" alt="Solar Network Logo"
style="max-width: 100%; vertical-align: middle">
</a>
<div role="separator" style="line-height: 24px">&zwj;</div>
<h1 style="margin: 0 0 24px; font-size: 24px; line-height: 32px; font-weight: 600; color: #0f172a">
@Localizer["UsernameFormat", Name]
</h1>
<p style="margin: 0 0 24px; font-size: 16px; line-height: 24px; color: #475569">
@Localizer["AccountDeletionBody"]
</p>
<div>
<a href="@Link"
style="display: inline-block; text-decoration: none; padding: 16px 24px; font-size: 16px; line-height: 1; border-radius: 4px; color: #fffffe; background-color: #020617"
class="hover-bg-slate-800">
<!--[if mso]><i style="mso-font-width: 150%; mso-text-raise: 31px" hidden>&emsp;</i><![endif]-->
<span style="mso-text-raise: 16px">@Localizer["AccountDeletionButton"]</span>
<!--[if mso]><i hidden style="mso-font-width: 150%">&emsp;&#8203;</i><![endif]-->
</a>
</div>
<div role="separator" style="line-height: 24px">&zwj;</div>
<p style="margin: 0; font-size: 16px; line-height: 24px; color: #475569">
Thanks,
<br>
<span style="font-weight: 600">Solar Network Team</span>
</p>
<div role="separator"
style="height: 1px; line-height: 1px; background-color: #cbd5e1; margin-top: 24px; margin-bottom: 24px">
&zwj;
</div>
<p class="mso-break-all" style="margin: 0 0 16px; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["AccountDeletionHint"]
</p>
<p class="mso-break-all"
style="margin: 0; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["AlternativeLinkHint"]
<a href="@Link" style="color: #1e293b; text-decoration: underline">@Link</a>
</p>
</td>
</tr>
</table>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td class="sm-px-6" style="padding: 24px 36px">
<p style="margin: 0; font-size: 12px; color: #64748b">
&copy; 2025 Solsynth LLC. All rights
reserved.
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>@(Localizer["AccountDeletionPara4"])</p>
</td>
</tr>
</div>
</div>
</EmailLayout>
@code {

View File

@@ -3,36 +3,106 @@
@using EmailResource = DysonNetwork.Pass.Localization.EmailResource
<EmailLayout>
<tr>
<td class="wrapper">
<p class="font-bold">@(Localizer["ContactVerificationHeader"])</p>
<p>@(Localizer["ContactVerificationPara1"]) @Name,</p>
<p>@(Localizer["ContactVerificationPara2"])</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<div style="display: none">
@Localizer["ContactVerificationHeader"]
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
</div>
<div role="article" aria-roledescription="email" aria-label lang="en">
<div class="sm-px-4"
style="background-color: #f8fafc; font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif">
<table align="center" style="margin: 0 auto" cellpadding="0" cellspacing="0" role="none">
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<td style="width: 552px; max-width: 100%">
<div role="separator" style="line-height: 24px">&zwj;</div>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td>
<a href="@Link" target="_blank">
@(Localizer["ContactVerificationButton"])
<td class="sm-p-6"
style="border-radius: 8px; background-color: #fffffe; padding: 24px 36px; border: 1px solid #e2e8f0">
<a href="https://solian.app">
<img src="https://solian.app/favicon.png" width="70" alt="Solar Network Logo"
style="max-width: 100%; vertical-align: middle">
</a>
<div role="separator" style="line-height: 24px">&zwj;</div>
<h1 style="margin: 0 0 24px; font-size: 24px; line-height: 32px; font-weight: 600; color: #0f172a">
@Localizer["UsernameFormat", Name]
</h1>
<p style="margin: 0 0 24px; font-size: 16px; line-height: 24px; color: #475569">
@Localizer["ContactVerificationBody"]
</p>
<div>
<a href="@Link"
style="display: inline-block; text-decoration: none; padding: 16px 24px; font-size: 16px; line-height: 1; border-radius: 4px; color: #fffffe; background-color: #020617"
class="hover-bg-slate-800">
<!--[if mso]><i style="mso-font-width: 150%; mso-text-raise: 31px" hidden>&emsp;</i><![endif]-->
<span style="mso-text-raise: 16px">@Localizer["ContactVerificationButton"]</span>
<!--[if mso]><i hidden style="mso-font-width: 150%">&emsp;&#8203;</i><![endif]-->
</a>
</div>
<div role="separator" style="line-height: 24px">&zwj;</div>
<p style="margin: 0; font-size: 16px; line-height: 24px; color: #475569">
Thanks,
<br>
<span style="font-weight: 600">Solar Network Team</span>
</p>
<div role="separator"
style="height: 1px; line-height: 1px; background-color: #cbd5e1; margin-top: 24px; margin-bottom: 24px">
&zwj;
</div>
<p class="mso-break-all" style="margin: 0 0 16px; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["ContactVerificationHint"]
</p>
<p class="mso-break-all"
style="margin: 0; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["AlternativeLinkHint"]
<a href="@Link" style="color: #1e293b; text-decoration: underline">@Link</a>
</p>
</td>
</tr>
</table>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td class="sm-px-6" style="padding: 24px 36px">
<p style="margin: 0; font-size: 12px; color: #64748b">
&copy; 2025 Solsynth LLC. All rights
reserved.
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>@(Localizer["ContactVerificationPara3"])</p>
<p>@(Localizer["ContactVerificationPara4"])</p>
</td>
</tr>
</div>
</div>
</EmailLayout>
@code {

View File

@@ -1,334 +1,62 @@
@inherits LayoutComponentBase
<!doctype html>
<html lang="en">
<!DOCTYPE html>
<html lang="en" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style media="all" type="text/css">
body {
font-family: Helvetica, sans-serif;
-webkit-font-smoothing: antialiased;
font-size: 16px;
line-height: 1.3;
-ms-text-size-adjust: 100%;
-webkit-text-size-adjust: 100%;
<meta charset="utf-8">
<meta name="x-apple-disable-message-reformatting">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="format-detection" content="telephone=no, date=no, address=no, email=no, url=no">
<meta name="color-scheme" content="light dark">
<meta name="supported-color-schemes" content="light dark">
<!--[if mso]>
<noscript>
<xml>
<o:OfficeDocumentSettings xmlns:o="urn:schemas-microsoft-com:office:office">
<o:PixelsPerInch>96</o:PixelsPerInch>
</o:OfficeDocumentSettings>
</xml>
</noscript>
<style>
td, th, div, p, a, h1, h2, h3, h4, h5, h6 {
font-family: "Segoe UI", sans-serif;
mso-line-height-rule: exactly;
}
table {
border-collapse: separate;
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
width: 100%;
.mso-break-all {
word-break: break-all;
}
</style>
<![endif]-->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet"
media="screen">
<style>
.hover-bg-slate-800:hover {
background-color: #1e293b !important
}
table td {
font-family: Helvetica, sans-serif;
font-size: 16px;
vertical-align: top;
}
body {
background-color: #f4f5f6;
margin: 0;
padding: 0;
}
.body {
background-color: #f4f5f6;
width: 100%;
}
.container {
margin: 0 auto !important;
max-width: 600px;
padding: 0;
padding-top: 24px;
width: 600px;
}
.content {
box-sizing: border-box;
display: block;
margin: 0 auto;
max-width: 600px;
padding: 0;
}
.main {
background: #ffffff;
border: 1px solid #eaebed;
border-radius: 16px;
width: 100%;
}
.wrapper {
box-sizing: border-box;
padding: 24px;
}
.footer {
clear: both;
padding-top: 24px;
text-align: center;
width: 100%;
}
.footer td,
.footer p,
.footer span,
.footer a {
color: #9a9ea6;
font-size: 16px;
text-align: center;
}
p {
font-family: Helvetica, sans-serif;
font-size: 16px;
font-weight: normal;
margin: 0;
margin-bottom: 16px;
}
a {
color: #0867ec;
text-decoration: underline;
}
.btn {
box-sizing: border-box;
min-width: 100% !important;
width: 100%;
}
.btn > tbody > tr > td {
padding-bottom: 16px;
}
.btn table {
width: auto;
}
.btn table td {
background-color: #ffffff;
border-radius: 4px;
text-align: center;
}
.btn a {
background-color: #ffffff;
border: solid 2px #0867ec;
border-radius: 4px;
box-sizing: border-box;
color: #0867ec;
cursor: pointer;
display: inline-block;
font-size: 16px;
font-weight: bold;
margin: 0;
padding: 12px 24px;
text-decoration: none;
text-transform: capitalize;
}
.btn-primary table td {
background-color: #0867ec;
}
.btn-primary a {
background-color: #0867ec;
border-color: #0867ec;
color: #ffffff;
}
.font-bold {
font-weight: bold;
}
.verification-code
{
font-family: "Courier New", Courier, monospace;
font-size: 24px;
letter-spacing: 0.5em;
}
@@media all {
.btn-primary table td:hover {
background-color: #ec0867 !important;
@@media (max-width: 600px) {
.sm-p-6 {
padding: 24px !important
}
.btn-primary a:hover {
background-color: #ec0867 !important;
border-color: #ec0867 !important;
}
}
.last {
margin-bottom: 0;
}
.first {
margin-top: 0;
}
.align-center {
text-align: center;
}
.align-right {
text-align: right;
}
.align-left {
text-align: left;
}
.text-link {
color: #0867ec !important;
text-decoration: underline !important;
}
.clear {
clear: both;
}
.mt0 {
margin-top: 0;
}
.mb0 {
margin-bottom: 0;
}
.preheader {
color: transparent;
display: none;
height: 0;
max-height: 0;
max-width: 0;
opacity: 0;
overflow: hidden;
mso-hide: all;
visibility: hidden;
width: 0;
}
.powered-by a {
text-decoration: none;
}
@@media only screen and (max-width: 640px) {
.main p,
.main td,
.main span {
font-size: 16px !important;
.sm-px-4 {
padding-left: 16px !important;
padding-right: 16px !important
}
.wrapper {
padding: 8px !important;
}
.content {
padding: 0 !important;
}
.container {
padding: 0 !important;
padding-top: 8px !important;
width: 100% !important;
}
.main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
.btn table {
max-width: 100% !important;
width: 100% !important;
}
.btn a {
font-size: 16px !important;
max-width: 100% !important;
width: 100% !important;
}
}
@@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
#MessageViewBody a {
color: inherit;
text-decoration: none;
font-size: inherit;
font-family: inherit;
font-weight: inherit;
line-height: inherit;
.sm-px-6 {
padding-left: 24px !important;
padding-right: 24px !important
}
}
</style>
</head>
<body>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="body">
<tr>
<td>&nbsp;</td>
<td class="container">
<div class="content">
<!-- START CENTERED WHITE CONTAINER -->
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="main">
<!-- START MAIN CONTENT AREA -->
@ChildContent
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="content-block">
<span class="apple-link">Solar Network</span>
<br> Solsynth LLC © @(DateTime.Now.Year)
</td>
</tr>
<tr>
<td class="content-block powered-by">
Powered by <a href="https://github.com/solsynth/dysonnetwork">Dyson Network</a>
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER --></div>
</td>
<td>&nbsp;</td>
</tr>
</table>
<body
style="margin: 0; width: 100%; background-color: #f8fafc; padding: 0; -webkit-font-smoothing: antialiased; word-break: break-word">
@ChildContent
</body>
</html>

View File

@@ -0,0 +1,107 @@
@using DysonNetwork.Pass.Localization
@using Microsoft.Extensions.Localization
@using EmailResource = DysonNetwork.Pass.Localization.EmailResource
<EmailLayout>
<div style="display: none">
@Localizer["CodeEmailHeader"]
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
</div>
<div role="article" aria-roledescription="email" aria-label lang="en">
<div class="sm-px-4"
style="background-color: #f8fafc; font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif">
<table align="center" style="margin: 0 auto" cellpadding="0" cellspacing="0" role="none">
<tr>
<td style="width: 552px; max-width: 100%">
<div role="separator" style="line-height: 24px">&zwj;</div>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td class="sm-p-6"
style="border-radius: 8px; background-color: #fffffe; padding: 24px 36px; border: 1px solid #e2e8f0">
<a href="https://solian.app">
<img src="https://solian.app/favicon.png" width="70" alt="Solar Network Logo"
style="max-width: 100%; vertical-align: middle">
</a>
<div role="separator" style="line-height: 24px">&zwj;</div>
<h1 style="margin: 0 0 24px; font-size: 24px; line-height: 32px; font-weight: 600; color: #0f172a">
@Localizer["UsernameFormat", Name]
</h1>
<p style="margin: 0 0 24px; font-size: 16px; line-height: 24px; color: #475569">
@Localizer["CodeEmailBody"]
</p>
<p style="margin: 0; font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 16px; line-height: 24px; font-weight: 700; letter-spacing: 8px; color: #475569">
@Code
</p>
<div role="separator" style="line-height: 24px">&zwj;</div>
<p style="margin: 0; font-size: 16px; line-height: 24px; color: #475569">
Thanks,
<br>
<span style="font-weight: 600">Solar Network Team</span>
</p>
<div role="separator"
style="height: 1px; line-height: 1px; background-color: #cbd5e1; margin-top: 24px; margin-bottom: 24px">
&zwj;
</div>
<p class="mso-break-all" style="margin: 0 0 16px; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["CodeEmailHint"]
</p>
<p class="mso-break-all"
style="margin: 0; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["CodeEmailHintSecondary"]
</p>
</td>
</tr>
</table>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td class="sm-px-6" style="padding: 24px 36px">
<p style="margin: 0; font-size: 12px; color: #64748b">
&copy; 2025 Solsynth LLC. All rights
reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</EmailLayout>
@code {
[Parameter] public required string Name { get; set; }
[Parameter] public required string Code { get; set; }
[Inject] IStringLocalizer<EmailResource> Localizer { get; set; } = null!;
[Inject] IStringLocalizer<SharedResource> LocalizerShared { get; set; } = null!;
}

View File

@@ -1,43 +0,0 @@
@using DysonNetwork.Pass.Localization
@using Microsoft.Extensions.Localization
@using EmailResource = DysonNetwork.Pass.Localization.EmailResource
<EmailLayout>
<tr>
<td class="wrapper">
<p class="font-bold">@(Localizer["LandingHeader1"])</p>
<p>@(Localizer["LandingPara1"]) @@@Name,</p>
<p>@(Localizer["LandingPara2"])</p>
<p>@(Localizer["LandingPara3"])</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<tr>
<td>
<a href="@Link" target="_blank">
@(Localizer["LandingButton1"])
</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>@(Localizer["LandingPara4"])</p>
</td>
</tr>
</EmailLayout>
@code {
[Parameter] public required string Name { get; set; }
[Parameter] public required string Link { get; set; }
[Inject] IStringLocalizer<EmailResource> Localizer { get; set; } = null!;
}

View File

@@ -3,36 +3,106 @@
@using EmailResource = DysonNetwork.Pass.Localization.EmailResource
<EmailLayout>
<tr>
<td class="wrapper">
<p class="font-bold">@(Localizer["PasswordResetHeader"])</p>
<p>@(Localizer["PasswordResetPara1"]) @@@Name,</p>
<p>@(Localizer["PasswordResetPara2"])</p>
<p>@(Localizer["PasswordResetPara3"])</p>
<table role="presentation" border="0" cellpadding="0" cellspacing="0" class="btn btn-primary">
<tbody>
<div style="display: none">
@Localizer["PasswordResetHeader"]
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
</div>
<div role="article" aria-roledescription="email" aria-label lang="en">
<div class="sm-px-4"
style="background-color: #f8fafc; font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif">
<table align="center" style="margin: 0 auto" cellpadding="0" cellspacing="0" role="none">
<tr>
<td align="left">
<table role="presentation" border="0" cellpadding="0" cellspacing="0">
<tbody>
<td style="width: 552px; max-width: 100%">
<div role="separator" style="line-height: 24px">&zwj;</div>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td>
<a href="@Link" target="_blank">
@(Localizer["PasswordResetButton"])
<td class="sm-p-6"
style="border-radius: 8px; background-color: #fffffe; padding: 24px 36px; border: 1px solid #e2e8f0">
<a href="https://solian.app">
<img src="https://solian.app/favicon.png" width="70" alt="Solar Network Logo"
style="max-width: 100%; vertical-align: middle">
</a>
<div role="separator" style="line-height: 24px">&zwj;</div>
<h1 style="margin: 0 0 24px; font-size: 24px; line-height: 32px; font-weight: 600; color: #0f172a">
@Localizer["UsernameFormat", Name]
</h1>
<p style="margin: 0 0 24px; font-size: 16px; line-height: 24px; color: #475569">
@Localizer["PasswordResetBody"]
</p>
<div>
<a href="@Link"
style="display: inline-block; text-decoration: none; padding: 16px 24px; font-size: 16px; line-height: 1; border-radius: 4px; color: #fffffe; background-color: #020617"
class="hover-bg-slate-800">
<!--[if mso]><i style="mso-font-width: 150%; mso-text-raise: 31px" hidden>&emsp;</i><![endif]-->
<span style="mso-text-raise: 16px">@Localizer["PasswordResetButton"]</span>
<!--[if mso]><i hidden style="mso-font-width: 150%">&emsp;&#8203;</i><![endif]-->
</a>
</div>
<div role="separator" style="line-height: 24px">&zwj;</div>
<p style="margin: 0; font-size: 16px; line-height: 24px; color: #475569">
Thanks,
<br>
<span style="font-weight: 600">Solar Network Team</span>
</p>
<div role="separator"
style="height: 1px; line-height: 1px; background-color: #cbd5e1; margin-top: 24px; margin-bottom: 24px">
&zwj;
</div>
<p class="mso-break-all" style="margin: 0 0 16px; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["PasswordResetHint"]
</p>
<p class="mso-break-all"
style="margin: 0; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["AlternativeLinkHint"]
<a href="@Link" style="color: #1e293b; text-decoration: underline">@Link</a>
</p>
</td>
</tr>
</table>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td class="sm-px-6" style="padding: 24px 36px">
<p style="margin: 0; font-size: 12px; color: #64748b">
&copy; 2025 Solsynth LLC. All rights
reserved.
</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>@(Localizer["PasswordResetPara4"])</p>
</td>
</tr>
</div>
</div>
</EmailLayout>
@code {

View File

@@ -0,0 +1,109 @@
@using Microsoft.Extensions.Localization
@using EmailResource = DysonNetwork.Pass.Localization.EmailResource
<EmailLayout>
<div style="display: none">
@Localizer["RegConfirmHeader"]
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
&#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847; &#8199;&#65279;&#847;
</div>
<div role="article" aria-roledescription="email" aria-label lang="en">
<div class="sm-px-4"
style="background-color: #f8fafc; font-family: Inter, ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif">
<table align="center" style="margin: 0 auto" cellpadding="0" cellspacing="0" role="none">
<tr>
<td style="width: 552px; max-width: 100%">
<div role="separator" style="line-height: 24px">&zwj;</div>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td class="sm-p-6"
style="border-radius: 8px; background-color: #fffffe; padding: 24px 36px; border: 1px solid #e2e8f0">
<a href="https://solian.app">
<img src="https://solian.app/favicon.png" width="70" alt="Solar Network Logo"
style="max-width: 100%; vertical-align: middle">
</a>
<div role="separator" style="line-height: 24px">&zwj;</div>
<h1 style="margin: 0 0 24px; font-size: 24px; line-height: 32px; font-weight: 600; color: #0f172a">
@Localizer["UsernameFormat", Name]
</h1>
<p style="margin: 0 0 24px; font-size: 16px; line-height: 24px; color: #475569">
@Localizer["RegConfirmBody"]
</p>
<div>
<a href="@Link"
style="display: inline-block; text-decoration: none; padding: 16px 24px; font-size: 16px; line-height: 1; border-radius: 4px; color: #fffffe; background-color: #020617"
class="hover-bg-slate-800">
<!--[if mso]><i style="mso-font-width: 150%; mso-text-raise: 31px" hidden>&emsp;</i><![endif]-->
<span style="mso-text-raise: 16px">@Localizer["RegConfirmButton"]</span>
<!--[if mso]><i hidden style="mso-font-width: 150%">&emsp;&#8203;</i><![endif]-->
</a>
</div>
<div role="separator" style="line-height: 24px">&zwj;</div>
<p style="margin: 0; font-size: 16px; line-height: 24px; color: #475569">
Thanks,
<br>
<span style="font-weight: 600">Solar Network Team</span>
</p>
<div role="separator"
style="height: 1px; line-height: 1px; background-color: #cbd5e1; margin-top: 24px; margin-bottom: 24px">
&zwj;
</div>
<p class="mso-break-all"
style="margin: 0; font-size: 12px; line-height: 20px; color: #475569">
@Localizer["AlternativeLinkHint"]
<a href="@Link" style="color: #1e293b; text-decoration: underline">@Link</a>
</p>
</td>
</tr>
</table>
<table style="width: 100%" cellpadding="0" cellspacing="0" role="none">
<tr>
<td class="sm-px-6" style="padding: 24px 36px">
<p style="margin: 0; font-size: 12px; color: #64748b">
&copy; 2025 Solsynth LLC. All rights
reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</div>
</EmailLayout>
@code {
[Parameter] public required string Name { get; set; }
[Parameter] public required string Link { get; set; }
[Inject] IStringLocalizer<EmailResource> Localizer { get; set; } = null!;
}

View File

@@ -1,27 +0,0 @@
@using DysonNetwork.Pass.Localization
@using Microsoft.Extensions.Localization
@using EmailResource = DysonNetwork.Pass.Localization.EmailResource
<EmailLayout>
<tr>
<td class="wrapper">
<p class="font-bold">@(Localizer["CodeHeader1"])</p>
<p>@(Localizer["CodePara1"]) @@@Name,</p>
<p>@(Localizer["CodePara2"])</p>
<p>@(Localizer["CodePara3"])</p>
<p class="verification-code">@Code</p>
<p>@(Localizer["CodePara4"])</p>
<p>@(Localizer["CodePara5"])</p>
</td>
</tr>
</EmailLayout>
@code {
[Parameter] public required string Name { get; set; }
[Parameter] public required string Code { get; set; }
[Inject] IStringLocalizer<EmailResource> Localizer { get; set; } = null!;
[Inject] IStringLocalizer<SharedResource> LocalizerShared { get; set; } = null!;
}

View File

@@ -1,7 +0,0 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10

View File

@@ -1,3 +1,4 @@
.idea
.vscode
node_modules
build_production

View File

@@ -0,0 +1,86 @@
---
bodyClass: bg-slate-50
preheader: Registeration Confirmation
---
<x-main>
<div class="bg-slate-50 sm:px-4 font-inter">
<table align="center" class="m-0 mx-auto">
<tr>
<td class="w-[552px] max-w-full">
<x-spacer height="24px" />
<table class="w-full">
<tr>
<td
class="py-6 px-9 sm:p-6 bg-white [border:1px_solid_theme(colors.slate.200)] rounded-lg"
>
<a href="https://solian.app">
<img
src="https://solian.app/favicon.png"
src-production="https://solian.app/favicon.png"
width="70"
alt="Solar Network Logo"
/>
</a>
<x-spacer height="24px" />
<h1 class="m-0 mb-6 text-2xl/8 text-slate-900 font-semibold">
Dear, {{ Name }}
</h1>
<p class="m-0 mb-6 text-base/6 text-slate-600">
We're happy to have you joining our community! Please confirm
your registeration in order to activate your account to unlock
all the features available:
</p>
<x-button
href="{{ URL }}"
class="bg-slate-950 hover:bg-slate-800"
>
Confirm
</x-button>
<x-spacer height="24px" />
<p class="m-0 text-base/6 text-slate-600">
Thanks,
<br />
<span class="font-semibold">Solar Network Team</span>
</p>
<x-divider />
<p class="m-0 text-xs/5 text-slate-600 mso-break-all mb-4">
The link will expires in 24 hours, if you didn't request
this code, you can safety ignore this email.
</p>
<p class="m-0 text-xs/5 text-slate-600 mso-break-all">
If you're having trouble clicking the "Confirm" button, copy
and paste the following URL into your web browser:
<a href="{{ URL }}" class="text-slate-800 underline"
>{{ URL }}</a
>
</p>
</td>
</tr>
</table>
<table class="w-full">
<tr>
<td class="py-6 px-9 sm:px-6">
<p class="m-0 text-xs text-slate-500">
&copy; {{ new Date().getFullYear() }} Solsynth LLC. All rights
reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</x-main>

View File

@@ -27,7 +27,7 @@ preheader: Registeration Confirmation
<x-spacer height="24px" />
<h1 class="m-0 mb-6 text-2xl/8 text-slate-900 font-semibold">
Hello there!
Dear, {{ Name }}
</h1>
<p class="m-0 mb-6 text-base/6 text-slate-600">

View File

@@ -0,0 +1,74 @@
---
bodyClass: bg-slate-50
preheader: Registeration Confirmation
---
<x-main>
<div class="bg-slate-50 sm:px-4 font-inter">
<table align="center" class="m-0 mx-auto">
<tr>
<td class="w-[552px] max-w-full">
<x-spacer height="24px" />
<table class="w-full">
<tr>
<td
class="py-6 px-9 sm:p-6 bg-white [border:1px_solid_theme(colors.slate.200)] rounded-lg"
>
<a href="https://solian.app">
<img
src="https://solian.app/favicon.png"
src-production="https://solian.app/favicon.png"
width="70"
alt="Solar Network Logo"
/>
</a>
<x-spacer height="24px" />
<h1 class="m-0 mb-6 text-2xl/8 text-slate-900 font-semibold">
Dear, {{ Name }}
</h1>
<p class="m-0 mb-6 text-base/6 text-slate-600">
Someone trying to use email auth factor to authorize an access
request. If that is you, enter the code below to continue.
</p>
<p class="m-0 text-3xl text-base/6 font-mono text-slate-600 font-bold tracking-2">
000000
</p>
<x-spacer height="24px" />
<p class="m-0 text-base/6 text-slate-600">
Thanks,
<br />
<span class="font-semibold">Solar Network Team</span>
</p>
<x-divider />
<p class="m-0 text-xs/5 text-slate-600 mso-break-all">
The code will expires in 30 minutes, if you didn't request
this code, you can safety ignore this email.
</p>
</td>
</tr>
</table>
<table class="w-full">
<tr>
<td class="py-6 px-9 sm:px-6">
<p class="m-0 text-xs text-slate-500">
&copy; {{ new Date().getFullYear() }} Solsynth LLC. All rights
reserved.
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</x-main>

View File

@@ -18,49 +18,34 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="LandingHeader1" xml:space="preserve">
<data name="RegConfirmHeader" xml:space="preserve">
<value>Welcome to the Solar Network!</value>
</data>
<data name="LandingPara1" xml:space="preserve">
<value>Dear, </value>
<data name="RegConfirmBody" xml:space="preserve">
<value>We're happy to have you joining our community! Please confirm your registeration in order to activate your account to unlock all the features available.</value>
</data>
<data name="LandingPara2" xml:space="preserve">
<value>Thank you for creating an account on the Solar Network. We're excited to have you join our community!</value>
</data>
<data name="LandingPara3" xml:space="preserve">
<value>To access all features and ensure the security of your account, please confirm your registration by clicking the button below:</value>
</data>
<data name="LandingButton1" xml:space="preserve">
<data name="RegConfirmButton" xml:space="preserve">
<value>Confirm Registration</value>
</data>
<data name="LandingPara4" xml:space="preserve">
<value>If you didn't create this account, please ignore this email.</value>
</data>
<data name="EmailLandingTitle" xml:space="preserve">
<data name="RegConfirmTitle" xml:space="preserve">
<value>Confirm your registration</value>
</data>
<data name="AccountDeletionHeader" xml:space="preserve">
<value>Account Deletion Confirmation</value>
</data>
<data name="AccountDeletionPara1" xml:space="preserve">
<value>Dear, </value>
</data>
<data name="AccountDeletionPara2" xml:space="preserve">
<value>We've received a request to delete your Solar Network account. We're sorry to see you go.</value>
</data>
<data name="AccountDeletionPara3" xml:space="preserve">
<value>To confirm your account deletion, please click the button below. Please note that this action is permanent and cannot be undone.</value>
<data name="AccountDeletionBody" xml:space="preserve">
<value>We've received a request to delete your Solar Network account. We're sorry to see you go. To confirm your account deletion, please click the button below. Please note that this action is permanent and cannot be undone.</value>
</data>
<data name="AccountDeletionButton" xml:space="preserve">
<value>Confirm Account Deletion</value>
</data>
<data name="AccountDeletionPara4" xml:space="preserve">
<data name="AccountDeletionHint" xml:space="preserve">
<value>If you did not request to delete your account, please ignore this email or contact our support team immediately.</value>
</data>
<data name="EmailAccountDeletionTitle" xml:space="preserve">
<value>Confirm your account deletion</value>
</data>
<data name="EmailPasswordResetTitle" xml:space="preserve">
<data name="PasswordResetTitle" xml:space="preserve">
<value>Reset your password</value>
</data>
<data name="PasswordResetButton" xml:space="preserve">
@@ -69,61 +54,46 @@
<data name="PasswordResetHeader" xml:space="preserve">
<value>Password Reset Request</value>
</data>
<data name="PasswordResetPara1" xml:space="preserve">
<value>Dear,</value>
</data>
<data name="PasswordResetPara2" xml:space="preserve">
<value>We recieved a request to reset your Solar Network account password.</value>
</data>
<data name="PasswordResetPara3" xml:space="preserve">
<value>You can click the button below to continue reset your password.</value>
</data>
<data name="PasswordResetPara4" xml:space="preserve">
<data name="PasswordResetHint" xml:space="preserve">
<value>If you didn't request this, you can ignore this email safety.</value>
</data>
<data name="EmailVerificationTitle" xml:space="preserve">
<value>Verify your email address</value>
<data name="ContractMethodVerificationTitle" xml:space="preserve">
<value>Verify Contact Method</value>
</data>
<data name="ContactVerificationHeader" xml:space="preserve">
<value>Verify Your Contact Information</value>
<value>Verify Contact Method</value>
</data>
<data name="ContactVerificationPara1" xml:space="preserve">
<value>Dear, </value>
</data>
<data name="ContactVerificationPara2" xml:space="preserve">
<value>Thank you for updating your contact information on the Solar Network. To ensure your account security, we need to verify this change.</value>
</data>
<data name="ContactVerificationPara3" xml:space="preserve">
<value>Please click the button below to verify your contact information:</value>
<data name="ContactVerificationBody" xml:space="preserve">
<value>Thank you for updating your contact method on the Solar Network. To ensure your account security, we need to verify this change. Please click the button below to verify your contact method:</value>
</data>
<data name="ContactVerificationButton" xml:space="preserve">
<value>Verify Contact Information</value>
<value>Verify</value>
</data>
<data name="ContactVerificationPara4" xml:space="preserve">
<data name="ContactVerificationHint" xml:space="preserve">
<value>If you didn't request this change, please contact our support team immediately.</value>
</data>
<data name="EmailContactVerificationTitle" xml:space="preserve">
<value>Verify your contact information</value>
</data>
<data name="EmailCodeTitle" xml:space="preserve">
<data name="CodeEmailTitle" xml:space="preserve">
<value>Your email one-time-password</value>
</data>
<data name="CodeHeader1" xml:space="preserve">
<data name="CodeEmailHeader" xml:space="preserve">
<value>Email One-time-password</value>
</data>
<data name="CodePara1" xml:space="preserve">
<value>Dear, </value>
<data name="CodeEmailBody" xml:space="preserve">
<value>Someone trying to use email auth factor to authorize an access request. If that is you, enter the code below to continue.</value>
</data>
<data name="CodePara2" xml:space="preserve">
<value>Someone trying to use email auth factor to authorize an access request</value>
</data>
<data name="CodePara3" xml:space="preserve">
<value>If that is you, enter the code below to continue</value>
</data>
<data name="CodePara4" xml:space="preserve">
<data name="CodeEmailHint" xml:space="preserve">
<value>This code will expire in 30 minutes.</value>
</data>
<data name="CodePara5" xml:space="preserve">
<data name="CodeEmailHintSecondary" xml:space="preserve">
<value>If you didn't request this, you can ignore this email safely</value>
</data>
<data name="UsernameFormat" xml:space="preserve">
<value>Dear, {0}</value>
</data>
<data name="AlternativeLinkHint" xml:space="preserve">
<value>If you're having trouble clicking the button, copy and paste the following URL into your web browser:</value>
</data>
<data name="PasswordResetBody" xml:space="preserve">
<value>We recieved a request to reset your Solar Network account password. Click the button below to continue and reset it.</value>
</data>
</root>

View File

@@ -11,43 +11,28 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="LandingHeader1" xml:space="preserve">
<data name="RegConfirmHeader" xml:space="preserve">
<value>欢迎来到 Solar Network</value>
</data>
<data name="LandingPara1" xml:space="preserve">
<data name="RegConfirmBody" xml:space="preserve">
<value>尊敬的 </value>
</data>
<data name="LandingButton1" xml:space="preserve">
<data name="RegConfirmButton" xml:space="preserve">
<value>确认注册</value>
</data>
<data name="LandingPara2" xml:space="preserve">
<value>感谢你在 Solar Network 上注册帐号,我们很激动你即将加入我们的社区!</value>
</data>
<data name="LandingPara3" xml:space="preserve">
<value>点击下方按钮来确认你的注册以获得所有功能的权限。</value>
</data>
<data name="LandingPara4" xml:space="preserve">
<value>如果你并没有注册帐号,你可以忽略此邮件。</value>
</data>
<data name="EmailLandingTitle" xml:space="preserve">
<data name="RegConfirmTitle" xml:space="preserve">
<value>确认你的注册</value>
</data>
<data name="AccountDeletionHeader" xml:space="preserve">
<value>账户删除确认</value>
</data>
<data name="AccountDeletionPara1" xml:space="preserve">
<value>尊敬的 </value>
</data>
<data name="AccountDeletionPara2" xml:space="preserve">
<value>我们收到了删除您 Solar Network 账户的请求。我们很遗憾看到您的离开。</value>
</data>
<data name="AccountDeletionPara3" xml:space="preserve">
<value>请点击下方按钮确认删除您的账户。请注意,此操作是永久性的,无法撤销。</value>
<data name="AccountDeletionBody" xml:space="preserve">
<value>我们收到了删除您 Solar Network 账户的请求。我们很遗憾看到您的离开。请点击下方按钮确认删除您的账户。请注意,此操作是永久性的,无法撤销。</value>
</data>
<data name="AccountDeletionButton" xml:space="preserve">
<value>确认删除账户</value>
</data>
<data name="AccountDeletionPara4" xml:space="preserve">
<data name="AccountDeletionHint" xml:space="preserve">
<value>如果您并未请求删除账户,请忽略此邮件或立即联系我们的支持团队。</value>
</data>
<data name="EmailAccountDeletionTitle" xml:space="preserve">
@@ -56,67 +41,52 @@
<data name="PasswordResetHeader" xml:space="preserve">
<value>密码重置请求</value>
</data>
<data name="PasswordResetPara1" xml:space="preserve">
<value>尊敬的 </value>
</data>
<data name="PasswordResetPara2" xml:space="preserve">
<value>我们收到了重置您 Solar Network 账户密码的请求。</value>
</data>
<data name="PasswordResetPara3" xml:space="preserve">
<value>请点击下方按钮重置您的密码。此链接将在24小时后失效。</value>
</data>
<data name="PasswordResetButton" xml:space="preserve">
<value>重置密码</value>
</data>
<data name="PasswordResetPara4" xml:space="preserve">
<data name="PasswordResetHint" xml:space="preserve">
<value>如果您并未请求重置密码,你可以安全地忽略此邮件。</value>
</data>
<data name="EmailPasswordResetTitle" xml:space="preserve">
<data name="PasswordResetTitle" xml:space="preserve">
<value>重置您的密码</value>
</data>
<data name="EmailVerificationTitle" xml:space="preserve">
<value>验证您的电子邮箱</value>
<data name="ContractMethodVerificationTitle" xml:space="preserve">
<value>验证您的联系方式</value>
</data>
<data name="ContactVerificationHeader" xml:space="preserve">
<value>验证您的联系信息</value>
<value>验证您的联系方式</value>
</data>
<data name="ContactVerificationPara1" xml:space="preserve">
<value>尊敬的 </value>
</data>
<data name="ContactVerificationPara2" xml:space="preserve">
<value>感谢您更新 Solar Network 上的联系信息。为确保您的账户安全,我们需要验证此更改。</value>
</data>
<data name="ContactVerificationPara3" xml:space="preserve">
<value>请点击下方按钮验证您的联系信息:</value>
<data name="ContactVerificationBody" xml:space="preserve">
<value>感谢您更新 Solar Network 上的联系方式。为确保您的账户安全,我们需要验证此更改。请点击下方按钮验证您的联系方式。</value>
</data>
<data name="ContactVerificationButton" xml:space="preserve">
<value>验证联系信息</value>
<value>验证</value>
</data>
<data name="ContactVerificationPara4" xml:space="preserve">
<data name="ContactVerificationHint" xml:space="preserve">
<value>如果您没有请求此更改,请立即联系我们的支持团队。</value>
</data>
<data name="EmailContactVerificationTitle" xml:space="preserve">
<value>验证您的联系信息</value>
</data>
<data name="EmailCodeTitle" xml:space="preserve">
<data name="CodeEmailTitle" xml:space="preserve">
<value>您的一次性邮件验证码</value>
</data>
<data name="CodeHeader1" xml:space="preserve">
<data name="CodeEmailHeader" xml:space="preserve">
<value>邮件一次性验证码</value>
</data>
<data name="CodePara1" xml:space="preserve">
<value>尊敬的</value>
<data name="CodeEmailBody" xml:space="preserve">
<value>有人正在尝试使用邮件验证码作为验证因子授权访问。如果那位用户就是您,输入下方的验证码来继续访问。</value>
</data>
<data name="CodePara2" xml:space="preserve">
<value>有人正在尝试使用邮件验证码作为验证因子授权访问</value>
</data>
<data name="CodePara3" xml:space="preserve">
<value>如果那位用户就是您,输入下方的验证码来继续访问</value>
</data>
<data name="CodePara4" xml:space="preserve">
<data name="CodeEmailHint" xml:space="preserve">
<value>验证码会在 30 分钟后过期</value>
</data>
<data name="CodePara5" xml:space="preserve">
<data name="CodeEmailHintSecondary" xml:space="preserve">
<value>如果您未申请过本验证码,您可以安全的忽略这封邮件</value>
</data>
<data name="UsernameFormat" xml:space="preserve">
<value>尊敬的 {0}</value>
</data>
<data name="AlternativeLinkHint" xml:space="preserve">
<value>如果您无法点击上面的按钮,您也可以尝试复制下面的连接到浏览器访问</value>
</data>
<data name="PasswordResetBody" xml:space="preserve">
<value>我们收到了重置您 Solar Network 账户密码的请求。请点击下方按钮重置您的密码</value>
</data>
</root>