Pular para conteúdo

OUTLOOK - Email e Calendário Microsoft

O que é este Node?

O OUTLOOK é o node responsável por integrar com o Microsoft Outlook permitindo enviar emails, buscar mensagens e criar eventos de calendário diretamente dos seus flows.

Por que este Node existe?

Automatizar comunicação por email é essencial para produtividade. O OUTLOOK existe para:

  1. Email automático: Enviar emails de confirmação, notificações e follow-ups
  2. Leitura de emails: Buscar e processar emails recebidos
  3. Agendamento: Criar eventos de calendário automaticamente
  4. Notificações de equipe: Avisar colaboradores sobre eventos importantes
  5. Integração corporativa: Conectar WhatsApp com ambiente Microsoft 365

Como funciona internamente?

Quando o OUTLOOK é executado, o sistema:

  1. Autentica usando access token do Microsoft Graph API
  2. Identifica operação (sendMail, getMails, createEvent)
  3. Conecta à API do Microsoft Graph v1.0
  4. Executa operação com os dados fornecidos
  5. Retorna resultado com confirmação ou dados
  6. Se erro: Loga e lança exceção

Código interno (productivity-executors.service.ts:253-356):

async executeOutlook(data: any, variables: Record<string, any>): Promise<any> {
  try {
    this.logger.log('📧 [OUTLOOK] Executing operation');

    const graphApiUrl = 'https://graph.microsoft.com/v1.0';
    const headers = {
      Authorization: `Bearer ${data.accessToken}`,
      'Content-Type': 'application/json',
    };

    switch (data.operation) {
      case 'sendMail':
        const sendMailUrl = `${graphApiUrl}/me/sendMail`;
        await firstValueFrom(
          this.httpService.post(sendMailUrl,
            {
              message: {
                subject: data.subject,
                body: {
                  contentType: data.bodyType || 'Text',
                  content: data.body,
                },
                toRecipients: data.to.map((email: string) => ({
                  emailAddress: { address: email },
                })),
                ccRecipients: data.cc?.map((email: string) => ({
                  emailAddress: { address: email },
                })) || [],
                attachments: data.attachments?.map((att: any) => ({
                  '@odata.type': '#microsoft.graph.fileAttachment',
                  name: att.name,
                  contentType: att.contentType,
                  contentBytes: att.content,
                })) || [],
              },
            },
            { headers }
          )
        );
        return {
          success: true,
          message: 'Email sent successfully',
        };

      case 'getMails':
        const getMailsUrl = `${graphApiUrl}/me/messages?$top=${data.limit || 10}&$orderby=receivedDateTime desc`;
        const getMailsResponse = await firstValueFrom(
          this.httpService.get(getMailsUrl, { headers })
        );
        return {
          success: true,
          emails: getMailsResponse.data.value.map((email: any) => ({
            id: email.id,
            subject: email.subject,
            from: email.from?.emailAddress?.address,
            receivedDateTime: email.receivedDateTime,
            bodyPreview: email.bodyPreview,
            hasAttachments: email.hasAttachments,
          })),
        };

      case 'createEvent':
        const createEventUrl = `${graphApiUrl}/me/events`;
        const createEventResponse = await firstValueFrom(
          this.httpService.post(createEventUrl,
            {
              subject: data.subject,
              body: {
                contentType: 'HTML',
                content: data.body || '',
              },
              start: {
                dateTime: data.startDateTime,
                timeZone: data.timeZone || 'America/Sao_Paulo',
              },
              end: {
                dateTime: data.endDateTime,
                timeZone: data.timeZone || 'America/Sao_Paulo',
              },
              location: {
                displayName: data.location,
              },
              attendees: data.attendees?.map((email: string) => ({
                emailAddress: { address: email },
                type: 'required',
              })) || [],
            },
            { headers }
          )
        );
        return {
          success: true,
          eventId: createEventResponse.data.id,
          webLink: createEventResponse.data.webLink,
        };

      default:
        throw new Error(`Unknown Outlook operation: ${data.operation}`);
    }
  } catch (error) {
    this.logger.error('Outlook execution error:', error);
    throw error;
  }
}

Quando você DEVE usar este Node?

Use OUTLOOK quando precisar automatizar email e agenda:

