# Building a Custom Bridge

How to extend the bridge with custom inbound or outbound providers.


# Custom Outbound Provider

To add a new outbound provider (e.g., SendGrid, SES, etc.), create a new file in:

bridge-outbound/src/outbound/

# 1. Create the Provider

// bridge-outbound/src/outbound/sendgrid.ts
import { OutboundProvider } from './interface.js';
import { OutgoingEmail } from '../types.js';
import { config } from '../config.js';

export class SendGridProvider implements OutboundProvider {
  name = 'sendgrid';

  async send(email: OutgoingEmail): Promise<void> {
    // email.to = recipient address
    // email.raw = RFC 2822 content

    // Your SendGrid logic here
    await sendgrid.send({
      to: email.to,
      raw: email.raw,
    });

    console.log(`Email sent via SendGrid to ${email.to}`);
  }
}

# 2. Register in index.ts

// bridge-outbound/src/outbound/index.ts
import { OutboundProvider } from './interface.js';
import { MailgunProvider } from './mailgun.js';
import { SmtpProvider } from './smtp.js';
import { SendGridProvider } from './sendgrid.js';  // Add import
import { config } from '../config.js';

export function createOutboundProvider(): OutboundProvider {
  switch (config.outboundProvider) {
    case 'mailgun':
      return new MailgunProvider();
    case 'sendgrid':                    // Add case
      return new SendGridProvider();
    case 'smtp':
    default:
      return new SmtpProvider();
  }
}

# 3. Add Config (if needed)

// bridge-outbound/src/config.ts
export const config = {
  // ... existing config
  sendgridApiKey: process.env.SENDGRID_API_KEY || '',
};

# Interface Reference

interface OutboundProvider {
  name: string;
  send(email: OutgoingEmail): Promise<void>;
}

interface OutgoingEmail {
  to: string;   // Recipient email address
  raw: string;  // RFC 2822 email content
}

# Custom Inbound Provider

To add a new inbound provider (e.g., AWS SES, custom webhook), create a new file in:

bridge-inbound/

# 1. Create the Provider

// bridge-inbound/ses/src/index.ts
import { initConfig, processIncomingEmail, IncomingEmail } from 'inbound-core';

initConfig();

// Example: AWS SES webhook
export async function handleSesNotification(notification: any) {
  const email: IncomingEmail = {
    from: notification.mail.source,
    to: notification.mail.destination[0],
    subject: notification.mail.commonHeaders.subject,
    body: notification.content,
    rawContent: notification.content,
    timestamp: Math.floor(Date.now() / 1000),
  };

  // processIncomingEmail handles:
  // 1. Extract recipient pubkey
  // 2. Run plugin filter
  // 3. Fetch DM relays
  // 4. Gift wrap and publish
  const result = await processIncomingEmail(email, 'ses', 'aws');

  return result;
}

# inbound-core Exports

// Main function - does everything
processIncomingEmail(email, sourceType, sourceInfo)

// Individual functions if you need more control
extractPubkeyFromEmail(address)  // Resolve to pubkey
lookupNip05(name, domain)        // NIP-05 lookup
fetchDMRelays(pubkey)            // Get DM relays (kind 10050)
giftWrapEmail(email, pubkey)     // Create gift wrap
publishToRelays(event, relays)   // Publish to relays
runPlugin(path, input)           // Run filter plugin

# IncomingEmail Interface

interface IncomingEmail {
  from: string;       // Sender address
  to: string;         // Recipient address
  subject: string;    // Email subject
  body: string;       // Email body
  rawContent: string; // Full RFC 2822 content
  timestamp: number;  // Unix timestamp
}