Commit Graph

54 Commits

Author SHA1 Message Date
medmunds
2cf14c3653 Mailgun: raise unsupported feature error on attachment without filename.
Mailgun's API silently drops attachments without filenames (and inline
attachments without Content-IDs). Raise an AnymailUnsupportedFeature
error on attempts to send these attachments.

Fixes #128
2018-10-11 15:38:50 -07:00
medmunds
9c493dba72 Postmark: Support merge_data and batch sending.
Use Postmark /email/batch or /email/batchWithTemplates APIs when
merge_data provided.

Parse Postmark batch-send API responses, and improve accuracy of
parsing individual recipient status from all responses.

Closes #122
2018-09-06 17:24:04 -07:00
medmunds
1ad406a9b5 Docs: fix typo in SendGrid 2018-09-06 17:16:16 -07:00
medmunds
753c895301 Postmark: Fix Postmark error on empty subject/body with template_id.
Postmark issues an error if Django's default empty strings are used
with template sends.

Include template send in Postmark integration tests. (Requires real
Postmark API token -- templates aren't testable with Postmark's
sandbox token.)

Fixes #121
2018-09-05 12:41:33 -07:00
medmunds
382ebf249c SendGrid: Improve esp_extra["personalizations"] handling.
Allow merging `esp_extra["personalizations"]` dict into other
message-derived personalizations.

