Merge pull request #128 from SamR1/add-email-uri-wo-auth
allow EMAIL_URL without authentication
This commit is contained in:
commit
7f809f9334
@ -18,7 +18,7 @@ export DATABASE_TEST_URL=postgresql://fittrackee:fittrackee@fittrackee-db:5432/f
|
|||||||
export UI_URL=http://0.0.0.0:5000
|
export UI_URL=http://0.0.0.0:5000
|
||||||
# For development:
|
# For development:
|
||||||
# export UI_URL=http://0.0.0.0:3000
|
# export UI_URL=http://0.0.0.0:3000
|
||||||
export EMAIL_URL=smtp://none:none@mail:1025
|
export EMAIL_URL=smtp://mail:1025
|
||||||
export SENDER_EMAIL=fittrackee@example.com
|
export SENDER_EMAIL=fittrackee@example.com
|
||||||
export REDIS_URL=redis://redis:6379
|
export REDIS_URL=redis://redis:6379
|
||||||
export WORKERS_PROCESSES=2
|
export WORKERS_PROCESSES=2
|
||||||
|
@ -210,6 +210,11 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
|
|||||||
- with STARTTLS: ``smtp://username:password@smtp.example.com:587/?tls=True``
|
- with STARTTLS: ``smtp://username:password@smtp.example.com:587/?tls=True``
|
||||||
|
|
||||||
|
|
||||||
|
.. versionadded:: 0.5.3
|
||||||
|
|
||||||
|
| Credentials can be omitted: ``smtp://smtp.example.com:25``.
|
||||||
|
| If ``:<port>`` is omitted, the port defaults to 25.
|
||||||
|
|
||||||
Map tile server
|
Map tile server
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
.. versionadded:: 0.4.0
|
.. versionadded:: 0.4.0
|
||||||
|
@ -458,6 +458,13 @@ see <a class="reference external" href="https://docs.sqlalchemy.org/en/13/core/p
|
|||||||
<li><p>with SSL: <code class="docutils literal notranslate"><span class="pre">smtp://username:password@smtp.example.com:465/?ssl=True</span></code></p></li>
|
<li><p>with SSL: <code class="docutils literal notranslate"><span class="pre">smtp://username:password@smtp.example.com:465/?ssl=True</span></code></p></li>
|
||||||
<li><p>with STARTTLS: <code class="docutils literal notranslate"><span class="pre">smtp://username:password@smtp.example.com:587/?tls=True</span></code></p></li>
|
<li><p>with STARTTLS: <code class="docutils literal notranslate"><span class="pre">smtp://username:password@smtp.example.com:587/?tls=True</span></code></p></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="versionadded">
|
||||||
|
<p><span class="versionmodified added">New in version 0.5.3.</span></p>
|
||||||
|
</div>
|
||||||
|
<div class="line-block">
|
||||||
|
<div class="line">Credentials can be omitted: <code class="docutils literal notranslate"><span class="pre">smtp://smtp.example.com:25</span></code>.</div>
|
||||||
|
<div class="line">If <code class="docutils literal notranslate"><span class="pre">:<port></span></code> is omitted, the port defaults to 25.</div>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section id="map-tile-server">
|
<section id="map-tile-server">
|
||||||
<h3>Map tile server<a class="headerlink" href="#map-tile-server" title="Permalink to this headline">¶</a></h3>
|
<h3>Map tile server<a class="headerlink" href="#map-tile-server" title="Permalink to this headline">¶</a></h3>
|
||||||
|
File diff suppressed because one or more lines are too long
@ -210,6 +210,11 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
|
|||||||
- with STARTTLS: ``smtp://username:password@smtp.example.com:587/?tls=True``
|
- with STARTTLS: ``smtp://username:password@smtp.example.com:587/?tls=True``
|
||||||
|
|
||||||
|
|
||||||
|
.. versionadded:: 0.5.3
|
||||||
|
|
||||||
|
| Credentials can be omitted: ``smtp://smtp.example.com:25``.
|
||||||
|
| If ``:<port>`` is omitted, the port defaults to 25.
|
||||||
|
|
||||||
Map tile server
|
Map tile server
|
||||||
^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^
|
||||||
.. versionadded:: 0.4.0
|
.. versionadded:: 0.4.0
|
||||||
|
@ -69,7 +69,7 @@ class EmailTemplate:
|
|||||||
class Email:
|
class Email:
|
||||||
def __init__(self, app: Optional[Flask] = None) -> None:
|
def __init__(self, app: Optional[Flask] = None) -> None:
|
||||||
self.host = 'localhost'
|
self.host = 'localhost'
|
||||||
self.port = 1025
|
self.port = 25
|
||||||
self.use_tls = False
|
self.use_tls = False
|
||||||
self.use_ssl = False
|
self.use_ssl = False
|
||||||
self.username = None
|
self.username = None
|
||||||
@ -110,7 +110,8 @@ class Email:
|
|||||||
with self.smtp(
|
with self.smtp(
|
||||||
self.host, self.port, **connection_params # type: ignore
|
self.host, self.port, **connection_params # type: ignore
|
||||||
) as smtp:
|
) as smtp:
|
||||||
smtp.login(self.username, self.password) # type: ignore
|
if self.username and self.password:
|
||||||
|
smtp.login(self.username, self.password) # type: ignore
|
||||||
if self.use_tls:
|
if self.use_tls:
|
||||||
smtp.starttls(context=context)
|
smtp.starttls(context=context)
|
||||||
smtp.sendmail(self.sender_email, recipient, message.as_string())
|
smtp.sendmail(self.sender_email, recipient, message.as_string())
|
||||||
|
@ -9,10 +9,12 @@ def parse_email_url(email_url: str) -> Dict:
|
|||||||
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 = parsed_url.auth.split(':')
|
credentials = (
|
||||||
|
parsed_url.auth.split(':') if parsed_url.auth else [None, None]
|
||||||
|
)
|
||||||
return {
|
return {
|
||||||
'host': parsed_url.host,
|
'host': parsed_url.host,
|
||||||
'port': 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': True if parsed_url.query == 'tls=True' else False,
|
||||||
'use_ssl': True if parsed_url.query == 'ssl=True' else False,
|
'use_ssl': True if parsed_url.query == 'ssl=True' else False,
|
||||||
'username': credentials[0],
|
'username': credentials[0],
|
||||||
|
@ -63,7 +63,8 @@ class TestEmailSending(CallArgsMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
smtp = mock_smtp.return_value.__enter__.return_value
|
smtp = mock_smtp.return_value.__enter__.return_value
|
||||||
assert smtp.starttls.not_called
|
assert smtp.login.call_count == 1
|
||||||
|
smtp.starttls.assert_not_called()
|
||||||
self.assert_smtp(smtp)
|
self.assert_smtp(smtp)
|
||||||
|
|
||||||
@patch('smtplib.SMTP_SSL')
|
@patch('smtplib.SMTP_SSL')
|
||||||
@ -79,7 +80,8 @@ class TestEmailSending(CallArgsMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
smtp = mock_smtp_ssl.return_value.__enter__.return_value
|
smtp = mock_smtp_ssl.return_value.__enter__.return_value
|
||||||
assert smtp.starttls.not_called
|
assert smtp.login.call_count == 1
|
||||||
|
smtp.starttls.assert_not_called()
|
||||||
self.assert_smtp(smtp)
|
self.assert_smtp(smtp)
|
||||||
|
|
||||||
@patch('smtplib.SMTP_SSL')
|
@patch('smtplib.SMTP_SSL')
|
||||||
@ -95,5 +97,24 @@ class TestEmailSending(CallArgsMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
smtp = mock_smtp.return_value.__enter__.return_value
|
smtp = mock_smtp.return_value.__enter__.return_value
|
||||||
|
assert smtp.login.call_count == 1
|
||||||
assert smtp.starttls.call_count == 1
|
assert smtp.starttls.call_count == 1
|
||||||
self.assert_smtp(smtp)
|
self.assert_smtp(smtp)
|
||||||
|
|
||||||
|
@patch('smtplib.SMTP_SSL')
|
||||||
|
@patch('smtplib.SMTP')
|
||||||
|
def test_it_sends_message_without_authentication(
|
||||||
|
self, mock_smtp: Mock, mock_smtp_ssl: Mock, app_wo_email_auth: Flask
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
email_service.send(
|
||||||
|
template='password_reset_request',
|
||||||
|
lang='en',
|
||||||
|
recipient='test@test.com',
|
||||||
|
data=self.email_data,
|
||||||
|
)
|
||||||
|
|
||||||
|
smtp = mock_smtp.return_value.__enter__.return_value
|
||||||
|
smtp.login.assert_not_called()
|
||||||
|
smtp.starttls.assert_not_called()
|
||||||
|
self.assert_smtp(smtp)
|
||||||
|
@ -12,6 +12,24 @@ class TestEmailUrlParser:
|
|||||||
with pytest.raises(InvalidEmailUrlScheme):
|
with pytest.raises(InvalidEmailUrlScheme):
|
||||||
parse_email_url(url)
|
parse_email_url(url)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def assert_parsed_email(url: str) -> None:
|
||||||
|
parsed_email = parse_email_url(url)
|
||||||
|
assert parsed_email['username'] is None
|
||||||
|
assert parsed_email['password'] is None
|
||||||
|
assert parsed_email['host'] == 'localhost'
|
||||||
|
assert parsed_email['port'] == 25
|
||||||
|
assert parsed_email['use_tls'] is False
|
||||||
|
assert parsed_email['use_ssl'] is False
|
||||||
|
|
||||||
|
def test_it_parses_email_url_without_port(self) -> None:
|
||||||
|
url = 'smtp://localhost'
|
||||||
|
self.assert_parsed_email(url)
|
||||||
|
|
||||||
|
def test_it_parses_email_url_without_authentication(self) -> None:
|
||||||
|
url = 'smtp://localhost:25'
|
||||||
|
self.assert_parsed_email(url)
|
||||||
|
|
||||||
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 = parse_email_url(url)
|
parsed_email = parse_email_url(url)
|
||||||
|
14
fittrackee/tests/fixtures/fixtures_app.py
vendored
14
fittrackee/tests/fixtures/fixtures_app.py
vendored
@ -125,13 +125,23 @@ def app_no_config() -> Generator:
|
|||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def app_ssl(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
def app_ssl(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
||||||
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025?ssl=True')
|
monkeypatch.setenv(
|
||||||
|
'EMAIL_URL', 'smtp://username:password@0.0.0.0:1025?ssl=True'
|
||||||
|
)
|
||||||
yield from get_app(with_config=True)
|
yield from get_app(with_config=True)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def app_tls(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
def app_tls(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
||||||
monkeypatch.setenv('EMAIL_URL', 'smtp://none:none@0.0.0.0:1025?tls=True')
|
monkeypatch.setenv(
|
||||||
|
'EMAIL_URL', 'smtp://username:password@0.0.0.0:1025?tls=True'
|
||||||
|
)
|
||||||
|
yield from get_app(with_config=True)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def app_wo_email_auth(monkeypatch: pytest.MonkeyPatch) -> Generator:
|
||||||
|
monkeypatch.setenv('EMAIL_URL', 'smtp://0.0.0.0:1025')
|
||||||
yield from get_app(with_config=True)
|
yield from get_app(with_config=True)
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user