Skip to content

Send a rejection email if incoming emails are too large

What does this MR do and why?

For gitlab-com/gl-infra/scalability#1488 (closed)

In !76724 (merged), we implemented an internal endpoint listening to MailRoom component's webhooks. The webhook requests attach the raw email content in their body. If an email contains a file attachment, the raw encoded email content may be too heavy. As a result, the endpoint refuses to process the email, and returns 400 status code. At the moment, those requests are faded into void without the senders' awareness. This MR is to send a rejection email notifying the senders about this situation.

The solution is simple. The limit exceed exception is caught inside the endpoint. When so, EmailRejectionMailer is triggered. As the failure handler is now inside EmailReceiverWorker, this MR also extracts those logic to Gitlab::Email::FailureHandler so that it can be re-used in the new endpoint.

Screenshots or screen recordings

This is the responding email when an email is too heavy.

Screen_Shot_2022-01-05_at_13.45.50

How to set up and validate locally

  1. Set the background job limit to a reasonable number for testing purpose. A recommended number is 4000 (bytes) compressing threshold and 5000 (bytes) limit.

Screen_Shot_2022-01-05_at_13.46.01

  1. Point the mail_room gem 0.0.17 (https://gitlab.com/gitlab-org/gitlab-mail_room/-/merge_requests/45#note_797929096)
  2. Create a temporary secret file.
echo "eao1Q7WZpH41L3tPdr0+NbUC6h8nHcQ9XE78mHxs5+A=" > /path/to/gdk/gitlab_mailroom_secret
  1. Add secret_file fields to incoming_email and service_desk_email configurations in config/gitlab.yml file. Set enabled of both to true
  incoming_email:
    enabled: true
    secret_file: /path/to/gdk/gitlab_mailroom_secret
  service_desk_email:
    enabled: true
    secret_file: /path/to/gdk/gitlab_mailroom_secrett
  1. Start rails-web and rails-background-jobs
  2. Paste the following script to f console. The script snippet is to add a command and close the latest issue. This script uses the new webhook delivery method in the gem, fires a POST request of the new endpoint.
require 'mail_room/delivery/postback'

incoming_email = Gitlab.config.incoming_email[:address].gsub('%{key}', SentNotification.where(noteable_type: "Issue").last.reply_key)
content = File.read("spec/fixtures/emails/commands_in_reply.eml") + "\n\n" + SecureRandom.hex(5000)
content.gsub!("reply+59d8df8370b7e95c5a49fbf86aeb2c93@appmail.adventuretime.ooo", incoming_email)

::MailRoom::Delivery::Postback.new(MailRoom::Delivery::Postback::Options.new(MailRoom::Mailbox.new(
  name: "inbox",
  email: "user@example.com",
  password: "password123",
  delivery_options: {
    delivery_url: 'http://localhost:3000/api/v4/internal/mail_room/incoming_email',
    jwt_auth_header: "Gitlab-Mailroom-Api-Request",
    jwt_issuer: "gitlab-mailroom",
    jwt_algorithm: "HS256",
    jwt_secret_path: Gitlab::MailRoom.enabled_configs[:incoming_email][:secret_file]
  }
))).deliver(content)
  1. Ensure that email_receiver queue is drained (http://localhost:3000/admin/sidekiq/queues/email_receiver)
  2. Open letter_opener dashboard, you'll see the rejection email:

Screen_Shot_2022-01-05_at_13.45.50

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Merge request reports