Merge pull request #433 from SamR1/handle-encoded-password

Handle encoded password in EMAIL_URL
This commit is contained in:
Sam 2023-10-02 12:09:41 +02:00 committed by GitHub
commit 4ade698306
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 31 additions and 5 deletions

View File

@ -4,6 +4,7 @@ import ssl
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText from email.mime.text import MIMEText
from typing import Dict, List, Optional, Type, Union from typing import Dict, List, Optional, Type, Union
from urllib.parse import unquote
from babel.support import Translations from babel.support import Translations
from flask import Flask from flask import Flask
@ -131,7 +132,7 @@ class EmailService:
parsed_url = parse_url(email_url) parsed_url = parse_url(email_url)
if parsed_url.scheme != 'smtp': if parsed_url.scheme != 'smtp':
raise InvalidEmailUrlScheme() raise InvalidEmailUrlScheme()
credentials = ( username, password = (
parsed_url.auth.split(':') parsed_url.auth.split(':')
if parsed_url.auth if parsed_url.auth
else [None, None] # type: ignore else [None, None] # type: ignore
@ -139,10 +140,12 @@ class EmailService:
return { return {
'host': parsed_url.host, 'host': parsed_url.host,
'port': 25 if parsed_url.port is None else parsed_url.port, 'port': 25 if parsed_url.port is None else parsed_url.port,
'use_tls': True if parsed_url.query == 'tls=True' else False, 'use_tls': parsed_url.query == 'tls=True',
'use_ssl': True if parsed_url.query == 'ssl=True' else False, 'use_ssl': parsed_url.query == 'ssl=True',
'username': credentials[0], 'username': username,
'password': credentials[1], 'password': (
unquote(password) if isinstance(password, str) else password
),
} }
@property @property

View File

@ -1,4 +1,5 @@
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from urllib.parse import quote
import pytest import pytest
from flask import Flask from flask import Flask
@ -43,6 +44,7 @@ class TestEmailServiceUrlParser(CallArgsMixin):
@staticmethod @staticmethod
def assert_parsed_email(url: str) -> None: def assert_parsed_email(url: str) -> None:
parsed_email = email_service.parse_email_url(url) parsed_email = email_service.parse_email_url(url)
assert parsed_email['username'] is None assert parsed_email['username'] is None
assert parsed_email['password'] is None assert parsed_email['password'] is None
assert parsed_email['host'] == 'localhost' assert parsed_email['host'] == 'localhost'
@ -60,7 +62,9 @@ class TestEmailServiceUrlParser(CallArgsMixin):
def test_it_parses_email_url(self) -> None: def test_it_parses_email_url(self) -> None:
url = 'smtp://test@example.com:12345678@localhost:25' url = 'smtp://test@example.com:12345678@localhost:25'
parsed_email = email_service.parse_email_url(url) parsed_email = email_service.parse_email_url(url)
assert parsed_email['username'] == 'test@example.com' assert parsed_email['username'] == 'test@example.com'
assert parsed_email['password'] == '12345678' assert parsed_email['password'] == '12345678'
assert parsed_email['host'] == 'localhost' assert parsed_email['host'] == 'localhost'
@ -70,7 +74,9 @@ class TestEmailServiceUrlParser(CallArgsMixin):
def test_it_parses_email_url_with_tls(self) -> None: def test_it_parses_email_url_with_tls(self) -> None:
url = 'smtp://test@example.com:12345678@localhost:587?tls=True' url = 'smtp://test@example.com:12345678@localhost:587?tls=True'
parsed_email = email_service.parse_email_url(url) parsed_email = email_service.parse_email_url(url)
assert parsed_email['username'] == 'test@example.com' assert parsed_email['username'] == 'test@example.com'
assert parsed_email['password'] == '12345678' assert parsed_email['password'] == '12345678'
assert parsed_email['host'] == 'localhost' assert parsed_email['host'] == 'localhost'
@ -80,7 +86,9 @@ class TestEmailServiceUrlParser(CallArgsMixin):
def test_it_parses_email_url_with_ssl(self) -> None: def test_it_parses_email_url_with_ssl(self) -> None:
url = 'smtp://test@example.com:12345678@localhost:465?ssl=True' url = 'smtp://test@example.com:12345678@localhost:465?ssl=True'
parsed_email = email_service.parse_email_url(url) parsed_email = email_service.parse_email_url(url)
assert parsed_email['username'] == 'test@example.com' assert parsed_email['username'] == 'test@example.com'
assert parsed_email['password'] == '12345678' assert parsed_email['password'] == '12345678'
assert parsed_email['host'] == 'localhost' assert parsed_email['host'] == 'localhost'
@ -88,6 +96,21 @@ class TestEmailServiceUrlParser(CallArgsMixin):
assert parsed_email['use_tls'] is False assert parsed_email['use_tls'] is False
assert parsed_email['use_ssl'] is True assert parsed_email['use_ssl'] is True
def test_it_parses_email_url_with_encoded_password(self) -> None:
username = "user_name@example.com"
password = "passwordWith@And&And?"
encoded_password = quote(password)
url = f"smtp://{username}:{encoded_password}@localhost:465?ssl=True"
parsed_email = email_service.parse_email_url(url)
assert parsed_email['username'] == username
assert parsed_email['password'] == password
assert parsed_email['host'] == 'localhost'
assert parsed_email['port'] == 465
assert parsed_email['use_tls'] is False
assert parsed_email['use_ssl'] is True
class TestEmailServiceSend(CallArgsMixin): class TestEmailServiceSend(CallArgsMixin):
email_data = { email_data = {