Forums

Flask Mail, Maximum Message Length

Maybe I'm missing it somewhere via documentation...

I'm using FLASK_MAIL to send emails.

If I send emails that exceed some sort of message size threshold (which I haven't been able to figure out the number), the system throws an error stating the message is too long.

"""

2019-06-06 16:25:55,996: reply: b'250 2.1.5 OK 50sm1402806qtt.77 - gsmtp\r\n'

2019-06-06 16:25:55,996: reply: retcode (250); Msg: b'2.1.5 OK 50sm1402806qtt.77 - gsmtp'

2019-06-06 16:25:55,997: send: 'data\r\n'

2019-06-06 16:32:32,168: Traceback (most recent call last):

2019-06-06 16:32:32,169: File "/usr/lib/python3.7/logging/handlers.py", line 939, in emit

2019-06-06 16:32:32,169: self.socket.sendto(msg, self.address)

2019-06-06 16:32:32,169: OSError: [Errno 90] Message too long

"""

This works locally with large files uploaded, but now, only small file sizes + body contents pass through.

Can anyone tell me why?

I feel like this isn't a Flask Mail issue but a logging issue on output, it's to large to output to the log file and throws an error.

Thanks

Perhaps Google has different size limitations for emails coming from different places or going to different places.

I figured out the problem.

Pythonanywhere seems to crash while sending large emails + attachments when the FLASK Application is in debug mode.

os.environ['FLASK_CONFIG'] = 'production'

Setting the FLASK_CONFIG to production stops the crashing inside the WSGI.py file.

It looks like in debug mode flask_mail tries to log the entire message, so the "message is too long" messge was coming from the logging system. In production mode that logging would not happen. You can probably also turn down the logging level in debug mode so that the entire message is not logged.

I actually tried something like that, even turning logging off outright doing something like below when I tested locally:

import logging
log = logging.getLogger('werkzeug')
log.disabled = True

But the flask_mail output still came through. Ideally whats hosted here shouldn't be in debug mode anyways so Ill just need to keep a mental note moving forward.

I have the same problem and I'm not using flask_mail, just attempting to get my Flask server to stand up for the first time. In my case there are Twilio HTTP requests that are made that return large amounts of data and the error is the same: ....

OSError: [Errno 90] Message too long

The solutions I've attempted include in my init.py:

os.environ['FLASK_CONFIG'] = 'production'

from flask.logging import default_handler
app.logger.removeHandler(default_handler)

In my .flaskenv:

FLASK_ENV=production

None of these things have affected what is logged. Any more ideas? This problem doesn't exist in my dev enviro on Windows with Flask config set to "development".

If you have it working locally, look in the logs that you have locally for really long lines and then use that to work out where they are coming from and from there, work out how to avoid logging them.

Well yes it's the Twilio requests as mentioned before; it's clear from the log where it fails. It's logging all HTTP requests, but the Twilio responses are big enough to cause the error. Locally the logging doesn't log the entire request, this is only happening on the production server.

To start, I thought I'd just turn off all logging to stop the problem, but have so far not figured out how to take any control of the logging at all. As another attempt I copied this code directly from the Flask documentation:

from logging.config import dictConfig

dictConfig({
    'version': 1,
    'formatters': {'default': {
        'format': '[%(asctime)s] %(levelname)s in %(module)s: %(message)s',
    }},
    'handlers': {'wsgi': {
        'class': 'logging.StreamHandler',
        'stream': 'ext://flask.logging.wsgi_errors_stream',
        'formatter': 'default'
    }},
    'root': {
        'level': 'INFO',
        'handlers': ['wsgi']
    }
})

And now I have a stack overflow :/

Where (in your code) does it happen?

The HTTP request that causes the logging to fail is a request to Twilio to retrieve messages:

        return twilio_client_prod.messages.list(
            to=caller_number,
            from_=from_number,
            limit=200)

This returns a large result, in my case ~>100 messages. The logger attempts to log the entire result and fails with the message

OSError: [Errno 90] Message too long

My local version of the same code does not log entire HTTP message bodies; this only happens on the production server. So I haven't had this problem locally, I'm just using the log setup defaults and apparently that is different somehow on the PythonAnywhere server. I will try to get my local logging to do something new and see where that leads.

The stack overflow described above happens when I paste that code as the first lines in the init.py file, before the line:

app = Flask(__name__)

It is in fact specific to Twilio's default logging level. The answer described here worked:

 import logging
 twilio_logger = logging.getLogger('twilio.http_client')
 twilio_logger.setLevel(logging.WARNING)

I guess what would have helped me get here sooner is if all the loggers announced themselves at least at server boot-up. But even in the log error there is no reference to the logger named 'twilio.http_client', which would have been helpful.

Looks like you need to change logging level on twilio.http_client logger in your code.