Samsung Auto-fit
This week, I got bit pretty hard by a bug I somehow managed to completely avoid until now. This bug involves three ingredients: the Samsung Email app on Android, its Auto-fit feature, and an Outlook account. Here’s everything I learnt about this.
It all started on a friday afternoon as I received an email from a client I’ve been working with in the past few months. Apparently, the fluid/hybrid templates I’ve carefully hand coded were rendering as the desktop version in the Samsung Email app on Android. And of course, the main boss of the organization used a Samsung phone with the Samsung Email app. So I had to fix this.
My first problem was… The Samsung Email app can only be installed on a Samsung device. And I didn’t have any Samsung device at hand. And the Samsung app isn’t part of Email of Acid or Litmus either. So I did what any email developer should do in this situation: ask for help in the #emailgeeks Slack.
Thankfully, Mark Robbins came to the rescue and offered his help. He quickly pointed me at this issue he reported on my email-bugs repo on GitHub back in 2019. I glanced at the thread and the problem seemed related to a feature of the Samsung Email app called Auto-fit. The feature is supposed to shrink email content to fit the screen
. But for some emails already optimised for mobile, it turns out it would actually do the exact opposite. Mark confirmed this was the problem and that my email worked fine with Auto-fit disabled. But since the feature is enabled by default, I needed to find a fix.
Luckily for me, @gabo recently posted a solution on the Mosaico blog. The fix only requires to include the following style in your email.
@media screen and (max-width: 384px) {
.mail-message-content {
width: 414px !important;
}
}
Mark was able to test with this fix and confirmed it did the trick. Hurray! Job done! Congratulations! I sent the fixed version to my client and called it a day.
Except that…
A few moments later, I got a reply from my client saying this didn’t fix anything. But how could that be? It did work for Mark after all. Frustrated by the situation, I ordered a Galaxy A13 from Back Market so I could do all the tests I needed.
While I wait for my order to arrive, let’s talk about the Samsung Email app.
Samsung Email with an Outlook Account
Do you know the acronym GANGA? It stands for “Gmail App with a Non Gmail Account” and refers to using the Google app (on either iOS or Android) with anything else than a Gmail account (for example with an Outlook.com address). This acronym is popular among email developers because in GANGA, you don’t get the same level of CSS support than with a regular Gmail account. (See my Trying to make sense of Gmail CSS support post from 2019.)
Well, little did I know that there is also a… “SEAWOA”. Or “Samsung Email App With an Outlook Account”. (Okay, I just made that up. I hope it sticks.) If we use the Samsung Email app with a “Hotmail Outlook Account”, we don’t get the same CSS support as for other types of accounts.
And one of the main difference in SEAWOA is the lack of media query support. And guess who uses Outlook accounts for their entire company?
My client.
This now explains why the media query fix tried earlier didn’t work for my client (who uses an Outlook account) while it worked for Mark (who used a Gmail account).
Whatever fix I would find, it needed to work without media queries. To better understand what is going on, let’s dive deeper into the Samsung Email app.
Auto-fit
Any Android app is distributed via an .apk
file format, which is nothing more than a ZIP archive. Which is great, because it means we can snoop through the app to look for anything interesting. So I went to APKMirror, searched for Samsung Email and downloaded the latest version APK.
As this was mentioned in Mosaico’s post I mentioned earlier, I knew that this whole feature was manager in an AutoFit.js
file. Which again is great, because it means we can read the source code right away since JavaScript is not a pre-compiled language. So I read it.
And the least I can say is that it is quite… surprising. For example:
- Comments in the code reference specific emails, for example from Yahoo Finance or Youtube, and even mentions a specific Gmail account used internally by Samsung for their tests. I know not everyone reads JavaScript from unpackaged Android apps as a hobby, but this feels like this shouldn’t be there.
- There are a lots of typos or spelling mistakes in variable names and functions, like
MOBILEDEIVCE
,chagneSize
ororignalDiv
. (I poked fun at this one on Mastodon as “orignal” is french for “moose”.) - The code organization is clunky. For example, there is a
removeHeight100InNode
function called early on in the script that is supposedly there to replace anyheight:100%
byheight:auto
throughout the HTML. (Interestingly, this is ignored if an element has aposition:relative
. I’m not sure what’s the reason for any of this.) But that same function is also responsible to determine the original maximum width of the email template.
And I think this is the heart of our problem here. Here’s an excerpt of the code from that function.
var width = element.getAttribute("width");
if (width && width != "100%") {
width = getMarginSize(width);
if (width > originMaxWidth) {
originMaxWidth = width;
}
}
if (element.width && element.width != "100%") {
width = getMarginSize(element.width);
if (width > originMaxWidth) {
originMaxWidth = width;
}
}
if (element.style.width && element.style.width != "100%") {
width = getMarginSize(element.style.width);
if (width > originMaxWidth) {
originMaxWidth = width;
}
}
This code is run in a loop of every HTML elements in an email. And for every element, it tries to determine the width of that element based on these three things, in that order:
- The
width
attribute. - The computed
width
in JavaScript. - The
width
style property.
At each step, it tries to assign the width found to an originMaxWidth
variable (initially set to zero before the loop) only if the width found is bigger than the current originMaxWidth
value.
And that’s the problem, here. Because in HTML and CSS, it doesn’t matter if an element has a width
attribute if it also has a width
style set. The style value overtakes the attribute value. But with Samsung’s algorithm, the width
attribute is actually more important. For example, consider the following code:
<img src="hero.jpg" alt="" width="600" style="width:100%; max-width:600px;" />
This image, viewed in a 300px
container, would be 300px
wide. But with Samsung’s algorithm, this sets the originMaxWidth
variable to 600px
because of the width
attribute. And this triggers Samsung Email’s Auto-fit to display our email at a 600px
width, even though it was fluid and responsive in the first place.
The only solution to prevent this is to set the width
attribute to 100%
. Easy enough, right?
But setting the width
attribute in images to a value in pixels is actually a very good and important practice in HTML emails. The Outlooks on Windows (versions 2016 and below) only understand the width
attribute of an image. And if it is set to a percentage value, Outlook will understand this as “a percentage of the image’s physical width”, not a percentage of the image’s parent element as we would expect in CSS. So this means that if we have a 1200px
wide image called in Outlook 2016 with a width="100%"
attribute, this image will be 1200px
wide.
The fix
I received my Samsung device on tuesday and was able to confirm this behavior and make more tests. I then offered my client two possible solutions:
- We use the
width="100%"
attribute on every large image. But they must make sure the image is at the physical width it will be displayed at in The Outlooks. - We duplicate the code for every large image and have one version with a
width
attribute value in pixels just for The Outlooks, and another version with awidth="100%"
attribute for every other email client. Something like this:
<!--[if mso]>
<img src="hero.jpg" alt="" width="600" />
<![endif]-->
<!--[if !mso]><!-->
<img src="hero.jpg" alt="" width="100%" />
<!--<![endif]-->
They chose to go with the first solution. After some more tests and tweaks to make the template more mobile first friendly, we finally had our emails responsive in SEAWOA!