Fix tests

This commit is contained in:
Dan Mindru 2019-09-03 23:47:55 +02:00 committed by Dan Mindru
parent e44a52c89f
commit 86944f3cee
8 changed files with 63 additions and 38 deletions

View File

@ -1,54 +1,60 @@
# Responsive HTML email signature(s) # Responsive HTML email signature(s)
[![npm](https://img.shields.io/npm/v/responsive-html-email-signature.svg)](https://www.npmjs.com/package/responsive-html-email-signature) [![npm](https://img.shields.io/npm/v/responsive-html-email-signature.svg)](https://www.npmjs.com/package/responsive-html-email-signature)
[![license](https://img.shields.io/github/license/danmindru/responsive-html-email-signature.svg)](/LICENSE) [![license](https://img.shields.io/github/license/danmindru/responsive-html-email-signature.svg)](/LICENSE)
[![test action status](https://github.com/danmindru/responsive-html-email-signature/workflows/Test%20template%20output/badge.svg)](https://github.com/danmindru/responsive-html-email-signature/actions) [![test action status](https://github.com/danmindru/responsive-html-email-signature/workflows/Test%20template%20output/badge.svg)](https://github.com/danmindru/responsive-html-email-signature/actions)
### Let's punch email clients in the stomach 👊 ### Let's punch email clients in the stomach 👊
When you need some basic responsive email signatures that work on mobile.<br/> When you need some basic responsive email signatures that work on mobile.<br/>
...and your colleagues need them too.<br/> ...and your colleagues need them too.<br/>
...but you don't want to deal with tables and inline styles. ...but you don't want to deal with tables and inline styles.
[Read the docs in other languages](/i18n) ↗️ [Read the docs in other languages](/i18n) ↗️
## Preview ## Preview
Here are some examples: Here are some examples:
![responsive emails-01](https://cloud.githubusercontent.com/assets/1515742/10591900/13889d32-76b9-11e5-8dc0-b89d80189e93.png) ![responsive emails-01](https://cloud.githubusercontent.com/assets/1515742/10591900/13889d32-76b9-11e5-8dc0-b89d80189e93.png)
![responsive emails-02](https://cloud.githubusercontent.com/assets/1515742/10591901/139c4954-76b9-11e5-80f7-5b0ccaf5af81.png) ![responsive emails-02](https://cloud.githubusercontent.com/assets/1515742/10591901/139c4954-76b9-11e5-80f7-5b0ccaf5af81.png)
## Getting started ## Getting started
- Clone repo `git clone https://github.com/danmindru/responsive-html-email-signature.git` - Clone repo `git clone https://github.com/danmindru/responsive-html-email-signature.git`
- Run `npm install` - Run `npm install`
- Run `npm start` to generate templates from configuration. This will continue to watch your files and re-make the template until you exit. - Run `npm start` to generate templates from configuration. This will continue to watch your files and re-make the template until you exit.
### Customizing templates ### Customizing templates
- Edit files in */templates*
- Edit files in _/templates_
- Open files from `./dist` in your fav browser to check them out - Open files from `./dist` in your fav browser to check them out
> When you're done, check out [how to add them to your email client of choice](#usage-with-different-email-clients) if in doubt. > When you're done, check out [how to add them to your email client of choice](#usage-with-different-email-clients) if in doubt.
## Motivation ## Motivation
Writing HTML emails & email signatures sucks. Let's make it easier. We can't fix all email clients, but we can surely make our lives easier with some automation. <br/> Writing HTML emails & email signatures sucks. Let's make it easier. We can't fix all email clients, but we can surely make our lives easier with some automation. <br/>
## What does this pile of code do ## What does this pile of code do
- [x] generates email templates from your config - [x] generates email templates from your config
- [x] allows generating multiple templates at once (for your colleagues too!) - [x] allows generating multiple templates at once (for your colleagues too!)
- [x] transforms linked (`<link>`) CSS into inline styles - [x] transforms linked (`<link>`) CSS into inline styles
- [x] embeds local `img[src]` into the template (base64).* - [x] embeds local `img[src]` into the template (base64).\*
- [x] minifies the template - [x] minifies the template
- [x] ads some basic media queries for mail clients that support them - [x] ads some basic media queries for mail clients that support them
- [x] can build templates from multiple sources - [x] can build templates from multiple sources
- [x] watches HTML / CSS files for changes and re-builds - [x] watches HTML / CSS files for changes and re-builds
- [x] supports LESS / SASS / PostCSS - [x] supports LESS / SASS / PostCSS
- [x] autoprefixer, so you don't have to worry about your `-moz-`s or `-webkit-`s - [x] autoprefixer, so you don't have to worry about your `-moz-`s or `-webkit-`s
- [x] linting, checks for used template config parameters and more!
**Some mail clients might have [hard limits](https://support.google.com/a/answer/176652?hl=en) regarding the email size, so don't include large images if possible. If you need to, use a URL instead and host the image somewhere else.* \*_Some mail clients might have [hard limits](https://support.google.com/a/answer/176652?hl=en) regarding the email size, so don't include large images if possible. If you need to, use a URL instead and host the image somewhere else._
## Docs ## Docs
### Installing ### Installing
```bash ```bash
$ npm install $ npm install
$ npm start # By default, templates will be created in `./dist` and HTML & CSS files in './templates' will be watched for changes. $ npm start # By default, templates will be created in `./dist` and HTML & CSS files in './templates' will be watched for changes.
@ -57,9 +63,11 @@ $ npm start # By default, templates will be created in `./dist` and HTML & CSS f
> Note: works well with node v10+. Earlier and later versions might also work. > Note: works well with node v10+. Earlier and later versions might also work.
### Configuring ### Configuring
To make a basic email from existing templates, you only have to edit the `conf.json` file in each template. To make a basic email from existing templates, you only have to edit the `conf.json` file in each template.
For example, the dark template accepts the following: For example, the dark template accepts the following:
```json ```json
{ {
"id": "<will-be-used-for-filename>", "id": "<will-be-used-for-filename>",
@ -75,15 +83,15 @@ For example, the dark template accepts the following:
``` ```
### Generating multiple emails from the same config (for your colleagues too!) ### Generating multiple emails from the same config (for your colleagues too!)
To generate multiple templates, use an array instead of an object in `conf.json`, like so: To generate multiple templates, use an array instead of an object in `conf.json`, like so:
```json ```json
[ [{ ...conf1 }, { ...conf2 }]
{...conf1},
{...conf2}
]
``` ```
### Using config values in HTML ### Using config values in HTML
Config variables are made available in all HTML files. <br/> Config variables are made available in all HTML files. <br/>
Add any variable to the configuration file and use it in HTML like so: Add any variable to the configuration file and use it in HTML like so:
@ -95,23 +103,23 @@ Where the configuration contains:
```json ```json
{ {
yourCustomVariable: "Custom!" "yourCustomVariable": "Custom!"
} }
``` ```
> NB: config variables also accept HTML. That's useful for including links. > NB: config variables also accept HTML. That's useful for including links.
### Adding CSS & pre-processing ### Adding CSS & pre-processing
Any number of CSS, SASS or LESS files in a template directory & they will be automatically processed & inlined into the files outputed in `./dist`. Any number of CSS, SASS or LESS files in a template directory & they will be automatically processed & inlined into the files outputed in `./dist`.
### Multiple emails in the same template ### Multiple emails in the same template
Templates can contain multiple HTML files from which to build emails. For example, the dark template has `signature.html` and `signature-reply.html`, which is a simpler version. Templates can contain multiple HTML files from which to build emails. For example, the dark template has `signature.html` and `signature-reply.html`, which is a simpler version.
Each HTML file will be treated as an email template, except for `*.inc.html`. See below ⬇️ Each HTML file will be treated as an email template, except for `*.inc.html`. See below ⬇️
### Using partials (\*.inc.html)
### Using partials (*.inc.html)
By naming files with `*.inc.html`, they become partials. Partials will not be treated as templates (ignored), but they can be included in any HTML template using the `@include` HTML comment. By naming files with `*.inc.html`, they become partials. Partials will not be treated as templates (ignored), but they can be included in any HTML template using the `@include` HTML comment.
```html ```html
@ -122,12 +130,17 @@ By naming files with `*.inc.html`, they become partials. Partials will not be tr
Partials are useful if you have bits of HTML that repeat, like headers, footers, etc. Partials are useful if you have bits of HTML that repeat, like headers, footers, etc.
### Advanced templating
Inside HTML files, any [preprocess directive](https://github.com/jsoverson/preprocess#all-directives) is supported, such as `@if`, `@extend`, `@exec`, etc.
## Template structure (examples) ## Template structure (examples)
There are no rules regarding how to structure templates, but it's a good idea to create directories for a template group. <br/> There are no rules regarding how to structure templates, but it's a good idea to create directories for a template group. <br/>
There are 2 examples of template structures, one for the `light` email template and one for the `dark` one. There are 2 examples of template structures, one for the `light` email template and one for the `dark` one.
Here's how the dark one is structured: Here's how the dark one is structured:
```bash ```bash
./templates ./templates
├── dark ├── dark
@ -142,6 +155,7 @@ Here's how the dark one is structured:
``` ```
Here's how the light one is structured: Here's how the light one is structured:
```bash ```bash
./templates ./templates
├── light ├── light
@ -160,62 +174,70 @@ There's one convention you have to keep in mind: `all files that you wish to inc
You are of course encouraged to change the default structure for your use case. You are of course encouraged to change the default structure for your use case.
## Overview of the build process ## Overview of the build process
The diagram below shows what happens to your email templates. The diagram below shows what happens to your email templates.
Each folder in 'templates' is considered a `template group`. A template file will be generated for each of the configuration objects you add have in the template group -> `conf.js`. Each folder in 'templates' is considered a `template group`. A template file will be generated for each of the configuration objects you add have in the template group -> `conf.js`.
![Responsive HTML email template/signatures diagram](https://user-images.githubusercontent.com/1515742/45000195-35268300-afc3-11e8-82b4-7507430c48a0.png) ![Responsive HTML email template/signatures diagram](https://user-images.githubusercontent.com/1515742/45000195-35268300-afc3-11e8-82b4-7507430c48a0.png)
## CSS Support ## CSS Support
Remember, it's HTML mails, so you need to check a big-ass table to find out nothing's gonna work. Remember, it's HTML mails, so you need to check a big-ass table to find out nothing's gonna work.
See [this](https://www.campaignmonitor.com/css/) for more info. [Gulp-inline-css](https://www.npmjs.com/package/gulp-inline-css) is being used to convert whatever CSS you throw at it to inline styles, but it probably won't handle everything. See [this](https://www.campaignmonitor.com/css/) for more info. [Gulp-inline-css](https://www.npmjs.com/package/gulp-inline-css) is being used to convert whatever CSS you throw at it to inline styles, but it probably won't handle everything.
Some bonuses of using `gulp-inline-css`: many css props will be converted to attributes. For example, the 'background-color' prop will be added as 'bgcolor' attribute to table elements. Some bonuses of using `gulp-inline-css`: many css props will be converted to attributes. For example, the 'background-color' prop will be added as 'bgcolor' attribute to table elements.
For more details take a look at the [inline-css mappings](https://github.com/jonkemp/inline-css/blob/master/lib/setTableAttrs.js). For more details take a look at the [inline-css mappings](https://github.com/jonkemp/inline-css/blob/master/lib/setTableAttrs.js).
## Usage with different email clients ## Usage with different email clients
### Thunderbird ### Thunderbird
There are several Thunderbird plugins which can automatically insert signatures when composing e-mails. We recommend [SmartTemplate4](https://addons.mozilla.org/en-us/thunderbird/addon/smarttemplate4) as one of the options. It can use different templates for new e-mails, replies and forwarded e-mails. There are several Thunderbird plugins which can automatically insert signatures when composing e-mails. We recommend [SmartTemplate4](https://addons.mozilla.org/en-us/thunderbird/addon/smarttemplate4) as one of the options. It can use different templates for new e-mails, replies and forwarded e-mails.
### Gmail ### Gmail
Go to your mailbox settings & paste the generated signature. Go to your mailbox settings & paste the generated signature.
> **NB**: Gmail doesn't seem to support inlined (base64) images. You have to use absolute `http(s)//...` from them to load up. > **NB**: Gmail doesn't seem to support inlined (base64) images. You have to use absolute `http(s)//...` from them to load up.
### Office 365 / outlook.live.com ### Office 365 / outlook.live.com
It's a bit hacky to set up, but possible. See [this issue](https://github.com/danmindru/responsive-html-email-signature/issues/52). It's a bit hacky to set up, but possible. See [this issue](https://github.com/danmindru/responsive-html-email-signature/issues/52).
### Apple Mail / OS X (oh boy) ### Apple Mail / OS X (oh boy)
#### Solution 1 #### Solution 1
- Open Mail.app and go to `Mail` -> `Preferences` -> `Signatures` - Open Mail.app and go to `Mail` -> `Preferences` -> `Signatures`
- Create a new signature and write some placeholder text (doesn't matter what it is, but you have to identify it later). - Create a new signature and write some placeholder text (doesn't matter what it is, but you have to identify it later).
- Close Mail.app. - Close Mail.app.
- Open terminal, then open the signature files using TextEdit (might be different for iCloud drive check the article below). - Open terminal, then open the signature files using TextEdit (might be different for iCloud drive check the article below).
``` ```
$ open -a TextEdit ~/Library/Mobile\ Documents/com~apple~mail/Data/V3/MailData/Signatures/ubiquitous_*.mailsignature $ open -a TextEdit ~/Library/Mobile\ Documents/com~apple~mail/Data/V3/MailData/Signatures/ubiquitous_*.mailsignature
``` ```
- Keep the file with the placeholder open, close the other ones. - Keep the file with the placeholder open, close the other ones.
- Replace the `<body>...</body>` and it's contents with the template of your choice. *Don't remove the meta information at the top!* - Replace the `<body>...</body>` and it's contents with the template of your choice. _Don't remove the meta information at the top!_
- Open Mail.app and compose a new mail. Select the signature from the list to test it out. - Open Mail.app and compose a new mail. Select the signature from the list to test it out.
> **NB**: Images won't appear in the signature preview, but will work fine when you compose a message. > **NB**: Images won't appear in the signature preview, but will work fine when you compose a message.
#### Solution 2 #### Solution 2
You can also open the HTML files in `/dist` in a browser, CMD + A, CMD + C and then paste into the signature box. This won't copy the `<html>` part or the `<style>` part that includes media queries. Follow the guide if you want it.
You can also open the HTML files in `/dist` in a browser, CMD + A, CMD + C and then paste into the signature box. This won't copy the `<html>` part or the `<style>` part that includes media queries. Follow the guide if you want it.
#### Troubleshooting #### Troubleshooting
If solution #1 doesn't work, you can repeat the steps and lock the signature files before you open Mail.app again. If solution #1 doesn't work, you can repeat the steps and lock the signature files before you open Mail.app again.
Lock Files: Lock Files:
``` ```
$ chflags uchg ~/Library/Mail/V3/MailData/Signatures/*.mailsignature $ chflags uchg ~/Library/Mail/V3/MailData/Signatures/*.mailsignature
``` ```
If you want to do changes later, you have to unlock the files: If you want to do changes later, you have to unlock the files:
``` ```
$ chflags nouchg ~/Library/Mail/V3/MailData/Signatures/*.mailsignature $ chflags nouchg ~/Library/Mail/V3/MailData/Signatures/*.mailsignature
``` ```
@ -225,6 +247,7 @@ If you are using iCloud drive or having problems with it, you might also want to
### Outlook 2010 Client for Windows 7 ### Outlook 2010 Client for Windows 7
#### Solution 1 #### Solution 1
- Open Outlook 2010 and go to `File > Option > Mail > Signature` - Open Outlook 2010 and go to `File > Option > Mail > Signature`
- Create new signature (with a placeholder for your convenience) - Create new signature (with a placeholder for your convenience)
- Open signature folder using CMD - Open signature folder using CMD
@ -241,6 +264,7 @@ start Signatures
- Open Outlook again and check your signature - Open Outlook again and check your signature
#### Solution 2 #### Solution 2
Unfortnately, Outlook 2010 client dosen't support HTML file import features for your email template. But you can add your own signatures by simple Copy and paste like **Solution 2** above. Unfortnately, Outlook 2010 client dosen't support HTML file import features for your email template. But you can add your own signatures by simple Copy and paste like **Solution 2** above.
- Open built html file on `/dist` folder and Ctrl A + C - Open built html file on `/dist` folder and Ctrl A + C
@ -249,11 +273,12 @@ Unfortnately, Outlook 2010 client dosen't support HTML file import features for
> **NB**: base 64 will not be shown on Outlook 2010 client. So, I recommend to use external url if you want to use images. > **NB**: base 64 will not be shown on Outlook 2010 client. So, I recommend to use external url if you want to use images.
## Other commands ## Other commands
### `npm run test` ### `npm run test`
Runs tests once. Runs tests once.
### `npm run once` ### `npm run once`
Creates templates and exits; does not watch files. Creates templates and exits; does not watch files.

View File

@ -74,7 +74,7 @@
"husky": { "husky": {
"hooks": { "hooks": {
"pre-push": "npm test", "pre-push": "npm test",
"pre-commit": "npm run lint && pretty-quick --staged" "pre-commit": "npm run lint && pretty-quick --staged --pattern ./**/*.js"
} }
} }
} }

View File

@ -3,36 +3,36 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
test('dark signature output', async t => { test('dark signature output', async t => {
const expected = fs.readFileSync(path.resolve('tests/sample/dark/signature-dark.html')); const expected = fs.readFileSync(path.resolve('tests/sample/dark/signature-dark.html'), 'utf8');
const built = fs.readFileSync(path.resolve('dist/dark/signature-dark.html')); const built = fs.readFileSync(path.resolve('dist/dark/signature-dark.html'), 'utf8');
t.deepEqual(expected, built); t.deepEqual(expected, built);
}); });
test('dark signature reply output', async t => { test('dark signature reply output', async t => {
const expected = fs.readFileSync(path.resolve('tests/sample/dark/signature-reply-dark.html')); const expected = fs.readFileSync(path.resolve('tests/sample/dark/signature-reply-dark.html'), 'utf8');
const built = fs.readFileSync(path.resolve('dist/dark/signature-reply-dark.html')); const built = fs.readFileSync(path.resolve('dist/dark/signature-reply-dark.html'), 'utf8');
t.deepEqual(expected, built); t.deepEqual(expected, built);
}); });
test('light signature output', async t => { test('light signature output', async t => {
const expected = fs.readFileSync(path.resolve('tests/sample/light/signature-light.html')); const expected = fs.readFileSync(path.resolve('tests/sample/light/signature-light.html'), 'utf8');
const built = fs.readFileSync(path.resolve('dist/light/signature-light.html')); const built = fs.readFileSync(path.resolve('dist/light/signature-light.html'), 'utf8');
t.deepEqual(expected, built); t.deepEqual(expected, built);
}); });
test('light signature reply output', async t => { test('light signature reply output', async t => {
const expected = fs.readFileSync(path.resolve('tests/sample/light/signature-reply-light.html')); const expected = fs.readFileSync(path.resolve('tests/sample/light/signature-reply-light.html'), 'utf8');
const built = fs.readFileSync(path.resolve('dist/light/signature-reply-light.html')); const built = fs.readFileSync(path.resolve('dist/light/signature-reply-light.html'), 'utf8');
t.deepEqual(expected, built); t.deepEqual(expected, built);
}); });
test('light full mail output', async t => { test('light full mail output', async t => {
const expected = fs.readFileSync(path.resolve('tests/sample/light/full-mail-light.html')); const expected = fs.readFileSync(path.resolve('tests/sample/light/full-mail-light.html'), 'utf8');
const built = fs.readFileSync(path.resolve('dist/light/full-mail-light.html')); const built = fs.readFileSync(path.resolve('dist/light/full-mail-light.html'), 'utf8');
t.deepEqual(expected, built); t.deepEqual(expected, built);
}); });

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta name="viewport" content="width=device-width"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">@media only screen and (max-width:560px){.footer td{font-size:12px!important}.footer__main__col1{width:100%!important}.footer__main__col1__td{text-align:left}.footer__main__col1__td>span{margin-bottom:10px}.footer__main__col2{width:100%!important}.footer__main__col2__td{text-align:left;padding-bottom:20px}.footer__main__col2__td__img{padding-left:0!important}}</style></head><body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"><br><table class="main rbcc" style="border: 0; cellpadding: 0; cellspacing: 0;" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff" width="100%"><tr class="sp" style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 22px;"><td class="sp__inner" style="padding: 15px 0;"></td></tr><tr class="rbcc" style="-webkit-box-sizing: border-box; border: 0; box-sizing: border-box; cellpadding: 0; cellspacing: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 22px;"><td class="footer footer--simple" style="border-top: 8px solid #585858; color: #f5f5f5; padding: 20px 30px 0px 30px; padding-bottom: 20px;" bgcolor="#FFFFFF"><table class="rbcc footer__main" style="border: 0; cellpadding: 0; cellspacing: 0;" border="0" cellpadding="0" cellspacing="0" width="100%"><tr style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 22px;"><td class="footer__main__signature" align="left" style="align: left; color: #888; font-size: 14px;">Best regards,<br>The dark mail team<br></td></tr></table></td></tr></table></body></html> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta name="viewport" content="width=device-width"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">@media only screen and (max-width:560px){.footer td{font-size:12px!important}.footer__main__col1{width:100%!important}.footer__main__col1__td{text-align:left}.footer__main__col1__td>span{margin-bottom:10px}.footer__main__col2{width:100%!important}.footer__main__col2__td{text-align:left;padding-bottom:20px}.footer__main__col2__td__img{padding-left:0!important}}</style></head><body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"><br><table class="main rbcc" style="border: 0; cellpadding: 0; cellspacing: 0;" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff" width="100%"><tr class="sp" style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 22px;"><td class="sp__inner" style="padding: 15px 0;"></td></tr><tr class="rbcc" style="-webkit-box-sizing: border-box; border: 0; box-sizing: border-box; cellpadding: 0; cellspacing: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 22px;"><td class="footer footer--simple" style="border-top: 8px solid #585858; color: #f5f5f5; padding: 20px 30px 0px 30px; padding-bottom: 20px;" bgcolor="#ffffff"><table class="rbcc footer__main" style="border: 0; cellpadding: 0; cellspacing: 0;" border="0" cellpadding="0" cellspacing="0" width="100%"><tr style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 22px;"><td class="footer__main__signature" align="left" style="align: left; color: #888; font-size: 14px;">Best regards,<br>The dark mail team<br></td></tr></table></td></tr></table></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta name="viewport" content="width=device-width"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">@media only screen and (max-width:480px){.footer td{font-size:12px!important}.footer__main__col1{width:100%!important}.footer__main__col2{width:100%!important}.footer__main__col2__td{text-align:left;padding-bottom:20px}.footer__main__col2__td__img{padding-left:0!important}.gray-hr hr{margin-bottom:10px!important;margin-top:10px!important}}@media only screen and (min-width:1025px){.body-with-bg{background-color:#f1f1f1}.body-with-bg .main{border:1px solid #e9e9e9!important;max-width:960px;margin:0 auto}.background{padding:30px;background-color:#f1f1f1}}</style></head><body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"><br><table class="main rbcc" style="border: 0; cellpadding: 0; cellspacing: 0; padding-top: 15px;" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff" width="100%"><tr class="sp" style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"><td class="sp__inner" style="padding: 15px 0;"></td></tr><tr class="rbcc" style="-webkit-box-sizing: border-box; border: 0; box-sizing: border-box; cellpadding: 0; cellspacing: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"><td class="footer footer--simple" style="border-top: 8px solid #EAEAEA; color: #888; padding: 20px 30px 0px 30px; padding-bottom: 20px;" bgcolor="#FFFFFF"><table class="rbcc footer__main" style="border: 0; cellpadding: 0; cellspacing: 0;" border="0" cellpadding="0" cellspacing="0" width="100%"><tr style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"><td class="footer__main__signature" align="left" style="align: left; color: #888; font-size: 14px;">Yours truly,<br>The light mail team<br></td></tr></table></td></tr></table></body></html> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta name="viewport" content="width=device-width"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">@media only screen and (max-width:480px){.footer td{font-size:12px!important}.footer__main__col1{width:100%!important}.footer__main__col2{width:100%!important}.footer__main__col2__td{text-align:left;padding-bottom:20px}.footer__main__col2__td__img{padding-left:0!important}.gray-hr hr{margin-bottom:10px!important;margin-top:10px!important}}@media only screen and (min-width:1025px){.body-with-bg{background-color:#f1f1f1}.body-with-bg .main{border:1px solid #e9e9e9!important;max-width:960px;margin:0 auto}.background{padding:30px;background-color:#f1f1f1}}</style></head><body style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;"><br><table class="main rbcc" style="border: 0; cellpadding: 0; cellspacing: 0; padding-top: 15px;" border="0" cellpadding="0" cellspacing="0" bgcolor="#ffffff" width="100%"><tr class="sp" style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"><td class="sp__inner" style="padding: 15px 0;"></td></tr><tr class="rbcc" style="-webkit-box-sizing: border-box; border: 0; box-sizing: border-box; cellpadding: 0; cellspacing: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"><td class="footer footer--simple" style="border-top: 8px solid #eaeaea; color: #888; padding: 20px 30px 0px 30px; padding-bottom: 20px;" bgcolor="#ffffff"><table class="rbcc footer__main" style="border: 0; cellpadding: 0; cellspacing: 0;" border="0" cellpadding="0" cellspacing="0" width="100%"><tr style="-webkit-box-sizing: border-box; box-sizing: border-box; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 14px; line-height: 20px;"><td class="footer__main__signature" align="left" style="align: left; color: #888; font-size: 14px;">Yours truly,<br>The light mail team<br></td></tr></table></td></tr></table></body></html>