<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Email template development guides, tutorials, tools - EDMdesigner Blog]]></title><description><![CDATA[EDMdesigner's email marketing blog focuses on responsive email template development. You can find tutorials, and guides in connection with the latest HTML email template development best practices. ]]></description><link>https://blog.edmdesigner.com/</link><image><url>https://blog.edmdesigner.com/favicon.png</url><title>Email template development guides, tutorials, tools - EDMdesigner Blog</title><link>https://blog.edmdesigner.com/</link></image><generator>Ghost 1.22</generator><lastBuildDate>Fri, 31 Jan 2020 15:30:10 GMT</lastBuildDate><atom:link href="https://blog.edmdesigner.com/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Email Marketing and Mobile Optimization]]></title><description><![CDATA[<div class="kg-card-markdown"><p>Although we know we are now in mobile email world, it seems that <strong>many subscribers in general still have <a href="http://edmdesigner.com/posts/80-of-people-have-negative-feelings-about-mobile-email" title="80% of People Have Negative Feelings About Mobile Email">negative feelings about marketing emails on their mobile</a></strong>.<br>
The top three reasons:</p>
<ul>
<li>Too many emails</li>
<li>They are not relevant</li>
<li>Too small to read and interact with.</li>
</ul>
<p>Number one and two aren’</p></div>]]></description><link>https://blog.edmdesigner.com/email-marketing-and-mobile-optimization/</link><guid isPermaLink="false">5c3c41cc865fc60a3692cd6a</guid><category><![CDATA[mobile optimization]]></category><category><![CDATA[mobile-friendly]]></category><dc:creator><![CDATA[Gergely Csaba Nagy]]></dc:creator><pubDate>Mon, 14 Jan 2019 08:03:38 GMT</pubDate><content:encoded><![CDATA[<div class="kg-card-markdown"><p>Although we know we are now in mobile email world, it seems that <strong>many subscribers in general still have <a href="http://edmdesigner.com/posts/80-of-people-have-negative-feelings-about-mobile-email" title="80% of People Have Negative Feelings About Mobile Email">negative feelings about marketing emails on their mobile</a></strong>.<br>
The top three reasons:</p>
<ul>
<li>Too many emails</li>
<li>They are not relevant</li>
<li>Too small to read and interact with.</li>
</ul>
<p>Number one and two aren’t exclusive to mobile email. <strong>A marketer needs to overcome all three to become an inbox champion.</strong> Ideally, your subscribers have a profound appreciation for you and your messaging. If there is brand appreciation, there is a much bigger chance your subscribers will interact with them based on the relationship. Even if your emails are not perfectly targeted or sent at the optimum time</p>
<h2 id="contentfirstemailsmusthelpsubscribers">Content first: Emails must Help Subscribers</h2>
<p>If your prime objective is to generate revenue through email marketing to your list, there is nothing wrong with that. Even more, the revenue is often one of the top reasons that email marketing is getting such high ROI, but <strong>subscribers aren’t ATMs and we shouldn’t approach it like that</strong>.</p>
<p>Look at your list as people who have reached out to you because they like the way you think. <strong>Look at your list as a community of people who need help, who need your expertise.</strong></p>
<p><strong>With every email you send</strong>, keep in mind that you can <strong>add value</strong> by helping subscribers with problems that they are facing. Yes, this can be through your own products and recommendation of other products that is perfect for their needs, nothing wrong with selling. <strong>But email marketing is not purely “Always Be Closing”</strong>, relationship building mails can be helpful without a secondary pitch.</p>
<p>Your subscribers will come to understand that you have (premium) products and services and might start to think about those over time as they come to trust you.</p>
<h2 id="emailsmustbeeasytoread">Emails MUST Be Easy to Read</h2>
<p><strong>A great relationship might give you inbox forgiveness, but your emails should be accessible.</strong> There are many aspects of readability that you can address. Like using mobile optimized and responsive design. Research on the importance of responsive email design shows that 82% of people open emails on their phones and that over half of that group delete emails that are not formatted for mobile displays. Responsive design allows scaling your full-sized newsletter and good email marketing provider’s tools will allow you to rearrange elements, to use larger buttons and reduce clutter very easily on mobile versions of your newsletter. But Responsive Design is not everything.</p>
<p><img src="http://edmdesigner.com/content/images/2015/04/Email-Marketing-and-Mobile-%E2%80%93-Make-Them-Love-You.png" alt="Email Marketing and Mobile – Make Them Love You">Image source: <a href="http://getresponse.com">Getresponse.com</a></p>
<h3 id="readability">Readability</h3>
<p>Emails need to be displayed in large fonts on mobile. This is just as important as being succinct. If someone is reading your email on their phone they are possibly talking or getting distracted at the same time. The attention you get is the attention you get, make use of it. <strong>You have to make the user’s life simple or they will just press the Delete button.</strong></p>
<h3 id="makeiteasytoread">Make it easy to read.</h3>
<p>Use a <strong>16 px or 18 px</strong> sans serif <strong>font for phones</strong>. Use a <strong>14 px font for tablets</strong>. <strong>Even on laptop <strong>screens</strong> emails need</strong> a** 12 px font** to allow viewers to read them easily.<br>
Here are some mobile scanning tips:</p>
<ul>
<li>Use short sentences. Short.</li>
<li>Use one or two sentence paragraphs.</li>
<li>Include a button to link CTA to the full post or product on your (responsive) website.</li>
</ul>
<h2 id="emailfrequencymustbejustright">Email Frequency MUST Be Just Right</h2>
<p>If you send emails less than once a month then subscribers are likely to forget that they signed up to your newsletters. If you send emails too frequently then your unsubscribe rate will sky-rocket. One of the most common complaints about email marketing is that emails are sent too often.</p>
<p><strong>There is no magic number regarding email frequency</strong>; it depends on your relationship with your subscribers. Coming back to the point first made: Relationships first.</p>
<h2 id="conclusion">Conclusion</h2>
<p><strong>When someone signs up to your email list they are granting you a privilege. Respect that privilege</strong> or lose it. You are being invited into people’s homes and phones because they think you have something interesting to say.</p>
<p>You will read much advice about <a href="https://www.rightinbox.com/blog/how-to-write-a-professional-email">getting your subscribers to open your emails</a>, but everything you read is less important than the <strong>emotional engagement between your subscribers and you</strong>.</p>
<h2 id="yourinput">Your Input</h2>
<p>Do your email subscribers love you? How have you earned their love? Please share your thinking using the comments box below.</p>
<p><em><strong>Guest post by <a href="https://twitter.com/jvanrijn">@jvanrijn</a></strong></em></p>
<p>Jordie van Rijn – is an independent email marketing consultant; Helps companies get the most out of their digital efforts and <a href="http://www.emailmonday.com/email-marketing-automation-software-selection" title="Find email marketing software">find email marketing software</a>.</p>
</div>]]></content:encoded></item><item><title><![CDATA[16 Command Examples to Send Email From The Linux Command Line]]></title><description><![CDATA[In this post you'll learn how to send emails from the Linux command line. I'll show the most often used commands,  SMTP configuration and terminal options.]]></description><link>https://blog.edmdesigner.com/send-email-from-linux-command-line/</link><guid isPermaLink="false">5afad21c3bed88001585fbab</guid><category><![CDATA[Email sending]]></category><category><![CDATA[SMTP]]></category><category><![CDATA[Linux]]></category><category><![CDATA[Command Line]]></category><category><![CDATA[Terminal]]></category><category><![CDATA[CLI]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 11 Apr 2018 13:25:03 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2018/04/linux-command-line-email-sending.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2018/04/linux-command-line-email-sending.png" alt="16 Command Examples to Send Email From The Linux Command Line"><p>Whether you are a developer working non-stop in the Linux command line or a server administrator wanting logs or other data extracted from administered systems, knowing how to send email from the command line is greatly useful.</p>
<p>In this post, you'll find examples of how to send email from the terminal. We'll look at custom configurations and touch on how to set up SMTP connections to email accounts or email service providers. I'll show you how to install the necessary console mailer packages and provide background for command line options based on the package's manuals.</p>
<p><a href="https://packages.debian.org/jessie/cowsay"><img src="https://blog.edmdesigner.com/content/images/2018/02/learn-email-sending-via-command-line-linux.png" alt="16 Command Examples to Send Email From The Linux Command Line"></a></p>
<h2 id="settingupcommandlinemailerpackages">Setting Up Command Line Mailer Packages</h2>
<p>All the mailer packages throughout the tutorial are available through <a href="https://wiki.debian.org/Apt">Debian's Advanced Package Manager</a> so the installation steps in the example below may be used for all the showcased packages.</p>
<p>Please note that these pieces of software may be installed by other default package managers such as <code>yum</code> or <code>dnf</code> depending on your Linux system distribution.</p>
<p>In most cases, either <code>sendmail</code> or <code>postfix</code> is available in each Linux distribution out-of-the-box or at least that's what similar blog posts say. Either I'm unlucky or the others were wrong, but I had to install one manually. <strong>However, you definitely need one of them for email delivery.</strong></p>
<h3 id="settingupsendmailwithssmtppackage">Setting Up Sendmail with SSMTP Package</h3>
<p>I'll continue with <code>sendmail</code> and the SSMTP package. SSMTP contains the <code>sendmail</code> package under the hood as you'll see and it facilitates the configuration, which is pretty hard for <code>sendmail</code> otherwise.</p>
<p><strong>Step 1.</strong> Check if Command Line Mailer Package is Installed</p>
<p>Type in the mailer package's name just the way you would run the command, to check if it's available:</p>
<ul>
<li>
<p>If the package is installed, the command runs, and the prompt changes — while trying to execute the command — and you'll see a blinking cursor followed by the message <code>Recipient names must be specified</code> in the case of <code>sendmail</code>. Conclusion: the package is installed.</p>
</li>
<li>
<p>If the package is NOT installed, you'll receive a warning message and a suggestion how to install it:</p>
</li>
</ul>
<pre><code>$ sendmail

The program 'sendmail' can be found in the following packages:
 * exim4-daemon-heavy
 * exim4-daemon-light
 * postfix
 * citadel-mta
 * courier-mta
 * dma
 * esmtp-run
 * masqmail
 * msmtp-mta
 * nullmailer
 * opensmtpd
 * qmail-run
 * sendmail-bin
 * ssmtp
Try: sudo apt install &lt;selected package&gt;
</code></pre>
<p>In this example, I tried if the <code>sendmail</code> command works. After we add the SSMTP package, this command and the <code>ssmtp</code> command will both work and change the command prompt in the terminal. Let's look at that!</p>
<p><strong>Step 2.</strong> Installing Sendmail Command Line Mailer Package</p>
<p>As the terminal output suggested, we need to run the Advanced Package Manager's install command — usually with root permission — to install the necessary package. As mentioned before, the configurations are much simpler for <code>sendmail</code> when you abstract away the complexity of the configuration. That can be done with SSMTP:</p>
<pre><code>     sudo apt install ssmtp

</code></pre>
<p><strong>Step 3.</strong> Verify the Installation</p>
<p>After the installation completed, you can check if <code>sendmail</code> is able to forward messages. Type the below code in the terminal:</p>
<pre><code>      echo &quot;Subject: hello&quot; | sendmail test@example.com
</code></pre>
<p>It should send out the email if everything works correctly. Here the <code>&quot;hello&quot;</code> string piped to the <code>sendmail</code> command will be the subject of the sent message, while the defined email address is naturally the recipient of the email.</p>
<p>You run the command... and, oops: <code>sendmail: Cannot open mailhub:25</code>. The reason for this is that we didn't provide mailhub settings at all. In order to forward messages, you need an SMTP server configured. That's where SSMTP performs really well: you just need to edit its configuration file once, and you are good to go.</p>
<p><strong>Step 4.</strong> Configuring SSMTP</p>
<p>Let's locate the config file at <code>/etc/ssmtp/ssmtp.conf</code>. Here, you should put the code below to configure an SMTP relay:</p>
<pre><code>    UseSTARTTLS=YES
	root=&lt;your-email-address&gt;
	mailhub=smtp.gmail.com:587
	AuthUser=&lt;your-account's-user-name&gt;
	AuthPass=&lt;your-account's-password&gt;
</code></pre>
<p>This means that you set up an external service that will actually forward<br>
your emails. When you provide credentials to Gmail for example, you'll see the messages sent from the terminal in your mailbox's 'Sent mail' directory. <a href="https://sendgrid.com/docs/Integrate/Mail_Servers/ssmtp.html">The configurations look similar</a> with other services too.</p>
<p>This was the basic configuration for <code>sendmail</code> and the installation steps for any frequently used command line mailer package. Next, we'll jump on installing and trying out various other packages.</p>
<div data-chamaileonplugin="blog-forms/signup-for-dev-posts" data-page="signup-for-dev-posts" data-location="inside-blog-post"></div>
<h2 id="sendingemailusingthessmtpcommand">Sending Email Using the SSMTP Command</h2>
<p>This is a nice little tool we just configured for mail delivery. <a href="https://linux.die.net/man/8/ssmtp">As its <code>man</code> page suggests</a>, it's a minimalistic emulator of <code>sendmail</code>. As such, SSMTP allows users to transfer emails through an SMTP server from the Linux command line. It provides the means to connect to a mailhub with a proper configuration file. If your config file was set up right, all your worries regarding command line email sending can disappear.</p>
<p><strong>Basic Implementation of the SSTMP command:</strong></p>
<p>If you just use SSMTP, the command should look as follows:</p>
<pre><code>      ssmtp  test@example.com &lt; mail.txt
</code></pre>
<p>Following the <code>ssmtp</code> command, you should put the recipient address, then you can include a file that will show in the email body. Here you can define headers for the message, list further recipients and set the content type. This way you can send HTML emails. SSMTP will interpret your message and use the provided values properly. Here is an example of an HTML you might send:</p>
<pre><code>	Cc: example@edmdesigner.com
	Subject: This is an HTML email
	From: developer@example.com
	Content-Type: text/html; charset=&quot;utf8&quot;


	html&gt;
	&lt;body&gt;
	&lt;div style=&quot;
		background-color:
		#abcdef; width: 300px;
		height: 300px;
		&quot;&gt;
	&lt;/div&gt;
	You can add any valid email HTML here.
	&lt;/body&gt;
	&lt;/html&gt;
</code></pre>
<p>You can't really give further options with SSMTP as they are not respected by its minimalistic design.</p>
<p><strong>Troubleshooting:</strong></p>
<p>In case you run into the following error on the command line:</p>
<pre><code>      ssmtp: Authorization failed (534 5.7.9  
      http://support.google.com/accounts/bin/answer.py?answer=185833 
      bk8sm8525341pad.28 - gsmtp)
</code></pre>
<p>that’s likely because Gmail is not treating SSMTP as a secure application. To get rid of this error, <a href="https://myaccount.google.com/lesssecureapps">you need to change the settings</a> in your Gmail account – you can look up more information on potential risks there as well.</p>
<h2 id="sendingemailusingthesendmailcommand">Sending Email Using the Sendmail Command</h2>
<p>For quite some time now sendmail is the classical <a href="https://en.wikipedia.org/wiki/Message_transfer_agent">mail transfer agent</a> from the world of UNIX. It was first introduced in 1979 and its highly-configurable nature and scalability made it the default go-to for server administrators.</p>
<p>We've already seen how to send basic emails by the <code>ssmtp</code> command, so let's see the difference using <code>sendmail</code>:</p>
<pre><code>      echo &quot;Subject: hello&quot; | sendmail -v test@example.com &lt; mail.txt
</code></pre>
<p>I threw in the <code>-v</code> argument, which will make the communication between the mail server and your mail transfer agent visible.</p>
<p>There are plenty of configurations that you can use if you set up your own mail server and implement sendmail on it. However, that is out of the scope of this article. We will return to the topic in an upcoming one. Stay tuned.</p>
<div data-chamaileonplugin="blog-forms/signup-for-email-design-posts" data-page="signup-for-email-design-posts" data-location="inside-blog-post"></div>
<h2 id="sendingemailusingcurlcommand">Sending Email Using CURL Command</h2>
<p>This tool is also tremendously common for data transfer from a server. It supports many protocols, like HTTP, FTP, POP3 or SMTP. The <a href="https://en.wikipedia.org/wiki/CURL">CURL</a> package is used widely around the globe, one main reason is that it has <a href="http://php.net/manual/en/book.curl.php">native PHP implementation</a> and <a href="https://blog.edmdesigner.com/sending-email-with-php/">PHP was the default server-side scripting language</a> for a long time.</p>
<p><strong>Installation:</strong></p>
<p>Check if the package is already installed. If not run the below:</p>
<pre><code>      sudo apt install curl
</code></pre>
<p>When you're done, you can access the cheat sheet for the available options for CURL by running <code>curl -h</code>. The more detailed version is accessible by either <code>man curl</code> or <code>curl --manual</code>. If you want to gain in-depth knowledge using cURL, there's <a href="https://www.gitbook.com/download/pdf/book/bagder/everything-curl">this handy Ebook</a> that contains everything you would ever want to know.</p>
<p><strong>Basic implementation for email sending with CURL:</strong></p>
<pre><code>curl --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
  --mail-from 'developer@gmail.com' --mail-rcpt 'edm-user@niceperson.com' \
  --upload-file mail.txt --user 'developer@gmail.com:your-accout-password'
</code></pre>
<p>In order to send an email with CURL, you need to set up SMTP connection. Most often <a href="https://support.google.com/mail/answer/7104828?hl=en">Google's</a> or <a href="https://help.yahoo.com/kb/SLN4724.html">Yahoo's</a> outgoing mail servers are used for testing email sending with SMTP. Please note that you must turn on access for less secure apps in Gmail settings and similar additional security settings may apply for Yahoo as well.</p>
<p>In the terminal command snippet above, the <code>--url</code> and <code>--user</code> parameters define the SMTP connection settings. The password section for <code>--user</code> parameter is your account's password for the given email address. Naturally, you could also use cloud email service providers. I will show that using Mailgun in the following section.</p>
<p><strong>Advanced implementation for email sending with CURL:</strong></p>
<p>Working with email delivery platforms, you first need to obtain an API key. In this tutorial, I'll show CURL email sending example using Mailgun, so if you get stuck during the registration process <a href="https://blog.edmdesigner.com/php-sending-html-emails/#sendinghtmlemailtemplatesusingmailgun">follow this setup guide</a> to get on the right track.</p>
<pre><code>curl -sv --user 'api:key-7e55d003b...f79accd31a' \
    https://api.mailgun.net/v3/sandbox21a78f824...3eb160ebc79.mailgun.org/messages \
    -F from='Excited User &lt;developer@yourcompany.com&gt;' \
    -F to=sandbox21a78f824...3eb160ebc79.mailgun.org \
    -F to=user@gmail.com \
    -F subject='Hello' \
    -F text='Testing some Mailgun awesomeness!' \
   --form-string html='&lt;h1&gt;EDMdesigner Blog&lt;/h1&gt;&lt;br /&gt;&lt;cite&gt;This tutorial helps me understand email sending from Linux console&lt;/cite&gt;' \
    -F attachment=@logo2yellow.jpg
</code></pre>
<p>The syntax is pretty straightforward. You may have noticed before, but you need to end each line of the command with <code>\</code> characters. This is a line continuation character, the command can be run without them all in one line as well. The other thing to remember is the <code>-F</code> option. An excerpt from the man page:</p>
<pre><code> -F, --form &lt;name=content&gt;
        (HTTP)  This lets  curl  emulate  a  filled-in form 
        in which a user has pressed the submit button. 
        This causes curl to POST data using the Content-Type 
        multipart/form-data according to RFC 2388. 
        This  enables uploading  of binary files etc. 
        To force the 'content' part to be a file, prefix 
        the file name with an @sign.
</code></pre>
<p>As I encouraged before, it's a good practice to dive into the manuals when using these command line mailer commands. As the CURL manual says, basically you're creating a form to send. Each line is an entry given as a <code>name=content</code> pair. When you attach files from your local machine, you need an <code>@</code> in front of the file name.</p>
<p>This is how the delivered email will look like:<br>
<img src="https://blog.edmdesigner.com/content/images/2018/03/sending-email-with-curl.jpg" alt="16 Command Examples to Send Email From The Linux Command Line"></p>
<p>You could do the same using most of the other email delivery platforms, like <a href="https://sendgrid.com/docs/Classroom/Send/How_Emails_Are_Sent/api_keys.html">Sendgrid</a> for example.</p>
<p><strong>Sending HTML email from the command line with CURL:</strong></p>
<p>You can apply the same logic of building a form in a text file, which enables you to send HTML messages easily:</p>
<pre><code>	To: customer@gmail.com
	Subject: This is an HTML message
	From: developer@yourcompany.com
	Content-Type: text/html; charset=&quot;utf8&quot;

	&lt;html&gt;
	&lt;body&gt;
	&lt;div style=&quot;
		background-color: 
		#abcdef; width: 300px; 
		height: 300px;
		&quot;&gt;
	&lt;/div&gt;
	You can add any valid email HTML here.
	&lt;/body&gt;
	&lt;/html&gt;
</code></pre>
<p>If you run the simple command from the first example...</p>
<pre><code>curl --url 'smtps://smtp.gmail.com:465' --ssl-reqd \
  --mail-from 'developer@edmdesigner.com' --mail-rcpt 'edm-user@niceperson.com' \
  --upload-file mail.txt --user 'developer@gmail.com:your-accout-password'
</code></pre>
<p>... and direct the <code>--upload-file</code> parameter to the updated text file (mail.txt in our case), the received message will show the HTML content.</p>
<p><strong>Troubleshooting:</strong></p>
<p>You may need the <code>--insecure</code> switch, which allows CURL to perform &quot;insecure&quot; SSL connections and transfers. CURL will return an error message if the remote server is using a self-signed certificate, or if the remote server certificate is not signed by a CA listed in the CA cert file.</p>
<h2 id="sendingemailusingswakscommand">Sending Email Using Swaks command</h2>
<p>As their documentation states, Swaks is a flexible, scriptable, transaction-oriented SMTP test tool. It is able to handle SMTP features and extensions such as TLS, authentication, and pipelining and multiple version of the SMTP protocols. It also supports multiple transport methods including UNIX-domain sockets, internet-domain sockets, and pipes to spawned processes.</p>
<p><strong>Installation:</strong></p>
<pre><code>      sudo apt install swaks
</code></pre>
<p><strong>Basic implementation for email sending with Swaks:</strong></p>
<p>In order to connect to an SMTP account you need to provide the server <code>-s</code>, the user <code>-au</code>, the password <code>-ap</code> and the address <code>-t</code> (where you want to send your mail) flags. The <a href="https://www.fastmail.com/help/technical/ssltlsstarttls.html"><code>-tls</code> flag is also important</a> if you connect on port <code>587</code>.</p>
<pre><code>      swaks --to mailbox@example.com -s smtp.gmail.com:587 
      -tls -au &lt;user-account&gt; -ap &lt;account-password&gt;
</code></pre>
<p>The credentials can also be provided via command line prompts, if you only specify to authenticate <code>-a</code>, not filling in the user and password through command line options.</p>
<p><strong>Advanced implementation for email sending with Swaks:</strong></p>
<pre><code>      swaks --to mailbox@example.com -s smtp.gmail.com:587 -tls -au &lt;user-account&gt; -ap &lt;account-password&gt;  --attach  -d ./mail.txt
</code></pre>
<p>There are other options which we will not touch now. Let's head to our next mailer package!</p>
<h2 id="sendingemailusingthemuttcommand">Sending Email Using the Mutt Command</h2>
<p><a href="http://www.mutt.org/">Mutt</a> is different from the previous email clients, as it is a feature-rich command line email client. You can use it for reading emails from the Linux terminal, connecting to local user mailboxes or to POP/IMAP servers. Mutt supports several mailbox formats such as mbox, MH, maildir, MMDF, full control of message headers during email composition, and multiple message tagging and colors to handle messages.</p>
<p><strong>Installation:</strong></p>
<pre><code>      sudo apt install mutt
</code></pre>
<p><strong>Basic implementation for email sending with mutt:</strong></p>
<p>By this time you won't be surprised by the structure of the command. You can provide an empty message body with <code>&lt; /dev/null</code>:</p>
<pre><code># mutt -s &quot;Test Email&quot; user@example.com &lt; /dev/null
</code></pre>
<p><strong>Advanced implementation for email sending with mutt:</strong></p>
<p>For sending email including attachments, you need the <code>-a</code> flag. This way you can send useful files, like system logs, to a specified address.</p>
<pre><code># mutt  -s &quot;System logs&quot; -a /opt/backup.sql user@example.com &lt; /dev/null
</code></pre>
<p>You could also send HTML email if the file extension you add to the message body is in HTML format. Mutt will recognize the file type and resolve it so it won't send your HTML as plain text:</p>
<pre><code>mutt -s &quot;Email subject&quot; test@example.com &lt; email.html
</code></pre>
<p>This is it for email sending with mutt. If you have it on your machine, I'd suggest to try out how you can work with incoming configuring your mailbox and handling incoming messages. If you do so, please share your thoughts in the comment section below. I welcome any opinion about the packages shown in the tutorial.</p>
<h2 id="sendingemailusingthemailxcommand">Sending Email Using the Mailx Command</h2>
<p><a href="https://mailutils.org/">The Mailutils</a> is a compound package for multiple use cases. It's designed to serve regular users, system administrators, and developers. We'll only touch on its basic functionalities regarding email forwarding. If you are interested in more features, check out its <code>man</code> page.</p>
<p><strong>Installation:</strong></p>
<pre><code>      sudo apt install mailutils
</code></pre>
<p><strong>Basic implementation for email sending with mailx:</strong></p>
<p>The mailx package has 2 equal command syntax (<code>mail</code> and <code>mailx</code> both work in the exact same way). The most simplistic command consists of the <code>mail/mailx</code> command and the address to send the mail to, but you would probably include the subject and at least some text-based message body. Such a command should look like this:</p>
<pre><code>      echo &quot;message body&quot; | mail -s &quot;subject&quot; test@example.com
</code></pre>
<p>By using the <code>echo</code> command and piping the output to the <code>mail</code> command, you can avoid mailx's additional prompts for Cc addresses and the message body.</p>
<p><strong>Advanced implementation for email sending with mailx:</strong></p>
<p>For the advanced example, we will send a full-fledged HTML email again. We need to provide the email HTML file of our choice with the <code>&lt;</code> character and add the &quot;append flag&quot; with the content type. The full code looks as follows:</p>
<pre><code>      mailx -a 'Content-Type: text/html' 
      -s &quot;This is advanced mailx indeed!&quot; &lt; email.html 
      &quot;recipient1@gmail.com, recipient2@yahoo.com&quot;
</code></pre>
<p>You can also set a return address with <code>--return-address=&lt;EMAIL-ADDRESS&gt;</code>, which may be useful. Another useful option, which I couldn't resolve to work with HTML email parallel, is to provide attachments in the same message: <code>-A &quot;mail.txt&quot;</code>. Though you can list multiple recipients, only a single attachment can be attached. You could configure external SMTP server if that fancies you.</p>
<h2 id="usingtelnetalternativeopensslcommand">Using Telnet Alternative Openssl Command</h2>
<p><a href="https://en.wikipedia.org/wiki/Telnet">Telnet is an interactive communication protocol</a> for communication with another host. It could be used to open an SMTP connection to another server and transfer email messages. However, as the protocol is not secured, most servers will reject this communication type. This is where <a href="https://www.openssl.org">Openssl</a> comes into the picture as it's built with <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">SSL/TLS</a> security included. It is invoked similarly to telnet with a host argument, and it performs an open command implicitly:</p>
<pre><code>        smiska➜Desktop/emails» openssl s_client -connect smtp.gmail.com:465     
                               -crlf -ign_eof
        ---
               certificate negotiation output from openssl
        ---

        220 smtp.gmail.com ESMTP j92sm925556edd.81 - gsmtp
            EHLO localhost
        250-smtp.gmail.com at your service, [78.139.22.28]
        250-SIZE 35882577
        250-8BITMIME
        250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
        250-ENHANCEDSTATUSCODES
        250-PIPELINING
        250-CHUNKING
        250 SMTPUTF8
            AUTH PLAIN *passwordhash*
        235 2.7.0 Accepted
            MAIL FROM: &lt;developer@edmdesigner.com&gt;
        250 2.1.0 OK j92sm925556edd.81 - gsmtp
            rcpt to: &lt;friendly@user.com&gt;
        250 2.1.5 OK j92sm925556edd.81 - gsmtp
            DATA
        354  Go ahead j92sm925556edd.81 - gsmtp
            Subject: This is openssl mailing

            Hello nice user
            .
        250 2.0.0 OK 1339757532 m46sm11546481eeh.9
            quit
        221 2.0.0 closing connection m46sm11546481eeh.9
        read:errno=0
</code></pre>
<p>I indented the inputs you need to provide while the communication channel is open. These inputs are self-explanatory, but one thing I need to detail is the password hash. It can be a base64 encoded hash, which you can obtain with the following command: <code>echo -en '\000username@gmail.com\000gmailpassword' | base64</code>. The escape characters from the string can't be omitted. If you don't have the base64 package installed, it is available through package managers.</p>
<p>As you can see above, this means of email sending only provides an interface for text-based messages, therefore it has its limitation in use cases. On the other hand, it shows all information exchanged with the mail server, which makes debugging really easy.</p>
<h2 id="troubleshootingmailproblems">Troubleshooting Mail Problems</h2>
<p><strong>Check the mail logs</strong></p>
<p>You need to locate your log file by navigating to the corresponding folder. I prefer to use <a href="https://blog.edmdesigner.com/how-to-use-sublime-text-for-html-email-development/">my code editor (eg. Sublime Text)</a> for this so I can have the logs with syntax highlight:</p>
<pre><code>$ sudo subl /var/log
</code></pre>
<p>Depending on your current Linux distribution you <a href="https://serverfault.com/questions/59602/where-to-check-log-of-sendmail">may need to look at different source</a>.<br>
The log may contain useful information about deliverability problems. At this point, when you scroll to the bottom of this:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/03/mail-log.png" alt="16 Command Examples to Send Email From The Linux Command Line"></p>
<p>you can inspect if delivery is successful or understand why the process failed.<br>
It can happen that your console shows no errors, but in the mail log you can see that the message was queued for delivery, so the process didn't halt on your machine but probably was denied by the mail server you were trying to reach.</p>
<h2 id="runningallcommandinasequence">Running All Command in a Sequence</h2>
<p>So, everything is ready for the final test. All the mailer terminal commands are gathered here in a script file. Once you downloaded <a href="https://edmdesigner.github.io/html-email-development-tools/lesson-terminal/commandlinesending.zip">the working folder</a> with the script file in it, navigate to the containing folder and make the script executable: <code>chmod u+x mail.sh</code>. If you have all the files I provided ready, you can start testing the mailer commands shown in the tutorial. You just need to replace the <code>&quot;&lt;RECIPIENT ADDRESS&gt;&quot;</code> to your test email address in the code and run <code>./mail.sh</code> in the command line.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/03/running-mail-shell-script.gif" alt="16 Command Examples to Send Email From The Linux Command Line"></p>
<p>Once the script finishes running, your inbox will be filled with the test emails.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/03/emails-arrived-to-mailbox.png" alt="16 Command Examples to Send Email From The Linux Command Line"></p>
<p>Well done!</p>
<h2 id="summary">Summary</h2>
<p>In this article, I showed you many ways to send email from the Linux command line. Hopefully, based on what you saw, you can install and configure these services on your machine yourself as well.</p>
<p>The post showed the most commonly used command line mailer packages and how to send emails with them, and in the end, I created a shell script that gathers all the commands used in the article. You can download <a href="https://edmdesigner.github.io/html-email-development-tools/lesson-terminal/commandlinesending.zip">the projects working files here</a>, and if you install the packages introduced in the tutorial and also fill in your credentials and recipient details, you can run the script at your leisure.</p>
<p>Could you follow each step of the tutorial? Very well then, it makes me glad. In case you have questions or see an opportunity to improve the content further by your ideas, please head to the comment section below.</p>
<p>Thanks for your attention. Happy sending!</p>
</div>]]></content:encoded></item><item><title><![CDATA[How to Create Responsive Email Designs with React Native]]></title><description><![CDATA[Responsive email coding is complex. Are you native in React Native? Abstract away email HTML & CSS into components with react-html-email or mjml frameworks.]]></description><link>https://blog.edmdesigner.com/react-native-responsive-email-design/</link><guid isPermaLink="false">5afad21c3bed88001585fbad</guid><category><![CDATA[responsive email]]></category><category><![CDATA[Components]]></category><category><![CDATA[Email markup language]]></category><category><![CDATA[responsive framework]]></category><category><![CDATA[optimized images]]></category><category><![CDATA[mjml]]></category><category><![CDATA[Javascript]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 28 Feb 2018 10:24:00 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2018/02/react-native-email-design.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2018/02/react-native-email-design.png" alt="How to Create Responsive Email Designs with React Native"><p>Responsive design is a factor that you need to consider while building applications, sending out emails, and designing templates. If the design looks awful on a small screen, more than half of your customers will feel dejected and the numbers are not going to get better.</p>
<p>Email development has many challenges on it's own. We tackled many of these topics <a href="https://blog.edmdesigner.com/tag/modern-html-email-tutorial/">in a previous article series.</a>  Imagine receiving a newsletter into your inbox with a broken layout, poor grid system and a microscopic font style that’s impossible to read without zooming in. As the web is being veered off into a mobile first environment, the strategy for designing emails needs to be upgraded.</p>
<p>In this post — written by <a href="https://cloudinary.com/">Cloudinary</a>, a leading SaaS technology company in digital asset management — we will discuss some of the basics things that you need to take care of while creating a responsive email design using a web/mobile application. As a developer, you might have to integrate responsively designed email templates into your application UI or create templates on the fly. This post will teach you how to do that for an application built using React Native.</p>
<h2 id="whyreactnative">Why React Native?</h2>
<p>React Native, as you might already know, is a popular framework for building cross-platform mobile apps for Android and iOS, which perform as well as a native application. It uses similar technology to that of its web counterpart, ReactJS. Both React and React Native are gaining grounds in terms of user base and popularity. If you’re developing a website and a mobile app for your product, you can reuse some components between React and React Native (for some information about this type of conversion, see <a href="https://medium.com/@gwen_faraday/converting-a-react-app-to-react-native-d7df17968fc6">this post</a>).</p>
<p>As a developer, you might be asked to integrate responsively designed email templates into your application UI, or to create templates on the fly and send them to a bunch of recipients. You can use an API to send the email to the recipients and that’s the easy part. But building a dynamic front-end layout for sending an email with multiple themes and images might be harder to do.</p>
<p>The steps involved are pretty much similar to that of building a responsive design using CSS. However, with React’s component architecture, you can use use third-party components to compose responsive templates that are dynamic and reusable.</p>
<p>For the purpose of this tutorial, we are going to use create-react-native-package to build a new React Native project.</p>
<pre><code>      npm install create-react-native-app
      create-react-native-app responsive-email
