Repository: Mailu/Mailu

Issue:
Cannot create aliases anymore
## Environment & Versions
### Environment
 - docker-compose

### Versions
master

## Description
Clicking save on a new alias leads to an "Internal Server Error" page.

## Replication Steps
Open the form to add a new alias to an email account, fill out the form, click save.

## Expected behaviour
The alias is added normally.

## Logs
```
admin_1      | /usr/lib/python3.8/site-packages/sqlalchemy/sql/crud.py:799: SAWarning: Column 'alias.email' is marked as a member of the prima[15/984]
or table 'alias', but has no Python-side or server-side default generator indicated, nor does it indicate 'autoincrement=True' or 'nullable=True', and
 no explicit value is passed.  Primary key columns typically may not store NULL.                        
admin_1      |   util.warn(msg)                                                                                                                       
admin_1      | [2021-07-21 14:43:14,316] ERROR in app: Exception on /ui/alias/create/***.** [POST]                
admin_1      | Traceback (most recent call last):                                                                                                     
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1243, in _execute_context
admin_1      |     self.dialect.do_execute(                                                                                                           
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
admin_1      |     cursor.execute(statement, parameters)                                                                                              
admin_1      | sqlite3.IntegrityError: NOT NULL constraint failed: alias.email            
admin_1      |                                                                                                                                        
admin_1      | The above exception was the direct cause of the following exception:                                                                   
admin_1      |                                                                                                                                        
admin_1      | Traceback (most recent call last):                          
admin_1      |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 2292, in wsgi_app                                                         
admin_1      |     response = self.full_dispatch_request()                                                                                            
admin_1      |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1815, in full_dispatch_request
admin_1      |     rv = self.handle_user_exception(e)
admin_1      |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1718, in handle_user_exception
admin_1      |     reraise(exc_type, exc_value, tb)
admin_1      |   File "/usr/lib/python3.8/site-packages/flask/_compat.py", line 35, in reraise
admin_1      |     raise value
admin_1      |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1813, in full_dispatch_request
admin_1      |     rv = self.dispatch_request()
admin_1      |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1799, in dispatch_request
admin_1      |     return self.view_functions[rule.endpoint](**req.view_args)
admin_1      |   File "/usr/lib/python3.8/site-packages/flask_login/utils.py", line 261, in decorated_view
admin_1      |     return func(*args, **kwargs)
admin_1      |   File "/app/mailu/ui/access.py", line 28, in wrapper
admin_1      |     return callback(function, args, kwargs, dargs, dkwargs)
admin_1      |   File "/app/mailu/ui/access.py", line 19, in callback
admin_1      |     return function(*args, **kwargs)
admin_1      |   File "/app/mailu/ui/views/aliases.py", line 31, in alias_create
admin_1      |     models.db.session.commit()
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/scoping.py", line 162, in do
admin_1      |     return getattr(self.registry(), name)(*args, **kwargs)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1026, in commit
admin_1      |     self.transaction.commit()
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 493, in commit
admin_1      |     self._prepare_impl()
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 472, in _prepare_impl
admin_1      |     self.session.flush()
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2451, in flush
admin_1      |     self._flush(objects)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2589, in _flush
admin_1      |     transaction.rollback(_capture_exception=True)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
admin_1      |     compat.reraise(exc_type, exc_value, exc_tb)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 129, in reraise
admin_1      |     raise value
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2549, in _flush
admin_1      |     flush_context.execute()
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/unitofwork.py", line 422, in execute
admin_1      |     rec.execute(self)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/unitofwork.py", line 586, in execute
admin_1      |     persistence.save_obj(
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/persistence.py", line 239, in save_obj
admin_1      |     _emit_insert_statements(
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/persistence.py", line 1119, in _emit_insert_statements
admin_1      |     result = cached_connections[connection].execute(
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 988, in execute
admin_1      |     return meth(self, multiparams, params)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
admin_1      |     return connection._execute_clauseelement(self, multiparams, params)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1101, in _execute_clauseelement
admin_1      |     ret = self._execute_context(
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1247, in _execute_context
admin_1      |     self._handle_dbapi_exception(
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1466, in _handle_dbapi_exception
admin_1      |     util.raise_from_cause(sqlalchemy_exception, exc_info)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 383, in raise_from_cause
admin_1      |     reraise(type(exception), exception, tb=exc_tb, cause=cause)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 128, in reraise
admin_1      |     raise value.with_traceback(tb)
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1243, in _execute_context
admin_1      |     self.dialect.do_execute(
admin_1      |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
admin_1      |     cursor.execute(statement, parameters)
admin_1      | sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: alias.email
admin_1      | [SQL: INSERT INTO alias (created_at, updated_at, comment, localpart, wildcard, destination, domain_name) VALUES (?, ?, ?, ?, ?, ?, ?)]
admin_1      | [parameters: ('2021-07-21', None, '', 'newalias', 0, 'account@***.**', '***.**')]
admin_1      | (Background on this error at: http://sqlalche.me/e/gkpj)
```



