Added tests

This commit is contained in:
Antoine Nguyen
2025-05-02 16:49:46 +02:00
parent 6a0a028ade
commit 7a36a5ae1b
5 changed files with 500 additions and 1 deletions
View File
+125
View File
@@ -0,0 +1,125 @@
# flake8: noqa
"""Tests data."""
BODYSTRUCTURE_SAMPLE_1 = [
b"36 (FLAGS (\\Seen))",
b'36 (UID 36 BODYSTRUCTURE (("text" "plain" ("charset" "UTF-8") NIL NIL "QUOTED-PRINTABLE" 959 29 NIL ("inline" NIL) NIL NIL)("text" "html" ("charset" "UTF-8") NIL NIL "QUOTED-PRINTABLE" 14695 322 NIL ("inline" NIL) NIL NIL) "alternative" ("boundary" "----=_Part_2437867_661044267.1501268072105") NIL NIL NIL))',
]
BODYSTRUCTURE_SAMPLE_2 = [
(
b'19 (UID 19 FLAGS (\\Seen $label4 user_flag-1) BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1" "format" "flowed") NIL NIL "7bit" 2 1 NIL NIL NIL NIL)("message" "rfc822" ("name*" "ISO-8859-1\'\'%5B%49%4E%53%43%52%49%50%54%49%4F%4E%5D%20%52%E9%63%E9%70%74%69%6F%6E%20%64%65%20%76%6F%74%72%65%20%64%6F%73%73%69%65%72%20%64%27%69%6E%73%63%72%69%70%74%69%6F%6E%20%46%72%65%65%20%48%61%75%74%20%44%E9%62%69%74") NIL NIL "8bit" 3632 ("Wed, 13 Dec 2006 20:30:02 +0100" {70}',
b"[INSCRIPTION] R\xe9c\xe9ption de votre dossier d'inscription Free Haut D\xe9bit",
),
(
b' (("Free Haut Debit" NIL "inscription" "freetelecom.fr")) (("Free Haut Debit" NIL "inscription" "freetelecom.fr")) ((NIL NIL "hautdebit" "freetelecom.fr")) ((NIL NIL "nguyen.antoine" "wanadoo.fr")) NIL NIL NIL "<20061213193125.9DA0919AC@dgroup2-2.proxad.net>") ("text" "plain" ("charset" "iso-8859-1") NIL NIL "8bit" 1428 38 NIL ("inline" NIL) NIL NIL) 76 NIL ("inline" ("filename*" "ISO-8859-1\'\'%5B%49%4E%53%43%52%49%50%54%49%4F%4E%5D%20%52%E9%63%E9%70%74%69%6F%6E%20%64%65%20%76%6F%74%72%65%20%64%6F%73%73%69%65%72%20%64%27%69%6E%73%63%72%69%70%74%69%6F%6E%20%46%72%65%65%20%48%61%75%74%20%44%E9%62%69%74")) NIL NIL) "mixed" ("boundary" "------------040706080908000209030901") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {266}',
b"Date: Tue, 19 Dec 2006 19:50:13 +0100\r\nFrom: Antoine Nguyen <nguyen.antoine@wanadoo.fr>\r\nTo: Antoine Nguyen <tonio@koalabs.org>\r\nSubject: [Fwd: [INSCRIPTION] =?ISO-8859-1?Q?R=E9c=E9ption_de_votre_?=\r\n =?ISO-8859-1?Q?dossier_d=27inscription_Free_Haut_D=E9bit=5D?=\r\n\r\n",
),
b")",
]
BODYSTRUCTURE_SAMPLE_3 = [
(
b'58 (UID 123753 BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 90 10 NIL NIL NIL NIL)("text" "html" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 1034 33 NIL NIL NIL NIL) "alternative" ("boundary" "_000_HE1PR10MB1642F2B8BA7FF8EAC0FC7AECD86E0HE1PR10MB1642EURP_") NIL NIL NIL)("application" "pdf" ("name" "=?iso-8859-1?Q?CV=5FAude=5FGIRODON=5FNGUYEN=5Fao=FBt2017_g=E9n=E9rique.pd?= =?iso-8859-1?Q?f?=") NIL {95}',
"=?iso-8859-1?Q?CV=5FAude=5FGIRODON=5FNGUYEN=5Fao=FBt2017_g=E9n=E9rique.pd?=\n =?iso-8859-1?Q?f?=",
),
b' "base64" 94130 NIL ("attachment" ("filename" "=?iso-8859-1?Q?CV=5FAude=5FGIRODON=5FNGUYEN=5Fao=FBt2017_g=E9n=E9rique.pd?= =?iso-8859-1?Q?f?=" "size" "68787" "creation-date" "Wed, 13 Sep 2017 08:50:03 GMT" "modification-date" "Wed, 13 Sep 2017 08:50:03 GMT")) NIL NIL) "mixed" ("boundary" "_004_HE1PR10MB1642F2B8BA7FF8EAC0FC7AECD86E0HE1PR10MB1642EURP_") NIL ("fr-FR") NIL))',
]
BODYSTRUCTURE_4 = b'BODYSTRUCTURE ((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 886 32 NIL NIL NIL NIL)("text" "html" ("charset" "us-ascii") NIL NIL "quoted-printable" 1208 16 NIL NIL NIL NIL) "alternative" ("boundary" "----=_NextPart_001_0003_01CCC564.B2F64FF0") NIL NIL NIL)("application" "octet-stream" ("name" "Carte Verte_2.pdf") NIL NIL "base64" 285610 NIL ("attachment" ("filename" "Carte Verte_2.pdf")) NIL NIL) "mixed" ("boundary" "----=_NextPart_000_0002_01CCC564.B2F64FF0") NIL NIL NIL)'
BODYSTRUCTURE_SAMPLE_4 = [
(
b"855 (UID 46931 "
+ BODYSTRUCTURE_4
+ b" BODY[HEADER.FIELDS (FROM TO CC DATE SUBJECT REPLY-TO MESSAGE-ID)] {235}",
b"From: <Service.client10@maaf.fr>\r\nTo: <TONIO@NGYN.ORG>\r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\nMessage-ID: <CABY0dkJspTaFn7v-1OG1nc9M0Qxn+VUTpcXzxyGNBnSnZtqMrw@mail.gmail.com>\r\n\r\n",
),
b")",
]
BODYSTRUCTURE_ONLY_4 = [(b"855 (UID 46931 " + BODYSTRUCTURE_4), ")"]
BODYSTRUCTURE_ONLY_5 = [(b"855 (UID 46932 " + BODYSTRUCTURE_4), ")"]
BODY_PLAIN_4 = [
(b"855 (UID 46931 BODY[1.1] {25}", b"This is a test message.\r\n"),
b")",
]
BODYSTRUCTURE_SAMPLE_5 = [
(
b'856 (UID 46936 BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 724 22 NIL NIL NIL NIL)("text" "html" ("charset" "ISO-8859-1") NIL NIL "quoted-printable" 2662 48 NIL NIL NIL NIL) "alternative" ("boundary" "----=_Part_1326887_254624357.1325083973970") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {258}',
"Date: Wed, 28 Dec 2011 15:52:53 +0100 (CET)\r\nFrom: =?ISO-8859-1?Q?Malakoff_M=E9d=E9ric?= <communication@communication.malakoffmederic.com>\r\nTo: Antoine Nguyen <tonio@ngyn.org>\r\nSubject: =?ISO-8859-1?Q?Votre_inscription_au_grand_Jeu_Malakoff_M=E9d=E9ric?=\r\n\r\n",
),
b")",
]
BODYSTRUCTURE_SAMPLE_6 = [
(
b'123 (UID 3 BODYSTRUCTURE (((("text" "plain" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 1266 30 NIL NIL NIL NIL)("text" "html" ("charset" "iso-8859-1") NIL NIL "quoted-printable" 8830 227 NIL NIL NIL NIL) "alternative" ("boundary" "_000_152AC7ECD1F8AB43A9AD95DBDDCA3118082C09GKIMA24cmcicfr_") NIL NIL NIL)("image" "png" ("name" "image005.png") "<image005.png@01CC6CAA.4FADC490>" "image005.png" "base64" 7464 NIL ("inline" ("filename" "image005.png" "size" "5453" "creation-date" "Tue, 06 Sep 2011 13:33:49 GMT" "modification-date" "Tue, 06 Sep 2011 13:33:49 GMT")) NIL NIL)("image" "jpeg" ("name" "image006.jpg") "<image006.jpg@01CC6CAA.4FADC490>" "image006.jpg" "base64" 2492 NIL ("inline" ("filename" "image006.jpg" "size" "1819" "creation-date" "Tue, 06 Sep 2011 13:33:49 GMT" "modification-date" "Tue, 06 Sep 2011 13:33:49 GMT")) NIL NIL) "related" ("boundary" "_006_152AC7ECD1F8AB43A9AD95DBDDCA3118082C09GKIMA24cmcicfr_" "type" "multipart/alternative") NIL NIL NIL)("application" "pdf" ("name" "bilan assurance CIC.PDF") NIL "bilan assurance CIC.PDF" "base64" 459532 NIL ("attachment" ("filename" "bilan assurance CIC.PDF" "size" "335811" "creation-date" "Fri, 16 Sep 2011 12:45:23 GMT" "modification-date" "Fri, 16 Sep 2011 12:45:23 GMT")) NIL NIL)(("text" "plain" ("charset" "utf-8") NIL NIL "quoted-printable" 1389 29 NIL NIL NIL NIL)("text" "html" ("charset" "utf-8") NIL NIL "quoted-printable" 1457 27 NIL NIL NIL NIL) "alternative" ("boundary" "===============0775904800==") ("inline" NIL) NIL NIL) "mixed" ("boundary" "_007_152AC7ECD1F8AB43A9AD95DBDDCA3118082C09GKIMA24cmcicfr_") NIL ("fr-FR") NIL)',
),
b")",
]
BODYSTRUCTURE_SAMPLE_7 = [
(
b'856 (UID 11111 BODYSTRUCTURE ((("text" "plain" ("charset" "UTF-8") NIL NIL "7bit" 0 0 NIL NIL NIL NIL) "mixed" ("boundary" "----=_Part_407172_3159001.1321948277321") NIL NIL NIL)("application" "octet-stream" ("name" "26274308.pdf") NIL NIL "base64" 14906 NIL ("attachment" ("filename" "(26274308.pdf")) NIL NIL) "mixed" ("boundary" "----=_Part_407171_9686991.1321948277321") NIL NIL NIL)',
),
b")",
]
BODYSTRUCTURE_SAMPLE_8 = [
(
b'1 (UID 947 BODYSTRUCTURE ("text" "html" ("charset" "utf-8") NIL NIL "8bit" 889 34 NIL NIL NIL NIL) BODY[HEADER.FIELDS (FROM TO CC DATE SUBJECT)] {80}',
"From: Antoine Nguyen <tonio@ngyn.org>\r\nDate: Sat, 26 Mar 2016 11:45:49 +0100\r\n\r\n",
),
b")",
]
BODYSTRUCTURE_SAMPLE_9 = [
(
b"855 (UID 46932 "
+ BODYSTRUCTURE_4
+ b" BODY[HEADER.FIELDS (FROM TO CC DATE SUBJECT)] {235}",
b"From: <Service.client10@maaf.fr>\r\nTo: <TONIO@NGYN.ORG>\r\nCc: \r\nSubject: Notre contact du 28/12/2011 - 192175092\r\nDate: Wed, 28 Dec 2011 13:29:17 +0100\r\nMessage-ID: <CABY0dkJspTaFn7v-1OG1nc9M0Qxn+VUTpcXzxyGNBnSnZtqMrw@mail.gmail.com>\r\n\r\n",
),
b")",
]
BODYSTRUCTURE_SAMPLE_10 = [
(
b"855 (UID 46932 " + BODYSTRUCTURE_4 + b" BODY[1.1] {10})",
b"XXXXXXXX\r\n",
b"BODY[2] {10}",
b"XXXXXXXX\r\n",
b")",
)
]
BODYSTRUCTURE_SAMPLE_WITH_FLAGS = [
(
b'19 (UID 19 FLAGS (\\Seen) RFC822.SIZE 100000 BODYSTRUCTURE (("text" "plain" ("charset" "ISO-8859-1" "format" "flowed") NIL NIL "7bit" 2 1 NIL NIL NIL NIL)("message" "rfc822" ("name*" "ISO-8859-1\'\'%5B%49%4E%53%43%52%49%50%54%49%4F%4E%5D%20%52%E9%63%E9%70%74%69%6F%6E%20%64%65%20%76%6F%74%72%65%20%64%6F%73%73%69%65%72%20%64%27%69%6E%73%63%72%69%70%74%69%6F%6E%20%46%72%65%65%20%48%61%75%74%20%44%E9%62%69%74") NIL NIL "8bit" 3632 ("Wed, 13 Dec 2006 20:30:02 +0100" {70}', # noqa
b"[INSCRIPTION] R\xe9c\xe9ption de votre dossier d'inscription Free Haut D\xe9bit",
), # noqa
(
b' (("Free Haut Debit" NIL "inscription" "freetelecom.fr")) (("Free Haut Debit" NIL "inscription" "freetelecom.fr")) ((NIL NIL "hautdebit" "freetelecom.fr")) ((NIL NIL "nguyen.antoine" "wanadoo.fr")) NIL NIL NIL "<20061213193125.9DA0919AC@dgroup2-2.proxad.net>") ("text" "plain" ("charset" "iso-8859-1") NIL NIL "8bit" 1428 38 NIL ("inline" NIL) NIL NIL) 76 NIL ("inline" ("filename*" "ISO-8859-1\'\'%5B%49%4E%53%43%52%49%50%54%49%4F%4E%5D%20%52%E9%63%E9%70%74%69%6F%6E%20%64%65%20%76%6F%74%72%65%20%64%6F%73%73%69%65%72%20%64%27%69%6E%73%63%72%69%70%74%69%6F%6E%20%46%72%65%65%20%48%61%75%74%20%44%E9%62%69%74")) NIL NIL) "mixed" ("boundary" "------------040706080908000209030901") NIL NIL NIL) BODY[HEADER.FIELDS (DATE FROM TO CC SUBJECT)] {266}', # noqa
b"Date: Tue, 19 Dec 2006 19:50:13 +0100\r\nFrom: Antoine Nguyen <nguyen.antoine@wanadoo.fr>\r\nTo: Antoine Nguyen <tonio@koalabs.org>\r\nSubject: [Fwd: [INSCRIPTION] =?ISO-8859-1?Q?R=E9c=E9ption_de_votre_?=\r\n =?ISO-8859-1?Q?dossier_d=27inscription_Free_Haut_D=E9bit=5D?=\r\n\r\n",
),
b")",
]
BODYSTRUCTURE_EMPTY_MAIL = [
b'33 (UID 33 BODYSTRUCTURE (("text" "plain" ("charset" "us-ascii") NIL NIL "quoted-printable" 0 0 NIL NIL NIL NIL)("application" "zip" ("name" "hotmail.com!ngyn.org!1435428000!1435514400.zip") NIL NIL "base64" 978 NIL ("attachment" ("filename" "hotmail.com!ngyn.org!1435428000!1435514400.zip")) NIL NIL) "mixed" ("boundary" "--boundary_32281_b52cf564-2a50-4f96-aeb0-ef5f83b05463") NIL NIL NIL))'
]
EMPTY_BODY = [(b"33 (UID 33 BODY[1] {0}", b""), b")"]
COMPLETE_MAIL = [
(
b"109 (UID 133872 BODY[] {2504}",
b"Return-Path: <test1@test.org>\r\nDelivered-To: test1@test.org\r\nReceived: from mail.testsrv.org\r\n\tby nelson.ngyn.org (Dovecot) with LMTP id E9jPFPHHe1u1bQAABvoInA\r\n\tfor <test1@test.org>; Tue, 21 Aug 2018 10:06:09 +0200\r\nReceived: from [192.168.0.12] (unknown [109.9.172.169])\r\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\r\n\t(No client certificate requested)\r\n\tby mail.testsrv.org (Postfix) with ESMTPSA id 2B279E00D2\r\n\tfor <test1@test.org>; Tue, 21 Aug 2018 10:06:09 +0200 (CEST)\r\nDKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=test.org; s=test;\r\n\tt=1534838769; h=from:from:sender:reply-to:subject:subject:date:date:\r\n\t message-id:message-id:to:to:cc:mime-version:mime-version:\r\n\t content-type:content-type:\r\n\t content-transfer-encoding:content-transfer-encoding:in-reply-to:\r\n\t references; bh=EVfAHeUMDygbJe0SkMWJHjgXGjtiTLZnMQbyWqzsrCY=;\r\n\tb=fRc4i+WbPkbdD1BNfV9TqsZZ9nTbnHn6CKbH4nwrQnmUYQvvFUcpXC8PBURyglyLBAqPKb\r\n\tF6Dq7TnvcYdkIpR0XyMko+XB/qt8Wj0J0tC8bFxfknN8yNqj32SQAjtLrsjtzEgC1LkcLo\r\n\tcXU+FQbZR0D8EL7YD/nnsbO4mYnf3as=\r\nTo: Antoine Nguyen <test1@test.org>\r\nFrom: Antoine Nguyen <test1@test.org>\r\nSubject: Simple message\r\nMessage-ID: <7ed6e950-9e2b-b0fc-9e66-5b8358453b8d@test.org>\r\nDate: Tue, 21 Aug 2018 10:06:08 +0200\r\nUser-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\r\n Thunderbird/52.9.1\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Transfer-Encoding: 7bit\r\nContent-Language: fr-FR\r\nARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=test.org;\r\n\ts=test; t=1534838769; h=from:from:sender:reply-to:subject:subject:date:date:\r\n\t message-id:message-id:to:to:cc:mime-version:mime-version:\r\n\t content-type:content-type:\r\n\t content-transfer-encoding:content-transfer-encoding:in-reply-to:\r\n\t references; bh=EVfAHeUMDygbJe0SkMWJHjgXGjtiTLZnMQbyWqzsrCY=;\r\n\tb=ZV1ndumHftEnhq8Z7zujDS9WUlpJmjrTIEzXsIy8+1HhZ6AEcmur5r8SmS/xfUvpoScNvF\r\n\tlYAHIdbKPX54Fpq7rZVgIhuy8vfcRGprHxH9DMhk3kHiuZLsJT1F6UdPwTYSGAWBTbg1u2\r\n\tHu2VoeSYBV5PrsINvPr1QCbo+GqTlJU=\r\nARC-Seal: i=1; s=test; d=test.org; t=1534838769; a=rsa-sha256; cv=none;\r\n\tb=CE7Q0SnkLMHx82eOtanv4pCtl3fhaPqOAYb3Nqxi5lqwDcO80vTMfGUwOv6r3Exv9Cnj3+nCxejzXtrO4TTKesL9bamOBf+veRYTLfy8wjRIfgEVXS/amOjf9u4UzGgwxL1HbhHWbCIqJhaVwrPZaHZwA9XPmboqGVQNP3i2nH0=\r\nARC-Authentication-Results: i=1; ORIGINATING;\r\n\tauth=pass smtp.auth=test1@test.org smtp.mailfrom=test1@test.org\r\nAuthentication-Results: ORIGINATING;\r\n\tauth=pass smtp.auth=test1@test.org smtp.mailfrom=test1@test.org\r\n\r\nHello!\r\n\r\n",
),
b")",
]
+112
View File
@@ -0,0 +1,112 @@
"""FETCH parser tests."""
import io
import unittest
from modoboa.webmail.lib.fetch_parser import FetchResponseParser
from . import data
def dump_bodystructure(fp, bs, depth=0):
"""Dump a parsed BODYSTRUCTURE."""
indentation = " " * (depth * 4)
for mp in bs:
if isinstance(mp, list):
if isinstance(mp[0], list):
print(f"{indentation}multipart/{mp[1]}", file=fp)
dump_bodystructure(fp, mp, depth + 1)
else:
dump_bodystructure(fp, mp, depth)
elif isinstance(mp, dict):
if isinstance(mp["struct"][0], list):
print("{}multipart/{}".format(indentation, mp["struct"][1]), file=fp)
dump_bodystructure(fp, mp["struct"][0], depth + 1)
else:
print("{}{}/{}".format(indentation, *mp["struct"][:2]), file=fp)
fp.seek(0)
result = fp.read()
return result
class FetchParserTestCase(unittest.TestCase):
"""Test FETCH parser."""
def setUp(self):
"""Setup test env."""
self.parser = FetchResponseParser()
def _test_bodystructure_output(self, bs, expected):
"""."""
r = self.parser.parse(bs)
fp = io.StringIO()
output = dump_bodystructure(fp, r[list(r.keys())[0]]["BODYSTRUCTURE"])
fp.close()
self.assertEqual(output, expected)
return r
def test_parse_bodystructure(self):
"""Test the parsing of several responses containing BS."""
self._test_bodystructure_output(
data.BODYSTRUCTURE_SAMPLE_1,
"""multipart/alternative
text/plain
text/html
""",
)
self._test_bodystructure_output(
data.BODYSTRUCTURE_SAMPLE_2,
"""multipart/mixed
text/plain
message/rfc822
""",
)
self._test_bodystructure_output(
data.BODYSTRUCTURE_SAMPLE_3,
"""multipart/mixed
multipart/alternative
text/plain
text/html
application/pdf
""",
)
self._test_bodystructure_output(
data.BODYSTRUCTURE_SAMPLE_4,
"""multipart/mixed
multipart/alternative
text/plain
text/html
application/octet-stream
""",
)
self._test_bodystructure_output(
data.BODYSTRUCTURE_SAMPLE_5,
"""multipart/alternative
text/plain
text/html
""",
)
self._test_bodystructure_output(
data.BODYSTRUCTURE_SAMPLE_6,
"""multipart/mixed
multipart/related
multipart/alternative
text/plain
text/html
image/png
image/jpeg
application/pdf
multipart/alternative
text/plain
text/html
""",
)
self._test_bodystructure_output(
data.BODYSTRUCTURE_SAMPLE_7,
"""multipart/mixed
multipart/mixed
text/plain
application/octet-stream
""",
)
self._test_bodystructure_output(data.BODYSTRUCTURE_SAMPLE_8, "text/html\n")
+256
View File
@@ -0,0 +1,256 @@
from datetime import timedelta
from io import BytesIO
import os
import shutil
import tempfile
from unittest import mock
from django.urls import reverse
from django.utils import timezone
from oauth2_provider.models import get_access_token_model, get_application_model
from modoboa.core import models as core_models
from modoboa.admin import factories as admin_factories
from modoboa.lib.tests import ModoAPITestCase
from . import data as tests_data
Application = get_application_model()
AccessToken = get_access_token_model()
def get_gif():
"""Return gif."""
gif = BytesIO(
b"GIF87a\x01\x00\x01\x00\x80\x01\x00\x00\x00\x00ccc,\x00"
b"\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02D\x01\x00;"
)
gif.name = "image.gif"
return gif
class IMAP4Mock:
"""Fake IMAP4 client."""
def __init__(self, *args, **kwargs):
self.untagged_responses = {}
def _quote(self, data):
return data
def _simple_command(self, name, *args, **kwargs):
if name == "CAPABILITY":
self.untagged_responses["CAPABILITY"] = [b""]
elif name == "LIST":
self.untagged_responses["LIST"] = [b'() "." "INBOX"']
elif name == "NAMESPACE":
self.untagged_responses["NAMESPACE"] = [b'(("" "/")) NIL NIL']
return "OK", None
def append(self, *args, **kwargs):
pass
def create(self, name):
return "OK", None
def delete(self, name):
return "OK", None
def list(self):
return "OK", [b'() "." "INBOX"']
def rename(self, oldname, newname):
return "OK", None
def uid(self, command, *args):
if command in ["SEARCH", "SORT"]:
return "OK", [b"19"]
elif command == "FETCH":
uid = int(args[0])
data = tests_data.BODYSTRUCTURE_SAMPLE_WITH_FLAGS
if uid == 46931:
if args[1] == "(BODYSTRUCTURE)":
data = tests_data.BODYSTRUCTURE_ONLY_4
elif "HEADER.FIELDS" in args[1]:
data = tests_data.BODYSTRUCTURE_SAMPLE_4
else:
data = tests_data.BODY_PLAIN_4
elif uid == 46932:
if args[1] == "(BODYSTRUCTURE)":
data = tests_data.BODYSTRUCTURE_ONLY_5
elif "HEADER.FIELDS" in args[1]:
data = tests_data.BODYSTRUCTURE_SAMPLE_9
else:
data = tests_data.BODYSTRUCTURE_SAMPLE_10
elif uid == 33:
if args[1] == "(BODYSTRUCTURE)":
data = tests_data.BODYSTRUCTURE_EMPTY_MAIL
else:
data = tests_data.EMPTY_BODY
elif uid == 133872:
data = tests_data.COMPLETE_MAIL
return "OK", data
elif command == "STORE":
return "OK", []
class WebmailTestCase(ModoAPITestCase):
@classmethod
def setUpTestData(cls):
super().setUpTestData()
admin_factories.populate_database()
cls.user = core_models.User.objects.get(username="user@test.com")
cls.application = Application.objects.create(
name="Test Application",
redirect_uris="http://localhost",
user=cls.user,
client_type=Application.CLIENT_PUBLIC,
authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE,
)
cls.access_token = AccessToken.objects.create(
user=cls.user,
scope="read write",
expires=timezone.now() + timedelta(seconds=300),
token="secret-access-token-key",
application=cls.application,
)
def setUp(self):
"""Connect with a simpler user."""
patcher = mock.patch("imaplib.IMAP4")
self.mock_imap4 = patcher.start()
self.mock_imap4.return_value = IMAP4Mock()
self.addCleanup(patcher.stop)
self.set_global_parameter("imap_port", 1435)
self.workdir = tempfile.mkdtemp()
os.mkdir(f"{self.workdir}/webmail")
self.set_global_parameter("update_scheme", False, app="core")
def tearDown(self):
"""Cleanup."""
shutil.rmtree(self.workdir)
def authenticate(self, username: str = "user@test.com"):
self.client.credentials(Authorization="Bearer " + self.access_token.token)
class UserMailboxViewSetTestCase(WebmailTestCase):
def test_list(self):
self.authenticate()
url = reverse("v2:webmail-mailbox-list")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()["mailboxes"]), 5)
def test_quota(self):
self.authenticate()
url = reverse("v2:webmail-mailbox-quota")
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
response = self.client.get(f"{url}?mailbox=INBOX")
self.assertEqual(response.status_code, 200)
self.assertEqual(response.json()["usage"], -1)
def test_create(self):
self.authenticate()
url = reverse("v2:webmail-mailbox-list")
body = {"name": "Test"}
response = self.client.post(url, body, format="json")
self.assertEqual(response.status_code, 201)
body = {"parent": "Test", "name": "Test"}
response = self.client.post(url, body, format="json")
self.assertEqual(response.status_code, 201)
def test_rename(self):
self.authenticate()
url = reverse("v2:webmail-mailbox-rename")
body = {"name": "Test renamed", "oldname": "Test"}
response = self.client.post(url, body, format="json")
self.assertEqual(response.status_code, 200)
def test_compress(self):
self.authenticate()
url = reverse("v2:webmail-mailbox-compress")
body = {"name": "INBOX"}
response = self.client.post(url, body, format="json")
self.assertEqual(response.status_code, 204)
def test_empty(self):
self.authenticate()
url = reverse("v2:webmail-mailbox-empty")
body = {"name": "INBOX"}
response = self.client.post(url, body, format="json")
self.assertEqual(response.status_code, 404)
body = {"name": "Trash"}
response = self.client.post(url, body, format="json")
self.assertEqual(response.status_code, 204)
def test_delete(self):
self.authenticate()
url = reverse("v2:webmail-mailbox-delete")
body = {"name": "Test"}
response = self.client.post(url, body, format="json")
self.assertEqual(response.status_code, 204)
class UserEmailViewSetTestCase(WebmailTestCase):
def test_listmailbox(self):
"""Check listmailbox action."""
self.authenticate()
url = reverse("v2:webmail-email-list")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
content = response.json()
self.assertEqual(content["count"], 1)
self.assertEqual(
content["results"][0]["from_address"]["address"],
"nguyen.antoine@wanadoo.fr",
)
response = self.client.get(f"{url}?search=Réception")
self.assertEqual(response.status_code, 200)
self.assertEqual(
content["results"][0]["from_address"]["address"],
"nguyen.antoine@wanadoo.fr",
)
def test_getmailsource(self):
"""Try to display a message's source."""
self.authenticate()
url = reverse("v2:webmail-email-source")
response = self.client.get(url)
self.assertEqual(response.status_code, 404)
response = self.client.get(f"{url}?mailbox=INBOX&mailid=133872")
self.assertEqual(response.status_code, 200)
self.assertIn("Message-ID", response.json()["source"])
class ComposeSessionViewSetTestCase(WebmailTestCase):
def test_create(self):
self.authenticate()
url = reverse("v2:webmail-compose-session-list")
response = self.client.post(url)
self.assertEqual(response.status_code, 201)
self.assertIn("uid", response.json())
def test_get_allowed_senders(self):
self.authenticate()
url = reverse("v2:webmail-compose-session-allowed-senders")
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertEqual(len(response.json()), 2)
def test_attachments(self):
self.authenticate()
url = reverse("v2:webmail-compose-session-list")
response = self.client.post(url)
uid = response.json()["uid"]
url = reverse("v2:webmail-compose-session-attachments", args=[uid])
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
+7 -1
View File
@@ -9,12 +9,14 @@ from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from modoboa.lib.paginator import Paginator
from modoboa.lib.viewsets import HasMailbox
from modoboa.webmail import lib, serializers
from modoboa.webmail.lib import attachments
class UserMailboxViewSet(viewsets.GenericViewSet):
permission_classes = (IsAuthenticated,)
permission_classes = (IsAuthenticated, HasMailbox)
def get_serializer_class(self):
if self.action == "list":
@@ -101,6 +103,8 @@ class UserMailboxViewSet(viewsets.GenericViewSet):
class UserEmailViewSet(viewsets.GenericViewSet):
permission_classes = (IsAuthenticated, HasMailbox)
def get_serializer_class(self):
if self.action == "list":
return serializers.PaginatedEmailListSerializer
@@ -262,6 +266,8 @@ class UserEmailViewSet(viewsets.GenericViewSet):
class ComposeSessionViewSet(viewsets.GenericViewSet):
permission_classes = (IsAuthenticated, HasMailbox)
def get_serializer_class(self):
if self.action == "send":
return serializers.SendEmailSerializer