2899 Commits

Author SHA1 Message Date
Rodolfo García Peñas (kix) d16afe503d Merge branch 'pr-241' into testing 2026-04-25 11:24:02 +02:00
Michael Hohmuth d4ccbbb049 Prevent deadlock in IMAPServer.close when using 'maxsyncaccounts' and 'maxconnections'.
We introduce a separate closing flag that's checked in
acquireconnection, decoupling the connectionlock from the semaphore
such that they can be acquired separately.

Signed-off-by: Michael Hohmuth <hohmuth@sax.de>
2026-04-24 14:27:20 +02:00
Rodolfo García Peñas (kix) 854f3891aa Robustly handle dead sockets during authentication by retrying the connection
This commit addresses issues where certain IMAP servers (like Protonmail Bridge)
abruptly close the socket during the authentication phase.

Following a simplified approach:
1. Updated __authn_helper to initiate STARTTLS unconditionally at the
   beginning of the loop.
2. Modified acquireconnection to catch OfflineImapError. If the socket is
   detected as dead during authentication, it now logs a warning and retries
   the entire connection process from scratch (up to 3 attempts).
3. This ensures each retry starts with a fresh connection and all configured
   authentication methods available, avoiding permanent list modification.
2026-04-20 09:43:37 +02:00
Rodolfo García Peñas (kix) 915dd0a510 Revert "fix: handle dead sockets during authentication by retrying remaining methods via AuthMethodSocketDeadError"
This reverts commit 38da540f99.
2026-04-20 09:14:30 +02:00
Rodolfo García Peñas (kix) 2afacde485 Merge branch 'fix-issue-31' into testing 2026-04-19 12:07:50 +02:00
Rodolfo García Peñas (kix) 2175481478 Update .travis.yml to use Python 3 (Closes #31)
The original Travis CI configuration was outdated, still targeting Python 2.7.
This commit updates the test matrix to include all supported Python 3 versions (3.6 through 3.13) to match the project's goals.

Additionally:
- Set dist: jammy (Ubuntu 22.04) for Linux builds to support modern Python versions.
- Updated the macOS (OSX) environment to use Python 3.12.0 for its tests.
2026-04-19 12:07:11 +02:00
Rodolfo García Peñas (kix) e722e8cf49 Merge branch 'ps-tls_stripping' into testing 2026-04-19 10:42:41 +02:00
Rodolfo García Peñas (kix) 38da540f99 fix: handle dead sockets during authentication by retrying remaining methods via AuthMethodSocketDeadError
Certain IMAP servers (like Protonmail Bridge) suffer from bugs where they hang and drop the connection when receiving specific authentication commands (such as `AUTHENTICATE PLAIN` immediately after STARTTLS). Previously, if the socket died during an authentication attempt, offlineimap would abort the entire synchronization process immediately.

This commit introduces `AuthMethodSocketDeadError` to handle this scenario gracefully. When an authentication mechanism kills the socket, it is temporarily removed from the list of available mechanisms for that session. Offlineimap then reconnects and retries the remaining authentication mechanisms (e.g., falling back from PLAIN to LOGIN), allowing synchronization to continue successfully without entering an infinite loop.
2026-04-19 10:42:09 +02:00
Rodolfo García Peñas (kix) 177145e7cf Fix TLS stripping vulnerability when STARTTLS is requested (Issue #222)
ç
When a user sets `starttls = yes`, offlineimap expects to negotiate a secure TLS tunnel. However, if a MITM attacker intercepts the connection and removes the `STARTTLS` capability from the server's greeting, the `if 'STARTTLS' in imapobj.capabilities` check fails silently. This causes offlineimap to skip TLS negotiation and proceed to send credentials in plaintext.

This commit introduces a strict check in `__start_tls()`: if the user requested STARTTLS but the server does not advertise it, offlineimap will immediately abort with a clear error message, protecting the user's password from being exposed. To connect insecurely, the user must explicitly set `starttls = no`.
2026-04-19 10:37:19 +02:00
Rodolfo García Peñas (kix) 1680e0c623 Merge branch 'pr-239' into testing 2026-04-19 10:04:35 +02:00
Rodolfo García Peñas (kix) 0185b11255 Fix UnicodeEncodeError on emails with malformed bytes
When fetching emails with defects or malformed bytes (e.g., spam or broken
MIME boundaries), the Python 3 `email.parser` handles un-decodable bytes
by safely substituting them with the Unicode Replacement Character `\ufffd`
(using the `errors='replace'` handler by default).

However, a problem arises during the `_fetch_from_imap` sync process when
OfflineIMAP3 tests if the message can be serialized back to bytes via
`as_bytes()`. If the malformed text part was originally declared as
`us-ascii` (or left unspecified, defaulting to ASCII), Python attempts to
encode the `\ufffd` string back to bytes using the ASCII codec. Since `\ufffd`
is out of the ASCII range, this triggers a `UnicodeEncodeError`, causing
OfflineIMAP3 to raise an `OfflineImapError` and entirely skip syncing the
message.

This commit fixes the issue by catching the `UnicodeEncodeError` when
`as_bytes()` fails. It then walks through the message parts, identifies
the text payloads that cannot be encoded with their current charset, and
dynamically forces their charset to `utf-8`. This allows Python to safely
encode the `\ufffd` character (automatically applying base64/quoted-printable
transfer encoding if needed), successfully serializing the message so it
can be synced without crashing.

Closes #240
Closes #229
Closes #224
Closes #160
2026-04-18 23:10:29 +02:00
Rodolfo García Peñas (kix) 8209ac20a7 Update Changelog.md for v8.0.2 v8.0.2 2026-04-11 14:49:10 +02:00
Derek Schrock 4d300783c7 Use correct IMAP folder name with imapobj.select
Like other imapobj.select translate it vi
imaputil.foldername_to_imapname
2026-04-05 19:34:12 -04:00
Rodolfo García Peñas (kix) 1c30a62d7b Merge branch 'v802' into testing 2026-04-06 00:15:19 +02:00
Rodolfo García Peñas (kix) 461ea973f6 Version bump to 8.0.2, update .gitignore for PyPI files, and remove setup.py.
This patch updates the version number to 8.0.2 in both pyproject.toml and offlineimap/__init__.py, removes the now-obsolete setup.py file, and adds a line to .gitignore to ignore the /dist directory where PyPI distribution files are generated.
2026-04-06 00:14:52 +02:00
Rodolfo García Peñas (kix) 196a045ab2 Merge branch 'pr-crash1' into testing 2026-04-05 11:10:49 +02:00
Rodolfo García Peñas (kix) 8122b6c03f Quick remote folder retrieval error handling
This patch adds error handling for the retrieval of remote folders in the `SyncableAccount` class. If an error occurs while getting the remote folders, a warning message is logged, and the account is skipped, allowing the synchronization process to continue with the next account.
2026-04-05 09:57:58 +02:00
Rodolfo García Peñas (kix) 3a5565bb5a Catch errors with remote folders
This patch adds error handling when fetching remote folders. If an error occurs, it logs a warning and continues with the next account instead of crashing the entire sync process.
2026-04-05 09:57:09 +02:00
Rodolfo García Peñas (kix) c0500d48c9 Merge branch 'pr-check-pool' into testing 2026-04-04 20:17:56 +02:00
Rodolfo García Peñas (kix) 9324259deb Check socket health before returning pooled connection
This patch adds a health check for pooled IMAP connections in the acquireconnection() method. After acquiring a connection from the pool, it sends a NOOP command to verify that the connection is still alive. If the NOOP command fails, it logs the failure, cleans up the stale connection, and recursively calls acquireconnection() to get a new one. This helps ensure that clients receive healthy connections from the pool and reduces the likelihood of encountering errors due to stale connections.
2026-04-04 20:03:17 +02:00
Rodolfo García Peñas (kix) 59663f77f2 Check if the socket is alive
This patch adds a helper function `_is_socket_alive` that checks if the underlying socket connection of an IMAP object is still usable. It uses `select` to check for readability and errors on the socket, and also checks if the socket has been closed by the peer. This function is called before attempting authentication methods to avoid long timeouts if the socket is already dead (e.g., after a failed STARTTLS). If the socket is found to be broken, it logs a debug message and aborts further authentication attempts.
2026-04-04 19:35:10 +02:00
Rodolfo García Peñas (kix) 6bb5280941 Merge branch 'pr-capa2extra' into testing 2026-04-04 17:39:21 +02:00
Rodolfo García Peñas (kix) 4b97c358a8 Do not shutdown the socket in start_tls
This commit removes the redundant shutdown() calls in start_tls() and acquireconnection() that were added to work around a TLS connection failure. The shutdown() calls were causing spurious warnings in the cleanup chain when the socket was already closed. The TLS connection failure should now be handled by the exception raised in start_tls() without needing to shutdown the socket again.

This avoid problems with the socket being closed twice and generating warnings, while still properly handling the TLS connection failure. The exception raised in start_tls() will indicate the failure without needing to shutdown the socket again.
2026-04-04 17:37:19 +02:00
Rodolfo García Peñas (kix) 0ed2ea4555 Merge branch 'pr-capa2' into testing 2026-04-04 13:46:43 +02:00
Rodolfo García Peñas (kix) ec7a4a95ae Solve imaplib2 hangs on STARTTLS
This patch works around imaplib2's unconditional CAPABILITY call after the TLS handshake, which causes a 60-second hang with servers like Protonmail Bridge that do not respond to CAPABILITY at that stage. The workaround temporarily substitutes a no-op for imaplib2's _get_capabilities method during the handshake, allowing it to set _tls_established=True without triggering the problematic CAPABILITY call. The patch also guards against a redundant second shutdown() call on the same socket, which can raise [Errno 9] Bad file descriptor and generate spurious warnings in the cleanup chain.
2026-04-04 13:45:34 +02:00
Rodolfo García Peñas (kix) f5b461b183 Merge branch 'pr-238' into testing 2026-04-03 10:11:42 +02:00
Rodolfo García Peñas (kix) 94c691df00 Merge branch 'pr-236' into testing 2026-04-03 10:11:18 +02:00
Rodolfo García Peñas (kix) 8bedeca880 Merge branch 'pr-235' into testing 2026-04-03 10:10:49 +02:00
Rodolfo García Peñas (kix) ccc25bfced Merge branch 'pr-232' into testing 2026-04-03 10:10:19 +02:00
Rodolfo García Peñas (kix) 419e5bbafd Merge branch 'pr-231' into testing 2026-04-03 10:09:51 +02:00
Franklin Bynum 25238dc6eb Update distro_utils.py
Add relocated CA bundle for Fedora 44
2026-04-01 21:46:22 -05:00
serge-sans-paille 9c352d7d9c Always pass an exception as first argument of ui.error
In various cases we were passing string messages, which is incompatible
with how ui.error handles its argument, leading to bugs like #233

Fix #233

Signed-off-by: serge-sans-paille <sergesanspaille@free.fr>
2026-04-01 08:05:12 +02:00
Volker Eckert addf5d6dec docs/doc-src/conf.py: fix intersphinx_mapping config syntax
Signed-off-by: Volker Eckert <volker@maxfinite.com>
2026-03-01 02:08:01 +00:00
Stephen Huan 649e518d74 Change keyring[keyring] -> keyring in setup.py
For consistency with pyproject.toml and requirements-keyring.txt.

Signed-off-by: Stephen Huan <stephen.huan@cgdct.moe>
2026-01-28 16:01:41 -05:00
Stephen Huan 950e7914be Add PySocks optional-dependencies
PySocks is used for the optional proxy feature.

Signed-off-by: Stephen Huan <stephen.huan@cgdct.moe>
2026-01-28 16:01:41 -05:00
Stephen Huan 7b67dbd7e5 Move urllib3 from dependencies to testinternet
It appears urllib3 is only used in contrib/internet-urllib3.py, so put
it with certifi in the `testinternet` optional-dependencies group.

Signed-off-by: Stephen Huan <stephen.huan@cgdct.moe>
2026-01-28 16:01:36 -05:00
Stephen Huan 0a4dab2896 Remove deprecated classifiers, specify gplv2+
After PEP 639 the `license` field in pyproject.toml is
no longer a table but a SPDX Expression containing a
License Identifier. This fixes the following warning.

********************************************************************************
Please use a simple string containing a SPDX expression for `project.license`. You can also use `project.license-files`. (Both options available on setuptools>=77.0.0).

By 2026-Feb-18, you need to update your project and remove deprecated calls
or your builds will no longer be supported.

See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details.
********************************************************************************

In addition, be more consistent about the license
being GPL v2.0 or later (as opposed to v2 only).

Signed-off-by: Stephen Huan <stephen.huan@cgdct.moe>
2026-01-28 13:25:51 -05:00
Rodolfo García Peñas (kix) bcf2238db5 Version 8.0.1 v8.0.1 2025-10-28 20:22:31 +01:00
Rodolfo García Peñas (kix) f14cead44f Merge branch 'master' of https://github.com/OfflineIMAP/offlineimap3 2025-10-28 16:20:36 +01:00
Rodolfo García Peñas (kix) 5f5ad420b7 Merge pull request #227 from derekschrock/depwarning
Fix DeprecationWarnings regex raw string and ConfigParser
2025-10-26 19:49:39 +01:00
Rodolfo García Peñas (kix) 08653dd8a5 Merge pull request #206 from lucrocha/lrocha/offlineimap.conf-regex-raw-string
offlineimap.conf: use raw strings in regex examples
2025-10-26 19:48:20 +01:00
Rodolfo García Peñas (kix) e4bcb82aaf Merge pull request #205 from tucksaun/fix/machinery
fix: "module importlib has no attribute 'machinery'"
2025-10-26 19:48:08 +01:00
Derek Schrock 2a8c6dc385 Fix DeprecationWarnings regex raw string and ConfigParser
- Make regex a raw string.
- Use parser.read_file()
2025-10-12 00:13:19 -04:00
Luciano Rocha 1cbc0755e3 offlineimap.conf: use raw strings in regex examples
Newer pythons are strict on the escape sequences allowed in normal
strings, which can cause issues with regular expressions as most of them
do include escape sequences that are not allowed. In those cases, the
process will exit with the confusing warning:
  <string>:1: SyntaxWarning: invalid escape sequence '\.'

To help prevent such cases, have the sample configuration use raw
strings when using regular expressions.

Signed-off-by: Luciano Rocha <lfrocha@gmail.com>
2024-09-12 12:00:12 -07:00
Tugdual Saunier 4c64d72882 fix: "module importlib has no attribute 'machinery'"
Since the merge of #190, the following errors happens:
```
ERROR: module 'importlib' has no attribute 'machinery'
ERROR: Exceptions occurred during the run!
ERROR: AttributeError: module 'importlib' has no attribute 'machinery'
```
This commit should fix this by importing the required package.
2024-09-03 09:32:39 +02:00
Rodolfo García Peñas (kix) 1ae217fefa Avoid crash if no connection with server
This patch allow run OfflineIMAP without connection with the server,
therefore the application is running and do not crash if the connection
fails or the network is temporaly down.
2024-08-28 01:13:05 +02:00
Rodolfo García Peñas (kix) db34745227 Merge pull request #154 from keithbowes/extra-search-paths
Find extra paths for default CA bundle through the SSL module if possible (Python 3.4+)
2024-08-26 18:14:57 +02:00
Rodolfo García Peñas (kix) 07c186e54c Merge pull request #204 from derekschrock/freebsd
Add FreeBSD pkg search/install to install examples
2024-08-26 18:06:23 +02:00
Rodolfo García Peñas (kix) 4f5b2529e4 Full packaging review
This patch includes a lot of changes:

1. Split the `requirements.txt` file in multiple files. This change holds
   the required packages for OfflineIMAP in the `requirements.txt` file.
   The optional packages are included in the files `requirements-option.txt`
   files. Now the standard OfflineIMAP configuration does not include
   packages like `cygwin`. See for example issue #192.
2. The `setup.py` process includes a lot of files (see issue #110). This
   creates a problem in the setup process, because some libraries are not
   found (see #39, the problem still happends). For this reason we can
   read the variables from the `offlineimap/__init__py` to include them
   in the `setup.py` script, without import the `offlineimap` module. I
   used the method presented at `https://www.youtube.com/watch?v=fHNhhHMUW7k`.
   In the setup module we don't need the testing code (it creates the import
   problem too), so this code is removed. To read the variables, we use
   some regex search in the `offlineimap/__init__py` file, save the
   values as variables, and then use them in the `setup()` call.
3. `setup.py` uses requires and extra_requires libraries, aligned with
   the `requirements` files. We use four different options: `kerberos`,
   `keyring`, `cygwin`, `cygwin` and `testinternet`.
4. `pyproject.toml`. This file is fully rewritten. The file use now the
   right dependencies, includes the optional dependencies aligned with
   the requirements and the `setup.py` files. The file include other
   details, like classifiers, URLs,... This script uses now the the
   `project.scripts` option, with the module and the method to call when
   the setup file is created. Then, this script includes as module
   `offlineimap.init`, and the startup method is `main`. Because this
   method is new, this method and the `__main__` functions are created
   in the `offlineimap/init.py` file:

        ```python
        def main():
            oi = OfflineImap()
            oi.run()

        if __name__ == "__main__":
            main()
        ```
With these changes, the setup process works fine, with and without
optional modules. Finally, the folder `offlineimap.egg-info`,
created in the setup process is included in the `.gitignore` file.

It is possible check the creation using:

```python
python -m pip install .
```

And then use the command `offilineimap` to use the module. Finally, the
`bin/offlineimap` command is not used, so we probably can remove it.

Fix: #192, Fix: #110, Fix: #39, Fix: #90
2024-08-26 18:01:14 +02:00
Derek Schrock 0c2433c5c1 Add FreeBSD pkg search/install to install examples 2024-08-25 16:25:36 -04:00