</code></pre>
<p>Now that we have that out of the way, let’s see what we can do to make the email responsive.</p>
<h2 id="createemailtemplatesusingreacthtmlemaillibrary">Create Email Templates using react-html-email Library</h2>
<p>There is an awesome library called react-html-email that lets you write reusable <a href="https://blog.edmdesigner.com/the-basics-of-modern-html-emails/#components">component based emails</a>. The library has a renderEmail() method that accepts an input component and renders it into an HTML string. Install the library by running</p>
<pre><code>      npm install --save react-html-email
</code></pre>
<p>Next, use the following code to generate a very basic email.</p>
<pre><code>      import { Email, Item, A, renderEmail } from 'react-html-email';

      const BasicEmail = () =&gt; (

        &lt;Email title='link'&gt;
          &lt;Test&gt; Hi &lt;/Test&gt;
          &lt;Item&gt;
            &lt;A href=&quot;#&quot; style={{ paddingLeft: 10 }}&gt;Hello Buddy!&lt;/A&gt;
          &lt;/Item&gt;
        &lt;/Email&gt;

      );
        renderEmail(&lt;InlineLink /&gt;);
</code></pre>
<p>The library exports a few components like Email, Box,Span Item, A and Image. This covers almost all of the basic tags that you’d require in an email. After composing the email template, you can pass it onto renderEmail() to generate the HTML string.  Here’s an example output string:</p>
<pre><code>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;&lt;html lang=&quot;en&quot; xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;&lt;head&gt;&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;/&gt;&lt;title&gt;link&lt;/title&gt;&lt;/head&gt;&lt;body style=&quot;width:100%;margin:0;padding:0;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%&quot;&gt;&lt;table width=&quot;100%&quot; height=&quot;100%&quot; cellPadding=&quot;0&quot; cellSpacing=&quot;0&quot; border=&quot;0&quot; align=&quot;left&quot; valign=&quot;top&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td align=&quot;center&quot; valign=&quot;top&quot;&gt;&lt;table width=&quot;600&quot; align=&quot;center&quot; cellPadding=&quot;0&quot; cellSpacing=&quot;0&quot; border=&quot;0&quot; valign=&quot;top&quot;&gt;&lt;tbody&gt;&lt;div&gt; Test &lt;/div&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;#&quot; target=&quot;_blank&quot; style=&quot;text-decoration:underline;padding-left:10px&quot;&gt;Hello Buddy!&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;
</code></pre>
<p>One of the good things about react-html-email is that it has an inbuilt validator that checks your HTML for compatibility against popular email clients. It returns a warning or an error when a validation check fails. If you ran the above code, you’d get a warning in the console like this:</p>
<pre><code>Warning: Style property `padding-left` supplied to `A`, 
in outlook: padding for p, div and a tags is not supported
</code></pre>
<h2 id="addresponsivedesignusingmediaquery">Add Responsive Design using Media Query</h2>
<p>Media queries are important for creating responsive designs. When you have to develop for smaller screens, you can use the @media declaration to specify the viewport of the screen that the style should apply to. Most of the major email clients support media queries and allow the inclusion of query styles in <head>.</head></p>
<p>The Email component that we created earlier accepts a headCSS prop. You can use this space to declare all the styles that should go into the <head> section. For instance, if you need to override the font-size to 14px for all devices with screen size 480px or less, you can do something like this:</head></p>
<pre><code>      const css = `@media only screen and (max-device-width: 480px) {
        font-size: 14px !important;
        text-align: center !important;
      }`.trim()
</code></pre>
<p>If you forget to add the the !important rule, other inline styles could override these declarations.</p>
<p>Now, add the headCSS prop to the Email component.</p>
<pre><code>      &lt;Email title=&quot;Test Email&quot; headCSS={css}&gt;
      //Removed for Brevity
      &lt;/Email&gt;
</code></pre>
<h2 id="optimizeimagesformobile">Optimize Images for Mobile</h2>
<p>Rendering optimized images based on screen size helps you create an attractive layout. For example, if you need a <a href="https://blog.edmdesigner.com/background-images-in-modern-html-emails/">background image</a> for the header, you can use a fluid image layout that looks like this.</p>
<pre><code>      @media only screen and (max-device-width: 480px) {
      .header {
          background-image: url(https://www.example.com/image.png) !important;
          background-size: cover;
          }
      }
</code></pre>
<p>You can also stick to the traditional method, such as setting background-size to 100% if you’re not sure about compatibility.</p>
<p>For serving high-resolution images, the actual images will need to be twice their display size. You can use an image uploader component to add <a href="https://cloudinary.com/visualweb/display/IMMC/React+Native+Image+Upload">React Native images</a> into the mix and then host them in different resolutions in the cloud. Based on screen size, the server will return a resolution of the image that aptly fits the screen size.</p>
<h2 id="responsivenessusingmjmlframework">Responsiveness using MJML framework</h2>
<p>We’d like to introduce you to another approach to <a href="https://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts/">automate the process of creating emails</a>. MJML is a framework that was developed to reduce the pain of coding responsive emails. The framework isn’t React Native specific, but most of the features work with the React architecture. Prior to version 4, MJML used React components to render the output HTML and hence was fully compatible.</p>
<p>Being a framework, MJML lets you create reusable components that can be used to create email templates. It has an ecosystem of tools and plugins that you can use to extend the framework’s abilities.</p>
<p>To generate a basic responsive email using MJML, install mjml if you haven’t already, and import the mjml2html API. Create a basic mjml string like the one below, compile it and output it to the console.</p>
<pre><code>      /*
        Compile an mjml string
      */
      const htmlOutput = mjml2html(`
        &lt;mjml&gt;
          &lt;mj-body&gt;
            &lt;mj-section&gt;
              &lt;mj-column&gt;
                &lt;mj-text&gt;
                  Hello World!
                &lt;/mj-text&gt;
              &lt;/mj-column&gt;
            &lt;/mj-section&gt;
          &lt;/mj-body&gt;
        &lt;/mjml&gt;
      `)


      /*
        Print the responsive HTML*/
      console.log(htmlOutput)
</code></pre>
<p>MJML has its own responsive layout and a grid system that complements the layout. The whole email can be composed of multiple sections as shown in the code above. You can <a href="https://mjml.io/" rel="nofollow">read more about the layout structuring</a> in the documentation.</p>
<h2 id="summary">Summary</h2>
<p>In this tutorial, we’ve covered some of the common techniques that you can use to compose responsive emails using React components. For building a front-end responsive email solution using React Native, you have multiple open-source tools like react-html-email and MJML that you can import into your project. The former is a small library that you can further customize depending on your requirements, whereas MJML is a full-fledged framework with focus on responsiveness.</p>
<p>Experiment with both the options and choose the one which works for you. If you have alternate ideas for integrating responsive email templates into a React Native project, share them in the comments!</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
</div>]]></content:encoded></item><item><title><![CDATA[Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES]]></title><description><![CDATA[Ever wondered how to use PHP for sending HTML email templates with Mailgun, Sendgrid and Amazon SES? Read on for step-by-step coding advice.]]></description><link>https://blog.edmdesigner.com/php-sending-html-emails/</link><guid isPermaLink="false">5afad21c3bed88001585fbaa</guid><category><![CDATA[PHP]]></category><category><![CDATA[Email delivery platform]]></category><category><![CDATA[Amazon SES]]></category><category><![CDATA[Email API]]></category><category><![CDATA[Mailgun]]></category><category><![CDATA[Sendgrid]]></category><category><![CDATA[Email sending]]></category><category><![CDATA[Sending with PHP]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 24 Jan 2018 14:36:11 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2018/01/sending-html-email-php-amazon-ses-sendgrid-mailgun-1.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2018/01/sending-html-email-php-amazon-ses-sendgrid-mailgun-1.jpg" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"><p>We have already discussed the PHP native mail() method and PHP mailer packages <a href="https://blog.edmdesigner.com/sending-email-with-php/">in a previous article</a>. First, we covered the mail() method features - such as sending rich HTML email templates with attachments. They were satisfactory on their own.</p>
<p>Additionally, we looked at two of the most frequently used packages, <strong><a href="http://pear.php.net/package/Mail">PEAR Mail package</a></strong> and <strong><a href="https://packagist.org/packages/phpmailer/phpmailer">PHP Mailer</a></strong>. We went through the installation steps and saw the value added by their use.</p>
<p>This includes, but is not limited to:</p>
<ul>
<li>The choice of configuring external SMTP directly from the code</li>
<li>Easier handling of header fields and attachments</li>
<li>Cleaner syntax and</li>
<li>Built-in security features</li>
</ul>
<p>Although these PHP mailer packages may be used for transactional emails as well as bulk sending for email lists, email cloud-based APIs are considered better solutions. There are several reasons for behind this. The most important one is that cloud hosts often prevent sending emails to preserve domain reputation. If you don't follow every requirement your emails may not be sent. The use of email APIs raises sending reliability and API providers also offer services that improve delivery rates.</p>
<p>Another reason is that when mass emails - eg. hundreds of thousands - are sent, you'll probably want to know statistics and also want smart tools to manage unsubscribes and email lists based on recipient behavior. They also help to simplify the required PHP mailing scripts, which is also a benefit from a developer's point of view.</p>
<p>Within this article, I'll show you three of the most popular choices for bulk email sending using PHP code. You'll see how to set these services up and you'll learn about some useful things such as a step-by-step description of how to include an image attachment with PHP script or how to create a reusable email template.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="sendinghtmlemailtemplatesusingmailgun">Sending HTML Email Templates Using Mailgun</h2>
<p><a href="https://www.mailgun.com/">Mailgun</a> is a wonderful email API for sending transactional emails. As an email API should, they put a big emphasis on deliverability and domain reputation. You can set up multiple domains with isolated reputation, <a href="https://en.wikipedia.org/wiki/DomainKeys_Identified_Mail">DKIM</a> or <a href="https://en.wikipedia.org/wiki/Sender_Policy_Framework">SPF</a> email sender validation, which is all key when it comes to managing reliable email sending.</p>
<p>To gain access to their API, first, you need to <a href="https://signup.mailgun.com/new/signup">sign up</a> on their webpage to get an Access Key. The key will enable the use of the API services. By first, you need to provide your contact details and information about your estimated email sending volume:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/mailgun-signup.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>Then an opt-in account verification email will be delivered to your inbox.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/mailgun-verify.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>After confirmation, you'll be faced with a quick setup guide:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/mailgun-setup.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>You can choose the desired programming language and get started immediately. Moving on, I'll walk you through the PHP code implementation. Setting up a PHP wrapper script for Mailgun is really straightforward.</p>
<p><strong>The steps are the following:</strong></p>
<ul>
<li>Include the vendor/autoloader.php script (when using Composer)</li>
<li>Instantiate the client</li>
<li>Make the call to the client</li>
</ul>
<p><strong>Other third-party services follow the same logic</strong> so you better store this piece of information really well.</p>
<p>Building PHP projects become much easier using the Composer dependency manager. If you are new to using Composer, read about <a href="https://blog.edmdesigner.com/sending-email-with-php/#gettingstartedwithcomposer">the installation details and the background about it.</a> It'll make PHP email sending much easier.</p>
<p>For now, we just go through with the necessary steps to have Mailgun ready for use with PHP:</p>
<pre><code>    1. Run in the terminal: $ composer init

    2. Answer the setup wizard questions:

        example 1: Would you like to define your
                dependencies (require) interactively [yes]? no
        example 2: Do you confirm generation [yes]? yes

    3. Add these to the generated 'composer.json' file:

        &quot;require&quot;: {
            &quot;mailgun/mailgun-php&quot;: &quot;^2.4&quot;,
            &quot;php-http/curl-client&quot;: &quot;^1.7&quot;,
            &quot;guzzlehttp/psr7&quot;: &quot;^1.4&quot;
        }

    4. Run in the terminal: $ composer install
</code></pre>
<p>Do you remember the 3-step list from the beginning of the section? Good, because that's what we'll continue with:</p>
<pre><code class="language-PHP">         &lt;?php

            # Include the Autoloader

            require 'vendor/autoload.php';
            use Mailgun\Mailgun;

            # Instantiate the client.

            $mgClient = new Mailgun('key-7e55d003b6608b22...943f79accd31a');
            $domain = &quot;sandbox21a78f824a064bc58...13eb160ebc79.mailgun.org&quot;;

            # Make the call to the client.

            $result = $mgClient-&gt;sendMessage($domain,
                    array('from'    =&gt; 'Developer &lt;developer@edmdesigner.com&gt;',
                            'to'      =&gt; 'Friendly User &lt;user@yourcompany.com&gt;',
                            'subject' =&gt; 'Hello Friendly User',
                            'text'    =&gt; 'Testing some Mailgun awesomeness with PHP!'));
        ?&gt;
</code></pre>
<p>If you use the script in a web application, you should store the Mailgun API key and other sensitive data in environment variables.</p>
<p>The only thing you might not know already is where to find your domain and the corresponding API key. There's no need to worry, just sign in to your Mailgun account end select the &quot;Domain&quot; navigation item:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/mailgun-apikey.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>This was the most basic implementation of the Mailgun API with a PHP wrapper. Let's see a more compound example code of PHP with attachments and other customization!</p>
<h3 id="htmlandimageattachmentwithphpmailgunapiwrapper">HTML and Image Attachment with PHP Mailgun API Wrapper</h3>
<p>In the previous section, we uncovered how to use the <code>sendMessage</code> function with the key parameters. Now, we'll reveal a few more properties we could use.</p>
<p>Working at a company providing bulletproof HTML email templates with <a href="https://edmdesigner.com/">drag &amp; drop editor</a>, I always consider the support of HTML format as a primary objective in emailing. Luckily, the <code>sendMessage</code> function accepts HTML without any complication. Add an HTML email template file to your working folder, complete the PHP wrapper with these missing lines:</p>
<pre><code>            # 1. Reading the contents of the HTML email template
            $htmlContent = file_get_contents(&quot;htmlContent.html&quot;);

            # 2. Reference the HTML content in the array of the 
            #    sendMessage function's second parameter
                'html'    =&gt; $htmlContent

</code></pre>
<p>It may not bother you right now, but later you might want to add email attachments such as images or PDF documents as well. That can be done by adding a third parameter to the <code>sendMessage</code> function. This also has to be an array as the parameter before. As a result, you could reference multiple sources within that at the same time. The full example including the image attachments, HTML email template, seasoned with multiple recipients looks as follows:</p>
<pre><code class="language-PHP">        &lt;?php
        # Include the Autoloader
        require 'vendor/autoload.php';
        use Mailgun\Mailgun;

        # Instantiate the client.
        $mgClient = new Mailgun('API-Key');
        $domain = &quot;sandboxdomain.mailgun.org&quot;;

        # Reading the contents of the HTML email template
        $htmlContent = file_get_contents(&quot;htmlContent.html&quot;);

        # Make the call to the client.

        $result = $mgClient-&gt;sendMessage(
            $domain,
            array(
                'from'    =&gt;
                    'Developer &lt;developer@edmdesigner.com&gt;',
                'to'      =&gt;
                    'Friendly User &lt;user@yourcompany.com&gt;',
                'subject' =&gt;
                    'Hello Friendly User',
                'text'    =&gt;
                    'Testing some Mailgun awesomeness with PHP!',
                'cc'      =&gt;
                    'Developer2 &lt;developer2@edmdesigner.com&gt;',
                'bcc'     =&gt;
                    'Friendly User2 &lt;user2@yourcompany.com&gt;',

                'html'    =&gt; $htmlContent
            ),
            array(
                'attachment' =&gt;
                    array('./logo2yellow.jpg','./logo2yellow.jpg'
            )
        ));

        ?&gt;
</code></pre>
<p>You may also be interested in seeing the example of email HTML code as well:</p>
<pre><code class="language-HTML">
&lt;!DOCTYPE html&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;  xmlns:v=&quot;urn:schemas-microsoft-com:vml&quot;&gt;
  &lt;head&gt;
    &lt;title&gt;Sending Email with Mailgun API PHP Wrapper&lt;/title&gt;
	&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;style&gt;
      html,
      body,
      table,
      tbody,
      tr,
      td,
      div,
      p,
      ul,
      ol,
      li,
      h1,
      h2,
      h3,
      h4,
      h5,
      h6 {
        margin: 0;
        padding: 0;
      }

      body {
        margin: 0;
        padding: 0;
        font-size: 0;
        line-height: 0;
        -ms-text-size-adjust: 100%;
        -webkit-text-size-adjust: 100%;
      }

      table {
        border-spacing: 0;
        mso-table-lspace: 0pt;
        mso-table-rspace: 0pt;
      }

      table td {
        border-collapse: collapse;
      }

      .ExternalClass {
        width: 100%;
      }

      .ExternalClass,
      .ExternalClass p,
      .ExternalClass span,
      .ExternalClass font,
      .ExternalClass td,
      .ExternalClass div {
        line-height: 100%;
      }
      /* Outermost container in Outlook.com */

      .ReadMsgBody {
        width: 100%;
      }

      img {
        -ms-interpolation-mode: bicubic;
      }

      h1,
      h2,
      h3,
      h4,
      h5,
      h6 {
        font-family: Arial;
      }

      h1 {
        font-size: 28px;
		font-weight:normal;
        line-height: 32px;
        padding-top: 10px;
        padding-bottom: 24px;
      }


      h2 {
        font-size: 24px;
        line-height: 28px;
        padding-top: 10px;
        padding-bottom: 20px;
      }

      h3 {
        font-size: 20px;
        line-height: 24px;
        padding-top: 10px;
        padding-bottom: 16px;
      }

      h4 {
        font-size: 18px;
        line-height: 21px;
        padding-top: 10px;
        padding-bottom: 12px;
      }

      h5 {
        font-size: 16px;
        line-height: 21px;
        padding-top: 10px;
        padding-bottom: 8px;
      }

      h6 {
        font-size: 14px;
        line-height: 21px;
        padding-top: 10px;
        padding-bottom: 8px;
      }

      p {
        font-size: 16px;
        line-height: 20px;
        font-family: Georgia, Arial, sans-serif;
      }

      @media all and (max-width: 599px) {
        .container600 {
          width: 100%;
        }
      }
    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body style=&quot;background-color:#F4F4F4;&quot;&gt;


    &lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;min-width:100%;&quot;&gt;
      &lt;tr&gt;
        &lt;td width=&quot;100%&quot; style=&quot;min-width:100%;background-color:#F4F4F4;padding:10px;&quot;&gt;
          &lt;center&gt;
            &lt;table class=&quot;container600&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; width=&quot;600&quot; style=&quot;margin:0 auto;&quot;&gt;
              &lt;tr&gt;
                &lt;td width=&quot;100%&quot; style=&quot;text-align:left;&quot;&gt;
                  &lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;min-width:100%;&quot;&gt;
                    &lt;tr&gt;
                      &lt;td width=&quot;100%&quot; style=&quot;min-width:100%;background-color:#FFFFFF;color:#000000;padding:30px;&quot;&gt;
                        &lt;img alt=&quot;&quot; src=&quot;https://edmdesigner.github.io/modern-html-email-tutorial/lesson08/img/logo.png&quot; width=&quot;210&quot; style=&quot;display: block;&quot; /&gt;
                      &lt;/td&gt;
                    &lt;/tr&gt;
                  &lt;/table&gt;
                  &lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;min-width:100%;&quot;&gt;
                    &lt;tr&gt;
                      &lt;td width=&quot;100%&quot; style=&quot;min-width:100%;background-color:#F8F7F0;color:#58585A;padding:30px;&quot;&gt;
							&lt;h1 style=&quot;font-family:Arial;font-size:36px;line-height:44px;padding-top:10px;padding-bottom:10px&quot;&gt;Mailgun Test Email with PHP&lt;/h1&gt;

							&lt;p&gt;This is some memorable HTML you could send with Mailgun in the blink of an eye.&lt;/p&gt;
							&lt;br&gt;

							&lt;h2&gt;Note the attachments as well.&lt;/h2&gt;
                      &lt;/td&gt;
                    &lt;/tr&gt;
                  &lt;/table&gt;
                  &lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;min-width:100%;&quot;&gt;
                    &lt;tr&gt;
                      &lt;td width=&quot;100%&quot; style=&quot;min-width:100%;background-color:#58585A;color:#FFFFFF;padding:30px;&quot;&gt;
                        &lt;p style=&quot;font-size:16px;line-height:20px;font-family:Georgia,Arial,sans-serif;text-align:center;&quot;&gt;2017 @ COPYRIGHT - EDMDESIGNER&lt;/p&gt;
                      &lt;/td&gt;
                    &lt;/tr&gt;
                  &lt;/table&gt;
                &lt;/td&gt;
              &lt;/tr&gt;
            &lt;/table&gt;
          &lt;/center&gt;
        &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/table&gt;
  &lt;/body&gt;
&lt;/html&gt;

</code></pre>
<p>The heavy use of tables in the HTML is the result of email design best practice.<br>
There are many <a href="https://blog.edmdesigner.com/modern-html-email-tutorial/">though spots</a> in coding HTML emails.</p>
<p>And delivered to the inbox:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/mailgun-inbox.jpg" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>There are plenty of other parameters you could use. The full list is available <a href="https://documentation.mailgun.com/en/latest/api-sending.html#sending">following this link.</a></p>
<h2 id="sendingemailtemplatesusingsendgrid">Sending Email Templates Using Sendgrid</h2>
<p>While Mailgun was an easy to use mass email-sending service, Sendgrid is a little more compound, as it offers an HTML builder and several out-of-box integrations for popular CMS solutions. For this reason, it takes a little more time to find our ways around <a href="https://sendgrid.com/docs/index.html">in the documentation</a>, but otherwise, it's still easy to set up mailing with Sendgrid.</p>
<p>The process is very similar as before. You <strong><a href="https://sendgrid.com/user/sign-up">signup to obtain an API key</a></strong>, then <strong>use that key to leverage the API</strong> functionalities according to your needs. That's followed by the <strong>3-step process of PHP wrapper creation</strong>: autoloader.php include, client instantiation and client calls.</p>
<p>This looks as follows with Sendgrid:</p>
<p>1, On first login you'll be directed to the setup guide. Select &quot;Integrate using our Web API or SMTP relay&quot; option by clicking &quot;Start&quot;.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/sendgrid-guide.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>2, On the next page as recommended, select the Web API option and on the screen after that your desired programming language - make sure that it's PHP!</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/sendgrid-web-api.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>Let's look at the code that delivers our message:</p>
<pre><code class="language-PHP">    &lt;?php
        require 'vendor/autoload.php';

        $from = new SendGrid\Email(&quot;Developer&quot;, &quot;developer@edmdesigner.com&quot;);
        $subject = &quot;Sending with SendGrid is Fun&quot;;
        $to = new SendGrid\Email(&quot;Friendly User&quot;, &quot;user@yourcompany.com&quot;);
        $content = new SendGrid\Content(&quot;text/plain&quot;, &quot;and easy to do anywhere, even with PHP&quot;);
        $mail = new SendGrid\Mail($from, $subject, $to, $content);

        $apiKey = getenv('SENDGRID_API_KEY');

        $sg = new \SendGrid($apiKey);

        $response = $sg-&gt;client-&gt;mail()-&gt;send()-&gt;post($mail);

        echo $response-&gt;statusCode();
        print_r($response-&gt;headers());
        echo $response-&gt;body();
    ?&gt;
</code></pre>
<p>If you look at the example, you can spot that this time we want to access all information about the HTTP response from the API. That's very good for practice because you can debug failing delivery more easily. For example, if you omit a variable from the <code>mail()</code> method, the <code>statusCode()</code>'s return value <code>400</code> may not give you much help, but the request header and request body will tell a lot about the issue.</p>
<h3 id="htmlandimageattachmentwithphpsendgridapiwrapper">HTML and Image Attachment with PHP Sendgrid API Wrapper</h3>
<p>Adding attachments requires the Sengrid <code>$attachment</code> object. There are five required parameters in the process: the arbitrary content Id, the base64 encoded image content, the file type, the include method and you can customize the file name. These are set with the call to the appropriate &quot;setter&quot; functions:</p>
<pre><code class="language-PHP">       // Setting the ID of the attachment
       $attachment = new SendGrid\Attachment();
       $attachment-&gt;setContentId(&quot;myId&quot;);
</code></pre>
<p>When you provided all 5 properties, you need to call the <code>addAttachment</code> method of the <code>$mail</code> helper class. As I mentioned before I always want to test if I can use HTML to my emails. Fortunately, it can be applied without any difficulty. We just need to provide it to the Content class:</p>
<pre><code class="language-PHP">        $htmlContent = file_get_contents(&quot;htmlContent.html&quot;);
        $content = new SendGrid\Content(&quot;text/html&quot;, $htmlContent);
</code></pre>
<p>The full example code looks as follows:</p>
<pre><code class="language-PHP">    &lt;?php
        require 'vendor/autoload.php';
        
        // 
        $from = new SendGrid\Email(&quot;Developer&quot;, &quot;developer@edmdesigner.com&quot;);
        $subject = &quot;Sending with SendGrid is Fun&quot;;
        $to = new SendGrid\Email(&quot;Friendly User&quot;, &quot;user@yourcompany.com&quot;);
        $htmlContent = file_get_contents(&quot;htmlContent.html&quot;);
        $content = new SendGrid\Content(&quot;text/html&quot;, $htmlContent);

        $mail = new SendGrid\Mail($from, $subject, $to, $content);

        
        $file_encoded = base64_encode(file_get_contents($filePath));

        $attachment = new SendGrid\Attachment();
        $attachment-&gt;setContent($file_encoded);
        $attachment-&gt;setContentId(&quot;myId&quot;);
        $attachment-&gt;setType(&quot;image/jpg&quot;);
        $attachment-&gt;setDisposition(&quot;attachment&quot;);
        $attachment-&gt;setFilename(&quot;logo2yellow.jpg&quot;);

        $mail = new SendGrid\Mail($from, $subject, $to, $content);
        $mail-&gt;addAttachment($attachment);

        $apiKey = getenv('SENDGRID_API_KEY');

        $sg = new \SendGrid($apiKey);

        $response = $sg-&gt;client-&gt;mail()-&gt;send()-&gt;post($mail);

        echo $response-&gt;statusCode();
        print_r($response-&gt;headers());
        echo $response-&gt;body();
    ?&gt;
</code></pre>
<p>I hope the steps were easy to follow. If you have any questions don't hesitate to ask them in the comment section, below the article.</p>
<h2 id="sendingemailtemplatesusingamazonses">Sending Email Templates Using Amazon SES</h2>
<p>Our last candidate is a product of the biggest cloud infrastructure provider in the world. <a href="https://aws.amazon.com/ses/">Amazon SES</a> stands for Amazon Simple Email Service. It's a cloud-hosted email delivery platform with <a href="https://aws.amazon.com/ses/pricing/">a pay-per-use price-model</a>. This makes it a scalable and affordable service for multiple uses. As with other Amazon services, there's a <a href="https://aws.amazon.com/blogs/ses/the-amazon-ses-free-tier/">free tier provided</a> for developers' testing purposes. We'll take advantage of that right now!</p>
<h3 id="sendingemailtemplatesusingtheawssdk">Sending Email Templates Using the AWS SDK</h3>
<p>An Amazon registration is slightly different from the previously showcased email APIs, as you must provide credit card information and billing address as part of the sign-up process.</p>
<p><a href="https://aws.amazon.com/documentation/ses/"><img src="https://blog.edmdesigner.com/content/images/2018/01/create-aws-ses-account.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></a></p>
<p>After registration there's an additional step you need to complete to be able to send test emails: <strong>you need to <a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/verify-email-addresses-procedure.html">verify the email addresses</a></strong> you'll use for sending and receiving. Otherwise, you'll receive such errors:</p>
<pre><code>      The email was not sent. Error message: 
      Email address is not verified. The following 
      identities failed the check in region US-WEST-2: 
      &lt;the address you used in your code&gt; 
</code></pre>
<p>You can do this verification on the Amazon SES dashboard. That's a minor added complication compared to Mailgun or Sendgrid.</p>
<p>To obtain the API key and corresponding API secret follow these steps in the dashboard:</p>
<ul>
<li>Click Your name in the navigation drop-down</li>
<li>Select &quot;My security credentials&quot; option</li>
<li>Click &quot;Continue to Security Credentials&quot; in the pop-up modal</li>
<li>From the accordion menus select &quot;Access Keys&quot;</li>
<li>Hit &quot;Create New Access Key&quot;</li>
<li>Then either click &quot;Show Access Key&quot; to activate the drop-down or &quot;Download Key File&quot; (that's better if you include it with environment variables)</li>
</ul>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/aws-create-access-key.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>Next, you'll need the following code:</p>
<pre><code class="language-PHP">    &lt;?php

        // Replace path_to_sdk_inclusion with the path to the SDK as described in
        define('REQUIRED_FILE','vendor/autoload.php');
        require REQUIRED_FILE;

        use Aws\Ses\SesClient;
        use Aws\Ses\Exception\SesException;

        // Require previously created HTML email template and other content items
        define('HTMLBODY', file_get_contents('htmlContent.html'));
        define('TEXTBODY', &quot;&lt;include the text version of the email template&gt;&quot;);
        define('SUBJECT','Amazon SES test (AWS SDK for PHP)');

        // Replace sender@example.com with your &quot;From&quot; address.
        // This address must be verified with Amazon SES.
        define('SENDER', 'developer@edmdesigner.com');

        // Replace recipient@example.com with a &quot;To&quot; address. If your account
        // is still in the sandbox, this address must be verified.
        define('RECIPIENT', 'friendly.user@company.com');

        // Include the AWS Region you're using for Amazon SES.
        define('REGION','us-west-2');

        define('CHARSET','UTF-8');

        // Instantiate SesClient class
        $client = SesClient::factory(array(
            'version'=&gt; 'latest',
            'region' =&gt; REGION
        ));

        // Send email with the defined named constants
        try {
            $result = $client-&gt;sendEmail([
            'Destination' =&gt; [
                'ToAddresses' =&gt; [
                    RECIPIENT,
                ],
            ],
            'Message' =&gt; [
                'Body' =&gt; [
                    'Html' =&gt; [
                        'Charset' =&gt; CHARSET,
                        'Data' =&gt; HTMLBODY,
                    ],
                    'Text' =&gt; [
                        'Charset' =&gt; CHARSET,
                        'Data' =&gt; TEXTBODY,
                    ],
                ],
                'Subject' =&gt; [
                    'Charset' =&gt; CHARSET,
                    'Data' =&gt; SUBJECT,
                ],
            ],
            'Source' =&gt; SENDER
        ]);

            $messageId = $result-&gt;get('MessageId');
            echo(&quot;Email sent! Message ID: $messageId&quot;.&quot;\n&quot;);

        } catch (SesException $error) {
            echo(&quot;The email was not sent. Error message: &quot;
                .
            $error-&gt;getAwsErrorMessage().&quot;\n&quot;);
        }

    ?&gt;
</code></pre>
<p>Let's see step-by-step what this piece of code contains:</p>
<ul>
<li>First you require the Autoloader to be able to access the AWS SDK classes. We'll need the <code>SesClient</code> and <code>SesException</code> classes, so we refer them to the <a href="http://uk3.php.net/manual/en/language.namespaces.importing.php">use operator</a></li>
<li>Next, provide the variables for the <code>sendEmail</code> function with named variables using the <a href="http://php.net/manual/en/function.define.php">define method</a></li>
<li>Last we instantiate the SesClient class into a <code>$client</code> variable and in a &quot;try-catch block&quot; we call the <code>sendEmail</code> function of SesClient and print a success message or the error based on the delivery result</li>
</ul>
<p>I bet you feel excited now. You head to the console to run the script: <code>php &lt;yourfile&gt;.php</code> and you receive: <code>Error message: Email address is not verified.</code> That's what I mentioned previously. Without verified addresses, you can't deliver emails, not even in sandbox mode. So, let's fix it.</p>
<p>Navigate to the Amazos SES dashboard:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/aws-ses.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>and once it loaded go to &quot;Email Addresses&quot; under &quot;Identity Management&quot;. You can add the email addresses you want to use there. When you retry you'll receive a success message and as the retrieval of the <code>MessageId</code> was set in the code, you'll also receive this Id that you can use to track your message delivery in the dashboard.</p>
<pre><code>      Email sent! Message ID: 
      01010160fe95d93d-b7bc4b30-ebdf-4380-b2cf-b21771....
</code></pre>
<p>That's it! You sent your first email using Amazon SES and PHP. If you didn't receive it, <a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/delivery-problems.html">this guide</a> can cast light on what could have gone wrong.</p>
<p>In the next section, I'll show you how to use some features of the API.</p>
<p><a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/create-shared-credentials-file.html">https://docs.aws.amazon.com/ses/latest/DeveloperGuide/create-shared-credentials-file.html</a></p>
<h3 id="amazonsesapiforsendinghtmlemailtemplates">Amazon SES API For Sending HTML Email Templates</h3>
<p>We've seen how to send an HTML email template using Amazon SES with the file given at a certain location in your file-system. If you implement the PHP wrapper on a server that's all well and good or if you send it from your local machine. But wouldn't it be better if you could use templates stored in your Amazon SES account?</p>
<p>It certainly makes sense, and as it's just a few additional lines of code, I'll show you how to do it programmatically. You can fully re-use the code from the previous section.</p>
<p>We are going to use the <a href="https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-email-2010-12-01.html#sendtemplatedemail">necessary fields and methods</a> of the Amazon SES API. Learning about these will enable you to create more complex code examples.</p>
<p>The first thing to do is to <strong>create a configuration set</strong>. On the client let's call the <code>createConfigurationSet</code> method as follows:</p>
<pre><code class="language-PHP">        $client-&gt;createConfigurationSet([
            'ConfigurationSet' =&gt; [ // REQUIRED
                'Name' =&gt; 'FirstSet', // REQUIRED
            ],
        ]);
</code></pre>
<p>Creating a template works similarly, we just switch the method and the supplied parameters:</p>
<pre><code class="language-PHP">        $client-&gt;createTemplate([
            'Template' =&gt; [ // REQUIRED
            'HtmlPart' =&gt; $htmlContent,
            'SubjectPart' =&gt; 'Subject of first awesomeness',
            'TemplateName' =&gt; 'Templating-101', // REQUIRED
            'TextPart' =&gt; 'This is just text']
        ]);
</code></pre>
<p>As you can see above, I supplement the HTML for the template as before by assigning the variable containing the HTML to the corresponding property.</p>
<p>If you insert these two pieces of code into the previously shown PHP wrapper and run the script, your AWS SES account will be enriched with your brand new template:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2018/01/aws-ses-template.png" alt="Using PHP for Sending HTML Emails with Mailgun, Sendgrid & Amazon SES"></p>
<p>As the next step, we need to move these bits of code into a separate file or comment it out, as we don't want to make duplicates of the configuration settings and the template (actually we can't with the same names): <code>The email was not sent. Error message: Configuration set &lt;FirstSet&gt; already exists.</code></p>
<p>So the template is created, unnecessary code taken out, we just need to reference the created template:</p>
<pre><code class="language-PHP">    $result = $client-&gt;sendTemplatedEmail([
        'ConfigurationSetName' =&gt; 'FirstSet',
        'Destination' =&gt; [ // REQUIRED
            'ToAddresses' =&gt; ['friendlyUser1@company.com',
             'friendlyUser2@company.com']
        ],
        'Source' =&gt; 'developer@edmdesinger.com', // REQUIRED
        'Tags' =&gt; [
            [
                'Name' =&gt; 'Name', // REQUIRED
                'Value' =&gt; 'Value', // REQUIRED
            ],
        ],
        'Template' =&gt; 'Templating-101', // REQUIRED
        'TemplateData' =&gt; 'jsonValues for template', // REQUIRED
    ]);
