Email – CSS-Tricks https://css-tricks.com Tips, Tricks, and Techniques on using Cascading Style Sheets. Thu, 06 Oct 2022 12:54:54 +0000 en-US hourly 1 https://wordpress.org/?v=6.1.1 https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/07/star.png?fit=32%2C32&ssl=1 Email – CSS-Tricks https://css-tricks.com 32 32 45537868 How to Safely Share Your Email Address on a Website https://css-tricks.com/how-to-safely-share-your-email-address-on-a-website/ https://css-tricks.com/how-to-safely-share-your-email-address-on-a-website/#comments Thu, 06 Oct 2022 12:54:53 +0000 https://css-tricks.com/?p=373798 Spammers are a huge deal nowadays. If you want to share your contact information without getting overwhelmed by spam email you need a solution. I run into this problem a few months ago. While I was researching how to solve …


How to Safely Share Your Email Address on a Website originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Spammers are a huge deal nowadays. If you want to share your contact information without getting overwhelmed by spam email you need a solution. I run into this problem a few months ago. While I was researching how to solve it, I found different interesting solutions. Only one of them was perfect for my needs.

In this article, I am going to show you how to easily protect your email address from spam bots with multiple solutions. It’s up to you to decide what technique fits your needs.

The traditional case

Let’s say that you have a website. You want to share your contact details, and you don’t want to share only your social links. The email address must be there. Easy, right? You type something like this:

<a href="mailto:email@address.com">Send me an Email</a>

And then you style it according to your tastes.

Well, even if this solution works, it has a problem. It makes your email address available to literally everyone, including website crawlers and all sorts of spam bots. This means that your inbox can be flooded with tons of unwanted rubbish like promotional offers or even some phishing campaign.

We are looking for a compromise. We want to make it hard for bots to get our email addresses, but as simple as possible for normal users.

The solution is obfuscation.

Obfuscation is the practice of making something difficult to understand. This strategy is used with source code for multiple reasons. One of them is hiding the purpose of the source code to make tampering or reverse-engineering more difficult. We will first look at different solutions that are all based on the idea of obfuscation.

The HTML approach

We can think of bots as software that browse the web and crawl through web pages. Once a bot obtains an HTML document, it interprets the content in it and extracts information. This extraction process is called web scraping. If a bot is looking for a pattern that matches the email format, we can try to disguise it by using a different format. For example, we could use HTML comments:

<p>If you want to get in touch, please drop me an email at<!-- fhetydagzzzgjds --> email@<!-- sdfjsdhfkjypcs -->addr<!-- asjoxp -->ess.com</p>

It looks messy, but the user will see the email address like this:

If you want to get in touch, please drop me an email at email@address.com

Pros:

  • Easy to set up.
  • It works with JavaScript disabled.
  • It can be read by assistive technology.

Cons:

  • Spam bots can skip known sequences like comments.
  • It doesn’t work with a mailto: link.

The HTML & CSS approach

What if we use the styling power of CSS to remove some content placed only to fool spam bots? Let’s say that we have the same content as before, but this time we place a span element inside:

<p>If you want to get in touch, please drop me an email at <span class="blockspam" aria-hidden="true">PLEASE GO AWAY!</span> email@<!-- sdfjsdhfkjypcs -->address.com</p>.

Then, we use the following CSS style rule:

span.blockspam {
  display: none;
}

The final user will only see this:

If you want to get in touch, please drop me an email at email@address.com.

…which is the content we truly care about.

Pros:

  • It works with JavaScript disabled.
  • It’s more difficult for bots to get the email address.
  • It can be read by assistive technology.

Con:

  • It doesn’t work with a mailto: link.

The JavaScript approach

In this example, we use JavaScript to make our email address unreadable. Then, when the page is loaded, JavaScript makes the email address readable again. This way, our users can get the email address.

The easiest solution uses the Base64 encoding algorithm to decode the email address. First, we need to encode the email address in Base64. We can use some websites like Base64Encode.org to do this. Type in your email address like this:

A large textarea to paste an email address with a series of options beneath it for how to encode the text.

Then, click the button to encode. With these few lines of JavaScript we decode the email address and set the href attribute in the HTML link:

var encEmail = "ZW1haWxAYWRkcmVzcy5jb20=";
const form = document.getElementById("contact");
form.setAttribute("href", "mailto:".concat(atob(encEmail)));

Then we have to make sure the email link includes id="contact" in the markup, like this:

<a id="contact" href="">Send me an Email</a>

We are using the atob method to decode a string of Base64-encoded data. An alternative is to use some basic encryption algorithm like the Caesar cipher, which is fairly straightforward to implement in JavaScript.

Pros:

  • It’s more complicated for bots to get the email address, especially if you use an encryption algorithm.
  • It works with a mailto: link.
  • It can be read by assistive technology.

Con:

  • JavaScript must be enabled on the browser, otherwise, the link will be empty.

The embedded form approach

Contact forms are everywhere. You certainly have used one of them at least once. If you want a way for people to directly contact you, one of the possible solutions is implementing a contact form service on your website.

Formspree is one example of service which provides you all the benefits of a contact form without worrying about server-side code. Wufoo is too. In fact, here is a bunch you can consider for handling contact form submissions for you.

The first step to using any form service is to sign up and create an account. Pricing varies, of course, as do the features offered between services. But one thing most of them do is provide you with an HTML snippet to embed a form you create into any website or app. Here’s an example I pulled straight from a form I created in my Formspring account

<form action="https://formspree.io/f/[my-key]" method="POST">
  <label> Your email:
    <input type="email" name="email" />
  </label>
  <label> Your message:
    <textarea name="message"></textarea>
  </label>
  <!-- honeypot spam filtering -->
  <input type="text" name="_gotcha" style="display:none" />
  <button type="submit">Send</button>
</form>

In the first line, you should customize action based on your endpoint. This form quite basic, but you can add as many fields as you wish.

Notice the hidden input tag on line 9. This input tag helps you filter the submissions made by regular users and bots. In fact, if Formspree’s back-end sees a submission with that input filled, it will discard it. A regular user wouldn’t do that, so it must be a bot.

Pros:

  • Your email address is safe since it is not public.
  • It works with Javascript disabled.

Con:

  • Relies on a third-party service (which may be a pro, depending on your needs)

There is one other disadvantage to this solution but I left it out of the list since it’s quite subjective and it depends on your use case. With this solution, you are not sharing your email address. You are giving people a way to contact you. What if people want to email you? What if people are looking for your email address, and they don’t want a contact form? A contact form may be a heavy-handed solution in that sort of situation.

Conclusion

We reached the end! In this tutorial, we talked about different solutions to the problem of online email sharing. We walked through different ideas, involving HTML code, JavaScript and even some online services like Formspree to build contact forms. At the end of this tutorial, you should be aware of all the pros and cons of the strategies shown. Now, it’s up to you to pick up the most suitable one for the your specific use case.


How to Safely Share Your Email Address on a Website originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/how-to-safely-share-your-email-address-on-a-website/feed/ 42 373798
Collecting Email Signups With the Notion API https://css-tricks.com/collecting-email-signups-with-the-notion-api/ https://css-tricks.com/collecting-email-signups-with-the-notion-api/#comments Mon, 27 Sep 2021 15:26:01 +0000 https://css-tricks.com/?p=352211 A lot of people these days are setting up their own newsletters. You’ve got the current big names like Substack and MailChimp, companies like Twitter are getting into it with Revue, and even Facebook is getting into the


Collecting Email Signups With the Notion API originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
A lot of people these days are setting up their own newsletters. You’ve got the current big names like Substack and MailChimp, companies like Twitter are getting into it with Revue, and even Facebook is getting into the newsletter business. Some folks are trying to bring it closer to home with a self-managed WordPress solution via MailPoet.

Let’s talk about another possibility: collecting your own email subscribers the good ol’ fashioned way: a <form> that submits to an API and puts them into data storage.

The first hurdle in setting up a newsletter is a mechanism to collect emails. Most apps that help you with building and sending newsletters will offer some kind of copy-and-paste signup form example, but most of these options are paid and we are looking for something that is free and completely hosted by us.

Nothing is handier than setting up our own system which we can control. In this tutorial, we will set up our own system to collect emails for our newsletters based on the Jamstack architecture. We will implement an HTML form to collect emails for our newsletter, process those emails with Netlify Functions, and save them to a Notion database with the Notion API.

But before we begin…

We need the following things:

All of these services are free (with limits). And as far as Mailgun goes, we could really use any email service provider that offers an API.

Get the entire code used in this tutorial over at GitHub.

First off, Notion

What is Notion, you ask? Let’s let them describe it:

Notion is a single space where you can think, write, and plan. Capture thoughts, manage projects, or even run an entire company — and do it exactly the way you want.

A screenshot of Notion's homepage. It says Notion is an all-in-one workspace and there is a form to enter an email address and create an account. Black and white illustrations of four people are below the form.

In other words, Notion is sort of like a database but with a nice visual interface. And each row in the database gets its own “page” where writing content is not unlike writing a blog post in the WordPress block editor.

And those databases can be visualized in a number of ways, from a simple spreadsheet to a Trello-like board, or a gallery, or a calendar, or a timeline, or a… you get the picture.

We are using Notion because we can set up tables that store our form responses, making it basically a data store. Notion also just so happened to recently release a full API for public use. We can take advantage of that API and interact with it using…

Netlify Functions

Netlify Functions are serverless API endpoints provided by, of course, Netlify’s hosting platform. We can write them in JavaScript or Go.

A screenshot of the Netlify Functions webpage. It has a large black heading in bold type that reads Build scalable, dynamic applications. There is a teal colored button with rounded corners below to get started with Netlify, then a text link beside it that reads talk to an expert.

We could use Netlify forms here to collect form submissions. In fact, Matthew Ström already shared how that works. But on a free plan, we can only receive 100 submissions per month. So, that’s why we’re using Netlify Functions — they can be invoked 125,000 times a month, meaning we can collect a quarter-million emails every month without paying a single penny.

Let’s set up the Notion database

The first thing we need to do is create a database in Notion. All that takes is creating a new page, then inserting a full-page table block by typing /table.

Screenshot of a Notion page with the block inserter open and the full page table option selected. The page has a dark background and a sidebar on the left with navigation for the user account.
Typing a command in Notion, like /table, opens up a contextual menu to insert a block on a page.

Let’s give our database a name: Newsletter Emails.

