Commit Graph

118 Commits

Author SHA1 Message Date
Mateusz Mandera 8bd3752d13 email_mirror: Handle encoded attachment filenames. 2020-01-30 13:03:47 -08:00
Mateusz Mandera 49b76318c6 email_mirror: Extract handle_header_content function. 2020-01-30 13:03:47 -08:00
Mateusz Mandera 9dcf677bf9 email_mirror: Parse encoded From headers with show_sender=True. 2020-01-29 12:27:35 -08:00
Mateusz Mandera d37e6ef921 email_mirror: Use plaintext if html body empty with prefer-html option.
If an email is sent with the .prefer-html option, but it has no html
body, it's better to fall back to plaintext content instead of treating
it as a user error.
2020-01-16 15:25:27 -08:00
Mateusz Mandera 0c9c218e91 email_mirror: Add prefer-html and prefer-text address options.
Closes #13484.

These options tell zulip whether to prefer the plaintext or html version
of the email message. prefer-text is the default behavior, so including
the option doesn't change anything as of now, but we're adding it to
prepare to potentially change the default behavior in the future.
2020-01-16 15:25:19 -08:00
Mateusz Mandera 0beae44081 email_mirror: Use .walk() to search all MIME parts for attachments.
Fixes #13416

We used to search only one level in depth through the MIME structure,
and thus would miss attachments that were nested deeper (which can
happen with some email clients). We can take advantage of message.walk()
to iterate through each MIME part.
2020-01-14 15:37:39 -08:00
Mateusz Mandera 1561d144e0 email_mirror: Insert a new line before attachment links. 2020-01-14 15:37:39 -08:00
Mateusz Mandera d5ac1afce8 email_mirror: Check address usability in get_missed_message_address. 2020-01-12 20:43:51 -08:00
Mateusz Mandera 89046ea1a9 email_mirror: Give extract_and_validate a more descriptive name. 2020-01-12 11:30:18 -08:00
Mateusz Mandera 90a69ab24f email_mirror: Reuse exception messages in mirror_email_message. 2020-01-12 11:30:18 -08:00
Mateusz Mandera b87cf22b33 email_mirror: Move send_to_mm_address code to process_missed_message.
process_missed_message did nothing other than calling
send_to_missed_message_address with the same arguments, so there's no
reason to have these as separate functions.
2020-01-07 13:03:32 -08:00
Mateusz Mandera c011d2c6d3 email_mirror: Migrate missed message addresses from redis to database.
Addresses point 1 of #13533.

MissedMessageEmailAddress objects get tied to the specific that was
missed by the user. A useful benefit of that is that email message sent
to that address will handle topic changes - if the message that was
missed gets its topic changed, the email response will get posted under
the new topic, while in the old model it would get posted under the
old topic, which could potentially be confusing.

Migrating redis data to this new model is a bit tricky, so the migration
code has comments explaining some of the compromises made there, and
test_migrations.py tests handling of the various possible cases that
could arise.
2020-01-07 13:03:22 -08:00
Mateusz Mandera 1c5461663f users: Eliminate some unnecessary get_personal_recipient calls. 2019-12-09 15:24:35 -08:00
Tim Abbott 6618cec9db logging: Switch various logging code paths to use user IDs.
This fixes EMAIL_ADDRESS_VISIBILITY_ADMINS support as well as being
more reliable/stable over time.
2019-11-15 17:24:01 -08:00
Mateusz Mandera 3271235200 email_mirror: Ignore missed message email if the user isn't active. 2019-09-20 17:58:10 -07:00
Mateusz Mandera f1b135bd16 email_mirror: Rename include-quotations to include-quotes. 2019-07-20 15:53:43 -07:00
Mateusz Mandera 58754830fd email_mirror: Rename "include-footers" option to "include-footer". 2019-07-08 20:10:21 -07:00
Mateusz Mandera 569d79b9d8 email_mirror: Add support for "+include-quotations" in address.
We add an option to disable the stripping of quotations from the email
body, if "+include-quotations" token is included in the email address.
2019-06-02 10:50:59 -07:00
Mateusz Mandera e4138c5463 email_mirror: Add support for "+include-footers" in address.
In addition to the "+show-sender" option, we now add "+include-footers"
which disables stripping of the footer from the email body if this token
is included in the email address.
2019-06-02 10:50:59 -07:00
Mateusz Mandera a5aa4adb54 email_mirror: Add general support for optional tokens in the address.
To enable a comfortable way of adding more optional tokens in the
address (like current '+show-sender') we change decode_email_address to
return a general dictionary containing options specified through adding
these optional tokens in the To: address. For now, we only have
"+show-sender", but more can be easily added using this change.
2019-06-02 10:50:59 -07:00
Mateusz Mandera a0efd76f4e email_mirror: Rewrite log_and_report and cover it with tests.
log_and_report and its helper functions were mostly old code no longer
well adapted to how email mirror works currently, as well as having no
test coverage. We rewrite this part of the email to report errors in a
similar manner, and add tests for it. We're able to get rid of the
clunky and now useless debug_info dictionary in process message, as
log_and_report only needs the recipient email in its third argument.
2019-05-20 19:35:32 -07:00
Mateusz Mandera 2adcdd0c25 email_mirror: Don't pass debug_info to process_stream_message.
The only place in which process_stream_message used debug_info was to
set the 'stream' key, which would only be used if ZulipEmailForwardError
was raised after this line in the code - which is impossible, because after
that line only send_zulip (which doesnt raise this exception) and
logger.info get called, then process_stream_message successfully returns
and then process_message succesfully returns as well. So this debug_info
code wasn't doing anything. We remove it.
2019-05-20 19:35:32 -07:00
Mateusz Mandera 40f5755546 email_mirror: Handle case of unspecified charset in Content-Type header.
If the text part of an email message didn't specify the charset in the
Content-Type header, the text content wouldn't be found. We fix this, by
assuming us-ascii charset in those cases, as specified by RFC6657:
https://tools.ietf.org/html/rfc6657
2019-05-09 09:57:40 -07:00
Mateusz Mandera c1ceba9037 rate_limiter: Move email_mirror limiter to use rate_limit_entity.
We change the rate limiting code in the email mirror to use the new,
general rate_limit_entity function.
2019-05-01 12:54:32 -07:00
Anders Kaseorg 643bd18b9f lint: Fix code that evaded our lint checks for string % non-tuple.
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2019-04-23 15:21:37 -07:00
Mateusz Mandera c7c1dbec60 email_mirror: Raise ZulipEmailForwardError if email pattern not recognised.
With the previous commit, fixes #1836.