(See comments in #120)
2018-08-27 11:10:48 -07:00
medmunds
dbca13243f SendGrid: support new "dynamic" transactional templates
Closes #120
2018-08-24 18:21:42 -07:00
medmunds
b5f8e86dd4 Docs: update ESP features table with new Postmark metadata support 2018-08-14 16:22:31 -07:00
medmunds
9e7814ad65 Mailgun: Support new (non-legacy) webhooks
Extend existing Mailgun tracking webhook handler to support both
original (legacy) and new (June, 2018) Mailgun webhooks.

Closes #117
2018-08-14 11:53:30 -07:00
medmunds
dacc299e5a Mailgun: Document how to use European region
Closes #116
2018-08-11 16:42:09 -07:00
medmunds
215c6a0a14 Docs: fix SparkPost Python client link
(The PyPI package is named "sparkpost". The GitHub repository is
"python-sparkpost". Sorry for any confusion.)
2018-08-11 16:13:23 -07:00
medmunds
46ff2e859c Postmark: Add metadata support
Closes #114
2018-08-11 16:00:58 -07:00
medmunds
02e6daf9d4 SendGrid: drop deprecated sendgrid_v2 EmailBackend 2018-05-30 16:02:21 -07:00
medmunds
c0172063a4 SendGrid UUID message_id cleanup
* Update authors
* Update integration tests
* Add webhook message_id = smtp-id fallback test case
* Test webhooks ignore smtp-id in non-fallback cases
* Update docs
2018-05-30 13:50:35 -07:00
Mike Edmunds
ef69fa3bf7 Amazon SES support
Integrate Amazon SES.

Closes #54.
2018-04-11 10:35:23 -07:00
medmunds
26cb882636 Postmark: Update docs and tests for "modular webhooks"
Existing tracking webhook code works fine with updated event payloads.
(So older Anymail versions will work, unmodified, with new Postmark
webhooks.)

Also update older doc links into Postmark docs.

Closes #101
2018-04-06 14:31:03 -07:00
medmunds
05f11db4ce SparkPost: add SPARKPOST_API_URL setting to allow SparkPost EU, etc.
Closes #100
2018-04-06 12:58:58 -07:00
medmunds
64bb3b6098 Docs: freeze left column of ESP feature matrix
(Make the wide table a little more readable.)
2018-04-05 18:03:59 -07:00
Mike Edmunds
d93a66326c SendinBlue: implement tracking webhooks
Completes #84
2018-03-08 13:47:46 -08:00
medmunds
4b28760a9a SendinBlue: cleanup integration tests, more docs
* Don't send *quite* so many emails during live integration tests.
  (Our test account is throttled to 40/hour.)
* Relax message_id check in integration tests. SendinBlue appears
  to use both @smtp-relay.mail.fr and @smtp-relay.sendinblue.com
  Message-IDs.
* Note requirement for HTML message body in docs.
2018-03-07 18:50:52 -08:00
medmunds
1e7aacdcb4 SendinBlue: update docs, readme, setup, Travis config
* Flesh out SendinBlue docs, add a readme mention
* Stop trying to list all the supported ESPs in the project short
  description and similar headlines -- it was becoming unwieldy.
* Support `pip install django-anymail[sendinblue]`
  and use it in Travis tests (for consistency; SendinBlue
  doesn't require any extra packages)
2018-03-01 17:29:57 -08:00
medmunds
07fbeac6bd Feature: Add envelope_sender
New EmailMessage attribute `envelope_sender` controls ESP's sender,
sending domain, or return path where supported:

* Mailgun: overrides SENDER_DOMAIN on individual message
  (domain portion only)
* Mailjet: becomes `Sender` API param
* Mandrill: becomes `return_path_domain` API param
  (domain portion only)
* SparkPost: becomes `return_path` API param
* Other ESPs: not believed to be supported

Also support undocumented Django SMTP backend behavior, where envelope
sender is given by `message.from_email` when
`message.extra_headers["From"]` is set. Fixes #91.
2018-02-26 18:42:19 -08:00
Rignon Noël
dc2b4b4e7a Add SendinBlue backend
Add support for sending transactional email through SendinBlue. (Thanks to @RignonNoel.)

Partially implements #84. (Tracking webhooks will be a separate PR. SendinBlue doesn't support inbound handling.)
2018-02-26 09:46:10 -08:00
medmunds
1a6086f2b5 Security: rename WEBHOOK_AUTHORIZATION --> WEBHOOK_SECRET
This fixes a low severity security issue affecting Anymail v0.2--v1.3.

Django error reporting includes the value of your Anymail
WEBHOOK_AUTHORIZATION setting. In a properly-configured deployment,
this should not be cause for concern. But if you have somehow exposed
your Django error reports (e.g., by mis-deploying with DEBUG=True or by
sending error reports through insecure channels), anyone who gains
access to those reports could discover your webhook shared secret. An
attacker could use this to post fabricated or malicious Anymail
tracking/inbound events to your app, if you are using those Anymail
features.

The fix renames Anymail's webhook shared secret setting so that
Django's error reporting mechanism will [sanitize][0] it.

If you are using Anymail's event tracking and/or inbound webhooks, you
should upgrade to this release and change "WEBHOOK_AUTHORIZATION" to
"WEBHOOK_SECRET" in the ANYMAIL section of your settings.py. You may
also want to [rotate the shared secret][1] value, particularly if you
have ever exposed your Django error reports to untrusted individuals.

If you are only using Anymail's EmailBackends for sending email and
have not set up Anymail's webhooks, this issue does not affect you.

The old WEBHOOK_AUTHORIZATION setting is still allowed in this release,
but will issue a system-check warning when running most Django
management commands. It will be removed completely in a near-future
release, as a breaking change.

Thanks to Charlie DeTar (@yourcelf) for responsibly reporting this
security issue through private channels.

[0]: https://docs.djangoproject.com/en/stable/ref/settings/#debug
[1]: https://anymail.readthedocs.io/en/1.4/tips/securing_webhooks/#use-a-shared-authorization-secret
2018-02-08 11:38:15 -08:00
Mike Edmunds
b57eb94f64 Add inbound mail handling
Add normalized event, signal, and webhooks for inbound mail.

Closes #43
Closes #86
2018-02-02 10:38:53 -08:00
medmunds
7e908184ed Postmark: support "clicked" tracking events
Handle Postmark's new click webhook.

Closes #78
2017-11-02 11:48:02 -07:00
medmunds
bb68f3dd6d Mailgun: fix event/metadata param extraction in tracking webhook
Mailgun merges user-variables (metadata) into the webhook post data
interspersed with the actual event params. This can lead to ambiguity
interpreting post data.

To extract metadata from an event, Anymail had been attempting to avoid
that ambiguity by instead using X-Mailgun-Variables fields found in the
event's message-headers param. But message-headers isn't included in
some tracking events (opened, clicked, unsubscribed), resulting in
empty metadata for those events. (#76)

Also, conflicting metadata keys could confuse Anymail's Mailgun event
parsing, leading to unexpected values in the normalized event. (#77)

This commit:
* Cleans up Anymail's tracking webhook to be explicit about which
  multi-value params it uses, avoiding conflicts with metadata keys.
  Fixes #77.
* Extracts metadata from post params for opened, clicked and
  unsubscribed events. All unknown event params are assumed to be
  metadata. Fixes #76.
* Documents a few metadata key names where it's impossible (or likely
  to be unreliable) for Anymail to extract metadata from the post data.

For reference, the order of params in the Mailgun's post data *appears*
to be (from live testing):
* For the timestamp, token and signature params, any user-variable with
  the same name appears *before* the corresponding event data.
* For all other params, any user-variable with the same name as a
  Mailgun event param appears *after* the Mailgun data.
2017-10-27 13:26:37 -07:00
medmunds
90b9dc6cfa Docs: simplify PyPI links
Use `:pypi:` sphinx-ext-extlink role for links to PyPI,
and add some missing package links.
2017-09-08 14:16:09 -07:00
medmunds
3809d3d2e2 Mailjet: correct settings docs
`MAILJET_SECRET_KEY` not `MAILJET_API_SECRET`.
(Heading was correct; text and example were wrong.)

Fixes #71
2017-07-24 11:13:59 -07:00
medmunds
54d2fe2513 Mailjet: add docs 2017-07-13 15:43:11 -07:00
medmunds
e0cca8c3ed Docs: update Mandrill webhook instructions
* Mandrill now refers to "whitelist change" events
  (used to be "whitelist sync").
* More details on solving validation failures due to
  webhook url mismatches.
2017-02-01 14:42:07 -08:00
medmunds
79288603fb Rename EmailBackends for Django consistency
* **Future breaking change:**
  Rename all Anymail backends to just `EmailBackend`,
  matching Django's naming convention.
  (E.g., switch to "anymail.backends.mailgun.EmailBackend"
  rather than "anymail.backends.mailgun.MailgunBackend".)

  The old names still work, but will issue a DeprecationWarning
  and will be removed in some future release.

  (Apologies for this change; the old naming convention was
  a holdover from Djrill, and I wanted consistency with
  other Django EmailBackends before hitting 1.0.)

Fixes #49.
2017-01-20 15:47:37 -08:00
Mike Edmunds
e568e50d0c SendGrid: update to new v3 send API (#50)
SendGrid: update to v3 send API

**SendGrid:** **[possibly-breaking]** Update SendGrid backend to newer Web API v3. This should be a transparent change for most projects. Exceptions: if you use SendGrid username/password auth, esp_extra with "x-smtpapi", or multiple Reply-To addresses, please review the [porting notes](http://anymail.readthedocs.io/en/latest/esps/sendgrid/#sendgrid-v3-upgrade).

Closes #28
2017-01-19 14:29:15 -08:00
medmunds
146afbaf3b Simplify Mandrill webhook validation handshake.
Anymail was requiring Mandrill's webhook authentication key for the initial webhook url validation request from Mandrill, but Mandrill doesn't issue the key until that validation request succeeds.

* Defer complaining about missing Mandrill webhook key until actual event post.
* Document the double-deploy process required to set up Mandrill webhooks.

Fixes #46.
2016-12-16 14:24:46 -08:00
medmunds
52596394cc Support Postmark delivery event webhook.
Add support for Postmark's recently-released [delivery tracking webhook] to Anymail's normailized status event handling. The existing Anymail tracking webhook URL can be copied to "Delivery webhook" in your Postmark outbound server settings.

Closes #45.
2016-12-15 14:24:10 -08:00
medmunds
e78410eea4 Docs: remove references to future inbound handling
(Postponed -- see discussion or vote to reopen in #4)

[ci skip]
2016-11-01 11:46:49 -07:00
medmunds
7248c3441e Postmark: add track_clicks support
Closes #38
2016-10-23 10:54:59 -07:00
medmunds
a1380b82f3 SendGrid: force empty text and html to " " with template_id
Work around an unexpected limitation in SendGrid template
rendering, where template text or html bodies are omitted
if the supplied message text or html is "". Changing empty
string to " " works around the issue.

https://sendgrid.com/docs/API_Reference/Web_API_v3/Transactional_Templates/smtpapi.html#-Text-or-HTML-Templates

Closes #32
2016-10-13 15:15:37 -07:00
medmunds
fb21c0d25b Mailgun: Add MAILGUN_SENDER_DOMAIN setting
Allow custom MAILGUN_SENDER_DOMAIN in Anymail
settings. (Replaces need to use global esp_extra.)

Improve docs to cover cases where this is needed.

(esp_extra sender_domain is still supported for
overriding individual messages.)

Fixes #26.
2016-08-03 14:19:35 -07:00
medmunds
f95be248ec SparkPost: remove empty content params with template_id
When using a stored template, SparkPost disallows
subject, text, and html. Django's EmailMessage default
empty strings are enough to provoke "Both content
object and template_id are specified" from SparkPost,
so remove them (if empty) when using stored templates.

Update docs and tests; add integration test for template_id.

Fixes #24
2016-06-24 12:13:32 -07:00
Mike Edmunds
db101bf6b9 Add SparkPost support (#20)
Implement SparkPost backend and tracking webhooks.

Closes #11.
2016-06-22 15:31:30 -07:00
medmunds
a0b92bee7a Mandrill: support esp_extra
* Merge esp_extra with Mandrill send payload
* Handle pythonic forms of `recipient_metadata`
  and `template_content` in esp_extra
* DeprecationWarning for Mandrill EmailMessage
  attributes inherited from Djrill
2016-05-11 15:08:57 -07:00
medmunds
75730e8219 Add ESP templates, batch send and merge
* message.template_id to use ESP stored templates
* message.merge_data and merge_global_data
  to supply per-recipient/global merge variables
  (with or without an ESP stored template)
* When using per-recipient merge_data, tell ESP to use
  batch send: individual message per "to" address.
  (Mailgun does this automatically; SendGrid requires
  using a different "to" field; Mandrill requires
  `preserve_recipients=False`; Postmark doesn't
  support *this type* of batch sending with merge data.)
* Allow message.from_email=None (must be set after
  init) and message.subject=None to suppress those
  fields in API calls (for ESPs that allow "From" and
  "Subject" in their template definitions).

Mailgun:
* Emulate merge_global_data by copying to
  recipient-variables for each recipient.

SendGrid:
* Add delimiters to merge field names via
  esp_extra['merge_field_format'] or
  ANYMAIL_SENDGRID_MERGE_FIELD_FORMAT setting.

Mandrill:
* Remove Djrill versions of these features;
  update migration notes.

Closes #5.
2016-05-06 12:27:11 -07:00
medmunds
1372ef21eb SendGrid: merge 'filters' in esp_extra
Previously, setting esp_extra['x-smtpapi']['filters']
would override the entire filters setting, potentially
undoing other Anymail options that use SendGrid
filters (like track_opens).

Now, 'filters' is special-cased, and merged with
any other Anymail filter options.

(We don't do a fully deep merge, because otherwise
there would be no way to use esp_extra to *clear*
Anymail settings.)
2016-04-30 10:21:11 -07:00
medmunds
d3f914be12 Event-tracking webhooks
Closes #3
2016-04-29 18:10:50 -07:00
medmunds
6b415eeaae Docs: note limited Mandrill support
Mandrill has disabled our test account and API key,
so future development will be purely against their docs.

[ci skip]
2016-04-29 11:21:11 -07:00
medmunds
8e43f29944 Workaround missing smtp-id in SendGrid tracking.
* Add smtp-id in unique_args (metadata), to ensure
  it shows up in click and open events.
* Add SENDGRID_GENERATE_MESSAGE_ID setting,
  default True, to control auto-Message-ID behavior.
* Document it.
2016-04-29 09:44:31 -07:00
medmunds
12229ab116 Docs: make ESP feature matrix maintainable
(reST substitutions bring the table width back within
a normal editor's width!)

[ci skip]
2016-03-14 19:48:47 -07:00
medmunds
f95bf1fbc4 Docs: typos, formatting
[ci skip]
2016-03-14 13:01:30 -07:00
medmunds
7bbd1c7e4e SendGrid: support username/password auth
Closes #9
2016-03-14 12:39:41 -07:00
medmunds
9462d03dc1 Docs: add ESP feature support matrix
[ci skip]
2016-03-14 11:34:33 -07:00