We want to keep things pretty simple, so all we’re collecting is an email address when someone submits the form. So, really, all we need is a column in the table called Email.

A screenshot of the Notion database, which is in a spreadsheet or table view. The white heading is titled Newsletter Emails, then there is one column for an email address.

But Notion is a little smarter than that and includes advanced properties that provide additional information. One of those is a “Created time” property which, true to its name, prints a timestamp for when a new submission is created.

The Notion database showing a second property being added to the database to display the created time of an email entry. A contextual menu is open with a Created time property type selected and an additional contextual menu beside it showing the different types of available properties.
Now, when a new “Email” entry is added to the table, the date it was added is displayed as well. That can be nice for other things, like calculating how long someone has been a subscriber.

We also need a Notion API Token

In order to interact with our Notion database, we need to create a Notion integration and get an API token. New integrations are made, not in your notion account, but on the Notion site when you’re logged into your account. We’ll give this integration a name that’s equally creative as the Notion table: Newsletter Signups.

A plain white webpage for Notion integrations. It has a heading that says Create a new integration with form fields for name, logo, associated workspace, and a submit button.
Create a new Notion integration and associate it with the workspace where the Newsletter Emails table lives.

Once the integration has been created, we can grab the Internal Integration Token (API Token). Hold onto it because we’ll use it in just a bit.

The Notion integrations conformation screen displaying the secret internal integration token, which is obscured by the app.
Once the integration has been created, Notion provides a secret API token that’s used to authenticate connections.

By default, Notion Integrations are actually unable to access Notion pages or databases. We need to explicitly share the specific page or database with our integration in order for the integration to properly read and use information in the table. Click on the Share link at the top-right corner of the Notion database, use the selector to find the integration by its name, then click Invite.

The Notion database with Share options displayed in a modal with a list of available integrations and a light blue invite button.

Next is Netlify

Our database is all set to start receiving form submissions from Notion’s API. Now is the time to create a form and a serverless function for handling the form submissions.

Since we are setting up our website on Netlify, let’s install the Netlify CLI on our local machine. Open up Terminal and use this command:

npm install netlify-cli -g

Based on your taste, we can authenticate to Netlify in different ways. You can follow Netlify’s amazing guide as a starting point. Once we have authenticated with Netlify, the next thing we have to do is to create a Netlify project. Here are the commands to do that:

$ mkdir newsletter-subscription-notion-netlify-function
$ cd newsletter-subscription-notion-netlify-function
$ npm init

Follow along with this commit in the GitHub project.

Let’s write a Netlify Function

Before we get into writing our Netlify function, we need to do two things.