As specified in the issue above, we make
get_email_gateway_message_string_from_address raise an exception if
it doesn't recognise the email gateway address pattern. Then, we make
appropriate adjustments in the codepaths which call this function.
2019-03-21 15:25:57 -07:00
Mateusz Mandera e32c444ecf email_mirror: Move some helper functions out of actions.py.
These functions don't really belong in actions.py, so we move them out,
into email_mirror_helpers.py. They can't go directly into
email_mirror.py or we'd get circular imports resulting in ImportError.
2019-03-21 15:25:57 -07:00
Mateusz Mandera 1901775383 email_mirror: Add realm-based rate limiting.
Closes #2420

We add rate limiting (max X emails withing Y seconds per realm) to the
email mirror. By creating RateLimitedRealmMirror class, inheriting from
RateLimitedObject, and rate_limit_mirror_by_realm function, following a
mechanism used by rate_limit_user, we're able to have this
implementation mostly rely on the already existing, and proven over
time, rate_limiter.py code. The rules are configurable in settings.py in
RATE_LIMITING_MIRROR_REALM_RULES, analogically to RATE_LIMITING_RULES.

Rate limit verification happens in the MirrorWorker in
queue_processors.py. We don't rate limit missed message emails, as due
to using one time addresses, they're not a spam threat.

