Received this from a customer, our password reset emails normally generate correctly, however what (in code) looks like this:
<h4> <a href="https://'.$this->server.'/password?email_token='.$email_token.'&user_email='.$user_email.'">reset here</a></h4>
And the string that was generated was as followed:
https://password/?email_token=111111111111111111111aaaaaaabbbb&user_email=info@mail.com
Finally, this is what it should look like:
https://website.com/password?email_token=111111111111111111111aaaaaaabbbb&user_email=info@mail.com
This is the interesting segment:
.'/password?
It was generated as followed:
password/?
Somehow when generating the email, the ‘/’ before ‘password’ was moved after password, but before the ‘?’
It’s a static string fragment, how could this happen?
Advertisement
Answer
This is an issue caused by the URL parsing within the client (Chrome, FireFox, Edge, and possibly other client interpreters like outlook). I did not test Opera but it does not occur in Internet Explorer 11.
For more details see: https://webkit.org/blog/7086/url-parsing-in-webkit/
The URL parsing may also be applied by the sending or receiving MTA such as; postfix, gmail, office.com, etc. However my testing with postfix and gmail did not alter the source code of the email message.
We would need to know your server configuration and the recipient’s MTA to validate.
The actual string output in the PHP source code and resulting HTML is as expected
https:///password?email_token=111111111111111111111aaaaaaabbbb&user_email=info@mail.com
Since it is not a valid URI, as the domain provided by $this->server
is missing, the offending client parses the URL and moves the extra /
.
Run the snippet below to experience the URL parsing during click and mouseover in your browser: Shortened the URL parameters for brevity.
<a href="https:///password?email_token=1">Test</a>
Rendered Result:
The same behavior can be experienced in Javascript when using new URL()
.
var url = 'https:///password?e=1'; var u = new URL(url); window.alert('Original: ' + url + "nParsed: " + u.href);
However when the domain is provided, the URL is not altered.
<a href="https://example.com/password?email_token=1">Test</a>