First, we need to install the [@notionhq/client](https://github.com/makenotion/notion-sdk-js) npm package, which is an official Notion JavaScript SDK for using the Notion API.

$ npm install @notionhq/client --save

Second, we need to create a .env file at the root of the project and add the following two environment variables:

NOTION_API_TOKEN=<your Notion API token>
NOTION_DATABASE_ID=<your Notion database>

The database ID can be found in its URL. A typical Notion page has a URL like https://www.notion.so/{workspace_name}/{database_id}?v={view_id} where {database_id} corresponds to the ID.

We are writing our Netlify functions in the functions directory. So, we need to create a netlify.toml file at the root of the project to tell Netlify that our functions need to be built from this directory.

[build]
functions = "functions"

Now, let’s create a functions directory at the root of the project. In the functions directory, we need to create an index.js file and add the following code. This function is available as an API endpoint at /.netlify/functions/index.

const { Client, LogLevel } = require('@notionhq/client');

const { NOTION_API_TOKEN, NOTION_DATABASE_ID } = process.env;

async function addEmail(email) {
  // Initialize Notion client
  const notion = new Client({
    auth: NOTION_API_TOKEN,
    logLevel: LogLevel.DEBUG,
  });

  await notion.pages.create({
    parent: {
      database_id: NOTION_DATABASE_ID,
    },
    properties: {
      Email: {
        title: [
          {
            text: {
              content: email,
            },
          },
        ],
      },
    },
  });
}

function validateEmail(email) {
  const re =
    /^(([^&lt;&gt;()[\\]\\\\.,;:\\s@&quot;]+(\\.[^&lt;&gt;()[\\]\\\\.,;:\\s@&quot;]+)*)|(&quot;.+&quot;))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;
  return re.test(String(email).toLowerCase());
}

module.exports.handler = async function (event, context) {
  // Check the request method
  if (event.httpMethod != 'POST') {
    return { statusCode: 405, body: 'Method not allowed' };
  }

  // Get the body
  try {
    var body = JSON.parse(event.body);
  } catch (err) {
    return {
      statusCode: 400,
      body: err.toString(),
    };
    return;
  }

  // Validate the email
  const { email } = body;
  if (!validateEmail(email)) {
    return { statusCode: 400, body: 'Email is not valid' };
  }

  // Store email in Notion
  await addEmail(email);
  return { statusCode: 200, body: 'ok' };
};

Let’s break this down, block by block.

The addEmail function is used to add the email to our Notion database. It takes an email parameter which is a string.

We create a new client for authenticating with the Notion API by providing our NOTION_API_TOKEN. We have also set the log level parameter to get information related to the execution of commands while we are developing our project, which we can remove once we are ready to deploy the project to production.

In a Notion database, each entry is known as a page. So, we use the notion.pages.create method to create a new entry in our Notion database. The module.exports.handler function is used by Netlify functions that handle the requests made to it.

The first thing we check is the request method. If the request method is something other than POST, we send back a 405 - Method not allowed response.

Then we parse the payload (event.body) object sent by the front end. If we are unable to parse the payload object, we send back a 400 - Bad request response.

Once we have parsed the request payload, we check for the presence of an email address. We use the validateEmail function to check the validity of the email. If the email is invalid, we send back a 400 - Bad request response with a custom message saying the Email is not valid.

After we have completed all the checks, we call the addEmail function to store the email in our Notion database and send back a 200 - Success response that everything went successfully.

Follow along with the code in the GitHub project with commit ed607db.

Now for a basic HTML form

Our serverless back-end is ready and the last step is to create a form to collect email submissions for our newsletter.

Let’s create an index.html file at the root of the project and add the following HTML code to it. Note that the markup and classes are pulled from Bootstrap 5.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Notion + Netlify Functions Newsletter</title>
  <link href="<https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css>" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">
</head>

<body>
  <div class="container py-5">
    <p>
      Get daily tips related to Jamstack in your inbox.
    </p>

    <div id="form" class="row">
      <div class="col-sm-8">
        <input name="email" type="email" class="form-control" placeholder="Your email" autocomplete="off">
        <div id="feedback-box" class="invalid-feedback">
            Please enter a valid email
        </div>
      </div>
      <div class="col-sm-4">
        <button class="btn btn-primary w-100" type="button" onclick="registerUser()">Submit form</button>
      </div>
    </div>

    <div id="success-box" class="alert alert-success d-none">
      Thanks for subscribing to our newsletter.
    </div>
    <div id="error-box" class="alert alert-danger d-none">
      There was some problem adding your email.
    </div>
  </div>
</body>
<script>
</script>
</html>

We have an input field for collecting user emails. We have a button that, when clicked, calls the registerUser function. We have two alerts that are shown, one for a successful submission and one for an unsuccessful submission.

Since we have installed Netlify CLI, we can use the netlify dev command to run our website on the localhost server:

$ netlify dev
Showing the email form with a heading that says Get daily tips related to Jamstack in your inbox above a form field for an email and a blue button next to it to submit the form. There is a read error message below the email input that reads Please enter a valid email.
Once the server is up and running, we can visit localhost:8888 and see our webpage with the form.

Next, we need to write some JavaScript that validates the email and sends an HTTP request to the Netlify function. Let’s add the following code in the <script> tag in the index.html file:

function validateEmail(email) {
  const re =
    /^(([^<>()[\\]\\\\.,;:\\s@"]+(\\.[^<>()[\\]\\\\.,;:\\s@"]+)*)|(".+"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$/;
  return re.test(String(email).toLowerCase());
}

async function registerUser() {
  const form = document.getElementById('form');
  const successBox = document.getElementById('success-box');
  const errorBox = document.getElementById('error-box');
  const feedbackBox = document.getElementById('feedback-box');
  const email = document.getElementsByName('email')[0].value;

  if (!validateEmail(email)) {
    feedbackBox.classList.add('d-block');
    return;
  }

  const headers = new Headers();
headers.append('Content-Type', 'application/json');
  
  const options = {
    method: 'POST',
    headers,
    body: JSON.stringify({email}),
  };

  const response = await fetch('/.netlify/functions/index', options);

  if (response.ok) {
    form.classList.add('d-none');
    successBox.classList.remove('d-none');
  }
  else {
    form.classList.add('d-none');
    errorBox.classList.remove('d-none');
  }
}

In the registerUser function, we check the validity of the email input using a RegEx function (validateEmail). If the email is invalid, we prompt the user to try again. Once we have validated the email, we call the fetch method to send a POST request to our Netlify function which is available at /.netlify/functions/index with a payload object containing the user’s email.

Based on the response, we show a success alert to the user otherwise we show an error alert.

Follow along with the code in the GitHub project with commit cd9791b.

Getting the Mailgun credentials

Getting emails in our database is good, but not enough, because we don’t know how we are going to use them. So, the final step is to send a confirmation email to a subscriber when they sign up.

We are not going to send a message immediately after a user signs up. Instead, we will set up a method to fetch the email signups in the last 30 minutes, then send the email. Adding a delay to the auto-generated email makes the welcome message feel a bit more personal, I think.

We’re using Mailgun to send, but again, we could really use any email service provider with an API. Let’s visit the Mailgun dashboard and, from the sidebar, go to the Settings → API Keys screen.

Showing the Mailgun API security screen. The page has a white background with a dark blue left sidebar that contains navigation. The page displays the private API key, the public validation key, and the HTTP web hook signing key.
We want the “Private API key.”

Let’s copy the Private API key and add it to the .env file as:

MAILGUN_API_KEY=<your Mailgun api key>

Every email needs to come from a sending address, so one more thing we need is the Mailgun domain from which the emails are sent. To get our Mailgun domain, we need to go to the Sending → Domains screen.

The Mailgun domains screen showing a table with one row that contains a sandbox URL with a series of statistics.
Mailgun offers a sandbox domain for testing.

Let’s copy our Mailgun sandbox domain and add it to the .env file as:

MAILGUN_DOMAIN=<your Mailgun domain>

Sending a confrimation email

Before we get into writing our Netlify function for sending an email confirmation, we need to install the [mailgun-js](https://github.com/mailgun/mailgun-js) npm package, which is an official Mailgun JavaScript SDK for using the Mailgun API:

$ npm install mailgun-js --save

We are using the /.netlify/functions/index endpoint for sending welcome emails. So, in the functions directory, let’s create a new a welcome.js file and add the following code:

const { Client, LogLevel } = require('@notionhq/client');
const mailgun = require('mailgun-js');

const {
  NOTION_API_TOKEN,
  NOTION_DATABASE_ID,
  MAILGUN_API_KEY,
  MAILGUN_DOMAIN,
} = process.env;

async function fetchNewSignups() {
  // Initialize notion client
  const notion = new Client({
    auth: NOTION_API_TOKEN,
    logLevel: LogLevel.DEBUG,
  });

  // Create a datetime that is 30 mins earlier than the current time
  let fetchAfterDate = new Date();
  fetchAfterDate.setMinutes(fetchAfterDate.getMinutes() - 30);

  // Query the database
  // and fetch only entries created in the last 30 mins
  const response = await notion.databases.query({
    database_id: NOTION_DATABASE_ID,
    filter: {
      or: [
        {
          property: 'Added On',
          date: {
            after: fetchAfterDate,
          },
        },
      ],
    },
  });

  const emails = response.results.map((entry) => entry.properties.Email.title[0].plain_text);

  return emails;
}

async function sendWelcomeEmail(to) {
  const mg = mailgun({ apiKey: MAILGUN_API_KEY, domain: MAILGUN_DOMAIN });

  const data = {
    from: `Ravgeet Dhillon <postmaster@${MAILGUN_DOMAIN}>`,
    to: to,
    subject: 'Thank you for subscribing',
    text: "Thank you for subscribing to my newsletter. I'll be sending daily tips related to JavScript.",
  };

  await mg.messages().send(data);
}

module.exports.handler = async function (event, context) {
  // Check the request method
  if (event.httpMethod != 'POST') {
    return { statusCode: 405, body: 'Method not allowed' };
  }

  const emails = await fetchNewSignups();

  emails.forEach(async (email) => {
    await sendWelcomeEmail(email);
  });

  return { statusCode: 200, body: 'ok' };
};

The above code has two main functions which we need to be understood. First, we have a fetchNewSignups function. We use the Notion SDK client to fetch the entries in our Notion database. We have used a filter to fetch only those emails which were added in the last 30 minutes. Once we get a response from the Notion API, we loop over the response and map the email into an emails array.

Second, we have a sendWelcomeEmail function. This function is used to send an email to the new subscriber via Mailgun API.

To bring everything together, we loop over the new emails in the module.exports.handler function and send a welcome email to each new email.

This function is available at localhost:8888/.netlify/functions/welcome.

Follow along with the code in the GitHub project with commit b802f93.

Let’s test this out!

Now that our project is ready, the first thing we need to do is to test the form and see whether the email is stored in our Notion database. Let’s go to localhost:8888 and enter a valid email address.

Perfect! We got the success message. Now let’s head over to our Notion database to see if the email address was captured.

Awesome, it’s there! We can also see that the Added On field has also been auto-filled by Notion, which is exactly what we want.

Next, let’s send a POST request to localhost:8888/.netlify/functions/welcome from Postman and check our inbox for the subscription confirmation message.

Woah! We have received the welcome email for subscribing to the newsletter.

Not seeing the email in your inbox? Make sure to check your spam folder.

What’s next?

The next step from here would be to set up a script that runs every 30 minutes and calls the welcome endpoint. As of now, Netlify doesn’t provide any way to run CRON jobs. So, we can set up GitHub Actions to handle it.

Also, we can secure the welcome endpoint using security mechanisms like a simple password or a JWT token. This will prevent anyone on the Internet from calling the welcome endpoint and sending tons of spam to our subscribers.

So, there we have it! We successfully implemented a Jamstack way to collect emails for a newsletter. The biggest advantage of doing something like this is that we can learn a lot about different technologies at once. We wired together services and APIs that collect email addresses, validate submissions, post to databases, and even send emails. It’s pretty cool that we can do so much with relatively so little.

I hope you enjoyed reading and learning something from this article as much as I enjoyed writing it for you. Let me know in the comments how you used this method for your own benefit. Happy coding!


Collecting Email Signups With the Notion API originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/collecting-email-signups-with-the-notion-api/feed/ 12 352211
WordPress Admin Warnings in the Block Editor https://css-tricks.com/wordpress-admin-warnings-in-the-block-editor/ https://css-tricks.com/wordpress-admin-warnings-in-the-block-editor/#comments Fri, 16 Jul 2021 20:27:46 +0000 https://css-tricks.com/?p=344217 We sent out an email the other week that ultimately had a <video> in the HTML markup. We send the newsletter by creating it here in the WordPress block editor, which is fetched through RSS-to-Mailchimp. Mailchimp dutifully sent it out, …


WordPress Admin Warnings in the Block Editor originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
We sent out an email the other week that ultimately had a <video> in the HTML markup. We send the newsletter by creating it here in the WordPress block editor, which is fetched through RSS-to-Mailchimp. Mailchimp dutifully sent it out, but the HTML was such that it totally borked the layout. This lead to some charming totally fair emails like this:

This email looks like trash in thunderbird, just giving a heads up.

You actually can send <video> in HTML email, but our system just isn’t set up for it. It requires some fancy dancing CSS (e.g. hiding it for non-supporting users with a fallback, and detecting support is super tricky, etc.) and HTML (e.g. making sure the width/height attributes are small-screen friendly). We could do it, but I don’t think it’s worth it for the handful of times we would want to do it.

So instead, to prevent us from doing it again, I used (drumroll)…. CSS.

I have some CSS that gets loaded in the admin area only when the block editor is loaded, which is in a functionality plugin:

wp_register_style(
  'css-tricks-code-block-editor-css',
  plugins_url('location/of/styles.css', dirname( __FILE__ )),
  array('wp-edit-blocks'),
  filemtime( plugin_dir_path(__DIR__) . 'location/of/styles.css')
);

I can put anything I want in that CSS file and it will effect styles of the block editor but nothing on the public front end of the site.

I also wanted to scope this CSS only to the newsletters page. Fortunately, WordPress has body classes in the editor as well. We have a Custom Post Type for newsletters, and that expresses itself as a class here:

So I chuck these styles in:

/* Warn about videos in newsletters */
.post-type-newsletters .wp-block-video {
  border: 5px solid red;
}
.post-type-newsletters .wp-block-video::before {
  content: "WARNING: NO VIDEOS IN EMAILS";
  display: block;
  color: red;
}

And boom, I have styles that warn about this problem before it happens again:


WordPress Admin Warnings in the Block Editor originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/wordpress-admin-warnings-in-the-block-editor/feed/ 1 344217
Can I Email… https://css-tricks.com/can-i-email/ https://css-tricks.com/can-i-email/#comments Fri, 07 May 2021 02:38:56 +0000 https://css-tricks.com/?p=339822 While I’m 85% certain you’ve seen and used Can I Use…, I bet there is only a 13% chance that you’ve seen and used Can I Email…. It’s the same vibe—detailed support information for web platform features—except instead …


Can I Email… originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
While I’m 85% certain you’ve seen and used Can I Use…, I bet there is only a 13% chance that you’ve seen and used Can I Email…. It’s the same vibe—detailed support information for web platform features—except instead of support information for web browsers, it is email clients. Campaign Monitor has maintained a guide for a long time as well, but I admit I like the design style pioneered by Can I Use….

HTML email is often joked about in how you have to code for it in such an antiquated way (<table> tags galore!) but that’s perhaps not a fair shake. Kevin Mandeville talked about how he used CSS grid (not kidding) in an email back in 2017:

Our Apple Mail audience at Litmus is approximately 30%, so a good portion of our subscriber base is able to see the grid desktop layout.

Where CSS Grid isn’t supported (and for device/window widths of less than 850 pixels), we fell back to a one-column layout.

Just like websites, right? They don’t have to look the same everywhere, as long as the experience is acceptable everywhere.

Me, I don’t do nearly as as much HTML email work as I do for-web-browsers work, but I do some! For example, the newsletter for CSS-Tricks is an RSS feed that feeds a MailChimp template. The email we send out to announce new shows for ShopTalk is similar. Both of those are pretty simple MailChimp templates that are customized with a bit of CSS.

But the most direct CSSin’ I do with HTML email is the templates for CodePen emails. We have all sorts of them, from totally custom templates, to special templates for The Spark and Challenges and, of course, transactional emails.

Those are all entirely from-scratch email templates. I’s very nice to know what kind of CSS features I can count on using. For example, I was surprised by how well flexbox is supported in email.

It’s always worth thinking about fallbacks. There is nothing stopping you from creating an email that is completely laid out with CSS grid. Some email clients will support it, and some won’t. When it is supported, a fancy layout happens. When it is not supported, assuming you leave the source order intelligible, you just get a column of blocks (which is what most emails are anyway) and should be perfectly workable.

Progressive enhancement is almost more straightforward in email where there is rarely any functionality to be concerned with.

To Shared LinkPermalink on CSS-Tricks


Can I Email… originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/can-i-email/feed/ 2 339822
The Ultimate Guide to Dark Mode for Email Marketers https://css-tricks.com/the-ultimate-guide-to-dark-mode-for-email-marketers/ https://css-tricks.com/the-ultimate-guide-to-dark-mode-for-email-marketers/#comments Tue, 07 Jan 2020 21:43:55 +0000 https://css-tricks.com/?p=300872 On the regular web (I suppose) we handle “dark mode” with the CSS prefers-color-scheme media query. But, and to nobody’s surprise, it’s way weirder in the land of HTML email. The weirdness is that across different email clients, they handle …


The Ultimate Guide to Dark Mode for Email Marketers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
On the regular web (I suppose) we handle “dark mode” with the CSS prefers-color-scheme media query. But, and to nobody’s surprise, it’s way weirder in the land of HTML email. The weirdness is that across different email clients, they handle the dark mode thing differently, starting with the fact that the email client itself might have its own toggle for dark mode.

Say that toggle has dark mode activated. There are three things that might happen:

  1. The UI of the app goes dark mode, but it leaves the email alone (e.g. Apple Mail).
  2. It tries to apply dark mode to your emails as well, but only when it detects areas that are light. Those areas become dark while leaving dark areas alone (e.g. Outlook.com).
  3. It goes full-bore and force-inverts email colors (e.g. Gmail app on iOS 13).

That last one is wacky-town. As Alice Li says:

This is the most invasive color scheme: it not only inverts the areas with light backgrounds but impacts dark backgrounds as well. So if you already designed your emails to have a dark theme, this scheme will ironically force them to become light.
Emphasis hers.

To Shared LinkPermalink on CSS-Tricks


The Ultimate Guide to Dark Mode for Email Marketers originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/the-ultimate-guide-to-dark-mode-for-email-marketers/feed/ 1 300872
Netlify Functions for Sending Emails https://css-tricks.com/netlify-functions-for-sending-emails/ https://css-tricks.com/netlify-functions-for-sending-emails/#comments Tue, 23 Apr 2019 14:26:58 +0000 http://css-tricks.com/?p=286226 (This is a sponsored post.)

Let’s say you’re rocking a JAMstack-style site (no server-side languages in use), but you want to do something rather dynamic like send an email. Not a problem! That’s the whole point of …


Netlify Functions for Sending Emails originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
(This is a sponsored post.)

Let’s say you’re rocking a JAMstack-style site (no server-side languages in use), but you want to do something rather dynamic like send an email. Not a problem! That’s the whole point of JAMstack. It’s not just static hosting. It’s that plus doing anything else you wanna do through JavaScript and APIs.

Here’s the setup: You need a service to help you send the email. Let’s just pick Sparkpost out of a hat. There are a number of them, and I’ll leave comparing their features and pricing to you, as we’re doing something extremely basic and low-volume here. To send an email with Sparkpost, you hit their API with your API key, provide information about the email you want to send, and Sparkpost sends it.

So, you’ll need to run a little server-side code to protect your API key during the API request. Where can you run that code? A Lambda is perfect for that (aka a serverless function or cloud function). There are lots of services to help you run these, but none are easier than Netlify, where you might be hosting your site anyway.

Get Sparkpost ready

I signed up for Sparkpost and made sure my account was all set up and verified. The dashboard there will give you an API key:

Toss that API Key into Netlify

Part of protecting our API key is making sure it’s only used in server-side code, but also that we keep it out of our Git repository. Netlify has environment variables that expose it to functions as needed, so we’ll plop it there:

Let’s spin up Netlify Dev, as that’ll make this easy to work with

Netlify Dev is a magical little tool that does stuff like run our static site generator for us. For the site I’m working on, I use Eleventy and Netlify Dev auto-detects and auto-runs it, which is super neat. But more importantly, for us, it gives us a local URL that runs our functions for testing.

Once it’s all installed, running it should look like this:

In the terminal screenshot above, it shows the website itself being spun up at localhost:8080, but it also says:

◈ Lambda server is listening on 59629

That’ll be very useful in a moment when we’re writing and testing our new function — which, by the way, we can scaffold out if we’d like. For example:

netlify functions:create --name hello-world

From there, it will ask some questions and then make a function. Pretty useful to get started quickly. We’ll cover writing that function in a moment, but first, let’s use this…

Sparkpost has their own Node lib

Sparkpost has an API, of course, for sending these emails. We could look at those docs and learn how to hit their URL endpoints with the correct data.

But things get even easier with their Node.js bindings. Let’s get this set up by creating all the folders and files we’ll need:

/project
   ... your entire website or whatever ...
   /functions/
      /send-email/
         package.json
         send-email.js

All we need the package.json file for is to yank in the Sparkpost library, so npm install sparkpost --save-dev will do the trick there.

Then the send-email.js imports that lib and uses it:

const SparkPost = require('sparkpost');
const client = new SparkPost(process.env.SPARKPOST);

exports.handler = function(event, context, callback) {
  client.transmissions
    .send({
      content: {
        from: 'chris@css-tricks.com',
        subject: 'Hello, World!',
        html:
          "<html><body><p>My cool email.</p></body></html>"
      },
    recipients: [{ address: 'chriscoyier@gmail.com' }]
  });
}

You’ll want to look at their docs for error handling and whatnot. Again, we’ve just chosen Sparkpost out of a hat here. Any email sending service will have an API and helper code for popular languages.

Notice line 2! That’s where we need the API key, and we don’t need to hard-code it because Netlify Dev is so darn fancy that it will connect to Netlify and let us use the environment variable from there.

Test the function

When Netlify Dev is running, our Lamba functions have that special port they are running. We’ll be able to have a URL like this to run the function:

http://localhost:34567/.netlify/functions/send-email

This function is set up to run when it’s hit, so we could simply visit that in a browser to run it.

Testing

Maybe you’ll POST to this URL. Maybe you’ll send the body of the email. Maybe you’ll send the recipient’s email address. It would be nice to have a testing environment for all of this.

Well, we can console.log() stuff and see it in the terminal, so that’s always handy. Plus we can write our functions to return whatever, and we could look at those responses in some kind of API testing tool, like Postman or Insomnia.

It works!

I’ll leave it to you to get fancy with it ;)


Netlify Functions for Sending Emails originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/netlify-functions-for-sending-emails/feed/ 6 286226
A Gutenburg-Powered Newsletter https://css-tricks.com/a-gutenburg-powered-newsletter/ https://css-tricks.com/a-gutenburg-powered-newsletter/#comments Thu, 28 Mar 2019 12:42:52 +0000 http://css-tricks.com/?p=285445 I like Gutenberg, the new WordPress editor. I’m not oblivious to all the conversation around accessibility, UX, and readiness, but I know how hard it is to ship software and I’m glad WordPress got it out the door. Now it …


A Gutenburg-Powered Newsletter originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
I like Gutenberg, the new WordPress editor. I’m not oblivious to all the conversation around accessibility, UX, and readiness, but I know how hard it is to ship software and I’m glad WordPress got it out the door. Now it can evolve for the better.

I see a lot of benefit to block-based editors. Some of my favorite editors that I use every day, Notion and Dropbox Paper, are block-based in their own ways and I find it effective. In the CMS context, even moreso. Add the fact that these aren’t just souped-up text blocks, but can be anything! Every block is it’s own little configurable world, outputting anything it needs to.

I’m using Gutenberg on a number of sites, including my personal site and my rambling email site, where the content is pretty basic. On a decade+ old website like CSS-Tricks though, we need to baby step it. One of our first steps was moving our newsletter authoring into a Gutenberg setup. Here’s how we’re doing that.

Gutenberg Ramp

Gutenberg Ramp is a plugin with the purpose of turning Gutenberg on for some areas and not for others. In our case, I wanted to turn on Gutenberg just for newsletters, which is a Custom Post Type on our site. With the plugin installed and activated, I can do this now in our functions.php:

if (function_exists('gutenberg_ramp_load_gutenberg')) {
  gutenberg_ramp_load_gutenberg(['post_types' => [ 'newsletters' ]]);
}

Which works great:

Classic editor for posts, Gutenberg for the Newsletters Custom Post Type

We already have 100+ newsletters in there, so I was hoping to only flip on Gutenberg over a certain date or ID, but I haven’t quite gotten there yet. I did open an issue.

What we were doing before: pasting in HTML email gibberish

We ultimately send out the email from MailChimp. So when we first started hand-crafting our email newsletter, we made a template in MailChimp and did our authoring right in MailChimp:

The MailChimp Editor

Nothing terrible about that, I just much prefer when we keep the clean, authored content in our own database. Even the old way, we ultimately did get it into our database, but we did it in a rather janky way. After sending out the email, we’d take the HTML output from MailChimp and copy-paste dump it into our Newsletter Custom Post Type.

That’s good in a way: we have the content! But the content is so junked up we can basically never do anything with it other than display it in an <iframe> as the content is 100% bundled up in HTML email gibberish.

Now we can author cleanly in Gutenberg

I’d argue that the writing experience here is similar (MailChimp is kind of a block editor too), but nicer than doing it directly in MailChimp. It’s so fast to make headers, lists, blockquotes, separators, drag and drop images… blocks that are the staple of our newsletter.

Displaying the newsletter

I like having a permanent URL for each edition of the newsletter. I like that the delivery mechanism is email primarily, but ultimately these are written words that I’d like to be a part of the site. That means if people don’t like email, they can still read it. There is SEO value. I can link to them as needed. It just feels right for a site like ours that is a publication.

Now that we’re authoring right on the site, I can output <?php the_content() ?> in a WordPress loop just like any other post or page and get clean output.

But… we have that “old” vs. “new” problem in that old newsletters are HTML dumps, and new newsletters are Gutenberg. Fortunately this wasn’t too big of a problem, as I know exactly when the switch happened, so I can display them in different ways according to the ID. In my `single-newsletters.php`:

<?php if (get_the_ID() > 283082) { ?>

  <main class="single-newsletter on-light">
    <article class="article-content">
      <h1>CSS-Tricks Newsletter #<?php the_title(); ?></h1>
      <?php the_content() ?>
    </article>
  </main>
  
<?php } else { // Classic Mailchimp HTML dump ?>

  <div class="newsletter-iframe-wrap">
    <iframe class="newsletter-iframe" srcdoc="<?php echo htmlspecialchars(get_the_content()); ?>"></iframe>
  </div>

<?php } ?>

At the moment, the primary way we display the newsletters is in a little faux phone UI on the newsletters page, and it handles both just fine:

Old and new newsletters display equally well, it’s just the old newsletters need to be iframed and I don’t have as much design control.

So how do they actually get sent out?

Since we aren’t creating the newsletters inside MailChimp anymore, did we have to find another way to send them out? Nope! MailChimp can send out a newsletter based on an RSS feed.

And WordPress is great at coughing up RSS feeds for Custom Post Yypes. You can do…

/feed/?post_type=your-custom-post-type

But… for us, I wanted to make sure that any of those old HTML dump emails never ended up in this RSS feed, so that the new MailChimp RSS feed would never see them an accidentally send them. So I ended up making a special Page Template that outputs a custom RSS feed. I figured that would give us ultimate control over it if we ever need it for even more things.

<?php
/*
Template Name: RSS Newsletterss
*/

the_post();
$id = get_post_meta($post->ID, 'parent_page_feed_id', true);

$args = array(
  'showposts' => 5,
  'post_type'  => 'newsletters',
  'post_status' => 'publish',
  'date_query' => array(
     array(
      'after'     => 'February 19th, 2019'
    )
  )
);

$posts = query_posts($args);

header('Content-Type: '.feed_content_type('rss-http').'; charset='.get_option('blog_charset'), true);
echo '<?xml version="1.0" encoding="'.get_option('blog_charset').'"?'.'>';
?>

<rss version="2.0"
  xmlns:content="http://purl.org/rss/1.0/modules/content/"
  xmlns:wfw="http://wellformedweb.org/CommentAPI/"
  xmlns:dc="http://purl.org/dc/elements/1.1/"
  xmlns:atom="http://www.w3.org/2005/Atom"
  xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
  <?php do_action('rss2_ns'); ?>>

<channel>
  <title>CSS-Tricks Newsletters RSS Feed</title>
  <atom:link href="<?php self_link(); ?>" rel="self" type="application/rss+xml" />
  <link><?php bloginfo_rss('url') ?></link>
  <description><?php bloginfo_rss("description") ?></description>
  <lastBuildDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_lastpostmodified('GMT'), false); ?></lastBuildDate>
  <language><?php echo get_option('rss_language'); ?></language>
  <sy:updatePeriod><?php echo apply_filters( 'rss_update_period', 'hourly' ); ?></sy:updatePeriod>
  <sy:updateFrequency><?php echo apply_filters( 'rss_update_frequency', '1' ); ?></sy:updateFrequency>

  <?php do_action('rss2_head'); ?>

  <?php while( have_posts()) : the_post(); ?>

    <item>
      <title><?php the_title_rss(); ?></title>
      <link><?php the_permalink_rss(); ?></link>
      <comments><?php comments_link(); ?></comments>
      <pubDate><?php echo mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true), false); ?></pubDate>
      <dc:creator><?php the_author(); ?></dc:creator>
  <?php the_category_rss(); ?>
      <guid isPermaLink="false"><?php the_guid(); ?></guid>

      <description><![CDATA[<?php the_excerpt_rss(); ?>]]></description>

      <content:encoded><![CDATA[<?php the_content(); ?>]]></content:encoded>

      <wfw:commentRss><?php echo get_post_comments_feed_link(); ?></wfw:commentRss>
      <slash:comments><?php echo get_comments_number(); ?></slash:comments>

      <?php rss_enclosure(); ?>
      <?php do_action('rss2_item'); ?>

    </item>

  <?php endwhile; ?>

