Sử dụng Outlook Mail API với Ruby on Rails
Bài đăng này đã không được cập nhật trong 3 năm
Điều kiện tiến hành :
- Tài khoản Microsoft dùng để tạo App.
- Ruby on Rails với gem
oauth2
vàfaraday
.
App đóng vai trò nhận Auth code
, tokens
giữa Client và Office 365.
Để hiểu thêm bạn cần tham khảo OAuth2
.
Flow :
Để tạo App, bạn có thể tạo qua :
- Azure Active Directory ( Yêu cầu tài khoản Azure ) - mất phí nhưng sẽ có nhiều tùy chọn.
- Tạo App miễn phí thông qua Application Registration Portal với những tùy chọn cơ bản.
Nếu mới bắt đầu làm quen thì nên sử dụng Application Registration Portal. Trong bài viết này mình sẽ dùng Application Registration Portal và sẽ hướng dẫn dùng Azure Active Directory trong bài viết khác.
- Tại Application Registration Portal, bạn tạo một app mới, click vào Generate New Password để tạo Application Secrets, copy lại password vừa tạo cùng Application ID vào đâu đó để sử dụng sau này.
- Tại Platforms bạn chọn là Web, ở mục Redirect URIs, bạn điền URI chỉ định nơi sẽ nhận Auth code trả về từ Office 365.
Đến đây cơ bản là xong phần App, thứ bạn cần quan tâm giờ là Application Secrets và Application ID vừa tạo ta.
Tạo một class Auth với nội dung như sau
module OutlookMail
class Auth
CLIENT_ID = # Application ID
CLIENT_SECRET = # Application Secrets
SITE = "https://login.microsoftonline.com".freeze
AUTHORIZE_URL = "/common/oauth2/v2.0/authorize".freeze
TOKEN_URL = "/common/oauth2/v2.0/token".freeze
SCOPES = ["openid",
"https://outlook.office.com/Mail.ReadWrite",
"https://outlook.office.com/Mail.Send",
"offline_access"]
REFRESH_GRANT_TYPE = "refresh_token".freeze
class << self
def get_login_url redirect_uri
auth_client.auth_code.authorize_url redirect_uri: redirect_uri, scope: SCOPES.join(" ")
end
def get_token_from_code auth_code, redirect_uri
auth_client.auth_code.get_token auth_code, redirect_uri: redirect_uri,
scope: SCOPES.join(" ")
end
def reset_token refresh_token
conn = Faraday.new(url: SITE) do |faraday|
faraday.response :logger
faraday.adapter Faraday.default_adapter
end
response = conn.post do |request|
request.url TOKEN_URL
request.headers["Content-Type"] = "application/x-www-form-urlencoded"
request.body = "grant_type=#{REFRESH_GRANT_TYPE}&
refresh_token=#{refresh_token}&
client_id=#{CLIENT_ID}&
client_secret=#{CLIENT_SECRET}"
end
JSON.parse response.body
end
private
def auth_client
OAuth2::Client.new CLIENT_ID, CLIENT_SECRET, site: SITE,
authorize_url: AUTHORIZE_URL, token_url: TOKEN_URL,
raise_errors: false
end
end
end
end
- Hàm
get_login_url
sẽ tạo cho bạn một đường link để request Auth code từ Office 365 dựa trên Application ID và Application Secrets của bạn. - Hàm
get_token_from_code
sẽ hỗ trợ lấy Access Token và Refresh Token từ Auth code nhận được. - Hàm
reset_token
sẽ sử dụng Refresh Token giúp ta lấy được một cặp Access Token và Refresh Token mới khi Access Token hết hạn.
Về cơ bản Access Token sẽ dùng mỗi khi bạn gửi request và Refresh Token sẽ hỗ trợ khi Access Token hết hạn.
Để gửi request lên Office 365, ta sẽ sử dụng Faraday
.
Khởi tạo :
def create_connect token
connect = Faraday.new url: RESOURCE do |faraday|
faraday.use CatchErrors
faraday.adapter Faraday.default_adapter
faraday.response :logger if LOG_REQUEST
faraday.request :url_encoded if URL_ENCODE
end
connect.headers = {
"Authorization" => "Bearer #{token}",
"Accept" => "application/json"
}
connect
end
Gửi một request :
def send_request url, params: nil
conn.get do |request|
request.url url, params
end
end
url
phụ thuộc vào đối tượng bạn muốn request, ví dụ để nhận danh sách tất cả email trong thư mục Inbox, ta sẽ có :
url = "https://outlook.office.com/api/v1.0/me/folders/inbox/messages"
Để biết thêm, hãy tham khảo Outlook Mail REST API reference.params
sử dụng khi bạn muốn gửi email hoặc tác vụ liên quan tới việc gửi dữ liệu lên Office 365.
Ví dụ một reponse nhận về
{
"@odata.context": "https://outlook.office365.com/api/v1.0/$metadata#Me/Folders('Inbox')/Messages",
"value": [
{
"@odata.id": "https://outlook.office365.com/api/v1.0/Users('demo39@a830edad9050849NDA1.onmicrosoft.com')/Messages('AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwBGAAADgR2nxNsv-kiMfj8LSgE8AQcA1jE7wJ_C3EqpppAp3Qe15gAAAgEMAAAA1jE7wJ_C3EqpppAp3Qe15gAAAgVTAAAA')",
"@odata.etag": "W/\"CQAAABYAAADWMTvAn4LcSqmmkCndB7XmAAAAAAbw\"",
"Id": "AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwBGAAADgR2nxNsv-kiMfj8LSgE8AQcA1jE7wJ_C3EqpppAp3Qe15gAAAgEMAAAA1jE7wJ_C3EqpppAp3Qe15gAAAgVTAAAA",
"ChangeKey": "CQAAABYAAADWMTvAn4LcSqmmkCndB7XmAAAAAAbw",
"Categories": [],
"DateTimeCreated": "2014-10-20T00:50:44Z",
"DateTimeLastModified": "2014-10-20T00:50:44Z",
"HasAttachments": false,
"Subject": "Event tomorrow - atrium closed",
"Body": {
"ContentType": "Text",
"Content": "Remember that the atrium will be closed tomorrow for the event."
},
"BodyPreview": "Remember that the atrium will be closed tomorrow for the event.",
"Importance": "Normal",
"ParentFolderId": "AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwAuAAADgR2nxNsv-kiMfj8LSgE8AQEAANYxO8CfgtxKqaaQKd0HteYAAAIBDAAAAA==",
"Sender": {
"EmailAddress": {
"Address": "katiej@a830edad9050849NDA1.onmicrosoft.com",
"Name": "Katie Jordan"
}
},
"From": {
"EmailAddress": {
"Address": "katiej@a830edad9050849NDA1.onmicrosoft.com",
"Name": "Katie Jordan"
}
},
"ToRecipients": [
{
"EmailAddress": {
"Address": "garthf@a830edad9050849NDA1.onmicrosoft.com",
"Name": "Garth Fort"
}
}
],
"CcRecipients": [],
"BccRecipients": [],
"ReplyTo": [],
"ConversationId": "AAQkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwAQACORL5p-BgdIvS98rIc4ZYQ=",
"IsDeliveryReceiptRequested": false,
"IsReadReceiptRequested": false,
"IsRead": false,
"IsDraft": false,
"DateTimeReceived": "2014-10-20T00:50:44Z",
"DateTimeSent": "2014-10-20T00:50:39Z",
"WebLink": "https://outlook.office365.com/owa/?ItemID=AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwBGAAADgR2nxNsv%2FkiMfj8LSgE8AQcA1jE7wJ%2BC3EqpppAp3Qe15gAAAgEMAAAA1jE7wJ%2BC3EqpppAp3Qe15gAAAgVTAAAA&exvsurl=1&viewmodel=ReadMessageItem"
},
{
"@odata.id": "https://outlook.office365.com/api/v1.0/Users('demo39@a830edad9050849NDA1.onmicrosoft.com')/Messages('AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwBGAAADgR2nxNsv-kiMfj8LSgE8AQcA1jE7wJ_C3EqpppAp3Qe15gAAAgEMAAAA1jE7wJ_C3EqpppAp3Qe15gAAAgVSAAAA')",
"@odata.etag": "W/\"CQAAABYAAADWMTvAn4LcSqmmkCndB7XmAAAAAAbv\"",
"Id": "AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwBGAAADgR2nxNsv-kiMfj8LSgE8AQcA1jE7wJ_C3EqpppAp3Qe15gAAAgEMAAAA1jE7wJ_C3EqpppAp3Qe15gAAAgVSAAAA",
"ChangeKey": "CQAAABYAAADWMTvAn4LcSqmmkCndB7XmAAAAAAbv",
"Categories": [],
"DateTimeCreated": "2014-10-20T00:36:29Z",
"DateTimeLastModified": "2014-10-20T00:36:29Z",
"HasAttachments": true,
"Subject": "Re: Meeting Notes",
"Body": {
"ContentType": "Text",
"Content": "\n________________________________________\nFrom: Alex D\nSent: Sunday, October 19, 2014 5:32 PM\nTo: Katie Jordan\nSubject: Meeting Notes\n\nPlease send me the meeting notes ASAP\n"
},
"BodyPreview": "________________________________________\nFrom: Alex D\nSent: Sunday, October 19, 2014 5:32 PM\nTo: Katie Jordan\nSubject: Meeting Notes\n\nPlease send me the meeting notes ASAP",
"Importance": "Normal",
"ParentFolderId": "AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwAuAAADgR2nxNsv-kiMfj8LSgE8AQEAANYxO8CfgtxKqaaQKd0HteYAAAIBDAAAAA==",
"Sender": {
"EmailAddress": {
"Address": "katiej@a830edad9050849NDA1.onmicrosoft.com",
"Name": "Katie Jordan"
}
},
"From": {
"EmailAddress": {
"Address": "katiej@a830edad9050849NDA1.onmicrosoft.com",
"Name": "Katie Jordan"
}
},
"ToRecipients": [
{
"EmailAddress": {
"Address": "demo39@a830edad9050849NDA1.onmicrosoft.com",
"Name": "Alex D"
}
}
],
"CcRecipients": [],
"BccRecipients": [],
"ReplyTo": [],
"ConversationId": "AAQkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwAQAJ6mQ1AJ6CVGnVVfBZfx47U=",
"IsDeliveryReceiptRequested": false,
"IsReadReceiptRequested": false,
"IsRead": false,
"IsDraft": false,
"DateTimeReceived": "2014-10-20T00:36:29Z",
"DateTimeSent": "2014-10-20T00:36:25Z",
"WebLink": "https://outlook.office365.com/owa/?ItemID=AQMkADQyMzRkYTE3LWI0M2MtNDc0My1iNDA1LWMzZDE3OTZmNGQxYwBGAAADgR2nxNsv%2FkiMfj8LSgE8AQcA1jE7wJ%2BC3EqpppAp3Qe15gAAAgEMAAAA1jE7wJ%2BC3EqpppAp3Qe15gAAAgVSAAAA&exvsurl=1&viewmodel=ReadMessageItem"
}
]
}
Reponse chứa khá đầy đủ các thông tin về email cũng như Web link, hỗ trợ ta tạo Mail Client đầy đủ mạnh mẽ không thua kém Web Mail.
Đến đây chắc các bạn cũng hiểu cơ bản cơ chế hoạt động cũng như cách thức tương tác với Outlook Mail REST API, với Outlook contacts, Outlook calendar, Files ... cũng sẽ tương tự, bạn có thể tham khảo tài liệu ở Office 365 API reference.
Nguồn tham khảo:
All rights reserved