</code></pre>
<p>If you included it correctly, your message will be delivered to the recipients without any problems. Note, that <code>sendEmail</code> method is replaced by<code>sendTemplatedEmail</code> to allow the use of the template from the Amazon account. Once you're done testing and ready to move to production, you can request a sending limit increase and move your account out of the <a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/request-production-access.html">limited sandbox environment</a>.</p>
<p>If you're really serious about getting to know Amazon SES check out <a href="https://aws.amazon.com/ses/getting-started/">the video tutorials</a> and the <a href="https://aws.amazon.com/documentation/ses/">documentation</a>.</p>
<h2 id="summary">Summary</h2>
<p>There are an endless number of services for bulk sending emails using PHP. We saw the most well-known ones Mailgun, Sendgrid and Amazon SES.</p>
<p>We gained hands-on experience in their basic setup and explored some commonly used features to learn about their API. We saw how to attach an image file to the email through the examples of Mailgun and Sendgrid APIs and looked at how to provide previously built HTML email templates within the message body. Last but not least, we tried the programmatic process of creating and referencing email templates with Amazon SES API.</p>
<p>I hope you could learn the basics and feel confident enough to give email APIs a try. If you have additional resources or code examples that fellow coders could make use of or inspiring thoughts about email APIs, please share them in the comment section below.</p>
<p>If you liked this article, you may like the others to come. Subscribe to our newsletter to get them delivered to your inbox.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
</div>]]></content:encoded></item><item><title><![CDATA[A Step-by-Step Guide to Sending HTML Email Templates Using PHP]]></title><description><![CDATA[In this comprehensive guide you will learn the ins and outs of sending text and HTML emails with built-in packages and email delivery services using PHP.]]></description><link>https://blog.edmdesigner.com/sending-email-with-php/</link><guid isPermaLink="false">5afad21c3bed88001585fba9</guid><category><![CDATA[PHP]]></category><category><![CDATA[PHP Mailer]]></category><category><![CDATA[SMTP]]></category><category><![CDATA[PEAR Mail]]></category><category><![CDATA[PHP Mail]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 10 Jan 2018 12:42:58 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2018/01/sending-emails-with-php-1.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2018/01/sending-emails-with-php-1.jpg" alt="A Step-by-Step Guide to Sending HTML Email Templates Using PHP"><p>Most developers who started off their programming careers before 2010 and had an interest in web development, most-likely encountered <a href="https://en.wikipedia.org/wiki/PHP">PHP</a> as their first server-side scripting language. PHP was very, very popular back then. The easiest way to start a blog or a website was through content management systems (CMS) running on PHP, like Wordpress or Joomla, which boosted popularity even more. <a href="https://w3techs.com/technologies/details/pl-php/all/all">The language is still popular</a> with great impact and a lot of options for different applications.</p>
<p>As the technology is used widely and many developers at email marketing agencies around the world understand the language well, we had the idea to gather as much information about sending email templates with PHP code as possible.</p>
<p>Our goal at <a href="https://edmdesigner.com/">EDMdesigner.com</a> is to make eye-catching, bulletproof<a href="https://blog.chamaileon.io/900-free-responsive-email-templates-to-help-you-start-with-email-design/"> HTML email templates</a> available for everyone. <a href="https://blog.edmdesigner.com/">The EDMdesigner blog</a> supports this mission by helping fellow developers get more educated in the field of email development.</p>
<p>By reading through this guide, you'll learn about how to write PHP code to send transactional and HTML emails. There are built-in methods, PHP extension packages, and we'll cover <a href="https://blog.edmdesigner.com/php-sending-html-emails/">email delivery services integrable in PHP code</a> in an upcoming article. They differ in flexibility and additional features. Learning about these options open the door to quick HTML email design testing capabilities during development. Reading this article will help you gain an understanding of the considerations when selecting the service suitable to your needs.</p>
<div data-chamaileonplugin="blog-forms/signup-for-dev-posts" data-page="signup-for-dev-posts" data-location="inside-blog-post"></div>
<h2 id="installingphp">Installing PHP</h2>
<p>The first step of bootstrapping any PHP code run project is to install PHP. That starts with fetching <a href="http://php.net/downloads.php">the necessary download bundle</a>. Since our goal is to run PHP scripts and send transactional and HTML email templates, it's sufficient to have PHP installed on our system and, we don't need to additionally configure a server. For developers using Linux distributions the quickest setup may be executed by running the following in the terminal:</p>
<pre><code>
sudo add-apt-repository ppa:ondrej/php
sudo apt-get update
sudo apt-get install php7.0-cli // or other desired PHP version

</code></pre>
<p>You can read the detailed installation steps <a href="https://launchpad.net/~ondrej/+archive/ubuntu/php">on the Launchpad web page</a>.</p>
<p>After the successful completion of this process, you can test if everything works correctly with a simple script:</p>
<pre><code>&lt;?php
   echo &quot;I write PHP code like a PRO! 
         Soon I'll be able to send out emails 
         using it as well.&quot;;
?&gt;
</code></pre>
<p>Place the above code in a <code>test.php</code> file, navigate to the folder where you created the file in the command line and run <code>php ./test.php</code>. This amazing script will print your message to the console. Well done!</p>
<h2 id="sendingemailwithbuiltinmailfunction">Sending Email with Built-In Mail Function</h2>
<p>The most basic way to send an email using PHP is the built-in <a href="http://php.net/manual/en/function.mail.php">mail() method</a>. The only compulsory parts are the <code>$to, $subject, $email_body</code> variables. If you omit any of them you'll see the following sad little error log: <code>PHP Warning: mail() expects at least 3 parameters, 2 given ...</code>, warning you about your mistake. The least complex implementation of the function would look like this:</p>
<pre><code>        &lt;?php
            $to = &quot;mail@example.com&quot;;
            $subject = &quot;Subject of your email&quot;;
            $email_body = &quot;The text for the mail...&quot;;

            mail($recipient, $subject, $email_body);
        ?&gt;
</code></pre>
<p>Let's see what happens, when we run the script! In the tutorial, we think in steps, so I go with running <code>php step-00.php</code>.</p>
<p>The most likely output is the following error: <code>sh: 1: /usr/sbin/sendmail: not found</code>. Now, this is a pity. As part of the installation, to be able to actually send test emails, we need to install the <a href="https://en.wikipedia.org/wiki/Sendmail">Sendmail</a> <a href="https://en.wikipedia.org/wiki/Message_transfer_agent">Mail Transport Agent </a>(MTA) as a locally accessible mail server. If you type sendmail in the terminal, you'll be notified about the packages that contain this library:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/12/sendmail.png" alt="A Step-by-Step Guide to Sending HTML Email Templates Using PHP"></p>
<p>When proceeding with <code>sudo apt install sendmail</code> a lot of updates happen.</p>
<p>Now you can proceed with configuring the default sender's values in the <code>php.ini</code> file. The <code>php.ini</code> file is the place to store runtime variables for PHP and this file includes the <a href="https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol">SMTP</a> setup, which tells your script about your local web server's configuration.</p>
<pre><code>[mail function]
; For Win32 only.
; http://php.net/smtp
SMTP = localhost
; http://php.net/smtp-port
smtp_port = 25

; For Win32 only.
; http://php.net/sendmail-from
;sendmail_from = me@example.com

; For Unix only.  You may supply arguments as well (default: &quot;sendmail -t -i&quot;).
; http://php.net/sendmail-path
;sendmail_path = &quot;/usr/sbin/sendmail -t -i -f info@edmdesigner.com
</code></pre>
<p>If you use Unix-based systems, like Linux, you need to uncomment the <code>sendmail_path</code> variable by removing the semicolon from the beginning of the line, so PHP finds your sendmail location. When all the above is done, naturally we try running <code>php step-00.php</code> again. Miraculously the script runs and our first PHP-sent mail arrives. Congrats!</p>
<p><a href="#pearmailpackage">Later we'll see</a>, that we can also choose our email service provider as the mail server and provide the SMTP setup in the script, for example, Gmail's email server.</p>
<p>This is all well and good, however, that's not all the <code>mail()</code> function can do. You can also:</p>
<ul>
<li>send complex HTML email templates</li>
<li>set additional email headers, like (content type, character set)</li>
<li>provide multiple addresses with comma separated lists</li>
<li>add attachments to the emails by formatting the message conform to the <a href="https://en.wikipedia.org/wiki/MIME">Multipurpose Internet Mail Extensions</a> (MIME) standard</li>
</ul>
<p>Following this you may ask 'If I can send rich HTML content with the <code>mail()</code> function, why should I learn about additional ways to send emails?'.</p>
<p>The answer can be found in the user comment section of the PHP docs:</p>
<ul>
<li>it's not efficient to <a href="https://pepipost.com/email-delivery-service/bulk-email-service/">bulk-send emails to email lists</a> as the function opens and closes an SMTP socket for each email</li>
<li>you can only use 70 character long strings, you need to separate the excess with <code>&quot;\r\n&quot;</code> line-breaks.</li>
<li>you can't set up SMTP access to external mail servers</li>
</ul>
<p>In the end, let’s see the updates to be made that enables sending any HTML email template.</p>
<p>They contain:</p>
<ul>
<li>setting up additional headers telling that we created an HTML email, which compliant with the MIME standard</li>
<li>reading the contents of an HTML file (though we could also insert it in the PHP script directly)</li>
<li>providing the <code>$headers</code> to the mail function</li>
</ul>
<pre><code class="language-PHP">$headers = &quot;MIME-Version: 1.0&quot; . &quot;\n&quot;;
$headers .= &quot;Content-type:text/html;charset=UTF-8&quot; . &quot;\n&quot;;

$htmlContent = file_get_contents(&quot;email_template.html&quot;);

// send email HTML
mail($to, $subject, $htmlContent, $headers);
</code></pre>
<p>If you assign the HTML directly to the <code>$htmlContent</code> variable in the script, it's important to avoid mixing single and double quotes. Otherwise, you'll be notified of a parse error of the mistake: <code>PHP Parse error: syntax error, unexpected ' ...unrecognized string... ' (T_STRING) in ...PHP file location...</code></p>
<p>I also consider mail attachments an important topic but beyond the reach of this article, <a href="https://stackoverflow.com/questions/9519588/send-php-html-mail-with-attachments">the following discussion may help</a> to shed light on how to do it properly.</p>
<h2 id="sendinghtmlemailswithexternalphppackages">Sending HTML Emails with External PHP Packages</h2>
<p>In the previous section, I mentioned that it’s not efficient to send emails with the PHP <code>mail()</code> function, considering multiple recipients as the function opens and closes an SMTP socket for each email sent. There are external PHP packages that handle these much better. These PHP scripts enable email sending with option for SMTP configuration of services like Gmail or Yahoo! Mail or other email service providers.</p>
<p>Most blog and community discussions on the web mention the PEAR Mail and the PHP Mailer packages as the default go-to in these situations, so I introduce these as well.</p>
<h3 id="pearmailpackage">PEAR Mail Package</h3>
<p><a href="https://pear.php.net">PHP Extension and Application Repository (PEAR)</a> is a framework and distribution system for reusable PHP code components. The most important email sending script within PEAR is the Mail package. Based on the installed PHP version, you may already have PEAR available. You can check it running <code>pear</code> with no arguments in the command line. If you followed the installation steps recommended in the first section, the command will return:<br>
<code>The program 'pear' is currently not installed. You can install it by typing: sudo apt install php-pear</code> warning. That's totally fine and exactly what we need to do.</p>
<p>Once that's done, we can start adding pear packages: we will need <code>sudo pear install Mail</code> and <code>sudo pear install Net_SMTP</code> for sending emails through email delivery services. You can find the <a href="http://pear.php.net/manual/en/package.mail.mail.php">PEAR Mail packages documentation here</a>.</p>
<p>First, we reference the necessary PEAR component in our <code>.php</code> file:</p>
<pre><code>        require_once &quot;Mail.php&quot;;
</code></pre>
<p>Next include the SMTP settings for the email delivery service in variables, <a href="https://support.google.com/mail/answer/7104828?hl=en">with Gmail</a> it looks as follows:</p>
<pre><code>        $host = &quot;ssl://smtp.gmail.com&quot;;
        $username = 'username';
        $password = 'password';
        $port = &quot;465&quot;;
        $to = &quot;saroy.mihaly@gmail.com&quot;;
</code></pre>
<p>Please note, that the <code>$host</code> variable also holds the security protocol. Here, the username and password are supposed to be your actual Gmail account's username and password. If you use your script on the web, for security reasons, you would store these credentials in environment variables and include them programmatically in the script. <a href="https://github.com/vlucas/phpdotenv">PHP dotenv</a> is a popular package to help with this.</p>
<p>You need to <a href="https://support.google.com/accounts/answer/1064203?hl=en">disable 2-step verification</a> for the SMTP authentication to work in Gmail.</p>
<p>The second part of our code is to provide the parameters to the email header and the variables for SMTP authentication to the mail function. With PEAR Mail package it looks as follows:</p>
<pre><code class="language-PHP">        $headers = array ('From' =&gt; $email_from, 
            'To' =&gt; $to, 'Subject' =&gt; $email_subject, 
            'Reply-To' =&gt; $email_address);
        $smtp = Mail::factory('smtp', array ('host' =&gt; $host, 
            'port' =&gt; $port, 'auth' =&gt; true, 
            'username' =&gt; $username, 'password' =&gt; $password));
        $mail = $smtp-&gt;send($to, $headers, 
            $email_body);
</code></pre>
<p>If you examine it closely, that's where this external PHP package outperforms the original PHP <code>mail()</code> method besides that it enables SMTP: there you could only work with string variables, here you can use arrays for setting the <code>$headers</code> and the various parameters.</p>
<p>Here you can see the full example:</p>
<pre><code>        &lt;?php
            require_once &quot;Mail.php&quot;;

            $host = &quot;ssl://smtp.gmail.com&quot;;
            $username = &quot;username@gmail.com&quot;;
            $password = &quot;*****&quot;;
            $port = &quot;465&quot;;
            $to = &quot;recipient@edmdesigner.com&quot;;

            $email_from = &quot;example@edmdesigner.com&quot;;
            $email_subject = &quot;Subject line&quot; ;
            $email_body = &quot;whatever you like&quot; ;
            $email_address = &quot;replyto@edmdesigner.com&quot;;
            $content = &quot;text/html; charset=utf-8&quot;;
            $mime = &quot;1.0&quot;;

            $headers = array ('From' =&gt; $email_from,
                            'To' =&gt; $to,
                            'Subject' =&gt; $email_subject,
                            'Reply-To' =&gt; $email_address,
                            'MIME-Version' =&gt; $mime,
                            'Content-type' =&gt; $content);

            $params = array  ('host' =&gt; $host,
                            'port' =&gt; $port,
                            'auth' =&gt; true,
                            'username' =&gt; $username,
                            'password' =&gt; $password);

            $smtp = Mail::factory ('smtp', $params);
            $mail = $smtp-&gt;send($to, $headers, $email_body);

            if (PEAR::isError($mail)) {
            echo(&quot;&lt;p&gt;&quot; . $mail-&gt;getMessage() . &quot;&lt;/p&gt;&quot;);
            } else {
            echo(&quot;&lt;p&gt;Message sent successfully!&lt;/p&gt;&quot;);
            }
        ?&gt;
</code></pre>
<p>Moving on, next we'll see an even more robust implementation of PHP mailing with the compound PHP Mailer framework.</p>
<h3 id="phpmailerpackage">PHP Mailer Package</h3>
<p>The contributors of this PHP mailer class say it’s the most popular code for email sending and let’s be honest: the almost 5 million downloads seem to support this statement quite well. It has detailed <a href="http://phpmailer.github.io/PHPMailer/classes/PHPMailer.PHPMailer.PHPMailer.html">documentation</a> on the available methods and <a href="https://github.com/PHPMailer/PHPMailer/tree/master/examples">a few examples</a> to help you get started.</p>
<p>The Mailer package may be <a href="https://github.com/PHPMailer/PHPMailer">downloaded or cloned from Github</a> and the script set up manually in projects, or if you prefer to be neat, use the PHP dependency manager - <a href="https://getcomposer.org/">Composer</a>.</p>
<h4 id="gettingstartedwithcomposer">Getting Started with Composer</h4>
<p>Composer is very similar to the <a href="https://www.npmjs.com/">Node Package Manager</a> in the JavaScript world: you can install and maintain project dependencies in a simple and controlled way from a central registry. They both provide a huge library of public packages.</p>
<p>Composer uses <a href="https://packagist.org/">Packagist</a> as the main repository for these packages and the <code>composer.json</code> file put at the root of your project's repository instructs Composer. You can install it with <code>curl -sS https://getcomposer.org/installer | php</code>. To use Composer you need PHP 5.3.2+. After this command finished running, you can add PHP Mailer package to a <code>composer.json</code> file. The simplest way of doing so, if you add the packages by Composer's bootstrap process: <code>composer init</code>.</p>
<p>You'll be asked a series of questions during the setup guide, one of which will be to select the dependencies:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/12/define-dependencies.png" alt="A Step-by-Step Guide to Sending HTML Email Templates Using PHP"></p>
<p>If you completed the setup guide as above, you can check if the package name and the current default version is added to the <code>composer.json</code> file: <code>&quot;phpmailer/phpmailer&quot;: &quot;~6.0&quot;</code>.</p>
<p>Now you only need to install the added project dependencies (in this case just PHP Mailer) with <code>composer install</code>. It'll add a <code>vendor/</code> folder supplied with <code>vendor/autoload.php</code> script generated by Composer and the required dependencies.</p>
<h4 id="usingthephpmailerpackage">Using the PHP Mailer Package</h4>
<p>As we use Composer and have <code>vendor/autoload.php</code> out-of-the-box, it is much simpler to include the external library in our project:</p>
<pre><code>      require &quot;vendor/autoload.php&quot;;
      use PHPMailer\PHPMailer\PHPMailer;
      $mail = new PHPMailer;
</code></pre>
<p>and we are good to go.</p>
<p>On the PHP Mailer's <code>$mail</code> object, we set the properties used for sending mails: <code>$mail-&gt;From = &quot;from@domain.com&quot;;</code>. There are helper methods in the process: <code>addAddress</code> <code>addReplyTo</code>, etc.</p>
<p>If you wish to send HTML email, and you'd probably want to, then set <code>$mail-&gt;isHTML(true)</code>.</p>
<p>Sending along any attachment - such as an image - is really easy using the PHP Mailer script. You only need to call the mail object's <code>addAttachment()</code> method passing the file location to the argument as a string value. That's very different from the pain of having to configure MIME header boundaries, like <a href="http://pear.php.net/manual/en/package.mail.mail.php#13632">using PEAR</a> or <a href="https://stackoverflow.com/a/32647763"> the <code>mail()</code> function</a></p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/12/phpmailer-sending.png" alt="A Step-by-Step Guide to Sending HTML Email Templates Using PHP"></p>
<p>Once you provided all the necessary properties, you can send the email with <code>$mail-&gt;send()</code>.</p>
<h2 id="summary">Summary</h2>
<p>In this tutorial, you could learn about the most commonly used options to send out plain text and HTML email templates with PHP. We started the post with the PHP mail function and settings for the local PHP environment.</p>
<p>We continued exploring PHP code based mailer packages and gained knowledge about the PHP package and dependency management system with Composer. We saw the example of Gmail on how to configure an SMTP mail server with these mailer packages.</p>
<p>This article focused on the possibilities strictly derived from the PHP ecosystem. Though we can send complex HTML emails to multiple recipients now, we can achieve a lot more through specific email delivery services. For this reason, we continue the topic with <a href="https://blog.edmdesigner.com/php-sending-html-emails/">email delivery API services using PHP</a>.</p>
<p>Thanks for your attention this time. Stay tuned.</p>
<div data-chamaileonplugin="blog-forms/signup-for-email-design-posts" data-page="signup-for-email-design-posts" data-location="inside-blog-post"></div>
</div>]]></content:encoded></item><item><title><![CDATA[How to Use a Templating Language in HTML Email Development]]></title><description><![CDATA[Shorten your development time with templating languages. EJS and the new JavaScript ES6 template strings can reduce the pain of responsive email coding.]]></description><link>https://blog.edmdesigner.com/templating-languages-in-html-email/</link><guid isPermaLink="false">5afad21c3bed88001585fba8</guid><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[Components]]></category><category><![CDATA[Templating languages]]></category><category><![CDATA[Template strings]]></category><category><![CDATA[ES6]]></category><category><![CDATA[EJS]]></category><category><![CDATA[Email markup language]]></category><dc:creator><![CDATA[Gyula Németh]]></dc:creator><pubDate>Wed, 13 Dec 2017 09:29:32 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/12/how-to-use-a-templating-language-in-html-email-development.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/12/how-to-use-a-templating-language-in-html-email-development.jpg" alt="How to Use a Templating Language in HTML Email Development"><p>Throughout this article series, <a href="https://blog.edmdesigner.com/html-email-development-tools/">we have discussed many tools</a> and methods that can help you to create maintainable email code. The most important concept is modularity. If you can decompose your monolith code, you already made a huge step.</p>
<p>A really good abstraction is when you think in components. If your component is general enough, does not include many hacks and you can use them as building blocks, then you are good to go.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=9">
</script> 
<p>Today, we are going to discuss some tools and technologies which will be your best friends in component-based email development.</p>
<h2 id="templatinglanguages">Templating Languages</h2>
<p>Most of you might have heard about templating languages and I guess many of you might have used them.</p>
<p>The typical usage is when you render something on the server side. The usual use-case is when you have to add dynamic content to your website, so when you fetch something from your database, you will have to replace some parts in your original template.</p>
<p>Besides that, you have basic control-flow in templating languages, for example, if branches and loops. These can help you to create a conditional rendering and to use the same sub-template multiple times. (Just think about a shopping cart, where you have to render multiple products. Their template can be the same, while the substituted data has to be different.)</p>
<p>The most popular templating languages that I know of and used are <a href="http://www.embeddedjs.com/">EJS</a>, <a href="http://handlebarsjs.com/">Handlebars</a>, and <a href="https://naltatis.github.io/jade-syntax-docs/">Jade</a>.</p>
<p>It's worth to mention, that in ES6 (the new standard for Javascript) there is a neat new feature called template strings. As you might have guessed, you can do the same trick with them as with templating languages. But which shall you use then? Don't worry, I will compare the two and talk about the pros and cons a little bit later.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="comparingtemplatinglanguagesandes6templatestrings">Comparing Templating Languages and ES6 Template Strings</h2>
<p>In this section, I am going to show you a short and easy to understand example implemented in EJS and with ES6 template strings.</p>
<p>I chose EJS because I have the most experience with that templating language. Also, it just adds to the original HTML syntax, so it's much more straightforward to me than Jade.</p>
<p>The example which I will show you is super simple. The page which we render will have a title and a list of products with prices. Each item will have different background-color, so we can easily navigate between the lines. It will look like this:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/12/simple-example.png" alt="How to Use a Templating Language in HTML Email Development"></p>
<p>As you can see, it's super-simple. I am going to show you some complex examples with real email HTML, but for now, I want to keep things simple so everybody can have a solid basis before we plunge into the nasty email code.</p>
<p>The JSON data with which we feed the template to render our page is:</p>
<pre><code class="language-js">{
  &quot;title&quot;: &quot;My Email HTML Products&quot;,
  &quot;products&quot;: [
    {
      &quot;name&quot;: &quot;Responsive Email Template&quot;,
      &quot;price&quot;: 500
    },
    {
      &quot;name&quot;: &quot;Email Template Builder&quot;,
      &quot;price&quot;: 2000
    },
    {
      &quot;name&quot;: &quot;HTML Generator&quot;,
      &quot;price&quot;: 5000
    },
    {
      &quot;name&quot;: &quot;Drop Calc Generator&quot;,
      &quot;price&quot;: 10000
    }
  ]
}
</code></pre>
<p>The EJS implementation looks like this:</p>
<pre><code class="language-ejs">&lt;html&gt;
    &lt;head&gt;
        &lt;style&gt;
            .even {
                background-color: #abcdef;
            }

            .odd {
                background-color: #fedcba;
            }

            .price {
                float: right;
            }
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;&lt;%= title %&gt;&lt;/h1&gt;

        &lt;div&gt;
            &lt;% for(let idx = 0; idx &lt; products.length; idx +=1) { %&gt;
                &lt;% if(idx % 2 === 0) { %&gt;
                &lt;div class=&quot;even&quot;&gt;
                &lt;% } else { %&gt;
                &lt;div class=&quot;odd&quot;&gt;
                &lt;% } %&gt;
                    &lt;span&gt;&lt;%= products[idx].name %&gt;&lt;/span&gt;
                    &lt;span class=&quot;price&quot;&gt;$&lt;%= products[idx].price %&gt;&lt;/span&gt;
                &lt;/div&gt;
            &lt;% } %&gt;
        &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>The same in Javascript with template strings:</p>
<pre><code class="language-js">function renderTemplate(data) {
    return `
    &lt;html&gt;
    &lt;head&gt;
        &lt;style&gt;
            .even {
                background-color: #abcdef;
            }
    
            .odd {
                background-color: #fedcba;
            }
    
            .price {
                float: right;
            }
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;${data.title}&lt;/h1&gt;
    
        &lt;div&gt;
            ${
                data.products.map((item, idx) =&gt; {
                    const className = idx % 2 === 0 ? &quot;even&quot; : &quot;odd&quot;;
                    return `
                        &lt;div class=&quot;${className}&quot;&gt;
                            &lt;span&gt;${item.name}&lt;/span&gt;
                            &lt;span class=&quot;price&quot;&gt;$${item.price}&lt;/span&gt;
                        &lt;/div&gt;
                    `;
                }).join(&quot;&quot;)
            }
        &lt;/div&gt;
    &lt;/body&gt;
    &lt;/html&gt;
    `;
}
</code></pre>
<p>Templating languages are great. Many people are most probably familiar with them already, so applying them to email development should not be a problem. Many of them are very well supported so you can enjoy syntax highlighting and many other neat features in text editors.</p>
<p>If you want to use templating languages (for example EJS), you have to use external libraries. To be honest, it can be a nightmare to debug these libraries. They hide many things from the developer. It's even impossible to use breakpoints, so you have to print every debug info to the output or the console if you want to debug something.</p>
<p>On the contrary, Javascript template strings are very, very easy to debug, because it's pure Javascript. You can use breakpoints and every other tool which you use for JS debugging.</p>
<p>You don't need dependencies because template strings is a built-in feature in modern Javascript.</p>
<p>My final argument is that template strings force you to use functional Javascript, for example, map, filter and reduce. If you master these features, you will be much, much more effective. You will write code faster and others who are familiar with these operations will understand your code in seconds.</p>
<p>Some people will not agree with me, but I think using Javascript's template strings is the way to go. What do you think about it?</p>
<h3 id="modularitywithjavascripttemplatestrings">Modularity with Javascript Template Strings</h3>
<p>The previous example is obviously a monolith. Not a big one, but still... If you want to decompose it, you have to identify those parts which are logically separate from the other parts of the program.</p>
<p>If you want to define components properly, then they have to be <a href="https://en.wikipedia.org/wiki/Context-free_grammar">context-free</a>, which means, that these components must not depend on their parent's properties. In other words, it means that they will look the same no matter where you put them.</p>
<p>In our example above, we can define one component for the list items, one for the list itself and the main component, which includes the whole template.</p>
<p>After the decomposition, our product-list-item looks like this:</p>
<pre><code class="language-javascript">module.exports = function productListItem(item) {
    return `
        &lt;div class=&quot;${item.className}&quot;&gt;
            &lt;span&gt;${item.name}&lt;/span&gt;
            &lt;span class=&quot;price&quot;&gt;$${item.price}&lt;/span&gt;
        &lt;/div&gt;
    `;
};
</code></pre>
<p>The product-list looks like this:</p>
<pre><code class="language-javascript">const productListItem = require(&quot;./product-list-item&quot;);

module.exports = function productList(products) {
    return products.map((item, idx) =&gt; {
        const className = idx % 2 === 0 ? &quot;even&quot; : &quot;odd&quot;;

        return productListItem({
            className: className,
            name: item.name,
            price: item.price
        });
    }).join(&quot;&quot;);
};
</code></pre>
<p>And the main function is the following:</p>
<pre><code class="language-javascript">function renderTemplate(data) {
    return `
    &lt;html&gt;
    &lt;head&gt;
        &lt;style&gt;
            .even {
                background-color: #abcdef;
            }
    
            .odd {
                background-color: #fedcba;
            }
    
            .price {
                float: right;
            }
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;${data.title}&lt;/h1&gt;
    
        &lt;div&gt;
            ${productList(data.products)}
        &lt;/div&gt;
    &lt;/body&gt;
    &lt;/html&gt;
    `;
}
</code></pre>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-09">You can download the tutorial's full coding examples on Github</a></p>
<p>The example above is super simple, but it shows the basic concepts of decomposing a huge HTML template into smaller independent chunks. This is a great way to create reusable code.</p>
<h2 id="definingacomponentsystemforemaildevelopment">Defining a Component System for Email Development</h2>
<p>Following the methodology above, you can define the most basic components for HTML emails. Later, you can define complex ones based on the basic components.</p>
<p>The basic elements fall into two main categories: layout and content elements. The layout elements can have children whereas the content elements are usually terminal nodes, meaning they don't have any children, but they hold the information of the email itself.</p>
<h3 id="layoutelements">Layout Elements</h3>
<p>Layout elements can be called as container elements as well since they contain other elements. They can contain other containers and content elements as well. This way they define the document tree.</p>
<p>There are three main layout elements:</p>
<ul>
<li><strong>Centered containers</strong>: their main property is their width (which is usually 600px in HTML emails.</li>
<li><strong>Multi-columns</strong>: you can put multiple columns next to each other.</li>
<li><strong>Sections</strong>: They are simple containers to divide different parts of the document, for example, header, content, and footer. They can be used in other containers as well. If you define their background colors, you can emphasize the difference between such areas in your email.</li>
</ul>
<p>With these three layout elements, you can create any kind of email layout with ease.</p>
<p>The usage of multi-columns is obvious, but let me explain something about sections and centered containers. You can combine them in two ways.</p>
<p>You can put sections into centered containers, where your sections will be the header, content, and footer. This is a very traditional way, the colored backgrounds of the sections will be 600px wide as their parent container is.</p>
<p>The other way you can combine them is when you put a centered container into a section. This way the sections background color will spread across the screen. You can put multiple stripes under each other (each stripe contains a section and a centered container within the section), and you will get a nice modern-looking email template.</p>
<h3 id="contentelements">Content Elements</h3>
<p>These kinds of elements contain the content itself. They can be text elements, image elements, and buttons. I think most of the functionality related to them is obvious, but let me go into a little bit more detail about the text element.</p>
<p>In this categorization, text elements can contain some markup as well. For example header elements (<code>&lt;h1&gt;</code>, <code>&lt;h2&gt;</code>, <code>&lt;h3&gt;</code>, etc), list elements (<code>&lt;ul&gt;</code>, <code>&lt;ol&gt;</code>, <code>&lt;li&gt;</code>), and markdown which emphasizes some parts of the text (<code>&lt;i&gt;</code>, <code>&lt;strong&gt;</code>, etc).</p>
<p>You could create separate element types for the ones above, but in many cases, you'd create this part of your template with a WYSIWYG editor so you can use the output of that editor directly as the value of the text element. But if you feel like, you can define your own basic heading and list components. (I'm sure that you don't want to define separate components for bold, italic, etc since then you'd have to define text-node as well.)</p>
<h3 id="thebenefitofredefiningsuchbasicelements">The Benefit of Redefining Such Basic Elements</h3>
<p>The best thing in a component system is that it's declarative. It means that you have to write down what you want to do, not how you want to do it.</p>
<p>Effectively, you don't have to deal with the implementation. Or you can even configure which implementation you want to use. For example you can generate a <code>div</code> or a <code>table</code> based email, depending on the email clients you have to support.</p>
<p>This kind of abstraction also helps you to separate the data from the visualization. Again, the HTML is hidden inside the implementation of the components. You just have to feed them with proper data, which is usually a JSON document.</p>
<p>Even though your document descriptor is a JSON, you can also define a markup language, which automatically translates to JSON. It means that instead of a JSON similar to this:</p>
<pre><code class="language-json">{
...
  &quot;body&quot;: [
    {
      &quot;type&quot;: &quot;container&quot;,
      &quot;children&quot;: [
        {
          &quot;type&quot;: &quot;section&quot;,
          &quot;children&quot;: [
            {
              &quot;type&quot;: &quot;text&quot;,
              &quot;tag&quot;: &quot;p&quot;,
              &quot;value&quot;: &quot;Header&quot;
            },
            {
              &quot;type&quot;: &quot;text&quot;,
              &quot;tag&quot;: &quot;p&quot;,
              &quot;value&quot;: &quot;Content&quot;
            }
            {
              &quot;type&quot;: &quot;text&quot;,
              &quot;tag&quot;: &quot;p&quot;,
              &quot;value&quot;: &quot;Footer&quot;
            }
          ]
        }
      ]
    }
  ]
...
}
</code></pre>
<p>you can write a much simpler markup, like this:</p>
<pre><code class="language-xml">&lt;eml&gt;
  &lt;body&gt;
    &lt;container&gt;
      &lt;section&gt;
        &lt;p&gt;Header&lt;/p&gt;
      &lt;/section&gt;
      &lt;section&gt;
        &lt;p&gt;Content&lt;/p&gt;
      &lt;/section&gt;
      &lt;section&gt;
        &lt;p&gt;Footer&lt;/p&gt;
      &lt;/section&gt;
    &lt;/container&gt;
  &lt;/body&gt;