</channel>

</rss>

Styling…

With a MailChimp RSS campaign, you still have control over the outside template like any other campaign:

But then content from the feed just kinda gets dumped in there. Fortunately, their preview tool does go grab content for you so you can actually see what it will look like:

And then you can style that by injecting a <style> block into the editor area yourself.

That gives us all the design control we need over the email, and it’s nicely independent of how we might choose to style it on the site itself.


A Gutenburg-Powered Newsletter originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/a-gutenburg-powered-newsletter/feed/ 3 285445
All About mailto: Links https://css-tricks.com/all-about-mailto-links/ https://css-tricks.com/all-about-mailto-links/#comments Fri, 22 Mar 2019 18:45:00 +0000 http://css-tricks.com/?p=284342 You can make a garden variety anchor link (<a>) open up a new email. Let’s take a little journey into this feature. It’s pretty easy to use, but as with anything web, there are lots of things to …


All About mailto: Links originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
You can make a garden variety anchor link (<a>) open up a new email. Let’s take a little journey into this feature. It’s pretty easy to use, but as with anything web, there are lots of things to consider.

The basic functionality

<a href="mailto:someone@yoursite.com">Email Us</a>

It works!

But we immediately run into a handful of UX issues. One of them is that clicking that link surprises some people in a way they don’t like. Sort of the same way clicking on a link to a PDF opens a file instead of a web page. Le sigh. We’ll get to that in a bit.

