Ruby & IMAP - 使用 Oauth 2.0 访问 Office 365



所以众所周知,MS禁用了IMAP进行基本身份验证。

我正试图弄清楚如何使用ruby(而不是rails上的ruby(使OAUTH2.0工作。我有Azure应用程序和所需的一切(我想(,但我找不到任何与ruby和获取访问令牌相关的代码。

第一步已经完成,但下一步是获取访问令牌。https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth

我需要阅读不同的Outlook邮箱。

有人能解释一下怎么做吗?

解决方案适合我!

我采取的步骤。

  1. 制作了一个Azure应用程序("设备流"对我来说是最简单的方法(查看链接中的步骤。如果你想使用IMAP,你还需要更改应用程序中的一些设置。在2:50-4:30之间查看youtube链接
  2. 从该链接获取邮递员请求(向下滚动一点((单击此处(
  3. 从邮递员那里你可以使用";CCD_ 1";请求
  4. Device Authorization Request开始(您需要一个scope和client_id(,我使用了https://outlook.office.com/IMAP.AccessAsUser.Allscope
  5. 转到您从请求中得到的链接,然后输入所需的代码
  6. 现在转到CCD_ 4;设备代码";从上一个请求开始,并将其放在code下,放在body下
  7. 你应该得到access_token

使用ruby连接

require 'gmail_xoauth' # MUST HAVE! otherwise XOAUTH2 auth wont work
require 'net/imap'
imap = Net::IMAP.new(HOST, PORT, true)
access_token = "XXXXX"
user_name = "email@outlook.com"
p imap.authenticate('XOAUTH2',"#{user_name}", "#{access_token}")
# example
imap.list('','*').each do |folders|
p folders
end

XOAUTH2返回

#<struct Net::IMAP::TaggedResponse tag="RUBY0001", name="OK", data=#<struct Net::IMAP::ResponseText code=nil, text="AUTHENTICATE completed.">, raw_data="RUBY0001 OK AUTHENTICATE completed.rn

仅用于指定

HOST = 'outlook.office365.com'
PORT = 993

更新25.01.2023

class Oauth2
require 'selenium-webdriver'
require 'webdrivers'
require 'net/http'
# Use: Oauth2.new.get_access_code
# Grants access to Office 365 emails.
def get_access_code
p "### Access Request Started #{Time.now} ###"
begin
codes = device_auth_request
authorize_device_code(codes[:user_code])
access_code = device_access_token(codes[:device_code])
access_code
rescue => e
p e
p "Something went wrong with authorizing"
end
end
def device_auth_request # Returns user_code and device_code
url = URI('https://login.microsoftonline.com/organizations/oauth2/v2.0/devicecode')
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request.body = "client_id=YOUR_CLIENT_ID&scope=%09https%3A%2F%2Foutlook.office.com%2FIMAP.AccessAsUser.All"
response = https.request(request)
{
user_code: JSON.parse(response.read_body)["user_code"],
device_code: JSON.parse(response.read_body)["device_code"]
}
end
def device_access_token(device_code)
url = URI('https://login.microsoftonline.com/organizations/oauth2/v2.0/token')
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request.body = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&code=#{device_code}&client_id=YOUR_CLIENT_ID"
response = https.request(request)
JSON.parse(response.read_body)["access_token"]
end
def authorize_device_code(device_code)
# SELENIUM SETUP
driver = setup_selenium
driver.get "https://microsoft.com/devicelogin"
sleep(4)
# ------------------------------------------
# Give Access
element = driver.find_element(:class, "form-control")
element.send_keys(device_code)
sleep(2)
element = driver.find_element(:id, "idSIButton9")
element.submit
sleep(2)
element = driver.find_element(:id, "i0116")
element.send_keys("YOUR OUTLOOK ACCOUNT EMAIL")
sleep(2)
element = driver.find_element(:class, "button_primary")
element.click
sleep(2)
element = driver.find_element(:id, "i0118")
element.send_keys("YOUR OUTLOOK PASSWORD")
element = driver.find_element(:class, "button_primary")
element.click
sleep(2)
element = driver.find_element(:class, "button_primary")
element.click
sleep(2)
# ------------------------------------------
driver.quit
end
def setup_selenium
require 'selenium-webdriver'
# set up Selenium
options = Selenium::WebDriver::Chrome::Options.new(
prefs: {
download: {
prompt_for_download: false
},
plugins: {
'always_open_pdf_externally' => true
}
}
)
options.add_argument('--headless')
options.add_argument('--no-sandbox')
# options.add_argument('-incognito')
options.add_argument('disable-popup-blocking')
Selenium::WebDriver.for :chrome, options: options
end
end

最新更新