Discussion:
@cobrafast I encountered exactly the same problem when creating a new alias on `master`. You reported this 4 hours earlier independent from me:

```
mailu_admin        | /usr/lib/python3.8/site-packages/sqlalchemy/sql/crud.py:799: SAWarning: Column 'alias.email' is marked as a member of the primary key for table 'alias', but has no Python-side or server-side default generator indicated, nor does it indicate 'autoincrement=True' or 'nullable=True', and no explicit value is passed.  Primary key columns typically may not store NULL.
mailu_admin        |   util.warn(msg)
mailu_admin        | [2021-07-21 19:07:35,443] ERROR in app: Exception on /ui/alias/create/mydomain.nl [POST]
mailu_admin        | Traceback (most recent call last):
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1243, in _execute_context
mailu_admin        |     self.dialect.do_execute(
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
mailu_admin        |     cursor.execute(statement, parameters)
mailu_admin        | sqlite3.IntegrityError: NOT NULL constraint failed: alias.email
mailu_admin        | 
mailu_admin        | The above exception was the direct cause of the following exception:
mailu_admin        | 
mailu_admin        | Traceback (most recent call last):
mailu_admin        |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 2292, in wsgi_app
mailu_admin        |     response = self.full_dispatch_request()
mailu_admin        |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1815, in full_dispatch_request
mailu_admin        |     rv = self.handle_user_exception(e)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1718, in handle_user_exception
mailu_admin        |     reraise(exc_type, exc_value, tb)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/flask/_compat.py", line 35, in reraise
mailu_admin        |     raise value
mailu_admin        |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1813, in full_dispatch_request
mailu_admin        |     rv = self.dispatch_request()
mailu_admin        |   File "/usr/lib/python3.8/site-packages/flask/app.py", line 1799, in dispatch_request
mailu_admin        |     return self.view_functions[rule.endpoint](**req.view_args)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/flask_login/utils.py", line 261, in decorated_view
mailu_admin        |     return func(*args, **kwargs)
mailu_admin        |   File "/app/mailu/ui/access.py", line 28, in wrapper
mailu_admin        |     return callback(function, args, kwargs, dargs, dkwargs)
mailu_admin        |   File "/app/mailu/ui/access.py", line 19, in callback
mailu_admin        |     return function(*args, **kwargs)
mailu_admin        |   File "/app/mailu/ui/views/aliases.py", line 31, in alias_create
mailu_admin        |     models.db.session.commit()
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/scoping.py", line 162, in do
mailu_admin        |     return getattr(self.registry(), name)(*args, **kwargs)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 1026, in commit
mailu_admin        |     self.transaction.commit()
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 493, in commit
mailu_admin        |     self._prepare_impl()
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 472, in _prepare_impl
mailu_admin        |     self.session.flush()
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2451, in flush
mailu_admin        |     self._flush(objects)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2589, in _flush
mailu_admin        |     transaction.rollback(_capture_exception=True)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
mailu_admin        |     compat.reraise(exc_type, exc_value, exc_tb)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 129, in reraise
mailu_admin        |     raise value
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/session.py", line 2549, in _flush
mailu_admin        |     flush_context.execute()
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/unitofwork.py", line 422, in execute
mailu_admin        |     rec.execute(self)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/unitofwork.py", line 586, in execute
mailu_admin        |     persistence.save_obj(
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/persistence.py", line 239, in save_obj
mailu_admin        |     _emit_insert_statements(
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/orm/persistence.py", line 1119, in _emit_insert_statements
mailu_admin        |     result = cached_connections[connection].execute(
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 988, in execute
mailu_admin        |     return meth(self, multiparams, params)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/sql/elements.py", line 287, in _execute_on_connection
mailu_admin        |     return connection._execute_clauseelement(self, multiparams, params)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1101, in _execute_clauseelement
mailu_admin        |     ret = self._execute_context(
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1247, in _execute_context
mailu_admin        |     self._handle_dbapi_exception(
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1466, in _handle_dbapi_exception
mailu_admin        |     util.raise_from_cause(sqlalchemy_exception, exc_info)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 383, in raise_from_cause
mailu_admin        |     reraise(type(exception), exception, tb=exc_tb, cause=cause)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/util/compat.py", line 128, in reraise
mailu_admin        |     raise value.with_traceback(tb)
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/base.py", line 1243, in _execute_context
mailu_admin        |     self.dialect.do_execute(
mailu_admin        |   File "/usr/lib/python3.8/site-packages/sqlalchemy/engine/default.py", line 552, in do_execute
mailu_admin        |     cursor.execute(statement, parameters)
mailu_admin        | sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: alias.email
mailu_admin        | [SQL: INSERT INTO alias (created_at, updated_at, comment, localpart, wildcard, destination, domain_name) VALUES (?, ?, ?, ?, ?, ?, ?)]
mailu_admin        | [parameters: ('2021-07-21', None, '', 'user', 0, '', 'mydomain.nl')]
mailu_admin        | (Background on this error at: http://sqlalche.me/e/gkpj)
```

