Revert "feat: Support Azure single-tenant application using the Graph… (#7436)

This commit is contained in:
Pranav Raj S
2023-06-29 16:50:18 -07:00
committed by GitHub
parent 191b8a64fe
commit 022f4f899f
14 changed files with 13 additions and 451 deletions

View File

@@ -4,7 +4,13 @@ class Api::V1::Accounts::Microsoft::AuthorizationsController < Api::V1::Accounts
def create
email = params[:authorization][:email]
redirect_url = microsoft_client.auth_code.authorize_url(auth_params)
redirect_url = microsoft_client.auth_code.authorize_url(
{
redirect_uri: "#{base_url}/microsoft/callback",
scope: 'offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send openid profile',
prompt: 'consent'
}
)
if redirect_url
email = email.downcase
::Redis::Alfred.setex(email, Current.account.id, 5.minutes)
@@ -19,31 +25,4 @@ class Api::V1::Accounts::Microsoft::AuthorizationsController < Api::V1::Accounts
def check_authorization
raise Pundit::NotAuthorizedError unless Current.account_user.administrator?
end
# SMTP, Pop and IMAP are being deprecated by Outlook.
# https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/deprecation-of-basic-authentication-exchange-online
#
# As such, Microsoft has made it a real pain to use them.
# If AZURE_TENANT_ID is set, we will use the MS Graph API instead.
def auth_params
return graph_auth_params if ENV.fetch('AZURE_TENANT_ID', false)
standard_auth_params
end
def standard_auth_params
{
redirect_uri: "#{base_url}/microsoft/callback",
scope: 'offline_access https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send openid profile',
prompt: 'consent'
}
end
def graph_auth_params
{
redirect_uri: "#{base_url}/microsoft/callback",
scope: 'offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send openid profile',
prompt: 'consent'
}
end
end

View File

@@ -5,8 +5,8 @@ module MicrosoftConcern
::OAuth2::Client.new(ENV.fetch('AZURE_APP_ID', nil), ENV.fetch('AZURE_APP_SECRET', nil),
{
site: 'https://login.microsoftonline.com',
authorize_url: "https://login.microsoftonline.com/#{azure_tenant_id}/oauth2/v2.0/authorize",
token_url: "https://login.microsoftonline.com/#{azure_tenant_id}/oauth2/v2.0/token"
authorize_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/authorize',
token_url: 'https://login.microsoftonline.com/common/oauth2/v2.0/token'
})
end
@@ -19,8 +19,4 @@ module MicrosoftConcern
def base_url
ENV.fetch('FRONTEND_URL', 'http://localhost:3000')
end
def azure_tenant_id
MicrosoftGraphAuth.azure_tenant_id
end
end

View File

@@ -2,19 +2,8 @@ class Inboxes::FetchImapEmailInboxesJob < ApplicationJob
queue_as :scheduled_jobs
def perform
# check imap_enabled for channel
Inbox.where(channel_type: 'Channel::Email').all.find_each(batch_size: 100) do |inbox|
next unless inbox.channel.imap_enabled?
fetch_emails(inbox)
end
end
def fetch_emails(inbox)
if inbox.channel.microsoft? && ENV.fetch('AZURE_TENANT_ID', false)
::Inboxes::FetchMsGraphEmailForTenantJob.perform_later(inbox.channel)
else
::Inboxes::FetchImapEmailsJob.perform_later(inbox.channel)
::Inboxes::FetchImapEmailsJob.perform_later(inbox.channel) if inbox.channel.imap_enabled
end
end
end

View File

@@ -1,101 +0,0 @@
require 'net/http'
class Inboxes::FetchMsGraphEmailForTenantJob < ApplicationJob
queue_as :scheduled_jobs
def perform(channel)
process_email_for_channel(channel)
rescue EOFError => e
Rails.logger.error e
rescue StandardError => e
ChatwootExceptionTracker.new(e, account: channel.account).capture_exception
end
private
def should_fetch_email?(channel)
channel.imap_enabled? && channel.microsoft? && !channel.reauthorization_required?
end
def process_email_for_channel(channel)
# fetching email for microsoft provider
fetch_mail_for_channel(channel)
# clearing old failures like timeouts since the mail is now successfully processed
channel.reauthorized!
end
def fetch_mail_for_channel(channel)
return if channel.provider_config['access_token'].blank?
access_token = valid_access_token channel
return unless access_token
graph = graph_authenticate(access_token)
process_mails(graph, channel)
end
def process_mails(graph, channel)
response = graph.get_from_api('me/messages', {}, graph_query)
unless response.is_a?(Net::HTTPSuccess)
channel.authorization_error!
return false
end
json_response = JSON.parse(response.body)
json_response['value'].each do |message|
inbound_mail = Mail.read_from_string retrieve_mail_mime(graph, message['id'])
next if channel.inbox.messages.find_by(source_id: inbound_mail.message_id).present?
process_mail(inbound_mail, channel)
end
end
def retrieve_mail_mime(graph, id)
response = graph.get_from_api("me/messages/#{id}/$value")
return unless response.is_a?(Net::HTTPSuccess)
response.body
end
def graph_authenticate(access_token)
MicrosoftGraphApi.new(access_token)
end
def yesterday
(Time.zone.today - 1).strftime('%FT%TZ')
end
def tomorrow
(Time.zone.today + 1).strftime('%FT%TZ')
end
# Query to replicate the IMAP search used in Inboxes::FetchImapEmailsJob
# Selects the top 1000 records within the given filter, as that is the maximum
# page size for the API. Might need to look into paginating the requests later,
# for inboxes that receive more than 1000 emails a day?
#
# 1. https://learn.microsoft.com/en-us/graph/api/user-list-messages
# 2. https://learn.microsoft.com/en-us/graph/query-parameters
def graph_query
{
'$filter': "receivedDateTime ge #{yesterday} and receivedDateTime le #{tomorrow}",
'$top': '1000', '$select': 'id'
}
end
def process_mail(inbound_mail, channel)
Imap::ImapMailbox.new.process(inbound_mail, channel)
rescue StandardError => e
ChatwootExceptionTracker.new(e, account: channel.account).capture_exception
end
# Making sure the access token is valid for microsoft provider
def valid_access_token(channel)
Microsoft::RefreshOauthTokenService.new(channel: channel).access_token
end
end

View File

@@ -23,7 +23,6 @@ module ConversationReplyMailerHelper
def ms_smtp_settings
return unless @inbox.email? && @channel.imap_enabled && @inbox.channel.provider == 'microsoft'
return ms_graph_settings if ENV.fetch('AZURE_TENANT_ID', false)
smtp_settings = {
address: 'smtp.office365.com',
@@ -41,15 +40,6 @@ module ConversationReplyMailerHelper
@options[:delivery_method_options] = smtp_settings
end
def ms_graph_settings
graph_settings = {
token: @channel.provider_config['access_token']
}
@options[:delivery_method] = :microsoft_graph
@options[:delivery_method_options] = graph_settings
end
def set_delivery_method
return unless @inbox.inbox_type == 'Email' && @channel.smtp_enabled