npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pavas-core/email-orchestrator

v1.0.3

Published

NestJS library for email orchestration - Google Workspace, Microsoft Outlook, IMAP/SMTP

Readme

@pavas-core/email-orchestrator

npm version License: MIT GitHub

Librería NestJS para orquestar correos electrónicos con múltiples proveedores desde una API unificada.

Características

  • Google Workspace (Gmail) — OAuth2, Gmail API y push notifications vía Pub/Sub
  • Microsoft Outlook — OAuth2, Microsoft Graph y webhooks para notificaciones
  • IMAP/SMTP — Conexión estándar, config por operación (sin forRoot)

Interfaces compartidas, paginación por cursor y flujos OAuth delegados al consumidor. La librería no almacena credenciales; tú gestionas tokens y configs.

  • Scopes de perfil siempre incluidosemail, profile, openid (Google) y User.Read, openid, profile (Outlook) se agregan automáticamente para obtener info de la cuenta.
  • Listar conexioneslistConnections(connectionKey) por usuario; listConnections() sin key devuelve todas agrupadas por key.

Requisitos

  • NestJS 10 o 11
  • Node.js 18+
  • Todas las credenciales las provee el consumidor (client ID, secret, scopes, tokens). La librería no persiste ni gestiona credenciales.

Instalación

npm install @pavas-core/email-orchestrator

Repositorio: github.com/juanpavasgarzon/email-orchestrator

Quick Start

Google (Gmail)

tokenCache opcional (usa InMemoryTokenCache por defecto). global opcional: si true, GoogleService disponible en toda la app; si false (por defecto), importa el módulo donde lo necesites.

import { GoogleModule, GoogleService } from '@pavas-core/email-orchestrator';

// Opción 1: Sin config (usa InMemoryTokenCache - almacenamiento automático)
@Module({
  imports: [
    GoogleModule.forRoot({
      clientId: process.env.GOOGLE_CLIENT_ID!,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      redirectUri: process.env.GOOGLE_REDIRECT_URI!,
      scopes: [
        'https://www.googleapis.com/auth/gmail.readonly',
        'https://www.googleapis.com/auth/gmail.send',
      ],
      global: true,  // opcional: false por defecto
    }),
  ],
})
export class AppModule {}
// OAuth: redirigir al login
@Get('auth/google')
redirectToGoogle() {
  return { url: this.googleService.getAuthUrl() };
}

// Callback: tokens se almacenan automáticamente con key userId-google
@Get('auth/google/callback')
async handleCallback(@Query('code') code: string, @Req() req) {
  const userId = req.user?.id ?? 'default';
  await this.googleService.exchangeCodeForTokens(code, userId);
  return { ok: true };
}

// Listar emails (connectionKey = userId del request)
const page = await this.googleService.listEmails(userId, { limit: 20 });

Propagación de state OAuth: Pasa datos (userId, returnTo, etc.) entre inicio y callback:

import {
  GoogleService,
  encodeOAuthState,
  decodeOAuthState,
} from '@pavas-core/email-orchestrator';

// Inicio: incluir state con datos
@Get('auth/google')
redirectToGoogle(@Req() req) {
  const userId = req.user?.id ?? 'default';
  const state = encodeOAuthState({ userId, returnTo: '/dashboard' });
  return { url: this.googleService.getAuthUrl(state) };
}

// Callback: leer state para obtener connectionKey
@Get('auth/google/callback')
async handleCallback(
  @Query('code') code: string,
  @Query('state') state: string,
) {
  const payload = decodeOAuthState(state ?? '');
  const connectionKey = payload?.userId ?? 'default';
  await this.googleService.exchangeCodeForTokens(code, connectionKey);
  return { redirect: payload?.returnTo ?? '/' };
}

tokenCache custom (DB, Redis, etc.) — los tokens se almacenan automáticamente con key connectionKey-provider:

import type { TokenCache } from '@pavas-core/email-orchestrator';

const myCache: TokenCache = {
  async get(key) { return db.get(key); },
  async set(key, tokens) { await db.set(key, tokens); },
};

GoogleModule.forRoot({
  clientId: '...',
  clientSecret: '...',
  redirectUri: '...',
  scopes: ['...'],
  tokenCache: myCache,
});

Outlook

global opcional (false por defecto). tokenCache opcional.

import { OutlookModule } from '@pavas-core/email-orchestrator';

