Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Outlook integration toolkit #1

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions langchain/src/tools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ export {
formatToOpenAIFunction,
formatToOpenAITool,
} from "./convert_to_openai.js";
export { OutlookIntegration } from "./outlookIntegration.js";
94 changes: 94 additions & 0 deletions langchain/src/tools/outlookIntegration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Tool, type ToolParams } from "./base.js";
import fetch from 'node-fetch';

export interface Email {
sender: string;
subject: string;
// Add other properties as needed
}

export class OutlookIntegration extends Tool {
accessToken: string; // Store the OAuth2 access token

constructor(params: ToolParams, accessToken: string) {
super(params);
this.accessToken = accessToken; // Initialize with an OAuth2 access token
}
Comment on lines +10 to +16
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

category Functionality severity major

The OutlookIntegration class extends the Tool class but doesn't implement its required methods. To ensure proper functionality, please implement the 'name' and 'description' properties, and the 'call' method as required by the Tool class. This will prevent potential runtime errors and ensure the class behaves correctly within the LangChain framework.

Comment on lines +10 to +16
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

category Security severity major

Security Issue: Direct usage of access token

The code directly uses the access token obtained from the user to make API requests to the Microsoft Graph API. If this access token is leaked or exposed, it could allow unauthorized access to the user's Outlook data, compromising their privacy and security.

Actionable Feedback:
Instead of directly using the access token, consider implementing a server-side proxy that securely stores and manages the access tokens. The client-side code should make requests to your own server, which then makes the API requests to the Microsoft Graph API using the stored access token. This way, the access token is not exposed in the client-side code.


async readEmails(): Promise<Email[]> {
try {
const response = await fetch("https://graph.microsoft.com/v1.0/me/mailFolders('Inbox')/messages?$select=sender,subject", {
headers: {
Authorization: `Bearer ${this.accessToken}`,
},
});

if (!response.ok) {
throw new Error(`Error: ${response.status}`);
}
Comment on lines +26 to +28
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

category Error Handling severity major

When making requests to the Microsoft Graph API in the readEmails and sendEmail methods, the code is not handling potential API errors effectively. If the API returns an error response, the code throws a generic error without providing specific details about the API error. To improve this, consider checking the response status code and parsing the error response from the API. You can then throw a more specific error or create a custom error class that includes the relevant details from the API error response. This will provide more meaningful error messages to the caller of the method and help with debugging and error handling.


const data = await response.json();
return data.value; // Assuming 'value' contains the array of emails
} catch (error) {
console.error("Failed to read emails:", error);
throw error;
}
}
Comment on lines +18 to +36
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

category Functionality severity major

The readEmails method currently doesn't handle pagination, which may lead to incomplete data retrieval if there are more emails than the default page size. Consider implementing pagination to ensure all emails are fetched. You can do this by checking for an '@odata.nextLink' property in the response and making additional requests until all emails are retrieved.


async sendEmail(to: string, subject: string, content: string): Promise<void> {
const message = {
message: {
subject: subject,
body: {
contentType: "Text",
content: content,
},
toRecipients: [
{
emailAddress: {
address: to,
},
},
],
},
};

try {
const response = await fetch("https://graph.microsoft.com/v1.0/me/sendMail", {
method: "POST",
headers: {
Authorization: `Bearer ${this.accessToken}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(message),
});

if (!response.ok) {
throw new Error(`Error: ${response.status}`);
}
Comment on lines +66 to +68
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance error handling for sending emails.

Improve the error handling by parsing the response to provide more specific error messages. This will help in debugging issues related to sending emails.

- throw new Error(`Error: ${response.status}`);
+ const errorDetails = await response.json();
+ throw new Error(`Error sending email: ${response.status} - ${errorDetails.error.message}`);
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!response.ok) {
throw new Error(`Error: ${response.status}`);
}
if (!response.ok) {
const errorDetails = await response.json();
throw new Error(`Error sending email: ${response.status} - ${errorDetails.error.message}`);
}


console.log("Email sent successfully");
} catch (error) {
console.error("Failed to send email:", error);
throw error;
}
}

// You can add more methods for other features like managing contacts, calendar, etc.

}


// import fetch from "node-fetch";

// const accessToken = "YOUR_ACCESS_TOKEN";

// const response = await fetch("https://graph.microsoft.com/v1.0/me/messages", {
// headers: {
// Authorization: `Bearer ${accessToken}`,
// },
// });

// const data = await response.json();

// console.log(data);