Comments (3)
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.
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.
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)
- Support Brevo inbound
- "Package would be ignored" warnings from setuptools when building package HOT 2
- Sendgrid multiple reply to HOT 1
- Can't lock with poetry HOT 2
- [Inbound] Apple Mail inline attachments not taken into account HOT 5
- Add support to Resend.com HOT 5
- Handlebars variables not substitued in mandrill templates HOT 1
- mailgun api key HOT 2
- Merging/Combine ESP Options get lost/overwritten HOT 2
- parse_address_list: Inability to Parse Email Addresses with Special Characters in Display Name Without Double-Quote Encapsulation HOT 1
- Mailjet Open tracking? HOT 4
- Inaccuracy in documentation about Brevo's behaviour HOT 2
- Feature request: Mailtrap HOT 4
- Resend: confusing ReadTimeout error for incorrect API key
- Add support to Unisender Go HOT 2
- Support Brevo batch sending with merge_data HOT 2
- Add batch sending support for Resend HOT 1
- Mailgun webhooks: AttributeError 'NoneType' object has no attribute 'get' HOT 1
- boto3 sesv2 client does not have method 'send_email'. Check AmazonSESV2SendEmailPayload HOT 4
- Bad UTF-8 "To" header encoding? HOT 6
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-anymail.