From f1b9fcfbdac075b6db1436825da6989e59587594 Mon Sep 17 00:00:00 2001 From: "v.kaukin" Date: Wed, 10 Jul 2024 09:50:18 +0500 Subject: [PATCH] SortCriteria to consts, __str__ to MailMessage, docs info --- README.rst | 18 +++++++++++------- docs/release_notes.rst | 6 ++++++ docs/todo.txt | 26 -------------------------- examples/basic.py | 11 +++++++++++ imap_tools/__init__.py | 6 +++--- imap_tools/consts.py | 35 +++++++++++++++++++++++++++++++++++ imap_tools/message.py | 4 ++++ imap_tools/utils.py | 35 ----------------------------------- tests/test_mailbox.py | 3 +-- 9 files changed, 71 insertions(+), 73 deletions(-) diff --git a/README.rst b/README.rst index 04615be..4ce2377 100644 --- a/README.rst +++ b/README.rst @@ -90,6 +90,9 @@ BaseMailBox.client - imaplib.IMAP4/IMAP4_SSL client instance. Email attributes ^^^^^^^^^^^^^^^^ +Email message has 2 basic body variants: text and html. +Sender can choose to include: one, other, both or neither(rare in practice). + MailMessage and MailAttachment public attributes are cached by functools.lru_cache .. code-block:: python @@ -131,7 +134,7 @@ MailMessage and MailAttachment public attributes are cached by functools.lru_cac Search criteria ^^^^^^^^^^^^^^^ -You can pass *"criteria"* argument to 3 methods of MailBox: *fetch, uids, numbers*. Criteria can be of three types: +The *"criteria"* argument is used at *fetch, uids, numbers* methods of MailBox. Criteria can be of three types: .. code-block:: python @@ -176,6 +179,11 @@ See `query examples `_, `Docpart `_, `meetttttt `_, -`sapristi `_ +`sapristi `_, +`thomwiggers `_ Help the project ---------------- diff --git a/docs/release_notes.rst b/docs/release_notes.rst index ddae7ab..629c1b4 100644 --- a/docs/release_notes.rst +++ b/docs/release_notes.rst @@ -1,3 +1,9 @@ +1.7.0 +===== +* Moved: SortCriteria to consts +* Added: __str__ to MailMessage +* Added: docs info + 1.6.0 ===== * [Breaking] Changed: "bulk" argument at BaseMailBox.fetch now can accept int values >=2 - for control bulk size diff --git a/docs/todo.txt b/docs/todo.txt index c6427e3..c6444d4 100644 --- a/docs/todo.txt +++ b/docs/todo.txt @@ -1,33 +1,7 @@ -move SortCriteria to consts - -+ important hints to readme each part - -__str__ - For more back compat - f string is bad. In next release I will make __str__ as: - 'date from subj' - thomwiggers - -fetch and uids examples? - FULL Macro equivalent to: (FLAGS INTERNALDATE RFC822.SIZE ENVELOPE BODY) -https://stackoverflow.com/questions/72942311/ some to docs? - The second problem is that you need to use imap_tools.MailBox. - Looking at the documentation and source at the repo it appears that the relevant classes to use are: - - MailBox - for a normal encrypted connection. This is what most email servers use these days, aka IMAPS (imap with SSL/TLS) - MailBoxTls - For a STARTTLS connection: this creates a plaintext connection then upgrades - it later by using a STARTTLS command in the protocol. The internet has mostly gone to the "always encrypted" - rather than "upgrade" paradigm, so this is not the class to use. - MailBoxUnencrypted - Standard IMAP without SSL/TLS. You should not use this on the public internet. - - The naming is a bit confusing. MailBox corresponds to imaplib.IMAP4_SSL; - MailBoxTls corresponds to imaplib.IMAP4, then using startls() on the resulting connection; - and MailboxUnencrypted corresponds to imaplib.IMAP4 with no security applied. - I imagine it's this way so the most common one (Mailbox) is a safe default. - add servers for tests rambler GMX Mail diff --git a/examples/basic.py b/examples/basic.py index 058daa4..0848d84 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -24,6 +24,17 @@ msg.subject - email subject, utf8 str msg.text - email plain text content, utf8 str msg.html - email html content, utf8 str + +Mailbox classes: + MailBox - for a normal encrypted connection. This is what most email servers use these days, aka IMAPS (imap with SSL/TLS) + MailBoxTls - For a STARTTLS connection: this creates a plaintext connection then upgrades + it later by using a STARTTLS command in the protocol. The internet has mostly gone to the "always encrypted" + rather than "upgrade" paradigm, so this is not the class to use. + MailBoxUnencrypted - Standard IMAP without SSL/TLS. You should not use this on the public internet. + + MailBox corresponds to imaplib.IMAP4_SSL; + MailBoxTls corresponds to imaplib.IMAP4, then using startls() on the resulting connection; + MailboxUnencrypted corresponds to imaplib.IMAP4 with no security applied. """ with MailBox('imap.mail.com').login('test@mail.com', 'pwd') as mailbox: for msg in mailbox.fetch(): diff --git a/imap_tools/__init__.py b/imap_tools/__init__.py index 1196256..760f25f 100644 --- a/imap_tools/__init__.py +++ b/imap_tools/__init__.py @@ -7,8 +7,8 @@ from .mailbox import BaseMailBox, MailBox, MailBoxUnencrypted, MailBoxTls from .message import MailMessage, MailAttachment from .folder import MailBoxFolderManager, FolderInfo -from .consts import MailMessageFlags, MailBoxFolderStatusOptions -from .utils import EmailAddress, SortCriteria +from .consts import MailMessageFlags, MailBoxFolderStatusOptions, SortCriteria +from .utils import EmailAddress from .errors import * -__version__ = '1.6.0' +__version__ = '1.7.0' diff --git a/imap_tools/consts.py b/imap_tools/consts.py index 6395a2b..c273263 100644 --- a/imap_tools/consts.py +++ b/imap_tools/consts.py @@ -40,3 +40,38 @@ class MailBoxFolderStatusOptions: (UIDVALIDITY, "The unique identifier validity value of the mailbox"), (UNSEEN, "The number of messages which do not have the Seen flag set"), ) + + +class SortCriteria: + """ + Sort criteria + https://datatracker.ietf.org/doc/html/rfc5256 + ARRIVAL - Internal date and time of the message. + This differs from the ON criteria in SEARCH, which uses just the internal date. + CC - [IMAP] addr-mailbox of the first "cc" address. + DATE - Sent date and time, as described in section 2.2. + FROM - [IMAP] addr-mailbox of the first "From" address. + SIZE - Size of the message in octets. + SUBJECT - Base subject text. + TO - [IMAP] addr-mailbox of the first "To" address. + """ + ARRIVAL_DT_ASC = 'ARRIVAL' + CC_ASC = 'CC' + DATE_ASC = 'DATE' + FROM_ASC = 'FROM' + SIZE_ASC = 'SIZE' + SUBJECT_ASC = 'SUBJECT' + TO_ASC = 'TO' + + ARRIVAL_DT_DESC = 'REVERSE ARRIVAL' + CC_DESC = 'REVERSE CC' + DATE_DESC = 'REVERSE DATE' + FROM_DESC = 'REVERSE FROM' + SIZE_DESC = 'REVERSE SIZE' + SUBJECT_DESC = 'REVERSE SUBJECT' + TO_DESC = 'REVERSE TO' + + all = ( + ARRIVAL_DT_ASC, CC_ASC, DATE_ASC, FROM_ASC, SIZE_ASC, SUBJECT_ASC, TO_ASC, + ARRIVAL_DT_DESC, CC_DESC, DATE_DESC, FROM_DESC, SIZE_DESC, SUBJECT_DESC, TO_DESC, + ) diff --git a/imap_tools/message.py b/imap_tools/message.py index 1fd6b91..301dba8 100644 --- a/imap_tools/message.py +++ b/imap_tools/message.py @@ -27,6 +27,10 @@ def from_bytes(cls, raw_message_data: bytes): """Alternative constructor""" return cls([(b'', raw_message_data)]) + def __str__(self): + repl = '[\t\n\r\f\v]' + return '{}, {}, {}'.format(self.date, re.sub(repl, '', self.from_), re.sub(repl, '', self.subject)) + @staticmethod def _get_message_data_parts(fetch_data: list) -> (bytes, bytes, List[bytes]): """ diff --git a/imap_tools/utils.py b/imap_tools/utils.py index 595096d..6854663 100644 --- a/imap_tools/utils.py +++ b/imap_tools/utils.py @@ -220,38 +220,3 @@ def chunks_crop(lst: iter, n: int) -> iter: """ for i in range(0, len(lst), n): yield lst[i:i + n] - - -class SortCriteria: - """ - Sort criteria - https://datatracker.ietf.org/doc/html/rfc5256 - ARRIVAL - Internal date and time of the message. - This differs from the ON criteria in SEARCH, which uses just the internal date. - CC - [IMAP] addr-mailbox of the first "cc" address. - DATE - Sent date and time, as described in section 2.2. - FROM - [IMAP] addr-mailbox of the first "From" address. - SIZE - Size of the message in octets. - SUBJECT - Base subject text. - TO - [IMAP] addr-mailbox of the first "To" address. - """ - ARRIVAL_DT_ASC = 'ARRIVAL' - CC_ASC = 'CC' - DATE_ASC = 'DATE' - FROM_ASC = 'FROM' - SIZE_ASC = 'SIZE' - SUBJECT_ASC = 'SUBJECT' - TO_ASC = 'TO' - - ARRIVAL_DT_DESC = 'REVERSE ARRIVAL' - CC_DESC = 'REVERSE CC' - DATE_DESC = 'REVERSE DATE' - FROM_DESC = 'REVERSE FROM' - SIZE_DESC = 'REVERSE SIZE' - SUBJECT_DESC = 'REVERSE SUBJECT' - TO_DESC = 'REVERSE TO' - - all = ( - ARRIVAL_DT_ASC, CC_ASC, DATE_ASC, FROM_ASC, SIZE_ASC, SUBJECT_ASC, TO_ASC, - ARRIVAL_DT_DESC, CC_DESC, DATE_DESC, FROM_DESC, SIZE_DESC, SUBJECT_DESC, TO_DESC, - ) diff --git a/tests/test_mailbox.py b/tests/test_mailbox.py index fef9211..e0daded 100644 --- a/tests/test_mailbox.py +++ b/tests/test_mailbox.py @@ -2,9 +2,8 @@ from tests.utils import MailboxTestCase, TEST_MAILBOX_NAME_SET, get_test_mailbox from imap_tools.errors import MailboxCopyError -from imap_tools.consts import MailMessageFlags +from imap_tools.consts import MailMessageFlags, SortCriteria from imap_tools.query import A -from imap_tools.utils import SortCriteria TEST_MESSAGE_DATA = b'From: Mikel \nTo: Mikel \nContent-Type: text/plain; charset=US-ASCII; format=flowed\nContent-Transfer-Encoding: 7bit\nMime-Version: 1.0 (Apple Message framework v929.2)\nSubject: _append_\nDate: Sat, 22 Nov 2008 11:04:59 +1100\n\nPlain email.\n' # noqa