I'm developing a django project for use in America, specifically the New York timezone and the system is hosted on AWS, with SES sending email.
The email backend is using django-anymail which is a simple wrapper for SES and the system uses send_mail from django core.
To support this I've opted for the following Django settings;
EMAIL_BACKEND = "anymail.backends.amazon_ses.EmailBackend"
LANGUAGE_CODE = 'en'
TIME_ZONE = 'America/New_York'
USE_I18N = False
USE_L10N = True
USE_TZ = True
ANYMAIL = {
"AMAZON_SES_CLIENT_PARAMS": {
"region_name": AWS_SES_REGION_NAME,
},
}
With the above settings django calls tzset() on startup which modifies the system timezone. This then means the timestamp used by botocore to sign the requests for SES is not UTC, because the following error is received from message sending;
An error occurred (ExpiredToken) when calling the SendRawEmail operation: The security token included in the request is expired
Emails are sent successfully by changing settings to TIME_ZONE = 'UTC'.
I can only assume that the requests are being signed in UTC -4 which then hit AWS which is in UTC.
How can django run in a specific timezone, but boto operate with UTC timestamps?
The system is running in a docker container (pre-production);
- docker compose 3.4 (unix host)
- python 2.7
- django 1.11
- django-anymail 3.0
LocaleMiddlewareis loaded
I'm not able to reproduce the error you're seeing with the settings you've described, but I can show you what is working correctly for me with extra logging, and you could compare that to your failing case to try to see what's different.
I ran this code in the Django shell (
python manage.py shell) just for convenience, but you could put it in a debugging view or anywhere else that works for you.Our working theory is that boto is using the wrong time zone to calculate timestamps for signing the API request, so let's enable some detailed boto3 logging that covers that area:
Now try to send a message:
You should see log output that looks something like this:
The important parts here are the dates:
Notice the signature calculations are all based on the UTC date (2019-03-20)—not the current local date in my Django timezone (2019-03-19).
So it looks like boto3 does use UTC for the signature calculations, despite the Django/environment time zone. And indeed, the send works for me without error.
So the question is, what's different when you see the problem?
AuthorizationandX-Amz-Date? (If you see aDateheader instead ofX-Amz-Date, that would also be interesting.)Hope that helps you either get a little closer to a solution, or at least figure out what detail is essential to reproducing the problem.