“Open in new tab” sometimes does matter.

If a user has their default mail client (e.g. Outlook, Apple Mail, etc.) set up to be a native app, it doesn’t really matter. They click a mailto: link, that application opens up, a new email is created, and it behaves the same whether you’ve attempted to open that link in a new tab or not.

But if a user has a browser-based email client set up, it does matter. For example, you can allow Gmail to be your default email handler on Chrome. In that case, the link behaves like any other link, in that if you don’t open in a new tab, the page will redirect to Gmail.

I’m a little on the fence about it. I’ve weighed in on opening links in new tabs before, but not specifically about opening emails. I’d say I lean a bit toward using target="_blank" on mail links, despite my feelings on using it in other scenarios.

<a href="mailto:someone@yoursite.com" target="_blank" rel="noopener noreferrer">Email Us</a>

Adding a subject and body

This is somewhat rare to see for some reason, but mailto: links can define the email subject and body content as well. They are just query parameters!

mailto:chriscoyier@gmail.com?subject=Important!&body=Hi.

Add copy and blind copy support

You can send to multiple email addresses, and even carbon copy (CC), and blind carbon copy (BCC) people on the email. The trick is more query parameters and comma-separating the email addresses.

mailto:someone@yoursite.com?cc=someoneelse@theirsite.com,another@thatsite.com,me@mysite.com&bcc=lastperson@theirsite.com

This site is awful handy

mailtolink.me will help generate email links.

Use a <form> to let people craft the email first

I’m not sure how useful this is, but it’s an interesting curiosity that you can make a <form> do a GET, which is basically a redirect to a URL — and that URL can be in the mailto: format with query params populated by the inputs! It can even open in a new tab.

See the Pen
Use a <form> to make an email
by Chris Coyier (@chriscoyier)
on CodePen.

People don’t like surprises

Because mailto: links are valid anchor links like any other, they are typically styled exactly the same. But clicking them clearly produces very different results. It may be worthwhile to indicate mailto: links in a special way.

If you use an actual email address as the link, that’s probably a good indication:

<a href="mailto:chriscoyier@gmail.com">chriscoyier@gmail.com</a>

Or you could use CSS to help explain with a little emoji story:

a[href^="mailto:"]::after {
  content: " (&#x1f4e8;&#x2197;&#xfe0f;)";
}

If you really dislike mailto: links, there is a browser extension for you.

https://ihatemailto.com/

I dig how it doesn’t just block them, but copies the email address to your clipboard and tells you that’s what it did.


All About mailto: Links originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/all-about-mailto-links/feed/ 27 284342
Choosing a Responsive Email Framework: MJML vs. Foundation for Emails https://css-tricks.com/choosing-a-responsive-email-framework%e2%80%8amjml-vs-foundation-for-emails/ https://css-tricks.com/choosing-a-responsive-email-framework%e2%80%8amjml-vs-foundation-for-emails/#comments Fri, 20 Apr 2018 13:58:58 +0000 http://css-tricks.com/?p=269999 Implementing responsive email design can be a bit of a drag. Building responsive emails isn’t simple at all, it is like taking a time machine back to 2001 when we were all coding website layouts in tables using Dreamweaver and …


Choosing a Responsive Email Framework: MJML vs. Foundation for Emails originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Implementing responsive email design can be a bit of a drag. Building responsive emails isn’t simple at all, it is like taking a time machine back to 2001 when we were all coding website layouts in tables using Dreamweaver and Fireworks.

But there’s hope! We have tools available that can make building email much easier and more like coding a modern site. Let’s take a look at a couple of different frameworks that set out to simplify things for us.

First, the Situation

You have to be compatible with lots of old email clients, many of which don’t even support the most basic web standards (floats, anyone?). You also have to deal with all sorts of webmail clients which, for security or technical reasons, have made their own opinionated choices about how to display your precious email.

Furthermore, now emails are read from different devices, with very different viewports and requirements.

The best solution, as is often the case, would be to keep things simple and stick to basic one-column designs, using multiple columns only for menus or simple interface elements of known width. You can produce great, effective designs using only one column, after all.

However end-users and clients, who are used to the “normal” browser-based web, may hold their email-viewing experience to the same high standards they do for viewing web pages in terms of graphics and responsiveness. Therefore, complex designs are expected: multiple columns, different behaviors on mobile devices as opposed to desktops, lots of images, etc., all of which have to be implemented consistently and pixel-perfect across all email clients. What options are available to make all that happen?

Option 1: Build From Scratch

One option you could choose is coding each email by hand, keeping it simple, and testing it while you go. This is a viable option only if:

  1. You have a very simple design to implement.
  2. You have direct control of the design, so you can eventually simplify things if you can’t come out with a consistent solution for what you intended to do.
  3. You can accept some degree of degradation on some older clients: you don’t mind if your email won’t look exactly the same (or even plain bad) in old Outlook clients, for example.
  4. You have a lot of time on your hands.

Obviously, you need to test your design heavily. Campaign Monitor has a great CSS guide you can reference during the build process and is sort of like Can I Use, but for email. After that, I recommend using automated test suites like Litmus or Email on Acid. Both offer you a complete testing suite and previews of how your email will look like on a huge variety of email clients. Expect some surprises, though, because often the same design does not look correct even on the same email client, if viewed on different browsers, or different operating systems. Fonts will render differently, margins will change, and so on.

Screenshot of the same email design tested on different devices on Email on Acid.

Option 2: Use a Boilerplate Template

Another option is to use one of the various boilerplates available, like Sean Powelll’s, which you can find here. Boilerplates already address many of the quirks of different email clients and platforms. This is sensible if:

  1. You are working alone, or on a small team.
  2. You have lots of experience, so you already know most of the quirks of email formatting because you’ve met them before.
  3. You have set up your own tools for managing components (for different newsletters which share some pieces of design), inlining styles (and yes, you should keep inlining your styles if your emails target an international audience), and have some kind of development toolkit in place (be it Gulp, Grunt or something similar) which will automate all of that for you.
  4. You have the kind of approach where you’d like to control everything in the code you produce and don’t like to rely on external tools.
  5. You prefer to solve your own bugs instead of having to solve possible bugs caused by the tool you are using.

Option 3: Use a Framework

However, if any of the following points are valid for you:

  1. You have to produce a lot of email templates with shared components.
  2. The job has to be carried out by a team of developers, who might change and/or have a variable degree of proficiency and experience with email implementation.
  3. You have little or no control on the original design.

…then you will likely benefit a lot from using a framework.

Currently, two of the most interesting and popular frameworks available are MJML and Foundation for Emails. The biggest advantages in using either framework is that they have already solved for you most of the quirks of email clients. They also provide you with an established workflow you can follow, both alone and as a team. They also handle responsive design very well, albeit differently from one another.

