Repository: paperless-ngx/paperless-ngx

Issue:
[BUG] 1.14.0-beta.rc1 password to long when setting up Microsoft 365 email account
### Description

I have completed the process of setting the app in Azure and have the access token. After I enter the required information, I click on the test button and it returns "Successfully connected to the mail server". When I click save, there is a "Saved account "HttpErrorResponse"." notification that pops up in the top right. When checking the logs in the web server docker container the last entry is "django.db.utils.DataError: (1406, "Data too long for column 'password' at row 1")".

I did originally have it behind Nginx Proxy Manager and thought maybe that was causing issues. I cleared data from docker file locations and setup the docker compose with no url env variable. Accessed it on http://<ip-address>:8001. I put in the information and still got the same error.

Example response from curl command for access token length:
{"token_type":"Bearer","expires_in":3599,"ext_expires_in":3599,"access_token":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxJJUy11S0lYb2pSR09LV0pKSUxBMW4wY1RweGciLCJhbGciOiJSUzI1NiIsIng1dCI6Ii1LSTNROW5OUjdiUm9meG1lWm9YcWJIWkdldyIsImtpZCI6Ii1LSTNROW5OUjdiUm9meG1lWm9YcWJIWkdldyJ9.eyJhdWQiOiJodHRwczovL291dGxvb2sub2ZmaWNlMzY1LmNvbSIsImlzcyI6Imh0dHBzOi8vc3RzLndpbmRvd3MubmV0L2IwMGY0YWZiLTFiODMtNGMyNy1iN2VhLWFjN2ZkMGUxODBkYS8iLCJpYXQiOjE2ODE5Mzg1NTYsIm5iZiI6MTY4MTkzODU1NiwiZXhwIjoxNjgxOTQyNDU2LCJhaW8iOiJFMlpnWVBocXBIa3l1c0Q4dlV2RmdwOEZzejN6QUE9PSIsImFwcF9kaXNwbGF5bmFtZSI6InBhcGVybGxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxMmI5ZWVjOGIyNjdjIiwiYXBwaWRhY3IiOiIxIiwiaWRwIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvYjAwZjRhZmItMWI4My00YzI3LWI3ZWEtYWM3ZmQwZTE4MGRhLyIsIm9pZCI6IjAxZWQxMjg3LTZjMmItNDZlMi1iYzM3LTNjZDc4MzIzZGM4MyIsInJoIjoiMC5BVVlBLTBvUHNJTWJKMHkzNnF4XzBPR0EyZ0lBQUFBQUFQRVB6Z0FBQUFBQUFBQ0FBQUEuIiwicm9sZXMiOlsiUE9QLkFjY2Vzc0FzQXBwIiwiSU1BUC5BY2Nlc3NBc0FwcCJdLCJzaWQiOiJiNzUxNTkyZS0zYjljLTQxMmExxxxxxxxxxxxxxxxxxxxxxxxxxxxxxWIiOiIwMWVkMTI4Ny02YzJiLTQ2ZTItYmMzNy0zY2Q3ODMyM2RjODMiLCJ0aWQiOiJiMDBmNGFmYi0xYjgzLTRjMjctYjdlYS1hYzdmZDBlMTgwZGEiLCJ1dGkiOiJqZHhWellhc0gwT2E5dkttem5VbkFBIiwidmVyIjoiMS4wIiwid2lkcyI6WyIwOTk3YTFkMC0wZDFkLTRhY2ItYjQwOC1kNWNhNzMxMjFlOTAiXX0.EZEOp_K0PYNubLnT27I2KGNaMVmnsDHx94PRSYF-iiAh_HylCxtEhcAbqCecBEq165n8ita6b86Tr8zvMxHBSFgRg6k8Pt5tipe8PEPT342ffYtpFXU2mNLXZzMQ9X9bMoskpijhXxi9RwD4M7hLBqiJiCoF-hFWLWJ0Xxi9Z7r19UGOAYUMjPqha9RgMNFU7bDeYvVMBQUqcemd_h1oyv2wutWpih382MKrDbpa42SFK14VPWv-SNSW5iURlI_eoBg3rHCpM7TCMiiafE9UYKU5m0xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}

That should be the correct number of characters for the token within the "" if I didn't miscount when replacing with x's.

I apologize if this is the incorrect location, first timer lol.

### Steps to reproduce

