Skip to main content
Glama

get_email_by_id

Retrieve a specific email from Microsoft Outlook using its unique identifier to access message details directly.

Instructions

Get specific email by ID

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
idYesEmail ID

Implementation Reference

  • Tool schema definition for get_email_by_id including name, description, and input schema requiring 'id' string
    {
      name: "get_email_by_id", 
      description: "Get specific email by ID",
      inputSchema: {
        type: "object",
        properties: {
          id: {
            type: "string",
            description: "Email ID"
          }
        },
        required: ["id"]
      }
    },
  • MCP server callTool handler: extracts 'id' from args, calls outlookManager.getEmailById, returns the email as formatted JSON text content
    case 'get_email_by_id': {
      const id = (args as any)?.id;
      if (!id) {
        throw new Error('Email ID is required');
      }
      const email = await outlookManager.getEmailById(id);
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(email, null, 2),
          },
        ],
      };
    }
  • OutlookManager.getEmailById helper method: Uses PowerShell COM interop with Outlook.Application to fetch email by EntryID, extracts properties (subject, sender, body, recipients, etc.), handles fallbacks and parsing errors.
    async getEmailById(id: string): Promise<EmailMessage> {
      const script = `
        try {
          Add-Type -AssemblyName "Microsoft.Office.Interop.Outlook" -ErrorAction Stop
          $outlook = New-Object -ComObject Outlook.Application -ErrorAction Stop
          $namespace = $outlook.GetNamespace("MAPI")
          
          # Try GetItemFromID first (fastest method)
          $item = $null
          try {
            $item = $namespace.GetItemFromID("${id.replace(/"/g, '""')}")
          } catch {
            # Fallback: search through folders
            foreach ($folderNum in @(6, 5, 16)) {
              $folder = $namespace.GetDefaultFolder($folderNum)
              foreach ($email in $folder.Items) {
                if ($email.EntryID -eq "${id.replace(/"/g, '""')}") {
                  $item = $email
                  break
                }
              }
              if ($item) { break }
            }
          }
          
          if (-not $item) { throw "Email not found" }
          
          # Extract data
          $subject = if ($item.Subject) { $item.Subject } else { "No Subject" }
          $sender = if ($item.SenderEmailAddress) { $item.SenderEmailAddress } else { "Unknown" }
          $body = if ($item.Body) { $item.Body } else { "" }
          $recipients = @()
          if ($item.Recipients) {
            foreach ($r in $item.Recipients) {
              $addr = if ($r.Address) { $r.Address } else { $r.Name }
              if ($addr) { $recipients += $addr }
            }
          }
          $timestamp = if ($item.SentOn) { $item.SentOn.ToString("yyyy-MM-dd HH:mm:ss") } 
                       elseif ($item.ReceivedTime) { $item.ReceivedTime.ToString("yyyy-MM-dd HH:mm:ss") } 
                       else { (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") }
          
          Write-Output ([PSCustomObject]@{
            Id = "${id.replace(/"/g, '""')}"
            Subject = $subject
            Sender = $sender
            Recipients = $recipients
            Body = $body
            ReceivedTime = $timestamp
            IsRead = -not $item.UnRead
            HasAttachments = $item.Attachments.Count -gt 0
            Success = $true
          } | ConvertTo-Json -Depth 3 -Compress)
          
        } catch {
          Write-Output ([PSCustomObject]@{
            Id = "${id.replace(/"/g, '""')}"
            Subject = "Email not found"
            Sender = "system"
            Recipients = @()
            Body = "Error: $($_.Exception.Message)"
            ReceivedTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
            IsRead = $true
            HasAttachments = $false
            Success = $false
          } | ConvertTo-Json -Depth 3 -Compress)
        }
      `;
    
      try {
        const result = await this.executePowerShell(script);
        const cleanResult = result.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, '').trim();
        const emailData = JSON.parse(cleanResult);
        
        return {
          id: emailData.Id || id,
          subject: this.cleanText(emailData.Subject || 'No Subject'),
          sender: this.cleanText(emailData.Sender || 'Unknown Sender'),
          recipients: Array.isArray(emailData.Recipients) ? emailData.Recipients.map((r: any) => this.cleanText(r)) : [],
          body: emailData.Body || '',
          receivedTime: new Date(emailData.ReceivedTime || new Date()),
          isRead: Boolean(emailData.IsRead),
          hasAttachments: Boolean(emailData.HasAttachments)
        };
        
      } catch (error) {
        return {
          id: id,
          subject: 'Email parsing failed',
          sender: 'system',
          recipients: [],
          body: `Failed to parse email: ${error instanceof Error ? error.message : String(error)}`,
          receivedTime: new Date(),
          isRead: true,
          hasAttachments: false
        };
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure but offers minimal insight. It implies a read-only operation ('Get') but doesn't specify permissions required, rate limits, error handling (e.g., for invalid IDs), or output format. For a tool with zero annotation coverage, this is inadequate, though not contradictory.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with a single sentence ('Get specific email by ID'), which is front-loaded and wastes no words. Every part of the sentence contributes directly to the tool's purpose, making it efficient and easy to parse, though this conciseness comes at the cost of detail in other dimensions.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (one parameter, no nested objects) but lack of annotations and output schema, the description is incomplete. It doesn't address behavioral aspects like what data is returned or error conditions, leaving gaps for the agent. For a read operation with no structured output guidance, more context is needed to be fully helpful.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with the parameter 'id' documented as 'Email ID'. The description adds no additional meaning beyond this, such as format examples (e.g., UUID) or sourcing hints. Since the schema fully describes the single parameter, the baseline score of 3 is appropriate, as the description doesn't compensate but doesn't detract either.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Get' and resource 'specific email by ID', making the purpose unambiguous. It distinguishes from sibling tools like get_inbox_emails or get_sent_emails by specifying retrieval of a single email via ID. However, it doesn't explicitly mention what 'get' entails (e.g., fetch metadata, content, or both), which prevents a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., needing a valid email ID), contrast with search tools (e.g., search_inbox_emails), or specify use cases like retrieving a known email versus browsing. This lack of context leaves the agent without clear usage direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cqyefeng119/windows-outlook-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server