Let’s look at an overview of both frameworks and compare the best use cases for each before drawing some conclusions.

MJML

MJML is a project that was created internally by Mailjet, a company specializing in email marketing tools. It was then open-sourced. It works with its own custom, HTML-like templating language, using its own tags. For example:

<mj-text>Your text here</mj-text>

When you compile the final code, MJML will convert their tags into HTML for everything from tables to custom components they have created for you, all using its internal engine. It takes out the heavy lifting for creating complex markup and it’s all been tested.

MJML has a set of standard components. They include sections, columns, groups, buttons, images, social links (which are very easy to create), tables, accordions, etc. They even include a pre-styled carousel, which should work in most clients. All of these components translate well into responsive emails, apart from the “invoice” component which I could not get to work in my tests. All of these components have parameters you can pass in your code to customize their appearance.

For example, the social links component allows you to stack icons vertically and horizontally, and to choose background colors for the related icons. There are actually a lot more parameters you can play with, all with the intent of allowing for greater flexibility. Even the logo image files are already included in the package, which is a great plus.

Here’s a preview of a simple configuration of the social links component:

Screenshot from the MJML website.

You can also create your own custom components, or use components created by the community. There is just one community component available at the moment, however.

MJML handles responsiveness automatically, meaning that components will switch from multi-column (more items in the same row) to single-column (items are put one under the other instead of side-by-side) without any active intervention from the developer. This is a very flexible solution, and works fine in most cases, but it gives the developer a little less control over what happens exactly in the template. As the docs mention, it’s worth keeping mind that:

For aesthetics purposes, MJML currently supports a maximum of 4 columns per section.

This is most likely not only an aesthetic preference but also about limiting possible drawbacks of having too many columns. The more columns you have, the more unpredictable the output, I guess.

How to Work With MJML

MJML can work as a command line tool, which you can install with npm, and output your files locally, with commands like:

$ mjml -r index.mjml -o index.html

This can be integrated in your build procedure via Gulp or the like, and in your development work by using a watch command, which will update your preview every time you save:

$ mjml --watch index.mjml -o index.html

MJML has plugins for Atom and Sublime Text. In Atom, it even supplies a real-time preview of your layout, which can be regenerated on every save. I haven’t tried it personally, but it seems very interesting:

Image from Atom.io

MJML also has its own simple desktop app, and it’s free. You can set up your code and components, have it build your designs for you, and get a real-time preview of the results, both for mobile and for desktop. I find that it works pretty well on Ubuntu, but the only drawback I’ve found is that you should never, never, never open your files with another editor while they’re open on the app, because the app crashes and the content of the file gets lost.

Here are some screenshots of the previews at work:

Desktop preview of email
Mobile preview of email

The app can also be integrated with a free Mailjet account, which allows you to send test emails immediately to yourself. This is very handy to quickly check problematic clients if you have them available directly. (I would suggest taking out that old Windows machine you have in the storage room to check things in Outlook, and to do it as often as possible.) However, I would still recommend using either Litmus or Email on Acid to test your emails cross-client before deploying them because you can never be too careful and email standards can change just like they do in browsers.

Overall, I have found MJML very easy to use. However, when I tried to make a pixel-perfect template which was identical to the design our client requested, I had some difficulties dealing with custom margins for some images. Not all of the component parameters available worked as expected from their description in the documentation. In particular, I had some problems customizing image margins and padding between desktop and mobile.

Advantages

  • Pre-built components
  • Integration with Mailjet
  • Easy to use, with instant preview of your work (on Atom and Desktop App)

Disadvantages

  • A bit less reliable than Foundation for Emails if you have to do pixel-perfect designs
  • Some components have parameters that don’t work as expected
  • Desktop App not perfectly stable
  • Does not come with a structured set of folders for your content (see Foundation below)

Foundation for Emails

Foundation for Emails (formerly known as Ink — insert obligatory Prince quote here) is a framework by Zurb, the same folks who brought us the responsive front-end framework, Foundation for Sites.

When you download the Starter Kit you get a full development environment, complete with Node.js commands to run your project. It will setup a Node routine and even open your browser to give you an immediate preview of your work.

The files you have to use are already organized in folders and subfolders, with a clear indication of where to put your stuff. For example, it has directories specifically for partials, templates and images. I find this feature very important, because it is very easy to end up using different folders when you work on a team, and this leads to a lot of lost time looking for stuff that isn’t where you expect it to be. Enforcing conventions is not a limitation; when you work in a team it is indispensable.

TFFKAI — The Framework Formerly Known As Ink

Foundation for Emails comes with a boilerplate template, which is the starting point for your code. It is fully annotated, so you know how to extend it with your code. It comes with SASS/SCSS support, which is very very handy for complex projects. It also comes with its own inliner, so you don’t have to worry about converting all your CSS (or SASS/SCSS) into inline styles.

There’s a template engine behind this framework called Inky. And, just like MJML, it has custom tags that will automatically convert to HTML when it’s compiled. There are tags like <container>, <row>, <column>, which will be used to build your grid. The grid is based on a 12-column system, which allows you to subdivide your layout very accurately. Why 12? Because it is divisible by 2, 3, 4 and 6, making it very easy to make a 2-column, 3-column, 4-column, or 6-column layout.

Foundation for Emails uses Panini to compile the code. Panini is a custom library which compiles HTML pages using layouts. It supports Handlebars syntax and there are several helpers you can use to customize the behavior of components depending on where they’re being used. You can also create your own helpers if you need to and set each template’s custom variables with custom data. This is very useful if you have several templates sharing the same components.

There are several pre-built email templates available you can download, which cover many of the standard use cases for email, like newsletters and announcements. There are also a few pre-built components (with their own custom tags), including buttons, menus and callouts (which, I have to admit, I don’t see a purpose for in emails, but never mind).

A code sample from a Foundation for Emails template.

The main difference between Foundation for Emails with MJML is that Foundation for Emails defaults to desktop view, then scales for smaller screens. According to the docs, this is because many desktop clients do not support media queries and defaulting to the large screen layout makes it more compliant across email clients. That said, it only manages one breakpoint. You create the desktop version and the mobile version, and the mobile version switches under a certain number of pixels, which can be configured.

You can decide whether some components will be visible only on large or small screens using handy pre-defined classes like .hide-for-large and .show-for-large (although .hide-for-large might not be supported by all clients). You can also decide how much space a column will take by using specific classes. For example, a class of .large-6 and .small-12 on a div will make a column that occupies half the screen on desktop and the whole screen width on mobile. This allows for very specific and predictable layout results.

A preview of the same e-mail template, developed with Foundation for Emails, on Outlook 2007 (left) and iPhoneX (right).

Foundation for Emails is a bit clunkier to use than MJML, in my opinion, but it does allow for much tighter control on the layout. That makes it ideal for projects where you need to reproduce pixel-perfect designs, with very specific differences between mobile and desktop layouts.

Advantages

  • A more precise control over end results
  • Pre-built templates
  • Sass support
  • Great documentation

Disadvantages

  • The project file size is heavy and takes a lot of disk space
  • A little less intuitive to use than MJML’s pre-defined parameters on components
  • Fewer components available for custom layouts

Conclusions

Producing email templates, even less than front-end development, is not an exact science. It requires a lot of trial and error and a LOT of testing. Whatever tool you use, if you need to support old clients, then you need to test the hell out of your layouts — especially if they have even the smallest degree of complexity. For example, if you have text that needs to sit beside an image, I recommend testing with content at different lengths and see what happens in all clients. If you have text that needs to overlap an image, it can be a bit of a nightmare.

The more complex the layout and the less control you have over the layout, then the more useful it is to use a framework over hand-coding your own emails, especially if the design is handed to you by a third party and has to be implemented as-is.

I wouldn’t say that one framework is better than the other and that’s not the point of this post. Rather, I would recommend MJML and Foundation for Emails for different use cases:

  • MJML for projects that have a quick turnaround and there is flexibility in the design.
  • Foundation for Emails for projects that require tighter control over the layout and where design is super specific.

Resources and Links


Choosing a Responsive Email Framework: MJML vs. Foundation for Emails originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/choosing-a-responsive-email-framework%e2%80%8amjml-vs-foundation-for-emails/feed/ 10 269999
On Paid Newsletters: An Interview With Adam Roberts of SitePoint’s Versioning https://css-tricks.com/on-paid-newsletters-an-interview-with-adam-roberts-of-sitepoints-versioning/ https://css-tricks.com/on-paid-newsletters-an-interview-with-adam-roberts-of-sitepoints-versioning/#comments Wed, 28 Mar 2018 13:09:50 +0000 http://css-tricks.com/?p=268329 You don’t often think of email as something you pay to get. If anything, most people would pay to get less of it. Of course, there are always emails you like to get and opt into on purpose. We have


On Paid Newsletters: An Interview With Adam Roberts of SitePoint’s Versioning originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
You don’t often think of email as something you pay to get. If anything, most people would pay to get less of it. Of course, there are always emails you like to get and opt into on purpose. We have a newsletter right here on CSS-Tricks that we really try to make worth reading. It’s free, like the vast majority of email newsletters. We hope it helps a bit with engagement and we make it worth doing financially by showing the occasional advertisement. It’s certainly not a full-time job.

I spoke with Adam Roberts who is trying to make it a full-time job by running SitePoint’s Versioning newsletter as a paid subscription. I don’t know much about this world, so I find it all pretty fascinating. I know Ann Friedman has a paid newsletter with a free variant. I know theSkimm is a free newsletter but has a paid membership that powers their app. I was told Bill Bishop made six figures on his first day going paid, which is wild. In the tech space, Ben Thompson’s Stratechery is a paid newsletter.

Let’s hear from Adam on how it’s doing it. I’ll ask questions as headers and the paragraph text is Adam.


So you’re doing it! Making the transition from a free, advertising-supported newsletter to a paid, subscriber-based newsletter. There is a lot to dig into here. Is the motivation a more direct and honest relationship with your readers?

Yep, it’s crazy! Versioning provides devs, designers and web people curated links aimed at making them more productive and up-to-date with the bleeding edge of their industry. I’ve done the newsletter for nearly four years and, up until now, it’s been a thing I squeeze in for an hour or two during my day, as a break from my actual job (most recently, head of content for the site). Now, it’s no longer being squeezed, and is my actual job! I can now focus entirely on making it something people find valuable. They’ll know that everything I include is there because I think it’ll make their lives, skills or knowledge better. I’ve always set a high standard for myself when it comes to what I include—never something I’m 50/50 on (unless it’s an emerging tech) and I never include something because we have a deal or something. Now, this is an actual formal thing. Ads were always a means to an end, now we have a better means, and hopefully a better end!

