From 2153fd7fa547fbf799591aab383bfa5322233567 Mon Sep 17 00:00:00 2001 From: Liangjun Song <146005915+adai26@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:10:01 +0100 Subject: [PATCH] Merge pull request #28898 from overleaf/ls-send-email-for-tax-exempt-certificate Send email if tax exempt certificate is required GitOrigin-RevId: 685fec7dbb129eab19095470e681d09423558e4c --- .../app/src/Features/Email/EmailBuilder.js | 29 +++++++++++ .../web/app/src/Features/Email/EmailSender.js | 3 ++ .../test/unit/src/Email/EmailBuilderTests.js | 51 +++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/services/web/app/src/Features/Email/EmailBuilder.js b/services/web/app/src/Features/Email/EmailBuilder.js index f1d52220fb..fd7844ff64 100644 --- a/services/web/app/src/Features/Email/EmailBuilder.js +++ b/services/web/app/src/Features/Email/EmailBuilder.js @@ -974,6 +974,35 @@ templates.removeGroupMember = NoCTAEmailTemplate({ }, }) +templates.taxExemptCertificateRequired = NoCTAEmailTemplate({ + subject(opts) { + return `Action required: Tax exemption verification for Overleaf [${opts.ein}]` + }, + title() { + return 'Action required: Tax exemption verification' + }, + greeting() { + return '' + }, + message(opts) { + return [ + 'Thanks for letting us know your organization is tax exempt. To confirm this, we need some additional verification.', + 'Please reply to this email with one of the following documents attached:', + '', + `These should match the EIN you provided:${opts.ein}.`, + 'If you have any questions, let us know by replying to this email.', + '
', + 'Best wishes,', + 'Team Overleaf', + '
', + `Our reference:${opts.stripeCustomerId}`, + ] + }, +}) + function _formatUserNameAndEmail(user, placeholder) { if (user.first_name && user.last_name) { const fullName = `${user.first_name} ${user.last_name}` diff --git a/services/web/app/src/Features/Email/EmailSender.js b/services/web/app/src/Features/Email/EmailSender.js index 678259a6f8..e0b7a012b0 100644 --- a/services/web/app/src/Features/Email/EmailSender.js +++ b/services/web/app/src/Features/Email/EmailSender.js @@ -104,6 +104,9 @@ async function sendEmail(options, emailType) { replyTo: options.replyTo || EMAIL_SETTINGS.replyToAddress, socketTimeout: 30 * 1000, } + if (options.cc) { + sendMailOptions.cc = options.cc + } if (EMAIL_SETTINGS.textEncoding != null) { sendMailOptions.textEncoding = EMAIL_SETTINGS.textEncoding } diff --git a/services/web/test/unit/src/Email/EmailBuilderTests.js b/services/web/test/unit/src/Email/EmailBuilderTests.js index 11380012ad..dbcdceb8d1 100644 --- a/services/web/test/unit/src/Email/EmailBuilderTests.js +++ b/services/web/test/unit/src/Email/EmailBuilderTests.js @@ -880,6 +880,57 @@ describe('EmailBuilder', function () { }) }) }) + + describe('taxExemptCertificateRequired', function () { + beforeEach(function () { + this.emailAddress = 'customer@example.com' + this.opts = { + to: this.emailAddress, + ein: '12-3456789', + stripeCustomerId: 'cus_123456789', + } + this.email = this.EmailBuilder.buildEmail( + 'taxExemptCertificateRequired', + this.opts + ) + this.dom = cheerio.load(this.email.html) + }) + + it('should build the email', function () { + expect(this.email.html).to.exist + expect(this.email.text).to.exist + }) + + describe('HTML email', function () { + it('should include the EIN', function () { + expect(this.email.html).to.contain(this.opts.ein) + }) + + it('should include the Stripe customer ID', function () { + expect(this.email.html).to.contain(this.opts.stripeCustomerId) + }) + + it('should include tax exemption verification text', function () { + expect(this.email.html).to.contain('tax exempt') + expect(this.email.html).to.contain('verification') + }) + }) + + describe('plain text email', function () { + it('should include the EIN', function () { + expect(this.email.text).to.contain(this.opts.ein) + }) + + it('should include the Stripe customer ID', function () { + expect(this.email.text).to.contain(this.opts.stripeCustomerId) + }) + + it('should include tax exemption verification text', function () { + expect(this.email.text).to.contain('tax exempt') + expect(this.email.text).to.contain('verification') + }) + }) + }) }) }) })