Progressive download mp4 with JW Player
Written Tuesday, July 26th, 2011 by Chris
The latest version of JW Player (Version 5.7) now allows us to stream H264 videos to iOS while still supporting the flash player for other platforms. YEAH! HTML5 isn’t quite ready for us to use and abandon the old ways, but we’re getting closer.
Anyhow, while deploying a progressive download video for a client I chose to use this latest version of JWPlayer. I ran into an issue where the source file was an mp4 and it was fully downloading before playing, rather than a progressive download (play as it’s downloading). I’ve run into this problem before and luckily it’s an easy fix.
It has to do with the moov atom on an mp4 being placed at the tail end of the video rather than the head of the video. So once you ffmpeg the video into your require h264 specs, you need to run qt-faststart on the video which will relocate the moov atom to the beginning of the video and your problem is fixed. Very simple syntax:
qt-faststart sourceVideo.mp4 finalVideo.mp4
for those who don’t have qt-faststart already installed on their CentOS computer:
shell> svn checkout svn://svn.ffmpeg.org/ffmpeg/trunk ffmpeg
shell> cd ffmpeg/
shell> ./configure
shell> make
shell> make tools/qt-faststart
shell> sudo cp tools/qt-faststart /usr/local/bin/qt-faststart
Thanx to turbolinux blog for the qt-faststart install instructions.
Editing your Hosts file in Windows
Written Thursday, June 2nd, 2011 by Jim
The Hosts file on your computer is responsible for mapping hostnames to IP addresses. There are various reasons why you may want to edit your hosts file that I won’t get into here, but here in the office our main reason is to bypass the Internet on our development server located in-house. This means that if the Internet is down, we can still access our development sites via our web browser and continue developing.
We also will have clients edit their hosts file so they can see new versions of their site before we make any DNS changes.
The hosts file in Windows is located at:
Windows\system32\drivers\etc\
Once you locate the hosts file, right-click on the file and open it in any text editor such as notepad. From here editing it is easy. At the bottom of the file we enter the IP address of our internet connection, followed by the domain we want to to bypass (make sure there is a space or tab between the IP address and the hostname). Repeat for any additional hostnames and we’re done. If you want to temporarily omit an entry without completely deleting it, just ad a # in front of the IP address. The system will simply ignore the entry. Now just save and exit your file and your done. An example entry:
192.168.01.26 www.bashbang.com
On a Windows 7 machine you may not be able to edit the hosts file directly, in which case just simply copy the file temporarily to a different location, edit it there, then copy/overwrite it back to the proper directory.
Transcode Video for Microsoft Movie Maker
Written Wednesday, June 1st, 2011 by Chris
I’m not a huge fan of MS Movie Maker, but it comes on newer versions of Windows and is easy to use, so who am I to judge.
Just had a small project that required some DVDs converted so they’d work in Movie Maker. It was a bit more challenging than I expected. I just assumed xVid, DivX, or H264 avi files would be imported into Movie Maker. Alas, this is not the case (at least from what I was able to find).
After several attempts at various video and audio codecs I finally got one to work. Here’s the process I used:
bash$> cat VTS_1_1.vod VTS_1_2.vob VTS_1_3.vob > myMovie.vob
bash$> ffmpeg -i myMovie.vob -qscale 7 -vcodec wmv2 -s 720x480 -aspect 4:3 -ab 256k -ar 48000 -vol 400 -async 48000 -ac 2 -acodec pcm_s16le -g 300 myMovie.wmv
** the asspect ratio, resolution and other settings were all defined to use the same specs as the original VOB file.
Diff over SSH
Written Monday, May 23rd, 2011 by Chris
Readers of this blog will know that I’m a big fan or rsync. We use it almost exclusively for doing our site deployments. Generally I do an rsync dry-run to ensure I’ve gotten the correct folders and have a reasonable idea that the files I’m about to launch live are really what should be going up.
Sometimes though I’ll see a file and I’m unsure as to why it’s going to be pushed up to the live server. I’m not always the one who’s edited the files so I’d like to see the differences between the live and the dev server. I know looking at the diff in CVS or SVN is one way, but mid deployment sometimes it’s just easier to see the differences between the two files.
So use this to see the differences between a local file and one on a remote server:
ssh user@123.123.123.123 "cat /var/www/html/remote_file_to_compare.php" | diff - "/var/www/html/local_file_to_compare"
** Use the proper IP address and file names of course.
You can add switches to the diff command but this gives you the basic syntax. The nice think about this solution is that it’s transferable to any command. I’m doing a diff here, but you can run any remote server command in this way. For example:
ssh user@123.123.123.123 "free -m"
ssh user@123.123.123.123 "df -h"
This simple trick will save you some time of logging into the server with a new session.
Flash and z-index issue
Written Thursday, May 19th, 2011 by Jim
I came across a scenario where I needed to add html content in a place that was currently taken up by Flash content. Now, I could’ve broken up the Flash content into multiple swfs, and placed them accordingly on my page so the Flash content and html content can harmoniously co-exist beside each other, but I found a simpler, alternative solution that produces way less code and doesn’t involve breaking up my Flash.
I first attempted to place my html div content on top of the Flash using position: absolute; in my CSS (and of course, position: relative; on the parent div). This worked flawlessly in FF3, FF4, Chrome 11, Opera 11, and IE9 but the Flash content appeared above my html content in Safari 5 and (of course) IE7 and IE8.
To solve this issue I attempted to layer my content using z-index in my CSS, hoping to force the html content to display on top of the Flash, but that didn’t work. It didn’t matter if the Flash was set to a z-index of 0 and the html content was set to 1000, the Flash didn’t want to budge. At this point it seemed a shame to have to do all this the long convoluted way just to support those 3 odd behaving browsers.
Upon a little research, almost everyone who has ran into this particular issue has claimed that Flash will always take priority over any content on your page, but upon stumbling on a page from slightlymore, it appears there is a solution.
Turns out that altering the window mode in your Flash with a paramater of ‘opaque’ allowed the html to sit on top of the Flash quite nicely. Simple.
So what was:
'wmode', 'window',
was changed to:
'wmode', 'opaque',
Doing this made the z-index values in my CSS completely irrelavant, so I removed them. Now all had to do was re-design my current swf so content didn’t reside underneath the html and I was done.
Thanks to Clinton from slightlymore for pointing this out.
Google Site Search over SSL
Written Tuesday, May 17th, 2011 by Chris
We recently had a client who wanted to enhance the search function on their website. Their current solution was just a keyword search through various fields in the database which is fine, but isn’t as robust a solution as they wish they could have. One of the key features they wanted was to have “recommendations” when someone made a spelling error. This is potentially quite complex to implement. Rather than building it we opted to use Google Site Search.
We implemented the free Google Site Search function and got it all up and working, then we launched it and upgraded to the premium ad free version for the live site. That all went smoothly until we hit what appeared to be a small problem.
The entire website in question is run over SSL. This means that in certain browsers (Internet Explorer in particular) a warning message pops up when mixed SSL/non-SSL content is displayed on a page. The Google content is non-ssl so we had a problem. Granted, it’s only a warning, but MS has done a good enough job of making the language scary enough that many users will opt not to display the unprotected content…resulting in a blank search results page in our case.
I did a lot of searching around and caused a few additional bald spots on my scalp looking for a fix to the issue. Something you’d expect to be a quick fix isn’t. On the Google Site Search customize section they even provide a HTTPS option for a user to choose. It pulls the required external javascript from HTTPS as it should. After looking at what that file actually does I saw that it generates an iframe that has a hard coded HTTP: within it. I simply downloaded that javascript file (https://www.google.com/afsonline/show_afs_search.js) put it on my site, modified the contents of the file where it shows HTTP: to HTTPS:, changed the call to use my own js file rather than the one from Google, and it’s done and works.
If you want to look at the code on show_afs_search.js you’ll need to read up on how to make the code readable. Start by reading this previous entry I wrote.
No credit to anyone this time…I figured it out all on my own.
In case you’re thinking it’s such an obscure problem no one else would ever have the same issue, read here.
Update: I was premature with posting this fix. Although it did work on the results page there seems to be issues when you choose a link from that results page. The href makes a call to javascript that isn’t wrapped within the SSL which then produces a warning. I gave up on it and just went to using CURL to grad the XML data, parsed, styled it then outputted it.
Artifact on Firefox 4 on a Mac
Written Tuesday, May 10th, 2011 by Chris

Recently we had a odd bug pop up on one of our projects. It only showed up on Firefox (3.6 & 4) on OS X. The issue was that on input fields (in our case a radio buttons and text entry fields) there was an odd graphical artifact that showed up far to the right of the entry field.

It took some digging and a lot of experimenting, but we finally tracked it down to a line of CSS:
overflow: auto;
When I changed that to overflow: hidden; the problem went away.
I didn’t bother to dig any deeper into the problem or try and figure out the cause of the problem yet…I will when things settle down.
Font Embedding using Font Squirrel’s @font-face Generator
Written Monday, May 2nd, 2011 by Jim

Font embedding is something I haven’t implemented into website development until recently. The main reasons for this was lack of browser support and the preparation and process that goes with making a font work within a website didn’t make it a worthwhile effort, especially when alternative methods of using graphics was satisfactory and gave a consistent cross-browser look.
Fortunately, the guys at Font Squirrel has made this process a bit easier by providing a service that gives us our desired fonts in all the necessary formats required by all the major browsers. With their @font-face Kit Generator, you upload your desired font (make sure it’s properly licensed), and it will spit out a downloadable package that contains your font in all the necessary formats needed plus the @font-face css code needed for implementation.
For example, uploading a font “MyFontFamily.otf” to the generator will result in in a downloadable package containing, “myfontfamily-webfont.eot” (needed for Internet Explorer 4+), “myfontfamily-webfont.svg” (required for iOS 4.2 and under), “myfontfamily-webfont.woff” (IE9+, FF3.6+, Chrome 5+) and “myfontfamily-webfont.ttf” (raw truetype file that works with FF3.5+, Safari 3.1+, Chrome 4.0.249.4+ and Opera 10+). You would then attach the @font-face CSS provided into your site’s CSS file:
@font-face {
font-family: 'MyFontFamily';
src: url('myfont-webfont.eot?#iefix') format('embedded-opentype'),
url('myfont-webfont.woff') format('woff'),
url('myfont-webfont.ttf') format('truetype'),
url('myfont-webfont.svg#svgFontName') format('svg');
}
Make sure your fonts are placed and being called from the proper location and declare “font-family: ‘MyFontFamily’;” in your CSS where you want your font to show up. That’s it!
Google AdSense Specs
Written Tuesday, April 26th, 2011 by Chris

Since I always forget and have to look it up each time I figured I’d post this info to my own blog:
– Headline: 25 characters max
– Line 1: 35 characters max
– Line 2: 35 characters max
– Display URL: 35 characters max
– Destination URL: 1024 characters max
AWS SES MTA
Written Thursday, April 7th, 2011 by Chris
The above subject line is what I searched for this afternoon. I took a moment to be amused as this search term brought up 2.2 million results. What does it even mean!?
AWS = Amazon Web Services (Amazon’s most excellent server hosting services)
SES = Simple Email Service (Amazon’s solution to bulk mailings)
MTA = Mail Transport Agent (sendmail, postfix, etc).
A bit of back story for you. I recently set up a group of servers for a client since their previous single dedicated server wasn’t cutting the mustard. We migrated them over to AWS with a load balancer, small farm of web servers (EC2), NFS server (EC2), a database (RDS), and a CDN for distributing some of their content (S3+CloudFront). It took a bit of doing and learning the “Amazon way” but it all worked out and is quite a nice setup. It allows for rapid scaling up to deal with bursts of traffic and scale down to save costs. I’ll write more about this setup in a future post. I want to talk about email problems today.

When we first set things up we discovered that getting mail sent out form an EC2 server is sort of like sending mail through snail mail…it doesn’t get to its destination. EC2 apparently is blacklisted on most all SPAM blacklists. I can see why with the ease of creating and destroying servers…those nasty spammers must have had a hay-day in the early days of AWS. We were left with the problem of not being able to send out our administrative emails like user account validation, lost password recovery, etc.
Our first solution was to use Google’s awesome corp email service. So I set up the domain with Google and we modified the servers sendmail to relay all our admin type emails through our Google account support account. This worked really well until this morning when I found out that Gmail has a limit of emails that are allowed to go out to different users….again, antispam percautions on their part. Here’s some references:
http://mail.google.com/support/bin/answer.py?answer=22839
http://mail.google.com/support/bin/answer.py?answer=81126
So much for that solution which I was thinking was a nice method. Back to the drawing board.
I ended up finding Amazon’s Simple Email Service (SES) which seemed to do exactly what I needed. I filled out the forms and got an approved account in less than a day. Thank goodness too because Google had cut us off and we were loosing registrations quickly.
Now the trick was to get SES working on the EC2 web servers. We initially set up Sendmail on the server to do our relay…but only because it was already installed on the server and we know how to set up the relay easily enough. So I went through the process of configing sendmail to use SES. The instructions are easy to follow and I did everything they said to do but kept running into problems when I went to actually send the emails. I was getting errors:
SYSERR(root): buildaddr: unknown mailer aws-email
and my emails weren’t getting delivered.
In my php code I know I was sending the emails using a validated account and was successfully able to run the ses-send-email.pl command from commandline without problems.
I gave up on sendmail and installed my trusty MTA postfix. Of course I had to set it up, but again it was an easy config.
It too had errors:
status=bounced (Command died with status 1: "/opt/aws/bin/ses-send-email.pl". Command output: Email address is not verified. )
and
relay=aws-email, delay=0.39, delays=0.01/0/0/0.38, dsn=5.3.0, status=bounced (Command died with status 1: "/opt/aws/bin/ses-send-email.pl". Command output: Missing final '@domain' )
At this point I’m pretty frustrated with the whole thing. After a break I came back it and eventually found this post:
http://benjisimon.blogspot.com/2011/02/gotcha-of-day-ec2-postfix-amazon-simple.html
Ben was right, the email was trying to send from the crazy EC2 hostname.
I did what he said and created a /etc/postfix/sender_canonical file with:
/(.*?)@(.*)/ $1@realdomain.com
And updated the main.cf file:
sender_canonical_maps = regexp:/etc/postfix/sender_canonical
It still didn’t work, BUT it was rewriting the domain portion correctly. I saw that it was apache that was trying to send out the mail so I just tweaked his reg exp to be this:
/(.*?)@(.*)/ validuser@realdomain.com
and there you have it…it worked! I know it’s not exactly right to hard code the valid user email into the postfix config so I’ll fix that up tomorrow, but for now I at least have a working config and can proceed with putting out some other fires.
Thanx Ben for the tip, it really helped me out.
Setting up a Primary URL
Written Tuesday, April 5th, 2011 by Chris
This post is more for my own reference as I always forget the syntax.
When you have several domains but want to have one of them set up as a primary I generally set up Apache like so:
<VirtualHost *:80>
ServerName domain.com
ServerAlias *.thedomain.com *.thedomain.ca *.domain.ca
DocumentRoot /var/www/domain/
</VirtualHost>
Then in the root folder set up a .htaccess with the following:
Options +FollowSymlinks
RewriteEngine on
RewriteCond %{HTTP_HOST} !^www\.domain\.com$
RewriteRule ^(.*) http://www.domain.com/$1 [L,R=301]
Error code: sec_error_unknown_issuer
Written Monday, February 14th, 2011 by Chris

Some time ago we purchased a SSL certificate from Comodo for a client to use on their site. When we first installed it everything worked smoothly.
Recently however, we noticed an issue where we were getting a SSL warning page with the error:
The certificate is not trusted because the issuer certificate is unknown.
Error code: sec_error_unknown_issuer
After lots of digging and reading I figured out that the “intermediate CA” had been changed. It was a simple matter of re-downloading the SSL from Comodo’s admin interface and installing the new client_domain.ca-bundle file.
It would have been nice if Comodo had emailed me to tell me the certificate had changed/updated.
For instructions on how to install a SSL (in case you’ve stumbled upon this link and are looking for that) use these instructions as a guide (no promises it’s up to date).
Stop The Meter On Your Internet Use
Written Saturday, February 5th, 2011 by Chris
Although the CRTC has been served noticed by the Gov’t to reconsider it’s stance on Metered billing for Internet usage, please watch these videos and consider signing the petition. The exorbitant charges for over-usage is INSANE! If the ISPs had just charged a reasonable price for over-usage instead of gouging their customers I doubt this would have become such a big deal.
PS: George, you’re THE MAN! Love your show…and yes, I watch it over the Internet.
This video gives a much better understanding of what’s going on:
Also, read over this article to get an idea of how crazy the over-usage prices really are:
For the naysayers out there, read this to put things into perspective.
We’re Geeks not Nerds. Get it right!
Written Monday, January 31st, 2011 by Jim
The terms “geek” and “nerd” have often been used inter-changeably, and I find, for one, being called a “nerd” is rather… insulting! I’m a geek! And even though I know the difference I just can’t explain it. Dictionary.com defines the two terms as such:
- geek Slang
-noun
a computer expert or enthusiast (a term of pride as self-reference, but often considered offensive when used by outsiders.)
- nerd Slang
-noun
an intelligent but single-minded person obsessed with a nonsocial hobby or pursuit: a computer nerd.
We know, that when trying to define slang, we get less then accurate results. In this day in age, geeks are not limited to the realm of computers (ie. movie geeks, gaming geeks), and nerds are not necessarily single-minded. Even using computers as an example of a “non-social” hobby is far from accurate (ie. facebook)
There is a viral image of a venn-diagram floating around the internet that sets these terms straight, defining the distinctions between nerds, geeks, dorks, and the like. Unfortunately, it is difficult to pin-point an original source of this brilliance as this image has been replicated and reproduced in blogs, articles, and forums all over the web.
Study, observe, and get it right!

HTML Email Horrors – Part 2: MS Outlook 2007/2010
Written Monday, January 24th, 2011 by Jim
Have I mentioned how much of a pain in the neck HTML emails are? Every email client will render an HTML email differently because each one has it’s own rules around how it deals with the markup. For example, Gmail doesn’t support styles in the <head> section and Hotmail ignores margins. Basically, designing for html emails means reverting back to the old ways like using tables and throwing out anything new we’ve learned like external stylesheets. For any developer, we all know how important web standards are among cross-browser compliance, however among the multitude of email clients out there, these standards are broken much more frequently. There has even been a movement called the Email Standards Project who are trying to strive for compliant code among all email clients. The worst of the worst among these clients however, bar none, is Outlook 2007. Even previous versions of Outlook rendered more correctly than Outlook 2007.

With the release of Outlook 2007, Microsoft switched from their Internet Explorer rendering engine to the (get ready for it) …Word rendering engine! It doesn’t make any sense to switch html rendering capabilities from a web-browser engine to a word-processor engine, but that is exactly what they have done. To make things even worse, Microsoft fails to see their mistake and continues to use the Word rendering engine in Outlook 2010. We know from statistics that Outlook 2007 has a market share of 9% and with the introduction of Outlook 2010, this number will continue to grow as users continue to upgrade and phase out their older (yet better) versions. This means that Outlook 2007/2010 and the headaches that come with it for developers, will be here to stay for at least the next 5 years. <facepalm>
We already had to step in a time-machine and go back in time to deal with these html emails but apparently we didn’t go back far enough!
Need some help? At least there is a community out there to help voice our opinions to Microsoft. On Microsoft’s own website there is a full-listing of supported and unsupported capabilities in Outlook 2007. If you’d like to know which CSS attributes are supported in specific email clients, the guys at CampaignMonitor provided us this handy CSS support guide.
Div Tag Disappears in TinyMCE
Written Thursday, January 13th, 2011 by Chris

We’ve worked with WordPress as a simple website platform for some time now. Often we’ve run into scenarios where we’ve customized a section of a page or post that required us to add a set of DIV tags. This is all well and good and works great if you’re only ever going to work in HTML mode. But if you swap between HTML and Design modes (as a client would do once they took ownership of the content updates) then the DIV tag get’s removed (disappears).

This is due to the WYSIWYG editor in WordPress called TinyMCE. Now I know there’s various plugins to help manage TinyMCE, but we just needed to simply prevent the DIV tags from being removed. Oh, and any fix we make we want it to not be overwritten when we do a WordPress Upgrade.
The fix
In wp-content/themes/your_custom_theme either edit or create a file called functions.php. Inside there add the following:
function change_mce_options( $init ) {
$init['extended_valid_elements'] = 'div[*]';
return $init;
}
add_filter('tiny_mce_before_init', 'change_mce_options');
Of course if you have other TinyMCE customizations you want to make you can add them into there as well. For example I also have these:
$init['theme_advanced_blockformats'] = 'p,address,pre,code,h1,h2,h3,h4,h5,h6';
$init['theme_advanced_disable'] = 'forecolor';
At this point I’d generally give credit to the person and or site to figure this out…but it was some time ago that I found this fix and I just don’t recall where I got this information from. So I apologize for not being able to cite my source.
Linux “timer” command
Written Monday, October 25th, 2010 by Chris
I was setting up a new server to be monitored this week and found a new Munin script that I’d not seen before. It is http_loadtime. It loads a page on the server (http://localhost/) and times the duration of the load to be complete. On the server I was setting up it all went fine and started to graph right away.

I figured this would be a nice thing to see on the other web servers I manage so I added this new script to those servers as well…but that’s when I started to run into issues. The script wouldn’t run due to a missing “timer” command. The script does a “which timer” to find the location of the timer command so that it can call it from the full path…a very sensible thing to do. The problem was that the “which timer” command didn’t return anything. A search of the server showed the command was no where to be found. There are other timer type libraries, but not the actual timer command.
The funny thing is when I executed the timer command from the command line outside the script it worked fine and exactly as expected. So where is the damn timer command then? How does it work?
After lots of searching which resulted in far too many results with people wanting to change the clock on their server and nothing to do with what I was looking for. I found an interesting note somewhere (can’t find the link again sorry) that mentioned the timer command may be build into the shell.
That was the info I needed. I knew about some commands being build into the shell, but never actually knew what they were. Apparently in the default install of CentOS 5 the bash shell has “timer” built in. Armed with that info it was a simple matter of doing a yum install timer and I was good to go. Script worked perfectly fine as is.
PS: This is an odd issue but for those looking for the answer it’s super hard to find in the search engines. So please link back to this post if you find it helped you. Hopefully we can get this posts ranking high enough that it’ll show higher on Google to help the next person.
SSL on Name Based Host
Written Wednesday, October 20th, 2010 by Chris
I was working on my dev server today and ran into an issue with a project I’ve recently taken over. The admin section of the site requires SSL so I had to set up a self signed certificate on my server. This is not my first time at doing SSL certs so I didn’t have an issue there. I did however run into a new Apache error:
[warn] _default_ VirtualHost overlap on port 443, the first has precedence
Google is my friend so I was able to find a fix. On the dev server I use name based virtual hosting allowing me have a single IP run many client dev sites. To fix the issue I just needed to add:
NameVirtualHost *:443
I put mine right under
NameVirtualHost *:80
note: Above the VirtualHosts config, outside the VirtualHost *:80 tags
I give credit to where credit is due. Thank you webchalk.
Munin Not Graphing
Written Sunday, October 17th, 2010 by Chris

Today I went to add a new server to my monitoring setup and experienced an odd issue. I of course first installed the munin-node to the host and updated the munin.conf file on the monitoring server. Since the munin script runs every 5 minutes it generally takes a while to see the results of the new host in the graphs. The host showed up in the list of monitored servers…just no list of services monitored.
After some time I still wasn’t seeing any results. It took me some time to figure this one one. I looked up all sorts of help on Google and monitored the various munin and linux log files…nothing which helped. I finally started to diagnose the issue by running the munin scripts manually.
It took forever but I finally figured out that the host name on the new server was the cause of the issue. Apparently the hostname of the server needs to match exactly (including case) what the hostname is in the munin.conf file. When I read this in the munin-node.conf file:
# Set this if the client doesn't report the correct hostname when
# telnetting to localhost, port 4949
#
#host_name lisse.hasselt.wieers.com
it occurred to me to telnet into the host to see if the hostname matched. I’d telneted in already to ensure there wasn’t a firewall issue, but I didn’t think about the host name.
So if your munin graphs don’t work be sure to either use the exact same hostname in the munin-conf file or set the host_name in the munin-node.conf file to match that which you used in the munin.conf on the monitoring server.
** normally at this point I give credit to the website that helped me figure this out, but this time I did it all on my own.
HTML Email Horrors – Part 1: Horizontal Image Gaps in Gmail
Written Tuesday, October 12th, 2010 by Jim

HTML emails are a pain in the neck to begin with. There are so many rules and conditions and every email client has it’s own nit-picks to making an html email render correctly. I can go on and on and probably dedicate an entire section on the nuances of email clients and their rendering abilities, but I’m going to just mention one of them right here. Particularly because it’s due to a change that happened recently.
It turns out, for some reason, Google changed the way they handle the rendering of images in an html email. As a result, horizontal gaps would appear above and below images where they really should be flush against each other. Depending on how you’ve made your image slices this could make your email look very broken.
The solution to this is to add a style=”display:block” within all the img tags. For example:
<img style="display:block" src="yourimage.jpg" alt="your image" />
That’s it. Well that solves the Gmail problem.
Full credit goes to these guys.