```bash
$ git log
commit 0031f262cc7c8351687d12dc04a0c0d80183d6ac (HEAD -> master, origin/master, origin/HEAD)
Merge: d010f1d3 1d65529c
Author: bors[bot] <26634292+bors[bot]@users.noreply.github.com>
Date:   Tue Jul 20 12:13:19 2021 +0000
```

Any ideas?
Issue is reproducible with latest `master` and empty Docker volume:
* Ubuntu desktop 21.04 AMD64
* Raspberry Pi 4 ARM64 Ubuntu server 20.04
```
Alias broken:
	commit fbd945390d32a3804ef8abd3b5c98e479890ddef (HEAD)
	Author: Alexander Graf <ghostwheel42@users.noreply.github.com>
	Date:   Tue Jun 29 16:13:04 2021 +0200

Internal server error after login:
	commit 6dc1a1939043efd5b3cc52137c4292a157fe8f33 (HEAD)
	Merge: 21a362fd fc1a663d
	Author: Dimitri Huisman <52963853+Diman0@users.noreply.github.com>
	Date:   Tue Jun 29 15:26:51 2021 +0200

Alias works:
	commit fc1a663da2aeb8775dbfa29b01cf065cf237476c (HEAD)
	Merge: 4ff90683 dd3d03f0
	Author: bors[bot] <26634292+bors[bot]@users.noreply.github.com>
	Date:   Tue Jun 29 12:32:21 2021 +0000
```
@ghostwheel42 ^ can you have a look please?
It should still be possible to add the aliases via the cli config-update command. See https://mailu.io/master/cli.html#config-update for more info.
Thanks @Diman0. The following command works:

```bash
docker-compose exec admin flask mailu alias foo example.net "mail1@example.com,mail2@example.com"
```

I'm now switched to 1.8 branch which works.

Resolving patch:
diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py
--- a/core/admin/mailu/models.py
+++ b/core/admin/mailu/models.py
@@ -371,8 +371,8 @@ def _update_domain_name(target, value, *_):
     @classmethod
     def __declare_last__(cls):
         # gets called after mappings are completed
-        sqlalchemy.event.listen(User.localpart, 'set', cls._update_localpart, propagate=True)
-        sqlalchemy.event.listen(User.domain_name, 'set', cls._update_domain_name, propagate=True)
+        sqlalchemy.event.listen(cls.localpart, 'set', cls._update_localpart, propagate=True)
+        sqlalchemy.event.listen(cls.domain_name, 'set', cls._update_domain_name, propagate=True)
 
     def sendmail(self, subject, body):
         """ send an email to the address """


Test patch: