2016-06-01 12:57:48 -07:00
|
|
|
import datetime
|
2013-07-26 20:15:39 -07:00
|
|
|
import email.header
|
|
|
|
|
import logging
|
2016-05-14 22:06:32 -07:00
|
|
|
import os
|
2013-07-26 20:15:39 -07:00
|
|
|
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
2016-05-14 22:06:32 -07:00
|
|
|
def get_settings():
|
|
|
|
|
return {
|
2021-02-03 23:05:48 -05:00
|
|
|
"strip_unallowed_mimetypes": getattr(
|
|
|
|
|
settings, "DJANGO_MAILBOX_STRIP_UNALLOWED_MIMETYPES", False
|
2016-05-14 22:06:32 -07:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"allowed_mimetypes": getattr(
|
|
|
|
|
settings, "DJANGO_MAILBOX_ALLOWED_MIMETYPES", ["text/plain", "text/html"]
|
2016-05-14 22:06:32 -07:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"text_stored_mimetypes": getattr(
|
2016-05-14 22:06:32 -07:00
|
|
|
settings,
|
2021-02-03 23:05:48 -05:00
|
|
|
"DJANGO_MAILBOX_TEXT_STORED_MIMETYPES",
|
|
|
|
|
["text/plain", "text/html"],
|
2016-05-14 22:06:32 -07:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"altered_message_header": getattr(
|
2016-05-14 22:06:32 -07:00
|
|
|
settings,
|
2021-02-03 23:05:48 -05:00
|
|
|
"DJANGO_MAILBOX_ALTERED_MESSAGE_HEADER",
|
|
|
|
|
"X-Django-Mailbox-Altered-Message",
|
2016-05-14 22:06:32 -07:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"attachment_interpolation_header": getattr(
|
2016-05-14 22:06:32 -07:00
|
|
|
settings,
|
2021-02-03 23:05:48 -05:00
|
|
|
"DJANGO_MAILBOX_ATTACHMENT_INTERPOLATION_HEADER",
|
|
|
|
|
"X-Django-Mailbox-Interpolate-Attachment",
|
2016-05-14 22:06:32 -07:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"attachment_upload_to": getattr(
|
2016-05-14 22:06:32 -07:00
|
|
|
settings,
|
2021-02-03 23:05:48 -05:00
|
|
|
"DJANGO_MAILBOX_ATTACHMENT_UPLOAD_TO",
|
|
|
|
|
"mailbox_attachments/%Y/%m/%d/",
|
2016-05-14 22:06:32 -07:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"store_original_message": getattr(
|
|
|
|
|
settings, "DJANGO_MAILBOX_STORE_ORIGINAL_MESSAGE", False
|
2016-05-14 22:06:32 -07:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"compress_original_message": getattr(
|
|
|
|
|
settings, "DJANGO_MAILBOX_COMPRESS_ORIGINAL_MESSAGE", False
|
2017-07-09 20:36:37 +02:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"original_message_compression": getattr(
|
|
|
|
|
settings, "DJANGO_MAILBOX_ORIGINAL_MESSAGE_COMPRESSION", 6
|
2017-07-09 20:36:37 +02:00
|
|
|
),
|
2021-02-03 23:05:48 -05:00
|
|
|
"default_charset": getattr(
|
2016-05-14 22:06:32 -07:00
|
|
|
settings,
|
2021-02-03 23:05:48 -05:00
|
|
|
"DJANGO_MAILBOX_default_charset",
|
|
|
|
|
"iso8859-1",
|
|
|
|
|
),
|
2016-05-14 22:06:32 -07:00
|
|
|
}
|
2013-07-26 20:15:39 -07:00
|
|
|
|
|
|
|
|
|
2014-04-22 15:49:49 -07:00
|
|
|
def convert_header_to_unicode(header):
|
2021-02-03 23:05:48 -05:00
|
|
|
default_charset = get_settings()["default_charset"]
|
2016-05-14 22:06:32 -07:00
|
|
|
|
2014-04-22 17:06:17 -07:00
|
|
|
def _decode(value, encoding):
|
2019-10-15 05:31:13 +02:00
|
|
|
if isinstance(value, str):
|
2014-04-22 17:06:17 -07:00
|
|
|
return value
|
2021-02-03 23:05:48 -05:00
|
|
|
if not encoding or encoding == "unknown-8bit":
|
2016-05-14 22:06:32 -07:00
|
|
|
encoding = default_charset
|
2021-02-03 23:05:48 -05:00
|
|
|
return value.decode(encoding, "replace")
|
2014-04-22 17:06:17 -07:00
|
|
|
|
2013-07-26 20:15:39 -07:00
|
|
|
try:
|
2021-02-03 23:05:48 -05:00
|
|
|
return "".join(
|
2013-07-26 20:15:39 -07:00
|
|
|
[
|
2021-02-03 23:05:48 -05:00
|
|
|
(_decode(bytestr, encoding))
|
|
|
|
|
for bytestr, encoding in email.header.decode_header(header)
|
2013-07-26 20:15:39 -07:00
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
except UnicodeDecodeError:
|
|
|
|
|
logger.exception(
|
2021-02-03 23:05:48 -05:00
|
|
|
"Errors encountered decoding header %s into encoding %s.",
|
2013-07-26 20:15:39 -07:00
|
|
|
header,
|
2016-05-14 22:06:32 -07:00
|
|
|
default_charset,
|
2013-07-26 20:15:39 -07:00
|
|
|
)
|
2021-02-03 23:05:48 -05:00
|
|
|
return header.decode(default_charset, "replace")
|
2014-09-01 15:31:13 -03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_body_from_message(message, maintype, subtype):
|
|
|
|
|
"""
|
|
|
|
|
Fetchs the body message matching main/sub content type.
|
|
|
|
|
"""
|
2021-02-03 23:05:48 -05:00
|
|
|
body = ""
|
2014-09-01 15:31:13 -03:00
|
|
|
for part in message.walk():
|
2021-02-03 23:05:48 -05:00
|
|
|
if part.get("content-disposition", "").startswith("attachment;"):
|
2018-02-09 09:13:39 +01:00
|
|
|
continue
|
2021-02-03 23:05:48 -05:00
|
|
|
if (
|
|
|
|
|
part.get_content_maintype() == maintype
|
|
|
|
|
and part.get_content_subtype() == subtype
|
|
|
|
|
):
|
2014-09-01 15:31:13 -03:00
|
|
|
charset = part.get_content_charset()
|
|
|
|
|
this_part = part.get_payload(decode=True)
|
|
|
|
|
if charset:
|
2014-11-15 22:15:25 -08:00
|
|
|
try:
|
2021-02-03 23:05:48 -05:00
|
|
|
this_part = this_part.decode(charset, "replace")
|
2014-11-15 22:15:25 -08:00
|
|
|
except LookupError:
|
2021-02-03 23:05:48 -05:00
|
|
|
this_part = this_part.decode("ascii", "replace")
|
2014-11-15 22:15:25 -08:00
|
|
|
logger.warning(
|
2021-02-03 23:05:48 -05:00
|
|
|
"Unknown encoding %s encountered while decoding "
|
|
|
|
|
"text payload. Interpreting as ASCII with "
|
|
|
|
|
"replacement, but some data may not be "
|
|
|
|
|
"represented as the sender intended.",
|
|
|
|
|
charset,
|
2014-11-15 22:15:25 -08:00
|
|
|
)
|
|
|
|
|
except ValueError:
|
2021-02-03 23:05:48 -05:00
|
|
|
this_part = this_part.decode("ascii", "replace")
|
2014-11-15 22:15:25 -08:00
|
|
|
logger.warning(
|
2021-02-03 23:05:48 -05:00
|
|
|
"Error encountered while decoding text "
|
|
|
|
|
"payload from an incorrectly-constructed "
|
|
|
|
|
"e-mail; payload was converted to ASCII with "
|
|
|
|
|
"replacement, but some data may not be "
|
|
|
|
|
"represented as the sender intended."
|
2014-11-15 22:15:25 -08:00
|
|
|
)
|
|
|
|
|
else:
|
2021-02-03 23:05:48 -05:00
|
|
|
this_part = this_part.decode("ascii", "replace")
|
2014-09-01 15:31:13 -03:00
|
|
|
|
2014-11-15 22:15:25 -08:00
|
|
|
body += this_part
|
2014-09-01 15:31:13 -03:00
|
|
|
|
|
|
|
|
return body
|
2016-05-14 22:06:32 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_attachment_save_path(instance, filename):
|
|
|
|
|
settings = get_settings()
|
|
|
|
|
|
2021-02-03 23:05:48 -05:00
|
|
|
path = settings["attachment_upload_to"]
|
|
|
|
|
if "%" in path:
|
2016-06-01 12:57:48 -07:00
|
|
|
path = datetime.datetime.utcnow().strftime(path)
|
|
|
|
|
|
2016-05-14 22:06:32 -07:00
|
|
|
return os.path.join(
|
2016-06-01 12:57:48 -07:00
|
|
|
path,
|
2016-05-14 22:06:32 -07:00
|
|
|
filename,
|
|
|
|
|
)
|