diff --git a/services/web/app/src/Features/Email/EmailBuilder.mjs b/services/web/app/src/Features/Email/EmailBuilder.mjs
index 2ad9e62b09..33aad13b96 100644
--- a/services/web/app/src/Features/Email/EmailBuilder.mjs
+++ b/services/web/app/src/Features/Email/EmailBuilder.mjs
@@ -1115,6 +1115,35 @@ templates.groupDomainCapturedByGroupChanged = ctaTemplate({
},
})
+templates.domainVerifiedForGroup = NoCTAEmailTemplate({
+ subject(opts) {
+ if (opts.capturedByGroup) {
+ return `Your domain is verified`
+ } else {
+ return 'Your domain is verified — ready to capture?'
+ }
+ },
+ message(opts, isPlainText) {
+ const message = [
+ `We've verified ${_.escape(opts.domain)} for your Overleaf group.`,
+ ]
+
+ if (opts.capturedByGroup) {
+ message.push(`Your group will continue capturing users with this domain.`)
+ } else {
+ message.push(
+ `To complete the capture, reply to this email and we'll take it from there.`,
+ `Once captured, existing Overleaf users with a ${_.escape(opts.domain)} address will be invited to join your group. Until they accept, they won't be able to access Overleaf. New users who sign up with ${_.escape(opts.domain)} will be added to your group automatically.`,
+ `You'll receive a confirmation email once the capture is active.`
+ )
+ }
+
+ return message.map(m => {
+ return EmailMessageHelper.cleanHTML(m, isPlainText)
+ })
+ },
+})
+
function _formatUserNameAndEmail(user, placeholder) {
if (user.first_name && user.last_name) {
const fullName = `${user.first_name} ${user.last_name}`
diff --git a/services/web/test/unit/src/Email/EmailBuilder.test.mjs b/services/web/test/unit/src/Email/EmailBuilder.test.mjs
index 06b61e4243..332a6f3139 100644
--- a/services/web/test/unit/src/Email/EmailBuilder.test.mjs
+++ b/services/web/test/unit/src/Email/EmailBuilder.test.mjs
@@ -1093,6 +1093,41 @@ describe('EmailBuilder', function () {
expect(email.text).to.contain('admin@overleaf.test')
})
})
+
+ describe('domainVerifiedForGroup', function () {
+ it('should build captured-by-group variant', function (ctx) {
+ const email = ctx.EmailBuilder.buildEmail('domainVerifiedForGroup', {
+ to: 'admin@example.com',
+ domain: 'example.com',
+ capturedByGroup: true,
+ })
+
+ expect(email.subject).to.equal('Your domain is verified')
+ expect(email.html).to.contain("We've verified")
+ expect(email.html).to.contain('example.com')
+ expect(email.html).to.contain(
+ 'Your group will continue capturing users with this domain.'
+ )
+ })
+
+ it('should build not-captured variant with support instructions', function (ctx) {
+ const email = ctx.EmailBuilder.buildEmail('domainVerifiedForGroup', {
+ to: 'admin@example.com',
+ domain: 'example.com',
+ capturedByGroup: false,
+ })
+
+ expect(email.subject).to.equal(
+ 'Your domain is verified — ready to capture?'
+ )
+ expect(email.html).to.contain(
+ "To complete the capture, reply to this email and we'll take it from there."
+ )
+ expect(email.html).to.contain(
+ "You'll receive a confirmation email once the capture is active."
+ )
+ })
+ })
})
})
})