mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
feat(backend): signup email localized (#8459)
* localized registration email * localized email verification email * localized reset password email
This commit is contained in:
parent
63dd215297
commit
65f764f6d9
@ -62,6 +62,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -185,6 +189,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
|
||||
@ -0,0 +1,261 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`sendEmailVerification English renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Hello User,</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>So, you want to change your e-mail? No problem! Just click the button below to verify your new address:</p><a class="button" href="http://webapp:3000/settings/my-email-address/verify?email=user%40example.org&nonce=123456">Verify e-mail address</a>
|
||||
<p>If you don't want to change your e-mail address feel free to ignore this message. </p>
|
||||
<p>If the above button doesn't work, you can also copy the following code into your browser window: <span>123456</span></p>
|
||||
<div class="text-block">
|
||||
<p>See you soon on <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– The ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "New E-Mail Address ocelot.social",
|
||||
"text": "HELLO USER,
|
||||
|
||||
So, you want to change your e-mail? No problem! Just click the button below to
|
||||
verify your new address:
|
||||
|
||||
Verify e-mail address
|
||||
[http://webapp:3000/settings/my-email-address/verify?email=user%40example.org&nonce=123456]
|
||||
|
||||
If you don't want to change your e-mail address feel free to ignore this
|
||||
message.
|
||||
|
||||
If the above button doesn't work, you can also copy the following code into your
|
||||
browser window: 123456
|
||||
|
||||
See you soon on ocelot.social [https://ocelot.social]!
|
||||
|
||||
– The ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`sendEmailVerification German renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Hallo User,</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>Du möchtest also deine E-Mail ändern? Kein Problem! Mit Klick auf diesen Button kannst Du Deine neue E-Mail Adresse bestätigen:</p><a class="button" href="http://webapp:3000/settings/my-email-address/verify?email=user%40example.org&nonce=123456">E-Mail Adresse bestätigen</a>
|
||||
<p>Falls Du deine E-Mail Adresse doch nicht ändern möchtest, kannst du diese Nachricht einfach ignorieren. </p>
|
||||
<p>Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: <span>123456</span></p>
|
||||
<div class="text-block">
|
||||
<p>Bis bald bei <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– Dein ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Neue E-Mail Addresse ocelot.social",
|
||||
"text": "HALLO USER,
|
||||
|
||||
Du möchtest also deine E-Mail ändern? Kein Problem! Mit Klick auf diesen Button
|
||||
kannst Du Deine neue E-Mail Adresse bestätigen:
|
||||
|
||||
E-Mail Adresse bestätigen
|
||||
[http://webapp:3000/settings/my-email-address/verify?email=user%40example.org&nonce=123456]
|
||||
|
||||
Falls Du deine E-Mail Adresse doch nicht ändern möchtest, kannst du diese
|
||||
Nachricht einfach ignorieren.
|
||||
|
||||
Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in
|
||||
Dein Browserfenster kopieren: 123456
|
||||
|
||||
Bis bald bei ocelot.social [https://ocelot.social]!
|
||||
|
||||
– Dein ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
@ -62,6 +62,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -184,6 +188,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -308,6 +316,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -432,6 +444,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -556,6 +572,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -679,6 +699,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -801,6 +825,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -920,6 +948,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1043,6 +1075,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1166,6 +1202,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1288,6 +1328,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1412,6 +1456,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1536,6 +1584,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1660,6 +1712,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1783,6 +1839,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -1905,6 +1965,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -2024,6 +2088,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
@ -2147,6 +2215,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
|
||||
@ -0,0 +1,559 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`sendRegistrationMail with invite code English renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Welcome to ocelot.social!</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>Thank you for joining our cause – it's awesome to have you on board. There's just one tiny step missing before we can start shaping the world together … Please confirm your e-mail address by clicking the button below:</p><a class="button" href="http://webapp:3000/registration?email=user%40example.org&nonce=123456&inviteCode=welcome&method=invite-code">Confirm your e-mail address</a>
|
||||
<p>If the above button doesn't work, you can also copy the following code into your browser window: <span>123456</span></p>
|
||||
<p>However, this only works if you have registered through our website.</p>
|
||||
<p>If you didn't sign up for <a>ocelot.social</a> we recommend you to check it out! It's a social network from people for people who want to connect and change the world together.
|
||||
</p>
|
||||
<p>PS: If you ignore this e-mail we will not create an account for you. ;)</p>
|
||||
<div class="text-block">
|
||||
<p>See you soon on <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– The ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Welcome to ocelot.social",
|
||||
"text": "WELCOME TO OCELOT.SOCIAL!
|
||||
|
||||
Thank you for joining our cause – it's awesome to have you on board. There's
|
||||
just one tiny step missing before we can start shaping the world together …
|
||||
Please confirm your e-mail address by clicking the button below:
|
||||
|
||||
Confirm your e-mail address
|
||||
[http://webapp:3000/registration?email=user%40example.org&nonce=123456&inviteCode=welcome&method=invite-code]
|
||||
|
||||
If the above button doesn't work, you can also copy the following code into your
|
||||
browser window: 123456
|
||||
|
||||
However, this only works if you have registered through our website.
|
||||
|
||||
If you didn't sign up for ocelot.social we recommend you to check it out! It's a
|
||||
social network from people for people who want to connect and change the world
|
||||
together.
|
||||
|
||||
PS: If you ignore this e-mail we will not create an account for you. ;)
|
||||
|
||||
See you soon on ocelot.social [https://ocelot.social]!
|
||||
|
||||
– The ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`sendRegistrationMail with invite code German renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Willkommen bei ocelot.social!</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>Danke, dass du dich angemeldet hast – wir freuen uns, dich dabei zu haben. Jetzt fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können … Bitte bestätige Deine E-Mail Adresse:</p><a class="button" href="http://webapp:3000/registration?email=user%40example.org&nonce=123456&inviteCode=welcome&method=invite-code">Bestätige Deine E-Mail Adresse</a>
|
||||
<p>Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: <span>123456</span></p>
|
||||
<p>Das funktioniert allerdings nur, wenn du Dich über unsere Website registriert hast.</p>
|
||||
<p>Falls Du Dich nicht selbst bei <a>ocelot.social</a> angemeldet hast, schau doch mal vorbei! Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.
|
||||
</p>
|
||||
<p>PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese E-Mail einfach ignorieren. ;)</p>
|
||||
<div class="text-block">
|
||||
<p>Bis bald bei <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– Dein ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Willkommen bei ocelot.social",
|
||||
"text": "WILLKOMMEN BEI OCELOT.SOCIAL!
|
||||
|
||||
Danke, dass du dich angemeldet hast – wir freuen uns, dich dabei zu haben. Jetzt
|
||||
fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können
|
||||
… Bitte bestätige Deine E-Mail Adresse:
|
||||
|
||||
Bestätige Deine E-Mail Adresse
|
||||
[http://webapp:3000/registration?email=user%40example.org&nonce=123456&inviteCode=welcome&method=invite-code]
|
||||
|
||||
Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in
|
||||
Dein Browserfenster kopieren: 123456
|
||||
|
||||
Das funktioniert allerdings nur, wenn du Dich über unsere Website registriert
|
||||
hast.
|
||||
|
||||
Falls Du Dich nicht selbst bei ocelot.social angemeldet hast, schau doch mal
|
||||
vorbei! Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.
|
||||
|
||||
PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese E-Mail einfach
|
||||
ignorieren. ;)
|
||||
|
||||
Bis bald bei ocelot.social [https://ocelot.social]!
|
||||
|
||||
– Dein ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`sendRegistrationMail without invite code English renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Welcome to ocelot.social!</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>Thank you for joining our cause – it's awesome to have you on board. There's just one tiny step missing before we can start shaping the world together … Please confirm your e-mail address by clicking the button below:</p><a class="button" href="http://webapp:3000/registration?email=user%40example.org&nonce=123456&method=invite-mail">Confirm your e-mail address</a>
|
||||
<p>If the above button doesn't work, you can also copy the following code into your browser window: <span>123456</span></p>
|
||||
<p>However, this only works if you have registered through our website.</p>
|
||||
<p>If you didn't sign up for <a>ocelot.social</a> we recommend you to check it out! It's a social network from people for people who want to connect and change the world together.
|
||||
</p>
|
||||
<p>PS: If you ignore this e-mail we will not create an account for you. ;)</p>
|
||||
<div class="text-block">
|
||||
<p>See you soon on <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– The ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Welcome to ocelot.social",
|
||||
"text": "WELCOME TO OCELOT.SOCIAL!
|
||||
|
||||
Thank you for joining our cause – it's awesome to have you on board. There's
|
||||
just one tiny step missing before we can start shaping the world together …
|
||||
Please confirm your e-mail address by clicking the button below:
|
||||
|
||||
Confirm your e-mail address
|
||||
[http://webapp:3000/registration?email=user%40example.org&nonce=123456&method=invite-mail]
|
||||
|
||||
If the above button doesn't work, you can also copy the following code into your
|
||||
browser window: 123456
|
||||
|
||||
However, this only works if you have registered through our website.
|
||||
|
||||
If you didn't sign up for ocelot.social we recommend you to check it out! It's a
|
||||
social network from people for people who want to connect and change the world
|
||||
together.
|
||||
|
||||
PS: If you ignore this e-mail we will not create an account for you. ;)
|
||||
|
||||
See you soon on ocelot.social [https://ocelot.social]!
|
||||
|
||||
– The ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`sendRegistrationMail without invite code German renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Willkommen bei ocelot.social!</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>Danke, dass du dich angemeldet hast – wir freuen uns, dich dabei zu haben. Jetzt fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können … Bitte bestätige Deine E-Mail Adresse:</p><a class="button" href="http://webapp:3000/registration?email=user%40example.org&nonce=123456&method=invite-mail">Bestätige Deine E-Mail Adresse</a>
|
||||
<p>Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: <span>123456</span></p>
|
||||
<p>Das funktioniert allerdings nur, wenn du Dich über unsere Website registriert hast.</p>
|
||||
<p>Falls Du Dich nicht selbst bei <a>ocelot.social</a> angemeldet hast, schau doch mal vorbei! Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.
|
||||
</p>
|
||||
<p>PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese E-Mail einfach ignorieren. ;)</p>
|
||||
<div class="text-block">
|
||||
<p>Bis bald bei <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– Dein ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Willkommen bei ocelot.social",
|
||||
"text": "WILLKOMMEN BEI OCELOT.SOCIAL!
|
||||
|
||||
Danke, dass du dich angemeldet hast – wir freuen uns, dich dabei zu haben. Jetzt
|
||||
fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können
|
||||
… Bitte bestätige Deine E-Mail Adresse:
|
||||
|
||||
Bestätige Deine E-Mail Adresse
|
||||
[http://webapp:3000/registration?email=user%40example.org&nonce=123456&method=invite-mail]
|
||||
|
||||
Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in
|
||||
Dein Browserfenster kopieren: 123456
|
||||
|
||||
Das funktioniert allerdings nur, wenn du Dich über unsere Website registriert
|
||||
hast.
|
||||
|
||||
Falls Du Dich nicht selbst bei ocelot.social angemeldet hast, schau doch mal
|
||||
vorbei! Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.
|
||||
|
||||
PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese E-Mail einfach
|
||||
ignorieren. ;)
|
||||
|
||||
Bis bald bei ocelot.social [https://ocelot.social]!
|
||||
|
||||
– Dein ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
@ -0,0 +1,260 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`sendResetPasswordMail English renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Hello Jenny Rostock,</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>So, you forgot your password? No problem! Just click the button below to reset it within the next 24 hours:</p><a class="button" href="http://webapp:3000/password-reset/change-password?email=user%40example.org&nonce=123456">Confirm your e-mail address</a>
|
||||
<p>If you didn't request a new password feel free to ignore this e-mail.</p>
|
||||
<p>If the above button doesn't work you can also copy the following code into your browser window: <span>123456</span></p>
|
||||
<div class="text-block">
|
||||
<p>See you soon on <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– The ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Reset Password ocelot.social",
|
||||
"text": "HELLO JENNY ROSTOCK,
|
||||
|
||||
So, you forgot your password? No problem! Just click the button below to reset
|
||||
it within the next 24 hours:
|
||||
|
||||
Confirm your e-mail address
|
||||
[http://webapp:3000/password-reset/change-password?email=user%40example.org&nonce=123456]
|
||||
|
||||
If you didn't request a new password feel free to ignore this e-mail.
|
||||
|
||||
If the above button doesn't work you can also copy the following code into your
|
||||
browser window: 123456
|
||||
|
||||
See you soon on ocelot.social [https://ocelot.social]!
|
||||
|
||||
– The ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`sendResetPasswordMail German renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Hallo Jenny Rostock,</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>Du hast also dein Passwort vergessen? Kein Problem! Mit Klick auf diesen Button kannst du innerhalb der nächsten 24 Stunden dein Passwort zurücksetzen:</p><a class="button" href="http://webapp:3000/password-reset/change-password?email=user%40example.org&nonce=123456">Bestätige Deine E-Mail Adresse</a>
|
||||
<p>Falls du kein neues Passwort angefordert hast, kannst du diese E-Mail einfach ignorieren.</p>
|
||||
<p>Sollte der Button für dich nicht funktionieren, kannst du auch folgenden Code in Dein Browserfenster kopieren: <span>123456</span></p>
|
||||
<div class="text-block">
|
||||
<p>Bis bald bei <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– Dein ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Neues Passwort ocelot.social",
|
||||
"text": "HALLO JENNY ROSTOCK,
|
||||
|
||||
Du hast also dein Passwort vergessen? Kein Problem! Mit Klick auf diesen Button
|
||||
kannst du innerhalb der nächsten 24 Stunden dein Passwort zurücksetzen:
|
||||
|
||||
Bestätige Deine E-Mail Adresse
|
||||
[http://webapp:3000/password-reset/change-password?email=user%40example.org&nonce=123456]
|
||||
|
||||
Falls du kein neues Passwort angefordert hast, kannst du diese E-Mail einfach
|
||||
ignorieren.
|
||||
|
||||
Sollte der Button für dich nicht funktionieren, kannst du auch folgenden Code in
|
||||
Dein Browserfenster kopieren: 123456
|
||||
|
||||
Bis bald bei ocelot.social [https://ocelot.social]!
|
||||
|
||||
– Dein ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
255
backend/src/emails/__snapshots__/sendWrongEmail.spec.ts.snap
Normal file
255
backend/src/emails/__snapshots__/sendWrongEmail.spec.ts.snap
Normal file
@ -0,0 +1,255 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`sendWrongEmail English renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Welcome to ocelot.social!</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>You requested a password reset but unfortunately we couldn't find an account associated with your e-mail address. Did you maybe use another one when you signed up?</p><a class="button" href="http://webapp:3000/password-reset/request">Try a different e-mail</a>
|
||||
<p>If you don't have an account at <a>ocelot.social</a> yet or if you didn't want to reset your password, please ignore this e-mail.
|
||||
</p>
|
||||
<div class="text-block">
|
||||
<p>See you soon on <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– The ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Wrong E-mail? ocelot.social",
|
||||
"text": "WELCOME TO OCELOT.SOCIAL!
|
||||
|
||||
You requested a password reset but unfortunately we couldn't find an account
|
||||
associated with your e-mail address. Did you maybe use another one when you
|
||||
signed up?
|
||||
|
||||
Try a different e-mail [http://webapp:3000/password-reset/request]
|
||||
|
||||
If you don't have an account at ocelot.social yet or if you didn't want to reset
|
||||
your password, please ignore this e-mail.
|
||||
|
||||
See you soon on ocelot.social [https://ocelot.social]!
|
||||
|
||||
– The ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`sendWrongEmail German renders correctly 1`] = `
|
||||
{
|
||||
"attachments": [],
|
||||
"from": "ocelot.social",
|
||||
"html": "<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta content="multipart/html; charset=UTF-8" http-equiv="content-type">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>.wf-force-outline-none[tabindex="-1"]:focus{outline:none;}</style>
|
||||
<style>body{
|
||||
display: block;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 17px;
|
||||
text-align: left;
|
||||
text-align: -webkit-left;
|
||||
justify-content: center;
|
||||
padding: 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 25px;
|
||||
font-size: 25px;
|
||||
font-weight: normal;
|
||||
line-height: 22px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 680px;
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.head-logo {
|
||||
width: 60%;
|
||||
height: auto;
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
a.button {
|
||||
background: #17b53e;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 15px;
|
||||
text-decoration: none;
|
||||
text-align:center;
|
||||
padding: 13px 17px;
|
||||
color: #ffffff;
|
||||
display: table;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
footer {
|
||||
padding: 20px;
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
text-align: center;
|
||||
color: #888888;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="head"><img class="head-logo" alt="Welcome Image" loading="lazy" src="http://webapp:3000/img/custom/logo-squared.svg">
|
||||
</div>
|
||||
</header>
|
||||
<h2>Willkommen bei ocelot.social!</h2>
|
||||
<div class="wrapper">
|
||||
<div class="content"></div>
|
||||
<p>Du hast bei uns ein neues Passwort angefordert – leider haben wir aber keinen Account mit deiner E-Mailadresse gefunden. Kann es sein, dass du mit einer anderen Adresse bei uns angemeldet bist?</p><a class="button" href="http://webapp:3000/password-reset/request">Versuch' es mit einer anderen E-Mail</a>
|
||||
<p>Wenn du noch keinen Account bei <a>ocelot.social</a> hast oder dein Password gar nicht ändern willst, kannst du diese E-Mail einfach ignorieren!
|
||||
</p>
|
||||
<div class="text-block">
|
||||
<p>Bis bald bei <a class="organization" href="https://ocelot.social">ocelot.social</a>!</p>
|
||||
<p>– Dein ocelot.social Team</p>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer"></div><a href="https://ocelot.social">ocelot.social Community</a>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>",
|
||||
"subject": "Falsche Mailaddresse? ocelot.social",
|
||||
"text": "WILLKOMMEN BEI OCELOT.SOCIAL!
|
||||
|
||||
Du hast bei uns ein neues Passwort angefordert – leider haben wir aber keinen
|
||||
Account mit deiner E-Mailadresse gefunden. Kann es sein, dass du mit einer
|
||||
anderen Adresse bei uns angemeldet bist?
|
||||
|
||||
Versuch' es mit einer anderen E-Mail [http://webapp:3000/password-reset/request]
|
||||
|
||||
Wenn du noch keinen Account bei ocelot.social hast oder dein Password gar nicht
|
||||
ändern willst, kannst du diese E-Mail einfach ignorieren!
|
||||
|
||||
Bis bald bei ocelot.social [https://ocelot.social]!
|
||||
|
||||
– Dein ocelot.social Team
|
||||
|
||||
|
||||
ocelot.social Community [https://ocelot.social]",
|
||||
"to": "user@example.org",
|
||||
}
|
||||
`;
|
||||
@ -7,12 +7,32 @@
|
||||
"followedUserPosted": "Neuer Beitrag von gefolgtem Nutzer",
|
||||
"mentionedInComment": "Erwähnung in Kommentar",
|
||||
"mentionedInPost": "Erwähnung in Beitrag",
|
||||
"newEmail": "Neue E-Mail Addresse",
|
||||
"removedUserFromGroup": "Aus Gruppe entfernt",
|
||||
"postInGroup": "Neuer Beitrag in Gruppe",
|
||||
"resetPassword": "Neues Passwort",
|
||||
"userJoinedGroup": "Nutzer tritt Gruppe bei",
|
||||
"userLeftGroup": "Nutzer verlässt Gruppe"
|
||||
"userLeftGroup": "Nutzer verlässt Gruppe",
|
||||
"wrongEmail": "Falsche Mailaddresse?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Danke, dass du dich angemeldet hast – wir freuen uns, dich dabei zu haben. Jetzt fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können … Bitte bestätige Deine E-Mail Adresse:",
|
||||
"codeHint": "Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: ",
|
||||
"codeHintException": "Das funktioniert allerdings nur, wenn du Dich über unsere Website registriert hast.",
|
||||
"notYouStart": "Falls Du Dich nicht selbst bei ",
|
||||
"notYouEnd": " angemeldet hast, schau doch mal vorbei! Wir sind ein gemeinnütziges Aktionsnetzwerk – von Menschen für Menschen.",
|
||||
"ps": "PS: Wenn Du keinen Account bei uns möchtest, kannst Du diese E-Mail einfach ignorieren. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: ",
|
||||
"introduction": "Du möchtest also deine E-Mail ändern? Kein Problem! Mit Klick auf diesen Button kannst Du Deine neue E-Mail Adresse bestätigen:",
|
||||
"doNotChange": "Falls Du deine E-Mail Adresse doch nicht ändern möchtest, kannst du diese Nachricht einfach ignorieren. "
|
||||
},
|
||||
"buttons": {
|
||||
"confirmEmail": "Bestätige Deine E-Mail Adresse",
|
||||
"resetPassword": "Passwort zurücksetzen",
|
||||
"tryAgain": "Versuch' es mit einer anderen E-Mail",
|
||||
"verifyEmail": "E-Mail Adresse bestätigen",
|
||||
"viewChat": "Chat anzeigen",
|
||||
"viewComment": "Kommentar ansehen",
|
||||
"viewGroup": "Gruppe ansehen",
|
||||
@ -23,7 +43,19 @@
|
||||
"seeYou": "Bis bald bei ",
|
||||
"yourTeam": "– Dein {team} Team",
|
||||
"settingsHint": "PS: Möchtest du keine E-Mails mehr erhalten, dann ändere deine ",
|
||||
"settingsName": "Benachrichtigungseinstellungen"
|
||||
"settingsName": "Benachrichtigungseinstellungen",
|
||||
"welcome": "Willkommen bei"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "Sollte der Button für dich nicht funktionieren, kannst du auch folgenden Code in Dein Browserfenster kopieren: ",
|
||||
"ignore": "Falls du kein neues Passwort angefordert hast, kannst du diese E-Mail einfach ignorieren.",
|
||||
"introduction": "Du hast also dein Passwort vergessen? Kein Problem! Mit Klick auf diesen Button kannst du innerhalb der nächsten 24 Stunden dein Passwort zurücksetzen:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"codeHint": "Sollte der Button für Dich nicht funktionieren, kannst Du auch folgenden Code in Dein Browserfenster kopieren: ",
|
||||
"ignoreEnd": " hast oder dein Password gar nicht ändern willst, kannst du diese E-Mail einfach ignorieren!",
|
||||
"ignoreStart": "Wenn du noch keinen Account bei ",
|
||||
"introduction": "Du hast bei uns ein neues Passwort angefordert – leider haben wir aber keinen Account mit deiner E-Mailadresse gefunden. Kann es sein, dass du mit einer anderen Adresse bei uns angemeldet bist?"
|
||||
},
|
||||
"changedGroupMemberRole": "deine Rolle in der Gruppe „{groupName}“ wurde geändert. Klicke auf den Knopf, um diese Gruppe zu sehen:",
|
||||
"chatMessageStart": "du hast eine neue Chat-Nachricht von ",
|
||||
|
||||
@ -7,12 +7,32 @@
|
||||
"followedUserPosted": "New post by followd user",
|
||||
"mentionedInComment": "Mentioned in comment",
|
||||
"mentionedInPost": "Mentioned in post",
|
||||
"newEmail": "New E-Mail Address",
|
||||
"removedUserFromGroup": "Removed from group",
|
||||
"postInGroup": "New post in group",
|
||||
"resetPassword": "Reset Password",
|
||||
"userJoinedGroup": "User joined group",
|
||||
"userLeftGroup": "User left group"
|
||||
"userLeftGroup": "User left group",
|
||||
"wrongEmail": "Wrong E-mail?"
|
||||
},
|
||||
"registration": {
|
||||
"introduction": "Thank you for joining our cause – it's awesome to have you on board. There's just one tiny step missing before we can start shaping the world together … Please confirm your e-mail address by clicking the button below:",
|
||||
"codeHint": "If the above button doesn't work, you can also copy the following code into your browser window: ",
|
||||
"codeHintException": "However, this only works if you have registered through our website.",
|
||||
"notYouStart": "If you didn't sign up for ",
|
||||
"notYouEnd": " we recommend you to check it out! It's a social network from people for people who want to connect and change the world together.",
|
||||
"ps": "PS: If you ignore this e-mail we will not create an account for you. ;)"
|
||||
},
|
||||
"emailVerification": {
|
||||
"codeHint": "If the above button doesn't work, you can also copy the following code into your browser window: ",
|
||||
"introduction": "So, you want to change your e-mail? No problem! Just click the button below to verify your new address:",
|
||||
"doNotChange": "If you don't want to change your e-mail address feel free to ignore this message. "
|
||||
},
|
||||
"buttons": {
|
||||
"confirmEmail": "Confirm your e-mail address",
|
||||
"resetPassword": "Reset password",
|
||||
"tryAgain": "Try a different e-mail",
|
||||
"verifyEmail": "Verify e-mail address",
|
||||
"viewChat": "Show Chat",
|
||||
"viewComment": "View comment",
|
||||
"viewGroup": "View group",
|
||||
@ -23,7 +43,18 @@
|
||||
"seeYou": "See you soon on ",
|
||||
"yourTeam": "– The {team} Team",
|
||||
"settingsHint": "PS: If you don't want to receive e-mails anymore, change your ",
|
||||
"settingsName": "notification settings"
|
||||
"settingsName": "notification settings",
|
||||
"welcome": "Welcome to"
|
||||
},
|
||||
"resetPassword": {
|
||||
"codeHint": "If the above button doesn't work you can also copy the following code into your browser window: ",
|
||||
"ignore": "If you didn't request a new password feel free to ignore this e-mail.",
|
||||
"introduction": "So, you forgot your password? No problem! Just click the button below to reset it within the next 24 hours:"
|
||||
},
|
||||
"wrongEmail": {
|
||||
"ignoreEnd": " yet or if you didn't want to reset your password, please ignore this e-mail.",
|
||||
"ignoreStart": "If you don't have an account at ",
|
||||
"introduction": "You requested a password reset but unfortunately we couldn't find an account associated with your e-mail address. Did you maybe use another one when you signed up?"
|
||||
},
|
||||
"changedGroupMemberRole": "your role in the group “{groupName}” has been changed. Click on the button to view this group:",
|
||||
"chatMessageStart": "you have received a new chat message from ",
|
||||
|
||||
@ -28,6 +28,7 @@ const defaultParams = {
|
||||
ORGANIZATION_URL: CONFIG.ORGANIZATION_URL,
|
||||
supportUrl: CONFIG.SUPPORT_URL,
|
||||
settingsUrl,
|
||||
renderSettingsUrl: true,
|
||||
}
|
||||
|
||||
export const transport = createTransport({
|
||||
@ -202,3 +203,137 @@ export const sendChatMessageMail = async (
|
||||
throw new Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
interface VerifyMailInput {
|
||||
email: string
|
||||
nonce: string
|
||||
locale: string
|
||||
}
|
||||
|
||||
interface RegistrationMailInput extends VerifyMailInput {
|
||||
inviteCode?: string
|
||||
}
|
||||
|
||||
export const sendRegistrationMail = async (
|
||||
data: RegistrationMailInput,
|
||||
): Promise<OriginalMessage> => {
|
||||
const { nonce, locale, inviteCode } = data
|
||||
const to = data.email
|
||||
const actionUrl = new URL('/registration', CONFIG.CLIENT_URI)
|
||||
actionUrl.searchParams.set('email', to)
|
||||
actionUrl.searchParams.set('nonce', nonce)
|
||||
if (inviteCode) {
|
||||
actionUrl.searchParams.set('inviteCode', inviteCode)
|
||||
actionUrl.searchParams.set('method', 'invite-code')
|
||||
} else {
|
||||
actionUrl.searchParams.set('method', 'invite-mail')
|
||||
}
|
||||
|
||||
try {
|
||||
const { originalMessage } = await email.send({
|
||||
template: path.join(__dirname, 'templates', 'registration'),
|
||||
message: {
|
||||
to,
|
||||
},
|
||||
locals: {
|
||||
...defaultParams,
|
||||
locale,
|
||||
actionUrl,
|
||||
nonce,
|
||||
renderSettingsUrl: false,
|
||||
},
|
||||
})
|
||||
return originalMessage as OriginalMessage
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
interface EmailVerificationInput extends VerifyMailInput {
|
||||
name: string
|
||||
}
|
||||
|
||||
export const sendEmailVerification = async (
|
||||
data: EmailVerificationInput,
|
||||
): Promise<OriginalMessage> => {
|
||||
const { nonce, locale, name } = data
|
||||
const to = data.email
|
||||
const actionUrl = new URL('/settings/my-email-address/verify', CONFIG.CLIENT_URI)
|
||||
actionUrl.searchParams.set('email', to)
|
||||
actionUrl.searchParams.set('nonce', nonce)
|
||||
|
||||
try {
|
||||
const { originalMessage } = await email.send({
|
||||
template: path.join(__dirname, 'templates', 'emailVerification'),
|
||||
message: {
|
||||
to,
|
||||
},
|
||||
locals: {
|
||||
...defaultParams,
|
||||
locale,
|
||||
actionUrl,
|
||||
nonce,
|
||||
name,
|
||||
renderSettingsUrl: false,
|
||||
},
|
||||
})
|
||||
return originalMessage as OriginalMessage
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const sendResetPasswordMail = async (
|
||||
data: EmailVerificationInput,
|
||||
): Promise<OriginalMessage> => {
|
||||
const { nonce, locale, name } = data
|
||||
const to = data.email
|
||||
const actionUrl = new URL('/password-reset/change-password', CONFIG.CLIENT_URI)
|
||||
actionUrl.searchParams.set('email', to)
|
||||
actionUrl.searchParams.set('nonce', nonce)
|
||||
try {
|
||||
const { originalMessage } = await email.send({
|
||||
template: path.join(__dirname, 'templates', 'resetPassword'),
|
||||
message: {
|
||||
to,
|
||||
},
|
||||
locals: {
|
||||
...defaultParams,
|
||||
locale,
|
||||
actionUrl,
|
||||
nonce,
|
||||
name,
|
||||
renderSettingsUrl: false,
|
||||
},
|
||||
})
|
||||
return originalMessage as OriginalMessage
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
export const sendWrongEmail = async (data: {
|
||||
locale: string
|
||||
email: string
|
||||
}): Promise<OriginalMessage> => {
|
||||
const { locale } = data
|
||||
const to = data.email
|
||||
const actionUrl = new URL('/password-reset/request', CONFIG.CLIENT_URI)
|
||||
try {
|
||||
const { originalMessage } = await email.send({
|
||||
template: path.join(__dirname, 'templates', 'wrongEmail'),
|
||||
message: {
|
||||
to,
|
||||
},
|
||||
locals: {
|
||||
...defaultParams,
|
||||
locale,
|
||||
actionUrl,
|
||||
renderSettingsUrl: false,
|
||||
},
|
||||
})
|
||||
return originalMessage as OriginalMessage
|
||||
} catch (error) {
|
||||
throw new Error(error)
|
||||
}
|
||||
}
|
||||
|
||||
35
backend/src/emails/sendEmailVerification.spec.ts
Normal file
35
backend/src/emails/sendEmailVerification.spec.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { sendEmailVerification } from './sendEmail'
|
||||
|
||||
describe('sendEmailVerification', () => {
|
||||
const data: {
|
||||
email: string
|
||||
nonce: string
|
||||
locale: string
|
||||
name: string
|
||||
} = {
|
||||
email: 'user@example.org',
|
||||
nonce: '123456',
|
||||
locale: 'en',
|
||||
name: 'User',
|
||||
}
|
||||
|
||||
describe('English', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'en'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendEmailVerification(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe('German', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'de'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendEmailVerification(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
63
backend/src/emails/sendRegistrationMail.spec.ts
Normal file
63
backend/src/emails/sendRegistrationMail.spec.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { sendRegistrationMail } from './sendEmail'
|
||||
|
||||
describe('sendRegistrationMail', () => {
|
||||
const data: {
|
||||
email: string
|
||||
nonce: string
|
||||
locale: string
|
||||
inviteCode?: string
|
||||
} = {
|
||||
email: 'user@example.org',
|
||||
nonce: '123456',
|
||||
locale: 'en',
|
||||
inviteCode: 'welcome',
|
||||
}
|
||||
|
||||
describe('with invite code', () => {
|
||||
describe('English', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'en'
|
||||
data.inviteCode = 'welcome'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendRegistrationMail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe('German', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'de'
|
||||
data.inviteCode = 'welcome'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendRegistrationMail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('without invite code', () => {
|
||||
describe('English', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'en'
|
||||
delete data.inviteCode
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendRegistrationMail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe('German', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'de'
|
||||
delete data.inviteCode
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendRegistrationMail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
35
backend/src/emails/sendResetPasswordMail.spec.ts
Normal file
35
backend/src/emails/sendResetPasswordMail.spec.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { sendResetPasswordMail } from './sendEmail'
|
||||
|
||||
describe('sendResetPasswordMail', () => {
|
||||
const data: {
|
||||
email: string
|
||||
nonce: string
|
||||
locale: string
|
||||
name: string
|
||||
} = {
|
||||
email: 'user@example.org',
|
||||
nonce: '123456',
|
||||
locale: 'en',
|
||||
name: 'Jenny Rostock',
|
||||
}
|
||||
|
||||
describe('English', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'en'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendResetPasswordMail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe('German', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'de'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendResetPasswordMail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
31
backend/src/emails/sendWrongEmail.spec.ts
Normal file
31
backend/src/emails/sendWrongEmail.spec.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { sendWrongEmail } from './sendEmail'
|
||||
|
||||
describe('sendWrongEmail', () => {
|
||||
const data: {
|
||||
email: string
|
||||
locale: string
|
||||
} = {
|
||||
email: 'user@example.org',
|
||||
locale: 'en',
|
||||
}
|
||||
|
||||
describe('English', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'en'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendWrongEmail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
||||
describe('German', () => {
|
||||
beforeEach(() => {
|
||||
data.locale = 'de'
|
||||
})
|
||||
|
||||
it('renders correctly', async () => {
|
||||
await expect(sendWrongEmail(data)).resolves.toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
10
backend/src/emails/templates/emailVerification/html.pug
Normal file
10
backend/src/emails/templates/emailVerification/html.pug
Normal file
@ -0,0 +1,10 @@
|
||||
extend ../layout.pug
|
||||
|
||||
block content
|
||||
.content
|
||||
p= t('emailVerification.introduction')
|
||||
a.button(href=actionUrl)= t('buttons.verifyEmail')
|
||||
p= t('emailVerification.doNotChange')
|
||||
|
||||
p= t('emailVerification.codeHint')
|
||||
span= nonce
|
||||
@ -0,0 +1 @@
|
||||
= `${t('subjects.newEmail')} ${APPLICATION_NAME}`
|
||||
@ -3,10 +3,13 @@
|
||||
- var organizationUrl = ORGANIZATION_URL
|
||||
- var team = APPLICATION_NAME
|
||||
- var settingsUrl = settingsUrl
|
||||
- var renderSettingsUrl = renderSettingsUrl
|
||||
p= t('general.seeYou')
|
||||
a.organization(href=organizationUrl)= team
|
||||
| !
|
||||
p= t('general.yourTeam', { team })
|
||||
|
||||
if renderSettingsUrl
|
||||
br
|
||||
p= t('general.settingsHint')
|
||||
a.settings(href=settingsUrl)= t('general.settingsName')
|
||||
|
||||
@ -50,6 +50,10 @@ a.button {
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
span {
|
||||
color: #17b53e;
|
||||
}
|
||||
|
||||
.text-block {
|
||||
margin-top: 20px;
|
||||
color: #000000;
|
||||
|
||||
1
backend/src/emails/templates/includes/welcome.pug
Normal file
1
backend/src/emails/templates/includes/welcome.pug
Normal file
@ -0,0 +1 @@
|
||||
h2= `${t('general.welcome')} ${APPLICATION_NAME}!`
|
||||
@ -14,10 +14,14 @@ html(lang=locale)
|
||||
style
|
||||
include includes/webflow.css
|
||||
|
||||
- var name = name
|
||||
body
|
||||
div.container
|
||||
include includes/header.pug
|
||||
if name
|
||||
include includes/salutation.pug
|
||||
else
|
||||
include includes/welcome.pug
|
||||
|
||||
.wrapper
|
||||
block content
|
||||
|
||||
15
backend/src/emails/templates/registration/html.pug
Normal file
15
backend/src/emails/templates/registration/html.pug
Normal file
@ -0,0 +1,15 @@
|
||||
extend ../layout.pug
|
||||
|
||||
block content
|
||||
.content
|
||||
p= t('registration.introduction')
|
||||
a.button(href=actionUrl)= t('buttons.confirmEmail')
|
||||
p= t('registration.codeHint')
|
||||
span= nonce
|
||||
p= t('registration.codeHintException')
|
||||
|
||||
p= t('registration.notYouStart')
|
||||
a(href=ORGANIZATION_LINK)= APPLICATION_NAME
|
||||
= t('registration.notYouEnd')
|
||||
|
||||
p= t('registration.ps')
|
||||
1
backend/src/emails/templates/registration/subject.pug
Normal file
1
backend/src/emails/templates/registration/subject.pug
Normal file
@ -0,0 +1 @@
|
||||
= `${t('general.welcome')} ${APPLICATION_NAME}`
|
||||
9
backend/src/emails/templates/resetPassword/html.pug
Normal file
9
backend/src/emails/templates/resetPassword/html.pug
Normal file
@ -0,0 +1,9 @@
|
||||
extend ../layout.pug
|
||||
|
||||
block content
|
||||
.content
|
||||
p= t('resetPassword.introduction')
|
||||
a.button(href=actionUrl)= t('buttons.confirmEmail')
|
||||
p= t('resetPassword.ignore')
|
||||
p= t('resetPassword.codeHint')
|
||||
span= nonce
|
||||
1
backend/src/emails/templates/resetPassword/subject.pug
Normal file
1
backend/src/emails/templates/resetPassword/subject.pug
Normal file
@ -0,0 +1 @@
|
||||
= `${t('subjects.resetPassword')} ${APPLICATION_NAME}`
|
||||
10
backend/src/emails/templates/wrongEmail/html.pug
Normal file
10
backend/src/emails/templates/wrongEmail/html.pug
Normal file
@ -0,0 +1,10 @@
|
||||
extend ../layout.pug
|
||||
|
||||
block content
|
||||
.content
|
||||
p= t('wrongEmail.introduction')
|
||||
a.button(href=actionUrl)= t('buttons.tryAgain')
|
||||
|
||||
p= t('wrongEmail.ignoreStart')
|
||||
a(href=ORGANIZATION_LINK)= APPLICATION_NAME
|
||||
= t('wrongEmail.ignoreEnd')
|
||||
1
backend/src/emails/templates/wrongEmail/subject.pug
Normal file
1
backend/src/emails/templates/wrongEmail/subject.pug
Normal file
@ -0,0 +1 @@
|
||||
= `${t('subjects.wrongEmail')} ${APPLICATION_NAME}`
|
||||
@ -69,6 +69,7 @@ export default {
|
||||
)
|
||||
return result.records.map((record) => ({
|
||||
name: record.get('user').properties.name,
|
||||
locale: record.get('user').properties.locale,
|
||||
...record.get('email').properties,
|
||||
}))
|
||||
})
|
||||
|
||||
@ -71,14 +71,14 @@ describe('passwordReset', () => {
|
||||
|
||||
describe('requestPasswordReset', () => {
|
||||
const mutation = gql`
|
||||
mutation ($email: String!) {
|
||||
requestPasswordReset(email: $email)
|
||||
mutation ($email: String!, $locale: String!) {
|
||||
requestPasswordReset(email: $email, locale: $locale)
|
||||
}
|
||||
`
|
||||
|
||||
describe('with invalid email', () => {
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, email: 'non-existent@example.org' }
|
||||
variables = { ...variables, email: 'non-existent@example.org', locale: 'de' }
|
||||
})
|
||||
|
||||
it('resolves anyways', async () => {
|
||||
@ -96,7 +96,7 @@ describe('passwordReset', () => {
|
||||
|
||||
describe('with a valid email', () => {
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, email: 'user@example.org' }
|
||||
variables = { ...variables, email: 'user@example.org', locale: 'de' }
|
||||
})
|
||||
|
||||
it('resolves', async () => {
|
||||
|
||||
@ -50,14 +50,14 @@ afterEach(async () => {
|
||||
|
||||
describe('Signup', () => {
|
||||
const mutation = gql`
|
||||
mutation ($email: String!, $inviteCode: String) {
|
||||
Signup(email: $email, inviteCode: $inviteCode) {
|
||||
mutation ($email: String!, $locale: String!, $inviteCode: String) {
|
||||
Signup(email: $email, locale: $locale, inviteCode: $inviteCode) {
|
||||
email
|
||||
}
|
||||
}
|
||||
`
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, email: 'someuser@example.org' }
|
||||
variables = { ...variables, email: 'someuser@example.org', locale: 'de' }
|
||||
})
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
|
||||
@ -9,7 +9,11 @@ type Query {
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
Signup(email: String!, inviteCode: String = null): EmailAddress
|
||||
Signup(
|
||||
email: String!
|
||||
locale: String!
|
||||
inviteCode: String = null
|
||||
): EmailAddress
|
||||
SignupVerification(
|
||||
nonce: String!
|
||||
email: String!
|
||||
|
||||
@ -245,7 +245,7 @@ type Mutation {
|
||||
|
||||
updateOnlineStatus(status: OnlineStatus!): Boolean!
|
||||
|
||||
requestPasswordReset(email: String!): Boolean!
|
||||
requestPasswordReset(email: String!, locale: String!): Boolean!
|
||||
resetPassword(email: String!, nonce: String!, newPassword: String!): Boolean!
|
||||
changePassword(oldPassword: String!, newPassword: String!): String!
|
||||
|
||||
|
||||
@ -2,43 +2,41 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { sendMail } from '@middleware/helpers/email/sendMail'
|
||||
import {
|
||||
signupTemplate,
|
||||
resetPasswordTemplate,
|
||||
wrongAccountTemplate,
|
||||
emailVerificationTemplate,
|
||||
} from '@middleware/helpers/email/templateBuilder'
|
||||
sendRegistrationMail,
|
||||
sendEmailVerification,
|
||||
sendResetPasswordMail,
|
||||
} from '@src/emails/sendEmail'
|
||||
|
||||
const sendSignupMail = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { inviteCode } = args
|
||||
const { inviteCode, locale } = args
|
||||
const response = await resolve(root, args, context, resolveInfo)
|
||||
const { email, nonce } = response
|
||||
if (nonce) {
|
||||
// emails that already exist do not have a nonce
|
||||
if (inviteCode) {
|
||||
await sendMail(signupTemplate({ email, variables: { nonce, inviteCode } }))
|
||||
} else {
|
||||
await sendMail(signupTemplate({ email, variables: { nonce } }))
|
||||
}
|
||||
await sendRegistrationMail({ email, nonce, locale, inviteCode })
|
||||
}
|
||||
delete response.nonce
|
||||
return response
|
||||
}
|
||||
|
||||
const sendPasswordResetMail = async (resolve, root, args, context, resolveInfo) => {
|
||||
const { email } = args
|
||||
const { email, locale } = args
|
||||
const { email: userFound, nonce, name } = await resolve(root, args, context, resolveInfo)
|
||||
const template = userFound ? resetPasswordTemplate : wrongAccountTemplate
|
||||
await sendMail(template({ email, variables: { nonce, name } }))
|
||||
if (userFound) {
|
||||
await sendResetPasswordMail({ email, nonce, name, locale })
|
||||
} else {
|
||||
// this is an antifeature allowing unauthenticated users to spam any email with wrong-email notifications
|
||||
// await sendWrongEmail({ email, locale })
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const sendEmailVerificationMail = async (resolve, root, args, context, resolveInfo) => {
|
||||
const response = await resolve(root, args, context, resolveInfo)
|
||||
const { email, nonce, name } = response
|
||||
const { email, nonce, name, locale } = response
|
||||
if (nonce) {
|
||||
await sendMail(emailVerificationTemplate({ email, variables: { nonce, name } }))
|
||||
await sendEmailVerification({ email, nonce, name, locale })
|
||||
}
|
||||
delete response.nonce
|
||||
return response
|
||||
|
||||
@ -177,8 +177,8 @@ describe('authorization', () => {
|
||||
|
||||
describe('access Signup', () => {
|
||||
const signupMutation = gql`
|
||||
mutation ($email: String!, $inviteCode: String) {
|
||||
Signup(email: $email, inviteCode: $inviteCode) {
|
||||
mutation ($email: String!, $locale: String!, $inviteCode: String) {
|
||||
Signup(email: $email, locale: $locale, inviteCode: $inviteCode) {
|
||||
email
|
||||
}
|
||||
}
|
||||
@ -189,6 +189,7 @@ describe('authorization', () => {
|
||||
variables = {
|
||||
email: 'some@email.org',
|
||||
inviteCode: 'ABCDEF',
|
||||
locale: 'de',
|
||||
}
|
||||
CONFIG.INVITE_REGISTRATION = false
|
||||
CONFIG.PUBLIC_REGISTRATION = false
|
||||
@ -231,6 +232,7 @@ describe('authorization', () => {
|
||||
variables = {
|
||||
email: 'some@email.org',
|
||||
inviteCode: 'ABCDEF',
|
||||
locale: 'de',
|
||||
}
|
||||
CONFIG.INVITE_REGISTRATION = false
|
||||
CONFIG.PUBLIC_REGISTRATION = true
|
||||
@ -269,6 +271,7 @@ describe('authorization', () => {
|
||||
variables = {
|
||||
email: 'some@email.org',
|
||||
inviteCode: 'ABCDEF',
|
||||
locale: 'de',
|
||||
}
|
||||
authenticatedUser = null
|
||||
})
|
||||
@ -288,6 +291,7 @@ describe('authorization', () => {
|
||||
variables = {
|
||||
email: 'some@email.org',
|
||||
inviteCode: 'no valid invite code',
|
||||
locale: 'de',
|
||||
}
|
||||
authenticatedUser = null
|
||||
})
|
||||
|
||||
@ -59,7 +59,12 @@ describe('Request', () => {
|
||||
})
|
||||
|
||||
it('delivers email to backend', () => {
|
||||
const expected = expect.objectContaining({ variables: { email: 'mail@example.org' } })
|
||||
const expected = expect.objectContaining({
|
||||
variables: {
|
||||
email: 'mail@example.org',
|
||||
locale: 'en',
|
||||
},
|
||||
})
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
|
||||
})
|
||||
|
||||
@ -92,7 +97,12 @@ describe('Request', () => {
|
||||
})
|
||||
|
||||
it('normalizes email to lower case letters', () => {
|
||||
const expected = expect.objectContaining({ variables: { email: 'mail@gmail.com' } })
|
||||
const expected = expect.objectContaining({
|
||||
variables: {
|
||||
email: 'mail@gmail.com',
|
||||
locale: 'en',
|
||||
},
|
||||
})
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
|
||||
})
|
||||
})
|
||||
|
||||
@ -85,13 +85,13 @@ export default {
|
||||
},
|
||||
async handleSubmit() {
|
||||
const mutation = gql`
|
||||
mutation ($email: String!) {
|
||||
requestPasswordReset(email: $email)
|
||||
mutation ($email: String!, $locale: String!) {
|
||||
requestPasswordReset(email: $email, locale: $locale)
|
||||
}
|
||||
`
|
||||
try {
|
||||
const { email } = this
|
||||
await this.$apollo.mutate({ mutation, variables: { email } })
|
||||
await this.$apollo.mutate({ mutation, variables: { email, locale: this.$i18n.locale() } })
|
||||
this.submitted = true
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
@ -36,8 +36,8 @@ import normalizeEmail from '~/components/utils/NormalizeEmail'
|
||||
import translateErrorMessage from '~/components/utils/TranslateErrorMessage'
|
||||
|
||||
export const SignupMutation = gql`
|
||||
mutation ($email: String!, $inviteCode: String) {
|
||||
Signup(email: $email, inviteCode: $inviteCode) {
|
||||
mutation ($email: String!, $locale: String!, $inviteCode: String) {
|
||||
Signup(email: $email, locale: $locale, inviteCode: $inviteCode) {
|
||||
email
|
||||
}
|
||||
}
|
||||
@ -140,7 +140,7 @@ export default {
|
||||
async onNextClick() {
|
||||
const { email } = this.formData
|
||||
const { inviteCode = null } = this.sliderData.collectedInputData
|
||||
const variables = { email, inviteCode }
|
||||
const variables = { email, inviteCode, locale: this.$i18n.locale() }
|
||||
|
||||
if (this.sliderData.collectedInputData.emailSend && !this.sendEmailAgain) {
|
||||
return true
|
||||
|
||||
@ -25,6 +25,9 @@ describe('Signup', () => {
|
||||
loading: false,
|
||||
mutate: jest.fn().mockResolvedValue({ data: { Signup: { email: 'mail@example.org' } } }),
|
||||
},
|
||||
$i18n: {
|
||||
locale: () => 'de',
|
||||
},
|
||||
}
|
||||
propsData = {}
|
||||
})
|
||||
@ -64,7 +67,7 @@ describe('Signup', () => {
|
||||
it('delivers email to backend', () => {
|
||||
const expected = expect.objectContaining({
|
||||
mutation: SignupMutation,
|
||||
variables: { email: 'mAIL@exAMPLE.org', inviteCode: null },
|
||||
variables: { email: 'mAIL@exAMPLE.org', locale: 'de', inviteCode: null },
|
||||
})
|
||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expected)
|
||||
})
|
||||
|
||||
@ -70,8 +70,8 @@ import { SweetalertIcon } from 'vue-sweetalert-icons'
|
||||
import translateErrorMessage from '~/components/utils/TranslateErrorMessage'
|
||||
|
||||
export const SignupMutation = gql`
|
||||
mutation ($email: String!, $inviteCode: String) {
|
||||
Signup(email: $email, inviteCode: $inviteCode) {
|
||||
mutation ($email: String!, $locale: String!, $inviteCode: String) {
|
||||
Signup(email: $email, locale: $locale, inviteCode: $inviteCode) {
|
||||
email
|
||||
}
|
||||
}
|
||||
@ -121,7 +121,7 @@ export default {
|
||||
try {
|
||||
const response = await this.$apollo.mutate({
|
||||
mutation: SignupMutation,
|
||||
variables: { email, inviteCode: null },
|
||||
variables: { email, locale: this.$i18n.locale(), inviteCode: null },
|
||||
})
|
||||
this.data = response.data
|
||||
setTimeout(() => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user