Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

Mime Base64 is a Thing?


:P
On this page:

Mime Banner

In all my years of developing software, sending binary data back and forth I've never heard of Mime Base64. Apparently that is a thing for email encoding of binary data for some legacy applications that don't directly accept binary content.

This came up recently when working with a customer that is using MailGun's API. We were sending original data from a front end application to the server and found ourselves stymied when trying to attach files that were encoded in plain Base64 and results coming back as 400 - Bad Request.

MIME Base64

MIME Base64 is based on the Base64 encoding but with specific rules for email communication. It ensures that the encoded data is safe for use in email headers and bodies.

Essentially this boils down to a slightly modified format that is safe for Mime and URL encoding so it can be used on URLs and form encoded body content in HTTP and email bodies for example.

The rules are pretty simple as applied to base Base64 content:

  • Trims any ending =
  • + is converted to -
  • / is converted to _

The latter two work because the characters converted to are not present in base64 content. + and / are and they are URL 'unsafe' characters that can be misinterpreted by URL or MIME Encoding parsers. MIME Base64 basically replaces the unsafe characters with safe characters. As such it's essentially a transport format that's converted to and converted back before actual use in most cases. Additionally the format strips off the trailing = padding characters that are used to fill base64 content to exact 3 boundary chunks.

Converting MIME Base64

To work around this is simple enough with a wrapper class around the Convert class base64 functionality native in the .NET base library.

The following class converts standard base64 to Mime base64 and back:

public static class Base64Mime
{
	public static string EncodeFromBytes(byte[] bytes)
	{
		var base64 = Convert.ToBase64String(bytes);
		return EncodeFromBase64String(base64);
	}
	
	public static byte[] DecodeToBytes(string mimeBase64)
	{		
		var base64 = DecodeToBase64(mimeBase64);
		return Convert.FromBase64String(base64);
	}

	public static string EncodeFromBase64String(string base64)
	{
		return base64
			.TrimEnd('=')
			.Replace('+', '-')
			.Replace('/', '_');
	}

	public static string DecodeToBase64(string mimeBase64)
	{
		mimeBase64 = mimeBase64.Replace('_', '/').Replace('-', '+');
		switch (mimeBase64.Length % 4)
		{
			case 2:
				mimeBase64 += "==";
				break;
			case 3:
				mimeBase64 += "=";
				break;
		}
		return mimeBase64;
	}	
}

Here's how you can use (LINQPad code):

var bytes = new byte[] { 32, 199,34,35, 233,137,38,39,40};
bytes.Dump();
var b64 = Convert.ToBase64String(bytes);

b64.Dump();

"-----".Dump();

var mimeB64 = Base64Mime.EncodeFromBase64String(b64);
mimeB64.Dump();

"-----".Dump();

b64 = Base64Mime.DecodeToBase64(mimeB64);
b64.Dump();

"-----".Dump();

mimeB64 = Base64Mime.EncodeFromBytes(bytes);
mimeB64.Dump();

"-----".Dump();

bytes = Base64Mime.DecodeToBytes(mimeB64);
Convert.ToBase64String(bytes).Dump();
bytes.Dump();

WebEncoders in ASP.NET Libraries

@Andrew in the comments mentioned that there's some work happening related to Base64 encoding to provide a dedicated Base64 encoding class that can handle many common operations - inculding URL encoded Base64 encoding. There's some more information in this GitHub Issue.

One of the comments in that thread also points at the existing WebEncoder class in the ASP.NET Core libraries which mimic the EncodeFromBytes() and `DecodeToBytes()`` methods above:

// Microsoft.AspNetCore.WebUtilities
var bytes = new byte[] { 32, 199,34,35, 233,137,38,39,40};
WebEncoders.Base64UrlEncode(bytes).Dump();
WebEncoders.Base64UrlDecode(mimeB64).Dump();

As of .NET 8 these helpers are available in an installable NuGet package that can be used outside of ASP.NET:

dotnet add package Microsoft.AspNetCore.WebUtilities

Who knew there was so much attention to this? Not me 😄

Summary

Nothing new here, but it's something that I missed, and I'm making a note for myself with this post so I may find it again in the future...

Posted in .NET  

The Voices of Reason


 

Andrew
May 27, 2024

# re: Mime Base64 is a Thing?

It would seem .NET is set to receive first class support for Base64 URL encode / decode.

https://github.com/dotnet/runtime/issues/1658

https://github.com/dotnet/runtime/pull/102364


Rick Strahl
May 28, 2024

# re: Mime Base64 is a Thing?

@Andrew - thanks for these links. I had no idea - looks like WebEncoders.Base64UrlEncode(bytes) (and decode) provide this very functionality I describe in this post.

Updated the post with more info. Thanks!


Rob
June 01, 2024

# re: Mime Base64 is a Thing?

If you don't know about these...worth exploring...

https://github.com/jstedfast/MimeKit https://github.com/jstedfast/MailKit


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024