feat(backend): improve e-mail deliverability with sender name (#8888)

* Avoid early html encoding for the remaining '='

* Make 'EMAIL_DEFAULT_SENDER' required env

* Implement sender and recipient name on send e-mails nodemailer conform

* Fix e-mail snapshots
This commit is contained in:
Wolfgang Huß 2025-09-13 13:39:39 +02:00 committed by GitHub
parent ebb8ef4f0e
commit d9a7c1adc5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 305 additions and 94 deletions

View File

@ -93,6 +93,8 @@ const redis = {
} }
const required = { const required = {
EMAIL_DEFAULT_SENDER: env.EMAIL_DEFAULT_SENDER,
AWS_ACCESS_KEY_ID: env.AWS_ACCESS_KEY_ID, AWS_ACCESS_KEY_ID: env.AWS_ACCESS_KEY_ID,
AWS_SECRET_ACCESS_KEY: env.AWS_SECRET_ACCESS_KEY, AWS_SECRET_ACCESS_KEY: env.AWS_SECRET_ACCESS_KEY,
AWS_ENDPOINT: env.AWS_ENDPOINT, AWS_ENDPOINT: env.AWS_ENDPOINT,
@ -122,7 +124,6 @@ function assertRequiredConfig(
assertRequiredConfig(required) assertRequiredConfig(required)
const options = { const options = {
EMAIL_DEFAULT_SENDER: env.EMAIL_DEFAULT_SENDER,
SUPPORT_EMAIL: env.SUPPORT_EMAIL, SUPPORT_EMAIL: env.SUPPORT_EMAIL,
SUPPORT_URL: emails.SUPPORT_LINK, SUPPORT_URL: emails.SUPPORT_LINK,
APPLICATION_NAME: metadata.APPLICATION_NAME, APPLICATION_NAME: metadata.APPLICATION_NAME,

View File

@ -3,7 +3,10 @@
exports[`sendChatMessageMail English chat_message template 1`] = ` exports[`sendChatMessageMail English chat_message template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -132,14 +135,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "chatReceiver",
},
} }
`; `;
exports[`sendChatMessageMail German chat_message template 1`] = ` exports[`sendChatMessageMail German chat_message template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -268,6 +277,9 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "chatReceiver",
},
} }
`; `;

View File

@ -3,7 +3,10 @@
exports[`sendEmailVerification English renders correctly 1`] = ` exports[`sendEmailVerification English renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -135,14 +138,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "User",
},
} }
`; `;
exports[`sendEmailVerification German renders correctly 1`] = ` exports[`sendEmailVerification German renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -274,6 +283,9 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "User",
},
} }
`; `;

View File

