API - allow EMAIL_URL without authentication - fix #127
This commit is contained in:
		@@ -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
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -209,6 +209,9 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
 | 
				
			|||||||
- with SSL: ``smtp://username:password@smtp.example.com:465/?ssl=True``
 | 
					- with SSL: ``smtp://username:password@smtp.example.com:465/?ssl=True``
 | 
				
			||||||
- 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``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Map tile server
 | 
					Map tile server
 | 
				
			||||||
^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^^
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -458,6 +458,10 @@ 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>
 | 
				
			||||||
 | 
					<p>Credentials can be omitted: <code class="docutils literal notranslate"><span class="pre">smtp://smtp.example.com:25</span></code></p>
 | 
				
			||||||
</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
											
										
									
								
							@@ -209,6 +209,9 @@ To send emails, a valid ``EMAIL_URL`` must be provided:
 | 
				
			|||||||
- with SSL: ``smtp://username:password@smtp.example.com:465/?ssl=True``
 | 
					- with SSL: ``smtp://username:password@smtp.example.com:465/?ssl=True``
 | 
				
			||||||
- 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``
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Map tile server
 | 
					Map tile server
 | 
				
			||||||
^^^^^^^^^^^^^^^
 | 
					^^^^^^^^^^^^^^^
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,7 +9,9 @@ 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': parsed_url.port,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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,16 @@ class TestEmailUrlParser:
 | 
				
			|||||||
        with pytest.raises(InvalidEmailUrlScheme):
 | 
					        with pytest.raises(InvalidEmailUrlScheme):
 | 
				
			||||||
            parse_email_url(url)
 | 
					            parse_email_url(url)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_it_parses_email_url_without_authentication(self) -> None:
 | 
				
			||||||
 | 
					        url = 'smtp://localhost:25'
 | 
				
			||||||
 | 
					        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(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)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user