Skip to content

Wrong Content-Type of Service Desk emails with template & attachments

Solves Wrong Content-Type of Service Desk `new_note` e... (#404967 - closed)

What does this MR do and why?

Service Desk new_note emails with a new_note.md template file in a repository and attachments used a wrong Content-Type text/plain instead of text/html. We also had no test coverage for this and also had no specs for service desk notification emails without a template.

Before native attachments we always set the content type to text/html. While working on native attachments we added a condition that only sets the content type to text/html if no attachments are present. But that does not work for cases with template and attachments. This is the comment that explain why we added the condition. TL;DR before we always set it to html, but with attachments we need a different content type . See additional info in MR comment

What we missed in that MR (maybe due to test coverage issues) was that we also needed to set this for cases with template and attachments.

Email envelopes and email parts

  1. Emails with both text and html have a content type of multipart/alternative. Inside, it has two parts, text/plain and text/html.
  2. Emails with attachments have a content type of multipart/mixed. If they only contain text or html then they have a text/plain or text/html part followed by the attachment part. The attachment is always last.
  3. Emails with attachments that have both text and html, have the multipart/mixed multipart/alternative content type. The first part is an envelope multipart/alternative that contains two parts text/plain and text/html. After the envelope all attachment parts follow. It contains the two parts text/plain and text/html followed by all attachments.

How does GitLab render these emails?

  1. Without template: We provide a text and html version.
    1. Without attachments the content type is multipart/alternative and the email contains the two content parts.
    2. With attachments the content type is multipart/mixed multipart/alternative. First part is a multipart/alternative envelope with the two content parts. After that all attachments. It contains the two content parts text/plain and text/html followed by all attachments.
  2. With template: We only provide a html version.
    1. Without attachments the content type is text/html. End of story.
    2. With attachments the content type is multipart/mixed. The first part is text/html (bug behavior was text/plain) with the template content followed by all attachments.

What has been done?

  1. Because email parts for emails with and without attachments and with and without templates are quite different we need strict tests that also inspect envelopes, email parts, their content types and the content.
    1. I added a new shared example a service desk notification email that checks envelopes and parts for emails without template and with and without attachments
    2. I modified the existing shared example for template content and renamed it to a service desk notification email with template content, so it also checks the envelope and content type (it only checked the content before).
  2. We reordered some method calls and add the attachments after the mail has been generated.
  3. For some reason the content part that was generated from a template had the content type text/plain. We can only change content types for parts, once the email has been generated. So I change the part content type in service_desk_new_note_email when attachments are present and we use a template. We only set the content_type for template content directly via the options. ActionMailer overrides this when we add new attachments after the mail has been generated.
  4. We don't have any information whether a template was used or not. We can only determine this from the parts that are used in the email. So I added a helper method uses_template? that checks that we do not have any multipart/alternative envelopes in our email. We don't need that anymore because we rely on ActionMailer to figure things out.
  5. Refactored some variable naming in the spec file as they were not very clear or misleading.
  6. We did not have examples in place that checked emails without template. We now have that for all notification emails.
  7. Pulled specs for attachments out of the with template context and addressed both with and without template in one go, to avoid code duplication.

Screenshots or screen recordings

Before:

image

After:

image

How to set up and validate locally

  1. Find a Service Desk issue, make an issue a Service Desk issue or create a new one (email ingestion required)
    # Make Service Desk issue from existing issue
    # Use whatever project with activated Service Desk. Defaults to "on" for every project
    project = Project.find_by(name: 'Flight')
    # E.g. issue with iid 12 in Flight project
    issue = Issue.find_by(project: project, iid: 12)
    your_email = 'yourname@gitlab.com'
    # Service Desk issues are authored by GitLab Support Bot
    issue.update!(service_desk_reply_to: your_email, author_id: User.support_bot.id)
    # Issue Email Participant is mandatory to generate service desk emails
    IssueEmailParticipant.create!(issue_id: issue.id, email: your_email)
  2. Add a template for the new_note email in the project's repository in .gitlab/service_deak_templates/new_note.md with some content. E.g.
    %{SYSTEM_HEADER}
    
    New message for issue **%{ISSUE_ID}** on **%{ISSUE_PATH}**
    
    %{NOTE_TEXT}
    
    [Unsubscribe](%{UNSUBSCRIBE_URL})
    
    %{SYSTEM_FOOTER}
  3. Go back to the issue and add a public comment. You should see the email in letter opener and it should use the template
  4. Write a public comment and add an upload to the comment. You should see the email in letter opener and it should display correctly (html) and have the attachments (link displayed in the list view).
  5. (Optional) If you want to further inspect the email, you could set up outgoing emails by having a config/initializers/smtp_settings.rb file in place and configured (see configuration in config/initializers/smtp_settings.rb.sample. I use a mailgun test account. Works fine). After gdk restart and sending another email with attachments you should find that email in the email participants mailbox (e.g. your company's gmail account). If you inspect the original email, you should see the content type multipart/mixed. The content part should have a content type of text/html.

MR acceptance checklist

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

Related to #404967 (closed)

Edited by Marc Saleiko

Merge request reports