Skip to content

Implement an Internal API to handle mailroom webhook

What does this MR do and why?

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

GitLab's incoming email feature enables the users to perform some actions on GitLab by replying to the notification directly. This feature depends on a service called MailRoom. Internally, this service uses a forked version of mailroom gem for the core logic. When the service starts, it periodically scans the configured email inboxes. New emails are pushed to GitLab Sidekiq fleet via EmailReceiverWorker and ServiceDeskEmailReceiverWorker. The recent configuration uses mailroom gem's sidekiq delivery strategy. This strategy pushes the job payloads directly into Redis without going through Sidekiq client middleware. This creates some issues:

We are making an attempt to migrate the sidekiq strategy to a webhook mechanism. This MR is one of the first step to accomplish that goal. Changes are in this MR:

  • Implement an internal API: POST /api/v4/internal/mail_room/*mailbox_type. This internal endpoint uses a JWT-style authentication header. This pattern was used in gitlab-pages and kas.
  • Create secret_file field to incoming_email and service_desk_email configuration. This field is the path to a shared symmetric secret file used to verify the JWT token in the Rails application. This field is essential to collaborate between mailroom processes and rails application in later iterations (gitlab-com/gl-infra/scalability#1456 (closed), gitlab-com/gl-infra/scalability#1458 (closed), gitlab-com/gl-infra/scalability#1461 (closed)).
  • Add JwtAuthenticable authentication to the aforementioned endpoint. This concern supports a single secret path at the moment. We'll need to modify it a bit to support two mailbox type secret files.

This MR should be review as a pair of the mailroom change.

Screenshots or screen recordings

This MR adds one internal endpoint. There shouldn't be any change from the user perspective.

How to set up and validate locally

  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 rails 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")
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 latest notification of the comment created from the above script.

Screen_Shot_2021-12-14_at_14.33.35

  1. Click on the comment, the issue page shows the comment:

Screen_Shot_2021-12-14_at_14.33.31

MR acceptance checklist

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

Edited by Quang-Minh Nguyen

Merge request reports