Skip to main content
Glama

get_sent_emails

Retrieve a list of sent emails from your Outlook account to review correspondence or track communications.

Instructions

Get sent emails list

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
countNoNumber of sent emails to retrieve

Implementation Reference

  • Core implementation of getSentEmails: Executes PowerShell script to retrieve emails from Outlook Sent Items folder (olFolderSentMail=5), sorts by SentOn, fetches properties like Id, Subject, Sender, Body preview, etc., returns cleaned EmailMessage[]
    async getSentEmails(count = 10) {
        const script = `
      function Clean-Text {
        param([string]$text)
        if (-not $text) { return "" }
        
        # Simple cleaning - remove control characters and normalize whitespace
        $text = $text -replace '[\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]', ''
        $text = $text -replace '\\r\\n', ' '
        $text = $text -replace '\\n', ' '
        $text = $text -replace '\\r', ' '
        $text = $text -replace '\\t', ' '
        $text = $text -replace '\\s+', ' '
        return $text.Trim()
      }
    
      try {
        Add-Type -AssemblyName "Microsoft.Office.Interop.Outlook" -ErrorAction Stop
        $outlook = New-Object -ComObject Outlook.Application -ErrorAction Stop
        $namespace = $outlook.GetNamespace("MAPI")
        $sentItems = $namespace.GetDefaultFolder(5)  # 5 = Sent Items folder
        
        $itemCount = $sentItems.Items.Count
        if ($itemCount -eq 0) {
          Write-Output "[]"
          exit 0
        }
        
        $items = $sentItems.Items
        $items.Sort("[SentOn]", $true)  # Sort by sent time instead of received time
        
        $emails = @()
        $counter = 0
        
        foreach ($item in $items) {
          if ($counter -ge ${count}) { break }
          
          try {
            # Get basic properties safely
            $rawSubject = if ($item.Subject) { $item.Subject.ToString() } else { "No Subject" }
            $rawSender = if ($item.SenderEmailAddress) { $item.SenderEmailAddress.ToString() } else { "Unknown" }
            $rawBody = if ($item.Body) { 
              $bodyStr = $item.Body.ToString()
              if ($bodyStr.Length -gt 150) { 
                $bodyStr.Substring(0, 150) + "..." 
              } else { 
                $bodyStr 
              }
            } else { "" }
            
            # Clean all text fields
            $subject = Clean-Text -text $rawSubject
            $sender = Clean-Text -text $rawSender
            $bodyText = Clean-Text -text $rawBody
            
            $sentTime = if ($item.SentOn) { 
              $item.SentOn.ToString("yyyy-MM-dd HH:mm:ss") 
            } else { 
              (Get-Date).ToString("yyyy-MM-dd HH:mm:ss") 
            }
            
            # Create simple email object
            $email = [PSCustomObject]@{
              Id = if ($item.EntryID) { $item.EntryID.ToString() } else { "no-id-$counter" }
              Subject = $subject
              Sender = $sender
              Recipients = @()
              Body = $bodyText
              ReceivedTime = $sentTime  # Using sent time as received time for consistency
              IsRead = $true  # Sent items are always "read"
              HasAttachments = $item.Attachments.Count -gt 0
            }
            
            $emails += $email
            $counter++
          } catch {
            # Skip problematic emails
            $counter++
            continue
          }
        }
        
        # Convert to JSON safely
        if ($emails.Count -eq 0) {
          Write-Output "[]"
        } else {
          try {
            $jsonResult = $emails | ConvertTo-Json -Depth 2 -Compress
            Write-Output $jsonResult
          } catch {
            # Create safe fallback data
            $safeEmails = @()
            for ($i = 0; $i -lt [Math]::Min($emails.Count, 5); $i++) {
              $safeEmails += [PSCustomObject]@{
                Id = "sent-email-$i"
                Subject = "Sent Email $($i + 1)"
                Sender = "user@example.com"
                Recipients = @()
                Body = "Sent email content available"
                ReceivedTime = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
                IsRead = $true
                HasAttachments = $false
              }
            }
            $fallbackJson = $safeEmails | ConvertTo-Json -Depth 2 -Compress
            Write-Output $fallbackJson
          }
        }
      } catch {
        $errorResult = [PSCustomObject]@{
          error = $_.Exception.Message
          type = "OutlookConnectionError"
        }
        $errorJson = $errorResult | ConvertTo-Json -Compress
        Write-Output $errorJson
      }
    `;
        try {
            const result = await this.executePowerShell(script);
            if (!result || result.trim() === '') {
                return [];
            }
            // Clean result before parsing
            const cleanResult = result
                .replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, '')
                .trim();
            const parsed = JSON.parse(cleanResult);
            if (parsed.error) {
                throw new Error(`Outlook Error: ${parsed.error}`);
            }
            const emailArray = Array.isArray(parsed) ? parsed : [parsed];
            return emailArray.map((item) => ({
                id: this.cleanText(item.Id || ''),
                subject: this.cleanText(item.Subject || 'No Subject'),
                sender: this.cleanText(item.Sender || 'Unknown'),
                recipients: [],
                body: this.cleanText(item.Body || ''),
                receivedTime: new Date(item.ReceivedTime),
                isRead: Boolean(item.IsRead),
                hasAttachments: Boolean(item.HasAttachments)
            }));
        }
        catch (error) {
            if (error instanceof SyntaxError) {
                console.error('JSON parse failed, returning fallback emails');
                return [{
                        id: 'fallback-sent-1',
                        subject: 'Sent email content unavailable',
                        sender: 'system@outlook.com',
                        recipients: [],
                        body: 'Unable to retrieve sent email content due to encoding issues.',
                        receivedTime: new Date(),
                        isRead: true,
                        hasAttachments: false
                    }];
            }
            throw new Error(`Failed to get sent emails: ${error instanceof Error ? error.message : String(error)}`);
        }
    }
  • src/index.js:160-173 (registration)
    Tool registration in ListToolsRequestHandler: defines name, description, and input schema for get_sent_emails tool (optional count parameter)
    {
        name: "get_sent_emails",
        description: "获取已发送邮件列表",
        inputSchema: {
            type: "object",
            properties: {
                count: {
                    type: "number",
                    description: "要获取的已发送邮件数量",
                    default: 10
                }
            }
        }
    },
  • MCP CallToolRequestHandler case for get_sent_emails: calls outlookManager.getSentEmails(count), formats and returns rich text response with email list
    case 'get_sent_emails': {
        const count = args?.count || 10;
        const emails = await outlookManager.getSentEmails(count);
        return {
            content: [
                {
                    type: 'text',
                    text: `📊 **邮件总览**\n总计: ${emails.length} 封邮件\n未读: ${emails.filter(e => !e.isRead).length} 封\n\n📋 **邮件列表:**\n` +
                        emails.map((email, index) => `${index + 1}. ${email.isRead ? '✅' : '📩'} **${email.subject}**\n   发件人: ${email.sender}\n   时间: ${email.receivedTime}\n   预览: ${email.body?.substring(0, 100)}...\n`).join('\n')
                },
            ],
        };
    }
  • TypeScript version of getSentEmails handler: delegates to shared getEmailsFromFolder for Sent Items folder
    async getSentEmails(count: number = 10): Promise<EmailMessage[]> {
      return this.getEmailsFromFolder(5, count, "[SentOn]"); // 5 = Sent Items
    }
  • src/index.ts:171-182 (registration)
    TypeScript registration of get_sent_emails tool with English description and input schema
    name: "get_sent_emails",
    description: "Get sent emails list",
    inputSchema: {
      type: "object",
      properties: {
        count: {
          type: "number",
          description: "Number of sent emails to retrieve",
          default: 10
        }
      }
    }