@ -3,7 +3,10 @@
exports[`sendNotificationMail English changed_group_member_role template 1`] = ` exports[`sendNotificationMail English changed_group_member_role template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -131,14 +134,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English commented_on_post template 1`] = ` exports[`sendNotificationMail English commented_on_post template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -268,14 +277,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English followed_user_posted template 1`] = ` exports[`sendNotificationMail English followed_user_posted template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -405,14 +420,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English mentioned_in_comment template 1`] = ` exports[`sendNotificationMail English mentioned_in_comment template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -542,14 +563,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English mentioned_in_post template 1`] = ` exports[`sendNotificationMail English mentioned_in_post template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -678,14 +705,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English post_in_group template 1`] = ` exports[`sendNotificationMail English post_in_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -813,14 +846,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English removed_user_from_group template 1`] = ` exports[`sendNotificationMail English removed_user_from_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -945,14 +984,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English user_joined_group template 1`] = ` exports[`sendNotificationMail English user_joined_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -1081,14 +1126,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail English user_left_group template 1`] = ` exports[`sendNotificationMail English user_left_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -1217,14 +1268,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German changed_group_member_role template 1`] = ` exports[`sendNotificationMail German changed_group_member_role template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -1352,14 +1409,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German commented_on_post template 1`] = ` exports[`sendNotificationMail German commented_on_post template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -1489,14 +1552,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German followed_user_posted template 1`] = ` exports[`sendNotificationMail German followed_user_posted template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -1626,14 +1695,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German mentioned_in_comment template 1`] = ` exports[`sendNotificationMail German mentioned_in_comment template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -1763,14 +1838,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German mentioned_in_post template 1`] = ` exports[`sendNotificationMail German mentioned_in_post template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -1900,14 +1981,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German post_in_group template 1`] = ` exports[`sendNotificationMail German post_in_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -2035,14 +2122,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German removed_user_from_group template 1`] = ` exports[`sendNotificationMail German removed_user_from_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -2167,14 +2260,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German user_joined_group template 1`] = ` exports[`sendNotificationMail German user_joined_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -2303,14 +2402,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendNotificationMail German user_left_group template 1`] = ` exports[`sendNotificationMail German user_left_group template 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -2439,6 +2544,9 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;

View File

@ -3,7 +3,10 @@
exports[`sendRegistrationMail with invite code English renders correctly 1`] = ` exports[`sendRegistrationMail with invite code English renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -94,7 +97,7 @@ footer {
<h2>Welcome to ocelot.social!</h2> <h2>Welcome to ocelot.social!</h2>
<div class="wrapper"> <div class="wrapper">
<div class="content"></div> <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&amp;nonce=123456&amp;inviteCode=welcome&amp;method=invite-code">Confirm your e-mail address</a> <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=moderator%40example.org&amp;nonce=123456&amp;inviteCode=welcome&amp;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>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>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>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.
@ -122,7 +125,7 @@ just one tiny step missing before we can start shaping the world together …
Please confirm your e-mail address by clicking the button below: Please confirm your e-mail address by clicking the button below:
Confirm your e-mail address Confirm your e-mail address
[http://webapp:3000/registration?email=user%40example.org&nonce=123456&inviteCode=welcome&method=invite-code] [http://webapp:3000/registration?email=moderator%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 If the above button doesn't work, you can also copy the following code into your
browser window: 123456 browser window: 123456
@ -144,14 +147,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "moderator@example.org",
"name": "Bob &"?@\\ Baumeister",
},
} }
`; `;
exports[`sendRegistrationMail with invite code German renders correctly 1`] = ` exports[`sendRegistrationMail with invite code German renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -242,7 +251,7 @@ footer {
<h2>Willkommen bei ocelot.social!</h2> <h2>Willkommen bei ocelot.social!</h2>
<div class="wrapper"> <div class="wrapper">
<div class="content"></div> <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&amp;nonce=123456&amp;inviteCode=welcome&amp;method=invite-code">Bestätige deine E-Mail Adresse</a> <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=moderator%40example.org&amp;nonce=123456&amp;inviteCode=welcome&amp;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>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>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>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.
@ -270,7 +279,7 @@ fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können
… Bitte bestätige deine E-Mail Adresse: … Bitte bestätige deine E-Mail Adresse:
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] [http://webapp:3000/registration?email=moderator%40example.org&nonce=123456&inviteCode=welcome&method=invite-code]
Sollte der Button für dich nicht funktionieren, kannst du auch folgenden Code in Sollte der Button für dich nicht funktionieren, kannst du auch folgenden Code in
dein Browserfenster kopieren: 123456 dein Browserfenster kopieren: 123456
@ -293,14 +302,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "moderator@example.org",
"name": "Bob &"?@\\ Baumeister",
},
} }
`; `;
exports[`sendRegistrationMail without invite code English renders correctly 1`] = ` exports[`sendRegistrationMail without invite code English renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -391,7 +406,7 @@ footer {
<h2>Welcome to ocelot.social!</h2> <h2>Welcome to ocelot.social!</h2>
<div class="wrapper"> <div class="wrapper">
<div class="content"></div> <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&amp;nonce=123456&amp;method=invite-mail">Confirm your e-mail address</a> <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=moderator%40example.org&amp;nonce=123456&amp;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>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>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>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.
@ -419,7 +434,7 @@ just one tiny step missing before we can start shaping the world together …
Please confirm your e-mail address by clicking the button below: Please confirm your e-mail address by clicking the button below:
Confirm your e-mail address Confirm your e-mail address
[http://webapp:3000/registration?email=user%40example.org&nonce=123456&method=invite-mail] [http://webapp:3000/registration?email=moderator%40example.org&nonce=123456&method=invite-mail]
If the above button doesn't work, you can also copy the following code into your If the above button doesn't work, you can also copy the following code into your
browser window: 123456 browser window: 123456
@ -441,14 +456,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "moderator@example.org",
"name": "Bob &"?@\\ Baumeister",
},
} }
`; `;
exports[`sendRegistrationMail without invite code German renders correctly 1`] = ` exports[`sendRegistrationMail without invite code German renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -539,7 +560,7 @@ footer {
<h2>Willkommen bei ocelot.social!</h2> <h2>Willkommen bei ocelot.social!</h2>
<div class="wrapper"> <div class="wrapper">
<div class="content"></div> <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&amp;nonce=123456&amp;method=invite-mail">Bestätige deine E-Mail Adresse</a> <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=moderator%40example.org&amp;nonce=123456&amp;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>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>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>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.
@ -567,7 +588,7 @@ fehlt nur noch eine Kleinigkeit, bevor wir gemeinsam die Welt verbessern können
… Bitte bestätige deine E-Mail Adresse: … Bitte bestätige deine E-Mail Adresse:
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] [http://webapp:3000/registration?email=moderator%40example.org&nonce=123456&method=invite-mail]
Sollte der Button für dich nicht funktionieren, kannst du auch folgenden Code in Sollte der Button für dich nicht funktionieren, kannst du auch folgenden Code in
dein Browserfenster kopieren: 123456 dein Browserfenster kopieren: 123456
@ -590,6 +611,9 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "moderator@example.org",
"name": "Bob &"?@\\ Baumeister",
},
} }
`; `;

View File

@ -3,7 +3,10 @@
exports[`sendResetPasswordMail English renders correctly 1`] = ` exports[`sendResetPasswordMail English renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -134,14 +137,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendResetPasswordMail German renders correctly 1`] = ` exports[`sendResetPasswordMail German renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -273,6 +282,9 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;

View File

@ -3,7 +3,10 @@
exports[`sendWrongEmail English renders correctly 1`] = ` exports[`sendWrongEmail English renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -132,14 +135,20 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "moderator@example.org",
"name": "Bob &"?@\\ Baumeister",
},
} }
`; `;
exports[`sendWrongEmail German renders correctly 1`] = ` exports[`sendWrongEmail German renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -268,6 +277,9 @@ devops@ocelot.social [devops@ocelot.social]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "moderator@example.org",
"name": "Bob &"?@\\ Baumeister",
},
} }
`; `;

