Mirra
BuildEvents

Gmail Events

Gmail events fire when emails are received or sent through your connected Gmail account. These events provide complete email details including sender, recipients, subject, body, attachments, and labels, with support for automatic content enrichment.


Event Types

gmail.email_received

The gmail.email_received event fires when an email is received in your Gmail inbox. This event provides complete email details including sender, recipients, subject, body, and attachments.

Event Type:

type: 'gmail.email_received'
source: 'google-gmail'

Fields:

content.text (string)

Email body content as plain text.

content.contentType (ContentType)

Always 'email' for Gmail messages.

actor.id (string)

Sender's email address.

actor.name (string)

Sender's display name or email if no name available.

context.channelId (string)

Gmail thread ID.

context.channelType (ChannelType)

Always 'email_thread'.

gmail.messageId (string)

Unique Gmail message ID. Use this for operations like adding labels or replying.

gmail.threadId (string)

Gmail conversation thread ID. All emails in a conversation share the same thread ID.

gmail.subject (string)

Email subject line. Empty string if no subject.

gmail.from (EmailAddress)

Sender email address with optional display name.

FieldTypeDescription
from.emailstringSender's email address
from.namestring | nullSender's display name
gmail.to (EmailAddress[])

Array of primary recipients. Empty array if none.

gmail.cc (EmailAddress[])

Array of CC recipients. Empty array if none.

gmail.bcc (EmailAddress[])

Array of BCC recipients. Empty array if none (usually unavailable).

gmail.date (Date)

When the email was sent.

gmail.hasAttachments (boolean)

True if the email has file attachments.

gmail.labels (string[])

Array of Gmail labels applied to this message (e.g., ["INBOX", "IMPORTANT", "UNREAD"]).

gmail.isUnread (boolean)

True if the email is unread.

enrichment (EventEnrichment | null)

Content enrichment including detected tickers, companies, and sentiment. Null until processing completes.

Example - Auto-Label Important Emails:

export async function handler(event, context) {
  const subject = event.gmail.subject.toLowerCase();
  const from = event.gmail.from.email;
  
  // Label urgent emails
  if (subject.includes('urgent') || subject.includes('asap')) {
    await mirra.gmail.addLabel({
      messageId: event.gmail.messageId,
      label: 'Urgent'
    });
  }
  
  // Label emails from VIPs
  const vips = ['boss@company.com', 'client@important.com'];
  if (vips.includes(from)) {
    await mirra.gmail.addLabel({
      messageId: event.gmail.messageId,
      label: 'VIP'
    });
  }
  
  return { success: true };
}

Example - Email Digest to Telegram:

export async function handler(event, context) {
  // Send email notification to Telegram
  const message = `
📧 New Email
 
From: ${event.gmail.from.name || event.gmail.from.email}
Subject: ${event.gmail.subject}
 
${event.content.text.substring(0, 200)}...
 
${event.gmail.hasAttachments ? '📎 Has attachments' : ''}
  `.trim();
  
  await mirra.telegram.sendMessage({
    chatId: 'your-chat-id',
    text: message
  });
  
  return { success: true };
}

Example - Invoice Tracker:

export async function handler(event, context) {
  // Only process emails with "invoice" in subject
  if (!event.gmail.subject.toLowerCase().includes('invoice')) {
    return { success: true, skipped: true };
  }
  
  // Log to spreadsheet
  await mirra.google.sheets.appendRow({
    spreadsheetId: 'your-sheet-id',
    sheetName: 'Invoices',
    values: [
      event.gmail.date.toISOString(),
      event.gmail.from.email,
      event.gmail.subject,
      event.gmail.hasAttachments ? 'Yes' : 'No',
      event.gmail.labels.join(', ')
    ]
  });
  
  // Add invoice label
  await mirra.gmail.addLabel({
    messageId: event.gmail.messageId,
    label: 'Invoices'
  });
  
  return { success: true };
}

Subscription Examples:

// All emails
{
  "eventType": "gmail.email_received"
}
 
// Only unread emails
{
  "eventType": "gmail.email_received",
  "conditions": [
    {
      "field": "gmail.isUnread",
      "operator": "equals",
      "value": true
    }
  ]
}
 
// Emails with attachments
{
  "eventType": "gmail.email_received",
  "conditions": [
    {
      "field": "gmail.hasAttachments",
      "operator": "equals",
      "value": true
    }
  ]
}
 
