symfony / swiftmailer-bundle

Symfony Swiftmailer Bundle
https://symfony.com/swiftmailer-bundle
MIT License
1.56k stars 151 forks source link

Using backslahes / on MAILER_URL .env #270

Closed sergiodinizoswald closed 5 years ago

sergiodinizoswald commented 5 years ago

Symfony version(s) affected: 4.1.8

Description
Can't use / on the password for email authentication.

How to reproduce
Use an email that has a password for example: stuff/2018.

Meaning that MAILER_URL would be something like this: MAILER_URL=smtp://test@gmail.com:stuff/2018@smtp.gmail.com?port=465&auth_mode=login&encryption=ssl

In my case I'm using gmail, and the password has a /, this completely breaks the MAILER_URL parameter, I've tried using %2F instead of /, even tried to use // to maybe escape or even \/ but nothing.

It basically breaks on: Symfony\Bundle\SwiftmailerBundle\DependencyInjection\SwiftmailerTransportFactory on the calling of parse_url around on line 102:

if (isset($options['url'])) {
    $parts = parse_url($options['url']);
    if (isset($parts['scheme'])) {
        $options['transport'] = $parts['scheme'];
    }
   if (isset($parts['user'])) {
        $options['username'] = $parts['user'];
    }

Using %2F as escaping works, and the password is correctly setup:

array:5 [▼
  "scheme" => "smtp"
  "host" => "smtp.gmail.com"
  "user" => "test@gmail.com"
  "pass" => "test%2F2018"
  "query" => "port=465&auth_mode=login&encryption=ssl"
]

But it then get's rejected by gmail in this case ( could gmail be the culprit here, don't really think so ), because the password does not match since the password really is: stuff/2018.

I've managed to go around it, by basically passing all the parameters separately.

Possible Solution

Running url_decode on each part returned by the parse_url function? Don't really know if this is a valid solution and secure one,, and if it won't break already functioning code, for example: https://github.com/symfony/symfony-docs/pull/9824 ( I was the one that lost 3 hours trying to figure out what happened with the + sign ).

Is this really a bug? Or am I missing something really simple?

stof commented 5 years ago

well, you can if you url-encode it, like any place where you put a password in an URL.

The weird thing is what happens when you use %2F. After parsing, it should not be a %2F but a /. could it be that parse_url does not properly url-decode each part ?

stof commented 5 years ago

hmm, that's indeed the case. It does not decode each part: https://secure.php.net/parse_url

stof commented 5 years ago

Doctrine DBAL is apply $url = array_map('rawurldecode', $url); (where $url is the equivalent of $parts in your snippet)

sergiodinizoswald commented 5 years ago

Yeah, that is probably the solution, and actually someone already did a PR for that: #263, but are using urldecode instead of rawurldecode, and are using it only on the user/password fields, I think it would be better to do the same as Doctrine Dbal does.

naderman commented 5 years ago

@sergiodinizoswald want to submit a PR with a better solution then?

sergiodinizoswald commented 5 years ago

@naderman yeah sure.. not a problem!

naderman commented 5 years ago

@sergiodinizoswald looks like @eeemarv updated his PR already https://github.com/symfony/swiftmailer-bundle/pull/263#issuecomment-484363352 maybe just confirm if that version works too? @stof are there any other $parts that would need special decoding?