mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-04-02 22:28:51 +00:00
Compare commits
1 Commits
feature-ma
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
376af81b9c |
@@ -1420,14 +1420,6 @@ ports.
|
|||||||
|
|
||||||
## Incoming Mail {#incoming_mail}
|
## Incoming Mail {#incoming_mail}
|
||||||
|
|
||||||
#### [`PAPERLESS_EMAIL_ALLOW_INTERNAL_HOSTS=<bool>`](#PAPERLESS_EMAIL_ALLOW_INTERNAL_HOSTS) {#PAPERLESS_EMAIL_ALLOW_INTERNAL_HOSTS}
|
|
||||||
|
|
||||||
: If set to false, incoming mail account connections are blocked when the
|
|
||||||
configured IMAP hostname resolves to a non-public address (for example,
|
|
||||||
localhost, link-local, or RFC1918 private ranges).
|
|
||||||
|
|
||||||
Defaults to true, which allows internal hosts.
|
|
||||||
|
|
||||||
### Email OAuth {#email_oauth}
|
### Email OAuth {#email_oauth}
|
||||||
|
|
||||||
#### [`PAPERLESS_OAUTH_CALLBACK_BASE_URL=<str>`](#PAPERLESS_OAUTH_CALLBACK_BASE_URL) {#PAPERLESS_OAUTH_CALLBACK_BASE_URL}
|
#### [`PAPERLESS_OAUTH_CALLBACK_BASE_URL=<str>`](#PAPERLESS_OAUTH_CALLBACK_BASE_URL) {#PAPERLESS_OAUTH_CALLBACK_BASE_URL}
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ from paperless.models import ApplicationConfiguration
|
|||||||
|
|
||||||
|
|
||||||
class TestViews(DirectoriesMixin, TestCase):
|
class TestViews(DirectoriesMixin, TestCase):
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls) -> None:
|
||||||
|
super().setUpTestData()
|
||||||
|
ApplicationConfiguration.objects.get_or_create()
|
||||||
|
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
self.user = User.objects.create_user("testuser")
|
self.user = User.objects.create_user("testuser")
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|||||||
@@ -497,10 +497,6 @@ SESSION_COOKIE_NAME = f"{COOKIE_PREFIX}sessionid"
|
|||||||
LANGUAGE_COOKIE_NAME = f"{COOKIE_PREFIX}django_language"
|
LANGUAGE_COOKIE_NAME = f"{COOKIE_PREFIX}django_language"
|
||||||
|
|
||||||
EMAIL_CERTIFICATE_FILE = get_path_from_env("PAPERLESS_EMAIL_CERTIFICATE_LOCATION")
|
EMAIL_CERTIFICATE_FILE = get_path_from_env("PAPERLESS_EMAIL_CERTIFICATE_LOCATION")
|
||||||
EMAIL_ALLOW_INTERNAL_HOSTS = get_bool_from_env(
|
|
||||||
"PAPERLESS_EMAIL_ALLOW_INTERNAL_HOSTS",
|
|
||||||
"true",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|||||||
@@ -39,8 +39,6 @@ from documents.loggers import LoggingMixin
|
|||||||
from documents.models import Correspondent
|
from documents.models import Correspondent
|
||||||
from documents.parsers import is_mime_type_supported
|
from documents.parsers import is_mime_type_supported
|
||||||
from documents.tasks import consume_file
|
from documents.tasks import consume_file
|
||||||
from paperless.network import is_public_ip
|
|
||||||
from paperless.network import resolve_hostname_ips
|
|
||||||
from paperless_mail.models import MailAccount
|
from paperless_mail.models import MailAccount
|
||||||
from paperless_mail.models import MailRule
|
from paperless_mail.models import MailRule
|
||||||
from paperless_mail.models import ProcessedMail
|
from paperless_mail.models import ProcessedMail
|
||||||
@@ -414,13 +412,6 @@ def get_mailbox(server, port, security) -> MailBox:
|
|||||||
"""
|
"""
|
||||||
Returns the correct MailBox instance for the given configuration.
|
Returns the correct MailBox instance for the given configuration.
|
||||||
"""
|
"""
|
||||||
if not settings.EMAIL_ALLOW_INTERNAL_HOSTS:
|
|
||||||
for ip_str in resolve_hostname_ips(server):
|
|
||||||
if not is_public_ip(ip_str):
|
|
||||||
raise MailError(
|
|
||||||
f"Connection blocked: {server} resolves to a non-public address",
|
|
||||||
)
|
|
||||||
|
|
||||||
ssl_context = ssl.create_default_context()
|
ssl_context = ssl.create_default_context()
|
||||||
if settings.EMAIL_CERTIFICATE_FILE is not None: # pragma: no cover
|
if settings.EMAIL_CERTIFICATE_FILE is not None: # pragma: no cover
|
||||||
ssl_context.load_verify_locations(cafile=settings.EMAIL_CERTIFICATE_FILE)
|
ssl_context.load_verify_locations(cafile=settings.EMAIL_CERTIFICATE_FILE)
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ from django.contrib.auth.models import User
|
|||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.db import DatabaseError
|
from django.db import DatabaseError
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test import override_settings
|
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from imap_tools import NOT
|
from imap_tools import NOT
|
||||||
from imap_tools import EmailAddress
|
from imap_tools import EmailAddress
|
||||||
@@ -1847,25 +1846,6 @@ class TestMailAccountTestView(APITestCase):
|
|||||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
self.assertEqual(response.content.decode(), "Unable to connect to server")
|
self.assertEqual(response.content.decode(), "Unable to connect to server")
|
||||||
|
|
||||||
@override_settings(EMAIL_ALLOW_INTERNAL_HOSTS=False)
|
|
||||||
@mock.patch("paperless_mail.mail.resolve_hostname_ips", return_value=["127.0.0.1"])
|
|
||||||
def test_mail_account_test_view_blocks_internal_host_when_disabled(
|
|
||||||
self,
|
|
||||||
_mock_resolve_hostname_ips,
|
|
||||||
) -> None:
|
|
||||||
data = {
|
|
||||||
"imap_server": "internal.example",
|
|
||||||
"imap_port": 993,
|
|
||||||
"imap_security": MailAccount.ImapSecurity.SSL,
|
|
||||||
"username": "admin",
|
|
||||||
"password": "secret",
|
|
||||||
"account_type": MailAccount.MailAccountType.IMAP,
|
|
||||||
"is_token": False,
|
|
||||||
}
|
|
||||||
response = self.client.post(self.url, data, format="json")
|
|
||||||
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
|
|
||||||
self.assertEqual(response.content.decode(), "Unable to connect to server")
|
|
||||||
|
|
||||||
@mock.patch(
|
@mock.patch(
|
||||||
"paperless_mail.oauth.PaperlessMailOAuth2Manager.refresh_account_oauth_token",
|
"paperless_mail.oauth.PaperlessMailOAuth2Manager.refresh_account_oauth_token",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -120,12 +120,12 @@ class MailAccountViewSet(ModelViewSet, PassUserMixin):
|
|||||||
serializer.validated_data["expiration"] = existing_account.expiration
|
serializer.validated_data["expiration"] = existing_account.expiration
|
||||||
|
|
||||||
account = MailAccount(**serializer.validated_data)
|
account = MailAccount(**serializer.validated_data)
|
||||||
try:
|
with get_mailbox(
|
||||||
with get_mailbox(
|
account.imap_server,
|
||||||
account.imap_server,
|
account.imap_port,
|
||||||
account.imap_port,
|
account.imap_security,
|
||||||
account.imap_security,
|
) as M:
|
||||||
) as M:
|
try:
|
||||||
if (
|
if (
|
||||||
existing_account is not None
|
existing_account is not None
|
||||||
and account.is_token
|
and account.is_token
|
||||||
@@ -145,11 +145,11 @@ class MailAccountViewSet(ModelViewSet, PassUserMixin):
|
|||||||
|
|
||||||
mailbox_login(M, account)
|
mailbox_login(M, account)
|
||||||
return Response({"success": True})
|
return Response({"success": True})
|
||||||
except MailError:
|
except MailError:
|
||||||
logger.error(
|
logger.error(
|
||||||
"Mail account connectivity test failed",
|
"Mail account connectivity test failed",
|
||||||
)
|
)
|
||||||
return HttpResponseBadRequest("Unable to connect to server")
|
return HttpResponseBadRequest("Unable to connect to server")
|
||||||
|
|
||||||
@action(methods=["post"], detail=True)
|
@action(methods=["post"], detail=True)
|
||||||
def process(self, request, pk=None):
|
def process(self, request, pk=None):
|
||||||
|
|||||||
Reference in New Issue
Block a user