test_mirror_worker is adapted to the altered MirrorWorker code and a new
test - test_mirror_worker_rate_limiting is added in test_queue_worker.py
to provide coverage for these changes.
2019-03-18 11:16:58 -07:00
Mateusz Mandera a64a075ff1 email_mirror: Ignore stream_name part of receiving address.
To prepare for changing how the stream name gets encoded into mirror
email addresses while making sure old addresses keep working, we ignore
the stream_name part when receiving emails into the mirror and we only
look at the email_token to identify into which stream to mirror the
email.
2019-03-18 11:06:51 -07:00
Tim Abbott 50dc317466 notifications: Rename notifications.py to email_notifications.py.
This library is entirely about email notifications specifically, and
this rename should help make the codebase more readable.
2019-03-15 11:02:17 -07:00
Mateusz Mandera edcb6d57fc email_mirror: Don't remove quotations from forwarded messages.
Addresses point 2 of #10612. We use a regex to detect if a form
of FWD indicator is present at the beginning of the subject, which
means the message has been forwarded.
remove_quotations argument is added to a couple of functions where
it's necessary.
In filter_footer, the criteria for a line to be a possible beginning
of a footer is changed to line.strip() == "--", instead of
line.strip().startswith("--"), because the former would remove
quotations from plaintext emails. This change makes sense, because
RFC 3676 specifies ""-- " as the separator line between the body
and the signature of a message":
https://tools.ietf.org/html/rfc3676
2019-03-09 15:36:17 -08:00
Mateusz Mandera 0633f268fb email_mirror: Move subject processing into process_stream_message.
We remove the 'subject' argument of process_stream_message and make
subject processing happen inside the function, as it's a more
appropriate place than the general process_message function and is
needed to have a good way of disabling removing quotations in forwarded
emails sent into the mirror.
2019-03-09 15:36:17 -08:00
Mateusz Mandera dbff533e09 email_mirror: Add the sender at the start of stream message.
Fixes part 3 of #10612. When sending an email to the email mirror to a
stream address, if "+show-sender" is added in the address, the stream
message will now include "From: <sender>" at the top.
2019-03-07 14:28:33 -08:00
Tim Abbott 7099d01641 email mirror: Fix missing variable for logging. 2019-02-13 13:16:55 -08:00
Eeshan Garg 179b747769 streams: Refactor multi-option helpers into separate functions.
For internal stream messages, most of the time, we have access to
a Stream object. For the few corner cases where we don't, it is a
much cleaner approach to have a separate function that accepts a
stream name than having one multi-option helper that accepts both
names and objects.
2019-02-12 11:10:26 -08:00
Eeshan Garg 3470e541c8 internal_send_stream_message: Support accepting a Stream object.
If the caller has access to a Stream object, it is wasteful to
query a database for a stream by ID or name. In addition, not
having to go through stream names eliminates various classes of
possible bugs involved with re-fetching the Stream object by name.
2019-02-08 08:59:03 -08:00
Anders Kaseorg f0ecb93515 zerver core: Remove unused imports.
Signed-off-by: Anders Kaseorg <andersk@mit.edu>
2019-02-02 17:41:24 -08:00
Tim Abbott a92a5f19f0 email_mirror: Handle case where email body is empty.
This provides logging that makes clear this situation is a user error.
2019-01-15 11:30:15 -08:00
Tim Abbott 14b2ed649b email_mirror: Don't email errors for emails missing body type.
This lowers the severity on content type errors to not send spammy
error emails, and instead just log a warning.
2019-01-15 11:30:15 -08:00
Tim Abbott 828577c3b2 email_mirror: Fix parsing of unicode in subject headers.
Previously, we had some hand-written logic for parsing the subject
line of the email's headers and turning it into a Python string using
each of the valid encodings for an email.  That logic was buggy, and
sometimes resulted in a bytes object being passed into the
`send_zulip`, which would eventually throw an exception.

The fix for this is to use the Python standard library make_header
method for handling internationalized email headers.

https://stackoverflow.com/questions/7331351/python-email-header-decoding-utf-8
2019-01-07 10:21:04 -08:00
Mateusz Mandera 87c95c6f41 email_mirror: Strip RE and FWD from email subject.
Fixes part 1 of #10612. We use a regex to remove RE:, FWD: (and similar
variations) from email subjects. Unit test is included, we add
subjects.json in fixtures containing various subjects to try the
stripping on.
2019-01-05 15:59:19 -08:00
Tom Daff f2e06128c6 email_mirror: Add email address parsing.
When trying to find the email gateway address, use the
`email.util.getaddresses` function to deal with cases
where multiple recipients are included in the email header
or the stream address appears as an angle-addr with a
name given (e.g. if someone added it to their address book).

Added some other headers where the required address may
appear: "Resent" headers are sometimes used for forwarding,
and streams may also be found in CC. There is no way to find
the address if the email was recieved as a BCC.
2019-01-03 13:34:20 -08:00
Tim Abbott adf27aae4c python: Remove now-unnecessary str_utils library.
This library was absolutely essential as part of our Python 2->3
migration process, but all of its calls should be either no-ops or
encode/decode operations.

Note also that the library has been wrong since the incorrect
refactoring in 1f9244e060.

Fixes #10807.
2018-11-27 11:57:54 -08:00
Marco Burstein 6f569719c9 integrations: Change the truncation marker for long messages.
Change the truncation marker from `...` to `\n[message truncated]`
when receiving messages from the API or through e-mail. Also, update
tests to account for the new change.

Fix #10871.
2018-11-26 11:09:39 -08:00
Steve Howell af1acf9239 Rename constant to MAX_TOPIC_NAME_LENGTH. 2018-11-07 10:03:53 -08:00
Steve Howell 2fd0cfe708 Use topic_name() helper in more places. 2018-11-07 10:03:53 -08:00
Tim Abbott 704967faa4 email_mirror: Don't import talon unless we're using it.
Talon is an expensive import; on my system, deferring this import
saves 28ms on the import time for Zulip.
2018-10-17 11:25:38 -07:00
Tim Abbott 75376a3fc5 email_mirror: Limit message length using defined constants.
Previously, we had the somewhat arbitrary limit of 2K characters
(which some users complained about), as well as the constant 60 for
the topic.
2018-09-21 10:39:57 -07:00
Aditya Bansal 1f9244e060 zerver/lib: Change use of typing.Text to str. 2018-05-10 14:19:49 -07:00
Tim Abbott 2cdd367d49 email_mirror: Fix handling of empty topic.
Also fixs some corner cases around pure-whitespace topics, and
migrates from the years-obsolete "no subject".

Fixes #9207.
2018-04-26 10:21:29 -07:00