Opened 7 years ago

Closed 4 months ago

#12666 closed New feature (fixed)

Setting for sending email using localtime instead of UTC

Reported by: net147 Owned by: Anton Ian Sipos
Component: Core (Mail) Version: 1.1
Severity: Normal Keywords:
Cc: mmitar@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: yes UI/UX: no

Description (last modified by Ramiro Morales)

I would like to be able to send emails using local time in the Date header instead of UTC by default.

Changes needed (based on Django 1.1.1):

  • django/conf/global_settings.py:
    • Add "EMAIL_USE_LOCALTIME = False" (won't sent using local time by default unless you explicitly enable it)
  • django/core/mail.py:
    • Change "msg['Date'] = formatdate()" to "msg['Date'] = formatdate(localtime=settings.EMAIL_USE_LOCALTIME)"

Change History (18)

comment:1 Changed 7 years ago by Russell Keith-Magee

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Resolution: wontfix
Status: newclosed

Is there a particularly compelling reason to send mail with headers in local time, rather than against UTC?

Marking wontfix because I'm not aware of any particular advantage. If you can provide any evidence that it's the right/best practice thing to do, this shouldn't be configurable - it should be turned on by default.

comment:2 Changed 6 years ago by Ramiro Morales

Description: modified (diff)

(re-formatted description)

comment:3 Changed 6 years ago by Ramiro Morales

#13535 proposed the same (without a setting) and contained a patch.

comment:4 in reply to:  1 Changed 6 years ago by geofft

Resolution: wontfix
Status: closedreopened

ramiro: thanks, I searched but couldn't find a prior ticket.

Replying to russellm:

Marking wontfix because I'm not aware of any particular advantage. If you can provide any evidence that it's the right/best practice thing to do, this shouldn't be configurable - it should be turned on by default.

The e-mail Date header is defined to include both a time and a timezone offset indicating the local time of the sender. As it is, we're effectively only sending one of those two and making the second one useless at best, and possibly actively misleading. This is why I attached a patch to change it unconditionally and not make it configurable.

Practically speaking, my e-mail client (alpine) displays times in the timezone of the Date header without converting them to local time. I'm generally used to this behavior, so it confused me to see an e-mail from a Django server in the same city (and building) as me send with a time several hours ahead, causing it to display in the index view as "Tomorrow", since it was past midnight UTC.

Personally, I'm also inclined to believe that Python's standard libraries default to localtime=False because they're generally just bad at handling time zones and try to pretend that they don't exist. I'm not sure I see arguments for why formatdate should be defaulting to localtime=False, and I really don't see arguments for why Django wants that setting past that it's the default.

comment:5 Changed 6 years ago by Luke Plant

I'm not convinced it is the right thing to do. I have sites that are 'British' (i.e. serve almost entirely a British audience who live in GMT time), but the server happens to be in the States. It would just as 'misleading' to have e-mails that come from a non-British time zone (whereas UTC is kind of 'neutral').

Strictly speaking, I guess the time zone ought to be the time zone of the 'sender'. But who is the sender? If it's a contact form, the sender is the person who enters the message - we have no idea what his/her time zone is. In the case of an automated message sent by the webserver, it's debatable whether the machine 'lives in' the time zone the machine happens to be located in. It's also probably not desirable for the behaviour of a web site to change if I happen to move it to a different server.

comment:6 Changed 6 years ago by Karen Tracey

Triage Stage: UnreviewedDesign decision needed

Replying to geofft:

The e-mail Date header is defined to include both a time and a timezone offset indicating the local time of the sender.

Note when making statements like this, it is helpful to include a reference to whatever source you are considering responsible for defining such things. In this case I'd guess the relevant standard is RFC 2822. It states in section 3.3 that: "The date and time-of-day SHOULD express local time." This same section also sates:

   Though "-0000" also indicates Universal Time, it is
   used to indicate that the time was generated on a system that may be
   in a local time zone other than Universal Time and therefore
   indicates that the date-time contains no information about the local
   time zone.

Which sounds to me like the standard explicitly allows for specifying dates/times using only an absolute value, with no indication of what local time may be. This "-0000" spec is what Django is currently sending, and thus per the standard I think what it is doing is technically correct. Programs which are inferring anything about the local time of the sender when "-0000" has been specified are the ones that are, technically, doing something wrong. (Gmail's labs "Sender Time Zone" extension falls into this category.)

I am not sure what the right answer is, but I'm leaning towards thinking Django ought to be specifying localtime=True here. Though Luke has a good point about the server's time zone not necessarily having any relevance, for some servers the local time may in fact be relevant, and it is a bit annoying that it is not reflected in the date headers included in mail.

comment:7 in reply to:  5 ; Changed 6 years ago by geofft

Replying to lukeplant:

I'm not convinced it is the right thing to do. I have sites that are 'British' (i.e. serve almost entirely a British audience who live in GMT time), but the server happens to be in the States. It would just as 'misleading' to have e-mails that come from a non-British time zone (whereas UTC is kind of 'neutral').

Isn't this what TIME_ZONE in settings.py is for?

In [3]: settings.TIME_ZONE
Out[3]: 'America/Chicago'

In [4]: formatdate(localtime=True)
Out[4]: 'Fri, 14 May 2010 12:33:04 -0500'
In [3]: settings.TIME_ZONE
Out[3]: 'Europe/London'

In [4]: formatdate(localtime=True)
Out[4]: 'Fri, 14 May 2010 18:33:35 +0100'

Replying to kmtracey:

Which sounds to me like the standard explicitly allows for specifying dates/times using only an absolute value, with no indication of what local time may be. This "-0000" spec is what Django is currently sending, and thus per the standard I think what it is doing is technically correct.

Oh, good call, and sorry for not double-checking the RFC. That said, I still think it would be more useful to send "information about the local time zone" than not to, especially given that there is a TIME_ZONE variable. (The part that confused me here the most was that TIME_ZONE was set but not used.)

comment:8 in reply to:  7 Changed 6 years ago by Luke Plant

Replying to geofft:

Isn't this what TIME_ZONE in settings.py is for?

In [3]: settings.TIME_ZONE
Out[3]: 'Europe/London'

In [4]: formatdate(localtime=True)
Out[4]: 'Fri, 14 May 2010 18:33:35 +0100'

That's a very good point. But now I've got to go and work out why I am not seeing that behaviour in the e-mails I receive, even though I have settings.TIME_ZONE = 'Europe/London' :-(

comment:9 Changed 6 years ago by Malcolm Tredinnick

Triage Stage: Design decision neededAccepted

Russ and I talked about this. It sounds like broken clients. To make things easier for people to change in the cases where a lot of their users have said clients, we'll make formatdate() a method on the Email class that, by default, calls the email utils' formatdate(). Then people can subclass the Email class (or just supply the date header, which you can already do) and put whatever they like there. Current behaviour is technically correct however and remains the default.

comment:10 Changed 5 years ago by Matt McClanahan

Severity: Normal
Type: New feature

comment:11 Changed 5 years ago by Andrey Mitroshin <mit@…>

Easy pickings: unset
UI/UX: unset

In django/core/mail/message.py (Django 1.3.1)

msg['Date'] = formatdate()

There is no localtime=True and emails are sending using UTC
When I correct django/core/mail/message.py to

msg['Date'] = formatdate(localtime=True) 

Then emails are being sent with correct Date header (using local time with timezone)

EDIT(aaugustin): fixed formatting

Last edited 5 years ago by Aymeric Augustin (previous) (diff)

comment:12 Changed 4 years ago by Aymeric Augustin

Status: reopenednew

comment:13 Changed 4 months ago by Mitar

Cc: mmitar@… added

comment:14 Changed 4 months ago by Carl Meyer

Easy pickings: set

comment:15 Changed 4 months ago by Anton Ian Sipos

Owner: changed from nobody to Anton Ian Sipos
Status: newassigned

comment:16 Changed 4 months ago by Carl Meyer

I'm not convinced of the value of the refactoring proposed in https://code.djangoproject.com/ticket/12666#comment:9 -- if someone really wants some strange handling for the Date header, they can just set the header themselves, which is likely easier than subclassing Email for this purpose. Exposing the stdlib's localtime boolean flag is a simple change which would be friendlier to those who want a local timezone in their email headers, especially if it actually does respect the currently active Django timezone (e.g. TIME_ZONE setting). (It's not clear to me from the above whether it does or not; that deserves clarification.)

comment:17 Changed 4 months ago by Tim Graham

Has patch: set
Patch needs improvement: set

PR with comments for improvement.

comment:18 Changed 4 months ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

In c3495bb9:

Fixed #12666 -- Added EMAIL_USE_LOCALTIME setting.

When EMAIL_USE_LOCALTIME=True, send emails with a Date header
in the local time zone.

Note: See TracTickets for help on using tickets.
Back to Top