View File

@ -3,7 +3,10 @@
exports[`sendResetPasswordMail with support English renders correctly 1`] = ` exports[`sendResetPasswordMail with support English renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -134,14 +137,20 @@ support@example.org [support@example.org]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendResetPasswordMail with support German renders correctly 1`] = ` exports[`sendResetPasswordMail with support German renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -273,14 +282,20 @@ support@example.org [support@example.org]
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendResetPasswordMail without support English renders correctly 1`] = ` exports[`sendResetPasswordMail without support English renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -405,14 +420,20 @@ See you soon on ocelot.social [https://ocelot.social]!
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;
exports[`sendResetPasswordMail without support German renders correctly 1`] = ` exports[`sendResetPasswordMail without support German renders correctly 1`] = `
{ {
"attachments": [], "attachments": [],
"from": "ocelot.social <devops@ocelot.social>", "from": {
"address": "devops@ocelot.social",
"name": "ocelot.social",
},
"html": "<!DOCTYPE html> "html": "<!DOCTYPE html>
<html lang="de"> <html lang="de">
<head> <head>
@ -538,6 +559,9 @@ Bis bald bei ocelot.social [https://ocelot.social]!
ocelot.social Community [https://ocelot.social]", ocelot.social Community [https://ocelot.social]",
"to": "user@example.org", "to": {
"address": "user@example.org",
"name": "Jenny Rostock",
},
} }
`; `;

View File

@ -29,7 +29,7 @@ export const defaultParams = {
renderSettingsUrl: true, renderSettingsUrl: true,
} }
const from = `${CONFIG.APPLICATION_NAME} <${CONFIG.EMAIL_DEFAULT_SENDER}>` const from = { name: CONFIG.APPLICATION_NAME, address: CONFIG.EMAIL_DEFAULT_SENDER }
const transport = createTransport(nodemailerTransportOptions) const transport = createTransport(nodemailerTransportOptions)
@ -74,8 +74,8 @@ interface OriginalMessage {
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export const sendNotificationMail = async (notification: any): Promise<OriginalMessage> => { export const sendNotificationMail = async (notification: any): Promise<OriginalMessage> => {
const locale = notification?.to?.locale const locale = notification?.to?.locale
const to = notification?.email
const name = notification?.to?.name const name = notification?.to?.name
const to = { name, address: notification?.email }
const template = notification?.reason const template = notification?.reason
try { try {
@ -165,7 +165,7 @@ export const sendChatMessageMail = async (
data: ChatMessageEmailInput, data: ChatMessageEmailInput,
): Promise<OriginalMessage> => { ): Promise<OriginalMessage> => {
const { senderUser, recipientUser } = data const { senderUser, recipientUser } = data
const to = data.email const to = { name: recipientUser.name, address: data.email }
try { try {
const { originalMessage } = await email.send({ const { originalMessage } = await email.send({
template: path.join(__dirname, 'templates', 'chat_message'), template: path.join(__dirname, 'templates', 'chat_message'),
@ -188,6 +188,7 @@ export const sendChatMessageMail = async (
} }
interface VerifyMailInput { interface VerifyMailInput {
name: string
email: string email: string
nonce: string nonce: string
locale: string locale: string
@ -200,10 +201,10 @@ interface RegistrationMailInput extends VerifyMailInput {
export const sendRegistrationMail = async ( export const sendRegistrationMail = async (
data: RegistrationMailInput, data: RegistrationMailInput,
): Promise<OriginalMessage> => { ): Promise<OriginalMessage> => {
const { nonce, locale, inviteCode } = data const { name, nonce, locale, inviteCode } = data
const to = data.email const to = { name, address: data.email }
const actionUrl = new URL('/registration', CONFIG.CLIENT_URI) const actionUrl = new URL('/registration', CONFIG.CLIENT_URI)
actionUrl.searchParams.set('email', to) actionUrl.searchParams.set('email', to.address)
actionUrl.searchParams.set('nonce', nonce) actionUrl.searchParams.set('nonce', nonce)
if (inviteCode) { if (inviteCode) {
actionUrl.searchParams.set('inviteCode', inviteCode) actionUrl.searchParams.set('inviteCode', inviteCode)
@ -240,9 +241,9 @@ export const sendEmailVerification = async (
data: EmailVerificationInput, data: EmailVerificationInput,
): Promise<OriginalMessage> => { ): Promise<OriginalMessage> => {
const { nonce, locale, name } = data const { nonce, locale, name } = data
const to = data.email const to = { name, address: data.email }
const actionUrl = new URL('/settings/my-email-address/verify', CONFIG.CLIENT_URI) const actionUrl = new URL('/settings/my-email-address/verify', CONFIG.CLIENT_URI)
actionUrl.searchParams.set('email', to) actionUrl.searchParams.set('email', to.address)
actionUrl.searchParams.set('nonce', nonce) actionUrl.searchParams.set('nonce', nonce)
try { try {
@ -270,9 +271,9 @@ export const sendResetPasswordMail = async (
data: EmailVerificationInput, data: EmailVerificationInput,
): Promise<OriginalMessage> => { ): Promise<OriginalMessage> => {
const { nonce, locale, name } = data const { nonce, locale, name } = data
const to = data.email const to = { name, address: data.email }
const actionUrl = new URL('/password-reset/change-password', CONFIG.CLIENT_URI) const actionUrl = new URL('/password-reset/change-password', CONFIG.CLIENT_URI)
actionUrl.searchParams.set('email', to) actionUrl.searchParams.set('email', to.address)
actionUrl.searchParams.set('nonce', nonce) actionUrl.searchParams.set('nonce', nonce)
try { try {
const { originalMessage } = await email.send({ const { originalMessage } = await email.send({
@ -296,11 +297,12 @@ export const sendResetPasswordMail = async (
} }
export const sendWrongEmail = async (data: { export const sendWrongEmail = async (data: {
name: string
locale: string locale: string
email: string email: string
}): Promise<OriginalMessage> => { }): Promise<OriginalMessage> => {
const { locale } = data const { locale, name } = data
const to = data.email const to = { name, address: data.email }
const actionUrl = new URL('/password-reset/request', CONFIG.CLIENT_URI) const actionUrl = new URL('/password-reset/request', CONFIG.CLIENT_URI)
try { try {
const { originalMessage } = await email.send({ const { originalMessage } = await email.send({

View File

@ -7,12 +7,14 @@ import { sendRegistrationMail } from './sendEmail'
describe('sendRegistrationMail', () => { describe('sendRegistrationMail', () => {
const data: { const data: {
name: string
email: string email: string
nonce: string nonce: string
locale: string locale: string
inviteCode?: string inviteCode?: string
} = { } = {
email: 'user@example.org', name: 'Bob &"?@\\ Baumeister',
email: 'moderator@example.org',
nonce: '123456', nonce: '123456',
locale: 'en', locale: 'en',
inviteCode: 'welcome', inviteCode: 'welcome',

View File

@ -7,10 +7,12 @@ import { sendWrongEmail } from './sendEmail'
describe('sendWrongEmail', () => { describe('sendWrongEmail', () => {
const data: { const data: {
name: string
email: string email: string
locale: string locale: string
} = { } = {
email: 'user@example.org', name: 'Bob &"?@\\ Baumeister',
email: 'moderator@example.org',
locale: 'en', locale: 'en',
} }

View File

@ -1 +1 @@
= `${APPLICATION_NAME} ${t('notification')}: ${t('subjects.removedUserFromGroup')}` != `${APPLICATION_NAME} ${t('notification')}: ${t('subjects.removedUserFromGroup')}`

View File

@ -11,10 +11,10 @@ import {
const sendSignupMail = async (resolve, root, args, context, resolveInfo) => { const sendSignupMail = async (resolve, root, args, context, resolveInfo) => {
const { inviteCode, locale } = args const { inviteCode, locale } = args
const response = await resolve(root, args, context, resolveInfo) const response = await resolve(root, args, context, resolveInfo)
const { email, nonce } = response const { name, email, nonce } = response
if (nonce) { if (nonce) {
// emails that already exist do not have a nonce // emails that already exist do not have a nonce
await sendRegistrationMail({ email, nonce, locale, inviteCode }) await sendRegistrationMail({ name, email, nonce, locale, inviteCode })
} }
delete response.nonce delete response.nonce
return response return response