// Emails from specific sender
{
  "eventType": "gmail.email_received",
  "conditions": [
    {
      "field": "gmail.from.email",
      "operator": "equals",
      "value": "important@sender.com"
    }
  ]
}
 
// Emails with keywords in subject
{
  "eventType": "gmail.email_received",
  "conditions": [
    {
      "operator": "or",
      "conditions": [
        {
          "field": "gmail.subject",
          "operator": "contains",
          "value": "invoice"
        },
        {
          "field": "gmail.subject",
          "operator": "contains",
          "value": "receipt"
        }
      ]
    }
  ]
}
 
// VIP emails
{
  "eventType": "gmail.email_received",
  "conditions": [
    {
      "field": "gmail.from.email",
      "operator": "in",
      "value": ["boss@company.com", "client@important.com"]
    }
  ]
}

Common Use Cases

Email to Task Converter

export async function handler(event, context) {
  // Convert emails with [TASK] in subject to assignments
  if (!event.gmail.subject.includes('[TASK]')) {
    return { success: true, skipped: true };
  }
  
  // Extract task details from subject
  const taskTitle = event.gmail.subject.replace('[TASK]', '').trim();
  
  // Create assignment
  await mirra.assignments.create({
    title: taskTitle,
    description: event.content.text.substring(0, 500),
    source: 'email',
    metadata: {
      emailId: event.gmail.messageId,
      from: event.gmail.from.email,
      receivedAt: event.gmail.date
    }
  });
  
  // Archive the email
  await mirra.gmail.archive({
    messageId: event.gmail.messageId
  });
  
  // Add task label
  await mirra.gmail.addLabel({
    messageId: event.gmail.messageId,
    label: 'Tasks'
  });
  
  return { success: true };
}

Newsletter Organizer

export async function handler(event, context) {
  // Detect newsletters by unsubscribe link
  const hasUnsubscribe = event.content.text.toLowerCase().includes('unsubscribe');
  
  if (!hasUnsubscribe) {
    return { success: true, skipped: true };
  }
  
  // Auto-label as newsletter
  await mirra.gmail.addLabel({
    messageId: event.gmail.messageId,
    label: 'Newsletters'
  });
  
  // Mark as read
  await mirra.gmail.markAsRead({
    messageId: event.gmail.messageId
  });
  
  // Archive
  await mirra.gmail.archive({
    messageId: event.gmail.messageId
  });
  
  return { success: true };
}

Email Backup

export async function handler(event, context) {
  // Only backup important emails
  if (!event.gmail.labels.includes('IMPORTANT')) {
    return { success: true, skipped: true };
  }
  
  // Save to memory/knowledge graph
  await mirra.memory.create({
    type: 'email_backup',
    content: event.content.text,
    metadata: {
      messageId: event.gmail.messageId,
      threadId: event.gmail.threadId,
      from: event.gmail.from.email,
      subject: event.gmail.subject,
      date: event.gmail.date,
      labels: event.gmail.labels,
      hasAttachments: event.gmail.hasAttachments
    }
  });
  
  return { success: true };
}

Smart Reply Suggestion

export async function handler(event, context) {
  // Only suggest replies for direct emails (not CC'd)
  const isDirectRecipient = event.gmail.to.some(
    recipient => recipient.email === 'your@email.com'
  );
  
  if (!isDirectRecipient || event.gmail.cc.length > 0) {
    return { success: true, skipped: true };
  }
  
  // Check sentiment
  if (event.enrichment?.sentiment) {
    const sentiment = event.enrichment.sentiment;
    
    // Generate contextual reply based on sentiment
    let suggestedReply = '';
    
    if (sentiment.label === 'positive') {
      suggestedReply = `Thank you for your email! I appreciate your message about ${event.gmail.subject}.`;
    } else if (sentiment.label === 'negative') {
      suggestedReply = `I understand your concern regarding ${event.gmail.subject}. Let me look into this right away.`;
    } else {
      suggestedReply = `Thanks for reaching out about ${event.gmail.subject}. I'll get back to you shortly.`;
    }
    
    // Store suggestion in memory for later use
    await mirra.memory.create({
      type: 'reply_suggestion',
      content: suggestedReply,
      metadata: {
        emailId: event.gmail.messageId,
        threadId: event.gmail.threadId,
        sentiment: sentiment.label
      }
    });
  }
  
  return { success: true };
}

See Also

On this page