&lt;/eml&gt;
</code></pre>
<p>If you want to write the code yourself, then you probably want to choose the latter, but if you need to do things programmatically, then the former might be more suitable for you.</p>
<p>You might have noticed that I used an <code>&lt;eml&gt;</code> tag in my second example. It stands for Email Markup Language, which I'm working on at the moment. I am very excited about it, it will contain tons of useful features for those who have to deal with HTML emails.</p>
<h3 id="complexcomponents">Complex Components</h3>
<p>Based on the basic elements, you can define complex components. You can simply compose them to build up a complex one.</p>
<p>Just think about a hero unit component, which consists of an image, a title (which is a text element), a description (which is also a text element) and a call-to-action button.</p>
<p>Another example could be a product-list-item or a product-list, just as you saw in my very simple example.</p>
<p>Besides composing the atomic elements we already defined, you can create components with non-default functionality. Just think about interactive emails. There are multiple components, which can't be composed of our basic elements (for example a carousel, a tabbed pane or even prefilled forms).</p>
<h2 id="summary">Summary</h2>
<p>In this article, you have learned about how to create reusable components for HTML emails with templating languages and Javascript template strings.</p>
<p>You also saw how to define a basic component system, which can be used as building blocks to create complex components.</p>
<p>This component system can be used to define a markup language to create responsive HTML emails. This is what I am secretly working on, so stay tuned, it will be released in the upcoming months.</p>
</div>]]></content:encoded></item><item><title><![CDATA[CSS Inliner Tools Worth Considering for Your Next Email]]></title><description><![CDATA[I hope you have never tried inlining CSS to your email code manually. Thankfully there are several CSS inliner tools. Check out their pros and cons.]]></description><link>https://blog.edmdesigner.com/css-inliner-tools-in-email/</link><guid isPermaLink="false">5afad21c3bed88001585fba7</guid><category><![CDATA[css]]></category><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[css inlining]]></category><category><![CDATA[css inliner tools]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 29 Nov 2017 14:52:09 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/11/css-inliner-tools-in-email.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/11/css-inliner-tools-in-email.jpg" alt="CSS Inliner Tools Worth Considering for Your Next Email"><p>There are three big &quot;Ouch&quot; moments for beginner email coders that you've probably got yourself over already (if not, <a href="https://blog.edmdesigner.com/the-basics-of-modern-html-emails/">check out the fundamental differences</a> between web HTML and email HTML): external resources are mostly banned from email templates, you need to use tables for everything and last but not least - you have to inline your CSS styles. In this article, we'll be concerned with the why&amp;how of the last piece.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=8">
</script> 
<p>You may also very well know that the must of CSS inlining <a href="https://blog.edmdesigner.com/coding-responsive-html-emails-after-the-gmail-update/">has changed a lot</a> since Gmail started to support the <code>&lt;style&gt;</code> tag. However, this technique is still widely used with regional webmail clients and some old Android devices' native mail app or old Gmail apps. Inlining is also a nice option to be used for complex layouts and it can be fundamental for progressive enhancement techniques as well.</p>
<p>So having settled on that it's important, let's learn about the available online and command line tools that make it possible.</p>
<p>Through the article, we'll discuss various tools, their advantages, and their disadvantages too. The goal is that after reading this post, you'll feel comfortable to use them and your senses will be sharpened to spot any possible flaws there might occur.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="cssinliningingeneral">CSS Inlining in General</h2>
<p>Inlining is a widely used method for converting embedded and external CSS style declarations into more reliable email code. You can see it resembled in the latest <a href="https://www.emailonacid.com/blog/article/email-development/email-development-best-practices-2017">Email on Acid's last yearly collection</a> likewise. It's a great way to support older or less developed email clients.</p>
<p>There's an <a href="https://litmus.com/community/discussions/6116-here-s-why-litmus-didn-t-inline-css-for-its-first-newsletter-of-2017">ongoing debate</a> about that it is advisable to drop inline styles in the future - we can conclude that it still depends on the email client list the end-users use.</p>
<p>Borrowing the template from our last tutorial about <a href="https://blog.edmdesigner.com/beginners-guide-to-sass-in-email/">using the Sass preprocessor for email coding</a> we can compare the embedded...</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/11/chrometonlinede-vertical-allowed-1366.png" alt="CSS Inliner Tools Worth Considering for Your Next Email"></p>
<p>and inlined ...</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/11/chrometonlinede-vertical-allowed-1366-inlined.png" alt="CSS Inliner Tools Worth Considering for Your Next Email"></p>
<p>versions of the same template. Here the previews are taken from T-Online.de, which clearly shows that if that is an important client for you, then you need to use inline styles to support it. Word-based Outlooks and different versions of Lotus Notes also benefit from inlined styles.</p>
<p>There are many email coders, who inline CSS styles manually, but it's easy to see that this method is very time consuming and error-prone. Using CSS inliners can help a lot with this aspect. But is there a perfect tool for this process?</p>
<p>Well, you have to decide that for yourself. Different tools have different strengths and weaknesses, and your goal and the end result will determine the true answer.</p>
<p>Based on <a href="https://julie.io/learn-email-html/issues/2-inliners-responsive-grids/">Julie Ng's article</a> we'll consider the following pre-requisites for CSS inliners:</p>
<ul>
<li>not to change our HTML,</li>
<li>not to remove conditional comments,</li>
<li>not to concatenate multiple CSS properties into shorthand and</li>
<li>to only inline and include the CSS specified, but not others</li>
</ul>
<p>Bear these in mind for the upcoming sections and let's dive deep.</p>
<h2 id="gettingstartedwithcssinlinertools">Getting Started with CSS Inliner Tools</h2>
<p>If you search for inliner tools online you'll find that there are 4 other options to manual inlining:</p>
<ul>
<li>online services, like <a href="https://putsmail.com/inliner">Litmus's Putsmail</a>, <a href="https://templates.mailchimp.com/resources/inline-css/">Mailchimp Inliner</a>, <a href="https://foundation.zurb.com/emails/inliner-v2.html">Zurb Foundation's CSS Inliner</a> and <a href="https://inliner.cm/">Campaing Monitor's Inliner.cm</a></li>
<li>APIs where you send the HTML &amp; CSS to receive the inlined version of your document</li>
<li>command line tools like <a href="https://rubygems.org/">ruby gems</a> and globally installed <a href="https://www.npmjs.com/get-npm">NPM packages</a></li>
<li>CSS inliners available through task runner plugins</li>
</ul>
<p>Next, we'll see examples of the options above.</p>
<h3 id="commandlinecssinliners">Command-Line CSS Inliners</h3>
<p>First, we start off with the simplest tool possible, but you'll see that the end results will show it does an amazing job. The tool is called Inlining and it's available through <a href="https://github.com/hail2u/node-inlining/">Github</a> and the <a href="https://www.npmjs.com/package/inlining">NodeJS package manager</a>.</p>
<p>The styles we inline needs to be in a separate CSS file. We'll apply the following during the inlining of the CSS:</p>
<pre><code>      body, p {
        margin: 0;
        padding: 0;
        margin-bottom: 0;
        -webkit-text-size-adjust: none;
        -ms-text-size-adjust: none; }

      table {
        border-spacing: 0;
        mso-table-lspace: 0pt;
        mso-table-rspace: 0pt; }
        table td {
          border-collapse: collapse; }

      .ExternalClass, 
      .ExternalClass p, 
      .ExternalClass span, 
      .ExternalClass font, 
      .ExternalClass td, 
      .ExternalClass div {
        line-height: 100%; }

      .ReadMsgBody {
        width: 100%; }

      img {
        -ms-interpolation-mode: bicubic; }

      p,
      h1,
      h2,
      h3,
      h4,
      h5,
      h6 {
        font-family: Arial; }

      /* default font sizes */
      h1 {
        font-size: 28px;
        line-height: 32px;
        padding-top: 10px;
        padding-bottom: 24px; }

 ...

    Additional heading and paragraph styles

 ...

      .container {
        width: 600px; }

      .hero {
        background-color: #71b47b;
        color: black; }
        .hero .alternate-background {
          background-color: #b471aa; }
        .hero .col33 {
          width: 33%; }
        .hero .col67 {
          width: 67%; }
        .hero .col50 {
          width: 50%; }

      @media only screen and (max-width: 599px) {
        .container, .col33, .col67, .col50 {
          width: 100% !important; } }
      .button, .button-primary, .button-secondary {
        font-family: sans-serif;
        font-size: 13px;
        font-weight: bold;
        text-align: center;
        text-decoration: none;
        display: inline-block;
        -webkit-text-size-adjust: none;
        border: 1px solid #1e3650;
        border-radius: 4px;
        background-color: #ccdd22;
        color: #ffffff;
        width: 200px;
        line-height: 40px; }
        .button-primary {
          background-color: #ffbbcc;
          color: #ffffff;
          width: 250px;
          line-height: 50px; }
        .button-secondary {
          background-color: #7733cc;
          color: #ffffff;
          width: 150px;
          line-height: 30px; }

</code></pre>
<p>In a previous tutorial we already introduced <a href="https://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts/#javascriptnodejs">the NodeJS ecosystem</a> and how to install NPM packages, having a glance at that previous post and following the installation steps:</p>
<pre><code>        npm install -g inlining
</code></pre>
<p>you should be able to set up Inlining easily.</p>
<p>If you run into issues that you can't solve, head to the comment section below the post, we'll help you out.<br>
As you install it globally you can run the following in the terminal <code>inlining input.html &gt;output.html</code> to inline styles. The output of the processed <code>input.html</code> will be pushed into a new <code>output.html</code> file. Using our test template we'll receive the HTML below:</p>
<pre><code>
&lt;!DOCTYPE html&gt;&lt;html&gt;&lt;head&gt;
    &lt;title&gt;One column layout&lt;/title&gt;
&lt;link&gt;

&lt;style&gt;/* default font sizes */

@media only screen and (max-width: 599px) {
  .container, .col33, .col67, .col50 {
    width: 100% !important; } }&lt;/style&gt;&lt;/head&gt;

&lt;body style=&quot;margin:0;padding:0;margin-bottom:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;background-color:#F4F4F4;&quot;&gt;
    &lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;min-width:100%;&quot;&gt;
        &lt;tbody&gt;&lt;tr&gt;
            &lt;td width=&quot;100%&quot; style=&quot;border-collapse:collapse;min-width:100%;&quot;&gt;
                &lt;center&gt;
                    &lt;table class=&quot;container&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; width=&quot;600&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;width:600px;margin:0 auto;&quot;&gt;
                        &lt;tbody&gt;&lt;tr&gt;
                            &lt;td width=&quot;100%&quot; style=&quot;border-collapse:collapse;text-align:left;&quot;&gt;

                                &lt;!-- header with image --&gt;
                                &lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;min-width:100%;&quot;&gt;
                                    &lt;tbody&gt;&lt;tr&gt;
                                        &lt;td width=&quot;100%&quot; style=&quot;border-collapse:collapse;min-width:100%;background-color:#FFFFFF;color:#000000;padding:30px;&quot;&gt;
                                            &lt;img alt=&quot;wonderful EDM logo&quot; src=&quot;https://edmdesigner.github.io/modern-html-email-tutorial/lesson03/img/logo.png&quot; width=&quot;210&quot; style=&quot;-ms-interpolation-mode:bicubic;display: block;&quot;&gt;
                                        &lt;/td&gt;
                                    &lt;/tr&gt;
                                &lt;/tbody&gt;&lt;/table&gt;

                                &lt;table class=&quot;hero&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;background-color:#71b47b;color:black;min-width:100%; &quot;&gt;
                                    &lt;tbody&gt;&lt;tr&gt;
                                        &lt;td width=&quot;100%&quot; style=&quot;border-collapse:collapse;min-width:100%;padding:20px;&quot;&gt;

                                            &lt;!-- Hero image --&gt;
                                            &lt;table class=&quot;col33&quot; align=&quot;left&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;width:33%;&quot;&gt;
                                                &lt;tbody&gt;&lt;tr&gt;
                                                    &lt;td width=&quot;100%&quot; align=&quot;center&quot; style=&quot;border-collapse:collapse;&quot;&gt;
                                                        &lt;img alt=&quot;wonderful Sass logo&quot; src=&quot;https://pbs.twimg.com/profile_images/583681608269471744/jCR2zNJV_200x200.png&quot; style=&quot;-ms-interpolation-mode:bicubic;display: block; max-width: 100%;&quot;&gt;
                                                    &lt;/td&gt;
                                                &lt;/tr&gt;
                                            &lt;/tbody&gt;&lt;/table&gt;

                                            &lt;!-- H1 --&gt;
                                            &lt;table class=&quot;col67 alternate-background&quot; align=&quot;left&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;background-color:#b471aa;width:67%;&quot;&gt;
                                                &lt;tbody&gt;&lt;tr&gt;
                                                    &lt;td width=&quot;100%&quot; style=&quot;border-collapse:collapse;&quot;&gt;
                                                        &lt;!-- H1 --&gt;
                                                        &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;&quot;&gt;
                                                            &lt;tbody&gt;&lt;tr&gt;
                                                                &lt;td align=&quot;center&quot; style=&quot;border-collapse:collapse;&quot;&gt;
                                                                    &lt;h1 style=&quot;font-family:Arial;font-size:28px;line-height:32px;padding-top:10px;padding-bottom:24px;&quot;&gt;
                                                                        Email coding is the best
                                                                    &lt;/h1&gt;
                                                                &lt;/td&gt;
                                                            &lt;/tr&gt;
                                                        &lt;/tbody&gt;&lt;/table&gt;
                                                    &lt;/td&gt;
                                                &lt;/tr&gt;
                                            &lt;/tbody&gt;&lt;/table&gt;

           ....

                                            &lt;!-- Button --&gt;
                                            &lt;table class=&quot;col67&quot; align=&quot;left&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;width:67%;&quot;&gt;
                                                &lt;tbody&gt;&lt;tr&gt;
                                                    &lt;td width=&quot;100%&quot; style=&quot;border-collapse:collapse;&quot;&gt;
                                                        &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;&quot;&gt;
                                                            &lt;tbody&gt;&lt;tr&gt;
                                                                &lt;td align=&quot;center&quot; style=&quot;border-collapse:collapse;&quot;&gt;
                                                                    &lt;div&gt;
                                                                        &lt;a class=&quot;button-secondary&quot; href=&quot;https://edmdesigner.com&quot; target=&quot;_blank&quot; style=&quot;font-family:sans-serif;font-size:13px;font-weight:bold;text-align:center;text-decoration:none;display:inline-block;-webkit-text-size-adjust:none;border:1px solid #1e3650;border-radius:4px;background-color:#ccdd22;color:#ffffff;width:200px;line-height:40px;background-color:#7733cc;color:#ffffff;width:150px;line-height:30px;&quot;&gt;
                                                                            Show me a button!
                                                                        &lt;/a&gt;
                                                                    &lt;/div&gt;
                                                                &lt;/td&gt;
                                                            &lt;/tr&gt;
                                                        &lt;/tbody&gt;&lt;/table&gt;
                                                    &lt;/td&gt;
                                                &lt;/tr&gt;
                                            &lt;/tbody&gt;&lt;/table&gt;

                                        &lt;/td&gt;
                                    &lt;/tr&gt;
                                &lt;/tbody&gt;&lt;/table&gt;

                                &lt;!-- footer --&gt;
                                &lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;border-spacing:0;mso-table-lspace:0pt;mso-table-rspace:0pt;min-width:100%;&quot;&gt;
                                    &lt;tbody&gt;&lt;tr&gt;
                                        &lt;td width=&quot;100%&quot; style=&quot;border-collapse:collapse;min-width:100%;background-color:#58585A;color:#FFFFFF;padding:30px;&quot;&gt;
                                            &lt;p style=&quot;margin:0;padding:0;margin-bottom:0;-webkit-text-size-adjust:none;-ms-text-size-adjust:none;font-family:Arial;font-size:17px;line-height:20px;padding-top:6px;padding-bottom:15px;font-size:16px;line-height:20px;font-family:Georgia,Arial,sans-serif;text-align:center;&quot;&gt;2017 @ COPYRIGHT - EDMDESIGNER&lt;/p&gt;
                                        &lt;/td&gt;
                                    &lt;/tr&gt;
                                &lt;/tbody&gt;&lt;/table&gt;

                            &lt;/td&gt;
                        &lt;/tr&gt;
                    &lt;/tbody&gt;&lt;/table&gt;
                &lt;/center&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/tbody&gt;&lt;/table&gt;


&lt;/body&gt;&lt;/html&gt;


</code></pre>
<p>There are a few things about this tool, I should mention:</p>
<ul>
<li>it preserves the media query in the style tag - you'll see that not all tool does so</li>
<li>inlines well the <code>width</code> properties of the layout classes <code>col67</code>, <code>col33</code></li>
<li>adds <code>&lt;tbody&gt;</code> tag to complete the <code>table</code> markup</li>
<li>it removes unknown CSS classes, like <code>ExternalClass</code> declaration</li>
</ul>
<p>Examining the <a href="https://litmus.com/checklist/emails/public/8a94e80">Litmus previews</a> we can determine that the correct fluid layout is applied in most mobile email clients, while the desktop view shows on desktop and webmail clients. The tool doesn't offer any configuration to customize the inlining process, but I'm pretty satisfied with the results. There are two negative aspects I run into using the tool: 1, you can only use it to inline CSS from external stylesheet 2, it uses a tabulation that makes the template harder to modify after inlining. All-in-all I can recommend it whole-heartedly.</p>
<h3 id="settingupanautomationtool">Setting Up an Automation Tool</h3>
<p>When I wanted to test the various tools for the inlining process, soon it turned out that the only effective approach is if I gather and run them together via a scripting language. Though any solution would work, there are special tools, so-called task runners, that facilitate this job. This way I just need to modify the HTML, CSS and the CSS inliner tools' configurations, other parts of the procedure are handled for me.</p>
<p>Task runners are tools to make regularly occurring tasks automated. The usual setup is based on a configuration file, specific for the task runner that holds all the defined tasks to carry out on a simple command.</p>
<p>Our choice, <a href="https://gulpjs.com/">Gulp</a>, is a frequently used, performant JavaScript task runner, and under a simple default command, we'll set up all the different CSS inliner tools' run commands. The installation is quite the same as you've seen <a href="https://blog.edmdesigner.com/css-inliner-tools-in-email/#commandlinecssinliners">in the section about Inlining.</a></p>
<p>We'll zoom-in on task automation in an upcoming article creating an automated email development framework. On the other hand, it seems useful to warm you up a bit and introduce one popular JavaScript task runner for the sake of this post anyway. Let's Gulp!</p>
<p>You can download and inspect my recommended project setup from <a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-08">Github</a>, but I'll quickly sum up how it works. If you see any way to improve that, I also welcome comments about it.</p>
<p>In our project will have:</p>
<ul>
<li>An <code>input.html</code> that contains the email template markup and either a <code>&lt;link&gt;</code> tag to the <code>main.css</code> containing the styles for the template, or the styles embedded into the <code>&lt;style&gt;</code> tag, when we want to test how that works</li>
<li>A <code>gulpfile.js</code>, having all the inlining tasks we want</li>
<li>NPM related files and folder: <code>package.json</code> file and <code>node_modules</code> folder - these will house the gulp util packages (like gulp-rename to customize the output file name) and CSS inliner packages available through NPM</li>
<li>I opened separate JavaScript files for each CSS inliner tool that's not set up to be run with Gulp directly</li>
<li>A <code>results</code> folder that we'll hold the generated inlined HTML's</li>
</ul>
<p>All of these together look as follows:</p>
<pre><code>        inliner-tasks/
            |_ node_modules/
            |
            |_ results/
            |   |
            |   |_&lt;inlined result files&gt;
            |
            |
            |_ input.html
            |
            |_ gulpfile.js
            |
            |_ package.json

</code></pre>
<p>So let's navigate to our working folder on the terminal and install everything we'll use:</p>
<p>We'll need to <code>npm install --save gulp-premailer gulp-juice gulp-email-builder</code>.</p>
<p>After it's completed, let's start to fill up the gulpfile. I'm only showing the task for one inliner to save space.</p>
<pre><code>        // REQUIRING NECESSARY PACKAGES
        var gulp = require('gulp');
        // this package let's us run command-line
        // commands from the Gulp JavaScript file
        var run = require(&quot;gulp-run-command&quot;).default;
        var rename = require(&quot;gulp-rename&quot;);

        // INLINER PACKAGES
        // ========================================
        var gulpPremailer = require(&quot;gulp-premailer&quot;);
        var gulpJuice = require(&quot;premailer-gulp-juice&quot;);
        var emailBuilder = require('gulp-email-builder');

        // FILE PATHS
        // ========================================
        var input = &quot;input.html&quot;;
        var output = &quot;results/&quot;;

        // INLINER TASKS
        // ========================================

        // Premailer
        var premailerRunFile = &quot;premailer/pre.rb&quot;
        var rubyCommand = &quot;ruby &quot;;

        var premailer = rubyCommand + premailerRunFile;

        // Gulp-premailer
        gulp.task(&quot;gPremailer&quot;, function () {
        gulp.src(input)
            .pipe(gulpPremailer())
            .pipe(rename(&quot;gpremailer.html&quot;))
            .pipe(gulp.dest(output));
        });

        var gPremailer = &quot;gulp gPremailer&quot;;

        // DEFAULT TASK
        // ========================================
        gulp.task(&quot;default&quot;, run([
             gPremailer
        ]));

</code></pre>
<p>The above content, which makes a valid gulfile.js, runnable with the <code>gulp</code> command:</p>
<ul>
<li>requires all the necessary packages to the operations defined for the tasks</li>
<li>provides some configuration, like the input and output files and folders</li>
<li>holds the task names and the function to implement, when the given task is run.</li>
</ul>
<p>Let's try it out and run <code>gulp default</code> in the terminal!</p>
<p>This is our project setup. I hope it makes sense to you. In the next sections, I'll show you how the inlined versions differ for the same template and give you an overview on some of the available configurations for each tool. I'll point out the key differences and implementation specifics you must consider if you decide to use inliners.</p>
<h3 id="gulpcssinlinerplugins">Gulp CSS Inliner Plugins</h3>
<p>As in the previous step, we run our <code>&quot;default&quot;</code> Gulp task, the <code>results/</code> folder is filled with output already. To be able to compare these results, I found <a href="https://www.diffchecker.com/diff">this online tool</a> that enables great opportunity to visually inspect differences between two documents. Before we get into the details, you may want to check out the <a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-08/inlining-example">working files of the project</a>.</p>
<p><strong>Premailer-Gulp-Juice</strong></p>
<p>In this section, the output HTML of <a href="https://www.npmjs.com/package/premailer-gulp-juice"><code>premailer-gulp-juice</code> package</a> will be our reference, as it keeps the media query in the <code>head</code> and also inlines the CSS from the class declarations correctly. Examining the <a href="https://litmus.com/checklist/emails/public/4f0c406">previews</a>, we can observe that they are almost identical to the ones we have seen with Inlining. One unexpected fix Juice adds to the original template: it completes <code>td</code> tags with <code>align=&quot;left&quot;</code> attribute.</p>
<p>A quick note: by default this Juice package encodes the image to Base64 code, which is only seen with the Gulp wrapper package.</p>
<p><strong>Gulp-Email-Builder</strong></p>
<p><a href="https://www.npmjs.com/package/gulp-email-builder">The Gulp-Email-Builder package</a> delivers a lot, not just considering inlining: it also offers means of sending out email tests and running Litmus previous directly from our script file. However these are out of the scope of this tutorial, so I just sum up the options of customization and differences to the output of the Juice package.</p>
<p>Here are the things to consider when opting for using this inliner:</p>
<ul>
<li>It lets you select from multiple external stylesheets, the ones to inline, the ones to embed and you can also select stylesheets to ignore. That can be a great option for development.</li>
<li>There are <a href="https://github.com/Email-builder/email-builder-core#options">options for customization</a> about the inlining process as well, like selecting to <code>normalizeWhitespace</code> or to <code>decodeEntities</code> available through the internally used <code>cheerio</code> package.</li>
<li>It removes the media query but applies its content overwriting <code>width</code> related properties. This is not desired, and you'll see that it breaks the template on many clients.</li>
</ul>
<p>You can access the Litmus previews with this tool <a href="https://litmus.com/checklist/emails/public/2619ad2">following this link</a>.</p>
<p><strong>Gulp-Premailer</strong></p>
<p>Gulp-Premailer is really similar to the previously shown Gulp-Email-Builder. However, it's a changing difference using it that it inlines the <code>width</code> properties from the CSS declarations and it also embeds the media query and <code>ExternalClass</code> class definitions. Premailer also offers an <a href="https://www.npmjs.com/package/premailer-api">API functionality</a> through NPM, so there's an option to set up your script file to send over the HTML and CSS to their API and you'll receive the inlined email HTML in your code. They also offer <a href="http://premailer.dialect.ca/">an online tool</a>, which you may consider trying.</p>
<p>You can access the Litmus previews with this tool <a href="https://litmus.com/checklist/emails/public/dc8bc47">following this link</a>.</p>
<h3 id="onlinecssinlinerservices">Online CSS Inliner Services</h3>
<p>The following tools are able to smartly take embedded styles from the <code>head</code> element of the HTML document and apply them either in the <code>&lt;body&gt;</code> tag in the appropriate HTML elements as inline styles. We'll see different behavior around how they work. The tools are not consistent in their job and if you are not careful some unwanted changes may be made to your project. We're going to see these next.</p>
<p>I tested 4 online inliner services thoroughly from the most well-respected companies in the email marketing industry. Namely, I used the inliner services of <a href="https://putsmail.com/inliner">Litmus (Putsmail)</a>, <a href="https://templates.mailchimp.com/resources/inline-css/">Mailchimp</a>, <a href="https://foundation.zurb.com/emails/inliner-v2.html">Zurb</a> and <a href="https://inliner.cm/">Campaing Monitor</a>.</p>
<p>You can find the HTML results after CSS inlining among the working files.(<a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-08/online-tool-tests">https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-08/online-tool-tests</a>)</p>
<p>These tools had similarities and more importantly very similar differences as well. I'll gather and explain what kind of unexpected behavior I've found. I'll summarize these below:</p>
<p><strong>Using external stylesheets:</strong></p>
<ul>
<li>Litmus's Putsmail tool and Zurb's tool doesn't handle external stylesheets, these resources are stripped totally and no inlining is done. The HTML is processed and what the tool offers is applied to the document. If you want to use external stylesheets Mailchimp's and Campaign Monitor's online tools are better solutions for you. They do the inlining, and also in Mailchimp the <code>&lt;link&gt;</code> tag is also included, while Campaign Monitor adds all the respective CSS to the <code>&lt;style&gt;</code> tag. That means a duplication of all styles. On the other hand, this way the media queries are kept, which keeps our layout as we wanted.</li>
</ul>
<p><strong>Using embedded styles:</strong></p>
<ul>
<li>As it turns out, all tools inline multi-column pattern's defined width values. First I thought this would be a problem, but as our previous research showed on the Drop Calc Method (<a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/</a>), these inline styles are overwritten from the media query class declarations.</li>
<li>Mailchimp and Campaign Monitor keep all embedded styles, which makes: 1, huge duplication on code 2, client specific targeting and smart hacks are also kept (like Margin Hack <code>p { Margin: 0px }</code> <a href="https://www.campaignmonitor.com/blog/email-marketing/2016/09/7-email-hacks-every-developer-should-know/">recommended by Paul Airy</a>. The other tools strip out the unknown CSS classes and properties.</li>
</ul>
<p>Last but not least, there are tool specific characteristics worth mentioning:</p>
<ul>
<li>Zurb stripps every HTML comments, but MSO conditional comments and also changes the HTML doctype to the following: <code>&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;</code></li>
<li>Putsmail and Mailchimp removed the closing <code>&lt;img&gt;</code> tag, which is strange and not valid HTML</li>
<li>Campaign Monitor separates <code>padding</code> and <code>margin</code> shorthands to their full form</li>
</ul>
<h2 id="summary">Summary</h2>
<p>We started off by discussing why CSS inlining is important for email developers and showing that it may not be necessary in the future, but it still makes sense in cases when the email client list to support demands it.</p>
<p>We saw a broad spectrum of available options for the task: online tools, command line tools, APIs and task runner plugins. We introduced the topic of task automation and learned how it can be used in the inlining process. We tested a few of the most well-known options through Gulp task runner and inspected the various settings and additional features available with these CSS inliners.</p>
<p>In the second part of the article, we observed the output of online CSS inliner tools and we saw a few interesting specialty with these tools. The most important takeaway was that considering complex layout techniques, the ones that build on inline styles and the <code>style</code> tag with media queries, these tools can break the layout.</p>
<p>To puzzle your mind, there are other techniques that can overcome this limitation. By using the method of abstract description you have more control over the most important layout declarations. If you don't have the faintest idea about what they are, no worries, we'll show that in the next article. We'll talk about templating languages and the ES2015 template strings. Thanks for joining us! See you next time as well.</p>
</div>]]></content:encoded></item><item><title><![CDATA[Beginner's Guide to Using Sass in Email Coding]]></title><description><![CDATA[Do you repeat bits of CSS code across email template projects? Learn to use the Sass preprocessor language to change that and design reusable components.]]></description><link>https://blog.edmdesigner.com/beginners-guide-to-sass-in-email/</link><guid isPermaLink="false">5afad21c3bed88001585fb9d</guid><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[maintainability]]></category><category><![CDATA[Preprocessors]]></category><category><![CDATA[SCSS]]></category><category><![CDATA[SASS]]></category><category><![CDATA[Components]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 15 Nov 2017 14:43:03 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/11/beginners-guide-to-using-sass-in-email-coding.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/11/beginners-guide-to-using-sass-in-email-coding.jpg" alt="Beginner's Guide to Using Sass in Email Coding"><p>In email development, the challenge often lies in hardly maintainable code. Development can turn from fun to nightmare quickly if you need to scroll up and down between the HTML and CSS each time you need to find something in your email template.</p>
<p>In this post, we'll try to change this unpleasant situation regarding CSS by the use of a preprocessor. By reading through the article you'll gain knowledge about how to organize your template styles better. You can learn about how to apply modular design by creating reusable code components in the style files.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=7">
</script>
<p>Throughout the post, we'll discuss what a preprocessor is and how it helps us better organize our code. I'll give you some background on the available options and why I chose Sass.</p>
<p>I'll walk you through an example to touch and feel it in action. You'll see that thinking in components is a natural way for managing CSS code.</p>
<p>In our next article, we'll go on to improve our workflow regarding how to use styles efficiently. We'll compare a few of the most frequently applied inliners and offer best practices for using them.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="csspreprocessors">CSS Preprocessors</h2>
<p>So what CSS preprocessors are and why are they useful for email coders?</p>
<p>Probably it's not new: they are dynamic CSS extension languages, extending the functionalities of the CSS language. In email development, we can benefit from these features and come up with structural guidelines and ideas that will promote maintainable code.</p>
<h3 id="sasslessstylus">Sass, Less, Stylus</h3>
<p>The three most important preprocessors of today are <a href="http://sass-lang.com/">Sass</a>, <a href="http://lesscss.org/">Less</a> and <a href="http://stylus-lang.com/">Stylus</a> - their popularity follows the same order too. The main keywords to remember them by are: <strong>variables, nesting, mixins, imports, and selector inheritance</strong>.  Each language has these functionalities implemented with their own syntax. I'll explain all you need to know about these expressions in the next section with a thorough example.</p>
<p><strong>Conceptually, the power of preprocessors lies in:</strong></p>
<ul>
<li>the possibility to eliminate code repetition in CSS</li>
<li>better showing the corresponding parts, like separate files for components or nested selectors</li>
<li>less code results in faster development time</li>
<li>they are easy to adapt to as regular CSS is valid in the files that are processed by the preprocessor</li>
</ul>
<p>It may seem hard to choose your preferred CSS preprocessor language. You may consider the quality of documentation, comparison articles or just pick the one that you may have already seen before. For a clearer understanding of their similarities and differences, I suggest to <a href="https://css-tricks.com/sass-vs-less/">read this article</a> - it's very in-depth about what aspects to consider.</p>
<p>Sass was the first preprocessor language to introduce a new, indented syntax to simplify the code. It has a large user base and other preprocessors (Less, Stylus and many other) picked up this <a href="https://www.python.org/">python-like syntax</a>,</p>
<p>where only indentation and newline characters are used to separate rules and code blocks:</p>
<pre><code>       #main
         background-color: blue 
         color: #eee
         
</code></pre>
<p>However, SCSS, the syntax that uses block formatting like CSS:</p>
<pre><code>       #main {
         background-color: blue;
         color: #eee;
       }
</code></pre>
<p>gained bigger traction. You can use regular CSS without any problems in preprocessed files an that makes far more easier to adapt to using SCSS as well. This syntax duality is also present in Less.</p>
<p>I turned to Sass because this similar syntax to CSS, which is painless to follow. Sass also has the most customizable functions and it was a plus that I've already used it in my projects before. Though we'll use Sass in our example, the operations we'll carry out would be achievable through every other CSS preprocessor language.</p>
<p>Now, you need to pay attention to the fact that preprocessed files aren't interpreted directly in the browser. Before your work would be actually usable, you need to compile the files to regular CSS. I'll also show that in the upcoming section, so let's go on.</p>
<h2 id="demoproject">Demo project</h2>
<p>As mentioned previously, we are going to make a sample project in Sass to show the most well-known and useful features of preprocessors.</p>
<p>Our main idea is to develop a component library, which can be shared among future projects. We'll have general components with customizable parameters varied by each project later. This will speed up development time radically, as we don't have to re-create general units each and every time. This modular design concept results in easily maintainable and scalable code. That's being said let's discuss the markup that comes up repeatedly in email templates.</p>
<h3 id="buildtheinitialhtmlmarkup">Build The Initial HTML Markup</h3>
<p>Each email has call-to-action buttons - that goes without saying. For simplicity's sake I borrow Campaign Monitor's button without the VML (I know, we say yes to poor results in Outlooks, but they aren't our priority now):</p>
<pre><code>        &lt;div&gt;
            &lt;a href=&quot;https://edmdesigner.com&quot;
            style=&quot;
                background-color:#556270;
                border:1px solid #1e3650;
                border-radius:4px;color:#ffffff;
                display:inline-block;
                font-family:sans-serif;
                font-size:13px;
                font-weight:bold;
                line-height:40px;
                text-align:center;
                text-decoration:none;width:200px;
                -webkit-text-size-adjust:none;
                &quot;&gt;
                Show me the button!
            &lt;/a&gt;
        &lt;/div&gt;
</code></pre>
<p>We'll use this in our exemplary template and will work on it as the &quot;call-to-action button component&quot; when we define the styles.</p>
<p>The next thing you often find yourself using I'm pretty sure, is a hero unit, like this:</p>
<pre><code>		&lt;div class=&quot;hero&quot;&gt;
		    &lt;img src=&quot;hero.png&quot; /&gt;
		    &lt;h1&gt;HERO&lt;/h1&gt;
		    &lt;p&gt;Description&lt;/p&gt;
		&lt;/div&gt;
</code></pre>
<p>which is translated to something as below in the email world:</p>
<pre><code>&lt;table class=&quot;hero&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;min-width:100%;&quot;&gt;
    &lt;tr&gt;
        &lt;td width=&quot;100%&quot; style=&quot;min-width:100%;background-color:#FFFFFF;color:#000000;&quot;&gt;

            &lt;!-- Hero image --&gt;
            &lt;table class=&quot;col33&quot; align=&quot;left&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; 
                border=&quot;0&quot; width=&quot;100%&quot;
            &gt;
                &lt;tr&gt;
                    &lt;td width=&quot;100%&quot; 
                        style=&quot;background-color:#F8F7F0;color:#58585A;padding:10px;&quot; 
                        align=&quot;center&quot;
                    &gt;
                        &lt;img alt=&quot;wonderful Sass logo&quot; src=&quot;example.png&quot; 
                        style=&quot;display: block; max-width: 100%;&quot;
                        /&gt;
                    &lt;/td&gt;
                &lt;/tr&gt;
            &lt;/table&gt;

            &lt;!-- H1 --&gt;
            &lt;table class=&quot;col67&quot; align=&quot;left&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; 
                border=&quot;0&quot; width=&quot;100%&quot;
                &gt;
                &lt;tr&gt;
                    &lt;td width=&quot;100%&quot;&gt;
                        &lt;!-- H1 --&gt;
                        &lt;table cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot; width=&quot;100%&quot;&gt;
                            &lt;tr&gt;
                                &lt;td style=&quot;background-color:#F8F7F0;color:#58585A;
                                    padding:10px;&quot; 
                                    align=&quot;center&quot;
                                &gt;
                                    &lt;h1&gt;
                                        Email coding is the best
                                    &lt;/h1&gt;
                                &lt;/td&gt;
                            &lt;/tr&gt;
                        &lt;/table&gt;
                    &lt;/td&gt;
                &lt;/tr&gt;
            &lt;/table&gt;

             ...

        &lt;/td&gt;
    &lt;/tr&gt;
&lt;/table&gt;
</code></pre>
<p>This two components will be the basis of the project, so remember them well. <a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-07/step-00/">You can download them for the next step from Github</a>.</p>
<p><strong>The project we're building will look as follows in the end:</strong></p>
<div data-preview="https://edmdesigner.github.io/html-email-development-tools/lesson-07/step-03/output.html"></div>   
&nbsp;
<p>You may wish to browse <a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-07/step-03/">the working folder of the final step</a>  to get familiar with the project before you go on. A quick glance at what to expect in the end will probably make easier to follow along the steps.</p>
<h3 id="makescssworkinemailtemplate">Make SCSS Work in Email Template</h3>
<p>Our first task is to learn how to compile a single Sass file into regular CSS. Remember that it's necessary in order to make our styles to work.</p>
<p><strong>We have two options:</strong></p>
<ul>
<li>Install Sass and use the Sass compiler for the task:</li>
</ul>
<p><a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-sass-on-your-vps-running-on-ubuntu">The following guide</a> will help you install Sass on your system. <a href="https://medium.com/@ricardozea/sass-for-beginners-the-friendliest-guide-about-how-to-install-use-sass-on-windows-22ff4a32c1f7">Windows users, check out this guide.</a> for the installation steps.</p>
<p>Once you're ready, the command as below will do the trick on the command line:</p>
<pre><code>         sass input.scss output.css
</code></pre>
<p>This exercise is cumbersome to do on each modification of our file(s). To make the duty automatic you can put a <code>--watch</code> flag in the end, so the file is re-compiled on every saved update.</p>
<ul>
<li>We can also continue the path we started in earlier tutorials and put scripts into use to compile and inline styles.</li>
</ul>
<p>For this tutorial, we'll stick to the first option, as it is much simpler. However, we'll have an article about task automation tools, like <a href="https://gulpjs.com/">Gulp</a>, later in the tutorial series. It'll open the horizon to a vast amount of opportunities. You may not want to miss it. Sign up if you think you'd be interested.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<p>There are also <a href="https://graygrids.com/best-tools-resources-compile-manage-sass-less-stylus-css-preprocessors/">various tools</a> that support live compilation. If you are impatient to start off experimenting with Sass immediately <a href="https://www.sassmeister.com/">try this one online</a>.</p>
<p>Getting the awkwardness of the compilation out of the way, we can dive into the fun part writing SCSS. I imagine that you are quite curious to try things out.</p>
<p>First, create a project folder with folders for <code>CSS</code> and <code>SCSS</code> files. Add the <code>main.scss</code> to your <code>SCSS</code> folder and the template you downloaded <a href="#buildtheinitialhtmlmarkup">in the previous section</a> and a <code>typography.scss</code> to get ready for some initial text styling.</p>
<pre><code>        sass-awesomeness/
            |_ CSS/
            |_ SCSS/
            |   |
            |   |_main.scss
            |   |_typography.scss
            |
            |_ index.html
</code></pre>
<p>The way we want the example to work is to have a single <code>main.scss</code> that gathers all the preprocessed style sheets. All of these styles will be pushed to a <code>main.css</code> file in the <code>CSS</code> folder.</p>
<p>Each component will have its own style sheet, which is core for modularity. This separates the concerns and makes absolutely clear where to look for a specific style declaration when you want to change something.</p>
<h4 id="theimportdirective">The @import Directive</h4>
<p>To pull the styles of <code>typography.scss</code> for example into <code>main.scss</code>, we need to use the @import directive in <code>main.scss</code>. It'll tell Sass where the location and name of the file is. In our project we add:</p>
<pre><code>/* main.scss */

        @import 'typography'; 
</code></pre>
<p>We can use just the name of the file as both files are in the same folder and Sass will resolve the file extention.</p>
<p>And we add any styles to the typography file:</p>
<pre><code>/* typograhy.scss */

        p, h1, h2, h3, h4, h5, h6 { font-family: Arial; } 
</code></pre>
<p>You can try less modest styles as well.</p>
<p>In the end, we need to compile the Sass files. To refresh your memories:</p>
<pre><code>        sass ./scss/main.scss ./css/main.css

        (or with --watch as an optional argument, 
        note the colon in the middle!)

        sass --watch ./scss/main.scss:./css/main.css
</code></pre>
<p>This will output all the existing SCCS styles linked with <code>@import</code> into <code>css/main.css</code>. Our final job is to make that appear in the HTML of our email template.</p>
<h4 id="includecssintohtmldocument">Include CSS Into HTML Document</h4>
<p>Higher client support dictates to inline whenever that's possible. But as our goal is to learn about preprocessors, instead of introducing inliner tools, we work with simple command line script. In our next article, we'll make up for it and show inlining in detail.</p>
<p>In the markup we have opened a <code>style</code> tag with the following string &quot;replace me&quot;. The below command will take this string and push all of the content of <code>main.css</code> into its place:</p>
<pre><code>         sed -e '/replace me/{r ./css/main.css' -e 'd}' index.html &gt; 
         output.html
</code></pre>
<p>I'm not an expert to say if this is the optimal way of doing this, but I think it's quite simple and self-explanatory what happens.</p>
<p>If you open up the project in the browser now, you can inspect if everything is included as expected.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/11/check-css-import.png" alt="Beginner's Guide to Using Sass in Email Coding"></p>
<p>Did you got it right? Well done!</p>
<h3 id="thebuttoncomponent">The Button Component</h3>
<p>This is the step where we create our very first reusable component. We'll use variables to define color schemes and dimensions for the button component and apply mixins to avoid duplication of code-blocks. Mixins are used in pair with @include directives, so be prepared to meet them as well. In the meantime you can pick up how nesting works too.</p>
<p>If you are new to preprocessors you may think that it's complex, but believe me it's not. If I could learn it, then so can you.</p>
<h4 id="variablesnestingandinheritance">Variables, Nesting, and Inheritance</h4>
<p>Variables are the cornerstone to achieve <a href="https://en.wikipedia.org/wiki/Don%27t_repeat_yourself">&quot;DRY&quot; code</a> with preprocessors. You can create them in global or local scope (eg. inside a mixin). You can pass them around and use them inside functions and custom calculations.</p>
<p>Nesting lets you visually indicate the hierarchy of selectors and properties.</p>
<p>This two concepts can be introduced smoothly with the button component. I promised separate variables for color and dimensions, here they are:</p>
<pre><code>        $defaultColor: #ccdd22;
        $primaryColor: #ffbbcc;
        $defaultFontColor: #ffffff;

        $defaultWidth: 200px;
        $defaultHeight: 40px;

        $defaultBorder: 1px solid #1e3650;
</code></pre>
<p>and you may include them like this:</p>
<pre><code>        .button {
            background-color: $defaultColor;
            color: $defaultFontColor;

            font: {
                size: 13px;
                weight: bold;
            }

            text: {
                align: center;
                decoration: none;
            }

            width: $defaultWidth;
            line-height: $defaultHeight;

            display: inline-block;
            border: $defaultBorder;
            border-radius: 4px;

            &amp;-primary {
                background-color: $primaryColor;
                color: $defaultFontColor;
            }
        }
</code></pre>
<p>Inheritance is what you see at the end of this code snippet. The <code>&amp;-primary</code> will be compiled to <code>.button-primary</code>, the <code>&amp;</code> sign is only a placeholder for the parent selector. This primary button is the child of the default <code>.button</code> class, as it is placed within it. It will inherit the properties defined in its parent and it completes it with its additional styles.</p>
<p>If you wish instant feedback at this point, you can observe the compiled CSS <a href="https://www.sassmeister.com/">at Sassmeister.com</a>.</p>
<h4 id="mixinsandtheincludedirective">Mixins and the @include Directive</h4>
<p>Mixins are very handy, function-like creatures in preprocessors. You can declare any SCSS within them and reuse them several times in the code with the <code>@include</code> directive:</p>
<pre><code>        @mixin color($color1, $color2) { 
             background-color: $color1; 
             color: $color2; 
        }

        .button {
            
              ...

              @include color($defaultColor, $defaultFontColor);
         }
</code></pre>
<p>The first part of the above code declares a <code>color</code> mixin and accepts two parameters and matches the corresponding property. In the button class, we're &quot;calling&quot; this mixin with the <code>@include directive</code> and pass in the pre-defined color properties.</p>
<p>For class declarations, which are going to extend this button class, we only need to add the <code>@include</code> with new color parameters.</p>
<p>We can do the same for the dimensions, <a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-07/step-03/">check it out in the end results</a>.</p>
<p>I strongly suggest to compile this step in the terminal. You can apply the <code>--watch</code> flag version as well, as we are going to continuously add to the project. Don't forget: you need to <code>@import 'buttons';</code> in the <code>main.scss</code> first.</p>
<p>After we push the styles to the <code>style</code> tag with our script, that's what we are at:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/11/update-buttons-class.gif" alt="Beginner's Guide to Using Sass in Email Coding"></p>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-07/step-01/">You can checko out the full source code here</a></p>
<h3 id="theherounitcomponent">The Hero Unit Component</h3>
<p>I've shown you the HTML for the component: in a container, we have a <code>title</code>, an <code>img</code> and a <code>p</code> tag for the descriptions. We want to be able to customize text color and an optional extra background color for the parts of the component.</p>
<h4 id="theifdirectiveandfunctions">The @if Directive and Functions</h4>
<p>This will need two new concept: the <a href="http://sass-lang.com/documentation/file.SASS_REFERENCE.html#_if">@if directive</a> and <a href="http://sass-lang.com/documentation/Sass/Script/Functions.html">functions</a>. Sass has wide-variety of options for customizing colors.</p>
<p>We start by defining the default colors in varialbes. Then you can see that we measure the lightness of the given color: <code>$colorLightness: lightness($heroBgColor)</code>, and have two different decision and outcome based on the input value:</p>
<pre><code>        $heroBgColor: #71b47b;
        $heroDefaultTextColor: #58585A;


        .hero {
            background-color: $heroBgColor;
            $colorLightness: lightness($heroBgColor);

            @if ($colorLightness &gt; 50%) {
                $heroDefaultTextColor: darken($heroDefaultTextColor, 30%);

                color: $heroDefaultTextColor;
            } @else {
                $heroDefaultTextColor: lighten($heroDefaultTextColor, 30%);

                color: $heroDefaultTextColor;
            }
         }
</code></pre>
<p>If the initial <code>background-color</code> is light colored (as the lightness is higher than 50%), we <code>darken()</code> the default text and set it to the <code>color</code> property. If the background is dark-toned, we raise the lightness of the text color.</p>
<h4 id="definelayoutwithmediaquerymixin">Define Layout With Media Query Mixin</h4>
<p>The component will have an outer <code>.hero</code> class on the outer container and for each the wrapper table of each blog (<code>title</code>, <code>img</code>, <code>p</code>), we apply a class for the desired <code>width</code> value. As the following <code>width</code> cover most of the use cases, we have <code>.col33</code>, <code>.col50</code> and <code>.col67</code> in our markup. Let's create the same in the SCSS.</p>
<p>We append the corresponding CSS to the end of our class declaration.</p>
<pre><code>        .hero {

                 ...

            .col33 {
                width: 33%;
            }

            .col67 {
                width: 67%;
            }

            .col50 {
                width: 50%;
            }

        }
</code></pre>
<p>This controls the width of desktop and webmail clients. For mobile users, we need to reorder the hero components parts and for that, we define a media query mixin.</p>
<p>We do this by mixin because:</p>
<ul>
<li>You'll often encounter this in others work</li>
<li>You may reuse the same media query declaration with different breakpoints when you build complex layouts.</li>
</ul>
<p>If you get stuck, just <a href="http://sass-lang.com/documentation/file.SASS_REFERENCE.html#Passing_Content_Blocks_to_a_Mixin__mixin-content">check out the Sass documentation</a>.</p>
<pre><code>        @mixin mobile {
            @media only screen and (max-width: $reorderBreakPoint) {

                @content;
            }
        }

        @include mobile {
            .container, .col33, .col67, .col50  {
                width: 100% !important;
            }
        }
</code></pre>
<p>What you can see above is that:</p>
<ul>
<li>we include our media query in a named mixin block</li>
<li>pass in a <code>$reorderBreakPoint</code> variable - this will be defined in <code>layout.scss</code><br>
-the <code>@content</code> directive will include the content defined in the <code>@include</code> directive</li>
</ul>
<p>Last but not least, we need a <code>layout.scss</code> basically just to handle the templates structure: it'll define the width of the email and the breakpoint values we want to use.</p>
<pre><code>$containerWidth: 600px;
$reorderBreakPoint: $containerWidth - 1px;

.container {
    width: $containerWidth;
}
</code></pre>
<p>If we put all of this together, compile it and embed the contents of <code>main.css</code> we are done with our work.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/11/change-components-color-scheme.gif" alt="Beginner's Guide to Using Sass in Email Coding"></p>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-07/step-02/">You can check it out in the end results</a>.</p>
<p>Among the working files, you can also find a <a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-07/step-03/">slightly improved version of the project</a> with <code>resets.scss</code> and a nice example for mixins in the <code>typography.scss</code>. I also included a mixin for the button component's dimensions in <code>buttons.scss</code>. I'm confident that you'll figure out how they work. If you'd have questions along the way, feel free to ask them in the comments section below the article.</p>
<p><strong>That's it for a short introduction about CSS preprocessors.</strong> I hope you agree that they provide more flexibility and control regarding design and maintenance of style rules. They apply changes better compared to regular CSS. You could see two example of general components. You can use them in future projects and you've learned how to quickly update your design.</p>
<h2 id="summary">Summary</h2>
<p>We've covered preprocessors as the first step of CSS code handling in this article. Our next post will continue this thread having its focus on style declaration inliner tools.</p>
<p>First in the post, we discussed the qualities specific to preprocessor languages. We selected Sass and learned to compile Sass files through the command line. We also saw a terminal based command to include all styles in the <code>style</code> tag.</p>
<p>We've seen before that HTML structure is often helped with <a href="https://blog.edmdesigner.com/how-to-use-sublime-text-for-html-email-development/#buildingcodesnippets">code snippets</a> and <a href="https://blog.edmdesigner.com/code-generator-tools-used-in-html-email-development/">generators</a> by creating components or modules all the time.</p>
<p>We showed that CSS can be similarly adjusted to apply modularity and logic by using preprocessors. We learned about the must-know features and built a hero unit and a button component using them that we can include in our next project.</p>
<p>Thanks for joining us! See you next time as well.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<script src="https://plugins.edmdesigner.com/EDMdesignerPlugins.js"></script>
<script src="https://edmdesigner.github.io/modern-html-email-tutorial/scripts/preivew.js"></script></div>]]></content:encoded></item><item><title><![CDATA[Open Source Email HTML Modification Tools for Email Developers]]></title><description><![CDATA[Grab these free & open-source HTML code modification tools created by EDMdesigner specifically for email coders.]]></description><link>https://blog.edmdesigner.com/open-source-email-html-modification-tools/</link><guid isPermaLink="false">5afad21c3bed88001585fba0</guid><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[scripting]]></category><category><![CDATA[maintainability]]></category><category><![CDATA[code quality]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 18 Oct 2017 13:20:32 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/10/open-source-email-html-modification-tools.jpg" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/10/open-source-email-html-modification-tools.jpg" alt="Open Source Email HTML Modification Tools for Email Developers"><p>Every now and then you can find yourself in situations, where you have to use other people's code or you need special versions of yours. Wouldn't it be great if you had ready-made tools to convert the existing code to what you actually need? In this post, you'll find three of them that help with different transformations. These types of tools are called code modifier tools.</p>
<p>It's important to understand that code modifiers are in fact specific <a href="https://blog.edmdesigner.com/code-generator-tools-used-in-html-email-development/">code generators</a>. They both provide the output based on the supplied input and the previously defined rules for the transformation. Opposed to code generation tools, however, in code modification tools the input has to be working pieces of codes (in our tools HTML), not only parameters, and the output is the same data with controlled alterations. Does it make sense?</p>
<p>I hope it does. If you think about it, inliners are good examples for code modifiers: HTML is provided with <code>style</code> tags, which is translated to markup with inline styles. We'll revisit them in detail in our next article, where we'll be talking about CSS architecture in email development.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=6">
</script>
<p>In this tutorial, I'll show you 3 open-source projects that surfaced as development needs during our email editor's development previously. The projects are as follows:</p>
<ul>
<li><strong>TextVersionJS</strong> strips out HTML markup and provide customizable markdown format</li>
<li><strong>Bulletprooflist</strong> converts <code>ul</code>, <code>ol</code> and <code>li</code> elements in HTML to legacy email client compatible code</li>
<li><strong>BulletproofLineLenght</strong> wraps long lines to separate multiple lines</li>
</ul>
<p>I'll show you thoroughly how to include them in any project. You may find them useful in your workflow as well. I even hope that they inspire you to write your own custom tools.</p>
<p>As we are developing a new generator engine at EDMdesigner, it is likely that we'll release new open-source projects in the future. You can visit us <a href="https://github.com/EDMdesigner">on Github</a> from time to time to check up on these upcoming tools.</p>
<h2 id="htmltotextstringwithtextversionjs">HTML To Text String with TextversionJS</h2>
<p>First, we start with <a href="http://textversionjs.com/">TextVersionJS</a> that converts email HTML to <a href="https://en.wikipedia.org/wiki/Markdown">markdown text</a>. You would most often need that to reduce SPAM scores of an email campaign. By sending along the email's text version in your ESP, <a href="https://litmus.com/blog/reach-more-people-and-improve-your-spam-score-why-multi-part-email-is-important">it's less likely</a> that the message gets marked as SPAM.</p>
<p>Another use case is for testing email campaigns' value with the plain text version. In some email marketing communication <a href="https://blog.chamaileon.io/choosing-between-plain-text-html-email/#thehistorybehindplaintexthtmlemail">plain text performs better</a> in user engagement. If you work with very long HTMLs, it's much easier to extract the content with this tool than by hand.</p>
<p>Let's see, how we can use the tool and what configurations are available.</p>
<p>We used the <a href="https://github.com/umdjs/umd">Universal Module Definition pattern</a>, which attempts to offer compatibility with the most popular script loaders of the day. With that, you can use the tool on the server-side and in the browser as well.</p>
<p>I'll show how to include TextVersionJS in the browser step-by-step firstly:</p>
<p><strong>1, Create a basic template:</strong></p>
<pre><code>    &lt;!DOCTYPE html&gt;
    &lt;html&gt;
    {% include head %}
    &lt;body&gt;   
        {% include header %}
  
        &lt;div class=&quot;page-content&quot;&gt;
            &lt;h1&gt;TextversionJS&lt;/h1&gt;
            &lt;p&gt;This tool is awesome&lt;/p&gt;
            &lt;h2&gt;HTML to plain text converter online&lt;/h2&gt;
 
            &lt;h3&gt;Paste your email HTML here&lt;/h3&gt;
            &lt;div&gt;
                &lt;textarea id=&quot;htmlTextarea&quot;&gt;&lt;/textarea&gt;
            &lt;/div&gt;
            &lt;button id=&quot;generateButton&quot;&gt;Generate&lt;/button&gt;
      
            &lt;h3&gt;The text version&lt;/h3&gt;
            &lt;div&gt;
                &lt;textarea id=&quot;textVersionTextarea&quot;&gt;&lt;/textarea&gt;
            &lt;/div&gt;       
        &lt;/div&gt;

        {% include footer %}
    &lt;/body&gt;
    &lt;/html&gt;
</code></pre>
<p>There are two <code>textarea</code> elements in the content. We define <code>id</code>s (&quot;htmlTextarea&quot; and &quot;textVersionTextarea&quot;) for easy access to them from the JavaScript.</p>
<p>The parts, denoted as <code>{% include footer %}</code> are for showing, where you would likely add fancy custom elements. We'll only change some of them.</p>
<p><strong>2, Include TextversionJS and make calls to the tool:</strong></p>
<p>As the JavaScript file detects it's environment as I showed before, you can include it as you would any other JS file in the HTML:</p>
<pre><code class="language-html">       &lt;script src=&quot;./textversion.js&quot;&gt;&lt;/script&gt;
</code></pre>
<p>To activate the freshly included JS functionality, we need to call its main method. That's <code>htmlToPlainText</code> according to the documentation, but it's set to be called as <code>createTextVersion</code> in the module definition.</p>
<p>We set up a button element, which will fetch the necessary DOM elements and call <code>createTextVersion</code> on them. The returned content will then bed pushed to the second textarea. You can see this below:</p>
<pre><code>&lt;script&gt;
    function generate() {
        var htmlTextarea = document.getElementById(&quot;htmlTextarea&quot;);
        var textVersionTextarea = document.getElementById(&quot;textVersionTextarea&quot;);
        textVersionTextarea.value = createTextVersion(htmlTextarea.value);
    }
    
    var generateButton = document.getElementById(&quot;generateButton&quot;);
    generateButton.onclick = generate;
&lt;/script&gt;
</code></pre>
<p><strong>3, Add basic styling for design value</strong></p>
<p>It has little value to the tool's functionality, but if you work with the browser probably can't leave out some finesse for the UI:</p>
<pre><code>            &lt;style&gt;
                .page-content {
                    margin: 0 30%;
                }
                textarea {
                    width: 40vw;
                    height:20vh;
                }    
            &lt;/style&gt;
</code></pre>
<p>It's time to see what we've achieved:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/10/textversion-1.gif" alt="Open Source Email HTML Modification Tools for Email Developers">](<a href="http://textversionjs.com/">http://textversionjs.com/</a>)</p>
<p>You can pass a configuration object for the tool with 7 configuration properties:</p>
<pre><code>    var styleConfig = {
        linkProcess : null,
        imgProcess : null,
        headingStyle : &quot;underline&quot;; // hashify, breaklink
        listStyle : &quot;indention&quot;; // indention
        uIndentionChar : &quot;-&quot;,
        listIndentionTabs : 3  
    }
</code></pre>
<p>To sum up, you can set the indentation, link and image output format and heading styles. The <code>linkProcess</code> and <code>imgProcess</code> properties are special because they'll apply any custom implementation you provide.</p>
<p>There are a few highlights about usability:</p>
<ul>
<li>It has no dependency, so you can use it safely and consistently</li>
<li>On the client-side, if you use custom strings you need to replace them before you could send the email</li>
<li>While you can convert the final HTML to text-version on the server-side, no additional steps required</li>
</ul>
<p>I encourage you to check out how it works and give it a try now <a href="http://textversionjs.com/">on the project's demo page</a> and <a href="https://github.com/EDMdesigner/textversionjs">check out the full source code of the tool</a>.</p>
<h2 id="croplineswithbulletprooflinelenght">Crop Lines with BulletproofLineLenght</h2>
<p>The next tool takes good care of long lines as most email clients have troubles displaying them. Many characters in a single line can break the layout easily. To prevent this from happening, we can use the BulletproofLineLenght tool and set up the line lengths to an arbitrary value.</p>
<p>In this section, we are going to use the tool on the server-side in the example, but you can <a href="https://edmdesigner.github.io/bulletprooflinelength/">access it online</a> too.</p>
<p>The project's working folder contains a test tool, where you can try out quickly how this code modification works. We are going to use that for the server-side example, with the only difference of including the project's working files via NPM. The steps are the following:</p>
<p><strong>1, Open a project folder:</strong></p>
<p>The necessary commands are:</p>
<pre><code>		mkdir &lt;your directory name&gt;
		cd &lt;your directory name&gt;
		npm init
		npm install bulletprooflinelength --save
</code></pre>
<p>After <code>npm init</code> you are prompted several questions about the project, completing them you'll have the <code>package.json</code> file created. If you need a deeper understanding about getting started with NPM, you can check <a href="https://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts/">our previous tutorial</a> on scripting or <a href="https://docs.npmjs.com/">the NPM documentation</a>.</p>
<p><strong>2, Install BulletproofLineLength:</strong></p>
<pre><code>		npm install bulletprooflinelength --save
</code></pre>
<p>With this command, a <code>node_modules</code> directory gets added to your working files.</p>
<p><strong>3, Using the tool in projects:</strong></p>
<p>As mentioned before we already have an exemplary use of the tool among our working files, and the project's documentation shows clearly how we can include it in our JavaScript files. So the modified code is:</p>
<pre><code>        // FROM THE DOCUMENTATION
        // Including from node_modules
        var bulletproofLineLength = 
        require(&quot;bulletproofLineLength&quot;);

        // FROM PROJECT'S TESTING TOOL
        // Requiring necessary Node packages
        var fs = require(&quot;fs&quot;);
        var path = require(&quot;path&quot;);

        var stringWithLongLines;
        var maximalLineLength = 50;

        // Parsing command line arguments
        var pathToFile = path.join(__dirname, process.argv[2]);
        var parsedPath = path.parse(pathToFile);

        stringWithLongLines = 
        fs.readFileSync(pathToFile, &quot;utf8&quot;);

        var stringWithShortLines = 
        bulletproofLineLength(stringWithLongLines, maximalLineLength);

        // Writing line-split HTML to file
        fs.writeFileSync(path.join(__dirname, &quot;./results/&quot;, parsedPath.name 
        + &quot;-splitted&quot; + parsedPath.ext), stringWithShortLines);
</code></pre>
<p>and that's it. We have BulletproofLineLength set up in our project, able to read HTML files and output line-split version of it into a separate file. It could be an end-task of an automated workflow.</p>
<p>It's time to spare some word about how the tool works and what restrictions or opportunities it has:</p>
<ul>
<li>the tool accepts any input format, but only HTML and CSS lines are processed, otherwise, the original line is returned</li>
<li>the splitting of lines are set up based on typical separator characters of the language: <code>&lt;</code>, <code>&gt;</code>, <code>&quot;</code>, <code>'</code> in HTML and <code>;</code>, <code>,</code>, <code>}</code> in CSS. That means that long inline style declarations are not split in the HTML.</li>
</ul>
<p>I encourage you to check out how it works and give it a try now <a href="https://edmdesigner.github.io/bulletprooflinelength/">on the project's demo page</a> and <a href="https://github.com/EDMdesigner/bulletprooflinelength">check out the full source code of the tool</a>.</p>
<h2 id="listsinemailswithbulletprooflist">Lists in Emails with Bulletprooflist</h2>
<p>This third project was introduced years ago in our email HTML generator. A recent update in it made us realize that it can be helpful for fellow email coders. The tool is responsible for making unordered and ordered lists bulletproof.</p>
<p>In this section, our main focus will be on the generated output, namely what makes a list bulletproof in email clients.</p>
<p>There's a necessary addition in order to make the tool work in the browser: we need to bundle our server-side dependency, the Cheerio package with <a href="http://browserify.org/">Browserify</a> or a similar bundler. Bundlers let us implement external modules easily. with this out of the way, let's jump in the middle:</p>
<p>After copy &amp; paste and generate we have a bulletproof list available for comparison with the original one:</p>
<style>

.client-summary {
	border: 1px solid black;
	border-collapse: collapse;
	margin-top: 10px;
	margin-bottom: 10px;
}

.client-summary th {
	border: 1px solid black;
	text-align: center;

	background-color: #E5E5EB;

	height: 15px;
	padding: 5px;
}

.client-summary td {
	border: 1px solid gray;
	vertical-align:middle;

	background-color: #f4f4f4;


}

.client-summary td p {
	list-style-type: none;
	text-align: center;
	margin: 0;
	padding: 0;
}

.client-summary td pre {
        
	margin: 3px;
	padding: 0;
}

@media all and (max-width: 600px) {
    .code-block-fix {
        font-size: 8px !important;
    }
}


</style>
<table class="client-summary code-block-fix" width="100%" cellspacing="0" cellpadding="0">
	<tr>
		<th>Before</th>
	</tr>
	<tr>
		<td>
```
          <html>
            <head></head>
              <body>
              <ul>
                  <li style="font-size: 16px;">First Item</li>
                  <li style="font-size: 16px;">Second Item</li>
                  <li style="font-size: 16px;">Third Item</li>
              </ul>
              </body>
          </html>
```
		</td>
      </tr>
</table>
<table class="client-summary code-block-fix" width="100%" cellspacing="0" cellpadding="0">
	<tr>
		<th>After</th>
	</tr>
        <tr>
		<td>
```
          <html><head></head>
          <body>
          <table cellpadding="0" cellspacing="0" border="0">
              <tr><td align="left" width="15" valign="top" style="font-size: 16px;">•</td>
                  <td align="left" style="font-size: 16px;">First Item</td>
              </tr>
              <tr><td align="left" width="15" valign="top" style="font-size: 16px;">•</td>
                  <td align="left" style="font-size: 16px;">Second Item</td>
              </tr>
              <tr><td align="left" width="15" valign="top" style="font-size: 16px;">•</td>
                  <td align="left" style="font-size: 16px;">Third Item</td>
              </tr>
          </table>
<pre><code>      &lt;/body&gt;&lt;/html&gt;
</code></pre>
<pre><code>		&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;

You see in the above tables that the `ul` tags are converted to `table`s (just as `ol`s would) and each `li`s are replaced with a `tr` element with 2 cells. The first `td` holds the bullet point and handles the spacing with the `width` value. The second cell contains the text content of the list item. They each inherit an `align=&quot;left&quot;` and a `font-size` property.

Now the most important step is to check the results of visual tests.

First, let's check what happens when we apply no style on our lists but have `margin` and `padding` reset as part of the necessary reset step of email development workflows. We can see that bullet points are not aligned correctly to their containers in regular lists, but they work correctly when used with the bulletproof method with tables:

&lt;table class=&quot;client-summary&quot; width=&quot;100%&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
	&lt;tr&gt;
		&lt;th&gt;Before&lt;/th&gt;
                &lt;th&gt;After&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt;
![Original email preview of HTML list](/content/images/2017/10/appmail9-vertical-allowed-1366.png)
		&lt;/td&gt;
		&lt;td&gt;
![Email preview of HTML list with Bulletproof code](/content/images/2017/10/appmail9-vertical-allowed-1366-bulletproof.png)
		&lt;/td&gt;
      &lt;/tr&gt;
&lt;/table&gt;

I only included Apple Mail's preview as it is the most modern client, but the same behavior was true for every other email client.

We continue by adding the following snippet to the code, which will make regular lists to align correctly:

</code></pre>
<pre><code>		tr,
		td,  
		ul,  
		ol,
		li {
		    margin: 10px;
		    padding: 10px;
		}
</code></pre>
<pre><code> 
We can open up the previews of the [original](https://litmus.com/checklist/emails/public/afe03b5) and the [bulletproof](https://litmus.com/checklist/emails/public/3e5e763) HTML to examine the difference. 

As you can see in the images below, list items aren't aligned correctly (bullet points are not in line with the ordered list's numbers) in some of the clients, but are fixed with the bulletproof code:


&lt;table class=&quot;client-summary&quot; width=&quot;100%&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
	&lt;tr&gt;
		&lt;th&gt;Original&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td style=&quot;padding:10px;&quot;&gt;
![Outlook 2003 original email preview](/content/images/2017/10/ol2003-vertical-allowed-1366-original.png)
		&lt;/td&gt;
      &lt;/tr&gt;
&lt;/table&gt;


&lt;table class=&quot;client-summary&quot; width=&quot;100%&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
	&lt;tr&gt;
                &lt;th&gt;Bulletproof&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td style=&quot;padding:10px;&quot;&gt;
![Outlook 2003 bulletproof email preview](/content/images/2017/10/ol2003-vertical-allowed-1366-bulletproof.png)
		&lt;/td&gt;
      &lt;/tr&gt;
&lt;/table&gt;

&lt;table class=&quot;client-summary&quot; width=&quot;100%&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
	&lt;tr&gt;
		&lt;th&gt;Original&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td style=&quot;padding:10px;&quot;&gt;
![Yahoo! Mail original email preview](/content/images/2017/10/yahoo-vertical-allowed-1366-original.png)
		&lt;/td&gt;
      &lt;/tr&gt;
&lt;/table&gt;

&lt;table class=&quot;client-summary&quot; width=&quot;100%&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
	&lt;tr&gt;
                &lt;th&gt;Bulletproof&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td style=&quot;padding:10px;&quot;&gt;
![Yahoo! Mail bulletproof email preview](/content/images/2017/10/yahoo-vertical-allowed-1366-bulletproof.png)
		&lt;/td&gt;
      &lt;/tr&gt;
&lt;/table&gt;




Last, but not least some additions to think of when you use the tool:

   - it increases the email size, which may increase the spam score, especially with long lists
   - you have little options for customization. You would need to modify the tool's code to receive different output

I encourage you to check out how it works and give it a try now [on the project's demo page](https://edmdesigner.github.io/bulletprooflist/) and [check out the full source code of the tool](https://github.com/EDMdesigner/bulletprooflist)

## Summary

By finishing this tutorial post you have learned all about our ready to use code modification tools.

We saw what TextVersionJS, Bulletprooflist, BulletproofLineLenght are good for but the name quite said it all.

**The key takeaways:**

You can use tools for single-purpose use cases.
  
Ours are available if you want to:

  -  bookmark them: [1](http://textversionjs.com/) , [2](https://edmdesigner.github.io/bulletprooflinelength/) , [3](https://edmdesigner.github.io/bulletprooflist/)   
  -  download or clone them from Github: [1](https://github.com/EDMdesigner/textversionjs) , [2](https://github.com/EDMdesigner/bulletprooflinelength) , [3](https://github.com/EDMdesigner/bulletprooflist)    
  -  install via NPM: [1](https://www.npmjs.com/package/textversionjs) , [2](https://www.npmjs.com/package/bulletprooflinelength) , [3](https://www.npmjs.com/package/bulletprooflist) 

Let your projects benefit from open source tools.

We also mentioned that with the whole new email generator engine we're building at EDMdesigner, we are likely to release similar open-source tools. Hope that the email developer community will find these tools useful.

If you enjoyed this tutorial post and you do not want to miss the next one, please subscribe to our newsletter.

&lt;div data-chamaileonplugin=&quot;blog-forms/subscribe-newsletter&quot; data-page=&quot;subscribe-newsletter&quot; data-location=&quot;inside-blog-post&quot;&gt;&lt;/div&gt;</code></pre>
</body></html></td></tr></table></div>]]></content:encoded></item><item><title><![CDATA[Managing Full-time Employees at a Growing SaaS Company]]></title><description><![CDATA[In this article you can read about how an early-stage startup can overcome management difficulties with the SCRUM methodology and the pomodoro technique.]]></description><link>https://blog.edmdesigner.com/managing-full-time-employees-at-a-growing-saas-company/</link><guid isPermaLink="false">5afad21c3bed88001585fba3</guid><category><![CDATA[SRCUM]]></category><category><![CDATA[Management]]></category><category><![CDATA[Pomodoro]]></category><category><![CDATA[Lessons Learned in SaaS Development]]></category><dc:creator><![CDATA[Gyula Németh]]></dc:creator><pubDate>Wed, 04 Oct 2017 06:44:00 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/10/managing-full-time-employees-at-a-growing-saas-company.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/10/managing-full-time-employees-at-a-growing-saas-company.png" alt="Managing Full-time Employees at a Growing SaaS Company"><p>Since we announced the <a href="https://blog.edmdesigner.com/tag/modern-html-email-tutorial/">Modern HTML Email Tutorial</a> on the 23rd of November last year, we published only tech-heavy articles every second week. This time it's going to be different.</p>
<p>This and the next article in this series are about how to manage people, how to motivate, and how to delegate in an efficient way that things will be predictable.</p>
<p>In the last five years, we have grown from an idea to a stable company of 15 people. There were times when only full-time employees worked at our company, and there were times when only I remained on the project full-time. At the moment, there are 5 full-time and 10 part-time people at the company.<br>
These extremely different conditions mean that we had to change our management style and methods from time to time. We had to adapt to these circumstances to survive as a company.</p>
<p>You always have to seek out for new methods to manage the chaos around you. This is especially true when we are talking about the management of part-time employees. There is an extra management cost, but if you build your company with this in mind, then you can have a lot of very motivated people working together with you to build a great company.</p>
<script src="https://edmdesigner.github.io/lessons-learned-in-saas-development/scripts/chapters.js?p=2">
</script>
<p>In this article, I'm focusing on managing a small team consisting of full-time employees. In my next article, I'm focusing on managing part-time teams.</p>
<p>Since this story is about growing a company from 0 to 15 people, I mainly recommend it to SaaS startups who have not grown to this level yet. Secondly, I recommend it to people who are interested in employing more part-time people, but they find it difficult to manage them.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="theearlydays">The Early Days</h2>
<p>Like many other startups, we also started off in a garage. Not exactly a garage, because we worked at my apartment, but the principle is the same. We worked irregularly because all of us had other jobs. I was teaching programming at a university, which turned out later to be a very good source for talent. Since there were only a few of us, we did not really need any kind of project management. It worked perfectly, communication on this level (3 people) was very easy.</p>
<p>Every project at the beginning is not very well organized, but to be honest, it does not really matter. You don't really need strict management policies when you have one or two developers working on a project.</p>
<p>After we got our investment, we hired two full-time employees (one of them from the university I was teaching at). Maybe it does not seem to be a big difference, but managing a five-people company is totally different from managing a three-people company. There were three main things:</p>
<ul>
<li><strong>Losing focus:</strong> It often happened to us that we tried to solve everything at once and eventually very few of those things became reality.</li>
<li><strong>Lack of information/miscommunication:</strong> If there are more and more people then it will be more and more often that for a subset of those people certain issues are crystal clear but not for others. It leads to situations when people think that the others are stupid. It's definitely something to avoid.</li>
<li><strong>Planning ahead was very hard:</strong> As mentioned before, we often lost focus, but also, we did not really plan the details of features thoroughly, so it was really hard to estimate when certain milestones would be ready.</li>
</ul>
<p>On top of these very serious issues, there were a lot of distractions in the office. It was very chaotic and I think the productivity was not even close to the level where it could have been.</p>
<p><strong>We needed a formalized system, which solves those problems.</strong></p>
<h2 id="scrumforthewin">SCRUM for the Win</h2>
<p>Our solution for the problems above was the SCRUM methodology, which is a set of practices bound together in a way that works very well for software development teams. I think you should not stick to a specific pre-defined set of rules strictly, but you have to pick those which work best for you.</p>
<p>There are many great articles about the SCRUM methodology, so I don't want to spend the time to describe the different parts. If you are not familiar with these concepts, I suggest you search for a good article about the SCRUM methodology. In this article, I will focus on what worked well and not so well for us.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/10/ScrumBacklog.jpg" alt="Managing Full-time Employees at a Growing SaaS Company"></p>
<p>It took us some time, but eventually, we could pick those parts from the SCRUM methodology which worked great for us. Actually, we were very strict with most of the things and everything just clicked.</p>
<p>I have to emphasize one thing here. We were a team of 5 full-time people. When you think about part-time employees, you have to radically change your mindset, but I will talk about that in the next article of this series.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h3 id="sprints">Sprints</h3>
<p>We tried one- and two-week long <strong>sprints</strong>. Both of them worked well for us, but in different situations. Shorter sprints are great if you want your team to focus for a short period of time, but you still want to add or remove things relatively quickly. I think you should not think about releasing new things faster than this. Longer sprints are better when we needed to develop a little bit bigger features. We tried even three-week long sprints, but that was just way too long.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/10/sprint.png" alt="Managing Full-time Employees at a Growing SaaS Company"></p>
<p>We had our <strong>sprint reviews</strong> and <strong>sprint plannings</strong> on Wednesdays. The reason is simple. If it's in the middle of the week, then usually you can finish it faster, because people are in the flow. We have tried Mondays as well, but then everybody was scratching their heads to recall what happened and what should be done differently. Also, it took some time for people on Mondays to recall the details of some features that were very well planned already. It just took too much time. (You know, weekends sometimes erase your memory from the last week...)</p>
<p>Sprint reviews were great. We created <strong>retrospectives</strong>, <strong>action items</strong> for improvement and there were people responsible for those action-items. Although it was great for the team, I often felt that it takes too much time and sometimes we did not use it properly.</p>
<p>Sprint plannings were very useful. We estimated the <strong>business value</strong> and the <strong>story points</strong> of every <strong>user story</strong> and based on those we chose which ones to implement in that sprint. After that, we associated well-detailed tasks to the user stories.</p>
<p>To be honest, estimating the story points never worked really well. Sometimes it seemed like we are doing it well, but after a few sprints, we failed again to estimate well. I think it can have a few reasons:</p>
<ul>
<li>Planning and estimating like this is just bad. I think it's much better to plan the tasks ahead of time and iterate over them for a while. In my experience, estimations will be much, much more precise that way. (After a while we started to create tasks during daily planning, not during the sprint planning. It also helped to keep sprint plannings less boring.)</li>
<li>Involved people did not risk enough. I think there was not enough motivation to estimate well and to finish the tasks. We never had a rule to stay there for weekends if something is not finished, although that way everybody would have taken it much more seriously.</li>
<li>Many people might not agree with me, but classical SCRUM is rather for developed companies, not for startups. Even if you think about the concept of user stories, that works well when there's someone who ordered a software from you. If you create your own product it's a little bit ridiculous in &quot;As a user... I want to...&quot; sentences. The other very important thing is that there should be the well-defined different roles, for example, the SCRUM master and the product owner. These distinctions rarely happen at startups.</li>
</ul>
<h3 id="dailyactivities">Daily Activities</h3>
<p>We had <strong>daily standups</strong> every day. This is a great way to see if the team has any problems and it's also a nice and controlled way to deal with those problems. I think daily standups are great if the team is interested in almost every piece of info or they can help each other. If it's not like that, then the standup is a waste of time for many people.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/10/standup.png" alt="Managing Full-time Employees at a Growing SaaS Company"></p>
<p>There was a very useful thing which we did at the beginning of every daily standup. We updated our totally manual <strong>burndown chart</strong>, which we draw on a piece of paper. It helped the team to realize if we were behind schedule. I know that there are many tools for this, but this ceremony had a really good effect on the whole team.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/10/burndown.png" alt="Managing Full-time Employees at a Growing SaaS Company"></p>
<p>Besides daily standups, we had another very, very important daily activity, which is usually not practiced by most companies. It's <strong>daily planning</strong>. It can help the whole team to have a commonly shared knowledge and point of view of the upcoming sprints' features.</p>
<p>We did it every day half an hour before our usual lunchtime. This way we were sure that these meetings wouldn't take too long. Just get to the point, and if you don't have enough time to discuss something, you can still do that tomorrow during the next daily planning. If that issue was not that important, then you will discuss something else.</p>
<p>Daily planning helped us a lot. When it comes to estimations, it leads the team from total chaos to a relatively well-coordinated state where we could make very good estimations and things were finished when they were supposed to be finished.</p>
<h2 id="afewwordsaboutprojectmanagementtools">A Few Words about Project Management Tools</h2>
<p>Let me share a few thoughts about the project management tools we used. At the beginning, we used <a href="https://trello.com/">trello</a> for project management. It's good for kanban, but not enough for sprints and SCRUM.</p>
<p>We turned to <a href="https://www.atlassian.com/software/jira">Jira</a> but to be honest, we never liked it. Although you can accomplish everything with Jira, it's extremely burdensome to use and it just does not feel right.</p>
<p>Eventually, we started to use <a href="https://www.zenhub.com/">ZenHub</a> which is simply the best project management tool so far. It builds upon GitHub's ticketing system and enhances its functionality with neat things, for example, Kanban boards and burndown charts. There are a few caveats but I can bravely suggest you and your team give it a try.</p>
<h2 id="thepomodorotechnique">The Pomodoro Technique</h2>
<p>As I mentioned previously, there was a lot of distraction in our office, even though there were only 5 people at the same time. Even if you introduce some kind of policy to keep everyone quiet, people tend to break those rules.</p>
<p>Here comes the Pomodoro technique into the scene. It divides your distraction-free time intervals in which you have to focus on a specific topic from the breaks, in which people can distract you.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/10/pomodoro.png" alt="Managing Full-time Employees at a Growing SaaS Company"></p>
<p>Originally this technique was invented for individuals to work effectively, but we introduced it on company level. This way we synchronized the focus time of every individual in the company.</p>
<p>If you want to try out a Pomodoro tool with which you can synchronize your whole team, try <a href="http://www.marinaratimer.com/">marinaratimer</a>. Although it's not perfect, we used it on a daily basis.</p>
<p>Synchronizing the whole company worked great for us because everybody knew when they can talk to others without interrupting them. Even if somebody stuck with some task, the longest amount of time while they won't get their answers is 25 minutes at max. (And they can always work on something else in the meanwhile.)</p>
<h2 id="summary">Summary</h2>
<p>By reading this article you have gained some insights how the management of full-time employees evolved in our first few years. From total chaos, we changed to a strict SCRUM company and we also used the Pomodoro technique to keep our distraction-free times.</p>
<p>I want to emphasize again that one of the most important habits we developed was the daily planning. With the help of that, we could estimate much, much better and the scrum meetings were more useful for everyone.</p>
<p>It worked very, very well with full-time employees, but after a while, we started to work together with many part-time employees. If you are interested why SCRUM was not suitable for them and how we changed the management in our company to work effectively, then come back and read the next article in this series.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
</div>]]></content:encoded></item><item><title><![CDATA[Code Generator Tools Used in HTML Email Development]]></title><description><![CDATA[Do you write every line of HTML manually when coding emails? Stop! It's time to find out more about code generator tools used in email development.]]></description><link>https://blog.edmdesigner.com/code-generator-tools-used-in-html-email-development/</link><guid isPermaLink="false">5afad21c3bed88001585fb9c</guid><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[code quality]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[code snippets]]></category><category><![CDATA[maintainability]]></category><category><![CDATA[code generators]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 20 Sep 2017 13:28:57 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/09/code-generator-tools-used-in-html-email-development.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/09/code-generator-tools-used-in-html-email-development.png" alt="Code Generator Tools Used in HTML Email Development"><p>Every now and then you hear that only machines will produce programming code in the near future. Computers are taking over. It may be frightening or challenging, depending on the perspective. But don't worry, there is still some time for the transition and thus it's really advantageous to take control and learn about how code generation tools work.</p>
<p>In this article we'll show you tools that help to create robust email code based on presets. Small, yet important steps to the rise of computer domination in development.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=5">
</script>
<p>Throughout this post, we'll be talking about Campaign Monitor's background and button code generators - well-known in the industry - and examine their advantages. Following these, we'll be showing two layout generators: one we created in-house and one found in our research.</p>
<p>By learning about these tools, we focus on quality and maintainability aspects of email development. We can use tools written by others or we can write them ourselves matching the best practices. We'll be able to leverage the controlled quality to always have the expected outcome.</p>
<p>In this tutorial series, we started off with generally-applicable improvements to anyone's email development workflow. As we have now a grounding knowledge on the basics, we dive into customized applications. By signing up, you can be an insider at EDMdesigner and look behind the scenes. Don't miss out on the chance!</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="codegenerationtools">Code Generation Tools</h2>
<p>As mentioned in the introduction, the big idea behind code generation tools is that you have bulletproof code snippets that can take parameters and generate code accordingly. You'll be sure that the code will work in the email clients you want to support and the process will save you time. That's the case with <a href="https://backgrounds.cm/">backgrounds.cm</a> and <a href="https://buttons.cm/">buttons.cm</a>, so let's look at them first.</p>
<h3 id="backgroundgenerator">Background Generator</h3>
<p>Supporting background images is somewhat tricky in email. You either want to insert them in specific areas or apply in the full email body. Based on your choice, you'll have different considerations. <a href="https://backgrounds.cm/">The backgrounds.cm tool</a> has a solution for both:</p>
<h4 id="fullemailbodybackgroundimage">Full Email Body Background Image</h4>
<p>You can look at Campaign Monitor default code for background images when they are applied to the full email body below:</p>
<pre><code>&lt;div style=&quot;background-color:#7bceeb;&quot;&gt;
  &lt;!--[if gte mso 9]&gt;
  &lt;v:background xmlns:v=&quot;urn:schemas-microsoft-com:vml&quot; fill=&quot;t&quot;&gt;
    &lt;v:fill type=&quot;tile&quot; src=&quot;https://i.imgur.com/YJOX1PC.png&quot; color=&quot;#7bceeb&quot;/&gt;
  &lt;/v:background&gt;
  &lt;![endif]--&gt;
  &lt;table height=&quot;100%&quot; width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; border=&quot;0&quot;&gt;
    &lt;tr&gt;
      &lt;td valign=&quot;top&quot; align=&quot;left&quot; background=&quot;https://i.imgur.com/YJOX1PC.png&quot;&gt;

         CONTENT

      &lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/div&gt;
</code></pre>
<p>The considerations for full body background images are as follows:</p>
<ul>
<li>As many clients block images by default, there's a <code>background-color</code> property in the <code>DIV</code> element as a &quot;fallback color&quot;. You probably don't want blank, white backgrounds to show in marketing emails, so you can define fallback colors to be displayed in those situations.</li>
<li>Generally speaking, it's a good idea to have fallback colors for the cases where images are disabled. However, where the message is forwarded and the fallback color is defined on the email body, this color is applied to the forwarded message's email body as well. That's normally not preferable, especially with dark backgrounds (that's why this phenomena is called &quot;Black reply&quot;). The backgrounds.cm tool uses a wrapper <code>DIV</code> element to avoid <a href="https://litmus.com/community/learning/25-understanding-background-images-in-email">&quot;Black Reply&quot;</a>.</li>
<li>Word-based Outlooks (2007/10/13 and Windows 10 Mail) don't support background images at all. You can only include them with encoding, meaning that the image is given in code. The one used for Outlook clients is <a href="https://www.w3.org/TR/NOTE-VML">VML</a>. These are the parts surrounded with conditional comments  (<code>&lt;!--[opening/closing part of the conditional statment]&gt;</code>). This is definitely a distinct advantage of the tool.</li>
<li>The VML design's architecture is not easy to master. You can get familiar with it with the helpf of <a href="http://www.htmlgoodies.com/beyond/xml/article.php/3473491/VML-Vector-Markup-Language.htm">this tutorial</a> or by using <a href="https://msdn.microsoft.com/en-us/library/bb263898(v=vs.85).aspx">Microsoft's official documentation</a>.</li>
<li><a href="http://freshinbox.com/blog/outlook-com-and-background-images/">According to Freshinbox's blog post</a> (and confirmed by our visual testing) Outlook.com and Office 365 don't support the <code>background-image</code> property in <code>DIV</code> tags. The tool takes care of the problem by the use of the inner table.</li>
<li>The <code>table</code> container's child <code>td</code> holds the background image for &quot;ordinary&quot; email clients. Please note that this is the most robust way of including background images. If you have doubts, check out our <a href="https://blog.edmdesigner.com/background-images-in-modern-html-emails/#backgroundimagesappliedondivs">blog post</a> where we showed it step-by-step. We use a different approach to full email body background images, you may be interested in <a href="https://blog.edmdesigner.com/background-images-in-modern-html-emails/#thebackgroundimagepatterninthebody">reading about it too</a>.</li>
</ul>
<p><strong>With properly set up VML and background attributes in the <code>td</code> elements, you can support almost all clients.</strong></p>
<p><a href="https://litmus.com/checklist/emails/public/c5180bb">Litmus test results for Backgrounds.cm in the email body</a><br>
<a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-05/step-00/index.html">You can check out the full source code of this step on Github</a></p>
<h4 id="asinglecellbackgroundimage">A Single Cell Background Image</h4>
<p>Below you can see the code generated by the tool for a single cell:</p>
<pre><code>&lt;td background=&quot;https://i.imgur.com/YJOX1PC.png&quot; bgcolor=&quot;#7bceeb&quot; width=&quot;120&quot; height=&quot;92&quot; valign=&quot;top&quot;&gt;
  &lt;!--[if gte mso 9]&gt;
  &lt;v:rect xmlns:v=&quot;urn:schemas-microsoft-com:vml&quot; fill=&quot;true&quot; stroke=&quot;false&quot; style=&quot;width:120px;height:92px;&quot;&gt;
    &lt;v:fill type=&quot;tile&quot; src=&quot;https://i.imgur.com/YJOX1PC.png&quot; color=&quot;#7bceeb&quot; /&gt;
    &lt;v:textbox inset=&quot;0,0,0,0&quot;&gt;
  &lt;![endif]--&gt;
  &lt;div&gt;

     CONTENT

  &lt;/div&gt;
  &lt;!--[if gte mso 9]&gt;
    &lt;/v:textbox&gt;
  &lt;/v:rect&gt;
  &lt;![endif]--&gt;
&lt;/td&gt;
</code></pre>
<p>The highlights here are:</p>
<ul>
<li>This setting has two additional sets of parameters (besides fallback color and image source settings).<br>
You can customize the <code>width</code> of the cell with a toggle to fit the email width, and adjust the <code>height</code> with a different toggle to the content height. The latter is far more interesting, because in addition to providing the previously missing dimension, it adds a <a href="https://msdn.microsoft.com/en-us/library/bb264057(v=vs.85).aspx"><code>style=&quot;mso-fit-shape-to-text:true&quot;</code></a>.</li>
<li>We also find a separation of &quot;for Outlooks&quot; and &quot;for other clients&quot;. The VML version of the background image is placed inside the table cell and is applied in desktop Outlook clients. The background from the wrapper <code>td</code> is picked up by all the other email clients.</li>
</ul>
<p>The background tool is a wonderful tool relied on by many email developers. From this short introduction, you could see how it works and if you run visual tests, you can experience it's great client coverage as well. We had our test by inserting the generated code in our boilerplate email template that uses <a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">the Drop Calc Method</a>:</p>
<p><a href="https://litmus.com/checklist/emails/public/ef5a059">Litmus test results for Backgrounds.cm in single cell</a><br>
<a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-05/step-01/index.html">You can check out the full source code of this step on Github</a></p>
<p>However, you may lack the option to use the tool offline in your workflow. The project is not open-sourced in a way that you could include it in your own projects programatically.</p>
<p>The other thing we miss out on is the support for <a href="https://litmus.com/blog/understanding-retina-images-in-html-email">retina background images</a>. We've read about them before, and though it's only a thing for progressive clients yet, it would be nice if you could choose an option for them or be able to develop this feature on the basis of the existing tool.</p>
<h3 id="buttongenerator">Button Generator</h3>
<p>Clickable Call-To-Action buttons are very important in email marketing that makes a bulletproof button generator, like <a href="https://buttons.cm/">Campaign Monitor's</a> invaluable.</p>
<p>There are four basic button types: VML-based, Padding-based, Border-based and Padding + border-based buttons. You can <a href="https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design">look up these buttons</a>, if you need more understanding about them. Last year we <a href="https://blog.edmdesigner.com/bulletproof-html-email-buttons-a-new-line-height-based-approach/">tested all and made some improvements</a> yielding a fifth button type: the Line-height Based Bulletproof Button. Building upon the practical experiments from the last article, we'll conclude why the Buttons.cm generator is a great tool to use.</p>
<p>For appetizers, this is what the generators default code looks like:</p>
<pre><code>    &lt;div&gt;
    &lt;!--[if mso]&gt;
        &lt;v:roundrect xmlns:v=&quot;urn:schemas-microsoft-com:vml&quot;
            xmlns:w=&quot;urn:schemas-microsoft-com:office:word&quot; 
            href=&quot;https://edmdesigner.com&quot; 
            style=&quot;height:40px;v-text-anchor:middle;width:200px;&quot; 
            arcsize=&quot;10%&quot; strokecolor=&quot;#1e3650&quot; fill=&quot;t&quot;&gt;
        &lt;v:fill type=&quot;tile&quot; src=&quot;https://i.imgur.com/0xPEf.gif&quot;
            color=&quot;#556270&quot; /&gt;
        &lt;w:anchorlock/&gt;
        &lt;center style=&quot;color:#ffffff;font-family:sans-serif;
            font-size:13px;font-weight:bold;&quot;&gt;
            Show me the button!
        &lt;/center&gt;
        &lt;/v:roundrect&gt;
    &lt;![endif]--&gt;
        &lt;a href=&quot;https://edmdesigner.com&quot;
        style=&quot;background-color:#556270;
        background-image:url(https://i.imgur.com/0xPEf.gif);
        border:1px solid #1e3650;border-radius:4px;
        color:#ffffff;display:inline-block;
        font-family:sans-serif;font-size:13px;
        font-weight:bold;line-height:40px;
        text-align:center;text-decoration:none;
        width:200px;-webkit-text-size-adjust:none;
        mso-hide:all;&quot;&gt;
        Show me the button!
        &lt;/a&gt;
    &lt;/div&gt;

</code></pre>
<p>Your first instinct may be to run away while you can, but I promise that this snippet is simple (for most parts) and therefore wonderful.</p>
<p>The notable parts:</p>
<ul>
<li>It's basically structured into two buttons: one for Outlook clients with VML, and a regular HTML button for regular email clients as we saw in the background section</li>
<li>VML is used for supporting desktop Outlook clients like with the background tool before. It's hidden for any other clients than desktop Outlooks as its conditional comments is only parsed by Outlook.</li>
<li>The regular HTML button consist of a <code>DIV</code> container element, and an <code>a</code> tag, which has <code>display: inline-block</code>, so it can apply the specified <code>height</code> and <code>width</code> for the link. The whole thing gets hidden by the <code>mso-hide:all;</code> property in desktop Outlooks.</li>
<li>The button can use a background image, which is a nice option to have. However, if the email client doesn't load images by default, the defined <code>background-color</code> will be visible.</li>
</ul>
<p>If you check the theory around which this button is built, it's very similar to EDMdesigner's Line-height Based Button. It also doesn't have padding or margin properties to stretch the button's dimensions, but uses the line-height on the <code>a</code> tag and the <code>width</code> property.</p>
<p>See the Line-height Based Button's code below:</p>
<pre><code>&lt;table width=&quot;100%&quot; border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;  
  &lt;tr&gt;
    &lt;td&gt;
       &lt;table border=&quot;0&quot; cellspacing=&quot;0&quot; cellpadding=&quot;0&quot;&gt;
          &lt;tr&gt;
             &lt;td bgcolor=&quot;### COLOR ####&quot; style=&quot;#### STYLES ####;
              -webkit-border-radius:3px; border-radius:3px;&quot; 
               align=&quot;center&quot;&gt;
                 &lt;a href=&quot;### HREF ###&quot; target=&quot;_blank&quot; 
                   style=&quot;### FONT PROPERTIES ###;
                   text-decoration:none; line-height:54px; 
                   width: 150px; display: inline-block;&quot;&gt;
                   &lt;p style=&quot;### FONT PROPERTIES ###; 
                   line-height:54px;&quot;&gt;
                      I am a button &amp;rarr;
                   &lt;/p&gt;
                &lt;/a&gt;
             &lt;/td&gt;
          &lt;/tr&gt;
       &lt;/table&gt;
     &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
</code></pre>
<p>The main difference comparing the two lies in the use of VML and <code>DIV</code> elements (these we could omit).</p>
<p>As far as support goes, the only clients left out are: old Lotus Notes, Outlook.com and Office365. All the other clients seem to display the button.</p>
<p><a href="https://litmus.com/checklist/emails/public/fa94448">Litmus test result for Buttons.cm</a><br>
<a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-05/step-02/index.html">You can check out the full source code of this step on Github</a></p>
<p>Now, last but not least let the simplicity of the below UI convince you to try this tool next time:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/09/buttonscm-1.png" alt="Code Generator Tools Used in HTML Email Development"></p>
<p>In this section we analyzed the code of the bulletproof button generator and we have seen the advantages it has. By the above image, you can see the available parameter options for customization. You can design beautiful buttons easily.</p>
<p>From the point of flexibility, we miss the option to select which button type you would want the generator to use. For example, if you don't need support for desktop users, the VML part is totally unnecessary, which can make your code more easier to use and much shorter.</p>
<h3 id="layoutgenerators">Layout Generators</h3>
<p>We won't dive into the very details with layout generators, but there are two tools worth mentioning besides the several layout code generators for the web. One is an offline tool, which with certain customization can be truly powerful (you may see that in our article about automation), the other is an online tool ready for use.</p>
<p>With these last pieces, you have most of an email covered. You have tools to generate the layout, background images and bulletproof buttons.</p>
<h4 id="edmdesignerstablegeneratorjs">EDMdesigner's TableGenerator.js</h4>
<p>The first tool is the one we introduced in <a href="https://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts/">a previous tutorial</a>. Our goal was to show, how you would start creating a code generator by yourself with JavaScript. In the post we showed a simple script, capable of creating multi-column layouts with <a href="https://nodejs.org/en/">Node.js</a> based on command line parameters.</p>
<pre><code>node tableGenerator.js 1 2 3 &gt; index.html
</code></pre>
<p><a href="https://nodejs.org/api/cli.html"><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-02/images/terminal-build.gif" alt="Code Generator Tools Used in HTML Email Development"></a></p>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-02/tableGenerator">You can check out the full source code on Github.</a></p>
<p>There are many options to improve the tool above. For simplicity's sake, we didn't customize it to high email client coverage with email specific styles and markup, but it can be done with little effort and some coding skills. Feel free to <a href="https://edmdesigner.github.io/html-email-development-tools/lesson-02/tableGenerator.zip">use the code from the article</a> and make a custom tool of it for emails!</p>
<h4 id="emaillayoutcalculatorbyjulieng">Email Layout Calculator by Julie Ng</h4>
<p>We're going to visit another layout tool lastly, created by a fellow email geek who we respect very much: <a href="https://twitter.com/jng5">Julie Ng</a>. You can access the tool <a href="https://julie.io/email-layout-calculator/">following this link</a>.</p>
<p>Now if you check it out, you can learn quite a handful and you'll get the help you need to design the layout. You get a description on how the tool works, why it uses the properties it uses, and you can customize your desired layout and see the generated code update on the fly.</p>
<p>Julie also <a href="https://julie.io/writing/gmail-first-strategy-for-responsive-emails/">published an article</a> detailing how her tool was designed and what clients it supports.</p>
<p>A two column, <code>600px</code> wide layout with <code>4px</code> separator line would look like this:</p>
<pre><code>    &lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot;
    &quot;http://www.w3.org/TR/html4/loose.dtd&quot;&gt;
    &lt;html lang=&quot;en&quot;&gt;
    &lt;head&gt;
    &lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt; 
    &lt;!-- So that mobile will display zoomed in --&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt; 
    &lt;!-- enable media queries for windows phone 8 --&gt;
    &lt;meta name=&quot;format-detection&quot; content=&quot;telephone=no&quot;&gt; 
    &lt;!-- disable auto telephone linking in iOS --&gt;
    &lt;title&gt;Email Layout Calculator&lt;/title&gt;

    &lt;!-- Included CSS for non gmail clients --&gt;
    &lt;style type=&quot;text/css&quot;&gt;

        /* Level Two: reset mobile gmail first gutters */
        .col-first-td {
        padding-left:  4px !important;
        padding-right: 2px !important;
        }

        .col-last-td {
        padding-left:  2px !important;
        padding-right: 4px !important;
        }

        /* Level Three: use mobile gutter */
        @media screen and (max-width: 599px) {
        .col {
            width: 100% !important;
            max-width: 100% !important;
        }

        .col td {
            padding-left:  2px !important;
            padding-right: 2px !important;
        }
        }
    &lt;/style&gt;
    &lt;/head&gt;
    &lt;body bgcolor=&quot;#ffffff&quot; leftmargin=&quot;0&quot; topmargin=&quot;0&quot; 
    marginwidth=&quot;0&quot; marginheight=&quot;0&quot;&gt;

    &lt;!-- Level One CSS (inlined): the mobile gmail 
    first (but still works in Outlook) markup --&gt;
    &lt;table width=&quot;600&quot; border=&quot;0&quot; cellpadding=&quot;0&quot; c
    ellspacing=&quot;0&quot; align=&quot;center&quot; id=&quot;container&quot;&gt;
        &lt;tr&gt;
        &lt;td&gt;

            &lt;!--[if mso]&gt;&lt;table width=&quot;100%&quot; border=&quot;0&quot; cellpadding=&quot;0&quot; 
            cellspacing=&quot;0&quot;&gt;&lt;tr&gt;&lt;td valign=&quot;top&quot; width=&quot;300&quot;&gt;&lt;![endif]--&gt;

            &lt;table width=&quot;100%&quot; border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; 
            align=&quot;left&quot; class=&quot;col&quot; style=&quot;width:100%;max-width:300px;&quot;&gt;
            &lt;tr&gt;
                &lt;td class=&quot;col-first-td&quot; style=&quot;padding-left:4px;
                padding-right:2px&quot;&gt;
                Column 1
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;/table&gt;

            &lt;!--[if mso]&gt;&lt;/td&gt;&lt;td valign=&quot;top&quot; width=&quot;300&quot;&gt;&lt;![endif]--&gt;

            &lt;table width=&quot;100%&quot; border=&quot;0&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; 
            align=&quot;left&quot; class=&quot;col&quot; style=&quot;width:100%;max-width:300px;&quot;&gt;
            &lt;tr&gt;
                &lt;td class=&quot;col-last-td&quot; style=&quot;padding-left:2px;
                padding-right:4px&quot;&gt;
                Column 2
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;/table&gt;

            &lt;!--[if mso]&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;![endif]--&gt;

        &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/table&gt;&lt;!--/#container--&gt;

    &lt;/body&gt;
    &lt;/html&gt;
</code></pre>
<p>It's important to note that you can:</p>
<ul>
<li>Set the layout <code>width</code> to any desired <code>width</code>, you are not limited to the long-standing tradition of <code>600px</code></li>
<li>The tool was created with concerns for email clients on mobile devices and as it was created before <a href="https://blog.edmdesigner.com/coding-responsive-html-emails-after-the-gmail-update/">the big Gmail update last year</a>, it has special focus on Gmail.</li>
</ul>
<p>For easier understanding about how the layout work, we added the following code to the beginning of the embedded styles:</p>
<pre><code>    * { 
        border: 3px dashed black;
        padding: 10px;
    }
</code></pre>
<p>It highlights each element, so it's visible how the layout is structured.</p>
<p><a href="https://litmus.com/checklist/emails/public/90e7905">Litmus test results for the layout code</a><br>
<a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-05/step-03/index.html">You can check out the full source code of this step on Github</a></p>
<p>Despite all of the very positive aspects, we still have the same wishes about the generator as before: the ability to customize the generation for specific client list, the ability to work offline and with that: to be able to add it to an existing workflow or modify to our own use cases (or possible email client improvements).</p>
<h2 id="summary">Summary</h2>
<p>Throughout the article, we introduced 4 code generation tools and showed you why you may want to use them.</p>
<p>We reviewed some useful characteristics of the bulletproof background and button tools of Campaign Monitor.</p>
<p>We saw how they support <strong>desktop Outlook</strong> email clients <strong>with VML</strong> and that they have <strong>regular HTML</strong> for high client support <strong>in other email clients</strong>. We also gathered the customization options and saw their effect in the applied properties.</p>
<p>Next, we saw two layout generator. With the first, our aim was to show you <strong>an example on</strong> how to start <strong>developing a code generation tool</strong> and give you a <strong>reusable code base</strong> that you can modify. The second was a simple tool, which <strong>helped to create layouts</strong> that considers mobile email clients and provided helpful comments on the key aspects of the code.</p>
<p>These tools have <strong>high reliability</strong> as they are created with <strong>well-defined and tested conditions</strong>, based on real life experience with the various email clients. The bulletproof code snippets are usually <strong>customized with parameters</strong> and thus offer the advantage of speeding up the development process as well.</p>
<p>We hope you enjoyed the topic and that you'll join us next time. We also welcome questions and ideas you may have and inspirational thoughts for others.</p>
<p>In the next article,we're going to continue with code modifier tools developed in-house at EDMdesigner. Get the next post in your inbox by signing up.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div></div>]]></content:encoded></item><item><title><![CDATA[Advanced Drop Calc Experiments]]></title><description><![CDATA[Drop Calc is a great way to create responsive emails, but also a general fallback technique for those numeric props which can be expressed with attributes.]]></description><link>https://blog.edmdesigner.com/advanced-drop-calc-experiments/</link><guid isPermaLink="false">5afad21c3bed88001585fb9e</guid><category><![CDATA[Drop Calc]]></category><category><![CDATA[Litmus Live London]]></category><dc:creator><![CDATA[Gyula Németh]]></dc:creator><pubDate>Wed, 06 Sep 2017 11:38:16 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/09/litmuslivelondon-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/09/litmuslivelondon-1.png" alt="Advanced Drop Calc Experiments"><p>As you might have heard, <a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">Drop Calc</a> is a new layout method for creating responsive emails. I invented it while I was working on one of the articles of the <a href="https://blog.edmdesigner.com/tag/modern-html-email-tutorial/">Modern HTML Email Tutorial</a>. I am really happy that the community finds it to be useful, and I feel honored that I had the chance to talk about it at <a href="https://litmus.com/conference/london">Litmus Live London</a> last week.</p>
<p>I am going to publish a short article in next two weeks, recapping my experiences from the conference. Also, I want to include the video of my presentation, so hopefully it will be published by then. If you are interested in hearing about my experiences at the greatest email related conference, please subscribe below.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="dropcalcasageneralfallbacktechnique">Drop Calc as a General Fallback Technique</h2>
<p>A few days before the conference, my presentation was finished already. I rehearsed it in front of my colleagues. They provided me incredible feedback. Thank you guys. I also presented it to <a href="https://litmus.com/blog/author/jaina">Jaina Mistry</a> from Litmus, and her ideas were also very valuable.</p>
<p>BUT the following happened...</p>
<p>On the way to the airport I was reading my emails. One of our customers asked if it's possible to create equal height columns. Our usual answer is NO with capital letters, because if you stack those columns on top of each other on mobile devices, there will be lot of empty space, so you will have to scroll a lot.</p>
<p>But wait... Why don't we apply Drop Calc to the height property? - I asked myself.</p>
<p>Doing that can allow you to have equal height columns on desktop, and those columns will collapse on mobile, meaning that you won't have those disturbing empty spaces.</p>
<p>On top of that I thought that I could apply it to other properties as well.</p>
<p>I made some experiments a few hours before my presentation, and it turns out that Drop Calc method can be used on any property which can be calculated and which has an attribute version. (So we can fall back to something.)</p>
<p>Because of this, I decided to change my well-rehearsed talk. I hope it was worth it.</p>
<h2 id="recapofthedropcalcmethod">Recap of the Drop Calc method</h2>
<p>Before talking about the new experiments, let's recap the most important parts of the <a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">Drop Calc method for creating responsive layouts or HTML emails</a>.</p>
<p>There are two very, very important observations:</p>
<ol>
<li>The first is that the CSS <code>calc</code> function is <em><strong>not</strong></em> supported in every email client.</li>
<li>The second is that there is a specific order of importance when it comes to width of tables: <em><strong>attribute &lt; class &lt; inline style &lt; !important in class</strong></em></li>
</ol>
<p>Let's say that we use !important only in media queries.</p>
<p>Now, if you put <code>calc</code> in inline style, the following things can happen:</p>
<ul>
<li>if the email client supports the <code>calc</code> function
<ul>
<li>and if it's a desktop client, then the calc in the inline style will be applied (which is the desktop version)</li>
<li>and if it's a mobile email client, then the media query will be applied (which is the mobile version)</li>
</ul>
</li>
<li>if the email client does not support the <code>calc</code> function
<ul>
<li>and does not support the style tag (thus classes), then the value of the width attribute will be applied (which is the mobile version)</li>
<li>and it supports the style tag (thus classes), then the width in the class will be applied (which is the desktop version)</li>
</ul>
</li>
</ul>
<p>We are very lucky, because the desktop email clients which don't support the calc function support the style tag. The mobile email clients which don't support the calc function don't support the style tag either (so the attribute will be applied).</p>
<p>This way we can create robust responsive layouts which will be correctly rendered on almost every email client. If you want to check out a thorough example, please read my <a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">previous article</a>.</p>
<p>Besides that, I suggest you to read my article about <a href="https://blog.edmdesigner.com/html-email-width-overcoming-the-600px-limitation/">how to create wider than 600px email layouts</a>, which also builds on the order of importance I mentioned earlier.</p>
<h2 id="experimentingwithheightdropcalc">Experimenting With Height &amp; Drop Calc</h2>
<p>As I wrote previously, one of our clients wanted to have equal height columns on desktop and those columns had to collapse on mobile, so no unnecessary empty space would be shown when the columns are stacked on top of each other.</p>
<p>So let's apply the same principles to the height property of a table. It means that you have to add for example, <code>calc(400px)</code> in inline style and provide fallbacks in class for old desktop clients and in the height attribute for old mobile clients.</p>
<p>For mobile clients, the fallback is actually nothing. You don't need to put anything in the attribute, because we want to get back the default behaviour when we are on old mobile clients. It means that the default height (auto) will be applied.</p>
<p>For old desktop clients, you need to define the height in class without the calc function.</p>
<p>I created this example a few hours before my presentation at Litmus Live London (2017):</p>
<div data-preview="https://edmdesigner.github.io/modern-html-email-tutorial/LitmusLiveLondon/height-experiment.html"></div>
<p>As you can see, there are three very famous people in this email from Litmus. But what's more important is that on desktop, our columns have the same 400px height.</p>
<p>Since it's an advanced topic I will let you, dear reader, discover the details of this experiment on <a href="https://github.com/EDMdesigner/modern-html-email-tutorial/blob/master/LitmusLiveLondon/height-experiment.html">GitHub</a>.</p>
<p>If you are not that familiar with the Drop Calc method, you definitely should read the <a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">original article</a> first.</p>
<p><a href="https://litmus.com/builder/19c7d1e">Check out the Litmus previews.</a></p>
<h2 id="experimentingwithfontsizedropcalc">Experimenting With Font Size &amp; Drop Calc</h2>
<p>After finishing the experiment with the height, I thought that we could use it for other numeric properties. I created another experiment with font size.</p>
<p>Luckily we have the good old <code>&lt;font&gt;</code> tag which has the <code>size</code> attribute. It means that there is an attribute to fallback to. We can use the <code>font-size</code> CSS property in inline style with the <code>calc</code> function, and we can use the same property without the calc function in class.</p>
<p>This way we have two different things to fallback to, which is the basis of the Drop Calc method.</p>
<p>I created the following experiment which you can check out on <a href="https://github.com/EDMdesigner/modern-html-email-tutorial/blob/master/LitmusLiveLondon/font-size-experiment.html">GitHub</a>:</p>
<div data-preview="https://edmdesigner.github.io/modern-html-email-tutorial/LitmusLiveLondon/font-size-experiment.html"></div>
<p>As you can see, the main goal is to increase the font size on mobile devices (also on old Androids). It definitely works, but there is one issue: you can't set the line-height with attributes! If anyone knows how to solve that problem, pleas let me know in the comments section below.</p>
<p>If you are okay with the fact that you won't be able to set the line-height on old Androids, then it's worth it to try the Drop Calc method with the font size property.</p>
<p><a href="https://litmus.com/builder/bdb18ff">Check out the Litmus previews.</a></p>
<h2 id="furtheropportunities">Further Opportunities</h2>
<p>As you can see from the previous examples, Drop Calc is a general fallback technique. If you apply it to the width property, you can <a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">create robust responsive layouts for HTML Emails</a>.</p>
<p>You can apply it to any numeric property which has an attribute version to fallback to. In this article you have read about two applications: height and font-size. Besides these you can think about any numeric property, for example the border width.</p>
<p>If you don't have an attribute to fall back to, that is not necessarily a problem. As you have seen in the height experiment, sometimes the attribute fallback can be omitted.</p>
<p>I was also thinking about using inherited values instead of attributes. This would mean that you could define some properties on a parent element, and you could override it with inline style (and calc) in a child element... This way you might be able to define fallbacks, but it's only an idea. I'm very curious if someone can come up with something like this.</p>
<p>My last thought is that you can play around with other CSS functions which are not supported everywhere. I'm not that familiar with CSS functions, but it would be awesome to create a fallback technique similar to Drop Calc, but with non-numerical values. (What about rgb, rgba or <em><strong>attr</strong></em>?)</p>
<script src="https://plugins.edmdesigner.com/EDMdesignerPlugins.js"></script>
<script src="https://edmdesigner.github.io/modern-html-email-tutorial/scripts/preivew.js"></script>
</div>]]></content:encoded></item><item><title><![CDATA[Code Quality Tools and Email Client Specific Targeting]]></title><description><![CDATA[Do you know good email development tools? Complete your toolset with free services and client specific targeting.]]></description><link>https://blog.edmdesigner.com/code-quality-tools-and-email-client-specific-targeting/</link><guid isPermaLink="false">5afad21c3bed88001585fb9b</guid><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[code quality]]></category><category><![CDATA[targeting]]></category><category><![CDATA[email clients]]></category><category><![CDATA[Browser Extensions]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 23 Aug 2017 13:27:56 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/08/code-quality-tools-and-email-client-specific-targeting.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/08/code-quality-tools-and-email-client-specific-targeting.png" alt="Code Quality Tools and Email Client Specific Targeting"><p>EDMdesigner blog has been offering in-depth tutorials on HTML email coding for the past few months. In this current article series, we have used and will continue to use frameworks and technologies exceeding the HTML &amp; CSS system of email coding. They are great ways to help productivity, but as a refresher we will take a step back into our comfort zone and look at online tools and less code heavy examples.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=4">
</script>
<p>In this post, we look at additional tools that help to secure the output. We'll <strong>see free online tools</strong> to validate the HTML code. Many visual testing services, including <a href="http://litmus.com/">Litmus</a> and <a href="https://www.emailonacid.com/">Email on Acid</a> provide these kind of tools, but if you don't use them or want to see a second opinion on a compound template, it makes sense to test with another service.</p>
<p><a href="https://blog.edmdesigner.com/visual-email-testing/">In the article before</a>, we discussed code inspection with the browser Developer Tools in webmails. It's also a good way to come up with <strong>client specific targeting</strong>. You see, a specific class or the way the client processes your code with its pre-processor can be the basis of custom designs.</p>
<p>In the third part, we'll see how Thunderbird can be a good companion in workflow and see <strong>extensions</strong> at your hands when you work in the browser.</p>
<p>There are some important topics however that we wont't discuss in this article. One is testing call-to-action buttons. It's hard to test them as you have to do it manually. We had a post on a <a href="https://blog.edmdesigner.com/bulletproof-html-email-buttons-a-new-line-height-based-approach/">new line-height based button</a> before and we had quite a few click tests with it so you know what to expect. There are <a href="https://litmus.com/blog/a-guide-to-bulletproof-buttons-in-email-design">standard button types</a>, where you can also rely on documented click tests.</p>
<p>We also leave off spam testing. There are easy-to-use initiatives to help you. We had an article last year <a href="http://blog.edmdesigner.com/collection-of-the-best-email-testing-tools-online/">gathering the full spectrum</a> of email quality testing. For the purposes of deliverability, like finding out your sender score, you can find great resources there. I also recommend checking things off <a href="https://www.campaignmonitor.com/blog/email-marketing/2017/02/email-campaign-preflight-checklist/">this list</a> before you send out a campaign.</p>
<p>In the next article, you can read about the special responsive layout technique of <a href="https://blog.edmdesigner.com/the-drop-calc-method-to-create-responsive-html-emails/">The Drop Calc Method</a> developed at EDMdesigner. You can gain insights of its development background and how it was received in Litmus Live Conference. Sign up, if you don't want to miss it!</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="codequalitycheckingtools">Code Quality Checking Tools</h2>
<p>We saw visual testing by the web browser and testing services <a href="https://blog.edmdesigner.com/visual-email-testing/">in the previous article</a>. We emphasized how important visual testing is, but it's no secret that there's so much more to email quality testing, which you should check before you hit send.</p>
<p>As mentioned in the introduction, first we cover email code quality. You need to make sure that the code has valid links, all the HTML tags are closed and that your code best fits to the standards. Many problems may be avoided by obeying this simple rule.</p>
<h3 id="codequalityincodeeditors">Code Quality in Code Editors</h3>
<p>During development, the standard help is syntax highlighting, but it misses many mistakes, so can't be relied on for the job.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/syntax-highlight-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>A more accurate option is to set up an HTML linter for your code editor. You can find an HTML linter for every popular code editor, like <a href="https://packagecontrol.io/packages/SublimeLinter-html-tidy">Sublime Text</a> or <a href="https://marketplace.visualstudio.com/items?itemName=mkaufman.HTMLHint">Visual Studio Code</a>. The purpose of linter packages is to help identify where and what the problem is. In the image below it's clear that something is wrong even by syntax highlighting, but the list generated by the linter-package makes it child's play to resolve:<br>
<img src="https://blog.edmdesigner.com/content/images/2017/08/html-lint-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<h3 id="onlinecodevalidators">Online Code Validators</h3>
<p>There are an ever-evolving number of tools to check if your code is confirm to the email best practices. They are easy to use, as the usual operation is just 3 steps:</p>
<ul>
<li>open the online service</li>
<li>copy &amp; paste the completed code to the validator's text area</li>
<li>run the validation process</li>
</ul>
<p>For checking HTML validity, the most common go-to is the <a href="https://validator.w3.org/nu/">W3C validator</a>. It's hard to follow every rule, but it can help to spot rookie mistakes. However you'll often find that legacy email development techniques are often filtered as well:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/w3c-validation.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>A more appropriate tool is <a href="https://blog.edmdesigner.com/code-quality-tools-and-email-client-specific-targeting/TODO">HTMLemailcheck</a> as it's designed specifically for email testing. The free plan covers HTML and CSS, but it has affordable price for additional tools like link checking and accessibility testing. You can validate and get actionable suggestions to fix the problems.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/html-email-check-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>Accessibility gains an evolving importance in web and email design and the available tools help you produce code that works in screen readers.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/accessible-email-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>Last but not least, you need to know about <a href="https://caniuse.email/">Can I Use in HTML Emails</a>, where you can quickly review support for CSS properties among the most definitive clients. As Outlook remains the most advanced client to support with respect to allowed properties, you may decide to run a quick test <a href="http://jonathanaquino.com/outlook-html-email-validator.php">with this tool</a> depending on your users' email client segmentation.</p>
<h2 id="targetinggmailandinboxemailclients">Targeting Gmail and Inbox Email Clients</h2>
<p>Most challenges in email development derive from knowing what to expect from particular clients. This enables us to tailor higher quality for state-of-the-art email clients. It's the basis of email client specific custom designs, like <a href="https://en.wikipedia.org/wiki/Progressive_enhancement">progressive enhancement</a>.</p>
<p>For the purposes of this article, we played around with this very cool <a href="http://freshinbox.com/blog/targeting-new-gmail-css/">Gmail/Inbox targeting technique</a>. We found it on <a href="http://freshinbox.com/blog/">FreshInbox Blog</a>.</p>
<p>The code looks as follows:</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;&lt;head&gt;
&lt;style&gt;
    u + .body section .gmail {
        display:block !important;
    }
    u + .body &gt; .inbox {
        display:block !important;
    }
&lt;/style&gt;
&lt;/head&gt;
&lt;body class=&quot;body&quot;&gt;
    &lt;section&gt;
        &lt;div class=&quot;gmail&quot; style=&quot;display:none;&quot;&gt;
            THIS IS GMAIL&lt;/div&gt;
        &lt;div class=&quot;inbox&quot; style=&quot;display:none;&quot;&gt;
            THIS IS INBOX&lt;/div&gt;
    &lt;/section&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>In the example we have inline styles hiding elements, and with a specialized CSS selector combination, we make them appear by <code>display: block !important;</code> property. For instance in Gmail, the <code>class=&quot;gmail&quot;</code> is applied from the embedded CSS, while the <code>class=&quot;inbox&quot;</code> is not.</p>
<p>The idea for this targeting is that in Inbox the <code>section</code> element gets removed, while GMAIL keeps it. It was our suspicion that the same rule applies to all HTML5 elements. It turned out mostly to be true (<code>&lt;details&gt;</code> or <code>&lt;summary&gt;</code> are invalid even in Gmail).</p>
<p>If you need to look up the CSS selectors, here are links for the <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Class_selectors">Class selector (&quot;.&quot;)</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_selectors">Adjacent sibling selector(&quot;&gt;&quot;)</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Child_selectors">Child combinator (&quot;+&quot;)</a>, and <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Descendant_selectors">Descendant combinator (&quot; &quot;)</a> used in the article.</p>
<p>Using Inbox, with the Developer Tools we can identify that HTML5 opening and closing tags are replaced with <code>&lt;u&gt;&lt;/u&gt;</code> HTML code. The nested content is raised to the same level as the <code>&lt;u&gt;</code> tags, thus making this specific targeting work.</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/inbox-inspection-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>However, it's clear from the above that based on this targeting we can achieve different client specific designs.</p>
<p>There's a very useful resource at this point, if you want to target email clients other than webmails (for these, you can always use the browser Developer Tools to inspect the HTML):  Rémi Permantier shared a link on <a href="https://litmus.com/blog/">Litmus Blog</a> about <a href="http://quickguid.es/messagesource/">a collection of methods</a> to retrieve email messages' source.</p>
<h2 id="thethunderbirdworkflowforemailtesting">The Thunderbird Workflow for Email Testing</h2>
<p>We chose to demonstrate Thunderbird because it has some really cool features. You could use it as a code editor or an email sending service, which makes it an invaluable addition to our current testing tools.</p>
<p><a href="https://www.mozilla.org/en-US/thunderbird/">Mozilla Thunderbird</a> is a free, open source, cross-platform email, news, RSS, and chat client. (<a href="https://en.wikipedia.org/wiki/Mozilla_Thunderbird">source</a> Wikipedia). It was developed by Mozilla Foundation and though there's a <a href="https://marksurman.commons.ca/2016/04/25/firefox-and-thunderbird-a-fork-in-the-road/">fork in the road</a> of Thunderbird and Firefox development, and <a href="https://blog.mozilla.org/thunderbird/2017/05/thunderbirds-future-home/">Thunderbird is migrating off Mozilla Corporation infrastructure</a>,  the effect is apparent in the software everywhere.</p>
<p>From the point of email development, we deal with Thunderbird because of its capabilities to:</p>
<ul>
<li>show email source for inspection even though it's a desktop client</li>
</ul>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/thunderbird-inspect-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<ul>
<li>
<p>have the unique <code>moz-text-html</code> class, which provides client specific targeting option (see it also in the above image)</p>
</li>
<li>
<p>let you insert HTML code and use it as sending service for HTML emails</p>
</li>
</ul>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/insert-html-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<ul>
<li>extend HTML editing capabilites with <a href="https://addons.mozilla.org/en-US/thunderbird/addon/thunderhtmledit/">ThunderHTMLedit</a></li>
</ul>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/thunder-html-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>A possible workflow might look something like this:</p>
<ul>
<li>You extract some raw code from your favorite code editor</li>
<li>Paste the HTML into the new message and send yourself a test</li>
<li>View the test to get a feel for the design and inspect with the smart wire-frames</li>
<li>Modify the code if necessary with the aid of ThunderHTMLEdit</li>
<li>Send another test, and repeat from the top if you need to</li>
</ul>
<p>In this section you could see a complete testing workflow with Thunderbird and specific Thunderbird targeting with the <code>moz-text-html</code> property.</p>
<p>For a full collection on client specific targeting check out: <a href="http://tabletrtd.com/email-client-targeting/">tabletrtd.com's article</a>. It's worth it to bookmark that page if you haven't done it yet. You can find actual email development gems there.</p>
<h2 id="browserextensionsforgooglechrome">Browser Extensions for Google Chrome</h2>
<p>In the previous section you could examine how an extension can add useful functionality to Thunderbird. In this section we'll boost the performance of our web browser in the same manner. We limit our selection to Google Chrome extentions, as Firefox is in the middle of transitioning their add-ons philosophy to the <a href="https://developer.mozilla.org/en-US/Add-ons/WebExtensions/What_are_WebExtensions">WebExtension system</a>.</p>
<p>There are two extensions we would like to sell you on in particular, but feel free to leave recommendations about your favorite tools  in the comment section below.</p>
<p>The first one is the Web Developer. As the name suggests it has functionalities exceeding our needs, but after you have installed it, it's just a click away to check in a completed template:</p>
<ul>
<li>if you added alt text to all of the images:</li>
</ul>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/devtool-alt-text-2.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<ul>
<li>inspect how your CSS works throughout the template:</li>
</ul>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/devtool1.gif" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>and basically you can distinctly analyze any element or properties of your design. This flexibility to separate parts of your design can be really amazing. It's worth a try.</p>
<p>Our second recommendation is called <a href="https://chrome.google.com/webstore/detail/emmet-review/epejoicbhllgiimigokgjdoijnpaphdp?hl=en-US">Emmet Re:view</a>. It's developed by the <a href="https://emmet.io/">emmet.io</a> team and is used to assist Responsive Design.</p>
<p>You may wonder why is it better than <a href="https://developers.google.com/web/tools/chrome-devtools/device-mode/">the Device Mode</a> in Chrome:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/devtool.gif" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>Why we consider it a good addition to your toolset is its capability to show the design by the multiple breakpoints defined in the email's code:</p>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/breakpoint-inspector-1.png" alt="Code Quality Tools and Email Client Specific Targeting"></p>
<p>You can also filter views based on device types, like 'tablets' or 'mobiles'.</p>
<p>In addition to introducing two extensions, it is worth mentioning that there are extensions for <a href="https://chrome.google.com/webstore/detail/email-on-acid/ohebieihangjpppjenegaecogcbaeeic">Email on Acid</a> and <a href="https://chrome.google.com/webstore/detail/litmus/makmhllelncgkglnpaipelogkekggpio">Litmus</a>. If you use these testing services, you can send code for full visual testing very easily. It can definitely help you speed up the testing process.</p>
<h2 id="summary">Summary</h2>
<p>In this article we went over three topics:</p>
<ul>
<li>code quality with online tools</li>
<li>client specific targeting</li>
<li>browser extensions</li>
</ul>
<p>You could learn about a handful of ways to check your code, like installing <strong>HTML linter package</strong> to your code editor or using the <strong>validator services</strong> of W3C, HTMLEmailCheck and Accessible-email.org.</p>
<p>We hope you feel inspired and intrigued to start thinking on <strong>custom designs for Gmail, Inbox and Thunderbird</strong> for your next campaign.</p>
<p>Next time you need to inspect the web version of your template, you have the <strong>Web Developer</strong> and <strong>Emmet Re:view</strong> extensions to help you with your worries.</p>
<p>If you enjoyed the article join us next time as well. You'll hear about the Litmus Conference and EDMdesigner's part in it from Gyula Németh, CTO @ EDMdesigner. See you then!</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
</div>]]></content:encoded></item><item><title><![CDATA[Visual Email Testing with Developer Tools, Litmus and Email on Acid]]></title><description><![CDATA[Have you ever struggled with email testing before? The browser developer tools, Litmus and Email on Acid can help you. See how to use them together.]]></description><link>https://blog.edmdesigner.com/visual-email-testing/</link><guid isPermaLink="false">5afad21c3bed88001585fb98</guid><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[email testing]]></category><category><![CDATA[code quality]]></category><category><![CDATA[developer tools]]></category><category><![CDATA[Litmus]]></category><category><![CDATA[Email on Acid]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 09 Aug 2017 13:18:17 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/08/visual-email-testing-1.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/08/visual-email-testing-1.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"><p>In the previous articles of the <a href="http://blog.edmdesigner.com/tag/html-email-development-tools/">HTML Email Develoment Tools series</a> we gave some pieces of advice and showed some tricks for development productivity, like <a href="http://blog.edmdesigner.com/how-to-use-sublime-text-for-html-email-development/">Sublime features</a> and <a href="http://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts">layout-generator scripts</a>. By having read those posts, you can write code more efficiently.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=3">
</script>
<p>Now it's time to see the tools that can define if the output is quality or rubbish. We consider the topic really important for email coders.</p>
<p>In this article, we are going to discuss visual testing, and we'll use the built-in tools of the browser first. The browsers' Developer Tools will enable quick iteration over design. It'll help us identify common mistakes that most email clients won't tolerate. Following that we'll walk through an example of some support problems that can only be identified via email testing services or email tests on physical devices.</p>
<p>Some of the tools throughout the post may be old friends from your professional experience or our previous tutorial series on HTML email coding. <a href="http://blog.edmdesigner.com/modern-html-email-tutorial/">In the Modern HTML Email Tutorial Series</a>, we revisited HTML email development principles based on the new era of modern emails as per the <a href="http://blog.edmdesigner.com/coding-responsive-html-emails-after-the-gmail-update/">Gmail update</a>.</p>
<p>In each topic, we had theories about how client-support may have changed in the past. We kept on continuously justifying these theories with visual email tests. With these tools, we could tell how code changes affected the rendered views in numerous email clients at the same time.</p>
<p>However, that was the time when we realized how time consuming it is to run tests through these services. We also noticed that we can save time if we do the initial testing of our concepts by the aid of web-browsers.</p>
<p>This article started off as a comprehensive introduction about testing tools for email coders. But soon enough we found out that there was so much to mention, that we decided to only discuss the built-in browser Developer Tools and visual testing in this post. We'll show other tools and extensions in the next article.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="introductiontoemailrenderingandthedom">Introduction to Email Rendering and the DOM</h2>
<p>Varied rendering is a worn out topic in email development. Every email client has its own implementation of supported HTML and CSS; to be a successful email developer you have to know about all of them. For this reason, we're looking under the hood inside our web browser to see the possible causes why our templates might break.</p>
<p>Next time you encounter odd behavior from some properties, you'll be able to identify the problem by yourself. In this section, we're going to discuss the theory first, then cover the topic through an example and sample images.</p>
<h3 id="fromhtmlcsscodetorenderedview">From HTML &amp; CSS Code to Rendered View</h3>
<p>Let's go over the process an email goes through until the recipient receives it. We cover this section based on our readings from <a href="https://litmus.com/blog/why-email-designs-break-rendering-guide-infographic?utm_campaign=industry&amp;utm_source=litmusblog&amp;utm_medium=blogs-break-rendering-guide-infographic">Litmus' article</a>.</p>
<p>Every fancy email starts with an HTML document, which has CSS inlined, like this:</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
&lt;meta charset=&quot;UTF-8&quot;&gt;
&lt;title&gt;Document&lt;/title&gt;
&lt;style&gt;	

	&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;

	&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;min-width: 100%; background-color: yellow; border: 1px solid #000;&quot;&gt;TABLE,
		&lt;tr&gt;TR element
			&lt;td style=&quot;background-color: orange;&quot;&gt;
        TD element
			&lt;/td&gt;
		&lt;/tr&gt;
&lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;

</code></pre>
<p>Pretty straightforward, right? (Although if you think about it, we'll see some email-client differences already, as some clients support external stylesheets... But let's just forget about that and use email best practices!) The document is sent to mailboxes by some sort of server. As we talk about emails, it is the mail server. Usually, there's no change in the HTML at this step, a lot of additional data for the mail client.</p>
<p>Here is an example excerpt from Gmail about the previous HTML code:</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/mailserver.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>Inside the recipient's email client there's a pre-processor which interprets the document. It eliminates all elements that are unknown or dangerous, like scripts from the attributes. If clients don't do this, the users are exposed to the security vulnerability of cross-site scripting <a href="https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet">XSS</a>. Cross-site scripting enables attackers to inject client-side scripts into the emails. Source: <a href="https://en.wikipedia.org/wiki/Cross-site_scripting">Wikipedia</a></p>
<p>At this point, custom classes and additional markup may also be added. At this point, huge implementation differences arise. You can access this data directly in every webmail client, using the Developer Tools:</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/inspected-in-gmail.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>In the subsequent article, continuing the topic of email quality inspection, we'll show you how to exploit this behavior.</p>
<p>Following these steps, the rendering engine receives the modified HTML and parses it to create the Document Object Model (DOM). The DOM is an object, representing the HTML document and the applied CSS properties. This representation is visible in the browser or in the mail clients. The email clients often use the operating system's browser engine to show the DOM.</p>
<p>The main reason behind the DOM is that HTML elements and attributes can be accessed by scripting languages, like JavaScript. As it provides an interface for programmatic use it's called the DOM API. However, scripts are removed in the vast majority of email clients, so we don't need to worry about this at all.</p>
<h3 id="thedevelopertoolsasatestingsolution">The Developer Tools as a Testing Solution</h3>
<p>As mentioned before, email clients often use web browsers present on your operating system to render views. Webmails use the browser in which you open them. Desktop email clients can default to specific browsers installed on your system. One example is Internet Explorer based Outlooks, they will use Internet Explorer or Edge on Windows-running machines.</p>
<p><strong>By the above mentioned details, we have 3 + 1 reasons to test first in the browser:</strong></p>
<ul>
<li>Quick iteration over your design</li>
</ul>
<p><em>Support to write properties on the fly</em><br>
 </p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/onthefly.gif" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p><em>Easy way to debug with tools like the option to turn properties on/off</em><br>
 </p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/togglefeatures.gif" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p><em>Almost immediate feedback about the payload and download speed</em><br>
 </p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/download-post.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"><br>
 </p>
<ul>
<li>Webmail view is usually very similar to browser view with the same browser<br>
 </li>
</ul>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/chrome-yahoo.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"><br>
 </p>
<ul>
<li>Specific desktop client's views can be anticipated from the browser view</li>
</ul>
<style>

.client-summary {
	border: 1px solid black;
	border-collapse: collapse;
	margin-top: 10px;
	margin-bottom: 10px;
}

.client-summary th {
	border: 1px solid black;
	text-align: center;

	background-color: #E5E5EB;

	height: 15px;
	padding: 5px;
}

.client-summary td {
	border: 1px solid gray;
	text-align: center;
	vertical-align:middle;

	background-color: #f4f4f4;

	padding: 2px;
}

.client-summary td {
	padding-top: 10px;
	padding-bottom: 10px;
}

.client-summary td p {
	list-style-type: none;
	text-align: center;
	margin: 0;
	padding: 0;
}

.client-summary .winner {
	margin-bottom: 25px;
}

</style>
<table class="client-summary" width="100%" cellspacing="0" cellpadding="0">
	<tr>
		<th>Internet Explorer 8 Emulated in Edge</th>
		<th>Outlook 2002</th>
	</tr>
	<tr>
		<td>
			<img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/ie8emulated.png" width="100%" height="auto" style="max-width: 1366px; height:auto;" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid">
		</td>
		<td>
			<img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/litmuso2002.png" width="100%" height="auto" style="max-width: 1366px; height:auto;" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid">
		</td>
	</tr>
</table>
&nbsp;
<ul>
<li>(Mobile views can be emulated in major browsers)<br>
 </li>
</ul>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/emulated-view.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>There's a plus one among the bullet-points because you always need to test emulated views as they are not 100% reliable.</p>
<p>There are a few conclusions to keep in mind here:</p>
<ul>
<li>We suggest browser testing only as a preliminary step to help you decide on the main design principles. It's always advised to confirm with visual testing services and physical devices.</li>
<li>Just as in web-development, you need to consider other browsers. It's best if your workflow supports the most frequently used browsers (like Chrome, Firefox, Edge, Safari). See our recommendation for multi-browser testing through an example in the next section.</li>
</ul>
<h2 id="browsertestingexample">Browser Testing Example</h2>
<p>Working with the browser can give an almost instant feedback on the design and we've seen quite a handful other reasons to do it. In this section, we'll see that we can also use it to catch rendering differences across browsers before we would use a testing service. First we'll work on our testing workflow, then we'll inspect what we've built through an example highlighting a rendering difference between Chrome and Firefox.</p>
<h3 id="gettingstartedtestingenvironmentsetup">Getting Started - Testing Environment Setup</h3>
<p>To be able to run consistent, well-orchestrated tests in multiple browsers, these are the tools you'll need:</p>
<ul>
<li>A text-editor, possibly with <a href="http://blog.edmdesigner.com/how-to-use-sublime-text-for-html-email-development/#installingplugins">LiveReload enabled</a></li>
<li>Major browsers installed</li>
<li>A server for serving your HTML documents. You can <a href="https://edmdesigner.github.io/html-email-development-tools/lesson-03/template-server.zip">download one here</a> running on Node.js</li>
<li>Virtual Machine with running operating systems for the browsers not supported on your system</li>
</ul>
<p>In your workflow, you'll open up a text editor, fire up a boilerplate template, or <a href="http://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts/#examplescriptforlayoutgeneration">generate some initial HTML&amp;CSS combo</a> first.</p>
<p>Then, you'll have at least the major browsers installed and open. If you still miss out on any, here are the download links for the recommended ones:</p>
<ul>
<li><a href="https://www.microsoft.com/en-us/windows/microsoft-edge">IE</a> / <a href="https://www.google.com/chrome/browser/desktop/index.html">Chrome</a> / <a href="https://www.mozilla.org/en-US/firefox/">Firefox</a> / <a href="https://support.apple.com/downloads/safari">Safari</a></li>
</ul>
<p>Now, there's a problem. Safari is not supported on Windows, while you can't install IE on Linux (there may be other restrictions you encounter; if so, please share it in the comment section). You can eliminate these kind of problems, if you install Windows for IE and Mac for Safari on virtual machines.</p>
<p>For this purpose we use Virtual Box, which you can <a href="https://www.virtualbox.org/wiki/Downloads">download here</a>.</p>
<p>Testing in 4 browsers may seem overwhelming and you may decide to skip this part. It's actually okay, if you only test in two of the most important ones for your email client list, when you'll do visual tests by testing services later. Nonetheless if you follow our recommendation here, it becomes really easy to test in multiple browsers.</p>
<p>Next, we'll <a href="https://edmdesigner.github.io/html-email-development-tools/lesson-03/template-server.zip">download</a> and extract the server and start it with Node.js, running <code>node server.js</code>.</p>
<p>This gives us the benefit of accessible working files in all web browsers. Even in the guest virtual machine you can open the exact same files. You need to type <code>ipconfig on Windows / ifconfig on Mac</code> on your host, so you'll be able to find the IP address of your host machine:</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/ifconfig.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>If your servers are running, you can access the served files from the browser. Just type the following pattern in the URL address bar: <code>localhost:&lt;portnumber&gt;</code> on the host machine, or <code>&lt;ip-address-of-host&gt;:&lt;portnumber&gt;/&lt;rest-of-address&gt;</code> on your guest virtual machine.</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/all-in-all.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>If you've also set up LiveReload, all the updates will show in every web browser on your host machine.</p>
<h3 id="inspectingthedomthroughthedevelopertools">Inspecting the DOM Through the Developer Tools</h3>
<p>With our environment ready, we can start actually developing and testing email HTML. In this example there is a very basic layout setup, which serves as a good basis to start inspecting elements.</p>
<p>The idea is that supported email HTML is developing among the various email clients, so maybe we could use <code>DIV</code> elements in our design. We're going to have a wrapper table, conform to email best practices, and have two <code>DIV</code>s inside, nested into each other. Filling it with nice, well-coded content, it could be developed into a beautiful marketing email - that's our goal.</p>
<p>The complete HTML of the document:</p>
<pre><code>	&lt;!DOCTYPE html&gt;
	&lt;html lang=&quot;en&quot;&gt;
	&lt;head&gt;
		&lt;meta charset=&quot;UTF-8&quot;&gt;
		&lt;title&gt;Document&lt;/title&gt;
		&lt;style&gt;	

			table {
			  background-color: yellow;
			  border: 1px solid #000;
			}

			table td {
		  	  background-color: orange;
			}

			table tr {
		  	  background-color: red;
			}

			table .outer {
			  min-height: 400px;
		  	  background-color: green;
			}

			table .inner {
			  height: 300px;
			  margin-bottom: 300px;
			  background-color: blue;
			}
		}

		&lt;/style&gt;
	&lt;/head&gt;
	&lt;body&gt;

		&lt;table width=&quot;100%&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; style=&quot;min-width:100%;&quot;&gt;TABLE,
			&lt;tr&gt;TR element
				&lt;td&gt;TD element
					&lt;div class=&quot;outer&quot;&gt;Outer DIV
						&lt;div class=&quot;inner&quot;&gt;Inner DIV&lt;/div&gt;
					&lt;/div&gt;
				&lt;/td&gt;
			&lt;/tr&gt;
		&lt;/table&gt;

	&lt;script&gt;document.write('&lt;script src=&quot;http://localhost:35729/livereload.js&quot;&gt;&lt;/' + 'script&gt;')&lt;/script&gt;

	&lt;/body&gt;
	&lt;/html&gt;
</code></pre>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-03/step-00/index.html">You can check out the full source code on Github as well.</a></p>
<p>As you can see in the CSS, we set the <code>inner DIV</code> to <code>300px</code> with <code>300px</code> bottom margin. The other dimension we apply is a <code>min-height</code> for the <code>outer DIV</code>. We'll expect the child <code>DIV</code> to stretch the parent <code>DIV</code> and all the <code>table</code>'s elements surrounding. As we color each element, a nice layout should show.</p>
<p>These are the results (left - Chorme / right - Firefox):</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/firefox-chrome-diff.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>Now the output is quite unexpected. They are radically different in Chrome and Firefox. If we would use testing services, the only thing we could do at this step is to modify the code. The visual feedback may help us to understand the initial cause of the problem.</p>
<p>When we use multiple browsers we can use the DOM inspector in each browser, turning features on and off and looking at how the CSS properties are calculated. In each browser, the Developer Tools are accessible by pressing: <code>F12</code> / <code>CMD + SHIFT + I</code>.</p>
<p>Let's take a look at Chrome's DOM inspector:</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/inspector-chrome.gif" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>And analyze the same in Firefox:</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/inspector-firefox.gif" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>We can conclude what we've seen with the two ways of inspections:</p>
<ul>
<li>If you examine carefully, both browsers know that the inner <code>DIV</code> is<br>
<code>600px</code> high, considering <code>height:300px</code> and <code>margin-bottom:300px</code></li>
<li>Firefox applies <code>min-width:400px</code> as an absolute value, and cuts off the inner <code>DIV</code> there, hiding the <code>margin-bottom</code> property</li>
<li>Chrome recognizes the <code>min-width</code>, but also nows that the inner <code>DIV</code> has a margin, so it counts it as if it were outside of the outer <code>DIV</code></li>
<li>Firefox counts the <code>TD</code> element to <code>400px</code> (+ font size), Chrome counts the same <code>TD</code> to <code>700px</code></li>
</ul>
<p>These differences are present as the two browsers both struggle with deciding the correct height for the elements. We can fix the templates by even adding a <code>zero</code> dimensioned element, which forces the browsers to calculate each element's height.</p>
<p>The fix looks as follows:</p>
<pre><code>...
   &lt;style&gt;
	.clr {
		clear:both;
		height:0;
		overflow:hidden;
	}
   &lt;/style&gt;
...
   &lt;body&gt;
...
        &lt;div&gt;
           &lt;div class=&quot;outer&quot;&gt;Outer DIV
	       &lt;div class=&quot;inner&quot;&gt;Inner DIV&lt;/div&gt;
	       &lt;div class=&quot;clr&quot;&gt;&lt;/div&gt;
	   &lt;/div&gt;
...
</code></pre>
<p><img src="https://blog.edmdesigner.com/content/images/2017/08/firefox-chorme-after.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-03/step-01/index.html">You can check out the full source code here.</a></p>
<h2 id="emailqualitytestingwithvisualtestsuites">Email Quality Testing with Visual Test Suites</h2>
<p>We fixed the templates so it looked the same in Chrome and Firefox. We are now confident that webmail clients will render great. To confirm that this is the case or not, we'll use visual test suites, Litmus and Email on Acid. They are the most comprehensive and respected choices available on the market.</p>
<h3 id="runningtests">Running Tests</h3>
<p>Both services provide a great number of features to help developing bulletproof emails. By far the most important service is the visual tests, where you can see live previews of your HTML code in several email clients.</p>
<p>You can also start development from scratch or paste your HTML code to their editors. We have our HTML ready so we can paste it as follows:</p>
<p>Paste in Litmus:</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/add-template-litmus.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>Paste in Email on Acid:</p>
<p><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/add-template-eoa.png" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>In each service you'll find an editor - specifically prepared to handle email HTML - and a preview pane. In the preview pane you have a browser view by default, which you can toggle to show numerous email client's previews:</p>
<p>In Litmus:<br>
<img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/toggleviewlitmus.gif" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>and also in Email on Acid:<br>
<img src="https://edmdesigner.github.io/html-email-development-tools/lesson-03/images/togglevieweoa.gif" alt="Visual Email Testing with Developer Tools, Litmus and Email on Acid"></p>
<p>The live previews guarantee the option to test in most of the significant environment setups of browsers, email clients and operating systems. It's also possible in both services to share the outcomes with a sharing link. We can now compare and contrast the results of the two testing service.</p>
<p><a href="https://litmus.com/checklist/emails/public/be0768c">You can check Litmus previews before here</a>.<br>
<a href="https://litmus.com/checklist/emails/public/1447efc">You can check Litmus previews after here</a>.<br>
<a href="https://www.emailonacid.com/app/acidtest/display/summary/luJ0GcNqMPJ8JpqMIFfArpi3B8DZ9n6H78cEj2gua8KC8/shared">You can check Email on Acid previews before here</a>.<br>
<a href="https://www.emailonacid.com/app/acidtest/display/summary/xVs0AzlTDIThl2xn7FWtWEk1G7HJaFR1D6lSXjlu9o9sd/shared">You can check Email on Acid  previews after here</a></p>
<p>Confirming our results in Litmus and Email on Acid we can see that browser testing was actually a good way to catch design problems, though we have a lot of differences remaining. If you wish to solve those too, <a href="http://blog.edmdesigner.com/html-email-padding-margin-border/">our previous article may be useful</a>.</p>
<h3 id="comparisonoflitmusandemailonacid">Comparison of Litmus and Email on Acid</h3>
<p>As you can see, both services are fundamental tools to make your design bulletproof. The only other option is to test on physical devices, which is costly and far more time-consuming. However there are other good features these platforms provide to help speeding up development process and improving code quality. Definitely our list won't be exhaustive, but let's see the most eye-catching items.</p>
<p>Both services have a number of pre-written templates, which you can modify to your needs. They have preview panes showing a browser view, which is quite similar to the browser testing we were doing before. You can switch it to examine mobile browser view or multi-client previews with a single click.</p>
<p>There's an option in both to follow up on your development history based on the code as well as the project preview. They have additional services like Spam Testing and email Analytics, but let's see more benefits that are related to code quality.</p>
<p>Litmus offers:</p>
<ul>
<li>Grid view for easy understanding of your markup structure for the browser preview</li>
<li>A service available from the Checklist that enables you to verify your subject-line in many clients with live previews</li>
<li>Multiple email templates in a project and you can run tests for them separately.</li>
</ul>
<p>Email on Acid offers:</p>
<ul>
<li>A built-in inliner tool shipped - your embedded CSS become inline styles by a click</li>
<li>An very easy to understand code quality checker warning about problems with your code and also an Optimizer tool, which will correct them instantly</li>
<li>The ability convert your special characters to HTML code in an instant.</li>
</ul>
<p>And last but not least, two very intriguing features: Litmus has <a href="https://litmus.com/blog/streamline-your-workflow-sync-your-emails-directly-from-litmus-to-your-esp">Sync to ESP</a>, Email on Acid has <a href="https://www.emailonacid.com/blog/article/industry-news/the_pulse_mozify_stirs_up_controversy">Mozify</a>.</p>
<h2 id="summary">Summary</h2>
<p>In this article we learned about the browser's Developer Tools and email testing services.</p>
<p>In the first part of the tutorial, we summed up the steps which an email goes through:</p>
<ul>
<li>HTML document is created with inlined CSS</li>
<li>Mail server sends the information usually untouched</li>
<li>Pre-processor modifies the document, strips away dangerous content</li>
<li>Rendering engine creates the Document Object Model (DOM) for representation</li>
</ul>
<p>Next, we inspected the DOM in Chrome and Firefox through a simple example, which was rendered very differently in the two browsers.</p>
<p>In the second part of the post, we discussed the two best email testing services, Litmus and Email on Acid. We analyzed the email previews and made some comparisons on their available features.</p>
<p>We hope that you found this article interesting. We're going to continue in the next one with some tricks and extensions in the browser and see some online services that will improve code quality. Join us next time as well!</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
</div>]]></content:encoded></item><item><title><![CDATA[How to Use JavaScript for Creating HTML Email Layouts]]></title><description><![CDATA[Does it take you 1+ hour to code an HTML email template? Maybe it's time to reconsider your workflow. Learn how to create email layouts with scripts.]]></description><link>https://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts/</link><guid isPermaLink="false">5afad21c3bed88001585fb99</guid><category><![CDATA[HTML Email Development Tools]]></category><category><![CDATA[scripting]]></category><category><![CDATA[Javascript]]></category><category><![CDATA[Node.js]]></category><category><![CDATA[NPM]]></category><category><![CDATA[generated HTML]]></category><dc:creator><![CDATA[Mihály Sáróy]]></dc:creator><pubDate>Wed, 26 Jul 2017 11:03:18 GMT</pubDate><media:content url="https://blog.edmdesigner.com/content/images/2017/07/how-to-use-javascript-for-creating-html-email-layouts-2.png" medium="image"/><content:encoded><![CDATA[<div class="kg-card-markdown"><img src="https://blog.edmdesigner.com/content/images/2017/07/how-to-use-javascript-for-creating-html-email-layouts-2.png" alt="How to Use JavaScript for Creating HTML Email Layouts"><p>Email HTML has always lacked the presence of scripts. No interaction, no DOM manipulation, no fun. Of course, this is a bold statement to make, but if you know some JavaScript, you may have had the feeling that you spent so many days, nights and hours of your spare time to learn it, and what for? You have to forget about it when it comes to HTML email. But that's not necessarily true. Today we are going to get relief and use JavaScript for creating HTML emails.</p>
<p>This article is a chapter of the HTML Email Development Tools series. The aim of the series is to improve our email development workflow. We have so many thoughts on the possibilities. We're searching for the best ways all the time. <a href="http://blog.edmdesigner.com/how-to-use-sublime-text-for-html-email-development/">In our first post</a>, we showed code editor features with Sublime Text, for example saving snippets. You can check out below what we wish to cover in the upcoming articles.</p>
<script src="https://edmdesigner.github.io/html-email-development-tools/scripts/chapters.js?p=2">
</script>
<p>In this post, we'll use some JavaScript for generating HTML Email templates. Don't worry if you aren't an expert; we'll progress in a step-by-step manner. In the first part, we gather the basics of scripting and show you why we chose JavaScript for our example. Next, we'll put together the pieces and code an example, which generates a table-based email layout from configuration lists. In the end, we will learn how to run the script in the command line to create the layout and push it into an HTML file.</p>
<p>The groundwork we lay down in this blog post will be used in future posts. We'll use scripting in the post about task-automation and probably in many more. If you don't want to miss them, please subscribe.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div>
<h2 id="gettingreadyforwritingexecutablescripts">Getting Ready for Writing Executable Scripts</h2>
<p>In this chapter, we go over all the theoretical knowledge that is crucial to get started. The topics we cover are: scripting in general, Javascript, Node.js, and last but not least the command line. Using these tools we can write really complex programs, but also simple scripts to support email development. In order to make the fundamentals easier to digest, we provide links at the end of each section enabling quick navigation back and forth between theory and practice.</p>
<h3 id="scriptingingeneral">Scripting in General</h3>
<p>A script is a series of instructions for a computer program to follow. It's created with the purpose of executing of a custom behavior. A language is considered a scripting language if it can be interpreted by a program without <a href="https://en.wikipedia.org/wiki/Compiler">compiling it</a> previously, or — in the case of JavaScript in the browser — it is compiled on the fly (JIT compilation).</p>
<p>There are <a href="https://en.wikipedia.org/wiki/List_of_programming_languages_by_type#Scripting_languages">various languages available</a> for the task. Standard examples exist for specific environments. <a href="https://en.wikipedia.org/wiki/Scripting_language">According to Wikipedia</a>, Bash is the default for Unix-like operating systems; ECMAScript (JavaScript), for web browsers; and Visual Basic for Applications (VBA) is for Microsoft Office applications, while Python is a commonly used, general-purpose language.</p>
<p>The three main reasons you would write a script are:</p>
<ul>
<li>A single task is repeated several times (eg. compressing a file for size optimization)</li>
<li>Time-consuming operations for humans (eg. reading through a huge document to find words matching a text pattern)</li>
<li>You wish to define a general term for a set of instructions. You reference the term once, and all the instructions are implemented by that (eg. a &quot;create project&quot; term can be responsible for creating and naming a new project folder, creating and opening some default project files populated with pre-defined entries, etc.)</li>
</ul>
<p>If you encounter all of the above, you would use a library to manage the complex, end-to-end processes. It's called task automation and we're going to have an entire article about that later.</p>
<p>For now, let's just see valuable, introductory use cases. Generating components and custom layouts for the email templates are good examples from email development. When you build dozens of similar templates, you probably need a nice little script to help you out.<br>
<a href="#writingthescriptitself">Jump to the article's script example, if you can't wait to see it in action.</a></p>
<p>In the next section, we're going to continue the preparations by diving into the JavaScript universe and learning about Node.js and NPM.</p>
<h3 id="javascriptnodejs">Javascript &amp; Node.js</h3>
<p>There are various languages to help you interact with your computer and give it your list of instructions. Nonetheless, your choice should be based on performance, good support and widespread use in the developer community. Because of these points, we selected JavaScript. In the following paragraphs, we try to exhaust some of the important benefits.</p>
<p>Javascript is referred as the language of the web. The reason is that it is interpreted by every browser. Because developers use it so often, the language evolved into a general purpose language over time. It's considered the most popular programming language by StackOverflow's <a href="https://insights.stackoverflow.com/survey/2016#technology">Developer Survey</a> and <a href="https://octoverse.github.com/">Github's review</a>.</p>
<p>JavaScript set its foot on the server-side with <a href="https://blog.edmdesigner.com/how-to-use-javascript-for-creating-html-email-layouts/(https://nodejs.org/)">Node.js</a>, but you can use it on your computer as well. Great applications were written in it: code editors like Brackets or Atom and <a href="https://node-os.com/">operating systems</a> using Node.js. If you haven't come across with it yet, Node.js is an open-source JavaScript run-time environment for executing JavaScript code. The engine behind Node is the same &quot;V8 JavaScript engine&quot; that powers Chrome browsers (and many more).</p>
<p>The Node.js runtime is shipped with the <a href="https://www.npmjs.com/">Node Package Manager (NPM)</a>, which constitutes the world largest software registry. The NPM is an amazing tool to include open source libraries into your code, or if you developed something new with high community value, you can make it public for others. Also, it's a great way to share the common libraries, developed within the company.</p>
<p>Before starting to code, you need to <a href="https://nodejs.org/">install Node</a>. On their main page, they detect your operating system and serve the corresponding download bundles.</p>
<p><a href="#runningthetablegeneratorscript">Go to the example run in Node to get a feeling on where this article is heading.</a></p>
<h3 id="thecommandline">The Command Line</h3>
<p>The last concept we need to grasp — before we could start scripting for HTML email layouts — is the use of the command line.</p>
<p>The command line is an interface for the computer, like the Graphical User Interface, but it is fully text based. It's a program that takes in text commands and passes them on to the computer's operating system to run. You can run programs, write scripts to automate common tasks, and combine simple commands to handle truly difficult tasks.</p>
<p>On UNIX-based operating systems like Mac OS X or Linux, they often refer to it as the terminal or console (for clarification on the proper terminology check <a href="https://superuser.com/questions/144666/what-is-the-difference-between-shell-console-and-terminal">this superuser discussion</a>). On Windows-based systems it's called the Command Prompt.</p>
<p>In our example, we'll use the terminal to install NPM packages and run the scripts written in JavaScript by Node.js. If you need some refresher on how to find the command line, check out the links fitting your operating system:</p>
<ul>
<li>on <a href="https://www.lifewire.com/how-to-open-command-prompt-2618089">Windows</a> / <a href="https://www.lifewire.com/ways-to-open-a-terminal-console-window-using-ubuntu-4075024">Linux</a> / <a href="http://www.wikihow.com/Open-a-Terminal-Window-in-Mac">Mac</a></li>
</ul>
<p>And below are links on how to use it:</p>
<ul>
<li>on <a href="https://www.lifewire.com/command-prompt-tricks-and-hacks-2618104">Windows</a> / <a href="https://www.techspot.com/guides/835-linux-command-line-basics/">Linux</a> / <a href="http://www.macworld.co.uk/feature/mac-software/how-use-terminal-on-mac-3608274/">Mac</a></li>
</ul>
<p>Since <a href="https://msdn.microsoft.com/en-us/commandline/wsl/about">Windows has support for Bash</a> - the standard shell program for UNIX-based systems, we'll focus solely on the UNIX-based command line. You can <a href="https://www.howtogeek.com/249966/how-to-install-and-use-the-linux-bash-shell-on-windows-10/">set it up easily</a> for Windows too.</p>
<p><a href="#npminitintheterminal">Jump to the command line heavy part of the example project.</a></p>
<h2 id="examplescriptforlayoutgeneration">Example Script for Layout Generation</h2>
<p>In the previous section, we gathered everything necessary for a complex, holistic example. We are going to use the Node Package Manager (NPM) to manage the essential <strong>external libraries called the project's dependencies</strong>. We'll see how to include them in the script file we write. Then we're going to run the script from the command line. You are really excited now, aren't you? Let's start then!</p>
<h3 id="npminitintheterminal">NPM Init in The Terminal</h3>
<p>First, open up the terminal. We begin by creating a new folder for our project with <code>mkdir &lt;projectname&gt;/</code> command and start the development by initializing the Node Package Manager (NPM). For this, we run <code>npm init</code>. The command creates a <code>package.json</code> file and prompts us with a few questions regarding the project.</p>
<p><a href="https://docs.npmjs.com/cli/init"><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-02/images/npm-init.gif" alt="How to Use JavaScript for Creating HTML Email Layouts"></a></p>
<p>After each entry, you need to press <code>enter</code>. The answers are recorded to the <code>package.json</code> file. We left most of them empty, so after completion, it looks like this:</p>
<pre><code>   {
     &quot;name&quot;: &quot;table-generator&quot;,
     &quot;version&quot;: &quot;1.0.0&quot;,
     &quot;description&quot;: &quot;&quot;,
     &quot;main&quot;: &quot;index.js&quot;,
     &quot;scripts&quot;: {
       &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
     },
     &quot;author&quot;: &quot;EDMdesigner.com&quot;,
     &quot;license&quot;: &quot;ISC&quot;
   }
</code></pre>
<p>This being taken care of, we install the project dependencies. We need the <a href="https://www.npmjs.com/package/cheerio">cheerio package</a> and <a href="https://www.npmjs.com/package/pretty">pretty</a> for this project as the only dependencies. Cheerio parses markup (like HTML) and provides an interface for navigating/manipulating the resulting data structure. This way it helps us selecting and nesting the HTML elements in the example. We install it by running the following: <code>npm install cheerio --save</code>.</p>
<p><a href="https://docs.npmjs.com/getting-started/installing-npm-packages-locally"><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-02/images/cheerio.gif" alt="How to Use JavaScript for Creating HTML Email Layouts"></a></p>
<p>We use the same steps to install &quot;pretty&quot;, which will make the output HTML look a lot nicer.</p>
<p>By running the command, NPM will:</p>
<ul>
<li>Look up its online registry (so you need an Internet connection) and download the code of the specified library</li>
<li>Create a new folder called <code>node_modules</code> on the same level as the <code>package.json</code> file is, and copy the code into it</li>
<li>Add the package's name in the package.json file</li>
</ul>
<p>You can confirm it by opening the <code>package.json</code> file.</p>
<p>The last point in the list is useful because you can track the versions of the project's dependencies and also it makes your code easily usable for others, if you <a href="https://docs.npmjs.com/getting-started/publishing-npm-packages">choose to publish</a> your project.</p>
<p><a href="#thecommandline">If you need to look up the theory on the terminal from above follow this link.</a></p>
<h3 id="writingthescriptitself">Writing The Script Itself</h3>
<p>Let's discuss a bit, how the program will work. Our goal is to control the layout generation process with just a series of numbers. We'll tell the program to create a layout in the email body with two rows, one column in the first, two columns in the second. For this, we just need to type: <code>&lt;create the layout with these numbers:&gt; 1 2</code>, hit <code>ENTER</code> ... and bam, there it is. How cool is that?</p>
<p>We'll implement the logic in this section. If you wish to check out the layout-generator first, and come back here to the very cool part after, then <a href="https://edmdesigner.github.io/html-email-development-tools/lesson-02/tableGenerator.zip">download the project in .zip format here</a>, unzip the files, and <a href="#runningthetablegeneratorscript">hop on to the next section</a>.</p>
<p>In a Node.js application, one of the first things to do is to require the packages necessary in that particular file. It'll virtually include the code from the selected sub-folder of the <code>node_modules</code> folder, making the public functions of those packages available. <a href="https://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-nodejs-apps/">Logging events from the Node.js app</a> will surely help you encounter any problems while trying this out.</p>
<pre><code>        var cheerio = require(&quot;cheerio&quot;);
        var pretty = require(&quot;pretty&quot;);
		
</code></pre>
<p>Cheerio is a light-weight library inspired by jQuery core, so we initialize it similar to jQuery: on the <code>$</code> sign. We can use it for easy selection of DOM elements.</p>
<p>The most important task is to abstract the functionalities away into specific methods in the JavaScript file. For this matter, we define the <code>createLayout(){ // code };</code> and <code>createMultiColumn(columnCount) { //code };</code> methods. The <code>createLayout</code> function creates the wrapper table and handles the single row - single cell type insertions. The <code>createMultiColumn</code> function is used to create the layout for more than one column. It includes additional <code>table</code> elements with single rows and populates them with the adequate number of table cells. This solution is called the multi-column element.</p>
<p>In the file, Node will read the instructing command line arguments as the &quot;layout configuration list&quot;. We'll make it loop through the arguments, and based on their values, it'll either add a row with a single cell or create a multi-column layout.</p>
<p>The code for the createMultiColumn method looks as follows:</p>
<pre><code>	function createMultiColumn(columnCount) {

		var multiColTable = $(&quot;&lt;table&gt;&lt;/table&gt;&quot;);
		var tr = $(&quot;&lt;tr&gt;&lt;/tr&gt;&quot;);

		multiColTable.append(tr);
                
        // APPEND TABLE CELLS TO THE CURRENT ROW
        // CORRESPONDING TO THE COLUMN COUNT
		for (var cols = 0; cols &lt; columnCount; cols += 1) { 
			var td = $(&quot;&lt;td&gt;&lt;/td&gt;&quot;);
			tr.append(td);
		}
		
		return multiColTable;
	}

</code></pre>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-02/tableGenerator">You can check out the full source code on Github.</a></p>
<h3 id="runningthetablegeneratorscript">Running The Table-Generator Script</h3>
<p>Everything is ready now. If you followed along, the project should look something like this:</p>
<p><a href="https://github.com/EDMdesigner/html-email-development-tools/tree/master/lesson-02/tableGenerator"><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-02/images/folder-structure.png" alt="How to Use JavaScript for Creating HTML Email Layouts"></a></p>
<p>First things first, make sure that Node.js is installed. Run <code>node -v</code> in the terminal, and if you see a version number like this <code>v6.x.x</code> that means you are good to go.</p>
<p>You need to navigate to the working files, and run the following:</p>
<pre><code>     node tableGenerator.js 1 2 3
</code></pre>
<p>and you'll achieve this layout:</p>
<pre><code>	&lt;html&gt;
		&lt;head&gt;

			&lt;style&gt;&lt;/style&gt;

		&lt;/head&gt;
		&lt;body&gt;
			&lt;table&gt;
				&lt;tr&gt;
					&lt;td&gt;&lt;/td&gt;
				&lt;/tr&gt;
				&lt;tr&gt;
					&lt;td&gt;
						&lt;table&gt;
							&lt;tr&gt;
								&lt;td&gt;&lt;/td&gt;
								&lt;td&gt;&lt;/td&gt;
							&lt;/tr&gt;
						&lt;/table&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
				&lt;tr&gt;
					&lt;td&gt;
						&lt;table&gt;
							&lt;tr&gt;
								&lt;td&gt;&lt;/td&gt;
								&lt;td&gt;&lt;/td&gt;
								&lt;td&gt;&lt;/td&gt;
							&lt;/tr&gt;
						&lt;/table&gt;
					&lt;/td&gt;
				&lt;/tr&gt;
			&lt;/table&gt;
		&lt;/body&gt;
	&lt;/html&gt;

</code></pre>
<p>Sidenote: it's also possible to configure with the filepath, which file to run. This makes it so the current directory doesn't matter.</p>
<p>Now, we can generate any custom layout running the <code>tableGenerator.js</code> file with Node.js and using a series of numbers. We can take our example one step further by using powerful command line features:</p>
<pre><code>node tableGenerator.js 1 2 3 &gt; index.html
</code></pre>
<p>With the <code>&gt;</code> operand, we can direct the console output into an HTML file.</p>
<p><a href="https://nodejs.org/api/cli.html"><img src="https://edmdesigner.github.io/html-email-development-tools/lesson-02/images/terminal-build.gif" alt="How to Use JavaScript for Creating HTML Email Layouts"></a></p>
<p>Naturally, this example is quite simple; we just wanted to show the main concepts. A few more lines of code in the JavaScript file could include pre-written styles inside the HTML head or the addition of other components. The sky's the only limit.</p>
<p><a href="#thecommandline">If you need to look up the theory on running terminal commands follow this link.</a></p>
<h2 id="summary">Summary</h2>
<p>We started this post by <strong>arguing the role of scripting in HTML email development</strong>. We wanted you to believe that it is useful in the development workflow. We saw the <strong>three reasons</strong> behind writing scripts:</p>
<ul>
<li>Single task repeated multiple times,</li>
<li>Multiple tasks intended to execute on a single command</li>
<li>Time-consuming duties</li>
</ul>
<p>and identified layout coding as a time-consuming task that's easy to facilitate by scripting. We also discovered <strong>tools from the JavaScript universe</strong> and learned the underlying theory in the latter half of the first part.</p>
<p>On the basis of our freshly grounded knowledge in general purpose JavaScript (Node.js), we coded <strong>a script file</strong>. Using the file, we could generate an email layout by a command and a few numbers describing the layout structure. We used <strong>the command-line</strong> to run the program. <strong><a href="https://edmdesigner.github.io/html-email-development-tools/lesson-02/tableGenerator.zip">Here is a download link</a> for the project's <code>.zip</code>.</strong> Feel free to modify it and share it with others. In case you made something clever from it, you shouldn't forget to also share it with us.</p>
<p>We are very proud of you making it 'til the end. This was a little lengthy and advanced article if you haven't written any scripts before, but we deeply believe that this knowledge can build nice template layouts fast. We hope that you agree.</p>
<p>As always, we encourage you to <strong>opt-in</strong> for the upcoming articles and also <strong>share your thoughts and ideas</strong> below to make these posts even better.</p>
<div data-chamaileonplugin="blog-forms/subscribe-newsletter" data-page="subscribe-newsletter" data-location="inside-blog-post"></div></div>]]></content:encoded></item></channel></rss>