Skip to content

Commit

Permalink
Add plaintext version of Plus expiration email
Browse files Browse the repository at this point in the history
  • Loading branch information
Vinnl committed Jan 29, 2025
1 parent 4ecdbab commit ec9fb04
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 8 deletions.
7 changes: 7 additions & 0 deletions locales-pending/emails-all.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
email-footer-reason-subscriber = You’re receiving this automated email as a subscriber of { -brand-mozilla-monitor }. If you received it in error, no action is required. For more information, please visit <support-link>{ -brand-mozilla } Support</support-link>.
email-footer-reason-subscriber-one-time = You’ve received this one-time automated email because you are subscribed to { -brand-monitor-plus }. You won’t receive any further emails like this. For more information, please visit <support-link>{ -brand-mozilla } Support</support-link>.
# Variables:
# $support_link (string) - The URL the user can visit for support, e.g. "https://support.mozilla.org"
email-footer-support-content-plain = Visit our Support Center for help: { $support_link }
# Variables:
# $hibp_link (string) - URL to Have I Been Pwned, e.g. "https://haveibeenpwned.com".
email-footer-source-hibp-plain = Breach data provided by { -brand-HIBP }: { $hibp_link }
## Monthly overview email

email-monthly-free-subject = Your monthly { -brand-monitor } report
Expand Down
7 changes: 7 additions & 0 deletions locales-pending/emails-plus.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ email-plus-expiration-body-part1 = Your { -brand-monitor-plus } subscription end
# Variables:
# $end_date (string) - The localised date the subscription will expire, e.g. "April 2, 1337".
email-plus-expiration-body-part2-styled = To keep your access, sign in and <renewal-link>renew your subscription</renewal-link> before <b>{ $end_date }</b>. If you need help, <support-link>contact our Support team</support-link>.
# Variables:
# $end_date (string) - The localised date the subscription will expire, e.g. "April 2, 1337".
# $renewal_link (string) - The URL the user can visit to renew their subscription, e.g. "https://monitor.mozilla.com/user/plus-expiration/"
email-plus-expiration-body-part2-plain = To keep your access, sign in and renew your subscription before { $end_date }: { $renewal_link }.
# Variables:
# $support_link (string) - The URL the user can visit to contact support, e.g. "https://support.mozilla.org/questions/new/monitor/form"
email-plus-expiration-body-part3-plain = If you need help, contact our Support team: { $support_link }.
# Variables:
# $end_date (string) - The localised date the subscription will expire, e.g. "April 2, 1337".
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ import { isEligibleForPremium } from "../../../../../functions/universal/premium
import { MonthlyActivityFreeEmail } from "../../../../../../emails/templates/monthlyActivityFree/MonthlyActivityFreeEmail";
import { getMonthlyActivityFreeUnsubscribeLink } from "../../../../../../app/functions/cronjobs/unsubscribeLinks";
import { getScanResultsWithBroker } from "../../../../../../db/tables/onerep_scans";
import { UpcomingExpirationEmail } from "../../../../../../emails/templates/upcomingExpiration/UpcomingExpirationEmail";
import {
getUnstyledUpcomingExpirationEmail,
UpcomingExpirationEmail,
} from "../../../../../../emails/templates/upcomingExpiration/UpcomingExpirationEmail";

async function getAdminSubscriber(): Promise<SubscriberRow | null> {
const session = await getServerSession();
Expand All @@ -66,6 +69,7 @@ async function send(
emailAddress: string,
subject: string,
template: ReactNode,
plaintextVersion?: string,
) {
const subscriber = await getAdminSubscriber();
if (!subscriber) {
Expand All @@ -85,6 +89,7 @@ async function send(
emailAddress,
"Test email: " + subject,
await renderEmail(template),
plaintextVersion,
);
}

Expand Down Expand Up @@ -303,5 +308,10 @@ export async function triggerPlusExpirationEmail(emailAddress: string) {
expirationDate={new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)}
l10n={l10n}
/>,
getUnstyledUpcomingExpirationEmail({
subscriber: sanitizeSubscriberRow(subscriber),
expirationDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000),
l10n: l10n,
}),
);
}
33 changes: 33 additions & 0 deletions src/emails/components/EmailFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -230,3 +230,36 @@ export const RedesignedEmailFooter = (props: Props) => {
</mj-wrapper>
);
};

export const getUnstyledRedesignedEmailFooter = (props: Props): string => {
const l10n = props.l10n;
const supportLinkUrlObject = new URL(CONST_URL_SUMO_MONITOR_SUPPORT_CENTER);
supportLinkUrlObject.searchParams.set("utm_medium", "product-email");
supportLinkUrlObject.searchParams.set("utm_source", "monitor-product");
supportLinkUrlObject.searchParams.set("utm_campaign", props.utm_campaign);
supportLinkUrlObject.searchParams.set("utm_content", "support-center");

const separator = "-".repeat(30);

return `
${separator}
${l10n.getString("email-footer-support-heading")}
${l10n.getString("email-footer-support-content-plain", { support_link: supportLinkUrlObject.href })}
${separator}
Mozilla Corporation
149 New Montgomery St, 4th Floor, San Francisco, CA 94105
${l10n.getString("email-footer-trigger-transactional")}
${l10n.getString("email-footer-source-hibp-plain", { hibp_link: "https://haveibeenpwned.com" })}
${l10n.getString("terms-of-service")}:
${CONST_URL_TERMS}
${l10n.getString("email-footer-meta-privacy-notice")}:
${CONST_URL_PRIVACY_POLICY}
`;
};
9 changes: 9 additions & 0 deletions src/emails/components/EmailHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,12 @@ export const EmailHeader = (props: Props) => {
</mj-section>
);
};

