# Buggy code
def release(request, mail_id):
    """Release message selection.

    :param str mail_id: message unique identifier
    """
    mail_id = check_mail_id(request, mail_id)
    msgrcpts = []
    wrapper = get_wrapper()
    mb = (
        Mailbox.objects.get(user=request.user)
        if request.user.group == "SimpleUsers"
        else None
    )
    for mid in mail_id:
        r, i = mid.split()
        if mb is not None and r != mb.full_address and not r in mb.alias_addresses:
            continue
        msgrcpts += [wrapper.get_recipient_message(r, i)]
    if mb is not None and parameters.get_admin("USER_CAN_RELEASE") == "no":
        # FIXME : can't use this syntax because extra SQL (using
        # .extra() for postgres) is not propagated (the 'tables'
        # parameter is lost somewhere...)
        #
        # msgrcpts.update(rs='p')
        for msgrcpt in msgrcpts:
            msgrcpt.rs = "p"
            msgrcpt.save()
        message = ungettext(
            "%(count)d request sent", "%(count)d requests sent", len(mail_id)
        ) % {"count": len(mail_id)}
        return ajax_response(
            request,
            "ok",
            respmsg=message,
            url=QuarantineNavigationParameters(request).back_to_listing(),
        )

    amr = AMrelease()
    error = None
    for rcpt in msgrcpts:
        result = amr.sendreq(rcpt.mail.mail_id, rcpt.mail.secret_id, rcpt.rid.email)
        if result:
            rcpt.rs = "R"
            rcpt.save()
        else:
            error = result
            break

    if not error:
        message = ungettext(
            "%(count)d message released successfully",
            "%(count)d messages released successfully",
            len(mail_id),
        ) % {"count": len(mail_id)}
    else:
        message = error
    return ajax_response(
        request,
        "ko" if error else "ok",
        respmsg=message,
        url=QuarantineNavigationParameters(request).back_to_listing(),
    )


# Traceback (IntegrityError)
Internal Server Error: /quarantine/process/
Traceback (most recent call last):
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/modoboa/extensions/amavis/views.py", line 307, in process
return release(request, ids)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/modoboa/extensions/amavis/lib.py", line 30, in wrapped_f
return f(request, *args, **kwargs)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/modoboa/extensions/amavis/views.py", line 282, in release
rcpt.save()
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/models/base.py", line 546, in save
force_update=force_update, update_fields=update_fields)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/models/base.py", line 626, in save_base
rows = manager.using(using).filter(pk=pk_val)._update(values)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/models/query.py", line 605, in _update
return query.get_compiler(self.db).execute_sql(None)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1020, in execute_sql
cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 846, in execute_sql
cursor.execute(sql, params)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/backends/util.py", line 41, in execute
return self.cursor.execute(sql, params)
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 122, in execute
six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
File "/srv/modoboa/python-virtualenv-modoboa-1.1.1/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 120, in execute
return self.cursor.execute(query, args)
File "/usr/lib/python2.7/dist-packages/MySQLdb/cursors.py", line 174, in execute
self.errorhandler(self, exc, value)
File "/usr/lib/python2.7/dist-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
raise errorclass, errorvalue
IntegrityError: (1062, "Duplicate entry '0-NTFOxSLhytYl-1' for key 'PRIMARY'")

# Fixed code
def release(request, mail_id):
    """Release message selection.

    :param str mail_id: message unique identifier
    """
    mail_id = check_mail_id(request, mail_id)
    msgrcpts = []
    wrapper = get_wrapper()
    mb = (
        Mailbox.objects.get(user=request.user)
        if request.user.group == "SimpleUsers"
        else None
    )
    for mid in mail_id:
        r, i = mid.split()
        if mb is not None and r != mb.full_address and not r in mb.alias_addresses:
            continue
        msgrcpts += [wrapper.get_recipient_message(r, i)]
    if mb is not None and parameters.get_admin("USER_CAN_RELEASE") == "no":
        for msgrcpt in msgrcpts:
            wrapper.set_msgrcpt_status(msgrcpt.rid.email, msgrcpt.mail.mail_id, "p")
        message = ungettext(
            "%(count)d request sent", "%(count)d requests sent", len(mail_id)
        ) % {"count": len(mail_id)}
        return ajax_response(
            request,
            "ok",
            respmsg=message,
            url=QuarantineNavigationParameters(request).back_to_listing(),
        )

    amr = AMrelease()
    error = None
    for rcpt in msgrcpts:
        result = amr.sendreq(rcpt.mail.mail_id, rcpt.mail.secret_id, rcpt.rid.email)
        if result:
            wrapper.set_msgrcpt_status(rcpt.rid.email, rcpt.mail.mail_id, "R")
        else:
            error = result
            break

    if not error:
        message = ungettext(
            "%(count)d message released successfully",
            "%(count)d messages released successfully",
            len(mail_id),
        ) % {"count": len(mail_id)}
    else:
        message = error
    return ajax_response(
        request,
        "ko" if error else "ok",
        respmsg=message,
        url=QuarantineNavigationParameters(request).back_to_listing(),
    )