Is it a straight cut? Anyone who doesn’t subscribe for a fee will stop getting it and have no way to read it?

If you sign up as a paid member, you’ll get the daily newsletter. You’ll also get periodic members-only updates, like deep dives on an emerging subject, always-updated posts on important subjects, and media guides. If you sign up to receive free updates, you’ll get a weekly update plus other periodic free updates.

I’m sure there are financial concerns. Anyone in this position would be nervous that paid subscribers won’t match what was coming in from advertisers before. Is that a concern here? How in-depth did you get trying to figure out the economics of it? Is there potential that it’s even better business?

Given this is a SitePoint venture and not my own thing, we had to make sure it was worthwhile for subscribers and that the numbers were friendly! There’s definitely potential this will work better in a financial sense, while also be being better for subscribers—we wouldn’t be doing it otherwise!

Do you have a good sense of what your readers want from you? It seems to me Versioning is largely a link-dump, but with your hand-curation and light commentary. Did you come to that over time?

I have always had a fairly active reader base, with people dropping me a line via email or Twitter to thank me for something they liked. We also have the requisite creepy email analytics (e.g. opens and clicks), which help to spot trends and subjects to focus on or avoid. It’s a challenge to cover a few different subject areas well (like front-end and back-end development, design, etc.) but I think most readers working in a particular niche in our industry find it helpful to know what everyone else is up to. The world also evolves quickly—the first edition covered a jQuery library, for example. That’s not an area that’s stayed in the forefront of the news since! Mind you, the first edition also had a Star Wars link, so maybe some things do stay the same.

I struggle with even knowing what I want from a newsletter. Most days, give me some personality. I want news but I want to know why I should care and I want an expert to tell me. Then other days, I hate to say it, but I want less talk and more links. Cool story about a goat, but I’m here for the performance links (or whatever). Are you a newsletter connoisseur yourself? Are you writing a newsletter you wanna read?

I think if I ran into Versioning in the wild, I’d want to subscribe to it. I’m working to try to get the content balance right—providing the right stuff for people, plus commentary that’s enjoyable. The other day I had links to an article on understanding state in React (I think it was on some site called CCS-Tricks, am I spelling that right? 😉), an article on fake science gurus on Facebook, one on an Australian cyborg who tried to pay for a train with a chip in his hand, and the video for Warren G’s Regulate (an allusion to the likely response to the various Facebook crises).

I subscribe to so many newsletters, and they’re all different. I think consistency in each newsletter helps. If I was to drop the format and post a long, detailed screed about one subject, that would not go over well. My aim is to include one link that every reader wants to click. Often, that’s all you can handle as a reader, especially on mobile where the interface doesn’t make collecting tabs easy. That’s also why I include the destination domain in brackets next to every link—I don’t want people to end up somewhere they’re not expecting. Also, some sites (like the The New York Times, The New Yorker, and Wired) have limits on the number of free articles people can view. I don’t want people to accidentally run out of freebies because of me—I want them to realize how much they value a site and support it.

Do paid newsletters replace the traditional blog or do you see them complementing one another? We’ve obviously been using our newsletter to support the blog and vice versa, but I’m curious if adding a paid layer changes that relationship.

The formats have different, complementary strengths, and so I don’t think the paid layer necessarily changes this. Newsletters are good at highlighting particularly important things, putting them in context, and maybe taking a long view of a certain issue. Sites (or blogs) are good at adding interactive elements and keeping content up-to-date and accurate as things change.

In our case, one of the things our email platform, Substack, allows us to do is send a particular edition out as both a newsletter and a post. This means a member can access it wherever is best for them. It also means I can do things like send out an initial newsletter outlining a particular topic, then update the online version with new content. I will use this to produce updated, canonical posts for a particular subject or technology. And these formats can be either free to all, or only available to paid members. There’s a lot you can do with this level of flexibility, I’m sure I’m only scratching the surface. The key is to produce something worthwhile for an audience and the format is secondary.

What is it about newsletters that seems to be clicking with people lately? If someone asked you, hey, I have a ton to say about this general topic, and so I’m thinking of either starting a blog or a newsletter, would you say newsletter? Any SEO concerns there?

There is a backlash against the algorithmic tide. Instead of opening a feed and hoping for good content, why not find someone you trust, and whose opinion and taste you find interesting and useful, and sign up to consistently receive content from them. You’ll still get the “something new and cool” dopamine hit you would in a feed, but it’ll be more consistent and reliable. And they’re all separate entities; there’s no “if you followed this publication, maybe you should follow this other one” thing. And if you stop enjoying them, you can just unsubscribe.

Newsletters are intimate. Your inbox is your personal space, where you step back from the tumult and take stock of the stuff that you’ve decided matters most to you. That’s why spam and relentless, poorly-conceived marketing emails always feel like such a violation.

I think newsletters and podcasts are both growing in prominence for the same reasons. Both mediums reward consistency and reliability in format and topic, are built on personality, and have an intimate feel. Someone’s either talking into your ears for hours every week, or writing to you in your private space.

Speaking of concerns, SEO is a tricky one. Algorithms are part of the discussion here again. SitePoint has a pretty decent search footprint, but new and niche publications aren’t so lucky. I suspect there will be a mini-industry of newsletter curation services start to develop. I would actually love to be in that space.

Filter bubbles are another concern. Newsletters are another opportunity for people to only read the stuff they agree with. But it turns out algorithms and social networks aren’t so good at stopping that either!

I was very, very, very sad to see the end of the Awl (and the Hairpin). That was a site that was chock-full of amazing content that was not targeted to appeal to Facebook and such, and as a result, it ultimately wasn’t sustainable. It kind of feels like such cases—plus the re-tooling of Facebook’s feed away from publications and towards people, and the rise of newsletters—are all related. It’s reductive to say “newsletters are the new blogs,” but it’s probably not far off. I would 100% be telling someone to start a newsletter. Actually, I’d tell them to use Substack, but I would have to declare my bias!

Tech-wise, what tooling are you using to curate, create, and send here?

I love talking about this stuff! Uses This is one of my favorite sites. Honestly, it’s pretty low-tech at the moment, just busy. I have a Pocket account with a #versioning tag, so that often gives me a dozen or so links at the start of the day, sourced from my internet meanderings through the evening. I subscribe to a million newsletters, both in my work and personal accounts, on a hopefully both diverse and relevant range of topics.

I subscribe to quite a few RSS feeds using Feedly, too. Nuzzel, which sends you a daily/weekly digest of the most-shared links among people you’re following in Twitter and Facebook, is very useful here too. I have a personal Twitter/Nuzzel feed, plus one I’ve specifically set up for this purpose. Refind is another service trying to solve this problem. Its breadth and depth kind of give me a headache though. They’ve got a Nuzzel-like daily/weekly digest, a service for creating your own newsletters, a cryptocurrency—there’s a lot.

I also have the requisite very big Tweetdeck set-up to grab other links that catch my eye. Oh, and Initab is a new Chrome tab extension you can populate with feeds from certain subreddits and other place. I’ve been playing around with psuedo-Tweetdeck-for-Reddit services too. And Spectrum is a new community service thing I found last week, looks like it could be a winner too. And I need to be more active in Facebook groups. Also, Slack!

So yeah, there’s a lot. A bit of a combo of algorithms and people, hopefully I have the balance right. I also change newsletters, feeds, and other sources regularly, trying to find a better balance.

As for collecting and writing, it’s actually fairly simple—I find something I like, copy the URL into a Markdown doc, then write a description. I deliberately use a web-based Markdown editor (currently Stackedit, though I have used Dillinger and Classeur in the past). Something web-based is good because I can easily tab to it without having to switch to a new app. Stackedit is good because you can paste the generated preview directly into Campaign Monitor and (now) Substack and have formatting and links sorted. I then have a Google Doc to collect links I’ve already shared, and to gauge the reception in the audience—I want to spot trends like a rising interest in micro-services.

Building emails is something we all sort of love and loathe as front-end developers. How did you approach your email design and did you learn anything from building it?

Yes, email design is hard! Fortunately for me, the content and approach I’ve adopted lends itself to a stripped-back design with very little going on. Versioning is just text and a few images, so it required practically zero design. Our use of Campaign Monitor and now Substack meant we could sidestep some of the template work. In general terms though, my advice would be:

  • Focus on the purpose and content of the newsletter, produce a template based on that. It’s more important to produce something compelling, promote it in the right places, gain an audience, and then keep it (and grow it) by making sure you’re consistent in your production.
  • If you can (via a survey or through whatever data your email platform offers) work out what devices and platforms your audience uses to access email. People read email in all sorts of obscure ways, but you can likely cover the main ones for your audience with relatively little effort.
  • Don’t forget the plaintext user! Make sure your URLs are short, your images have alt tags, you’re generally nice to those in your audience who are in this boat. Versioning, given the niche, has a high proportion of these.
  • If all else fails, work with an expert or use one of a plethora of tools and services to do the work for you. Substack has a stripped-back CMS, Campaign Monitor and MailChimp have built-in template builders, and there are plenty of other services you could use. The compatibility issues with email are legendary. You could instead spend your time on things like a distinctive logo and branding or a landing page that communicates your newsletter’s value.

Ultimately people will enjoy a simple newsletter full of content they love presented in a way they can absorb. The design shouldn’t tie you in knots!

Let’s open this up to readers. Are you into the idea of paid newsletters?


On Paid Newsletters: An Interview With Adam Roberts of SitePoint’s Versioning originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/on-paid-newsletters-an-interview-with-adam-roberts-of-sitepoints-versioning/feed/ 6 268329
So you need to parse an email? https://css-tricks.com/need-parse-email/ Fri, 03 Nov 2017 23:59:33 +0000 http://css-tricks.com/?p=262041 Say you have a website with users who have accounts. Those users email you sometimes. What if you could parse that email for more context about that user, their account, and what they might want?

There are email parsing services …


So you need to parse an email? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Say you have a website with users who have accounts. Those users email you sometimes. What if you could parse that email for more context about that user, their account, and what they might want?

There are email parsing services out there. For example, Zapier offers Parser, which is free, with the idea being that you use Zapier itself to interconnect that data with other apps.

