Commit Graph

893 Commits

Author SHA1 Message Date
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
c924c9ec03 Add developer notes on supporting new ESPs
(This should eventually migrate to the docs.)
2018-02-01 16:53:22 -08:00
Charlie DeTar
771d4040df Un-hardcode message_id in test backend; add console backend
* Un-hardcode status message_id in test backend

For the test EmailBackend, get message ID's based on array position in
`mail.outbox`, so that tests can predict the message ID.


* Add a console backend for use in development

Adds an EmailBackend derived from both Anymail's test backend and
Django's console backend, to provide anymail statuses and signal
handling while printing messages to the console.  For use during
development on localhost.

Closes #87
2018-01-28 12:25:05 -08:00
medmunds
09def30868 Add timeout to all Requests calls
Use a default timeout of 30 seconds for all requests, and add a
REQUESTS_TIMEOUT Anymail setting to override.

(I'm making a judgement call that this is not a breaking change in the
real world, and not bumping the major version. Theoretically, it could
affect you if your network somehow takes >30s to connect to your ESP,
but eventually succeeds. If so, set REQUESTS_TIMEOUT to None to restore
the earlier behavior.)

Fixes #80.
2018-01-17 14:36:50 -08:00
medmunds
5fb46952c6 Tests: fix MockRequestsBackend.get_api_call_arg edge cases
get_api_call_arg had incorrectly returned None if a kwarg was passed
to the mocked function with a False-y value (e.g., [] or {})

get_api_call_json had only considered data param, ignoring json param
requests added a while back
2018-01-17 13:53:06 -08:00
medmunds
2bf492c2f4 Docs: Update intersphinx source urls
Python and Django have both moved their docs to https.
2018-01-17 13:10:49 -08:00
medmunds
e454864232 Travis: switch to released Django 2.0
And move Python 3.6 live integration tests from Django 1.11
to Django 2.0.
2017-12-02 11:37:51 -08:00
medmunds
7029298b93 Release 1.2 2017-11-02 14:08:18 -07: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
930753e4b6 Release 1.1 2017-10-28 11:45:31 -07:00
medmunds
9acf6501b5 Utils: Finish ParsedEmail --> EmailAddress conversion
Within an EmailAddress (previously ParsedEmail object), properties
now match Python 3.6 email.headerregistry.Address naming:

* .email --> .addr_spec
* .name --> .display_name
* .localpart --> .username

(Completes work started in 386668908423d1d4eade90cf7a21a546a1e96514;
this updates remaining uses of old names and removes them.)
2017-10-27 17:53:13 -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
636c8a5d80 Tests: move sample files into separate subdir 2017-10-25 19:50:31 -07:00
medmunds
3866689084 Utils: convert internal ParsedEmail to documented EmailAddress
Update internal-use ParsedEmail to be more like Python 3.6+
email.headerregistry.Address, and remove "internal use only"
recommendation.

(Prep for exposing inbound email headers in a convenient form.
Old names remain temporarily available for internal use;
should clean up at some point.)
2017-10-25 19:50:31 -07:00
medmunds
fe097ce4b4 Utils: add parse_rfc2822date
(Useful for interpreting date header in inbound messages)
2017-10-25 19:50:31 -07:00
medmunds
bd912fa3ca Tests: Django 2.0 prerelease (fix travis indents) 2017-10-11 15:53:49 -07:00
medmunds
68de868ebf Tests: prep for string_concat deprecation in Django 2.1
Test either or both of the lazy string builders `string_concat`
and `format_lazy`, depending on which is/are available in the
Django being tested.
2017-10-11 15:34:11 -07:00
medmunds
9e1f9fbcdc Tests: Test Django 2.0a 2017-10-11 15:30:39 -07:00
medmunds
c657d883a8 Release 1.0 2017-09-17 17:02:51 -07:00
medmunds
8cad1a6367 Keep flake happy on int/long test code 2017-09-14 11:54:30 -07:00
medmunds
3b9cb963ef SendGrid: convert long to str in headers, metadata
SendGrid requires extra headers and metadata values be strings.
Anymail has always coerced int and float; this treats Python 2's
`long` integer type the same.

Fixes #74
2017-09-14 11:45:17 -07:00
medmunds
168d46a254 Release 1.0.rc0 2017-09-08 17:29:17 -07:00
medmunds
01f56ae2b0 Prep for 1.0 release
* Remove "pre-1.0" warnings in docs, readme
* Jump trove classifer from pre-alpha all the way up to stable
  (arguably this should have been "beta" for the past several months)
