• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / blurts-server / #12980

pending completion
#12980

push

circleci

Vinnl
Add redundant social media preview tags

Not all social media websites implement the same (or any) fallbacks
for preview cards, so we have to add them redundantly to make sure
they show up everywhere.

282 of 1595 branches covered (17.68%)

Branch coverage included in aggregate %.

959 of 4308 relevant lines covered (22.26%)

1.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/controllers/email-l10n.js
1
'use strict'
2

3
const EmailUtils = require('../email-utils')
×
4
const AppConstants = require('../app-constants')
×
5
const path = require('path')
×
6
const { readFile } = require('fs/promises')
×
7

8
const partials = ['alert', 'report', 'email_verify', 'email-monthly-unresolved']
×
9
const mockBreaches = ['Dropbox', 'Apollo', 'Adobe']
×
10
const mockBreachStats = {
×
11
  passwords: {
12
    count: 1,
13
    numResolved: 0
14
  },
15
  numBreaches: {
16
    count: 2,
17
    numResolved: 0,
18
    numUnresolved: 2
19
  },
20
  monitoredEmails: {
21
    count: 2
22
  }
23
}
24

25
async function getEmailMockup (req, res) {
26
  if (!['dev', 'heroku', 'stage'].includes(AppConstants.NODE_ENV)) return res.sendStatus(404)
×
27

28
  if (!req.query.partial) {
×
29
    return res.redirect('/email-l10n/?partial=email_verify&type=email_verify') // default when no specific partial requested
×
30
  } else if (!partials.includes(req.query.partial)) {
×
31
    return res.sendStatus(404) // requested partial is not in partials list
×
32
  }
33

34
  const emailStr = await readFile(path.resolve('views/layouts/email-2022.hbs'), { encoding: 'utf-8' })
×
35
  const emailStyle = emailStr.substring(emailStr.indexOf('<style>'), emailStr.indexOf('</style>') + 8)
×
36
  const { unsafeBreachesForEmail, emailSubject, breachAlert, unsubscribeUrl, heading, subheading } = getPartialData(req.query.type, req.app.locals.breaches)
×
37
  const utmCampaign = req.query.type
×
38

39
  res.render('email_l10n', {
×
40
    layout: 'email_l10n_mockups.hbs',
41
    unsafeBreachesForEmail,
42
    supportedLocales: req.supportedLocales,
43
    whichPartial: `email_partials/${req.query.partial}`,
44
    partialType: req.query.type,
45
    breachedEmail: req.user?.primary_email || 'breachedEmail@testing.com',
×
46
    breachAlert,
47
    emailSubject: req.fluentFormat(emailSubject),
48
    heading: req.fluentFormat(heading),
49
    subheading: req.fluentFormat(subheading),
50
    ctaHref: EmailUtils.getEmailCtaHref(utmCampaign, 'dashboard-cta'),
51
    utmCampaign,
52
    emailStyle,
53
    unsubscribeUrl,
54
    csrfToken: req.csrfToken(),
55
    breachStats: mockBreachStats
56
  })
57
}
58

59
function getPartialData (partialType, breaches) {
60
  const unsafeBreachesForEmail = []
×
61
  let emailSubject, breachAlert, unsubscribeUrl, heading, subheading
62

63
  switch (partialType) {
×
64
    case 'email_verify':
65
      emailSubject = 'email-subject-verify'
×
66
      heading = 'email-verify-heading'
×
67
      subheading = 'email-verify-subhead'
×
68
      break
×
69
    case 'noBreaches':
70
      emailSubject = 'email-subject-no-breaches'
×
71
      heading = 'email-breach-summary'
×
72
      break
×
73
    case 'singleBreach':
74
      emailSubject = 'email-subject-found-breaches'
×
75
      heading = 'email-breach-summary'
×
76
      unsafeBreachesForEmail.push(breaches.find(breach => breach.Name === mockBreaches[0]))
×
77
      break
×
78
    case 'multipleBreaches':
79
      emailSubject = 'email-subject-found-breaches'
×
80
      heading = 'email-breach-summary'
×
81
      mockBreaches.forEach(name => {
×
82
        unsafeBreachesForEmail.push(breaches.find(breach => breach.Name === name))
×
83
      })
84
      break
×
85
    case 'alert':
86
      emailSubject = 'breach-alert-subject'
×
87
      heading = 'email-spotted-new-breach'
×
88
      breachAlert = breaches.find(breach => breach.Name === 'LinkedIn')
×
89
      break
×
90
    case 'email-monthly-unresolved':
91
      emailSubject = 'email-unresolved-heading'
×
92
      heading = 'email-unresolved-heading'
×
93
      subheading = 'email-unresolved-subhead'
×
94
      unsubscribeUrl = 'fakeunsubscribe.test.com'
×
95
      break
×
96
  }
97

98
  return { unsafeBreachesForEmail, emailSubject, breachAlert, unsubscribeUrl, heading, subheading }
×
99
}
100

101
async function sendTestEmail (req, res) {
102
  const { unsafeBreachesForEmail, emailSubject, breachAlert, heading, subheading } = getPartialData(req.body.partialType, req.app.locals.breaches)
×
103
  const supportedLocales = req.supportedLocales
×
104

105
  const unsubscribeUrl = EmailUtils.getMonthlyUnsubscribeUrl(req.user, 'monthly-unresolved', 'unsubscribe-cta')
×
106
  const utmCampaign = req.body.partialType
×
107
  const context = {
×
108
    whichPartial: req.body.whichPartial,
109
    supportedLocales,
110
    heading: req.fluentFormat(heading),
111
    subheading: req.fluentFormat(subheading),
112
    breachedEmail: req.user.primary_email,
113
    unsafeBreachesForEmail,
114
    breachAlert,
115
    breachStats: req.user.breach_stats,
116
    unsubscribeUrl,
117
    ctaHref: EmailUtils.getEmailCtaHref(utmCampaign, 'dashboard-cta'),
118
    utmCampaign
119
  }
120

121
  await EmailUtils.sendEmail(req.body.recipientEmail, req.fluentFormat(emailSubject), 'email-2022', context)
×
122

123
  res.send(`
×
124
    <h2>Email sent!</h2>
125
    <a href='/email-l10n/'>Go Back</a> | <a href='/user/logout'>Sign Out</a>
126
    `)
127
}
128

129
function notFound (req, res) {
130
  res.status(404)
×
131
  res.render('subpage', {
×
132
    analyticsID: 'error',
133
    headline: req.fluentFormat('error-headline'),
134
    subhead: req.fluentFormat('home-not-found')
135
  })
136
}
137

138
module.exports = {
×
139
  getEmailMockup,
140
  notFound,
141
  sendTestEmail
142
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc