When Windows Phone Mail can’t display an image attachment

I came across a strange little problem reported in answers.microsoft.com with Windows Phone 8 Mail. It wasn’t downloading  jpg images.

The email app that comes with Windows Phone 8 does not display image attachments automatically. You need to tap on them and then they download and you can view them. That drives some people batty, but it saves on bandwidth and prevents web bugs from tracking you.

When you view an image in an email, you are providing a lot of information about yourself to the sender. First of all, you are telling the sender that your address is active.  Which can mean more spam.  For that reason Google is now sending all images coming in through GMail through a proxy server.

A user reported that he couldn’t download images from mail. When he tapped on them, just just displayed the “Downloading…” status message.  We traded a few messages and nothing sounded out of the ordinary. So I asked him to me an email with one of those images. And he did.  He sent a few images in an email.  To keep thing simple, I’ll just refer to a single image and call it “foo bar.jpg”. His image had a different file name, but this one matches the naming convention with out using his personal information.

I saw the same thing.  Tapped on the image and saw the “Downloading…” display without ever getting the image. So I started playing around his message.  I used a GMail account and I viewed the message from the GMail web app.  Sure enough, it displayed the image just fine.  That ruled out the image being corrupt.

I saved the image to my PC and looked it with a few apps.  Nothing out of the ordinary, just an image from a Kodak digital camera, according the EXIF data.

So I decided to poke around a bit. Using GMail, I sent the same picture to another gmail account that I have.  That worked just fine on my phone.  That was strange so I took another look at his email.  His email was sent from Windows Mail. So I sent the same picture to my gmail account from Windows Mail on Windows 8.1.

And I couldn’t open the picture from Windows Phone Mail.  I could create the problem on my end. That’s half the battle in fixing bugs, getting past “It works on my machine” stage.

Image from the Coding Horror

To completely rule his picture being part of the problem, I went into Paint.Net and created a small jpeg and saved it as “test.jpg”. I sent that picture from Windows Mail to the GMail account, and sure enough that worked just fine.

I thought I was going down the right path, but another data point was mocking me. Mocking me to my face. Time to dig in deeper.  I went into GMail and opened up the message that had “foo bar.jpg” in it and selected “Show original” to see the actual message being sent.  It looked pretty normal, until I got to the part with the image attachment.

Content-Type: image/jpeg; name="=?utf-8?Q?Foo_Bar.jpg?="
Content-Description: =?utf-8?Q?Foo_Bar.jpg?=
Content-Disposition: attachment; name="=?utf-8?Q?Foo_Bar.jpg?="
Content-Transfer-Encoding: base64

After that the data for the image itself was included.  The image data was fine, but the file name seemed a little odd. The =?utf-8?Q? bit just says that the file name is UTF-8 encoded. The name itself had replaced the space in “foo bar.jpg” with an underscore to make “foo_bar.jpg”.

When I sent the email from GMail, the content header block for the image looked like this

Content-Type: image/jpeg; name="Foo Bar.jpg"
Content-Disposition: attachment; filename="Foo Bar.jpg"
Content-Transfer-Encoding: base64

Gmail did not replace the ” ” with a “_”.  When you viewed the both emails on the phone, the file name was displayed with the space. I copied the image to foobar.jpg and sent it from Windows Mail, it worked perfectly.

As near as I can tell, the problem is with the Windows Phone Mail app, everything else seems to handle the images correctly. The question thread has been passed along to Microsoft to take a closer look at.

I’m not anticipating a quick fix from Microsoft.  But it’s easy to get around this.  Don’t send images with spaces in the file name from Windows Mail. Use a different email app or rename the file.

It’s 2013, stop trying to write to the Program Files folder already

Type To Learn

Type to Learn’s login screen

My daughter asked if I could install Type to Learn 4, an app that she uses at school.  It provides a fun way to learn typing skills. If a school buys the app, they can provide student accounts and the student can download and install the app at home.

She, of course, had not told me any of this.  I went to the web site for Type To Learn and saw that there were two versions.  A School Login Portal, and the home version.  So I clicked on the home version which took me to Amazon.

No middle ground

The first thing I saw was the 2.5 out 5 star rating.  That’s not a good sign.  It was an inverse bell curve, people either loved it or hated it.  When you see numbers like that, you read the 1 star reviews to see what went wrong.

