Setu Recipes: reusable workflows across every app.Browse templates

Integrations / Outlook

Outlook

Read, search, draft and send email in Outlook and Microsoft 365 mail through Microsoft Graph.

9 actions OAuth 2 5 read4 write Calls graph.microsoft.com

Connect

TypeScript
const conn = await setu.connections.initiate({ userId: "user_1", toolkit: "outlook" });
console.log(conn.connectUrl); // show this to your user
await conn.waitUntilActive();

Permissions requested

ScopeWhy it is requested
Mail.ReadRead your email so an assistant can find and summarise messages
Mail.ReadWriteCreate and edit drafts in your mailbox
Mail.SendSend email on your behalf
User.ReadIdentify which Microsoft account you connected
offline_accessStay connected without asking you to sign in again

Actions

Create draftwriteoutlook.create_draftSave a new email as a draft without sending it. Safe way to let an AI prepare a message for the user to review and send.

Needs scope: Mail.ReadWrite

InputTypeDescription
subjectstringRequiredSubject line
bodystringRequiredMessage body
body_typestringRequiredWhether body is plain text or HTML
to_recipientsarray of objectRequiredRecipients, each as {emailAddress:{address}}
cc_recipientsarray of objectOptionalOptional cc recipients
importancestringOptionalOptional importance
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.create_draft",
  input: {
    "subject": "<subject>",
    "body": "<body>",
    "body_type": "<body_type>",
    "to_recipients": []
  },
});
Create reply draftwriteoutlook.create_reply_draftCreate a draft reply to the sender of an existing message, optionally with a comment as the reply text. The draft is not sent; use send_draft after review.

Needs scope: Mail.ReadWrite

InputTypeDescription
message_idstringRequiredID of the message to reply to
commentstringOptionalReply text placed above the quoted original
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.create_reply_draft",
  input: {
    "message_id": "<message_id>"
  },
});
Get messagereadoutlook.get_messageRead one message in full: sender, recipients, subject and the body as plain text.

Needs scope: Mail.Read

InputTypeDescription
message_idstringRequiredMessage ID from list_messages or search_messages
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.get_message",
  input: {
    "message_id": "<message_id>"
  },
});
List messages in a folderreadoutlook.list_folder_messagesList messages in one mail folder, for example the inbox, drafts or sent items, using a folder ID or a well-known name.

Needs scope: Mail.Read

InputTypeDescription
folder_idstringRequiredFolder ID from list_mail_folders, or a well-known name: inbox, drafts, sentitems, deleteditems, archive, junkemail
topintegerOptionalNumber of messages to return (1 to 50 is sensible; default 10)
filterstringOptionalOptional OData $filter, for example: isRead eq false
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.list_folder_messages",
  input: {
    "folder_id": "<folder_id>"
  },
});
List mail foldersreadoutlook.list_mail_foldersList the top-level mail folders with their IDs and unread counts. Use a folder ID with list_folder_messages.

Needs scope: Mail.Read

InputTypeDescription
topintegerOptionalMaximum number of folders to return (default 10)
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.list_mail_folders",
  input: {},
});
List messagesreadoutlook.list_messagesList recent messages across the whole mailbox (newest first by default), with sender, subject, preview and read state. Optionally filter with an OData $filter such as isRead eq false.

Needs scope: Mail.Read

InputTypeDescription
topintegerOptionalNumber of messages to return (1 to 50 is sensible; default 10)
filterstringOptionalOptional OData $filter, for example: isRead eq false
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.list_messages",
  input: {},
});
Search messagesreadoutlook.search_messagesSearch the mailbox by keyword across sender, subject and body (Microsoft search syntax, for example: pizza or from:adele). Results are sorted by sent date.

Needs scope: Mail.Read

InputTypeDescription
querystringRequiredSearch text, for example: invoice or from:adele
topintegerOptionalNumber of messages to return (1 to 50 is sensible; default 10)
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.search_messages",
  input: {
    "query": "<query>"
  },
});
Send draftwriteoutlook.send_draftSend an existing draft message (a new draft or a reply draft) to its recipients. This cannot be undone once delivered.

Needs scope: Mail.Send

InputTypeDescription
message_idstringRequiredID of the draft from create_draft or create_reply_draft
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.send_draft",
  input: {
    "message_id": "<message_id>"
  },
});
Send emailwriteoutlook.send_mailSend a new email from the connected Outlook account immediately. It is saved in Sent Items unless disabled. Use create_draft instead to prepare a message for review.

Needs scope: Mail.Send

InputTypeDescription
subjectstringRequiredSubject line
bodystringRequiredMessage body
body_typestringRequiredWhether body is plain text or HTML
to_recipientsarray of objectRequiredRecipients, each as {emailAddress:{address}}
cc_recipientsarray of objectOptionalOptional cc recipients
bcc_recipientsarray of objectOptionalOptional bcc recipients
save_to_sent_itemsbooleanOptionalSet false to skip saving a copy in Sent Items (default true)
TypeScript
await setu.execute({
  userId: "user_1",
  action: "outlook.send_mail",
  input: {
    "subject": "<subject>",
    "body": "<body>",
    "body_type": "<body_type>",
    "to_recipients": []
  },
});