Casos de uso:

  1. Confirmação de pedido: Enviar email automático após compra
  2. Agendar reunião: Criar evento no calendário com convite
  3. Follow-up automático: Enviar lembretes por email
  4. Notificar equipe: Avisar sobre novos tickets ou tarefas
  5. Buscar mensagens: Verificar emails importantes automaticamente
  6. Anexar documentos: Enviar propostas e contratos por email

Quando NÃO usar OUTLOOK:

  • Marketing em massa: Use MAILCHIMP ou similar
  • Chat em tempo real: Use WhatsApp diretamente
  • SMS: Use node específico de SMS

Parâmetros Detalhados

operation (string, obrigatório)

O que é: Define qual operação será executada no Outlook.

Valores possíveis: - sendMail: Enviar email - getMails: Buscar emails recebidos - createEvent: Criar evento no calendário

accessToken (string, obrigatório)

O que é: Token de acesso do Microsoft Graph API.

Como obter: Configure aplicação no Azure AD e obtenha via OAuth2.

subject (string, obrigatório para sendMail/createEvent)

O que é: Assunto do email ou título do evento.

Flow completo para testar:

{
  "name": "Teste OUTLOOK - Enviar Email",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Email Destinatário",
        "parameters": {
          "message": "Email do destinatário:",
          "variable": "email_destino"
        }
      }
    },
    {
      "id": "input_2",
      "type": "input",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Mensagem",
        "parameters": {
          "message": "Digite a mensagem:",
          "variable": "mensagem"
        }
      }
    },
    {
      "id": "outlook_1",
      "type": "outlook",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Enviar Email",
        "parameters": {
          "operation": "sendMail",
          "to": ["{{email_destino}}"],
          "subject": "Mensagem via Lumina Flow",
          "body": "{{mensagem}}\n\nEnviado automaticamente pelo Lumina Flow Builder",
          "bodyType": "Text",
          "accessToken": "{{microsoft_access_token}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Email enviado para {{email_destino}}!"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1100, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "input_2" },
    { "source": "input_2", "target": "outlook_1" },
    { "source": "outlook_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

to (array, obrigatório para sendMail)

O que é: Array com endereços de email dos destinatários.

Exemplo: ["cliente@empresa.com", "gestor@empresa.com"]

body (string, obrigatório para sendMail/createEvent)

O que é: Corpo do email ou descrição do evento.

bodyType (string, opcional)

O que é: Formato do corpo da mensagem.

Valores: "Text" ou "HTML" (padrão: Text)

cc (array, opcional)

O que é: Array com endereços de email para cópia (CC).

attachments (array, opcional)

O que é: Array de anexos do email.

Formato:

[
  {
    "name": "arquivo.pdf",
    "contentType": "application/pdf",
    "content": "base64_encoded_content"
  }
]

startDateTime e endDateTime (string, obrigatório para createEvent)

O que é: Data/hora de início e fim do evento no formato ISO 8601.

Exemplo: "2025-01-20T14:00:00"

Flow completo para testar:

{
  "name": "Teste OUTLOOK - Criar Evento",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Título da Reunião",
        "parameters": {
          "message": "Título da reunião:",
          "variable": "titulo_reuniao"
        }
      }
    },
    {
      "id": "date_1",
      "type": "date",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Data",
        "parameters": {
          "message": "Data da reunião (DD/MM/YYYY):",
          "variable": "data_reuniao"
        }
      }
    },
    {
      "id": "outlook_1",
      "type": "outlook",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Agendar Reunião",
        "parameters": {
          "operation": "createEvent",
          "subject": "{{titulo_reuniao}}",
          "body": "Reunião agendada via WhatsApp",
          "startDateTime": "{{data_reuniao}}T14:00:00",
          "endDateTime": "{{data_reuniao}}T15:00:00",
          "timeZone": "America/Sao_Paulo",
          "location": "Sala de Reuniões",
          "attendees": ["equipe@empresa.com"],
          "accessToken": "{{microsoft_access_token}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Reunião agendada!\n\n📅 {{titulo_reuniao}}\n🕐 {{data_reuniao}} às 14:00\n\n🔗 {{outlook_1.webLink}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1100, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "date_1" },
    { "source": "date_1", "target": "outlook_1" },
    { "source": "outlook_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

limit (number, opcional para getMails)

O que é: Número máximo de emails a retornar (padrão: 10).

Parâmetros

Campo Tipo Obrigatório Descrição
operation string Sim sendMail, getMails, createEvent
accessToken string Sim Token Microsoft Graph API
to array Sim* Destinatários (para sendMail)
subject string Sim* Assunto/título (para sendMail, createEvent)
body string Sim* Corpo do email/evento
bodyType string Não Text ou HTML (padrão: Text)
cc array Não Cópia (CC)
attachments array Não Anexos do email
limit number Não Limite de emails (padrão: 10)
startDateTime string Sim* Início do evento (ISO 8601)
endDateTime string Sim* Fim do evento (ISO 8601)
timeZone string Não Fuso horário (padrão: America/Sao_Paulo)
location string Não Local do evento
attendees array Não Participantes do evento

*Obrigatório dependendo da operação

Exemplo 1: Confirmação de Pedido por Email

Objetivo: Enviar email automático com detalhes do pedido após conclusão.

JSON para Importar

{
  "name": "Confirmação de Pedido - Outlook",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Número do Pedido",
        "parameters": {
          "message": "Número do pedido:",
          "variable": "numero_pedido"
        }
      }
    },
    {
      "id": "email_1",
      "type": "email",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Email Cliente",
        "parameters": {
          "message": "Email do cliente:",
          "variable": "email_cliente"
        }
      }
    },
    {
      "id": "number_1",
      "type": "number",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Valor",
        "parameters": {
          "message": "Valor do pedido:",
          "variable": "valor_pedido",
          "decimals": 2
        }
      }
    },
    {
      "id": "outlook_1",
      "type": "outlook",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Enviar Confirmação",
        "parameters": {
          "operation": "sendMail",
          "to": ["{{email_cliente}}"],
          "cc": ["vendas@empresa.com"],
          "subject": "Confirmação de Pedido #{{numero_pedido}}",
          "bodyType": "HTML",
          "body": "<h2>Pedido Confirmado!</h2><p>Olá,</p><p>Seu pedido foi recebido com sucesso:</p><ul><li><strong>Número:</strong> {{numero_pedido}}</li><li><strong>Valor:</strong> R$ {{valor_pedido}}</li><li><strong>Data:</strong> {{timestamp}}</li></ul><p>Entraremos em contato em breve.</p><p>Atenciosamente,<br>Equipe de Vendas</p>",
          "accessToken": "{{microsoft_access_token}}"
        }
      }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Confirmar",
        "parameters": {
          "message": "✅ Pedido #{{numero_pedido}} confirmado!\n\n📧 Email enviado para {{email_cliente}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1300, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "input_1" },
    { "source": "input_1", "target": "email_1" },
    { "source": "email_1", "target": "number_1" },
    { "source": "number_1", "target": "outlook_1" },
    { "source": "outlook_1", "target": "message_1" },
    { "source": "message_1", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: Número do pedido:
Usuário: 12345
Sistema: Email do cliente:
Usuário: cliente@email.com
Sistema: Valor do pedido:
Usuário: 250.50
Sistema: ✅ Pedido #12345 confirmado!

📧 Email enviado para cliente@email.com

Exemplo 2: Agendar Reunião Automática

Objetivo: Criar evento no calendário com base em solicitação via WhatsApp.

JSON para Importar

{
  "name": "Agendar Reunião - Outlook",
  "nodes": [
    {
      "id": "start_1",
      "type": "start",
      "position": { "x": 100, "y": 100 },
      "data": { "label": "Início" }
    },
    {
      "id": "message_1",
      "type": "message",
      "position": { "x": 300, "y": 100 },
      "data": {
        "label": "Boas-vindas",
        "parameters": {
          "message": "📅 Vamos agendar sua reunião!"
        }
      }
    },
    {
      "id": "input_1",
      "type": "input",
      "position": { "x": 500, "y": 100 },
      "data": {
        "label": "Assunto",
        "parameters": {
          "message": "Qual o assunto da reunião?",
          "variable": "assunto"
        }
      }
    },
    {
      "id": "date_1",
      "type": "date",
      "position": { "x": 700, "y": 100 },
      "data": {
        "label": "Data",
        "parameters": {
          "message": "Qual a data? (DD/MM/YYYY)",
          "variable": "data"
        }
      }
    },
    {
      "id": "input_2",
      "type": "input",
      "position": { "x": 900, "y": 100 },
      "data": {
        "label": "Horário",
        "parameters": {
          "message": "Qual o horário? (HH:MM)",
          "variable": "horario"
        }
      }
    },
    {
      "id": "outlook_1",
      "type": "outlook",
      "position": { "x": 1100, "y": 100 },
      "data": {
        "label": "Criar Evento",
        "parameters": {
          "operation": "createEvent",
          "subject": "{{assunto}}",
          "body": "Reunião agendada via WhatsApp com {{contact_name}}",
          "startDateTime": "{{data}}T{{horario}}:00",
          "endDateTime": "{{data}}T{{horario + 1}}:00",
          "timeZone": "America/Sao_Paulo",
          "location": "Online",
          "attendees": ["{{contact_email}}", "equipe@empresa.com"],
          "accessToken": "{{microsoft_access_token}}"
        }
      }
    },
    {
      "id": "message_2",
      "type": "message",
      "position": { "x": 1300, "y": 100 },
      "data": {
        "label": "Confirmação",
        "parameters": {
          "message": "✅ Reunião agendada!\n\n📅 {{assunto}}\n🗓️ {{data}}\n🕐 {{horario}}\n📍 Online\n\n🔗 Link do evento:\n{{outlook_1.webLink}}"
        }
      }
    },
    {
      "id": "end_1",
      "type": "end",
      "position": { "x": 1500, "y": 100 },
      "data": { "label": "Fim" }
    }
  ],
  "edges": [
    { "source": "start_1", "target": "message_1" },
    { "source": "message_1", "target": "input_1" },
    { "source": "input_1", "target": "date_1" },
    { "source": "date_1", "target": "input_2" },
    { "source": "input_2", "target": "outlook_1" },
    { "source": "outlook_1", "target": "message_2" },
    { "source": "message_2", "target": "end_1" }
  ]
}

Saída esperada:

Sistema: 📅 Vamos agendar sua reunião!
Sistema: Qual o assunto da reunião?
Usuário: Apresentação do Projeto
Sistema: Qual a data? (DD/MM/YYYY)
Usuário: 20/01/2025
Sistema: Qual o horário? (HH:MM)
Usuário: 14:00
Sistema: ✅ Reunião agendada!

📅 Apresentação do Projeto
🗓️ 20/01/2025
🕐 14:00
📍 Online

🔗 Link do evento:
https://outlook.office365.com/calendar/...

Resposta do Node

Operação SEND_MAIL:

{
  "success": true,
  "message": "Email sent successfully"
}

Operação GET_MAILS:

{
  "success": true,
  "emails": [
    {
      "id": "AAMkAGI2T...",
      "subject": "Re: Proposta Comercial",
      "from": "cliente@empresa.com",
      "receivedDateTime": "2025-01-15T10:30:00Z",
      "bodyPreview": "Olá, gostaria de mais informações...",
      "hasAttachments": false
    }
  ]
}

Operação CREATE_EVENT:

{
  "success": true,
  "eventId": "AAMkAGI2T...",
  "webLink": "https://outlook.office365.com/calendar/deeplink/..."
}

Boas Práticas

SIM: - Use HTML para emails mais ricos e profissionais - Sempre inclua informações claras no assunto - Adicione CC para manter equipe informada - Use timeZone correto para eventos - Valide emails antes de enviar

NÃO: - Não envie spam ou emails não solicitados - Não exponha access token em logs - Não esqueça de tratar erros de envio - Não crie eventos sem confirmar disponibilidade

Dicas

💡 Templates HTML: Crie templates de email reutilizáveis para consistência

💡 Anexos: Converta arquivos para base64 antes de anexar

💡 Fuso horário: Use sempre America/Sao_Paulo ou ajuste conforme necessário

💡 Follow-up: Combine com DELAY para envios programados

💡 Integração: Use com GOOGLE SHEETS para registrar emails enviados

Próximo Node

GMAIL - Alternativa Google para emails → GOOGLE CALENDAR - Calendário do Google → MAILCHIMP - Email marketing