export const getUnstyledEmailHeader = (props: Props) => {
const l10n = props.l10n;

return `
${l10n.getString("public-nav-name")}
${"-".repeat(30)}
`;
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@

import { SanitizedSubscriberRow } from "../../../app/functions/server/sanitize";
import { ExtendedReactLocalization } from "../../../app/functions/l10n";
import { RedesignedEmailFooter } from "../../components/EmailFooter";
import { EmailHeader } from "../../components/EmailHeader";
import {
getUnstyledRedesignedEmailFooter,
RedesignedEmailFooter,
} from "../../components/EmailFooter";
import {
EmailHeader,
getUnstyledEmailHeader,
} from "../../components/EmailHeader";
import { HeaderStyles, MetaTags } from "../../components/HeaderStyles";
import { getLocale } from "../../../app/functions/universal/getLocale";

Expand Down Expand Up @@ -119,6 +125,36 @@ export const UpcomingExpirationEmail = (props: Props) => {
);
};

export const getUnstyledUpcomingExpirationEmail = (_props: Props): string => {
return "TODO";
export const getUnstyledUpcomingExpirationEmail = (props: Props): string => {
const l10n = props.l10n;
return `
${getUnstyledEmailHeader({ l10n: l10n, utm_campaign: utmCampaign })}
# ${l10n.getString("email-plus-expiration-heading")}
${l10n.getString("email-plus-expiration-body-part1", {
end_date: props.expirationDate.toLocaleDateString(getLocale(l10n), {
day: "numeric",
month: "long",
year: "numeric",
}),
})}
${l10n.getString("email-plus-expiration-body-part2-plain", {
end_date: props.expirationDate.toLocaleDateString(getLocale(l10n), {
day: "numeric",
month: "long",
year: "numeric",
}),
renewal_link: `${process.env.SERVER_URL}/user/plus-expiration/?utm_campaign=${utmCampaign}&utm_source=${utmSource}&utm_medium=${utmMedium}&utm_content=resubscribe-link-plain`,
})}
${l10n.getString("email-plus-expiration-body-part3-plain", {
support_link: `https://support.mozilla.org?utm_campaign=${utmCampaign}&utm_source=${utmSource}&utm_medium=${utmMedium}&utm_content=expiration-support-plain`,
})}
${l10n.getString("email-plus-expiration-signoff")}
${l10n.getString("email-plus-expiration-sender")}
${getUnstyledRedesignedEmailFooter({ l10n: l10n, utm_campaign: utmCampaign })}
`;
};
10 changes: 9 additions & 1 deletion src/scripts/cronjobs/churnDiscount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import { SubscriberChurnRow, SubscriberRow } from "knex/types/tables";
import { sanitizeSubscriberRow } from "../../app/functions/server/sanitize";
import { getCronjobL10n } from "../../app/functions/l10n/cronjobs";
import { renderEmail } from "../../emails/renderEmail";
import { UpcomingExpirationEmail } from "../../emails/templates/upcomingExpiration/UpcomingExpirationEmail";
import {
getUnstyledUpcomingExpirationEmail,
UpcomingExpirationEmail,
} from "../../emails/templates/upcomingExpiration/UpcomingExpirationEmail";
import { getFeatureFlagData } from "../../db/tables/featureFlags";

await run();
Expand Down Expand Up @@ -71,6 +74,11 @@ async function sendChurnDiscountEmail(
l10n={l10n}
/>,
),
getUnstyledUpcomingExpirationEmail({
subscriber: sanitizedSubscriber,
expirationDate: subscriber.current_period_end,
l10n: l10n,
}),
);

logger.info(`sent email to: ${subscriber.userid}`);
Expand Down
7 changes: 5 additions & 2 deletions src/utils/email.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

import { createTransport, Transporter } from "nodemailer";
import { createTransport, Transporter, SendMailOptions } from "nodemailer";
import crypto from "crypto";

import { SentMessageInfo } from "nodemailer/lib/smtp-transport/index.js";
Expand Down Expand Up @@ -47,22 +47,25 @@ export function closeEmailPool() {
* @param recipient
* @param subject
* @param html
* @param plaintext
*/
export async function sendEmail(
recipient: string,
subject: string,
html: string,
plaintext?: string,
): Promise<SentMessageInfo> {
if (!gTransporter) {
throw new Error("SMTP transport not initialized");
}

const emailFrom = envVars.EMAIL_FROM;
const mailOptions = {
const mailOptions: SendMailOptions = {
from: emailFrom,
to: recipient,
subject,
html,
text: plaintext,
headers: {
"x-ses-configuration-set": envVars.SES_CONFIG_SET,
},
Expand Down

0 comments on commit ec9fb04

Please sign in to comment.