2017-09-08 17:16:18 -07:00
medmunds
a67e174f38 Remove deprecated <ESP>Backend names
(Deprecated with warnings since v0.8)
2017-09-08 16:42:28 -07:00
medmunds
9c3761c216 Docs: add info on batch send performance 2017-09-08 15:46:28 -07:00
medmunds
0a95f1346a Docs: add info on handling transient ESP errors
Closes #55
2017-09-08 14:27:49 -07:00
medmunds
b6c75fe06b Docs: update intersphinx refs from Python 3.5 to 3.6 2017-09-08 14:19:43 -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
2faa5f96cb Clean up and document Anymail's test EmailBackend
* Change Anymail's test EmailBackend to collect sent messages in
  django.core.mail.outbox, same as Django's own locmem EmailBackend.
  (So Django's test runner will automatically clear accumulated mail
  between test cases.)

* Rename EmailMessage `test_response` attr to `anymail_test_response`
  to avoid conflicts, and record merged ESP send params in
  new `anymail_send_params` attr.

* Add docs

Closes #36.
2017-09-01 13:13:25 -07:00
Jonas Haag
a9c663f36a Docs: Add more mail template apps (#72) 2017-08-29 12:07:34 -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
6ddfe8e5d6 Add GitHub issue template 2017-07-13 17:02:08 -07:00
medmunds
872b67ee57 Open development for 0.12 2017-07-13 16:43:14 -07:00
medmunds
60a6c968f2 setup: flake clean 2017-07-13 16:30:40 -07:00
medmunds
7c6072afc9 Release 0.11 2017-07-13 16:28:21 -07:00
medmunds
516312bf00 Docs: note auth header must be passed through WSGI for webhooks
(See #69.)
2017-07-13 16:05:54 -07:00
medmunds
beec6e876a Mailjet: include in setup.py 2017-07-13 15:45:02 -07:00
medmunds
54d2fe2513 Mailjet: add docs 2017-07-13 15:43:11 -07:00
medmunds
d6d8044066 Mailjet: support tracking webhooks 2017-07-13 11:27:00 -07:00
medmunds
fc59707133 Webhooks: default tracking event tags=[], metadata={}
If a tracking event doesn't contain tags or metadata, set the event
record fields to tags=[] or metadata={} to simplify checking values.

Closes #67
2017-06-30 16:56:36 -07:00
Peter Wu
e39614e5a5 Mailjet backend support (#66)
Add Mailjet backend. (Docs and webhooks to follow.)

Thanks to @Lekensteyn and @calvin.
2017-06-30 16:33:53 -07:00
medmunds
1cc357836f Open development for 0.11 2017-05-22 12:09:19 -07:00
medmunds
6cc7ba38b0 Release 0.10 2017-05-22 11:49:30 -07:00
medmunds
0b50f278b5 Docs: add contact email for security issues 2017-05-22 11:46:37 -07:00
medmunds
67b9d8361d Include SparkPost in PyPI short description 2017-05-22 11:39:02 -07:00
medmunds
ba6ccdb13a Mailgun: handle x.y.z status code in webhooks
Mailgun sometimes (though not usually) gives the 'code' event
field as an RFC-3463 extended SMTP status code. Handle either
format.

Fixes #62
2017-05-22 11:09:26 -07:00
medmunds
bb54806dcf Tests: update settings for Django 1.11 final
Regenerate test settings.py using released Django 1.11.
(Had version from alpha Django 1.11a1. Only comments changed.)
2017-04-19 12:49:02 -07:00
medmunds
6b6793016e Mailgun, SparkPost: support multiple from_email addresses
[RFC-5322 allows](https://tools.ietf.org/html/rfc5322#section-3.6.2)
multiple addresses in the From header.

Django's SMTP backend supports this, as a single comma-separated
string (*not* a list of strings like the recipient params):

    from_email='one@example.com, two@example.com'
    to=['one@example.com', 'two@example.com']

Both Mailgun and SparkPost support multiple From addresses
(and Postmark accepts them, though truncates to the first one
on their end). For compatibility with Django -- and because
Anymail attempts to support all ESP features -- Anymail now
allows multiple From addresses, too, for ESPs that support it.

Note: as a practical matter, deliverability with multiple
From addresses is pretty bad. (Google outright rejects them.)

This change also reworks Anymail's internal ParsedEmail object,
and approach to parsing addresses, for better consistency with
Django's SMTP backend and improved error messaging.

In particular, Django (and now Anymail) allows multiple email
addresses in a single recipient string:

    to=['one@example.com', 'two@example.com, three@example.com']
    len(to) == 2  # but there will be three recipients

Fixes #60
2017-04-19 12:43:33 -07:00
medmunds
3c2c0b3a9d Travis: move live tests from pypy to py3
Fix incorrect change from Django 1.11 release.
Intent is to run live tests on newest released Django
under Python 3, and on oldest supported Django under
Python 2.7. (Though they should -- and do -- pass under
pypy. Just trying to conserve ESP testing credits.)
2017-04-16 15:24:18 -07:00
medmunds
db43af366e Add flake8 Travis-CI jobs
(Using bash env tests like this is a little ugly;
in the future, should just switch to tox.)
2017-04-16 12:40:05 -07:00