Skip to content

HTML password reset does not work for @yahoo.com accounts #4314

Description

@mman

Issue Description

Using both plain text and html templates for password reset. Both templates use the {{link}} macro to expand the password reset link. Works like a charm for all users except for those who have @yahoo.com email address.

Yahoo does something to the email while receiving it that the password reset link can not be clicked. This is what I see when opening the raw email message via browser based html email client (the link excerpt):

The plaintext version:

https://api.example.=
com/myappname/apps/unused/request_password_reset?=
token=jQBDc29205uwCHTDDnwQnxUhZ&username=martin.czman%40yahoo=
.com

The HTML version:

<a href=3D"https:&#x2F;&#x2F; api.example.=
com&#x2F; myappname&#x2F;apps&#x2F;unused&#x2F;request_password_reset?=
token&#x3D;jQBDc29205uwCHTDDnwQnxUhZ&amp;username&#x3D;martin.czman%40yahoo=
.com">Change your password</a>

I'm not sure how to get to the plaintext version of the email, but the HTML version seems garbled and the href is clearly wrong.

Any ideas where this could be coming from? Are you experiencing the same as well?

Steps to reproduce

Create an account for your Parse App using @yahoo.com email address and try to reset your password.

Expected Results

HTML link to change the password be clickable.

Actual Outcome

When reading an email either in the mobile Yahoo Mail app, or via browser based Yahoo Mail, the link is not clickable.

Environment Setup

  • Server

    • parse-server version (Be specific! Don't say 'latest'.) : 2.6.5
    • Operating System: N/A
    • Hardware: N/A
    • Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): Digital Ocean
  • Database

    • MongoDB version: N/A
    • Storage engine: N/A
    • Hardware: N/A
    • Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): Digital Ocean

Logs/Trace

Include all relevant logs. You can turn on additional logging by configuring VERBOSE=1 in your environment.

