IMAPClient 3.1.0__tar.gz → 4.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {imapclient-3.1.0 → imapclient-4.0.1}/AUTHORS.rst +2 -0
- imapclient-4.0.1/IMAPClient.egg-info/PKG-INFO +195 -0
- imapclient-4.0.1/IMAPClient.egg-info/SOURCES.txt +43 -0
- imapclient-4.0.1/IMAPClient.egg-info/entry_points.txt +3 -0
- imapclient-4.0.1/PKG-INFO +195 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/README.rst +12 -12
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/__init__.py +0 -1
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/config.py +1 -1
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/imap4.py +1 -10
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/imapclient.py +24 -4
- {imapclient-3.1.0 → imapclient-4.0.1/imapclient}/livetest.py +8 -12
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/response_types.py +7 -2
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/util.py +14 -1
- imapclient-4.0.1/imapclient/version.py +17 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/pyproject.toml +61 -1
- {imapclient-3.1.0 → imapclient-4.0.1}/setup.cfg +0 -3
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_imapclient.py +12 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_store.py +28 -14
- imapclient-3.1.0/IMAPClient.egg-info/PKG-INFO +0 -56
- imapclient-3.1.0/IMAPClient.egg-info/SOURCES.txt +0 -89
- imapclient-3.1.0/IMAPClient.egg-info/requires.txt +0 -3
- imapclient-3.1.0/MANIFEST.in +0 -8
- imapclient-3.1.0/NEWS.rst +0 -7
- imapclient-3.1.0/PKG-INFO +0 -56
- imapclient-3.1.0/doc/html/_modules/imapclient/exceptions.html +0 -116
- imapclient-3.1.0/doc/html/_modules/imapclient/imapclient.html +0 -2122
- imapclient-3.1.0/doc/html/_modules/imapclient/response_types.html +0 -205
- imapclient-3.1.0/doc/html/_modules/imapclient/testable_imapclient.html +0 -123
- imapclient-3.1.0/doc/html/_modules/imapclient/tls.html +0 -139
- imapclient-3.1.0/doc/html/_modules/index.html +0 -77
- imapclient-3.1.0/doc/html/_sources/advanced.rst.txt +0 -148
- imapclient-3.1.0/doc/html/_sources/api.rst.txt +0 -68
- imapclient-3.1.0/doc/html/_sources/concepts.rst.txt +0 -159
- imapclient-3.1.0/doc/html/_sources/contributing.rst.txt +0 -97
- imapclient-3.1.0/doc/html/_sources/index.rst.txt +0 -129
- imapclient-3.1.0/doc/html/_sources/installation.rst.txt +0 -30
- imapclient-3.1.0/doc/html/_sources/releases.rst.txt +0 -979
- imapclient-3.1.0/doc/html/_static/basic.css +0 -930
- imapclient-3.1.0/doc/html/_static/contents.png +0 -0
- imapclient-3.1.0/doc/html/_static/file.png +0 -0
- imapclient-3.1.0/doc/html/_static/minus.png +0 -0
- imapclient-3.1.0/doc/html/_static/navigation.png +0 -0
- imapclient-3.1.0/doc/html/_static/plus.png +0 -0
- imapclient-3.1.0/doc/html/_static/pygments.css +0 -74
- imapclient-3.1.0/doc/html/_static/sphinxdoc.css +0 -350
- imapclient-3.1.0/doc/html/advanced.html +0 -331
- imapclient-3.1.0/doc/html/api.html +0 -1196
- imapclient-3.1.0/doc/html/concepts.html +0 -318
- imapclient-3.1.0/doc/html/contributing.html +0 -210
- imapclient-3.1.0/doc/html/index.html +0 -340
- imapclient-3.1.0/doc/html/installation.html +0 -144
- imapclient-3.1.0/doc/html/py-modindex.html +0 -112
- imapclient-3.1.0/doc/html/releases.html +0 -1091
- imapclient-3.1.0/doc/html/search.html +0 -96
- imapclient-3.1.0/doc/src/advanced.rst +0 -148
- imapclient-3.1.0/doc/src/api.rst +0 -68
- imapclient-3.1.0/doc/src/concepts.rst +0 -152
- imapclient-3.1.0/doc/src/conf.py +0 -213
- imapclient-3.1.0/doc/src/contributing.rst +0 -97
- imapclient-3.1.0/doc/src/index.rst +0 -130
- imapclient-3.1.0/doc/src/installation.rst +0 -30
- imapclient-3.1.0/doc/src/releases.rst +0 -983
- imapclient-3.1.0/imapclient/version.py +0 -24
- imapclient-3.1.0/interact.py +0 -9
- imapclient-3.1.0/setup.py +0 -67
- imapclient-3.1.0/tests/__init__.py +0 -3
- imapclient-3.1.0/tests/imapclient_test.py +0 -8
- imapclient-3.1.0/tests/test_version.py +0 -24
- {imapclient-3.1.0 → imapclient-4.0.1}/COPYING +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/IMAPClient.egg-info/dependency_links.txt +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/IMAPClient.egg-info/top_level.txt +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/datetime_util.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/exceptions.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/fixed_offset.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/imap_utf7.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/interact.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/response_lexer.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/response_parser.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/testable_imapclient.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/tls.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/imapclient/typing_imapclient.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_auth.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_datetime_util.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_enable.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_fixed_offset.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_folder_status.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_imap_utf7.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_init.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_response_lexer.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_response_parser.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_search.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_sort.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_starttls.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_thread.py +0 -0
- {imapclient-3.1.0 → imapclient-4.0.1}/tests/test_util_functions.py +0 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: IMAPClient
|
|
3
|
+
Version: 4.0.1
|
|
4
|
+
Summary: Easy-to-use, Pythonic and complete IMAP client library
|
|
5
|
+
Author-email: Menno Finlay-Smits <hello@menno.io>
|
|
6
|
+
Maintainer-email: IMAPClient Maintainers <imapclient@groups.io>
|
|
7
|
+
Project-URL: Homepage, https://github.com/mjs/imapclient/
|
|
8
|
+
Keywords: imap,client,email,mail
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Communications :: Email :: Post-Office :: IMAP
|
|
16
|
+
Classifier: Topic :: Internet
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: System :: Networking
|
|
19
|
+
Requires-Python: >=3.8.0
|
|
20
|
+
Description-Content-Type: text/x-rst
|
|
21
|
+
License-File: COPYING
|
|
22
|
+
License-File: AUTHORS.rst
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
Essentials
|
|
26
|
+
----------
|
|
27
|
+
IMAPClient is an easy-to-use, Pythonic and complete IMAP client
|
|
28
|
+
library.
|
|
29
|
+
|
|
30
|
+
========================= ========================================
|
|
31
|
+
Supported Python versions 3.8 - 3.14
|
|
32
|
+
License New BSD
|
|
33
|
+
Project home https://github.com/mjs/imapclient/
|
|
34
|
+
PyPI https://pypi.python.org/pypi/IMAPClient
|
|
35
|
+
Documentation https://imapclient.readthedocs.io/
|
|
36
|
+
Discussions https://github.com/mjs/imapclient/discussions
|
|
37
|
+
Test Status |build master|
|
|
38
|
+
========================= ========================================
|
|
39
|
+
|
|
40
|
+
.. |build master| image:: https://github.com/mjs/imapclient/actions/workflows/main.yml/badge.svg
|
|
41
|
+
:target: https://github.com/mjs/imapclient/actions
|
|
42
|
+
:alt: master branch
|
|
43
|
+
|
|
44
|
+
Features
|
|
45
|
+
--------
|
|
46
|
+
- Arguments and return values are natural Python types.
|
|
47
|
+
- IMAP server responses are fully parsed and readily usable.
|
|
48
|
+
- IMAP unique message IDs (UIDs) are handled transparently. There is
|
|
49
|
+
no need to call different methods to use UIDs.
|
|
50
|
+
- Escaping for internationalised mailbox names is transparently
|
|
51
|
+
handled. Unicode mailbox names may be passed as input wherever a
|
|
52
|
+
folder name is accepted.
|
|
53
|
+
- Time zones are transparently handled including when the server and
|
|
54
|
+
client are in different zones.
|
|
55
|
+
- Convenience methods are provided for commonly used functionality.
|
|
56
|
+
- Exceptions are raised when errors occur.
|
|
57
|
+
|
|
58
|
+
Example
|
|
59
|
+
-------
|
|
60
|
+
|
|
61
|
+
.. code-block:: python
|
|
62
|
+
|
|
63
|
+
from imapclient import IMAPClient
|
|
64
|
+
|
|
65
|
+
# context manager ensures the session is cleaned up
|
|
66
|
+
with IMAPClient(host="imap.host.org") as client:
|
|
67
|
+
client.login('someone', 'secret')
|
|
68
|
+
client.select_folder('INBOX')
|
|
69
|
+
|
|
70
|
+
# search criteria are passed in a straightforward way
|
|
71
|
+
# (nesting is supported)
|
|
72
|
+
messages = client.search(['NOT', 'DELETED'])
|
|
73
|
+
|
|
74
|
+
# fetch selectors are passed as a simple list of strings.
|
|
75
|
+
response = client.fetch(messages, ['FLAGS', 'RFC822.SIZE'])
|
|
76
|
+
|
|
77
|
+
# `response` is keyed by message id and contains parsed,
|
|
78
|
+
# converted response items.
|
|
79
|
+
for message_id, data in response.items():
|
|
80
|
+
print('{id}: {size} bytes, flags={flags}'.format(
|
|
81
|
+
id=message_id,
|
|
82
|
+
size=data[b'RFC822.SIZE'],
|
|
83
|
+
flags=data[b'FLAGS']))
|
|
84
|
+
|
|
85
|
+
Why IMAPClient?
|
|
86
|
+
---------------
|
|
87
|
+
You may ask: "why create another IMAP client library for Python?
|
|
88
|
+
Doesn't the Python standard library already have imaplib?".
|
|
89
|
+
|
|
90
|
+
The problem with imaplib is that it's very low-level. It expects
|
|
91
|
+
string values where lists or tuples would be more appropriate and
|
|
92
|
+
returns server responses almost unparsed. As IMAP server responses can
|
|
93
|
+
be quite complex this means everyone using imaplib ends up writing
|
|
94
|
+
their own fragile parsing routines.
|
|
95
|
+
|
|
96
|
+
Also, imaplib doesn't make good use of exceptions. This means you need
|
|
97
|
+
to check the return value of each call to imaplib to see if what you
|
|
98
|
+
just did was successful.
|
|
99
|
+
|
|
100
|
+
IMAPClient actually uses imaplib internally. This may change at some
|
|
101
|
+
point in the future.
|
|
102
|
+
|
|
103
|
+
Installing IMAPClient
|
|
104
|
+
---------------------
|
|
105
|
+
IMAPClient is listed on PyPI and can be installed with `uv
|
|
106
|
+
<https://docs.astral.sh/uv/>`_::
|
|
107
|
+
|
|
108
|
+
uv add imapclient
|
|
109
|
+
|
|
110
|
+
More installation methods are described in the documentation.
|
|
111
|
+
|
|
112
|
+
Documentation
|
|
113
|
+
-------------
|
|
114
|
+
IMAPClient's manual is available at http://imapclient.readthedocs.io/.
|
|
115
|
+
Release notes can be found at
|
|
116
|
+
http://imapclient.readthedocs.io/#release-history.
|
|
117
|
+
|
|
118
|
+
See the `examples` directory in the root of project source for
|
|
119
|
+
examples of how to use IMAPClient.
|
|
120
|
+
|
|
121
|
+
Current Status
|
|
122
|
+
--------------
|
|
123
|
+
You should feel confident using IMAPClient for production purposes.
|
|
124
|
+
|
|
125
|
+
In order to clearly communicate version compatibility, IMAPClient
|
|
126
|
+
will strictly adhere to the `Semantic Versioning <http://semver.org>`_
|
|
127
|
+
scheme from version 1.0 onwards.
|
|
128
|
+
|
|
129
|
+
The project's home page is https://github.com/mjs/imapclient/ (this
|
|
130
|
+
currently redirects to the IMAPClient Github site). Details about
|
|
131
|
+
upcoming versions and planned features/fixes can be found in the issue
|
|
132
|
+
tracker on Github. The maintainers also blog about IMAPClient
|
|
133
|
+
news. Those articles can be found `here
|
|
134
|
+
<http://menno.io/tags/imapclient>`_.
|
|
135
|
+
|
|
136
|
+
Discussions
|
|
137
|
+
-----------
|
|
138
|
+
`Github Discussions`_ can be used to ask questions, propose changes or praise
|
|
139
|
+
the project maintainers :)
|
|
140
|
+
|
|
141
|
+
.. _`Github Discussions`: https://github.com/mjs/imapclient/discussions
|
|
142
|
+
|
|
143
|
+
Working on IMAPClient
|
|
144
|
+
---------------------
|
|
145
|
+
The `contributing documentation
|
|
146
|
+
<http://imapclient.rtfd.io/en/master/contributing.html>`_ contains
|
|
147
|
+
information for those interested in improving IMAPClient.
|
|
148
|
+
|
|
149
|
+
IMAP Servers
|
|
150
|
+
------------
|
|
151
|
+
IMAPClient is heavily tested against Dovecot, Gmail, Fastmail.fm
|
|
152
|
+
(who use a modified Cyrus implementation), Office365 and Yahoo. Access
|
|
153
|
+
to accounts on other IMAP servers/services for testing would be
|
|
154
|
+
greatly appreciated.
|
|
155
|
+
|
|
156
|
+
Interactive Console
|
|
157
|
+
-------------------
|
|
158
|
+
This script connects an IMAPClient instance using the command line
|
|
159
|
+
args given and starts an interactive session. This is useful for
|
|
160
|
+
exploring the IMAPClient API and testing things out, avoiding the
|
|
161
|
+
steps required to set up an IMAPClient instance.
|
|
162
|
+
|
|
163
|
+
The IPython shell is used if it is installed. Otherwise the
|
|
164
|
+
code.interact() function from the standard library is used.
|
|
165
|
+
|
|
166
|
+
The interactive console functionality can be accessed by running the
|
|
167
|
+
``imapclient-interact`` script that is installed alongside IMAPClient,
|
|
168
|
+
or by invoking the interact module like this::
|
|
169
|
+
|
|
170
|
+
uv run python -m imapclient.interact ...
|
|
171
|
+
|
|
172
|
+
"Live" Tests
|
|
173
|
+
------------
|
|
174
|
+
IMAPClient includes a series of live, functional tests which exercise
|
|
175
|
+
it against a live IMAP account. These are useful for ensuring
|
|
176
|
+
compatibility with a given IMAP server implementation.
|
|
177
|
+
|
|
178
|
+
The livetest functionality is run using the ``imapclient-livetest``
|
|
179
|
+
script that is installed alongside IMAPClient::
|
|
180
|
+
|
|
181
|
+
uv run imapclient-livetest <livetest.ini> [ optional unittest arguments ]
|
|
182
|
+
|
|
183
|
+
The configuration file format is
|
|
184
|
+
`described in the main documentation <http://imapclient.rtfd.io/#configuration-file-format>`_.
|
|
185
|
+
|
|
186
|
+
**WARNING**: The operations used by livetest are destructive and could
|
|
187
|
+
cause unintended loss of data. That said, as of version 0.9, livetest
|
|
188
|
+
limits its activity to a folder it creates and subfolders of that
|
|
189
|
+
folder. It *should* be safe to use with any IMAP account but please
|
|
190
|
+
don't run livetest against a truly important IMAP account.
|
|
191
|
+
|
|
192
|
+
Please include the output of imapclient-livetest with an issue if it
|
|
193
|
+
fails to run successfully against a particular IMAP server. Reports of
|
|
194
|
+
successful runs are also welcome. Please include the type and version
|
|
195
|
+
of the IMAP server, if known.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
AUTHORS.rst
|
|
2
|
+
COPYING
|
|
3
|
+
README.rst
|
|
4
|
+
pyproject.toml
|
|
5
|
+
IMAPClient.egg-info/PKG-INFO
|
|
6
|
+
IMAPClient.egg-info/SOURCES.txt
|
|
7
|
+
IMAPClient.egg-info/dependency_links.txt
|
|
8
|
+
IMAPClient.egg-info/entry_points.txt
|
|
9
|
+
IMAPClient.egg-info/top_level.txt
|
|
10
|
+
imapclient/__init__.py
|
|
11
|
+
imapclient/config.py
|
|
12
|
+
imapclient/datetime_util.py
|
|
13
|
+
imapclient/exceptions.py
|
|
14
|
+
imapclient/fixed_offset.py
|
|
15
|
+
imapclient/imap4.py
|
|
16
|
+
imapclient/imap_utf7.py
|
|
17
|
+
imapclient/imapclient.py
|
|
18
|
+
imapclient/interact.py
|
|
19
|
+
imapclient/livetest.py
|
|
20
|
+
imapclient/response_lexer.py
|
|
21
|
+
imapclient/response_parser.py
|
|
22
|
+
imapclient/response_types.py
|
|
23
|
+
imapclient/testable_imapclient.py
|
|
24
|
+
imapclient/tls.py
|
|
25
|
+
imapclient/typing_imapclient.py
|
|
26
|
+
imapclient/util.py
|
|
27
|
+
imapclient/version.py
|
|
28
|
+
tests/test_auth.py
|
|
29
|
+
tests/test_datetime_util.py
|
|
30
|
+
tests/test_enable.py
|
|
31
|
+
tests/test_fixed_offset.py
|
|
32
|
+
tests/test_folder_status.py
|
|
33
|
+
tests/test_imap_utf7.py
|
|
34
|
+
tests/test_imapclient.py
|
|
35
|
+
tests/test_init.py
|
|
36
|
+
tests/test_response_lexer.py
|
|
37
|
+
tests/test_response_parser.py
|
|
38
|
+
tests/test_search.py
|
|
39
|
+
tests/test_sort.py
|
|
40
|
+
tests/test_starttls.py
|
|
41
|
+
tests/test_store.py
|
|
42
|
+
tests/test_thread.py
|
|
43
|
+
tests/test_util_functions.py
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: IMAPClient
|
|
3
|
+
Version: 4.0.1
|
|
4
|
+
Summary: Easy-to-use, Pythonic and complete IMAP client library
|
|
5
|
+
Author-email: Menno Finlay-Smits <hello@menno.io>
|
|
6
|
+
Maintainer-email: IMAPClient Maintainers <imapclient@groups.io>
|
|
7
|
+
Project-URL: Homepage, https://github.com/mjs/imapclient/
|
|
8
|
+
Keywords: imap,client,email,mail
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Natural Language :: English
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Communications :: Email :: Post-Office :: IMAP
|
|
16
|
+
Classifier: Topic :: Internet
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: System :: Networking
|
|
19
|
+
Requires-Python: >=3.8.0
|
|
20
|
+
Description-Content-Type: text/x-rst
|
|
21
|
+
License-File: COPYING
|
|
22
|
+
License-File: AUTHORS.rst
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
Essentials
|
|
26
|
+
----------
|
|
27
|
+
IMAPClient is an easy-to-use, Pythonic and complete IMAP client
|
|
28
|
+
library.
|
|
29
|
+
|
|
30
|
+
========================= ========================================
|
|
31
|
+
Supported Python versions 3.8 - 3.14
|
|
32
|
+
License New BSD
|
|
33
|
+
Project home https://github.com/mjs/imapclient/
|
|
34
|
+
PyPI https://pypi.python.org/pypi/IMAPClient
|
|
35
|
+
Documentation https://imapclient.readthedocs.io/
|
|
36
|
+
Discussions https://github.com/mjs/imapclient/discussions
|
|
37
|
+
Test Status |build master|
|
|
38
|
+
========================= ========================================
|
|
39
|
+
|
|
40
|
+
.. |build master| image:: https://github.com/mjs/imapclient/actions/workflows/main.yml/badge.svg
|
|
41
|
+
:target: https://github.com/mjs/imapclient/actions
|
|
42
|
+
:alt: master branch
|
|
43
|
+
|
|
44
|
+
Features
|
|
45
|
+
--------
|
|
46
|
+
- Arguments and return values are natural Python types.
|
|
47
|
+
- IMAP server responses are fully parsed and readily usable.
|
|
48
|
+
- IMAP unique message IDs (UIDs) are handled transparently. There is
|
|
49
|
+
no need to call different methods to use UIDs.
|
|
50
|
+
- Escaping for internationalised mailbox names is transparently
|
|
51
|
+
handled. Unicode mailbox names may be passed as input wherever a
|
|
52
|
+
folder name is accepted.
|
|
53
|
+
- Time zones are transparently handled including when the server and
|
|
54
|
+
client are in different zones.
|
|
55
|
+
- Convenience methods are provided for commonly used functionality.
|
|
56
|
+
- Exceptions are raised when errors occur.
|
|
57
|
+
|
|
58
|
+
Example
|
|
59
|
+
-------
|
|
60
|
+
|
|
61
|
+
.. code-block:: python
|
|
62
|
+
|
|
63
|
+
from imapclient import IMAPClient
|
|
64
|
+
|
|
65
|
+
# context manager ensures the session is cleaned up
|
|
66
|
+
with IMAPClient(host="imap.host.org") as client:
|
|
67
|
+
client.login('someone', 'secret')
|
|
68
|
+
client.select_folder('INBOX')
|
|
69
|
+
|
|
70
|
+
# search criteria are passed in a straightforward way
|
|
71
|
+
# (nesting is supported)
|
|
72
|
+
messages = client.search(['NOT', 'DELETED'])
|
|
73
|
+
|
|
74
|
+
# fetch selectors are passed as a simple list of strings.
|
|
75
|
+
response = client.fetch(messages, ['FLAGS', 'RFC822.SIZE'])
|
|
76
|
+
|
|
77
|
+
# `response` is keyed by message id and contains parsed,
|
|
78
|
+
# converted response items.
|
|
79
|
+
for message_id, data in response.items():
|
|
80
|
+
print('{id}: {size} bytes, flags={flags}'.format(
|
|
81
|
+
id=message_id,
|
|
82
|
+
size=data[b'RFC822.SIZE'],
|
|
83
|
+
flags=data[b'FLAGS']))
|
|
84
|
+
|
|
85
|
+
Why IMAPClient?
|
|
86
|
+
---------------
|
|
87
|
+
You may ask: "why create another IMAP client library for Python?
|
|
88
|
+
Doesn't the Python standard library already have imaplib?".
|
|
89
|
+
|
|
90
|
+
The problem with imaplib is that it's very low-level. It expects
|
|
91
|
+
string values where lists or tuples would be more appropriate and
|
|
92
|
+
returns server responses almost unparsed. As IMAP server responses can
|
|
93
|
+
be quite complex this means everyone using imaplib ends up writing
|
|
94
|
+
their own fragile parsing routines.
|
|
95
|
+
|
|
96
|
+
Also, imaplib doesn't make good use of exceptions. This means you need
|
|
97
|
+
to check the return value of each call to imaplib to see if what you
|
|
98
|
+
just did was successful.
|
|
99
|
+
|
|
100
|
+
IMAPClient actually uses imaplib internally. This may change at some
|
|
101
|
+
point in the future.
|
|
102
|
+
|
|
103
|
+
Installing IMAPClient
|
|
104
|
+
---------------------
|
|
105
|
+
IMAPClient is listed on PyPI and can be installed with `uv
|
|
106
|
+
<https://docs.astral.sh/uv/>`_::
|
|
107
|
+
|
|
108
|
+
uv add imapclient
|
|
109
|
+
|
|
110
|
+
More installation methods are described in the documentation.
|
|
111
|
+
|
|
112
|
+
Documentation
|
|
113
|
+
-------------
|
|
114
|
+
IMAPClient's manual is available at http://imapclient.readthedocs.io/.
|
|
115
|
+
Release notes can be found at
|
|
116
|
+
http://imapclient.readthedocs.io/#release-history.
|
|
117
|
+
|
|
118
|
+
See the `examples` directory in the root of project source for
|
|
119
|
+
examples of how to use IMAPClient.
|
|
120
|
+
|
|
121
|
+
Current Status
|
|
122
|
+
--------------
|
|
123
|
+
You should feel confident using IMAPClient for production purposes.
|
|
124
|
+
|
|
125
|
+
In order to clearly communicate version compatibility, IMAPClient
|
|
126
|
+
will strictly adhere to the `Semantic Versioning <http://semver.org>`_
|
|
127
|
+
scheme from version 1.0 onwards.
|
|
128
|
+
|
|
129
|
+
The project's home page is https://github.com/mjs/imapclient/ (this
|
|
130
|
+
currently redirects to the IMAPClient Github site). Details about
|
|
131
|
+
upcoming versions and planned features/fixes can be found in the issue
|
|
132
|
+
tracker on Github. The maintainers also blog about IMAPClient
|
|
133
|
+
news. Those articles can be found `here
|
|
134
|
+
<http://menno.io/tags/imapclient>`_.
|
|
135
|
+
|
|
136
|
+
Discussions
|
|
137
|
+
-----------
|
|
138
|
+
`Github Discussions`_ can be used to ask questions, propose changes or praise
|
|
139
|
+
the project maintainers :)
|
|
140
|
+
|
|
141
|
+
.. _`Github Discussions`: https://github.com/mjs/imapclient/discussions
|
|
142
|
+
|
|
143
|
+
Working on IMAPClient
|
|
144
|
+
---------------------
|
|
145
|
+
The `contributing documentation
|
|
146
|
+
<http://imapclient.rtfd.io/en/master/contributing.html>`_ contains
|
|
147
|
+
information for those interested in improving IMAPClient.
|
|
148
|
+
|
|
149
|
+
IMAP Servers
|
|
150
|
+
------------
|
|
151
|
+
IMAPClient is heavily tested against Dovecot, Gmail, Fastmail.fm
|
|
152
|
+
(who use a modified Cyrus implementation), Office365 and Yahoo. Access
|
|
153
|
+
to accounts on other IMAP servers/services for testing would be
|
|
154
|
+
greatly appreciated.
|
|
155
|
+
|
|
156
|
+
Interactive Console
|
|
157
|
+
-------------------
|
|
158
|
+
This script connects an IMAPClient instance using the command line
|
|
159
|
+
args given and starts an interactive session. This is useful for
|
|
160
|
+
exploring the IMAPClient API and testing things out, avoiding the
|
|
161
|
+
steps required to set up an IMAPClient instance.
|
|
162
|
+
|
|
163
|
+
The IPython shell is used if it is installed. Otherwise the
|
|
164
|
+
code.interact() function from the standard library is used.
|
|
165
|
+
|
|
166
|
+
The interactive console functionality can be accessed by running the
|
|
167
|
+
``imapclient-interact`` script that is installed alongside IMAPClient,
|
|
168
|
+
or by invoking the interact module like this::
|
|
169
|
+
|
|
170
|
+
uv run python -m imapclient.interact ...
|
|
171
|
+
|
|
172
|
+
"Live" Tests
|
|
173
|
+
------------
|
|
174
|
+
IMAPClient includes a series of live, functional tests which exercise
|
|
175
|
+
it against a live IMAP account. These are useful for ensuring
|
|
176
|
+
compatibility with a given IMAP server implementation.
|
|
177
|
+
|
|
178
|
+
The livetest functionality is run using the ``imapclient-livetest``
|
|
179
|
+
script that is installed alongside IMAPClient::
|
|
180
|
+
|
|
181
|
+
uv run imapclient-livetest <livetest.ini> [ optional unittest arguments ]
|
|
182
|
+
|
|
183
|
+
The configuration file format is
|
|
184
|
+
`described in the main documentation <http://imapclient.rtfd.io/#configuration-file-format>`_.
|
|
185
|
+
|
|
186
|
+
**WARNING**: The operations used by livetest are destructive and could
|
|
187
|
+
cause unintended loss of data. That said, as of version 0.9, livetest
|
|
188
|
+
limits its activity to a folder it creates and subfolders of that
|
|
189
|
+
folder. It *should* be safe to use with any IMAP account but please
|
|
190
|
+
don't run livetest against a truly important IMAP account.
|
|
191
|
+
|
|
192
|
+
Please include the output of imapclient-livetest with an issue if it
|
|
193
|
+
fails to run successfully against a particular IMAP server. Reports of
|
|
194
|
+
successful runs are also welcome. Please include the type and version
|
|
195
|
+
of the IMAP server, if known.
|
|
@@ -4,7 +4,6 @@ IMAPClient is an easy-to-use, Pythonic and complete IMAP client
|
|
|
4
4
|
library.
|
|
5
5
|
|
|
6
6
|
========================= ========================================
|
|
7
|
-
Current version 3.0.1
|
|
8
7
|
Supported Python versions 3.8 - 3.14
|
|
9
8
|
License New BSD
|
|
10
9
|
Project home https://github.com/mjs/imapclient/
|
|
@@ -79,9 +78,10 @@ point in the future.
|
|
|
79
78
|
|
|
80
79
|
Installing IMAPClient
|
|
81
80
|
---------------------
|
|
82
|
-
IMAPClient is listed on PyPI and can be installed with
|
|
81
|
+
IMAPClient is listed on PyPI and can be installed with `uv
|
|
82
|
+
<https://docs.astral.sh/uv/>`_::
|
|
83
83
|
|
|
84
|
-
|
|
84
|
+
uv add imapclient
|
|
85
85
|
|
|
86
86
|
More installation methods are described in the documentation.
|
|
87
87
|
|
|
@@ -139,11 +139,11 @@ steps required to set up an IMAPClient instance.
|
|
|
139
139
|
The IPython shell is used if it is installed. Otherwise the
|
|
140
140
|
code.interact() function from the standard library is used.
|
|
141
141
|
|
|
142
|
-
The interactive console functionality can be accessed running the
|
|
143
|
-
interact
|
|
144
|
-
interact module like this::
|
|
142
|
+
The interactive console functionality can be accessed by running the
|
|
143
|
+
``imapclient-interact`` script that is installed alongside IMAPClient,
|
|
144
|
+
or by invoking the interact module like this::
|
|
145
145
|
|
|
146
|
-
python -m imapclient.interact ...
|
|
146
|
+
uv run python -m imapclient.interact ...
|
|
147
147
|
|
|
148
148
|
"Live" Tests
|
|
149
149
|
------------
|
|
@@ -151,10 +151,10 @@ IMAPClient includes a series of live, functional tests which exercise
|
|
|
151
151
|
it against a live IMAP account. These are useful for ensuring
|
|
152
152
|
compatibility with a given IMAP server implementation.
|
|
153
153
|
|
|
154
|
-
The livetest functionality
|
|
155
|
-
|
|
154
|
+
The livetest functionality is run using the ``imapclient-livetest``
|
|
155
|
+
script that is installed alongside IMAPClient::
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
uv run imapclient-livetest <livetest.ini> [ optional unittest arguments ]
|
|
158
158
|
|
|
159
159
|
The configuration file format is
|
|
160
160
|
`described in the main documentation <http://imapclient.rtfd.io/#configuration-file-format>`_.
|
|
@@ -165,7 +165,7 @@ limits its activity to a folder it creates and subfolders of that
|
|
|
165
165
|
folder. It *should* be safe to use with any IMAP account but please
|
|
166
166
|
don't run livetest against a truly important IMAP account.
|
|
167
167
|
|
|
168
|
-
Please include the output of livetest
|
|
169
|
-
to run successfully against a particular IMAP server. Reports of
|
|
168
|
+
Please include the output of imapclient-livetest with an issue if it
|
|
169
|
+
fails to run successfully against a particular IMAP server. Reports of
|
|
170
170
|
successful runs are also welcome. Please include the type and version
|
|
171
171
|
of the IMAP server, if known.
|
|
@@ -8,6 +8,5 @@
|
|
|
8
8
|
from .imapclient import * # noqa: F401,F403
|
|
9
9
|
from .response_parser import * # noqa: F401,F403
|
|
10
10
|
from .tls import * # noqa: F401,F403
|
|
11
|
-
from .version import author as __author__ # noqa: F401
|
|
12
11
|
from .version import version as __version__ # noqa: F401
|
|
13
12
|
from .version import version_info # noqa: F401
|
|
@@ -40,7 +40,7 @@ def get_config_defaults() -> Dict[str, Any]:
|
|
|
40
40
|
def parse_config_file(filename: str) -> argparse.Namespace:
|
|
41
41
|
"""Parse INI files containing IMAP connection details.
|
|
42
42
|
|
|
43
|
-
Used by livetest
|
|
43
|
+
Used by imapclient.livetest and imapclient.interact
|
|
44
44
|
"""
|
|
45
45
|
|
|
46
46
|
parser = configparser.ConfigParser(get_string_config_defaults())
|
|
@@ -10,16 +10,7 @@ from typing import Optional
|
|
|
10
10
|
class IMAP4WithTimeout(imaplib.IMAP4):
|
|
11
11
|
def __init__(self, address: str, port: int, timeout: Optional[float]) -> None:
|
|
12
12
|
self._timeout = timeout
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def open(
|
|
16
|
-
self, host: str = "", port: int = 143, timeout: Optional[float] = None
|
|
17
|
-
) -> None:
|
|
18
|
-
# This is overridden to make it consistent across Python versions.
|
|
19
|
-
self.host = host
|
|
20
|
-
self.port = port
|
|
21
|
-
self.sock = self._create_socket(timeout)
|
|
22
|
-
self.file = self.sock.makefile("rb")
|
|
13
|
+
super().__init__(address, port, timeout=timeout)
|
|
23
14
|
|
|
24
15
|
def _create_socket(self, timeout: Optional[float] = None) -> socket.socket:
|
|
25
16
|
return socket.create_connection(
|
|
@@ -22,7 +22,7 @@ from .datetime_util import datetime_to_INTERNALDATE, format_criteria_date
|
|
|
22
22
|
from .imap_utf7 import decode as decode_utf7
|
|
23
23
|
from .imap_utf7 import encode as encode_utf7
|
|
24
24
|
from .response_parser import parse_fetch_response, parse_message_list, parse_response
|
|
25
|
-
from .util import assert_imap_protocol, chunk, to_bytes, to_unicode
|
|
25
|
+
from .util import assert_imap_protocol, chunk, to_bytes, to_ints, to_unicode
|
|
26
26
|
|
|
27
27
|
if hasattr(select, "poll"):
|
|
28
28
|
POLL_SUPPORT = True
|
|
@@ -830,7 +830,11 @@ class IMAPClient:
|
|
|
830
830
|
"""
|
|
831
831
|
logger.debug("< UNSELECT")
|
|
832
832
|
# IMAP4 class has no `unselect` method so we can't use `_command_and_check` there
|
|
833
|
-
|
|
833
|
+
typ, data = self._imap._simple_command("UNSELECT")
|
|
834
|
+
# Mirror imaplib.IMAP4.unselect: return the connection to the
|
|
835
|
+
# authenticated state so subsequent commands (e.g. ENABLE) are legal.
|
|
836
|
+
if typ == "OK":
|
|
837
|
+
self._imap.state = "AUTH"
|
|
834
838
|
return data[0]
|
|
835
839
|
|
|
836
840
|
def _process_select_response(self, resp):
|
|
@@ -1375,6 +1379,9 @@ class IMAPClient:
|
|
|
1375
1379
|
b'INTERNALDATE': datetime.datetime(2011, 2, 24, 19, 30, 36),
|
|
1376
1380
|
b'SEQ': 110}}
|
|
1377
1381
|
|
|
1382
|
+
Note that due to IMAP unsolicited FETCH responses the return
|
|
1383
|
+
value may include fields not matching the original data query.
|
|
1384
|
+
It is up to the caller to handle that gracefully.
|
|
1378
1385
|
"""
|
|
1379
1386
|
if not messages:
|
|
1380
1387
|
return {}
|
|
@@ -1391,7 +1398,13 @@ class IMAPClient:
|
|
|
1391
1398
|
typ, data = self._imap._command_complete("FETCH", tag)
|
|
1392
1399
|
self._checkok("fetch", typ, data)
|
|
1393
1400
|
typ, data = self._imap._untagged_response(typ, data, "FETCH")
|
|
1394
|
-
|
|
1401
|
+
response = parse_fetch_response(data, self.normalise_times, self.use_uid)
|
|
1402
|
+
# Drop unsolicited responses for other messages
|
|
1403
|
+
return {
|
|
1404
|
+
message_id: response[message_id]
|
|
1405
|
+
for message_id in to_ints(messages)
|
|
1406
|
+
if message_id in response
|
|
1407
|
+
}
|
|
1395
1408
|
|
|
1396
1409
|
def append(self, folder, msg, flags=(), msg_time=None):
|
|
1397
1410
|
"""Append a message to *folder*.
|
|
@@ -1789,7 +1802,14 @@ class IMAPClient:
|
|
|
1789
1802
|
)
|
|
1790
1803
|
if silent:
|
|
1791
1804
|
return None
|
|
1792
|
-
|
|
1805
|
+
response = parse_fetch_response(data)
|
|
1806
|
+
# Drop unsolicited responses for other messages
|
|
1807
|
+
without_unsolicited = {
|
|
1808
|
+
message_id: response[message_id]
|
|
1809
|
+
for message_id in to_ints(messages)
|
|
1810
|
+
if message_id in response
|
|
1811
|
+
}
|
|
1812
|
+
return self._filter_fetch_dict(without_unsolicited, fetch_key)
|
|
1793
1813
|
|
|
1794
1814
|
def _filter_fetch_dict(self, fetch_dict, key):
|
|
1795
1815
|
return dict((msgid, data[key]) for msgid, data in fetch_dict.items())
|
|
@@ -19,18 +19,18 @@ import unittest
|
|
|
19
19
|
from datetime import datetime
|
|
20
20
|
from email.utils import make_msgid
|
|
21
21
|
|
|
22
|
-
from
|
|
23
|
-
from
|
|
24
|
-
from
|
|
25
|
-
from
|
|
22
|
+
from .config import create_client_from_config, parse_config_file
|
|
23
|
+
from .exceptions import IMAPClientError
|
|
24
|
+
from .fixed_offset import FixedOffset
|
|
25
|
+
from .imapclient import (
|
|
26
26
|
_dict_bytes_normaliser,
|
|
27
27
|
DELETED,
|
|
28
28
|
IMAPClient,
|
|
29
29
|
RECENT,
|
|
30
30
|
SocketTimeout,
|
|
31
31
|
)
|
|
32
|
-
from
|
|
33
|
-
from
|
|
32
|
+
from .response_types import Address, Envelope
|
|
33
|
+
from .util import to_bytes, to_unicode
|
|
34
34
|
|
|
35
35
|
# TODO cleaner verbose output: avoid "__main__" and separator between classes
|
|
36
36
|
|
|
@@ -62,9 +62,7 @@ Content-Transfer-Encoding: 7bit
|
|
|
62
62
|
Here is the second part.
|
|
63
63
|
|
|
64
64
|
--===============1534046211==--
|
|
65
|
-
""".replace(
|
|
66
|
-
"\n", "\r\n"
|
|
67
|
-
)
|
|
65
|
+
""".replace("\n", "\r\n")
|
|
68
66
|
|
|
69
67
|
|
|
70
68
|
SMILE = "\u263a"
|
|
@@ -75,9 +73,7 @@ Subject: stuff
|
|
|
75
73
|
Content-Type: text/plain; charset="UTF-8"
|
|
76
74
|
|
|
77
75
|
\xe2\x98\xba
|
|
78
|
-
""".replace(
|
|
79
|
-
b"\n", b"\r\n"
|
|
80
|
-
)
|
|
76
|
+
""".replace(b"\n", b"\r\n")
|
|
81
77
|
|
|
82
78
|
|
|
83
79
|
class _TestBase(unittest.TestCase):
|
|
@@ -141,8 +141,13 @@ class BodyData(_BodyDataType):
|
|
|
141
141
|
if TYPE_CHECKING:
|
|
142
142
|
assert isinstance(part, tuple)
|
|
143
143
|
parts.append(part)
|
|
144
|
-
|
|
145
|
-
|
|
144
|
+
# The runtime representation of BodyData mixes converted
|
|
145
|
+
# BodyData/list items with raw, not-yet-converted response
|
|
146
|
+
# atoms. _BodyDataType can't precisely express this shape, so
|
|
147
|
+
# the construction below can't be typed exactly.
|
|
148
|
+
body_parts = ([cls.create(part) for part in parts],) + response[i:]
|
|
149
|
+
return cls(body_parts) # type: ignore[arg-type]
|
|
150
|
+
return cls(response) # type: ignore[arg-type]
|
|
146
151
|
|
|
147
152
|
@property
|
|
148
153
|
def is_multipart(self) -> bool:
|