Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

client.connect() call hangs after server timeout #243

Open
ThirVondukr opened this issue Jan 19, 2024 · 8 comments
Open

client.connect() call hangs after server timeout #243

ThirVondukr opened this issue Jan 19, 2024 · 8 comments
Labels
🐛 bug something that isn't supposed to happen

Comments

@ThirVondukr
Copy link

Describe the bug
It seems like at some point my smtp client is losing connection client.is_connected is None, and it hangs indefinitely if I call client.connect().
That problem may be related to specific SMTP server I'm using, but I don't know 🤷.

My question is: I keep SMTP instance in memory indefinitely, is that okay, or should I create a new client each time I need to send a message?

@ThirVondukr ThirVondukr added the 🐛 bug something that isn't supposed to happen label Jan 19, 2024
@cole
Copy link
Owner

cole commented Feb 14, 2024

client.is_connected should always be a boolean, and client.connect() shouldn't hang. Any idea what it's hanging on?

You can avoid the whole problem by using the send coroutine and creating a new connection each time, which is probably better practice anyway. But if you do have any more information, please provide it 🙂

@ThirVondukr
Copy link
Author

I'm not sure why client was hanging, that may have something to do with the SMTP server we use, which I have no info about. For now I fixed it by creating a new client each time, which seems to work 🤔

@ThirVondukr
Copy link
Author

Could you explain why creating a new connection would be considered best practice by the way?

@cole
Copy link
Owner

cole commented Feb 14, 2024

It's just a simple way to avoid a lot of error states from server timeouts, etc.

I wonder if there is an internal lock in the library that's getting stuck, I'll see if I can add some test cases around that.

@cole cole changed the title [Question] For how long can I use the same SMTP client? client.connect() call hangs after server timeout Feb 14, 2024
@ThirVondukr
Copy link
Author

I tried writing a context manager like this:

@contextlib.asynccontextmanager
async def reconnect_smtp_client(
    client: aiosmtplib.SMTP,
    timeout: float = 15,
) -> AsyncIterator[None]:
    try:
        if not client.is_connected:
            logging.warning("SMTP client is not connected, reconnecting.")
            async with asyncio.timeout(timeout):
                await client.connect()
        yield
    except SMTPServerDisconnected:
        logging.warning("Caught SMTPServerDisconnected exception, reconnecting.")
        async with asyncio.timeout(timeout):
            await client.connect()
        raise

But as I said it hanged on client.connect() indefinitely (initially asyncio.timeout wasn't there)

@alex-pirogov
Copy link

im also facing this issue
my idea is to keep SMTP client instance in memory because i dont want to spend time connecting & doing login to a server each time i want to send a message

my steps to reproduce are:

  1. create SMTP client instance
smtp_client = SMTP(...)
  1. connect to an SMTP server (i use mailslurper for development) and send a message
if not smtp_client.is_connected:
   await smtp_client.connect(timeout=10)

smtp_client.send_message(message)
  1. intentionally stop SMTP server
  2. try to repeat step 2. when calling await smtp_client.connect the program hangs infinitely

@ThirVondukr
Copy link
Author

I think that's the exact problem I had

@alex-pirogov
Copy link

i did some digging and found out that this is the place where program hangs
so we need to explicitly release _connect_lock in order to be able to reconnect again
this code seems to work

if not smtp_client.is_connected:
    if smtp_client._connect_lock and smtp_client._connect_lock.locked():
        smtp_client.close()

    await smtp_client.connect()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug something that isn't supposed to happen
Projects
None yet
Development

No branches or pull requests

3 participants