Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#17561 closed Bug (invalid)

EmailField does not automatically lower the case in email addresses

Reported by: zechs.marquie@… Owned by: nobody
Component: Database layer (models, ORM) Version: 1.3
Severity: Normal Keywords: EmailField, duplicates
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Neither in a form or a model does the EmailField become lower case upon saving or validating.

If this field were to be lower the validation regex would be simpler. In addition if you have a unique constraint on this field within your model then you are free to add test@… and tesT@… and any unique variant of upper/lower case characters.

Seems a bit of a short fall seeing as the EmailField does some validation on email addresses already.

Change History (8)

comment:1 Changed 3 years ago by anonymous

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

comment:2 Changed 3 years ago by nate_b

  • Resolution set to invalid
  • Status changed from new to closed

The problem is that test@... and tesT@... are different email addresses. Take a look at the answers to this question How do I upper case an email address?, and the relevant links to the RFC.

In practice uppercase letters are discouraged, but breaking that would probably not be a good idea.

comment:3 Changed 3 years ago by zechs.marquie@…

I suppose its better to adhere to the RFC. Perhaps an option could be passed to EmailField to state whether you want it to lower all case or not. It would save having to do something in the form validation like

def clean_email(self):
    return self.cleaned_data['email'].lower()
Last edited 3 years ago by lrekucki (previous) (diff)

comment:4 Changed 3 years ago by lrekucki

I'm not sure adding another option to save you 2 lines in not so common case is a good idea.

One thing to note is that only the *local part* of the email is case sensitive. Host names are by definition case insensitive (at least in ASCII range, not sure about IDN), ie. me...@example.com and me...@Example.com are the same address. IMO, doing such normalization is useful, but it's a bit different thing then proposed on this ticket.

comment:5 Changed 3 years ago by aaugustin

Django shouldn't alter user input. IMO this ticket is "wontfix" anyway.

comment:6 Changed 3 years ago by zechs.marquie@…

Well think about it this way. The ORM is something that sits between us and the database and the database is supposed to be something we don't want to fudge around behind the ORM's back. The database WON'T notify you if you insert me@… and me@…. For every production site out there recording an email address, this crops up. Twitter, Facebook, Github, Imgur, Stack overflow and Google all treat email as case insensitive. If most email vendors enforce case insensitivity ( for simplifying the administration ) then you will most likely want to follow suit. Email is often stored as a unique column in a database so those two lines are probably already very commonly hit out there.

I cannot force something into Django, but when people say email validation of this nature is NOT common I have to DISAGREE. Its an unwritten rule that we treat the entire email as being case insensitive for security and ease of administration so I think the flag would be useful here. Is it a case of us saying EmailFields operate to strict standards or saying EmailFields accommodate a useful features out of the box.

PS Nothing anyone has said so far is incorrect. But this feature supports both positions by making this check optional.

comment:7 Changed 3 years ago by anonymous

Interesting, my company ran into this problem as well. We ended up having to run a South schema migration on 2 million users, after making the following modification:

def email_prep(self, value):
    """
    Lower-cases the value returned by super, while still allowing nullable email fields.
    """
    prep_value = super(EmailField, self).get_prep_value()
    if prep_value is not None:
        return prep_value.lower()
    return prep_value

EmailField.get_prep_value = email_prep

comment:8 Changed 3 years ago by anonymous

Just noticed a typo - prep_value = super(EmailField, self).get_prep_value(value)

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