Activity

  1. mman commented on Nov 3, 2017

    @mman
    ContributorAuthor

    Just for completeness, this is my html template fragment that does the change your password link:

    <a href="{{link}}">Change your password</a>
    

    The template itself is a bit more complex with some CSS and styling attached. The email comes to the host mail.example.com and is pointing back to api.example.com host for password reset.

  2. flovilmart commented on Nov 3, 2017

    @flovilmart
    Contributor

    That's shitty, what do you use to deliver the emails? Do other emails sent with your provider are equally borked?

  3. mman commented on Nov 3, 2017

    @mman
    ContributorAuthor

    I'm using mailgun.com and everywhere else it works as expected (@gmail.com, @icloud.com, ...), it's just the HTML email delivered to @yahoo.com. I had a conversation with mailgun guys where they explained to me that they need to do certain tricks to even deliver the emails to @yahoo.com, meaning yahoo.com is generally probably rather broken in many other ways.

    I just want to confirm whether this has something to do with my HTML templates, or is it a wide spread issue. Does it happen for your apps as well @flovilmart? Or you sending just the plaintext variant?

  4. flovilmart commented on Nov 3, 2017

    @flovilmart
    Contributor

    We don't use email login in our apps, so I'm, not sure it is widespread or not. I don'T believe it's an issue with the way we do templates, but perhaps it is.

  5. montymxb commented on Nov 3, 2017

    @montymxb
    Contributor

    Geez, they're just encoding the entire thing -_-. That is super weird. We've dealt with yahoo.com issues in the past, particularly with multipart text/html emails, but never saw an issue with them failing to decode links afterwards. For it to be specifically yahoo is a bit suspicious though.

    I'm curious, I'm going to take a look and see if something has changed with their handling.

  6. montymxb commented on Nov 3, 2017

    @montymxb
    Contributor

    @mman Nothing out of the ordinary for our stuff, links in yahoo look fine. Granted I tested with a direct send, not with mailgun. Just curious, what transfer encodings are being used in the parts of the received email? We run with the following:

    // plain
    Content-Transfer-Encoding: base64
    Content-Type: text/plain; charset=UTF-8; format=flowed; delsp=yes
    
    // html
    Content-Transfer-Encoding: quoted-printable
    Content-Type: text/html; charset=UTF-8
    

    From what we've seen encoding with base64 and quoted-printable works pretty good for us, even on some of the weirder hosts.

    It's possible that something is being misrepresented, resulting in a failure to properly decode content. We've seen that some providers will do some inferring for things like this, resulting in stuff that seems to work even if it's not quite formatted right.

  7. flovilmart commented on Nov 3, 2017

    @flovilmart
    Contributor

    Maybe there’s some tweaking to do in the html payload / metadatas sent through the mailgun API? That seems bending over backwards.

  8. montymxb commented on Nov 3, 2017

    @montymxb
    Contributor

    Perhaps. I just looked and didn't really see anything about setting outgoing encodings from the API, but I think they go to quoted-printable by default, not really sure though.

    @mman can you specify what adapter you're using? There's the default and some community ones, and perhaps you have your own too. Knowing how the api is being interacted with would be a start.

  9. mman commented on Nov 4, 2017

    @mman
    ContributorAuthor

    I'm using "parse-server-mailgun": "^2.0.0" as the adapter and copy pasted the config from readme, like this:

            passwordResetEmail: {
              subject: 'Password Reset Email',
              pathPlainText: resolve(__dirname, 'templates/password_reset_email.txt'),
              pathHtml: resolve(__dirname, 'templates/password_reset_email.html')
            },
    

    So I wonder whether my .html can have some garbage in it that will confuse either parse server, or mailgun, or yahoo...

    But given the fact that all other email addresses are working, I bet it's something towards the yahoo.com side...

  10. montymxb commented on Nov 4, 2017

    @montymxb
    Contributor

    I'm wondering if that's the case. When I have a moment I'll put together something to test this out against mailgun and see if I can't dig something up or find a way to work around what's going on here.

  11. flovilmart commented on Nov 4, 2017

    @flovilmart
    Contributor

    @mman, this may be a stupid question, but what happens when using mailgun from the JS SDK / another SDK and sending those mails?

  12. montymxb commented on Nov 6, 2017

    @montymxb
    Contributor

    @mman I went ahead and setup a little test server with parse-server-mailgun as the email adapter and sent using the mailgun sandbox api. The link in the final email looked just fine the first time around. Here's a snippet of the plain & html parts.

    ------sinikael-?=_1-15099907682760.5737941825734576
    Content-Type: text/plain
    Content-Transfer-Encoding: 7bit
    
    Hi there!
    
    This is a request to reset your password.
    
    You can use the link here, http://localhost:1337/parse
    
    Have a nice day!
    ------sinikael-?=_1-15099907682760.5737941825734576
    Content-Type: text/html
    Content-Transfer-Encoding: 7bit
    
    <body>
    <h1>Hi there!</h1>
    <h2>This is a request to reset your password.</h2>
    <p>
        You can use the link <a href="http://localhost:1337/parse">here</a>.
    </p>
    <p>Have a nice day!</p>
    </body>
    ------sinikael-?=_1-15099907682760.5737941825734576--
    

    Notice that both part encodings are 7bit and the link is as expected.

    However I realized that you were dynamically adding the link when you send the email, so I went ahead and did that as well.

    <p>
        You can use the link <a href="{{link}}">here</a>.
    </p>

    Now that caused a problem.

    ------sinikael-?=_1-15099912063160.9182591906745077
    Content-Type: text/plain
    Content-Transfer-Encoding: 7bit
    
    Hi there!
    
    This is a request to reset your password.
    
    You can use the link here, http:&#x2F;&#x2F;localhost:1337
    
    Have a nice day!
    ------sinikael-?=_1-15099912063160.9182591906745077
    Content-Type: text/html
    Content-Transfer-Encoding: quoted-printable
    
    <body>
        <h1>Hi there!</h1>
        <h2>This is a request to reset your =
    password.</h2>
        <p>
            You can use the link <a =
    href=3D"http:&#x2F;&#x2F;localhost:1337">here</a>.
        </p>
        <p>Have a nice day!</p>
    </body>
    ------sinikael-?=_1-15099912063160.9182591906745077--
    

    The encoding for the html part has now changed to quoted-printable, probably just a choice they're making because of the characters that are showing up where link is injected.

    To further verify I wanted to send the same email to gmail to see what happened there. Sure enough the link works! But, looking under the hood...

    ------sinikael-?=_1-15099920779000.39336503352272967
    Content-Type: text/plain
    Content-Transfer-Encoding: 7bit
    
    Hi there!
    
    This is a request to reset your password.
    
    You can use the link here, http:&#x2F;&#x2F;localhost:1337
    
    Have a nice day!
    ------sinikael-?=_1-15099920779000.39336503352272967
    Content-Type: text/html
    Content-Transfer-Encoding: quoted-printable
    
    <body>
        <h1>Hi there!</h1>
        <h2>This is a request to reset your password.</h2>
        <p>
            You can use the link <a href=3D"http:&#x2F;&#x2F;localhost:1337">he=
    re</a>.
        </p>
        <p>Have a nice day!</p>
    </body>
    ------sinikael-?=_1-15099920779000.39336503352272967--
    

    it's still broken!

    Although their quoted-printable encoding approach is slightly different it can be considered equivalent. So, gmail is capable of recognizing and properly decoding the urls back.

    Ultimately looks like whatever is happening it has to do with the injection being done by mustaches and parse-server-mailgun in the templates you are using. Later I'm going to check exactly where it's causing this, and will see if I can't submit a PR to them to patch this behavior.

  13. montymxb commented on Nov 6, 2017

    @montymxb
    Contributor

    After looking a bit further at mustache I found the following in their docs.

    All variables are HTML escaped by default. If you want to return unescaped HTML, use the triple mustache: {{{name}}}.

    Went ahead and tried this out on my test setup and it worked just fine 👍 .

  14. flovilmart commented on Nov 6, 2017

    @flovilmart
    Contributor

    So that's a moustache issue then!

  15. montymxb commented on Nov 6, 2017

    @montymxb
    Contributor

    Yep, normal behavior, just need to change the template to get the expected results. Closing this out since that's pretty much it.

    @mman let us know that this does actually work for you. I'm expecting it will, but in any case keep us posted!

  16. mman commented on Nov 6, 2017

    @mman
    ContributorAuthor

    @montymxb @flovilmart I have now updated both the .txt and .html template to quote all variables using {{{ and }}} and it indeed works as expected and Yahoo users can click the password reset link. Looking at the raw email body it also looks much better. I was not even aware there is mustache involved but I thank you both a lot for your effort +1 +1 +1 +1 :)

    Looks to me that the docs will need to be updated because I did copy/paste this from somewhere I'm sure...

  17. flovilmart commented on Nov 6, 2017

    @flovilmart
    Contributor

    That's great news! Thanks @montymxb for tracking it down!

  18. mman commented on Nov 6, 2017

    @mman
    ContributorAuthor

    Just to follow up, the README at https://github.com/sebsylvester/parse-server-mailgun already mentions that {{{link}}} needs to be escaped using {{{ and }}}. Thanks all for your help.

  19. flovilmart commented on Nov 6, 2017

    @flovilmart
    Contributor

    hahah so it was actually documented! easy to miss though.

  20. montymxb commented on Nov 6, 2017

    @montymxb
    Contributor

    Sure thing, and of course it was right there the whole time -_-

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions