Search code examples
c#asp.net-corerazorhtml-emailrazorengine

Razor Engine: URL generation in template of & generates &


I have an ASP.NET Core application which use Identity for user management.

I have a MailProvider which prepares an email to send via smtp for account activation purposes:

// ...
var activationMailViewModel = new ActivationMailViewModel()
{
    LastName = user.LastName,
    FirstName= user.FirstName,
    UserName = userName,
    Email = user.Email,
    CompanyName = companyName,
    Url = url.Action("ConfirmEmail", "Account", new { Area = "", code = token, userId = user.Id }, request.Scheme)
};
// ...
var result = Engine.Razor.RunCompile(new LoadedTemplateSource($"Activation", path), "SendUserAccountCreation" + Guid.NewGuid(), null, activationMailViewModel);
// ...

 var mailMessage = new MailMessage(
                new MailAddress("kyc@vente-privee.com", "KYC-vente-privee.com"),
                new MailAddress(user.Email, userName))
            {
                Subject = GetGlobalString("ActivationMail_Subject", cultureCode),
                BodyEncoding = System.Text.Encoding.UTF8,
                SubjectEncoding = System.Text.Encoding.UTF8
            };

<p><a href="@Model.Url" class="button">ACTIVATE MY ACCOUNT</a></p>

However it seems that the link generated can be interpreted in two different ways due to the transcription of the character & into &amp; in the query string of the url.

http://base.url.net/Account/ConfirmEmail?code=CfDJ8PtYvJr8Ve1GnxXJykedIzKTQDg%2FTXBwV6NmIYMy8Gi7yUbqZagGbZRacKSFrE717h%2FGjmm6l8QA3knPPgxyNnM1vxe3wb6KnFsGtZUOMTas7QhX1MW5dE4cU5sorA99Dz03zV8ldVMOMP5BGfUrts2nNQqbs8dNLPNgupdkNzaWa4q6fM5u9E99CzRcFjAn7nnd57Ht3IIREAqz6lqufFYo469%2BN2VJxmNJJ1p6OAvO6dMJ9M%2Fzdz3xkpBajJbxRw%3D%3D**&**userId=21e4673c-f121-417f-9837-7f5b234f6f01

http://base.url.net/Account/ConfirmEmail?code=CfDJ8PtYvJr8Ve1GnxXJykedIzKTQDg%2FTXBwV6NmIYMy8Gi7yUbqZagGbZRacKSFrE717h%2FGjmm6l8QA3knPPgxyNnM1vxe3wb6KnFsGtZUOMTas7QhX1MW5dE4cU5sorA99Dz03zV8ldVMOMP5BGfUrts2nNQqbs8dNLPNgupdkNzaWa4q6fM5u9E99CzRcFjAn7nnd57Ht3IIREAqz6lqufFYo469%2BN2VJxmNJJ1p6OAvO6dMJ9M%2Fzdz3xkpBajJbxRw%3D%3D**&**userId=21e4673c-f121-417f-9837-7f5b234f6f01

Which can be problematic for the my AccountController:

[Authorize]
public class AccountController : BaseController
{

    // GET: /Account/ConfirmEmail
    [AllowAnonymous]
    public async Task<ActionResult> ConfirmEmail(string code, string userId)
    {
        if (code == null || userId == null)
        {
            return View("Error");
        }

    // Rest of the code... not relevant to the question
}

If the browser / mail client interprets & as &amp; then the userId will be set to null and the account / email cannot be confirmed.

For example:

  • On ProtonMail: the link on which I can click leads to an address which use & in the query string, which is just fine.
  • On Gmail: &amp; and hence the link does not confirm the email.

However in both email providers, the plain text shows that the url has been generated with the Razor engine is: &amp;.

What is the best strategy so that my users do not end up with a link that does not work.


Solution

  • Seems the issue was about the raw formatting which was not applied to the email.

    The answer given here on SO:

    When doing e-mails, I use the RazorEngineService in RazorEngine.Templating, e.g. in my case, it looks like this:

    using RazorEngine.Templating;
    
    RazorEngineService.Create().RunCompile(html, ...) 
    

    Assuming you are using the same assembly, @Html.Raw does NOT exist with this usage. I > was finally able to get raw HTML output by doing this in my e-mails:

    @using RazorEngine.Text
    
    @(new RawString(Model.Variable))