Skip to content

Use Service Desk custom email as Reply-To email

Marc Saleiko requested to merge ms-sd-custom-email-reply-to into master

Feature context

Click to expand 👇

Right now it is not possible to customize the Service Desk email address (intake and sending) in its entirety. On self-hosted instances you have more control over the used addresses, but you will still have a rather cryptic target email address for a specific service desk in a project. For .com users it's currently not possible to customize the Service Desk email at all.

There is a proposal and a further exploration around this issue. A summary of the solution path is the following: Users set up their custom email to forward all emails to the cryptic Service Desk email and provide SMTP credentials so we can send emails on their behalf. This way customers seeking support will only see the custom email address in their communication.

There is further discussion about improving and changing the general infrastructure, but this approach is a MVC to solve the issue for our customers.

🗺 How does it contribute to the whole feature?

This MR is part of a series of MRs that will follow in order to complete this feature. See #329990 (comment 1227384943) for a detailed breakdown. Here's a summary:

  1. Using SMTP credentials. Foundation work.
  2. Verify email ownership, correct function and setup
  3. Add settings and validation to Settings page.
  4. 👷 Ingest replies from custom email
    1. 🎯 Use Service Desk custom email as Reply-To email
    2. Ingest replies generated from Service Desk custom email
  5. Add documentation

What does this MR do and why?

Contributes to Custom email reply address (#423879 - closed) and Configurable e-mail address for service desk (#329990 - closed)

This MR introduces the feature flag service_desk_custom_email_reply and generates a Reply-To header address from the Service Desk custom email instead of the incoming email if enabled.

The Service Desk custom email feature sends Service Desk emails using custom SMTP settings. The next step is to change the Reply-To header from an address generated from incoming_email to an address generated from the custom email.

Say you have an incoming address incoming@example.com and a custom email address support@example.com. A reply address would normally look like this: incoming+b7721fc7e8419911a8bea145236a0519@example.com. If the feature flag is enabled and a custom email address is configured and enabled we generate this reply address: support+b7721fc7e8419911a8bea145236a0519@example.com.

Screenshots or screen recordings

🚫 backend only

How to set up and validate locally

There are a number of settings and records that need to be set up, but you can easily reverse that. We will fake set up a custom email address for Service Desk and not use real email ingestion at all.

  1. Select a project and an issue and make it a Service Desk issue
    project = Project.find(7)
    current_user = User.first
    # Create a new issue before running this script if you'd like to use a vanilla issue.
    issue = project.issues.last
    participant_email = 'user@example.com'
    
    issue.update!(author: Users::Internal.support_bot, service_desk_reply_to: participant_email)
    IssueEmailParticipant.create!(issue: issue, email: participant_email)
  2. Add a comment to the issue and keep the reference
    note_params = {
      noteable_type: 'Issue',
      noteable_id: issue.id,
      note: FFaker::Lorem.sentence,
    }
    note = Notes::CreateService.new(project, current_user, note_params).execute
  3. Enable feature flag for custom email and custom email reply
    Feature.enable(:service_desk_custopm_email, project)
    Feature.enable(:service_desk_custopm_email_reply, project)
  4. Configure a custom email address and mark verification as finished and enable custom email for this Service Desk
    custom_email = 'support@example.com'
    
    setting = ServiceDeskSetting.find_or_create_by!(project_id: project.id)
    setting.update!(custom_email: custom_email)
    
    credential = ServiceDesk::CustomEmailCredential.create!(
      project_id: project.id,
      smtp_address: 'smtp.gmail.com', # we need a valid smtp address
      smtp_port: 587,
      smtp_username: custom_email,
      smtp_password: 'supersecret'
    )
    
    verification = ServiceDesk::CustomEmailVerification.new(
      project_id: project.id
    )
    verification.mark_as_started!(current_user)
    verification.mark_as_finished!
    
    project.reset
    setting.reset
    
    # Enabled custom email
    setting.update!(custom_email_enabled: true)
  5. Generate new note email
    mail = Notify.service_desk_new_note_email(issue.id, note.id, issue.service_desk_reply_to)
    last_reply_key = SentNotification.last
  6. Check whether the reply address matches custom email and reply key is from latest SentNotificationentry
    puts "issue id #{issue.id}"
    puts "mail reply to #{mail.reply_to}"
    puts "Last reply key is #{last_reply_key.reply_key} for noteable #{last_reply_key.noteable_type}##{last_reply_key.noteable_id}"
    nil

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 Marc Saleiko

Merge request reports