EXPORTED int mailbox_expunge(struct mailbox *mailbox,
                    mailbox_decideproc_t *decideproc, void *deciderock,
                    unsigned *nexpunged, int event_type)
{
    int r = 0;
    int numexpunged = 0;
    const message_t *msg;
    struct mboxevent *mboxevent = NULL;

    assert(mailbox_index_islocked(mailbox, 1));

    /* anything to do? */
    if (!mailbox->i.num_records) {
        if (nexpunged) *nexpunged = 0;
        return 0;
    }

    if (event_type)
        mboxevent = mboxevent_new(event_type);

    if (!decideproc) decideproc = expungedeleted;

    struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_EXPUNGED);
    while ((msg = mailbox_iter_step(iter))) {
        const struct index_record *record = msg_record(msg);
        if (decideproc(mailbox, record, deciderock)) {
            numexpunged++;

            struct index_record copyrecord = *record;
            /* mark deleted */
            copyrecord.internal_flags |= FLAG_INTERNAL_EXPUNGED;

            r = mailbox_rewrite_index_record(mailbox, &copyrecord);
            if (r) {
                mboxevent_free(&mboxevent);
                mailbox_iter_done(&iter);
                return IMAP_IOERROR;
            }

            mboxevent_extract_record(mboxevent, mailbox, &copyrecord);
        }
    }
    mailbox_iter_done(&iter);

    if (numexpunged > 0) {
        syslog(LOG_NOTICE, "Expunged %d messages from %s",
               numexpunged, mailbox_name(mailbox));

        /* send the MessageExpunge or MessageExpire event notification */
        mboxevent_extract_mailbox(mboxevent, mailbox);
        mboxevent_set_access(mboxevent, NULL, NULL, "", mailbox_name(mailbox), 0);
        mboxevent_set_numunseen(mboxevent, mailbox, -1);
        mboxevent_notify(&mboxevent);
    }
    mboxevent_free(&mboxevent);

    if (nexpunged) *nexpunged = numexpunged;

    return 0;
}
EXPORTED int mailbox_expunge(struct mailbox *mailbox,
                    mailbox_decideproc_t *decideproc, void *deciderock,
                    unsigned *nexpunged, int event_type)
{
    int r = 0;
    int numexpunged = 0;
    const message_t *msg;
    struct mboxevent *mboxevent = NULL;

    assert(mailbox_index_islocked(mailbox, 1));

     
    if (!mailbox->i.num_records) {
        if (nexpunged) *nexpunged = 0;
        return 0;
    }

    if (event_type)
        mboxevent = mboxevent_new(event_type);

    if (!decideproc) decideproc = expungedeleted;

    struct mailbox_iter *iter = mailbox_iter_init(mailbox, 0, ITER_SKIP_EXPUNGED);
    while ((msg = mailbox_iter_step(iter))) {
        const struct index_record *record = msg_record(msg);
        if (decideproc(mailbox, record, deciderock)) {
            numexpunged++;

            struct index_record copyrecord = *record;
             
            copyrecord.internal_flags |= FLAG_INTERNAL_EXPUNGED;

            r = mailbox_rewrite_index_record(mailbox, &copyrecord);
            if (r) {
                mboxevent_free(&mboxevent);
                mailbox_iter_done(&iter);
                return IMAP_IOERROR;
            }

            mboxevent_extract_record(mboxevent, mailbox, &copyrecord);
        }
    }
    mailbox_iter_done(&iter);

    if (numexpunged > 0) {
        syslog(LOG_NOTICE, "Expunged %d messages from %s",
               numexpunged, mailbox_name(mailbox));

         
        mboxevent_extract_mailbox(mboxevent, mailbox);
        mboxevent_set_access(mboxevent, NULL, NULL, "", mailbox_name(mailbox), 0);
        mboxevent_set_numunseen(mboxevent, mailbox, -1);
        mboxevent_notify(&mboxevent);
    }
    mboxevent_free(&mboxevent);

    if (nexpunged) *nexpunged = numexpunged;

    return 0;
}