I zeroed in on the comment posted here.  That user had determined that Type To Learn was trying to write data back to a data file located in it ‘s program folder (C:\program files (x86)\sunburst). That’s not a good thing.

 Unless you had admin rights, that’s going to fail.  Starting with Windows Vista, standard users can’t write to any folders in the Program Files or Program Files (x86) space.  Just not allowed.  You can write to those folders if you have admin rights.  

My kids don’t have admin rights on the home PC’s.  They don’t need them and keeps the PC running smoothly.  Under normal usage, only setup applications should be writing to Program Files.

There is also the multiple user situation. If you are writing to one location and you have multiple user accounts on the machine, the you need to make sure that your saved data is multiuser friendly.

As it turned out, we didn’t need to buy the app from Amazon, we could just download the app from the School Login Portal.  But we still would have the same problem the data being written back to Program Files (x86).

Where are you supposed to put your application data?  For desktop applications, you have two choices.  Shared data goes into a folder under %PROGRAMDATA%, which usually maps to a hidden root folder name ‘ProgramData“.

User specific data should go into  %APPDATA% or %LOCALAPPDATA%.  Under Windows 8.1, APPDATA maps to something like c:\users\username\appdata\roaming.  This is used for data shared across multiple machines. LOCALAPPDATA maps to c:\users\username\appdata\local and is where you would store user data for that machine.

So we have an app writing to the verboten Program Files folder.  We can’t change that behavior, but we can allow it to work for a non-admin user without disabling all of the security.  We just need to everyone full access to that folder.

I like to do stuff like that from the command line. When messing around with access rights, I want to be explicit with what I am setting.  That’s just the way I roll.  With that, our tool is the trusty Icacls command.

Icacls is used for setting user and group access to a folder.  It does more than that, but if you don’t have an IT background. the rest of what it does will make your eyes bleed.  I mean the /verify parameter is documented to “Finds all files with ACLs that are not canonical or have lengths inconsistent with ACE (access control entry) counts.”.  You don’t need to know what that means, trust me.

Here’s what you need to know:

Run cmd.exe as administrator.  With Windows 8/8.1, this is easy.  From the Metro screen (Yes, I know. I still call it Metro), just type “cmd” and right click on “Command Prompt” and select “Run as administrator.  It should look like this:

Run as adminitratpr

When that cmd window opens up, CD into “c:\program files (x86)“. That will save you from having to type “c:\program files (x86)” over and over again.

[Edit]
A cricket player from Eastern Europe sent in the following tip:

An even easier way to launch an admin cmd prompt is Win+X then A. It’s the newest keyboard shortcut forever burned into my memory.

Now run

icacls sunburst

Sunburst is the company that makes or sells Type To Learn, all of the files are in that folder.  You should see the following:

That tells us that the TrustedInstaller (i.e. setup programs) and admins have full rights to that folder, every one else has read access

Now run

icacls sunburst /grant Everyone:(OI)(CI)F

In human speak, that means give (/grant) everyone full access (F) to the sunburst folder and all of the files ((OI)) in that folder and all of the folders ((CI)) in the sunburst folder. Then run “icacls sunburst” again to verify that the change took effect.  It should look like this

You should see that everone has full rights to that folder. Now you can run Type To Learn as  standard user.

Cross-Platform Localization for Mobile Apps in CODE Magazine

The January/February 2014 issue of CODE Magazine is up on the CODE Magazine site.  This issue focuses on mobile development.  There are a couple of Xamarin flavored articles in this issue, including one that I wrote.  I did an article on cross platform localization for mobile apps and you can read it  here.  The source code is available here.

You’ll want to jump to that article to see how to handle multiple languages and locales with code shared across Windows Phone, iOS, and Android.   All in C#.

Moved this blog from Blogger to an Azure colored WordPress

You may have noticed that this blog looks a little different.  I just migrated my blog from Google’s Blogger platform to a self-hosted WordPress blog.  And it’s running in Microsoft’s Azure cloud.

Migrated nearly decade of posts, comments, permalinks, and hopefully most of the images.  After a few days of WordPress, I really wish I had done this years ago.  So much easier to maintain, from both the WordPress side and the Azure side of things.

I’m in the process of doing another post that explains how I did it.  Spoiler: it was a piece of cake.