You teach it about your emails and then get programatic access to those data bits.

mailparser.io is another service just for this.

Same deal, you send the emails to them, and from within that app you set up parsers and do all the processing you need to do.

That might not be exactly what you need.

Perhaps your goal in parsing an email is to extend the data available to you right in your email client.

Gmail is a pretty huge email client. I just noticed that they have released and official way to make “Gmail Add-ons”:

Gmail add-ons are developed using Apps Script, a scripting language based on JavaScript that serves as a connective platform between Google products like Docs, Sheets, Drive, and Gmail. Every Gmail add-on has a corresponding Apps Script project where you define your add-on’s appearance and behavior.

That might be just the ticket for those of you looking to get your hands on email data, do stuff with it, and have a UI for doing stuff right within Gmail. There is a marketplace to check out with existing apps. The Trello one seemed pretty compelling to me.

Plus:

The contextual cards you create for your add-ons work for both web and mobile versions of Gmail. This means that you don’t need to create separate web and mobile versions of the add-on—the same code works everywhere!

Personally, I make pretty heavy use of Front, which is like a shared team inbox superapp.

Front offers a plugin system as well, which adds your own custom panel right into the app itself and gives you all that programatic parsing stuff you need to get into emails (or tweets or whatnot).

We use it at CodePen to figure out who’s emailing us (from the perspective of our own app) and show some contextual information about them, as well as provide some quick common actions that we might need.

Another thing to consider is how the emails are being generated at all. For example, do you offer customer support by just saying “email us at xxx@yyy.com”, or do you have them fill out a form which generates an email? If it’s a form, that’s, in a sense, parsing an email before it’s even sent, meaning it has structure and potentially programattic access to individual fields.

An example of that might be using a Wufoo form for your support and then using the API to access the data as needed. Maybe you can skip email parsing entirely.


So you need to parse an email? originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
262041
Visual Email Builder Apps https://css-tricks.com/visual-email-builder-apps/ https://css-tricks.com/visual-email-builder-apps/#comments Thu, 17 Aug 2017 11:33:32 +0000 http://css-tricks.com/?p=259222 I bet y’all know that apps like Campaign Monitor and MailChimp have visual email builders built right into them. You drag and drop different types of content right into a layout. You edit text right within the email. It’s nice. …


Visual Email Builder Apps originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
I bet y’all know that apps like Campaign Monitor and MailChimp have visual email builders built right into them. You drag and drop different types of content right into a layout. You edit text right within the email. It’s nice. It’s a lot nicer than editing the quagmire of HTML underneath, anyway!

But not everybody needs all the rest of the features that those apps bring, like list management and the actual sending of the email. Perhaps you have an app that already handles that kind of thing. You just need to design some emails, get the final HTML, and use it in your own app.

When I was looking around at email tooling, I was surprised there were a good number of apps that help just with the visual email building. Very cool.

Topol

BEE free

EDMdesigner

RED (Responsive Email Designer)

Taxi for Email

Postcards


I haven’t used any of them extensively enough to make a firm recommendation, but I’ve been dabbling and I like that they exist and that there are options.


Visual Email Builder Apps originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/visual-email-builder-apps/feed/ 16 259222
The Tools of an HTML Email Workflow https://css-tricks.com/tools-html-email-workflow/ https://css-tricks.com/tools-html-email-workflow/#comments Wed, 24 May 2017 14:20:08 +0000 http://css-tricks.com/?p=254561 Last week’s ShopTalk Show was all about HTML Email. It’s such a fascinating subject, as technically it is front-end web development, but it almost feels like a bizarro alternate universe.

We have dozens of browsers to worry about, they have …


The Tools of an HTML Email Workflow originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Last week’s ShopTalk Show was all about HTML Email. It’s such a fascinating subject, as technically it is front-end web development, but it almost feels like a bizarro alternate universe.

We have dozens of browsers to worry about, they have hundreds of clients to consider. We worry about whether fancy new APIs are supported, they worry about whether padding is supported. We have grid layout, they have…. grid layout?!

It’s tempting to make the joke: “It’s coding like it’s 1999!”, but as we talk about in this episode, that’s not really true.

Aside from all that, another thing I thing fascinating are all the tools involved. Lemme think this out.

Creation Tools: Bare Metal

You can create an email with just HTML. I’m sure quite a lot of HTML email is created this way. Open code editor, create HTML email, send HTML email. I know I’m tempted by this and go this route a lot, especially when creating an important one-off email.

Check out Really Good Emails on CodePen, where they have archived loads of the full HTML of sent email campaigns.

The builder tool in Litmus is also a bare metal editor. You see and edit the entire HTML document.

Creation Tools: HTML Templates

It’s still creating by hand and hand-authoring HTML, but you can reach for HTML email templates. This is probably a very good route for most us, because of how tricky HTML email can be to get right. Fortunately, a lot of the hard work of figuring out nice and simple email templates with functional layout and type has already been done.

Creation Tools: Abstracted Templates

Creating an email by directly working with one big giant gnarly piece of HTML is certainly possible, but front-end developers hardly ever work that way. One of the first abstractions we always reach for is abstracting HTML into parts. You can do that with email.

  • You could use your own server-side partials to break up the HTML into parts, so that making new emails can re-use those parts and they are quicker to build and easier to maintain.
  • Dan Denney has a system called eMMail that uses Middleman, Haml, and Sass to abstract the emails into manageable parts.
  • Lee Monroe has a Grunt Email Design Workflow which is Handlebars/Assemble and Sass to piece emails together.
  • Foundation Emails uses an abstracted HTML language called Inky which compiles into HTML ready for email.
  • MJML is also a an abstracted HTML language designed to be preprocessed into HTML for email.

UI Builder and Sending Tools

Rather than touching code at all, you could design and write an email directly through a tool built for that. These choices are probably pretty obvious to most folks, as there is huge demand for this. Rightly so! Tools like these let you get right to writing and designing the email without getting distracted by tools.

It’s just not always possible to use tools like this for all the emails you send. They are usually cost prohibitive for really giant email lists, and not really built for transactional email.

These tools tend to tie together the visual building of the email along with sending and analytics. Everything in one.

Sendwithus is a little different. It is built for transactional email, and gives you a system for building and templating emails, but doesn’t send them directly itself (despite the name). You bring-your-own email sending service. Speaking of which…

Sending Tools: APIs

These services actually send the email for you. You hit their API with the email itself, the subject line, the recipients, and whatever else they need and it sends the email. Here’s a non-comprehensive list:

Analytics is usually a feature that comes with these tools that do the sending. That’s true of these email APIs along with the build-and-send apps.

Inlining CSS tools

I always assumed this was absolutely 100% required for HTML emails, but it isn’t really. Most email clients support a <style> block in the <head>. That means you can ship CSS without having to inline it. Even when that is supported though, you need to think about which features are supported. Like just because a style block is supported, it doesn’t mean border-radius necessarily.

Email support chart from Campaign Monitor.

Even that red mark above is out of date, as Gmail does support style blocks now. So inlining CSS might be going away ultimately, but I imagine there are some email clients that still need it, and if it’s part of a build process anyway, I guess it can’t hurt.

Copy and paste in-browser tools:

Programmatic tools:

Testing Tools

  • You could send yourself an email and look at it. Probably best to spin up as many email clients as you possibly can, across different operating systems and devices.
  • Litmus is the biggest player in this area. Many other tools that offer previews of your email are actually Litmus doing that work.
  • Email on Acid is a similar tool and a bit less expensive.

The Tools of an HTML Email Workflow originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/tools-html-email-workflow/feed/ 19 254561
Client Email Helper https://css-tricks.com/client-email-helper/ Wed, 14 Dec 2016 18:24:15 +0000 http://css-tricks.com/?p=248997 For all you freelancers out there, Jessica Hische has written some copy to help you articulate saying no to things you should be saying no to.

I’ve created this handy tool to help you say “no” to free and low-budget


Client Email Helper originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
For all you freelancers out there, Jessica Hische has written some copy to help you articulate saying no to things you should be saying no to.

I’ve created this handy tool to help you say “no” to free and low-budget work and to help ask for more favorable contract terms before the start of a project.

To Shared LinkPermalink on CSS-Tricks


Client Email Helper originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
248997
Inky and Slinky https://css-tricks.com/inky-and-slinky/ https://css-tricks.com/inky-and-slinky/#comments Wed, 21 Sep 2016 13:12:19 +0000 http://css-tricks.com/?p=245731 Inky is kinda like a preprocessor for HTML created by Zurb, specifically designed for responsive emails.

I’m sure a lot of us have hand-coded HTML emails (I do it regularly) and know that it’s typically <table> soup. It’s not even …


Inky and Slinky originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
Inky is kinda like a preprocessor for HTML created by Zurb, specifically designed for responsive emails.

I’m sure a lot of us have hand-coded HTML emails (I do it regularly) and know that it’s typically <table> soup. It’s not even just the tables that are annoying, but the fact that there are so many of them nested to do even fairly simple things it’s hard to keep straight.

Inky’s appeal is pretty clear from the first demo in their docs:

But how do you go about using it? Like any preprocessor, ultimately you need to convert its syntax into browser-readable code. Inky is in node, so you also use it much like any other node-based preprocessor. You can install it and call it directly from the command line, from within node code, or as a Gulp plugin.

This is where Slinky comes in.

Slinky makes it easier to play around with Inky. In fact it could be your primary workflow if you design one-off emails pretty regularly.

You edit this Pen:

See the Pen PGPNwk by Inky (@FoundationForEmails) on CodePen.

You should fork a copy so you can save it and get your own URL slug. Slinky will need that.

Zurb has this Pen set up so that it processes the Inky code and injects the processed code, so you can see the live results. You can even do additional styling with SCSS right in the Pen!

When you’re done, you hit the big pink “Get your HTML Email” button in the lower right of the preview.

You’ll hop back over to the Slinky page and it’ll give you all that raw HTML, inline CSS included:

That raw HTML is exactly what you need to send the email. It’s ready-to-go.

Say you’re using MailChimp to send HTML email. They have a “Code Your Own” option where you’d be just pasting in what you now have:

Or say you use service like that sends your emails via an API, like MailGun:

You’d do it like that, only pass an html parameter instead of text.

I’d say if you hand-write and maintain a good amount of HTML emails, this could be a pretty useful way to work.


Inky and Slinky originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.

]]>
https://css-tricks.com/inky-and-slinky/feed/ 9 245731