OutlookModule.forRoot({
  clientId: process.env.OUTLOOK_CLIENT_ID!,
  clientSecret: process.env.OUTLOOK_CLIENT_SECRET!,
  tenantId: process.env.OUTLOOK_TENANT_ID!,
  redirectUri: process.env.OUTLOOK_REDIRECT_URI!,
  scopes: [
    'https://graph.microsoft.com/Mail.Read',
    'https://graph.microsoft.com/Mail.Send',
  ],
  global: true,      // opcional
  tokenCache: myCache,
});

Flujo OAuth: getAuthUrl() → redirect → callback con exchangeCodeForTokens(code) → tokens guardados en tokenCache.

Google y Outlook usan la misma configuración: clientId, clientSecret, redirectUri, scopes, tokenCache. Solo Outlook añade tenantId. El cliente provee la persistencia (tokenCache); la librería construye el token provider internamente.

MSAL (@azure/msal-node): La librería no incluye MSAL. Instálalo en tu app (npm install @azure/msal-node). Implementa un tokenCache que lea de MSAL; es el único punto externo de persistencia:

import { ConfidentialClientApplication } from '@azure/msal-node';
import type { TokenCache, OAuthTokens } from '@pavas-core/email-orchestrator';

// Tu TokenCache que adapta MSAL
const msalTokenCache: TokenCache<OAuthTokens> = {
  async get(key: string) {
    const connectionKey = key.replace('-outlook', '');
    const integration = await getIntegrationByConnectionKey(connectionKey);
    const homeAccountId = integration.metadata.home_account_id as string;
    const client = createMsalClient(homeAccountId); // ConfidentialClientApplication con cache
    const account = await client.getTokenCache().getAccountByHomeId(homeAccountId);
    const result = await client.acquireTokenSilent({ account, scopes: integration.scopes });
    return {
      accessToken: result.accessToken,
      refreshToken: '',
      expiresAt: result.expiresOn ? result.expiresOn.getTime() : undefined,
    };
  },
  async set(key, tokens) {
    // MSAL ya persiste en acquireTokenByCode; o sincroniza aquí si usas nuestro exchange
  },
};

OutlookModule.forRoot({ ...config, tokenCache: msalTokenCache });

En el callback OAuth usa acquireTokenByCode de MSAL (no exchangeCodeForTokens). MSAL almacena en su cache; tu tokenCache.get() lee desde ahí.

IMAP / SMTP

Sin config de credenciales a nivel módulo. Usa forRoot(). Opción global: si true, ImapSmtpService está disponible en toda la app; si false (por defecto), importa el módulo en cada módulo que lo use.

import { ImapSmtpModule, ImapSmtpService } from '@pavas-core/email-orchestrator';
import type { ImapSmtpConnectionConfig } from '@pavas-core/email-orchestrator';

@Module({
  imports: [ImapSmtpModule.forRoot()],  // forRoot({ global: true }) si quieres ImapSmtpService en toda la app
})
export class AppModule {}

// Registrar conexión (aparece en listConnections)
@Post('imap-smtp/connect')
async register(@Body() config: ImapSmtpConnectionConfig, @Req() req) {
  const userId = req.user?.id;
  await this.imapSmtp.registerConnection(userId, config);
}

// Enviar con config pasada (solo smtp configurado = envío)
await this.imapSmtp.sendEmail(config, { to: '...', subject: '...', text: '...' });

// Listar con config pasada (solo imap configurado = lectura)
await this.imapSmtp.listEmails(config, { limit: 20 });

// Config: imap y/o smtp (al menos uno)
const connection: ImapSmtpConnectionConfig = {
  imap: { host: 'imap.ejemplo.com', port: 993, user: '...', password: '...', tls: true },
  smtp: { host: 'smtp.ejemplo.com', port: 587, user: '...', password: '...', secure: false },
};

Listar conexiones establecidas

Con Google, Outlook o ImapSmtp importados, ConnectionRegistry está disponible. Inyecta y pasa el connectionKey (userId, apiKey, etc.):

import { ConnectionRegistry } from '@pavas-core/email-orchestrator';

@Injectable()
export class ConnectionsController {
  constructor(private readonly connections: ConnectionRegistry) {}

  @Get('connections')
  async list(@Req() req, @Query('all') all?: string) {
    if (all === 'true') {
      return this.connections.listConnections();  // todas las conexiones (por key)
    }
    const connectionKey = req.user?.id ?? req.headers['x-api-key'];
    return this.connections.listConnections(connectionKey);  // solo ese usuario
  }
}

