mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
Added support for a shared secret in email
This commit is contained in:
parent
3b5d4cdd39
commit
6b0a537bff
@ -90,13 +90,16 @@ So, with all that in mind, here's what you do to get it running:
|
|||||||
folder in an existing email box and note the path to that folder.
|
folder in an existing email box and note the path to that folder.
|
||||||
2. In ``settings.py`` set all of the appropriate values in ``MAIL_CONSUMPTION``.
|
2. In ``settings.py`` set all of the appropriate values in ``MAIL_CONSUMPTION``.
|
||||||
If you decided to use a subfolder of an existing account, then make sure you
|
If you decided to use a subfolder of an existing account, then make sure you
|
||||||
set ``INBOX`` accordingly here.
|
set ``INBOX`` accordingly here. You also have to set the
|
||||||
|
``UPLOAD_SHARED_SECRET`` to something you can remember 'cause you'll have to
|
||||||
|
include that in every email you send.
|
||||||
3. Restart the :ref:`consumer <utilities-consumer>`. The consumer will check
|
3. Restart the :ref:`consumer <utilities-consumer>`. The consumer will check
|
||||||
the configured email account every 10 minutes for something new and pull down
|
the configured email account every 10 minutes for something new and pull down
|
||||||
whatever it finds.
|
whatever it finds.
|
||||||
4. Send yourself an email! Note that the subject is treated as the file name,
|
4. Send yourself an email! Note that the subject is treated as the file name,
|
||||||
so if you set the subject to ``Sender - Title - tag,tag,tag``, you'll get
|
so if you set the subject to ``Sender - Title - tag,tag,tag``, you'll get
|
||||||
what you expect.
|
what you expect. Also, you must include the aforementioned secret string in
|
||||||
|
every email so the fetcher knows that it's safe to import.
|
||||||
5. After a few minutes, the consumer will poll your mailbox, pull down the
|
5. After a few minutes, the consumer will poll your mailbox, pull down the
|
||||||
message, and place the attachment in the consumption directory with the
|
message, and place the attachment in the consumption directory with the
|
||||||
appropriate name. A few minutes later, the consumer will import it like any
|
appropriate name. A few minutes later, the consumer will import it like any
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import datetime
|
import datetime
|
||||||
import email
|
|
||||||
import imaplib
|
import imaplib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
from email import policy
|
||||||
|
from email.parser import BytesParser
|
||||||
from dateutil import parser
|
from dateutil import parser
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
@ -29,14 +30,7 @@ class Message(Renderable):
|
|||||||
and n attachments, and that we don't care about the message body.
|
and n attachments, and that we don't care about the message body.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _set_time(self, message):
|
SECRET = settings.UPLOAD_SHARED_SECRET
|
||||||
self.time = datetime.datetime.now()
|
|
||||||
message_time = message.get("Date")
|
|
||||||
if message_time:
|
|
||||||
try:
|
|
||||||
self.time = parser.parse(message_time)
|
|
||||||
except (ValueError, AttributeError):
|
|
||||||
pass # We assume that "now" is ok
|
|
||||||
|
|
||||||
def __init__(self, data, verbosity=1):
|
def __init__(self, data, verbosity=1):
|
||||||
"""
|
"""
|
||||||
@ -50,17 +44,15 @@ class Message(Renderable):
|
|||||||
self.time = None
|
self.time = None
|
||||||
self.attachment = None
|
self.attachment = None
|
||||||
|
|
||||||
message = email.message_from_bytes(data)
|
message = BytesParser(policy=policy.default).parsebytes(data)
|
||||||
self.subject = message.get("Subject").replace("\r\n", "")
|
self.subject = str(message["Subject"]).replace("\r\n", "")
|
||||||
|
self.body = str(message.get_body())
|
||||||
|
|
||||||
|
self.check_subject()
|
||||||
|
self.check_body()
|
||||||
|
|
||||||
self._set_time(message)
|
self._set_time(message)
|
||||||
|
|
||||||
if self.subject is None:
|
|
||||||
raise InvalidMessageError("Message does not have a subject")
|
|
||||||
if not Sender.SAFE_REGEX.match(self.subject):
|
|
||||||
raise InvalidMessageError("Message subject is unsafe: {}".format(
|
|
||||||
self.subject))
|
|
||||||
|
|
||||||
self._render('Fetching email: "{}"'.format(self.subject), 1)
|
self._render('Fetching email: "{}"'.format(self.subject), 1)
|
||||||
|
|
||||||
attachments = []
|
attachments = []
|
||||||
@ -94,6 +86,26 @@ class Message(Renderable):
|
|||||||
def __bool__(self):
|
def __bool__(self):
|
||||||
return bool(self.attachment)
|
return bool(self.attachment)
|
||||||
|
|
||||||
|
def check_subject(self):
|
||||||
|
if self.subject is None:
|
||||||
|
raise InvalidMessageError("Message does not have a subject")
|
||||||
|
if not Sender.SAFE_REGEX.match(self.subject):
|
||||||
|
raise InvalidMessageError("Message subject is unsafe: {}".format(
|
||||||
|
self.subject))
|
||||||
|
|
||||||
|
def check_body(self):
|
||||||
|
if self.SECRET not in self.body:
|
||||||
|
raise InvalidMessageError("The secret wasn't in the body")
|
||||||
|
|
||||||
|
def _set_time(self, message):
|
||||||
|
self.time = datetime.datetime.now()
|
||||||
|
message_time = message.get("Date")
|
||||||
|
if message_time:
|
||||||
|
try:
|
||||||
|
self.time = parser.parse(message_time)
|
||||||
|
except (ValueError, AttributeError):
|
||||||
|
pass # We assume that "now" is ok
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def file_name(self):
|
def file_name(self):
|
||||||
return "{}.{}".format(self.subject, self.attachment.suffix)
|
return "{}.{}".format(self.subject, self.attachment.suffix)
|
||||||
|
@ -38,7 +38,7 @@ This is a multi-part message in MIME format.
|
|||||||
Content-Type: text/plain; charset=utf-8
|
Content-Type: text/plain; charset=utf-8
|
||||||
Content-Transfer-Encoding: 7bit
|
Content-Transfer-Encoding: 7bit
|
||||||
|
|
||||||
This is the test body.
|
The secret word is "paperless" :-)
|
||||||
|
|
||||||
--------------090701020702030809070008
|
--------------090701020702030809070008
|
||||||
Content-Type: application/pdf;
|
Content-Type: application/pdf;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user