Search code examples
pythonexchange-serverexchangelib

Exchange mail filter problems Python


I have a script to list emails from exchange account and it takes too long to get a response, and other times I get errors like.

EXCEPTION IN (<string>, L_203 ""): HTTPSConnectionPool(host='outlook.office365.com', port=443): Read timed out.

or

requests.exceptions.ChunkedEncodingError: ("Connection broken: ConnectionResetError(10054, 'Se ha forzado la interrupción de una conexión existente por el host remoto', None, 10054, None)", ConnectionResetError(10054, 'Se ha forzado la interrupción de una conexión existente por el host remoto', None, 10054, None))

I don't understand why it takes so long. Will it be a problem with my account? sometimes it takes up to 2 minutes before giving an error

This is a part of my code:

class ExchangeModule:
    def __init__(self, user_, pwd, server_, mail_):
        self.pwd = pwd
        self.mail = mail_
        self.server = server_
        self.user = user_
        self.credentials = None
        self.config = None

    def init(self):
        from exchangelib import Credentials, Configuration
        self.credentials = Credentials(username=self.user, password=self.pwd)
        self.config = Configuration(server=self.server, credentials=self.credentials)
        return self.config

if module == "exchange":
    user = GetParams('user')
    password = GetParams('pass')
    server = GetParams('server')
    address = GetParams('address')
    print('USUARIO', user)
    exchange_module = ExchangeModule(user, password, server, address)
    config = exchange_module.init()

if module == "get_new_mail":

    if exchange_module.config is not None:
        config = exchange_module.config
    else:
        raise Exception("Execute Email Configuration command")
    address = exchange_module.mail
    a = Account(primary_smtp_address=address, config=config,
                access_type=DELEGATE, autodiscover=False)

    var = GetParams('var')
    filter_type= GetParams('tipo_filtro')
    filtro = GetParams('filtro')
    id_ = []

    if filtro:
        if filter_type== 'author':
            for m in a.inbox.all():
                if not m.is_read and filtro in m.author.email_address:
                    id_.append(m.id)
                    

        if tipo_filtro == 'subject':
            mails_filters = a.inbox.filter(subject__contains=filtro)
            for m in mails_filters:
                if not m.is_read:
                    id_.append(m.id)
                    # print('FOR',m.id)

    else:
        id_ = [m.id for m in a.inbox.all() if not m.is_read]

    SetVar(var, id_)

Solution

  • If you enable debug logging in exchangelib (see https://ecederstrand.github.io/exchangelib/#troubleshooting) you can see exactly what is going on.

    Your script is fetching all item fields, even though it only really needs the id field. That is very heavy since you're also fetching the full body, attachments, etc. Additionally, it is filtering items client-side that might as well be filtered server-side, giving you much less data to transfer. Instead of:

    for m in a.inbox.all():
        if not m.is_read and filtro in m.author.email_address:
            id_.append(m.id)
    

    do

    for m in a.inbox.filter(is_read=True, author__contains=filtro).only('id'):
        id_.append(m.id)
    

    And instead of:

    mails_filters = a.inbox.filter(subject__contains=filtro)
    for m in mails_filters:
        if not m.is_read:
            id_.append(m.id)
    

    do

    for m in a.inbox.filter(subject__contains=filtro, is_read=True).only('id'):
        id_.append(m.id)
    

    Apart from that, you may just have a slow Internet connection. You can configure fault tolerance (https://ecederstrand.github.io/exchangelib/#fault-tolerance) if you want to hide these errors and let your script try again.