How to correctly encode MailTo links in ASP.NET MVC?
Asked Answered
E

3

16

I have the following mailto link on an ASP.NET MVC 5 application:

<a rel="nofollow" href="@(
  String.Format("mailto:?subject={0}&amp;body={1}", 
    "The title", "The description" + "%0D%0A" + "http://theurl.xyz")">
  share by email
</a>

This is not validating on HTML Validator. I get the error:

Bad value mailto:?subject=The subject&body=This is the url:%0D%0Ahttp://localhost:8580/home for attribute href on element a: Whitespace in query component. Use %20 in place of spaces.

I tried encoding using HttpUtility.UrlEncode but when I open the email I get "+" signs and others in the subject and body and I am not able to solve that.

Excrescence answered 21/12, 2013 at 16:4 Comment(2)
Have you tried out the HttpUtility.UrlPathEncode as I've suggested?Arly
Uri.EscapeDataString did the trickJoyner
V
25

I know this is a little old, but I came across this when I was trying to figure out the best way to encode mailto links. I've found the best way is use Uri.EscapeDataString for each parameter and then encode the entire attribute thing using HttpUtility.HtmlAttributeEncode:

HttpUtility.HtmlAttributeEncode(
    String.Format("mailto:?subject={0}&body={1}", 
        Uri.EscapeDataString(subject), 
        Uri.EscapeDataString(body)))

HttpUtility.UrlEncode and HttpUtility.UrlEncodeUnicode do not correctly encode spaces -- they become plus signs ("+") which then show up as plus signs in the subject line/body/etc. HttpUtility.UrlPathEncode seems to fix that problem, but doesn't properly encode other characters like ?, #, and /. Uri.EscapedDataString seems to be the only method that properly encodes all of these characters. I imagine Uri.HexEscape would work equally as well, but it seems like that might be overkill.

Caveat: I haven't tested this with even a remotely wide variety of browsers and email clients

Villareal answered 25/3, 2015 at 16:10 Comment(1)
Please see this SO answer from @lukas-kabrt <a class="btn btn-primary center" href="mailto:@[email protected]&[email protected](Model.body)">Send Mail</a>Tapley
A
9

You need to use the HttpUtility.UrlPathEncode instead of the HttpUtility.UrlEncode:

<a rel="nofollow" href="@(
  (String.Format("mailto:?subject={0}&body={1}", 
    HttpUtility.UrlPathEncode("The subject line"), 
    HttpUtility.UrlPathEncode("The body") + "%0D%0A" + "http://theurl.xyz"))))">
  share by email
</a>

Note: you need to HttpUtility.UrlPathEncode the parts separately, and you cannot put the HttpUtility.UrlPathEncode around the whole String.Format because the HttpUtility.UrlPathEncode handles the ? specially and only encodes the text before the ?.

From MSDN:

You can encode a URL using with the UrlEncode method or the UrlPathEncode method. However, the methods return different results. The UrlEncode method converts each space character to a plus character (+). The UrlPathEncode method converts each space character into the string "%20", which represents a space in hexadecimal notation.

Arly answered 21/12, 2013 at 16:36 Comment(2)
I'm not sure about the OPs situation but for me this is right but only to a point. I need to handle both spaces and an ampersand. THe UrlPathEncode will properly handle space but improperly handle ampersands. Still +1 since it points me in the right direction.Divan
Please take a look at this answer in SOTapley
C
0

That's because razor doesn't know when to start processing c# code. You have to explicitly tell razor when to interpret c#...

<a rel="nofollow" href=" @(string.Format("mailto:?subject={0}&body={1}", ViewBag.Title, ViewBag.Description + "%0D%0A" + ViewBag.Url))>Share by Email </a>

Edit

Answer

I got carried away by sytanx errors you had in your razor. However, even after you edited your question I can still see some issues there. The first issue is that you open two parenthesis but close only one. The second issue is that you specify an empty email address, well, you should at least add a space (not html encoded). And the last issue is that you are not actually separating the subject and body because you are using ? instead of &. If you correct these issues you should be good to go. Here's an example based on your question...

<a rel="nofollow" href="@(String.Format("mailto: ?subject={0}&body={1}"
                                            , "The title"
                                            , "The description" + "%0D%0A" + "http://theurl.xyz"))">
    share by email
</a>

That should work as it is. But if you want to do more funky stuff, please read this RFC

Cid answered 21/12, 2013 at 16:9 Comment(1)
Sorry mate, I misread your question and the first thing that I noticed a syntactical malformation in your razor code. I'll edit my answerCid

© 2022 - 2024 — McMap. All rights reserved.