Cada ítem incluye:

  • provider'google' | 'outlook' | 'imap-smtp'
  • email, name, picture — datos de la cuenta
  • requestedScopes — permisos solicitados en la config
  • grantedScopes — permisos efectivamente otorgados (pueden ser menos según Workspace/Admin)

Persistencia sustituible: Por defecto usa memoria. Para DB, Redis, etc.:

import {
  ConnectionRegistry,
  CONNECTION_PERSISTENCE,
  type ConnectionPersistence,
} from '@pavas-core/email-orchestrator';

@Injectable()
class MyDbConnectionPersistence implements ConnectionPersistence {
  async get(connectionKey: string) { /* devuelve ConnectionInfo[] | null */ }
  async set(connectionKey: string, connections: ConnectionInfo[]) { /* almacena */ }
  async getAll() { /* devuelve ConnectionGroup[] = { connectionKey, connections }[] */ }
}

@Module({
  imports: [GoogleModule, OutlookModule],
  providers: [
    { provide: CONNECTION_PERSISTENCE, useClass: MyDbConnectionPersistence },
  ],
})
export class AppModule {}
  • listConnections(connectionKey?) — con key: consulta APIs y actualiza. Sin key: devuelve todas desde cache (ConnectionGroup[]).
  • getCachedConnections(connectionKey?) — con key: conexiones del usuario. Sin key: todas (ConnectionGroup[]).
  • mergeConnection(connectionKey, connectionInfo) — fusiona una conexión en la persistencia (usado por getConnectionInfo de cada provider).

Reducción de costos: Los scopes de email (Google Workspace, Microsoft Graph) tienen un costo monetario alto. Para minimizar llamadas a APIs:

import {
  ConnectionModule,
  CONNECTION_REGISTRY_OPTIONS,
  type ConnectionRegistryOptions,
} from '@pavas-core/email-orchestrator';

@Module({
  imports: [GoogleModule, OutlookModule],
  providers: [
    {
      provide: CONNECTION_REGISTRY_OPTIONS,
      useValue: {
        connectionInfoCacheTtlMs: 300000, // 5 min cache para listConnections
      } as ConnectionRegistryOptions,
    },
  ],
})
export class AppModule {}
  • getConnectionInfo de cada provider (Google, Outlook, IMAP/SMTP) actualiza automáticamente la cache de ConnectionRegistry.

Ejemplo de respuesta listConnections(connectionKey) (un usuario):

[
  {
    "provider": "google",
    "email": "[email protected]",
    "name": "Usuario",
    "picture": "https://...",
    "requestedScopes": ["email", "profile", "openid", "https://www.googleapis.com/auth/gmail.readonly", "https://www.googleapis.com/auth/gmail.send"],
    "grantedScopes": ["https://www.googleapis.com/auth/userinfo.email", "https://www.googleapis.com/auth/userinfo.profile", "openid", "https://www.googleapis.com/auth/gmail.readonly"]
  },
  {
    "provider": "outlook",
    "email": "[email protected]",
    "name": "Usuario Empresa",
    "requestedScopes": ["User.Read", "openid", "profile", "Mail.Read", "Mail.Send"],
    "grantedScopes": ["User.Read", "Mail.Read", "Mail.Send"]
  }
]

Ejemplo de respuesta listConnections() sin key (todas las conexiones, desde cache):

[
  {
    "connectionKey": "user123",
    "connections": [
      { "provider": "google", "email": "[email protected]", "name": "Usuario", "requestedScopes": [...], "grantedScopes": [...] }
    ]
  },
  {
    "connectionKey": "user456",
    "connections": [
      { "provider": "outlook", "email": "[email protected]", "name": "Otro", "requestedScopes": [...], "grantedScopes": [...] }
    ]
  }
]

Token Cache

Siempre se usa tokenCache. La key es connectionKey-provider (ej: user123-google).

  • Sin tokenCache: usa InMemoryTokenCache, tokens se guardan en el callback.
  • Con tokenCache: exchangeCodeForTokens y refreshAccessToken hacen set(key, tokens) automáticamente.

Implementa TokenCache para cache custom (DB, Redis, etc.):

import type { TokenCache, OAuthTokens } from '@pavas-core/email-orchestrator';

