Giter Club home page Giter Club logo

Comments (3)

medmunds avatar medmunds commented on May 23, 2024

In your test script, it looks like you're missing an opening double-quote on the "realname" part of the email address:

    sender = 'Foobar, inc. (via SomeOtherFoobar)" <[email protected]>'
    #         ^ missing opening " to match here ^

(Your curl example doesn't have any double quotes, so it's not testing the same case.)

Anymail should accept -- and pass correctly to your ESP -- any validly-formatted email addresses. BTW, the double quotes shouldn't be necessary. Django's EmailMessage API makes you split multiple emails into a python list, so there's no confusion over commas: they're always assumed to be part of the "realname":

    # Either of these should work: matching double-quotes on realname:
    sender = '"Foobar, inc. (via SomeOtherFoobar)" <[email protected]>'
    # or no quotes on realname:
    sender = 'Foobar, inc. (via SomeOtherFoobar) <[email protected]>'

[Edit: above comment is wrong -- the double quotes are required for a validly-formatted email address]

from django-anymail.

melgart avatar melgart commented on May 23, 2024

very sorry about that -- typo while setting up my test file; i used the same test file to break it first, then fix it by surrounding the 'real name' part with double quotes, as you mentioned.

removing that stray double quote so that the sender email is:

'Foobar, inc. (via SomeOtherFoobar) [email protected]'

still fails when sending to Mailgun though, but the issue is with the python email package being used in django-anymail.anymail.utils.py, specifically the email.parseaddr function used in the ParsedEmail class. here's a quick test to show how email.parseaddr() deals with an email address like that:

from email.utils import parseaddr
email1 = 'Foobar, inc. (via SomeOtherFoobar) <[email protected]>'  # problem addr
print parseaddr(email1)
email2 = '"Foobar, inc. (via SomeOtherFoobar)" <[email protected]>'
print parseaddr(email2)

which returns:

(pw_ci)wintermute:app 21:23:38 melgart$ python test_email_parseaddr.py
('', 'Foobar')  # <-- unexpected
('Foobar, inc. (via SomeOtherFoobar)', '[email protected]')  # expected

i just wanted to pass along this info in case any of your other users ran into this problem. the fix from the sender's side is trivial, just not documented and it's a little confusing because Mailgun's email validation endpoint (https://api.mailgun.net/v3/address/validate) says this email address (above) is NOT valid, even with the double quotes around the real name part, yet the curl command below works, even without the real name in double quotes:

curl -s --user 'api:<secret>' \
    https://api.mailgun.net/v3/<mydomain>/messages \
    -F from='Foobar Construction & Design, LLC. (via FoobarsRUs) <[email protected]>' \
    -F [email protected] \
    -F subject='Hello' \
    -F text='Testing some Mailgun awesomness!'

so, i'm thoroughly confused but i understand how to proceed. thanks for the info and again, thank you for your work on AnyMail -- a very nice package to use.

from django-anymail.

medmunds avatar medmunds commented on May 23, 2024

Ah, thanks for tracking it down to the python library email.utils.parseaddr call.

Parsing email addresses -- even without the realname part -- is notoriously complex. (Which is why ordinary programmers like me are supposed to delegate the work to well-tested library calls.)

There's definitely a bug here in Anymail: parseaddr actually parses an address list and returns the (realname, email) of the first address in the list, if any. The python docs are a little ambiguous on this. (Also, good find! This has been broken for years, way back into Anymail's predecessor package Djrill.)

From muddling through RFC 5322, I'm pretty sure the double quotes are required for a valid email address that does what you intend. (Omitting the quotes from a "display-name" is allowed as an "obs-phrase". But an obs-phrase can't contain a comma.) I'd guess Mailgun has relaxed validation for the address fields in its API.

The python library getaddresses call correctly interprets the problem address without the quotes as two separate addresses:

>>> from email.utils import getaddresses
>>> email1 = 'Foobar, inc. (via SomeOtherFoobar) <[email protected]>'  # problem addr
>>> getaddresses([email1])
[('', 'Foobar'), ('inc. (via SomeOtherFoobar)', '[email protected]')]

Anymail needs to switch from parseaddr to getaddresses, and needs to raise an error when what should be a single email address actually contains multiple ones.

from django-anymail.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.