diff --git a/api/src/lib/email/send.test.ts b/api/src/lib/email/send.test.ts
index c76e94c..27ab67a 100644
--- a/api/src/lib/email/send.test.ts
+++ b/api/src/lib/email/send.test.ts
@@ -27,12 +27,15 @@ describe('mailer', () => {
"handler": "nodemailer",
"handlerOptions": undefined,
"headers": {},
- "htmlContent": "Leave this email here",
+ "htmlContent": null,
"renderer": "plain",
"rendererOptions": {},
"replyTo": undefined,
"subject": "Don't delete me",
- "textContent": "Leave this email here",
+ "textContent": "Leave this email here
+
+To unsubscribe from all Freevite emails forever, click here:
+https://example.com/unsubscribe?email=darlene%40fs0ciety.pizza&token=wgPFf2G9H7D9zKIEjop_AeZCED7pLZex619NqYasXwk",
"to": [
"darlene@fs0ciety.pizza",
],
diff --git a/api/src/lib/email/send.ts b/api/src/lib/email/send.ts
index 3259e39..dfe08c0 100644
--- a/api/src/lib/email/send.ts
+++ b/api/src/lib/email/send.ts
@@ -4,6 +4,7 @@ import { mailer } from 'src/lib/mailer'
import { logger } from '../logger'
import { Plain } from './plain'
+import { unsubscribeFooter } from './unsubscribe'
interface Params {
to: string | string[]
@@ -16,10 +17,13 @@ interface Params {
* @param params The email parameters
* @returns The result of the send operation
*/
-export async function sendEmail({ subject, text, ...p }: Params) {
+export async function sendEmail({ subject, text: _text, ...p }: Params) {
+ const firstRecipient = Array.isArray(p.to) ? p.to[0] : p.to
+ const to = Array.isArray(p.to) ? p.to : [p.to]
+
+ const text = _text.trim() + '\n\n' + unsubscribeFooter(firstRecipient)
const { name, email } = MAIL_SENDER
const from = `"${name}" <${email}>`
- const to = Array.isArray(p.to) ? p.to : [p.to]
logger.info({ from, to, subject, text }, 'Sending email')
return mailer.send(Plain({ text }), { subject, from, to })
}
diff --git a/api/src/lib/email/template/event.test.ts b/api/src/lib/email/template/event.test.ts
index d0c279b..b04e144 100644
--- a/api/src/lib/email/template/event.test.ts
+++ b/api/src/lib/email/template/event.test.ts
@@ -31,7 +31,7 @@ describe('with test handler', () => {
"handler": "nodemailer",
"handlerOptions": undefined,
"headers": {},
- "htmlContent": "Hello from Freevite! Click this link to manage your event details and make it public:
https://example.com/edit?token=SOME-EDIT-TOKEN
You must click the above link within 24 hours to confirm your email address.
Otherwise, we will automatically delete your event. Feel free to recreate it.
If you did not create this event, you can ignore this email and this event will be deleted.
If you need any help, just reply to this email. Thanks for using Freevite!",
+ "htmlContent": null,
"renderer": "plain",
"rendererOptions": {},
"replyTo": undefined,
@@ -45,7 +45,10 @@ Otherwise, we will automatically delete your event. Feel free to recreate it.
If you did not create this event, you can ignore this email and this event will be deleted.
-If you need any help, just reply to this email. Thanks for using Freevite!",
+If you need any help, just reply to this email. Thanks for using Freevite!
+
+To unsubscribe from all Freevite emails forever, click here:
+https://example.com/unsubscribe?email=emma%40example.com&token=oyTyug8SP9wjzqGkAI7AKThdFp4hQs0bBLAPfq1SbRs",
"to": [
"emma@example.com",
],
diff --git a/api/src/lib/email/template/reminder.test.ts b/api/src/lib/email/template/reminder.test.ts
index 4e5cd7e..bbd8a6b 100644
--- a/api/src/lib/email/template/reminder.test.ts
+++ b/api/src/lib/email/template/reminder.test.ts
@@ -37,7 +37,7 @@ describe('with test handler', () => {
"handler": "nodemailer",
"handlerOptions": undefined,
"headers": {},
- "htmlContent": "Hello from Freevite! You asked for a reminder about this event when you RSVPed:
Emma's Holiday Party
Starts at: Sun Dec 25, 2022, 7:00 AM EST (in a day))
Ends at: Sun Dec 25, 2022, 10:00 AM EST (3 hours long)
View the event here:
https://example.com/events/emmas-holiday-party
Thanks for using Freevite!",
+ "htmlContent": null,
"renderer": "plain",
"rendererOptions": {},
"replyTo": undefined,
@@ -51,7 +51,10 @@ Ends at: Sun Dec 25, 2022, 10:00 AM EST (3 hours long)
View the event here:
https://example.com/events/emmas-holiday-party
-Thanks for using Freevite!",
+Thanks for using Freevite!
+
+To unsubscribe from all Freevite emails forever, click here:
+https://example.com/unsubscribe?email=holmes%40example.com&token=xZPATAWTt2b9dRKrUFJ9yE982ThnnvUg6APxtN_gr8s",
"to": [
"holmes@example.com",
],
diff --git a/api/src/lib/email/template/response.test.ts b/api/src/lib/email/template/response.test.ts
index 2f66c6e..8762a18 100644
--- a/api/src/lib/email/template/response.test.ts
+++ b/api/src/lib/email/template/response.test.ts
@@ -37,7 +37,7 @@ describe('with test handler', () => {
"handler": "nodemailer",
"handlerOptions": undefined,
"headers": {},
- "htmlContent": "Hello from Freevite!
Click here to confirm you're attending Emma's Holiday Party:
https://example.com/rsvp?token=SOME-EDIT-TOKEN
Once you do, we'll confirm your RSVP and notify the event organizer.
To change your response or delete your RSVP, click the link above.
If you did not RSVP to this event, you can ignore this email.",
+ "htmlContent": null,
"renderer": "plain",
"rendererOptions": {},
"replyTo": undefined,
@@ -50,7 +50,10 @@ Once you do, we'll confirm your RSVP and notify the event organizer.
To change your response or delete your RSVP, click the link above.
-If you did not RSVP to this event, you can ignore this email.",
+If you did not RSVP to this event, you can ignore this email.
+
+To unsubscribe from all Freevite emails forever, click here:
+https://example.com/unsubscribe?email=holmes%40example.com&token=xZPATAWTt2b9dRKrUFJ9yE982ThnnvUg6APxtN_gr8s",
"to": [
"holmes@example.com",
],
@@ -83,7 +86,7 @@ If you did not RSVP to this event, you can ignore this email.",
"handler": "nodemailer",
"handlerOptions": undefined,
"headers": {},
- "htmlContent": "Hello from Freevite! Sherlock Holmes has confirmed they are attending Emma's Holiday Party:
Name: Sherlock Holmes
Guests: 2
Comment: Looking forward to it!
To view all responses and manage your event, click here:
https://example.com/edit?token=SOME-EDIT-TOKEN
Thanks for using Freevite!",
+ "htmlContent": null,
"renderer": "plain",
"rendererOptions": {},
"replyTo": undefined,
@@ -97,7 +100,10 @@ Comment: Looking forward to it!
To view all responses and manage your event, click here:
https://example.com/edit?token=SOME-EDIT-TOKEN
-Thanks for using Freevite!",
+Thanks for using Freevite!
+
+To unsubscribe from all Freevite emails forever, click here:
+https://example.com/unsubscribe?email=emma%40example.com&token=oyTyug8SP9wjzqGkAI7AKThdFp4hQs0bBLAPfq1SbRs",
"to": [
"emma@example.com",
],
@@ -130,7 +136,7 @@ Thanks for using Freevite!",
"handler": "nodemailer",
"handlerOptions": undefined,
"headers": {},
- "htmlContent": "Hello from Freevite! Sherlock Holmes has canceled their RSVP to Emma's Holiday Party.
Here are the details of the RSVP before it was canceled:
Name: Sherlock Holmes
Guests: 2
Comment: Looking forward to it!
To view all RSVPs and manage your event, click here:
https://example.com/edit?token=SOME-EDIT-TOKEN
Thanks for using Freevite!",
+ "htmlContent": null,
"renderer": "plain",
"rendererOptions": {},
"replyTo": undefined,
@@ -145,7 +151,10 @@ Comment: Looking forward to it!
To view all RSVPs and manage your event, click here:
https://example.com/edit?token=SOME-EDIT-TOKEN
-Thanks for using Freevite!",
+Thanks for using Freevite!
+
+To unsubscribe from all Freevite emails forever, click here:
+https://example.com/unsubscribe?email=emma%40example.com&token=oyTyug8SP9wjzqGkAI7AKThdFp4hQs0bBLAPfq1SbRs",
"to": [
"emma@example.com",
],
diff --git a/api/src/lib/mailer.ts b/api/src/lib/mailer.ts
index 9fc2fa6..3eedddd 100644
--- a/api/src/lib/mailer.ts
+++ b/api/src/lib/mailer.ts
@@ -1,5 +1,4 @@
import { render as reactEmailRender } from '@react-email/render'
-import escapeHTML from 'escape-html'
import { Mailer } from '@redwoodjs/mailer-core'
import { AbstractMailRenderer } from '@redwoodjs/mailer-core'
@@ -20,7 +19,7 @@ class PlainEmailRenderer extends AbstractMailRenderer {
_utilities?: MailUtilities
): MailRenderedContent {
const text = template.props.children
- const html = escapeHTML(text).replace(/\n/g, '
')
+ const html = null
return { text, html }
}