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

mozilla / blurts-server / 5cdb8060-c45f-4db8-a67a-036a3b1dac73

pending completion
5cdb8060-c45f-4db8-a67a-036a3b1dac73

push

circleci

GitHub
Merge pull request #2805 from mozilla/MNTOR-1150-Fix-email-header-style

282 of 1283 branches covered (21.98%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

959 of 3456 relevant lines covered (27.75%)

4.51 hits per line

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

0.0
/src/views/email-2022.js
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4

5
import AppConstants from '../app-constants.js'
6
import { getMessage } from '../utils/fluent.js'
7

8
const companyAddress = '2 Harrison St. #175, San Francisco, California 94105 USA'
×
9
const links = (data) => ({
×
10
  faq: 'https://support.mozilla.org/kb/firefox-monitor-faq',
11
  hibp: 'https://haveibeenpwned.com/',
12
  legal: `https://www.mozilla.org/about/legal?utm_source=fx-monitor&utm_medium=email&utm_campaign=${data.utmCampaign}&utm_content=email-footer-link`,
13
  termsAndPrivacy: `https://www.mozilla.org/privacy/firefox-monitor?utm_source=fx-monitor&utm_medium=email&utm_campaign=${data.utmCampaign}&utm_content=email-footer-link`
14
})
15

16
const images = {
×
17
  header: `${AppConstants.SERVER_URL}/images/person-at-desk.webp`,
18
  footer: `${AppConstants.SERVER_URL}/images/mozilla-logo-bw.webp`,
19
  logoDark: `${AppConstants.SERVER_URL}/images/monitor-logo-transparent-dark-mode.webp`,
20
  logoLight: `${AppConstants.SERVER_URL}/images/monitor-logo-bg-light.webp`
21
}
22

23
const bodyStyle = `
×
24
  color: black;
25
  font: normal 16px/1.2 sans-serif;
26
`
27

28
const tableStyle = `
×
29
  margin: auto;
30
  max-width: 1080px;
31
  text-align: center;
32
  width: 100%;
33
`
34

35
const headerTableStyle = `
×
36
  background-color: #321c64;
37
  color: white;
38
  height: 331px;
39
  text-align: left;
40
  width: 100%;
41
`
42

43
const headerImageContainerStyle = `
×
44
  background-color: #321c64;
45
  vertical-align: bottom;
46
  width: 50%;
47
`
48

49
const headerImageStyle = `
×
50
  display: block;
51
  margin-left: auto;
52
  max-width: 100%;
53
  object-fit: cover;
54
  object-position: left;
55
`
56

57
const footerContainerStyle = `
×
58
  background: #f9f9fa;
59
  border-top: 1px solid #dddddd;
60
  padding: 24px 0;
61
`
62

63
const footerImageStyle = `
×
64
  display: block;
65
  margin: 24px auto 0;
66
`
67

68
const emailHeader = (data) => `
×
69
  <tr class='logo'>
70
    <td height='100'></td>
71
  </tr>
72
  <tr class='header'>
73
    <td>
74
      <table
75
        border='0'
76
        cellpadding='0'
77
        cellspacing='0'
78
        role='presentation'
79
        style='${headerTableStyle}'
80
      >
81
        <tr>
82
          <td>
83
            <h1>
84
              ${getMessage(data.heading)}
85
            </h1>
86
            <p>
87
              ${getMessage(data.subhead)}
88
            </p>
89
          </td>
90
          <td
91
            class='header-image'
92
            style='${headerImageContainerStyle}'
93
          >
94
            <img
95
              alt=''
96
              height='331'
97
              src='${images.header}'
98
              style='${headerImageStyle}'
99
              width='476'
100
            >
101
          </td>
102
        </tr>
103
      </table>
104
    </td>
105
  </tr>
106
`
107

108
const emailFooter = (data) => `
×
109
  <tr class='footer'>
110
    <td style='${footerContainerStyle}'>
111
      <p>
112
        ${getEmailFooterCopy(data)}
113
      </p>
114
      <p>
115
        ${getMessage('email-2022-hibp-attribution', {
116
          'hibp-link-attr': `href='${links(data).hibp}' rel='noopener'`
117
        })}
118
      </p>
119
      <img
120
        alt='${getMessage('mozilla')}'
121
        src='${images.footer}'
122
        style='${footerImageStyle}'
123
        width='130px'
124
      >
125
      <p>
126
        ${companyAddress}
127
      </p>
128
      <p>
129
        <a href='${links(data).legal}'>
130
          ${getMessage('legal')}
131
        </a>
132
        ${' • '}
133
        <a href='${links(data).termsAndPrivacy}'>
134
          ${getMessage('terms-and-privacy')}
135
        </a>
136
      </p>
137
    </td>
138
  </tr>
139
`
140

141
function getEmailFooterCopy (data) {
142
  const unsubLink = `
×
143
    <a href='${data.unsubscribeUrl}'>
144
      ${getMessage('email-unsub-link')}
145
    </a>
146
  `
147
  const faqLink = `
×
148
    <a href='${links(data).faq}'>${getMessage('frequently-asked-questions')}</a>
149
  `
150

151
  return getMessage('email-footer-blurb', {
×
152
    unsubLink,
153
    faqLink
154
  })
155
}
156

157
const getTemplate = (data, partial) => `
×
158
  <!doctype html>
159
  <html>
160
    <head>
161
      <meta name='viewport' content='width=device-width, initial-scale=1.0' />
162
      <meta http-equiv='Content-Type' content='text/html; charset=UTF-8' />
163

164
      <title>
165
        ${getMessage('brand-fx-monitor')}
166
      </title>
167

168
      <style>
169
        * {
170
          margin: 0;
171
          padding: 0;
172
        }
173

174
        body {
175
          color: black;
176
          font: normal 16px/1.2 sans-serif;
177
        }
178

179
        h1,
180
        p {
181
          margin: 12px auto;
182
          max-width: 600px;
183
          padding: 0 24px;
184
        }
185

186
        a {
187
          color: #592acb;
188
          text-decoration: none;
189
        }
190

191
        table {
192
          table-layout: fixed;
193
        }
194

195
        .logo > td {
196
          height: 100px;
197
          background-color: #f9f9fa;
198
          background-position: 50%;
199
          background-image: url('${images.logoLight}');
200
          background-repeat: no-repeat;
201
          background-size: 240px 50px;
202
          width: 100%;
203
        }
204

205
        @media screen and (max-width:600px) {
206
          .header-image {
207
            display: none;
208
          }
209
        }
210

211
        @media (prefers-color-scheme: dark) {
212
          .logo > td {
213
            background-image: url('${images.logoDark}')
214
          }
215
        }
216
      </style>
217
    </head>
218

219
    <body style='${bodyStyle}'>
220
      <table
221
        border='0'
222
        cellpadding='0'
223
        cellspacing='0'
224
        role='presentation'
225
        style='${tableStyle}'
226
      >
227
        ${emailHeader({
228
          heading: 'email-verify-heading',
229
          subhead: 'email-verify-subhead'
230
        })}
231
        ${partial}
232
        ${emailFooter(data)}
233
      </table>
234
    </body>
235
  </html>
236
`
237

238
export { getTemplate }
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