A work around for the files in use bug with HeatDirectory in MSBuild

I have this multi-project solution in Visual Studio 2013 and one of the projects is a Windows Installer project.  It uses WiX (Windows Installer XML) 3.8 and when I rebuild the solution, the final result is a nice .MSI file that will install the executable bits from the other projects.

To get the files that need to be bundled with the installer, I copy the files that I need from the project bin folders to a folder in the WiX project named “files”.  This folder is not part of the project or the solution and is not in source control.  I started out with a prebuild event of the WIX project that did the following:

  1. Delete the files folder. I just assume that everything in the folder is obsolete
  2. Robocopy the deployable files from a WPF project to the files folder.
  3. Robocopy an ASP.Net MVC 4 project to the filles folder
  4. Run ctt.exe (Config Transformation Tool) to clean up the web.config file and set some default values.
  5. Run the WiX Harvest tool, heat.exe, to generate a .wxi include file of all of the files in the files folder.

Using robocopy makes it easy to just the files that you want and not include the files that are not needed for deployment.

With Windows Installer, every object that gets installed has to be defined in a WiX source file.  You get end up with stuff that looks like:

Which is hideous to do by hand.  You can run heat.exe on a folder and it will generate that the include file for all the files in that folder for you.  In my prebuild event, I had the following lines:

The 5th line is the heat command line. The various command line options are documented here. This ran without any problems on my dev machine. Hilarity ensued when I tried to make a build from our TFS server.  I was getting build errors when it executed heat.exe

 

heat.exe: Access to the path 'C:\Builds\31\VSTancillary\FleetVision_Dev\Sources\WixSetupProject\adminfiles.wxs' is denied.

That was annoying. During the build, heat was recreating the adminfiles.wxs file each time.  Since that file was in source control, it was set to read only on the build server.  That caused heat.exe to abort out since it couldn’t recreate that file. Our build engineer suggested using the attrib command to clear the read only bit. The light bulb (LED, should last longer than incandescent) flickered above my head and I realized that since that file was in source control, I didn’t need to created it on the build server.  I just needed to set the build so that heat didn’t run on the build server.

There are probably a few ways of doing this, I went with setting it up so that heat would only get run for debug builds.  Our build server is only doing release builds, this would work for me. So I moved the prebuild code out of the project property settings and implemented them as individual MSBuild tasks.

The first part of doing that was to install the MSBuild Extension Pack from CodePlex. I did that to get a RoboCopy task for MSBuild.  Robocopy is very powerful tool for copying and synching up files, but has this one little quirk. It return 1 as a success code. Everything else on Planet DOS returns 0 for success and non-zero values to indicate an error.  The MSBuild.ExtensionPack.FileSystem.RoboCopy task knows about that quirk and prevents MSBuild from reporting a robocopy success code as an error.  Lots of good stuff in the Extension Pack, you’ll want to have one in your toolbelt.

When you install WIX, you get WIX specific extensions for MSBuild.  The task for heat is called HeatDirectory.  The HeatDirectory equivalent of the heat.exe command line that I was using looks like this:

The first element is Condition, which is comes with MSBuild.  By setting the value to ” ‘$(Configuration)|$(Platform)’ == ‘Debug|x86’ “, MSBuild will only execute that task when the condition evaluates to true.

That worked perfectly, but only for the first time.  After doing one debug build, the next build bombed out on the RoboCopy task.  There was a problem with the files being in use.  If I restarted VS, I could do another build. If I commented out the HeatDirectory task, the build would work.  I went to the WIX site and sure enough, this was a known bug. The heat.exe was keeping the file handles open for the files that it read.

By default, HeatDirectory was running heat.exe from within the Visual Studio process. This was the fast way to execute heat, but you pick up any handle heaks from the heat.exe.  In one of the comments to the bug report, a work around was suggested.  Add RunAsSeparateProcess=”true” to HeatDirectory.  This forces heat.exe to be run as a separate process and the leaked handles get flushed when that process ends.

That took care of the problem.  While this is a known bug, the comments associated with that bug made it clear that it’s not going toget addressed any time soon.

So what is CTT? It is a command line version of the XDT transform that Visual Studio uses when it transforms web.config from web.release.config and web.debug.config.  It’s another good tool.

If you are still reading this, here is the final version of the prebuild events