microsoft_graph_mailer 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 12632ade885e197f206aa7cbdaa9be6770820b9a47de70eeaf092f606928c911
4
+ data.tar.gz: 409fee6a54f49282b55cb8384a3d4e279e747de350fae421438b19fd43624a28
5
+ SHA512:
6
+ metadata.gz: 156c69eebea594d1aa1a554155cc4fb82aeeca74085fe8bd87f90e66f01a88a041ce0044a3ddbcff05cd4175394b825bc51a2a97d9910454a4e6b122e5b07761
7
+ data.tar.gz: 2ed8b199e9f26d0629f78a153c857fe13b1645a99515c3f21c3db9527503f293b933d47429d01e0df277a82a2f0da6ba469ee1720999e674dc14ccba8a1693fa
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 GitLab B.V.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,104 @@
1
+ # microsoft_graph_mailer
2
+
3
+ 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).
4
+
5
+ ## The reason for this gem
6
+
7
+ See [https://gitlab.com/groups/gitlab-org/-/epics/8259](https://gitlab.com/groups/gitlab-org/-/epics/8259).
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'microsoft_graph_mailer'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ ```shell
20
+ bundle
21
+ ```
22
+
23
+ Or install it yourself as:
24
+
25
+ ```shell
26
+ gem install microsoft_graph_mailer
27
+ ```
28
+
29
+ ## Settings
30
+
31
+ To use the Microsoft Graph API to send mails, you will
32
+ need to create an application in the Azure Active Directory. See the
33
+ [Microsoft instructions](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) for more details:
34
+
35
+ 1. Sign in to the [Azure portal](https://portal.azure.com).
36
+ 1. Search for and select `Azure Active Directory`.
37
+ 1. Under `Manage`, select `App registrations` > `New registration`.
38
+ 1. Enter a `Name` for your application, such as `MicrosoftGraphMailer`. Users of your app might see this name, and you can change it later.
39
+ 1. If `Supported account types` is listed, select the appropriate option.
40
+ 1. Leave `Redirect URI` blank. This is not needed.
41
+ 1. Select `Register`.
42
+ 1. Under `Manage`, select `Certificates & secrets`.
43
+ 1. Under `Client secrets`, select `New client secret`, and enter a name.
44
+ 1. Under `Expires`, select `Never`, unless you plan on updating the credentials every time it expires.
45
+ 1. Select `Add`. Record the secret value in a safe location for use in a later step.
46
+ 1. Under `Manage`, select `API Permissions` > `Add a permission`. Select `Microsoft Graph`.
47
+ 1. Select `Application permissions`.
48
+ 1. Under the `Mail` node, select `Mail.Send`. Then select Add permissions.
49
+ 1. If `User.Read` is listed in the permission list, you can delete this.
50
+ 1. Click `Grant admin consent` for these permissions.
51
+
52
+ - `user_id` - The unique identifier for the user. To use Microsoft Graph on behalf of the user.
53
+ - `tenant` - The directory tenant the application plans to operate against, in GUID or domain-name format.
54
+ - `client_id` - The application ID that's assigned to your app. You can find this information in the portal where you registered your app.
55
+ - `client_secret` - The client secret that you generated for your app in the app registration portal.
56
+
57
+ ## Usage
58
+
59
+ ```ruby
60
+ require "microsoft_graph_mailer"
61
+
62
+ microsoft_graph_mailer = MicrosoftGraphMailer::Delivery.new(
63
+ {
64
+ user_id: "YOUR-USER-ID",
65
+ tenant: "YOUR-TENANT-ID",
66
+ client_id: "YOUR-CLIENT-ID",
67
+ client_secret: "YOUR-CLIENT-SECRET-ID"
68
+ # Defaults to "https://login.microsoftonline.com".
69
+ azure_ad_endpoint: "https://login.microsoftonline.us",
70
+ # Defaults to "https://graph.microsoft.com".
71
+ graph_endpoint: "https://graph.microsoft.us"
72
+ }
73
+ )
74
+
75
+ message = Mail.new do
76
+ from "about@gitlab.com"
77
+ to "to@example.com"
78
+ subject "GitLab Mission"
79
+
80
+ html_part do
81
+ content_type "text/html; charset=UTF-8"
82
+ body "It is GitLab's mission to make it so that <strong>everyone can contribute</strong>."
83
+ end
84
+ end
85
+
86
+ microsoft_graph_mailer.deliver!(message)
87
+ ```
88
+
89
+ ## Usage with ActionMailer
90
+
91
+ ```ruby
92
+ ActionMailer::Base.delivery_method = :microsoft_graph
93
+
94
+ ActionMailer::Base.microsoft_graph_settings = {
95
+ user_id: "YOUR-USER-ID",
96
+ tenant: "YOUR-TENANT-ID",
97
+ client_id: "YOUR-CLIENT-ID",
98
+ client_secret: "YOUR-CLIENT-SECRET-ID"
99
+ # Defaults to "https://login.microsoftonline.com".
100
+ azure_ad_endpoint: "https://login.microsoftonline.us",
101
+ # Defaults to "https://graph.microsoft.com".
102
+ graph_endpoint: "https://graph.microsoft.us"
103
+ }
104
+ ```
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "oauth2"
4
+
5
+ module MicrosoftGraphMailer
6
+ class Client
7
+ attr_accessor :user_id, :tenant, :client_id, :client_secret, :azure_ad_endpoint, :graph_endpoint
8
+
9
+ def initialize(user_id:, tenant:, client_id:, client_secret:, azure_ad_endpoint:, graph_endpoint:)
10
+ @user_id = user_id
11
+ @tenant = tenant
12
+ @client_id = client_id
13
+ @client_secret = client_secret
14
+ @azure_ad_endpoint = azure_ad_endpoint
15
+ @graph_endpoint = graph_endpoint
16
+ end
17
+
18
+ def send_mail(message_in_mime_format)
19
+ # https://docs.microsoft.com/en-us/graph/api/user-sendmail
20
+ token.post(
21
+ send_mail_url,
22
+ headers: { "Content-type" => "text/plain" },
23
+ body: Base64.encode64(message_in_mime_format)
24
+ )
25
+ end
26
+
27
+ private
28
+
29
+ def token
30
+ # https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
31
+ OAuth2::Client.new(
32
+ client_id,
33
+ client_secret,
34
+ site: azure_ad_endpoint,
35
+ token_url: "/#{tenant}/oauth2/v2.0/token"
36
+ ).client_credentials.get_token({ scope: scope })
37
+ end
38
+
39
+ def scope
40
+ "#{graph_endpoint}/.default"
41
+ end
42
+
43
+ def base_url
44
+ "#{graph_endpoint}/v1.0/users/#{user_id}"
45
+ end
46
+
47
+ def send_mail_url
48
+ "#{base_url}/sendMail"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "client"
4
+
5
+ module MicrosoftGraphMailer
6
+ class Delivery
7
+ attr_reader :microsoft_graph_settings
8
+
9
+ def initialize(microsoft_graph_settings)
10
+ @microsoft_graph_settings = microsoft_graph_settings
11
+
12
+ [:user_id, :tenant, :client_id, :client_secret].each do |setting|
13
+ unless microsoft_graph_settings[setting]
14
+ raise MicrosoftGraphMailer::ConfigurationError, "'#{setting}' is missing"
15
+ end
16
+ end
17
+
18
+ @microsoft_graph_settings[:azure_ad_endpoint] ||= "https://login.microsoftonline.com"
19
+ @microsoft_graph_settings[:graph_endpoint] ||= "https://graph.microsoft.com"
20
+ end
21
+
22
+ def deliver!(message)
23
+ # https://github.com/mikel/mail/pull/872
24
+ if message[:bcc]
25
+ previous_message_bcc_include_in_headers = message[:bcc].include_in_headers
26
+ message[:bcc].include_in_headers = true
27
+ end
28
+
29
+ message_in_mime_format = message.encoded
30
+
31
+ client = MicrosoftGraphMailer::Client.new(
32
+ user_id: microsoft_graph_settings[:user_id],
33
+ tenant: microsoft_graph_settings[:tenant],
34
+ client_id: microsoft_graph_settings[:client_id],
35
+ client_secret: microsoft_graph_settings[:client_secret],
36
+ azure_ad_endpoint: microsoft_graph_settings[:azure_ad_endpoint],
37
+ graph_endpoint: microsoft_graph_settings[:graph_endpoint]
38
+ )
39
+
40
+ response = client.send_mail(message_in_mime_format)
41
+
42
+ raise MicrosoftGraphMailer::DeliveryError unless response.status == 202
43
+
44
+ response
45
+ ensure
46
+ message[:bcc].include_in_headers = previous_message_bcc_include_in_headers if message[:bcc]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "delivery"
4
+
5
+ module MicrosoftGraphMailer
6
+ class Railtie < Rails::Railtie
7
+ ActiveSupport.on_load(:action_mailer) do
8
+ add_delivery_method :microsoft_graph, MicrosoftGraphMailer::Delivery
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MicrosoftGraphMailer
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "microsoft_graph_mailer/delivery"
4
+ require_relative "microsoft_graph_mailer/railtie" if defined?(Rails::Railtie)
5
+ require_relative "microsoft_graph_mailer/version"
6
+
7
+ module MicrosoftGraphMailer
8
+ class Error < StandardError
9
+ end
10
+
11
+ class ConfigurationError < Error
12
+ end
13
+
14
+ class DeliveryError < Error
15
+ end
16
+ end
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: microsoft_graph_mailer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Bogdan Denkovych
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-19 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: mail
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.7'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: oauth2
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.4.4
34
+ - - "<"
35
+ - !ruby/object:Gem::Version
36
+ version: '3'
37
+ type: :runtime
38
+ prerelease: false
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: 1.4.4
44
+ - - "<"
45
+ - !ruby/object:Gem::Version
46
+ version: '3'
47
+ - !ruby/object:Gem::Dependency
48
+ name: debug
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.0.0
61
+ - !ruby/object:Gem::Dependency
62
+ name: rails
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: rspec
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 3.11.0
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 3.11.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: webmock
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 3.18.1
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 3.18.1
103
+ description:
104
+ email:
105
+ - bdenkovych@gitlab.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - LICENSE.txt
111
+ - README.md
112
+ - lib/microsoft_graph_mailer.rb
113
+ - lib/microsoft_graph_mailer/client.rb
114
+ - lib/microsoft_graph_mailer/delivery.rb
115
+ - lib/microsoft_graph_mailer/railtie.rb
116
+ - lib/microsoft_graph_mailer/version.rb
117
+ homepage: https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/gems/microsoft_graph_mailer
118
+ licenses:
119
+ - MIT
120
+ metadata:
121
+ homepage_uri: https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/gems/microsoft_graph_mailer
122
+ source_code_uri: https://gitlab.com/gitlab-org/gitlab/-/tree/master/vendor/gems/microsoft_graph_mailer
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 2.7.0
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubygems_version: 3.3.22
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Allows delivery of emails using Microsoft Graph API with OAuth 2.0 client
142
+ credentials flow
143
+ test_files: []