Is 'try / finally' the best way for me to handle (and close) this long-running IMAP4 connection? I'm writing a script to archive email messages from one IMAP folder to another. It looks, more or less, like the following. I've obfuscated about 30 lines unrelated to this question:

import imaplib
import getpass

def main():
    user = getpass.getuser() + '@mymailbox.com'
    mailbox = imaplib.IMAP4_SSL('mymailbox.com', 993)
    try:
        mailbox.login(user, getpass.getpass())
    except imaplib.IMAP4.error:
        raise RuntimeError('Credential error.')
    mailbox.select('my_mailbox')

    # Here lies some 30 lines not relevant to the question, but which
    # find mailbox messages, copies them to another folder, and
    # sets the delete flag in 'my_mailbox'.

    try:
        mailbox.close()    # which also expunges the mailbox
    except:
        pass
    mailbox.logout()


After working with my IMAP server for a while, I've discovered a fair amount of unexpected error conditions arising from its implementation of RFC 3501. No matter what, however, I always want to attempt mailbox.close() and mailbox.logout().

It sounds like a good occasion for a try / finally block, and that usage is supported by other examples. All the same, it feels unnatural to wrap some 40 lines of main() execution in a try-block:

def main():
    user = getpass.getuser() + '@mymailbox.com'
    mailbox = imaplib.IMAP4_SSL('mymailbox.com', 993)
    try:
        try:
            mailbox.login(user, getpass.getpass())
        except imaplib.IMAP4.error:
            raise RuntimeError('Credential error.')
        mailbox.select('my_mailbox')

        # Here lies some 30 lines not relevant to the question, but which
        # find mailbox messages, copy them to another folder, and
        # set delete flags in 'my_mailbox'.
    finally:
        try:
            mailbox.close()    # which also expunges the mailbox
        except:
            pass
        mailbox.logout()


Is that a common pattern? I could also write my own context manager; perhaps that's the better way to go. What's the best practice for long-running connections like this?
Move the working logic into its own function

def process_mailbox(mailbox):
    user = getpass.getuser() + '@mymailbox.com'
    try:
        mailbox.login(user, getpass.getpass())
    except imaplib.IMAP4.error:
        raise RuntimeError('Credential error.')
    mailbox.select('my_mailbox')
    #whatever else

def main():
    mailbox = imaplib.IMAP4_SSL('mymailbox.com', 993)
    try:
        process_mailbox(mailbox)
    finally:
        try:
            mailbox.close()    # which also expunges the mailbox
        except:
            pass
        mailbox.logout()