1. Create new mail account
2. Enter Microsoft 365 imap information
3. Check box for "Password is token"
4. Paste in access token from curl response
5. Click "Test". Get notification that it is successful.
6. Click "Save". Get HttpErrorResponse notification top right.

### Webserver logs

```bash
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 486, in thread_handler
    raise exc_info[1]
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 43, in inner
    response = await get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 448, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/usr/local/lib/python3.9/asyncio/tasks.py", line 442, in wait_for
    return await fut
  File "/usr/local/lib/python3.9/site-packages/asgiref/current_thread_executor.py", line 22, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.9/site-packages/asgiref/sync.py", line 490, in thread_handler
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 55, in wrapped_view
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/mixins.py", line 19, in create
    self.perform_create(serializer)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/mixins.py", line 24, in perform_create
    serializer.save()
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 212, in save
    self.instance = self.create(validated_data)
  File "/usr/src/paperless/src/documents/serialisers.py", line 203, in create
    instance = super().create(validated_data)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 962, in create
    instance = ModelClass._default_manager.create(**validated_data)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 671, in create
    obj.save(force_insert=True, using=self.db)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 812, in save
    self.save_base(
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 863, in save_base
    updated = self._save_table(
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 1006, in _save_table
    results = self._do_insert(
  File "/usr/local/lib/python3.9/site-packages/django/db/models/base.py", line 1047, in _do_insert
    return manager._insert(
  File "/usr/local/lib/python3.9/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 1791, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
  File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1660, in execute_sql
    cursor.execute(sql, params)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.9/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/usr/local/lib/python3.9/site-packages/django/db/backends/mysql/base.py", line 75, in execute
    return self.cursor.execute(query, args)
  File "/usr/local/lib/python3.9/site-packages/MySQLdb/cursors.py", line 206, in execute
    res = self._query(query)
  File "/usr/local/lib/python3.9/site-packages/MySQLdb/cursors.py", line 320, in _query
    self._do_get_result(db)
  File "/usr/local/lib/python3.9/site-packages/MySQLdb/cursors.py", line 145, in _do_get_result
    self._result = result = self._get_result()
  File "/usr/local/lib/python3.9/site-packages/MySQLdb/cursors.py", line 352, in _get_result
    return self._get_db().store_result()
django.db.utils.DataError: (1406, "Data too long for column 'password' at row 1")
```


### Browser logs

_No response_

### Paperless-ngx version

1.14.0-beta.rc1

### Host OS

Ubuntu 22.04.2

### Installation method

Docker - official image

### Browser

Brave

### Configuration changes

_No response_

### Other

_No response_


Discussion:
Well, the password field has a max length of 256 characters.  If I'm understanding what portion is the access token above, it's 1540.  That's a massive length.  Is that standard or some sort of ultra security setting?
Yea that seems long. Not sure if @Craneson or anyone else can verify, but looking around a little e.g. this video: https://youtu.be/bMYA-146dmM?t=1003 & https://stackoverflow.com/questions/32183696/what-is-the-maximum-length-of-the-oauth-token-given-by-azure-active-directory-in it does seem to be the case
It seems alright to increase the length to something more, like 2048.  I can't imagine a token being longer

Resolving patch:
diff --git a/src/paperless_mail/migrations/0021_alter_mailaccount_password.py b/src/paperless_mail/migrations/0021_alter_mailaccount_password.py
new file mode 100644
--- /dev/null
+++ b/src/paperless_mail/migrations/0021_alter_mailaccount_password.py
@@ -0,0 +1,17 @@
+# Generated by Django 4.1.7 on 2023-04-20 15:03
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("paperless_mail", "0020_mailaccount_is_token"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="mailaccount",
+            name="password",
+            field=models.CharField(max_length=2048, verbose_name="password"),
+        ),
+    ]
diff --git a/src/paperless_mail/models.py b/src/paperless_mail/models.py
--- a/src/paperless_mail/models.py
+++ b/src/paperless_mail/models.py
@@ -36,7 +36,7 @@ class ImapSecurity(models.IntegerChoices):
 
     username = models.CharField(_("username"), max_length=256)
 
-    password = models.CharField(_("password"), max_length=256)
+    password = models.CharField(_("password"), max_length=2048)
 
     is_token = models.BooleanField(_("Is token authentication"), default=False)
 


Test patch: