diff options
Diffstat (limited to 'vendor/gems/microsoft_graph_mailer')
17 files changed, 898 insertions, 0 deletions
diff --git a/vendor/gems/microsoft_graph_mailer/.gitlab-ci.yml b/vendor/gems/microsoft_graph_mailer/.gitlab-ci.yml new file mode 100644 index 00000000000..1b10debb1b9 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/.gitlab-ci.yml @@ -0,0 +1,32 @@ +workflow: + rules: + - if: $CI_MERGE_REQUEST_ID + +.rspec: + cache: + key: microsoft_graph_mailer-ruby + paths: + - vendor/gems/microsoft_graph_mailer/vendor/ruby + before_script: + - cd vendor/gems/microsoft_graph_mailer + - ruby -v # Print out ruby version for debugging + - gem install bundler --no-document # Bundler is not installed with the image + - bundle config set --local path 'vendor' # Install dependencies into ./vendor/ruby + - bundle config set with 'development' + - bundle config set --local frozen 'true' # Disallow Gemfile.lock changes on CI + - bundle config # Show bundler configuration + - bundle install -j $(nproc) + script: + - bundle exec rspec + +rspec-2.7: + image: "ruby:2.7" + extends: .rspec + +rspec-3.0: + image: "ruby:3.0" + extends: .rspec + +rspec-3.1: + image: "ruby:3.1" + extends: .rspec diff --git a/vendor/gems/microsoft_graph_mailer/Gemfile b/vendor/gems/microsoft_graph_mailer/Gemfile new file mode 100644 index 00000000000..be173b205f7 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/Gemfile @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gemspec diff --git a/vendor/gems/microsoft_graph_mailer/Gemfile.lock b/vendor/gems/microsoft_graph_mailer/Gemfile.lock new file mode 100644 index 00000000000..d6bb01eba73 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/Gemfile.lock @@ -0,0 +1,217 @@ +PATH + remote: . + specs: + microsoft_graph_mailer (0.1.0) + mail (~> 2.7) + oauth2 (>= 1.4.4, < 3) + +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.0.4) + actionpack (= 7.0.4) + activesupport (= 7.0.4) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (7.0.4) + actionpack (= 7.0.4) + activejob (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + mail (>= 2.7.1) + net-imap + net-pop + net-smtp + actionmailer (7.0.4) + actionpack (= 7.0.4) + actionview (= 7.0.4) + activejob (= 7.0.4) + activesupport (= 7.0.4) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.0) + actionpack (7.0.4) + actionview (= 7.0.4) + activesupport (= 7.0.4) + rack (~> 2.0, >= 2.2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (7.0.4) + actionpack (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + globalid (>= 0.6.0) + nokogiri (>= 1.8.5) + actionview (7.0.4) + activesupport (= 7.0.4) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.4) + activesupport (= 7.0.4) + globalid (>= 0.3.6) + activemodel (7.0.4) + activesupport (= 7.0.4) + activerecord (7.0.4) + activemodel (= 7.0.4) + activesupport (= 7.0.4) + activestorage (7.0.4) + actionpack (= 7.0.4) + activejob (= 7.0.4) + activerecord (= 7.0.4) + activesupport (= 7.0.4) + marcel (~> 1.0) + mini_mime (>= 1.1.0) + activesupport (7.0.4) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) + builder (3.2.4) + concurrent-ruby (1.1.10) + crack (0.4.5) + rexml + crass (1.0.6) + debug (1.6.2) + irb (>= 1.3.6) + reline (>= 0.3.1) + diff-lcs (1.5.0) + digest (3.1.0) + erubi (1.11.0) + faraday (2.5.2) + faraday-net_http (>= 2.0, < 3.1) + ruby2_keywords (>= 0.0.4) + faraday-net_http (3.0.0) + globalid (1.0.0) + activesupport (>= 5.0) + hashdiff (1.0.1) + hashie (5.0.0) + i18n (1.12.0) + concurrent-ruby (~> 1.0) + io-console (0.5.11) + irb (1.4.1) + reline (>= 0.3.0) + jwt (2.5.0) + loofah (2.19.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (1.0.2) + method_source (1.0.0) + mini_mime (1.1.2) + mini_portile2 (2.8.0) + minitest (5.16.3) + multi_xml (0.6.0) + net-imap (0.2.3) + digest + net-protocol + strscan + net-pop (0.1.1) + digest + net-protocol + timeout + net-protocol (0.1.3) + timeout + net-smtp (0.3.1) + digest + net-protocol + timeout + nio4r (2.5.8) + nokogiri (1.13.8) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + oauth2 (2.0.8) + faraday (>= 0.17.3, < 3.0) + jwt (>= 1.0, < 3.0) + multi_xml (~> 0.5) + rack (>= 1.2, < 3) + snaky_hash (~> 2.0) + version_gem (~> 1.1) + public_suffix (5.0.0) + racc (1.6.0) + rack (2.2.4) + rack-test (2.0.2) + rack (>= 1.3) + rails (7.0.4) + actioncable (= 7.0.4) + actionmailbox (= 7.0.4) + actionmailer (= 7.0.4) + actionpack (= 7.0.4) + actiontext (= 7.0.4) + actionview (= 7.0.4) + activejob (= 7.0.4) + activemodel (= 7.0.4) + activerecord (= 7.0.4) + activestorage (= 7.0.4) + activesupport (= 7.0.4) + bundler (>= 1.15.0) + railties (= 7.0.4) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.4.3) + loofah (~> 2.3) + railties (7.0.4) + actionpack (= 7.0.4) + activesupport (= 7.0.4) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rake (13.0.6) + reline (0.3.1) + io-console (~> 0.5) + rexml (3.2.5) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.1) + diff-lcs (>= 1.2.0, < 2.0) + rspec-support (~> 3.11.0) + rspec-support (3.11.1) + ruby2_keywords (0.0.5) + snaky_hash (2.0.0) + hashie + version_gem (~> 1.1) + strscan (3.0.4) + thor (1.2.1) + timeout (0.3.0) + tzinfo (2.0.5) + concurrent-ruby (~> 1.0) + version_gem (1.1.0) + webmock (3.18.1) + addressable (>= 2.8.0) + crack (>= 0.3.2) + hashdiff (>= 0.4.0, < 2.0.0) + websocket-driver (0.7.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.6.0) + +PLATFORMS + ruby + +DEPENDENCIES + debug (>= 1.0.0) + microsoft_graph_mailer! + rails + rspec (~> 3.11.0) + webmock (~> 3.18.1) + +BUNDLED WITH + 2.3.22 diff --git a/vendor/gems/microsoft_graph_mailer/LICENSE.txt b/vendor/gems/microsoft_graph_mailer/LICENSE.txt new file mode 100644 index 00000000000..7ed79aa0423 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2022 GitLab B.V. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/gems/microsoft_graph_mailer/README.md b/vendor/gems/microsoft_graph_mailer/README.md new file mode 100644 index 00000000000..dd9dfecfc56 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/README.md @@ -0,0 +1,104 @@ +# microsoft_graph_mailer + +This gem allows delivery of emails using [Microsoft Graph API](https://docs.microsoft.com/en-us/graph/api/user-sendmail) with [OAuth 2.0 client credentials flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow). + +## The reason for this gem + +See [https://gitlab.com/groups/gitlab-org/-/epics/8259](https://gitlab.com/groups/gitlab-org/-/epics/8259). + +## Installation + +Add this line to your application's Gemfile: + +```ruby +gem 'microsoft_graph_mailer' +``` + +And then execute: + +```shell +bundle +``` + +Or install it yourself as: + +```shell +gem install microsoft_graph_mailer +``` + +## Settings + +To use the Microsoft Graph API to send mails, you will +need to create an application in the Azure Active Directory. See the +[Microsoft instructions](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) for more details: + +1. Sign in to the [Azure portal](https://portal.azure.com). +1. Search for and select `Azure Active Directory`. +1. Under `Manage`, select `App registrations` > `New registration`. +1. Enter a `Name` for your application, such as `MicrosoftGraphMailer`. Users of your app might see this name, and you can change it later. +1. If `Supported account types` is listed, select the appropriate option. +1. Leave `Redirect URI` blank. This is not needed. +1. Select `Register`. +1. Under `Manage`, select `Certificates & secrets`. +1. Under `Client secrets`, select `New client secret`, and enter a name. +1. Under `Expires`, select `Never`, unless you plan on updating the credentials every time it expires. +1. Select `Add`. Record the secret value in a safe location for use in a later step. +1. Under `Manage`, select `API Permissions` > `Add a permission`. Select `Microsoft Graph`. +1. Select `Application permissions`. +1. Under the `Mail` node, select `Mail.Send`. Then select Add permissions. +1. If `User.Read` is listed in the permission list, you can delete this. +1. Click `Grant admin consent` for these permissions. + +- `user_id` - The unique identifier for the user. To use Microsoft Graph on behalf of the user. +- `tenant` - The directory tenant the application plans to operate against, in GUID or domain-name format. +- `client_id` - The application ID that's assigned to your app. You can find this information in the portal where you registered your app. +- `client_secret` - The client secret that you generated for your app in the app registration portal. + +## Usage + +```ruby +require "microsoft_graph_mailer" + +microsoft_graph_mailer = MicrosoftGraphMailer::Delivery.new( + { + user_id: "YOUR-USER-ID", + tenant: "YOUR-TENANT-ID", + client_id: "YOUR-CLIENT-ID", + client_secret: "YOUR-CLIENT-SECRET-ID" + # Defaults to "https://login.microsoftonline.com". + azure_ad_endpoint: "https://login.microsoftonline.us", + # Defaults to "https://graph.microsoft.com". + graph_endpoint: "https://graph.microsoft.us" + } +) + +message = Mail.new do + from "about@gitlab.com" + to "to@example.com" + subject "GitLab Mission" + + html_part do + content_type "text/html; charset=UTF-8" + body "It is GitLab's mission to make it so that <strong>everyone can contribute</strong>." + end +end + +microsoft_graph_mailer.deliver!(message) +``` + +## Usage with ActionMailer + +```ruby +ActionMailer::Base.delivery_method = :microsoft_graph + +ActionMailer::Base.microsoft_graph_settings = { + user_id: "YOUR-USER-ID", + tenant: "YOUR-TENANT-ID", + client_id: "YOUR-CLIENT-ID", + client_secret: "YOUR-CLIENT-SECRET-ID" + # Defaults to "https://login.microsoftonline.com". + azure_ad_endpoint: "https://login.microsoftonline.us", + # Defaults to "https://graph.microsoft.com". + graph_endpoint: "https://graph.microsoft.us" +} +``` diff --git a/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer.rb b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer.rb new file mode 100644 index 00000000000..8bd252aac94 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +require_relative "microsoft_graph_mailer/delivery" +require_relative "microsoft_graph_mailer/railtie" if defined?(Rails::Railtie) +require_relative "microsoft_graph_mailer/version" + +module MicrosoftGraphMailer + class Error < StandardError + end + + class ConfigurationError < Error + end + + class DeliveryError < Error + end +end diff --git a/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/client.rb b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/client.rb new file mode 100644 index 00000000000..b779bb28c39 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/client.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require "oauth2" + +module MicrosoftGraphMailer + class Client + attr_accessor :user_id, :tenant, :client_id, :client_secret, :azure_ad_endpoint, :graph_endpoint + + def initialize(user_id:, tenant:, client_id:, client_secret:, azure_ad_endpoint:, graph_endpoint:) + @user_id = user_id + @tenant = tenant + @client_id = client_id + @client_secret = client_secret + @azure_ad_endpoint = azure_ad_endpoint + @graph_endpoint = graph_endpoint + end + + def send_mail(message_in_mime_format) + # https://docs.microsoft.com/en-us/graph/api/user-sendmail + token.post( + send_mail_url, + headers: { "Content-type" => "text/plain" }, + body: Base64.encode64(message_in_mime_format) + ) + end + + private + + def token + # https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow + OAuth2::Client.new( + client_id, + client_secret, + site: azure_ad_endpoint, + token_url: "/#{tenant}/oauth2/v2.0/token" + ).client_credentials.get_token({ scope: scope }) + end + + def scope + "#{graph_endpoint}/.default" + end + + def base_url + "#{graph_endpoint}/v1.0/users/#{user_id}" + end + + def send_mail_url + "#{base_url}/sendMail" + end + end +end diff --git a/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/delivery.rb b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/delivery.rb new file mode 100644 index 00000000000..c807ee4319e --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/delivery.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +require_relative "client" + +module MicrosoftGraphMailer + class Delivery + attr_reader :microsoft_graph_settings + + def initialize(microsoft_graph_settings) + @microsoft_graph_settings = microsoft_graph_settings + + [:user_id, :tenant, :client_id, :client_secret].each do |setting| + unless microsoft_graph_settings[setting] + raise MicrosoftGraphMailer::ConfigurationError, "'#{setting}' is missing" + end + end + + @microsoft_graph_settings[:azure_ad_endpoint] ||= "https://login.microsoftonline.com" + @microsoft_graph_settings[:graph_endpoint] ||= "https://graph.microsoft.com" + end + + def deliver!(message) + # https://github.com/mikel/mail/pull/872 + if message[:bcc] + previous_message_bcc_include_in_headers = message[:bcc].include_in_headers + message[:bcc].include_in_headers = true + end + + message_in_mime_format = message.encoded + + client = MicrosoftGraphMailer::Client.new( + user_id: microsoft_graph_settings[:user_id], + tenant: microsoft_graph_settings[:tenant], + client_id: microsoft_graph_settings[:client_id], + client_secret: microsoft_graph_settings[:client_secret], + azure_ad_endpoint: microsoft_graph_settings[:azure_ad_endpoint], + graph_endpoint: microsoft_graph_settings[:graph_endpoint] + ) + + response = client.send_mail(message_in_mime_format) + + raise MicrosoftGraphMailer::DeliveryError unless response.status == 202 + + response + ensure + message[:bcc].include_in_headers = previous_message_bcc_include_in_headers if message[:bcc] + end + end +end diff --git a/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/railtie.rb b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/railtie.rb new file mode 100644 index 00000000000..607d68cc454 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/railtie.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require_relative "delivery" + +module MicrosoftGraphMailer + class Railtie < Rails::Railtie + ActiveSupport.on_load(:action_mailer) do + add_delivery_method :microsoft_graph, MicrosoftGraphMailer::Delivery + end + end +end diff --git a/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/version.rb b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/version.rb new file mode 100644 index 00000000000..057aebdad2b --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/lib/microsoft_graph_mailer/version.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +module MicrosoftGraphMailer + VERSION = "0.1.0" +end diff --git a/vendor/gems/microsoft_graph_mailer/microsoft_graph_mailer.gemspec b/vendor/gems/microsoft_graph_mailer/microsoft_graph_mailer.gemspec new file mode 100644 index 00000000000..af9fb5987ca --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/microsoft_graph_mailer.gemspec @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require_relative "lib/microsoft_graph_mailer/version" + +Gem::Specification.new do |spec| + spec.name = "microsoft_graph_mailer" + spec.version = MicrosoftGraphMailer::VERSION + spec.authors = ["Bogdan Denkovych"] + spec.email = ["bdenkovych@gitlab.com"] + + spec.summary = "Allows delivery of emails using Microsoft Graph API with OAuth 2.0 client credentials flow" + spec.homepage = "https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/gems/microsoft_graph_mailer" + spec.license = "MIT" + spec.required_ruby_version = ">= 2.7.0" + + spec.metadata["homepage_uri"] = spec.homepage + spec.metadata["source_code_uri"] = "https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/gems/microsoft_graph_mailer" + + spec.files = Dir["lib/**/*.rb"] + ["LICENSE.txt", "README.md"] + spec.require_paths = ["lib"] + + spec.add_runtime_dependency "mail", "~> 2.7" + spec.add_runtime_dependency "oauth2", [">= 1.4.4", "< 3"] + + spec.add_development_dependency "debug", ">= 1.0.0" + spec.add_development_dependency "rails" + spec.add_development_dependency "rspec", "~> 3.11.0" + spec.add_development_dependency "webmock", "~> 3.18.1" +end diff --git a/vendor/gems/microsoft_graph_mailer/spec/fixtures/attachments/gitlab.txt b/vendor/gems/microsoft_graph_mailer/spec/fixtures/attachments/gitlab.txt new file mode 100644 index 00000000000..1df29200042 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/spec/fixtures/attachments/gitlab.txt @@ -0,0 +1 @@ +GitLab diff --git a/vendor/gems/microsoft_graph_mailer/spec/fixtures/attachments/gitlab_logo.png b/vendor/gems/microsoft_graph_mailer/spec/fixtures/attachments/gitlab_logo.png Binary files differnew file mode 100644 index 00000000000..12525056939 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/spec/fixtures/attachments/gitlab_logo.png diff --git a/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer/delivery_spec.rb b/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer/delivery_spec.rb new file mode 100644 index 00000000000..23096e75b76 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer/delivery_spec.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +require "spec_helper" + +require "securerandom" + +RSpec.describe MicrosoftGraphMailer::Delivery do + let(:microsoft_graph_settings) do + { + user_id: SecureRandom.hex, + tenant: SecureRandom.hex, + client_id: SecureRandom.hex, + client_secret: SecureRandom.hex, + azure_ad_endpoint: "https://test-azure_ad_endpoint", + graph_endpoint: "https://test-graph_endpoint" + } + end + + subject { described_class.new(microsoft_graph_settings) } + + describe ".new" do + it "sets #microsoft_graph_settings" do + expect(subject.microsoft_graph_settings).to eq(microsoft_graph_settings) + end + + [:user_id, :tenant, :client_id, :client_secret].each do |setting| + it "raises MicrosoftGraphMailer::ConfigurationError when '#{setting}' is missing" do + microsoft_graph_settings[setting] = nil + + expect { subject } + .to raise_error(MicrosoftGraphMailer::ConfigurationError, "'#{setting}' is missing") + end + end + + it "sets azure_ad_endpoint setting to 'https://login.microsoftonline.com' when it is missing" do + microsoft_graph_settings[:azure_ad_endpoint] = nil + + expect(subject.microsoft_graph_settings[:azure_ad_endpoint]).to eq("https://login.microsoftonline.com") + end + + it "sets graph_endpoint setting to 'https://graph.microsoft.com' when it is missing" do + microsoft_graph_settings[:graph_endpoint] = nil + + expect(subject.microsoft_graph_settings[:graph_endpoint]).to eq("https://graph.microsoft.com") + end + end + + describe "#deliver!" do + let(:access_token) { SecureRandom.hex } + + let(:message) do + Mail.new do + from "about@gitlab.com" + + to "to@example.com" + + cc "cc@example.com" + + subject "GitLab Mission" + + text_part do + body "It is GitLab's mission to make it so that everyone can contribute." + end + + html_part do + content_type "text/html; charset=UTF-8" + body "It is GitLab's mission to make it so that <strong>everyone can contribute</strong>." + end + + add_file fixture_path("attachments", "gitlab.txt") + + add_file fixture_path("attachments", "gitlab_logo.png") + end + end + + context "when token request is successful" do + before do + stub_token_request(microsoft_graph_settings: subject.microsoft_graph_settings, access_token: access_token, response_status: 200) + end + + context "when send mail request returns response status 202" do + it "sends mail and returns an instance of OAuth2::Response" do + stub_send_mail_request(microsoft_graph_settings: subject.microsoft_graph_settings, access_token: access_token, message: message, response_status: 202) + + expect(subject.deliver!(message)).to be_an_instance_of(OAuth2::Response) + end + + it "sends mail including bcc field" do + message.bcc = "bcc@example.com" + + stub_send_mail_request(microsoft_graph_settings: subject.microsoft_graph_settings, access_token: access_token, message: message, response_status: 202) + + subject.deliver!(message) + end + + it "does not change message[:bcc].include_in_headers" do + message.bcc = "bcc@example.com" + expected_message_bcc_include_in_headers = "42" + message[:bcc].include_in_headers = expected_message_bcc_include_in_headers + + stub_send_mail_request(microsoft_graph_settings: subject.microsoft_graph_settings, access_token: access_token, message: message, response_status: 202) + + subject.deliver!(message) + + expect(message[:bcc].include_in_headers).to eq(expected_message_bcc_include_in_headers) + end + end + + context "when send mail request returns response status other than 202" do + it "raises MicrosoftGraphMailer::DeliveryError" do + stub_send_mail_request(microsoft_graph_settings: subject.microsoft_graph_settings, access_token: access_token, message: message, response_status: 200) + + expect { subject.deliver!(message) }.to raise_error(MicrosoftGraphMailer::DeliveryError) + end + end + end + + context "when token request is not successful" do + before do + stub_token_request(microsoft_graph_settings: subject.microsoft_graph_settings, access_token: access_token, response_status: 503) + end + + it "raises OAuth2::Error" do + expect { subject.deliver!(message) }.to raise_error(OAuth2::Error) + end + end + end +end diff --git a/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer/railtie_spec.rb b/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer/railtie_spec.rb new file mode 100644 index 00000000000..d1a60522cdf --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer/railtie_spec.rb @@ -0,0 +1,140 @@ +# frozen_string_literal: true + +require "spec_helper" + +require "securerandom" + +class TestMailer < ActionMailer::Base + def gitlab_mission(to:, cc: []) + mail(from: "about@gitlab.com", to: to, cc: cc, subject: "GitLab Mission") do |format| + format.text { render plain: "It is GitLab's mission to make it so that everyone can contribute." } + format.html { render html: "It is GitLab's mission to make it so that <strong>everyone can contribute</strong>.".html_safe } + end + + mail.attachments["gitlab.txt"] = File.read(fixture_path("attachments", "gitlab.txt")) + + mail.attachments["gitlab_logo.png"] = File.read(fixture_path("attachments", "gitlab_logo.png")) + end +end + +RSpec.describe MicrosoftGraphMailer::Railtie do + let(:microsoft_graph_settings) do + { + user_id: SecureRandom.hex, + tenant: SecureRandom.hex, + client_id: SecureRandom.hex, + client_secret: SecureRandom.hex, + azure_ad_endpoint: "https://test-azure_ad_endpoint", + graph_endpoint: "https://test-graph_endpoint" + } + end + + let(:message) { TestMailer.gitlab_mission(to: "to@example.com", cc: "cc@example.com") } + + before do + ActionMailer::Base.delivery_method = :microsoft_graph + ActionMailer::Base.microsoft_graph_settings = microsoft_graph_settings + end + + it "its superclass is Rails::Railtie" do + expect(MicrosoftGraphMailer::Railtie.superclass).to eq(Rails::Railtie) + end + + describe "settings" do + describe "ActionMailer::Base.delivery_methods[:microsoft_graph]" do + it "returns MicrosoftGraphMailer::Delivery" do + expect(ActionMailer::Base.delivery_methods[:microsoft_graph]).to eq(MicrosoftGraphMailer::Delivery) + end + end + + describe "ActionMailer::Base.microsoft_graph_settings" do + it "returns microsoft_graph_settings" do + expect(ActionMailer::Base.microsoft_graph_settings).to eq(microsoft_graph_settings) + end + end + + it "sets #microsoft_graph_settings" do + expect(message.delivery_method.microsoft_graph_settings).to eq(microsoft_graph_settings) + end + + [:user_id, :tenant, :client_id, :client_secret].each do |setting| + it "raises MicrosoftGraphMailer::ConfigurationError when '#{setting}' is missing" do + microsoft_graph_settings[setting] = nil + ActionMailer::Base.microsoft_graph_settings = microsoft_graph_settings + + expect { message.delivery_method } + .to raise_error(MicrosoftGraphMailer::ConfigurationError, "'#{setting}' is missing") + end + end + + it "sets azure_ad_endpoint setting to 'https://login.microsoftonline.com' when it is missing" do + microsoft_graph_settings[:azure_ad_endpoint] = nil + ActionMailer::Base.microsoft_graph_settings = microsoft_graph_settings + + expect(message.delivery_method.microsoft_graph_settings[:azure_ad_endpoint]).to eq("https://login.microsoftonline.com") + end + + it "sets graph_endpoint setting to 'https://graph.microsoft.com' when it is missing" do + microsoft_graph_settings[:graph_endpoint] = nil + ActionMailer::Base.microsoft_graph_settings = microsoft_graph_settings + + expect(message.delivery_method.microsoft_graph_settings[:graph_endpoint]).to eq("https://graph.microsoft.com") + end + end + + describe "ActionMailer::MessageDelivery#deliver_now" do + let(:access_token) { SecureRandom.hex } + + context "when token request is successful" do + before do + stub_token_request(microsoft_graph_settings: microsoft_graph_settings, access_token: access_token, response_status: 200) + end + + context "when send mail request returns response status 202" do + it "sends and returns mail" do + stub_send_mail_request(microsoft_graph_settings: microsoft_graph_settings, access_token: access_token, message: message, response_status: 202) + + expect(message.deliver_now).to eq(message) + end + + it "sends mail including bcc field" do + message.bcc = "bcc@example.com" + + stub_send_mail_request(microsoft_graph_settings: microsoft_graph_settings, access_token: access_token, message: message, response_status: 202) + + message.deliver_now + end + + it "does not change message[:bcc].include_in_headers" do + message.bcc = "bcc@example.com" + expected_message_bcc_include_in_headers = "42" + message[:bcc].include_in_headers = expected_message_bcc_include_in_headers + + stub_send_mail_request(microsoft_graph_settings: microsoft_graph_settings, access_token: access_token, message: message, response_status: 202) + + message.deliver_now + + expect(message[:bcc].include_in_headers).to eq(expected_message_bcc_include_in_headers) + end + end + + context "when send mail request returns response status other than 202" do + it "raises MicrosoftGraphMailer::DeliveryError" do + stub_send_mail_request(microsoft_graph_settings: microsoft_graph_settings, access_token: access_token, message: message, response_status: 200) + + expect { message.deliver_now }.to raise_error(MicrosoftGraphMailer::DeliveryError) + end + end + end + + context "when token request is not successful" do + before do + stub_token_request(microsoft_graph_settings: microsoft_graph_settings, access_token: access_token, response_status: 503) + end + + it "raises OAuth2::Error" do + expect { message.deliver_now }.to raise_error(OAuth2::Error) + end + end + end +end diff --git a/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer_spec.rb b/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer_spec.rb new file mode 100644 index 00000000000..3306e91db38 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/spec/lib/microsoft_graph_mailer_spec.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe MicrosoftGraphMailer do + describe "::VERSION" do + it "returns a version number" do + expect(MicrosoftGraphMailer::VERSION).to eq("0.1.0") + end + end + + describe "::Error" do + it "its superclass is StandardError" do + expect(MicrosoftGraphMailer::Error.superclass).to eq(StandardError) + end + end + + describe "::ConfigurationError" do + it "its superclass is MicrosoftGraphMailer::Error" do + expect(MicrosoftGraphMailer::ConfigurationError.superclass).to eq(MicrosoftGraphMailer::Error) + end + end + + describe "::DeliveryError" do + it "its superclass is MicrosoftGraphMailer::Error" do + expect(MicrosoftGraphMailer::DeliveryError.superclass).to eq(MicrosoftGraphMailer::Error) + end + end +end diff --git a/vendor/gems/microsoft_graph_mailer/spec/spec_helper.rb b/vendor/gems/microsoft_graph_mailer/spec/spec_helper.rb new file mode 100644 index 00000000000..ac5dd817904 --- /dev/null +++ b/vendor/gems/microsoft_graph_mailer/spec/spec_helper.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require "rails" +require "action_mailer/railtie" + +require "microsoft_graph_mailer" + +require "mail" + +require "webmock/rspec" + +RSpec.configure do |config| +end + +def fixture_path(*path) + File.join(__dir__, "fixtures", path) +end + +def stub_token_request(microsoft_graph_settings:, access_token:, response_status:) + stub_request( + :post, + "#{microsoft_graph_settings[:azure_ad_endpoint]}/#{microsoft_graph_settings[:tenant]}/oauth2/v2.0/token" + ).with( + body: { + "grant_type" => "client_credentials", + "scope" => "#{microsoft_graph_settings[:graph_endpoint]}/.default" + } + ).to_return( + body: { + "token_type" => "Bearer", + "expires_in" => "3599", + "access_token" => access_token + }.to_json, + status: response_status, + headers: { "content-type" => "application/json; charset=utf-8" } + ) +end + +def stub_send_mail_request(microsoft_graph_settings:, access_token:, message:, response_status:) + if message[:bcc] + previous_message_bcc_include_in_headers = message[:bcc].include_in_headers + message[:bcc].include_in_headers = true + end + + stub_request( + :post, + "#{microsoft_graph_settings[:graph_endpoint]}/v1.0/users/#{microsoft_graph_settings[:user_id]}/sendMail" + ).with( + body: Base64.encode64(message.encoded), + headers: { + "Authorization" => "Bearer #{access_token}", + "Content-Type" => "text/plain" + } + ).to_return( + body: "", + status: response_status + ) +ensure + message[:bcc].include_in_headers = previous_message_bcc_include_in_headers if message[:bcc] +end |