Behavior2/5

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

No annotations are provided, so the description carries full burden but discloses minimal behavioral traits. It implies a read operation but doesn't specify permissions needed, rate limits, pagination, sorting order, or what data is returned (e.g., subject, sender, date). For a tool with no annotation coverage, this leaves critical behavioral aspects undocumented.

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 at three words, with zero wasted language. It's front-loaded with the core action and resource. For a simple tool, this brevity is appropriate, though it may sacrifice completeness.

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 no annotations, no output schema, and a simple but underexplained tool, the description is incomplete. It doesn't address return values, error conditions, or how it differs from similar tools like 'search_sent_emails'. For a tool in a context with many siblings, more guidance is needed to ensure correct usage.

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 single parameter 'count' well-documented in the schema. The description adds no parameter semantics beyond what the schema provides, but with high coverage, the baseline is 3. No additional context about parameter usage or constraints is given.

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

Purpose3/5

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

The description 'Get sent emails list' states the basic action (get) and resource (sent emails list), but is vague about scope and format. It doesn't differentiate from sibling tools like 'search_sent_emails' or 'get_inbox_emails' beyond the obvious 'sent' focus. The purpose is understandable but lacks specificity about what constitutes the 'list' (e.g., metadata vs. full content).

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?

No guidance is provided on when to use this tool versus alternatives. With sibling tools like 'search_sent_emails' available, the description doesn't explain if this is for simple retrieval versus filtered searching, or when to prefer one over the other. There's no mention of prerequisites, context, or exclusions.

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