class MyTokenCache implements TokenCache {
  async get(key: string): Promise<OAuthTokens | null> {
    return await db.getTokens(key);
  }
  async set(key: string, tokens: OAuthTokens): Promise<void> {
    await db.saveTokens(key, tokens);
  }
}

Helpers sin Nest

Puedes usar los helpers OAuth fuera de Nest en rutas externas o scripts:

import {
  getGoogleAuthUrl,
  exchangeGoogleCodeForTokens,
  refreshGoogleAccessToken,
} from '@pavas-core/email-orchestrator/google';

import {
  getOutlookAuthUrl,
  exchangeOutlookCodeForTokens,
  refreshOutlookAccessToken,
} from '@pavas-core/email-orchestrator/outlook';

Push Notifications

Gmail (Pub/Sub)

1. Google Cloud Console

  • Crea un proyecto y habilita Gmail API.
  • Credenciales OAuth con scopes gmail.readonly y gmail.modify.

2. Pub/Sub

# Crear topic
gcloud pubsub topics create gmail-notifications

# Otorgar permisos a Gmail API
gcloud pubsub topics add-iam-policy-binding gmail-notifications \
  --member="serviceAccount:[email protected]" \
  --role="roles/pubsub.publisher"

3. Push subscription

Crea una suscripción que apunte a tu endpoint HTTPS (ej. https://tu-app.com/webhooks/gmail):

gcloud pubsub subscriptions create gmail-push \
  --topic=gmail-notifications \
  --push-endpoint=https://tu-app.com/webhooks/gmail

4. Código

// Módulo con callbacks configurables (onNewEmail, onReply)
GoogleModule.forRoot({
  // ... clientId, clientSecret, etc.
  pushNotificationCallbacks: {
    onNewEmail: (event) => console.log('Correo nuevo:', event.message?.subject),
    onReply: (event) => console.log('Respondieron:', event.message?.subject),
  },
});

// Iniciar watch (después de OAuth)
const { historyId, expiration } = await this.googleService.setupPushNotifications(
  'projects/TU_PROJECT_ID/topics/gmail-notifications'
);

// Endpoint POST: una sola llamada a handleWebhook invoca los callbacks automáticamente
@Post('webhooks/gmail')
async handleGmailPush(@Body() body: unknown) {
  await this.googleService.handleWebhook(body);
}

Tipos de notificación (ambos pueden estar habilitados):

  • onNewEmail: correo nuevo en el buzón (se llama siempre que llega algo)
  • onReply: alguien respondió un correo (tiene In-Reply-To). Si es reply, se invocan ambos callbacks

Outlook (Webhooks)

1. Endpoint HTTPS

Tu app debe exponer un endpoint que reciba solicitudes de Microsoft (ej. https://tu-app.com/webhooks/outlook).

2. Validación inicial

Microsoft envía primero un GET con ?validationToken=xxx. Tu endpoint debe responder 200 con el body = exactamente el validationToken (texto plano):

// Módulo con callbacks configurables
OutlookModule.forRoot({
  // ...
  pushNotificationCallbacks: {
    onNewEmail: (event) => this.notifyNewEmail(event),
    onReply: (event) => this.notifyReply(event),
  },
});

@All('webhooks/outlook')
async handleOutlookWebhook(@Req() req: Request, @Res() res: Response) {
  if (this.outlookService.isValidationRequest(req.query)) {
    return res.status(200).send(this.outlookService.getValidationResponse(req.query));
  }
  res.status(202).send(); // Responder en < 3 segundos
  void this.outlookService.handleWebhook(req.body); // Procesa e invoca callbacks
}

3. Crear suscripción

const { subscriptionId, expirationDateTime } =
  await this.outlookService.setupPushNotifications(
    'https://tu-app.com/webhooks/outlook'
  );
// Guardar subscriptionId y renovar antes de expirationDateTime

4. Renovar

await this.outlookService.renewPushSubscription(subscriptionId);

IMAP IDLE (push-like)

Para IMAP no hay webhooks nativos, pero startIdleWatcher simula push:

const stop = await this.imapSmtpService.startIdleWatcher(
  connectionConfig,
  (newMail) => console.log('Nuevo email:', newMail)
);
// Cuando quieras desconectar:
stop();

Interfaces Comunes

Todos los servicios usan las mismas interfaces y paginación por cursor:

| Tipo | Descripción | |---------------------|--------------------------------------------------| | EmailMessage | Mensaje normalizado (id, subject, from, to, body) | | ListEmailsOptions | { limit?, cursor?, filter?, orderBy?, query?, labelIds? } — filter/orderBy unificados | | ListEmailsResult | { items, nextCursor?, hasMore } | | SendEmailOptions | Opciones para enviar | | SendEmailResult | { messageId } | | FetchHistoryOptions | { startHistoryId?, cursor?, limit? } | | FetchHistoryResult | { events, nextCursor?, hasMore } |

import type {
  EmailMessage,
  ListEmailsOptions,
  ListEmailsFilter,
  ListEmailsOrderBy,
  ListEmailsResult,
  SendEmailOptions,
  SendEmailResult,
} from '@pavas-core/email-orchestrator';

// Filtro unificado (Google, Outlook, IMAP/SMTP - misma sintaxis)
await googleService.listEmails(userId, {
  filter: { from: '[email protected]', subject: 'foo', isUnread: true },
  orderBy: { field: 'date', direction: 'desc' },
  limit: 20,
});

Varios Proveedores

Puedes importar varios módulos en el mismo proyecto:

@Injectable()
export class EmailOrchestrator {
  constructor(
    private readonly googleService: GoogleService,
    private readonly outlookService: OutlookService,
    private readonly imapSmtpService: ImapSmtpService,
  ) {}

  async sendViaGoogle(connectionKey: string, opts: SendEmailOptions) {
    return this.googleService.sendEmail(connectionKey, opts);
  }

  async sendViaImap(config: ImapSmtpConnectionConfig, opts: SendEmailOptions) {
    return this.imapSmtpService.sendEmail(config, opts);
  }
}

Arquitectura de servicios (SOLID)

Cada provider expone 2 servicios con responsabilidades separadas:

| Provider | Auth/Connection | Utilidad | |----------|-----------------|----------| | Google | GoogleAuthService — OAuth, tokens, getAuthUrl | GoogleService — email ops, push (extiende Auth) | | Outlook | OutlookAuthService — OAuth, tokens, MSAL | OutlookService — email ops, webhooks (extiende Auth) | | IMAP/SMTP | ImapSmtpConnectionService — registerConnection, getConnectionInfo | ImapSmtpService — sendEmail, listEmails (delega conexiones) |

Inyecta GoogleAuthService o OutlookAuthService cuando solo necesitas auth. GoogleService y OutlookService heredan los métodos de auth y añaden los de correo.


API Reference — Métodos y Scopes

GoogleModule

forRoot y forRootAsync aceptan global?: boolean (false por defecto). Exporta GoogleAuthService y GoogleService.

GoogleService / GoogleAuthService

GoogleService extiende GoogleAuthService. Todos los métodos reciben connectionKey como primer argumento (excepto getAuthUrl).

| Método | Descripción | Scope requerido | |--------|-------------|-----------------| | getAuthUrl() | URL de autorización OAuth | Scopes configurados | | exchangeCodeForTokens(code, connectionKey) | Intercambiar code por tokens | Scopes configurados | | refreshAccessToken(refreshToken, connectionKey) | Refrescar access token | Scopes configurados | | getConnectionInfo(connectionKey) | Info de cuenta + permisos otorgados | email, profile, openid (automático) | | sendEmail(connectionKey, options) | Enviar correo | https://www.googleapis.com/auth/gmail.send | | listEmails(connectionKey, options) | Listar correos | https://www.googleapis.com/auth/gmail.readonly | | getEmail(connectionKey, messageId) | Obtener correo por ID | https://www.googleapis.com/auth/gmail.readonly | | setupPushNotifications(connectionKey, topic) | Configurar push (Pub/Sub) | https://www.googleapis.com/auth/gmail.modify | | stopPushNotifications(connectionKey) | Detener push | https://www.googleapis.com/auth/gmail.modify | | handleWebhook(connectionKey, body) | Maneja webhook: parsea, obtiene cambios e invoca onNewEmail/onReply | gmail.readonly | | parsePubSubPayload(body) | Parsear payload Pub/Sub | — (sin API) | | fetchChangesSinceHistory(connectionKey, options) | Obtener cambios tras push | https://www.googleapis.com/auth/gmail.readonly |

Scopes Google más usados:

  • gmail.send — enviar
  • gmail.readonly — leer
  • gmail.modify — leer + modificar + push notifications

OutlookModule

forRoot y forRootAsync aceptan global?: boolean (false por defecto). Exporta OutlookAuthService y OutlookService.

OutlookService / OutlookAuthService

OutlookService extiende OutlookAuthService. Todos los métodos reciben connectionKey como primer argumento (excepto getAuthUrl).

| Método | Descripción | Scope requerido | |--------|-------------|-----------------| | getAuthUrl() | URL de autorización OAuth | Scopes configurados | | exchangeCodeForTokens(code, connectionKey) | Intercambiar code por tokens | Scopes configurados | | refreshAccessToken(refreshToken, connectionKey) | Refrescar tokens | Scopes configurados | | getConnectionInfo(connectionKey) | Info de cuenta + permisos | User.Read (automático) | | sendEmail(connectionKey, options) | Enviar correo | https://graph.microsoft.com/Mail.Send | | listEmails(connectionKey, options) | Listar correos | https://graph.microsoft.com/Mail.Read | | getEmail(connectionKey, messageId) | Obtener correo por ID | https://graph.microsoft.com/Mail.Read | | setupPushNotifications(connectionKey, url) | Configurar webhooks | https://graph.microsoft.com/Mail.Read | | renewPushSubscription(connectionKey, id) | Renovar suscripción | https://graph.microsoft.com/Mail.Read | | deletePushSubscription(connectionKey, id) | Eliminar suscripción | https://graph.microsoft.com/Mail.Read | | handleWebhook(connectionKey, body) | Maneja webhook: parsea, obtiene mensajes e invoca onNewEmail/onReply | Mail.Read | | parsePushNotification(body) | Parsear notificación | — (sin API) | | fetchFullMessagesForEvents(connectionKey, events) | Mensajes completos para eventos | https://graph.microsoft.com/Mail.Read | | isValidationRequest(query) | Detectar validación webhook | — (estático) | | getValidationResponse(query) | Respuesta para validación | — (estático) |

Scopes Outlook más usados:

  • Mail.Send — enviar
  • Mail.Read — leer + push notifications

ImapSmtpModule

| Método | Descripción | |--------|-------------| | forRoot(options?) | Registra el módulo. Exporta ImapSmtpConnectionService e ImapSmtpService. |

ImapSmtpConnectionService

Gestiona conexiones: registerConnection, getStoredConnection, removeConnection, getConnectionInfo.

ImapSmtpService

Operaciones de correo. La config se pasa en cada llamada o se registra con registerConnection (delega a ImapSmtpConnectionService).

| Método | Descripción | |--------|-------------| | registerConnection(connectionKey, config) | Almacena conexión (aparece en listConnections) | | getStoredConnection(connectionKey) | Obtiene config almacenada | | removeConnection(connectionKey) | Elimina conexión almacenada | | sendEmail(connection, options) | Enviar correo (requiere smtp en config) | | listEmails(connection, options) | Listar correos (requiere imap en config) | | getEmail(connection, messageIdOrUid) | Obtener correo | | startIdleWatcher(connection, onNewMail) | Escuchar nuevos correos (IDLE) |

Config: imap y/o smtp (al menos uno). grantedScopes en listConnections: ['imap'], ['smtp'] o ['imap','smtp'].


ConnectionRegistry

| Método | Descripción | |--------|-------------| | listConnections(connectionKey?) | Con key: consulta APIs, actualiza. Sin key: todas desde cache | | getCachedConnections(connectionKey?) | Con key: cache del usuario. Sin key: todas (ConnectionGroup[]) |

La persistencia es sustituible: por defecto InMemoryConnectionPersistence. Provee CONNECTION_PERSISTENCE con tu implementación de ConnectionPersistence (DB, Redis, etc.).


Exports del paquete

| Export | Contenido | |--------|-----------| | ./ (root) | Interfaces, ConnectionRegistry, ConnectionModule, InMemoryTokenCache, CONNECTION_PERSISTENCE, IMAP_SMTP_CONNECTION_STORE | | ./google | GoogleModule, GoogleService, helpers OAuth | | ./outlook | OutlookModule, OutlookService, helpers OAuth | | ./imap-smtp | ImapSmtpModule, ImapSmtpService |

ConnectionRegistry se obtiene al importar GoogleModule u OutlookModule (incluyen ConnectionModule).


Licencia

MIT © Pavas. Ver LICENSE.