Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generated tests fail to preg_match the token #333

Open
jeremyVignelles opened this issue Sep 15, 2024 · 3 comments
Open

Generated tests fail to preg_match the token #333

jeremyVignelles opened this issue Sep 15, 2024 · 3 comments

Comments

@jeremyVignelles
Copy link

jeremyVignelles commented Sep 15, 2024

Version: 1.22.0

I used the maker bundle to generate tests for the password reset feature.
I adapted the code so that the mail is in french, but the generated code fails to properly get the token

Test method excerpt:

        // Ensure the reset password email was sent
        // Use either assertQueuedEmailCount() || assertEmailCount() depending on your mailer setup
        self::assertQueuedEmailCount(1);
        // self::assertEmailCount(1);

...

        // Test the link sent in the email is valid
        $email = $messages[0]->toString();
        preg_match('#(/reset-password/reset/[a-zA-Z0-9]+)#', $email, $resetLink);// Matches the first characters of the link, see below

        $this->client->request(\Symfony\Component\HttpFoundation\Request::METHOD_GET, $resetLink[1]);

        self::assertResponseRedirects('/reset-password/reset');

        $this->client->followRedirect();

        // Test we can set a new password
        $this->client->submitForm('Changer votre mot de passe', [// Fails here : can't find the button... $this->client is still on a redirect page
            'change_password_form[plainPassword][first]' => 'newStrongPassword',
            'change_password_form[plainPassword][second]' => 'newStrongPassword',
        ]);

$email value excerpt:

...
Bonjour,=20
    Pour r=C3=A9initialiser votre mot de passe, veuillez clique=
r sur le lien suivant

http://localhost/reset-password/reset/qsfTOThd0P=
F4p0nwzCMVl53pkFjj8yq4r0RczL5P

Ce lien va expirer dans 1 heure.

A=
 bient=C3=B4t !
...
<p>Bonjour, <br />
    Pour r=C3=A9initialiser votre mot de passe, veuill=
ez cliquer sur le lien suivant</p>

<a href=3D"http://localhost/reset-p=
assword/reset/qsfTOThd0PF4p0nwzCMVl53pkFjj8yq4r0RczL5P">http://localhost/re=
set-password/reset/qsfTOThd0PF4p0nwzCMVl5"

Notice how the link is split in two lines.
In that case, only qsfTOThd0P matches as the token, which throws an InvalidResetPasswordTokenException because the length is not 40 in ResetPasswordHelper::validateTokenAndFetchUser

Workaround:

instead of getting toString() of a templated message, we can get the raw text body, that doesn't have the formatting issue.

        /** @var Email $email */
        $email = $messages[0];
        preg_match('#(/reset-password/reset/[a-zA-Z0-9]+)#', $email->getTextBody(), $resetLink);
@bocharsky-bw
Copy link
Member

Hey Jeremy,

If toString() method does not work, how does that test pass in this repo? And actually, I would suppose that the raw text body contained the line breaks as well, no? Why toString() would add those line breaks? Or am I missing something?

@jeremyVignelles
Copy link
Author

jeremyVignelles commented Sep 21, 2024

Hi,
My assumption is that toString() formats the message as it would be sent over the wire, with the target chunking and encoding (multipart/mixed), while the textBody doesn't have that limitation, it's just the raw text as it is intended.

I assume the =\n part to be because of the multipart encoding that truncates the lines to a maximum length.

I don't know why, and maybe that's a misconfiguration in my case ? Or maybe it's because I'm using the messenger component to send the message asynchronously ?

@jeremyVignelles
Copy link
Author

Seems like toString() calls Email::GenerateBody, which in turn creates a TextPart, which uses quoted-printable as the encoding.
The encoder calls the native quoted_printable_encode PHP function which truncates lines to 75 characters as specified by the RFC. The corresponding source code of PHP can be found here.
That being said, that doesn't explain how tests can pass in this repo (spoiler: I didn't look at them yet).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants