@z_06/relay-temp-mail 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -110,7 +110,7 @@ var CFEmailClient = class {
110
110
  * @param httpClient - Optional HTTP client (defaults to fetch-based implementation)
111
111
  */
112
112
  constructor(apiUrl, token, httpClient) {
113
- this.apiUrl = apiUrl;
113
+ this.apiUrl = apiUrl.replace(/\/+$/, "");
114
114
  this.token = token;
115
115
  this.httpClient = httpClient ?? new DefaultHttpClient();
116
116
  }
@@ -352,7 +352,8 @@ var HttpClient = class {
352
352
  };
353
353
 
354
354
  // src/parser.ts
355
- var MOZMAIL_PATTERN = /[a-zA-Z0-9]+@mozmail\.com/g;
355
+ var EMAIL_PATTERN = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
356
+ var MOZMAIL_SUFFIX_PATTERN = /@mozmail\.com$/i;
356
357
  var ENCODED_WORD_PATTERN = /=\?([^?]+)\?([BbQq])\?([^?]*)\?=/g;
357
358
  var EmailParser = class {
358
359
  parseEmail(raw) {
@@ -375,11 +376,14 @@ var EmailParser = class {
375
376
  extractRelayAlias(raw) {
376
377
  try {
377
378
  const headers = this.parseHeaders(raw);
378
- const toHeader = headers.get("to");
379
- if (!toHeader) return null;
380
- const decodedTo = this.decodeHeader(toHeader);
381
- const matches = decodedTo.match(MOZMAIL_PATTERN);
382
- return matches && matches.length > 0 ? matches[0].toLowerCase() : null;
379
+ const fromAddresses = this.extractHeaderEmails(headers.get("from"));
380
+ const toAddresses = this.extractHeaderEmails(headers.get("to"));
381
+ const allAddresses = [...fromAddresses, ...toAddresses];
382
+ const mozmailAddress = allAddresses.find(
383
+ (address) => MOZMAIL_SUFFIX_PATTERN.test(address)
384
+ );
385
+ if (mozmailAddress) return mozmailAddress;
386
+ return toAddresses[0] ?? null;
383
387
  } catch {
384
388
  return null;
385
389
  }
@@ -442,6 +446,12 @@ var EmailParser = class {
442
446
  const emailMatch = decoded.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/);
443
447
  return emailMatch ? emailMatch[0].toLowerCase() : decoded.trim().toLowerCase();
444
448
  }
449
+ extractHeaderEmails(headerValue) {
450
+ if (!headerValue) return [];
451
+ const decoded = this.decodeHeader(headerValue);
452
+ const matches = decoded.match(EMAIL_PATTERN);
453
+ return matches ? matches.map((match) => match.toLowerCase()) : [];
454
+ }
445
455
  extractMessageId(headerValue) {
446
456
  if (!headerValue) return `<generated-${Date.now()}@relay-temp-mail>`;
447
457
  const cleaned = headerValue.replace(/[<>]/g, "").trim();
@@ -594,7 +604,7 @@ var RelayClient = class {
594
604
  if (aliasAddress) {
595
605
  const normalizedAlias = aliasAddress.toLowerCase();
596
606
  return parsedEmails.filter(
597
- (email) => email.relayAlias?.toLowerCase() === normalizedAlias
607
+ (email) => email.relayAlias?.toLowerCase() === normalizedAlias || email.address.toLowerCase() === normalizedAlias
598
608
  );
599
609
  }
600
610
  return parsedEmails;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/cf-api.ts","../src/http.ts","../src/parser.ts","../src/relay-api.ts","../src/client.ts"],"sourcesContent":["/**\n * relay-temp-mail\n * \n * A JavaScript/TypeScript package for managing Firefox Relay email aliases\n * and retrieving temporary emails via the CloudFlare temp email API.\n */\n\n// Re-export types from types.ts\nexport type {\n RelayConfig,\n RelayAlias,\n Email,\n ParsedEmail,\n ListAliasesOptions,\n GetEmailsOptions,\n CFMailsResponse,\n RelayAddressesResponse,\n CreateAliasResponse,\n} from './types.js';\n\n// Re-export error classes from errors.ts\nexport {\n RelayTempMailError,\n NetworkError,\n AuthError,\n NotFoundError,\n ParseError,\n RateLimitError,\n} from './errors.js';\n\n// Re-export main class from client.ts\nexport { RelayClient } from './client.js';\n","/**\n * Custom error classes for the relay-temp-mail package.\n *\n * These errors provide structured error information including error codes,\n * HTTP status codes, and response data for better error handling.\n */\n\n/**\n * Base error class for all relay-temp-mail errors.\n *\n * Extends the built-in Error class with additional context about the error,\n * including an error code for programmatic error handling and optional\n * response data from the API.\n */\nexport class RelayTempMailError extends Error {\n /**\n * Machine-readable error code for programmatic error handling.\n * Examples: 'NETWORK_ERROR', 'AUTH_ERROR', 'NOT_FOUND'\n */\n code: string;\n\n /**\n * HTTP status code associated with this error, if applicable.\n */\n statusCode?: number;\n\n /**\n * Raw response data from the API, if available.\n */\n response?: any;\n\n /**\n * Creates a new RelayTempMailError instance.\n *\n * @param message - Human-readable error message describing the error.\n * @param code - Machine-readable error code (e.g., 'UNKNOWN_ERROR').\n * @param statusCode - Optional HTTP status code associated with the error.\n * @param response - Optional raw response data from the API.\n */\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n response?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.statusCode = statusCode;\n this.response = response;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error for network-related failures.\n *\n * Thrown when there is a problem establishing or maintaining a network\n * connection, such as DNS resolution failures, connection timeouts,\n * or network unreachability.\n */\nexport class NetworkError extends RelayTempMailError {\n code = 'NETWORK_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NETWORK_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for authentication and authorization failures.\n *\n * Thrown when API requests fail due to invalid or missing credentials\n * (401) or when the authenticated user lacks permission for the\n * requested operation (403).\n */\nexport class AuthError extends RelayTempMailError {\n code = 'AUTH_ERROR' as const;\n\n constructor(message: string, statusCode?: number, response?: any) {\n super(message, 'AUTH_ERROR', statusCode, response);\n }\n}\n\n/**\n * Error for resource not found errors.\n *\n * Thrown when the requested resource does not exist (404 response),\n * such as when trying to access a non-existent alias or email.\n */\nexport class NotFoundError extends RelayTempMailError {\n code = 'NOT_FOUND' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NOT_FOUND', 404, response);\n }\n}\n\n/**\n * Error for MIME message parsing failures.\n *\n * Thrown when there is an error parsing email MIME content,\n * such as malformed headers or invalid message structure.\n */\nexport class ParseError extends RelayTempMailError {\n code = 'PARSE_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'PARSE_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for rate limiting responses.\n *\n * Thrown when the API rate limit has been exceeded (429 response).\n * The client should wait and retry the request after the indicated\n * cooldown period.\n */\nexport class RateLimitError extends RelayTempMailError {\n code = 'RATE_LIMIT_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'RATE_LIMIT_ERROR', 429, response);\n }\n}\n","/**\n * CloudFlare temp email API client.\n *\n * This module provides the CFEmailClient class for interacting with the\n * CloudFlare temp email API to retrieve emails.\n */\n\nimport { Email, CFMailsResponse } from './types.js';\nimport { AuthError, NetworkError, NotFoundError, RateLimitError, RelayTempMailError } from './errors.js';\n\n/**\n * HTTP client interface for making requests.\n *\n * This interface allows for dependency injection, making testing easier\n * by allowing mock implementations.\n */\nexport interface HttpClient {\n /**\n * Makes an HTTP GET request.\n *\n * @param url - The URL to request\n * @param options - Request options including headers\n * @returns The response body as unknown\n */\n get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown>;\n}\n\n/**\n * Default HTTP client implementation using fetch.\n */\nclass DefaultHttpClient implements HttpClient {\n async get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown> {\n const response = await fetch(url, {\n method: 'GET',\n headers: options?.headers,\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new RelayTempMailError(\n `HTTP ${response.status}: ${errorBody}`,\n 'HTTP_ERROR',\n response.status,\n errorBody\n );\n }\n\n return response.json();\n }\n}\n\n/**\n * Raw email response from CF API (snake_case properties).\n */\ninterface CFRawEmail {\n id: number;\n message_id: string;\n source: string;\n address: string;\n raw: string;\n metadata: any | null;\n created_at: string;\n}\n\n/**\n * Raw API response structure.\n */\ninterface CFRawResponse {\n results: CFRawEmail[];\n count: number;\n}\n\n/**\n * Client for interacting with the CloudFlare temp email API.\n *\n * This client handles authentication, request formatting, and response\n * mapping from the CF API's snake_case to camelCase.\n */\nexport class CFEmailClient {\n private readonly apiUrl: string;\n private readonly token: string;\n private readonly httpClient: HttpClient;\n\n /**\n * Creates a new CFEmailClient instance.\n *\n * @param apiUrl - Base URL for the CF temp email API\n * @param token - Bearer token for authentication\n * @param httpClient - Optional HTTP client (defaults to fetch-based implementation)\n */\n constructor(apiUrl: string, token: string, httpClient?: HttpClient) {\n this.apiUrl = apiUrl;\n this.token = token;\n this.httpClient = httpClient ?? new DefaultHttpClient();\n }\n\n /**\n * Retrieves emails from the CF temp email API.\n *\n * @param limit - Maximum number of emails to return (default: 20)\n * @param offset - Pagination offset (default: 0)\n * @returns Promise resolving to an array of Email objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n * @throws NotFoundError if the endpoint doesn't exist\n * @throws RateLimitError if rate limited\n */\n async getMails(limit: number = 20, offset: number = 0): Promise<Email[]> {\n const url = new URL(`${this.apiUrl}/api/mails`);\n url.searchParams.set('limit', String(limit));\n url.searchParams.set('offset', String(offset));\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.token}`,\n };\n\n try {\n const response = await this.httpClient.get(url.toString(), { headers });\n return this.mapCFResponse(response as CFRawResponse);\n } catch (error) {\n throw this.handleError(error);\n }\n }\n\n /**\n * Maps the raw CF API response to the Email interface.\n *\n * Converts snake_case property names to camelCase.\n *\n * @param response - Raw response from CF API\n * @returns Array of Email objects\n */\n private mapCFResponse(response: CFRawResponse): Email[] {\n return response.results.map((item): Email => ({\n id: item.id,\n messageId: item.message_id,\n source: item.source,\n address: item.address,\n raw: item.raw,\n metadata: item.metadata,\n createdAt: item.created_at,\n }));\n }\n\n /**\n * Handles errors from HTTP requests.\n *\n * Maps HTTP errors to appropriate error classes.\n *\n * @param error - The caught error\n * @returns Appropriate RelayTempMailError subclass\n */\n private handleError(error: unknown): RelayTempMailError {\n if (error instanceof RelayTempMailError) {\n const statusCode = error.statusCode;\n\n if (statusCode === 401 || statusCode === 403) {\n return new AuthError(error.message, statusCode, error.response);\n }\n if (statusCode === 404) {\n return new NotFoundError(error.message, error.response);\n }\n if (statusCode === 429) {\n return new RateLimitError(error.message, error.response);\n }\n\n return error;\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError(error.message);\n }\n\n if (error instanceof Error) {\n return new NetworkError(error.message);\n }\n\n return new RelayTempMailError(\n 'Unknown error occurred',\n 'UNKNOWN_ERROR',\n undefined,\n error\n );\n }\n}\n","/**\n * HTTP client utilities for the relay-temp-mail package.\n *\n * This module provides a configurable HTTP client with timeout support,\n * automatic retry logic, and proper error classification for API responses.\n */\n\nimport {\n RelayTempMailError,\n NetworkError,\n AuthError,\n NotFoundError,\n RateLimitError,\n} from './errors';\n\n/**\n * Options for individual HTTP requests.\n */\nexport interface RequestOptions {\n /** Custom headers to include in the request */\n headers?: Record<string, string>;\n\n /** Request body (will be JSON serialized) */\n body?: unknown;\n\n /** Request timeout in milliseconds (overrides client default) */\n timeout?: number;\n\n /** Number of retries on failure (overrides client default) */\n retries?: number;\n}\n\n/**\n * HTTP client for making requests to the relay-temp-mail API.\n *\n * Provides a configurable base URL with timeout, retry, and automatic\n * JSON parsing capabilities.\n */\nexport class HttpClient {\n private baseUrl: string;\n private defaultTimeout: number;\n private defaultRetries: number;\n\n /**\n * Creates a new HttpClient instance.\n *\n * @param baseUrl - Base URL for all requests (e.g., 'https://api.example.com')\n * @param defaultTimeout - Default timeout in milliseconds (default: 30000)\n * @param defaultRetries - Default number of retries on failure (default: 0)\n */\n constructor(\n baseUrl: string,\n defaultTimeout: number = 30000,\n defaultRetries: number = 0\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.defaultTimeout = defaultTimeout;\n this.defaultRetries = defaultRetries;\n }\n\n /**\n * Makes an HTTP request to the specified path.\n *\n * @param method - HTTP method (GET, POST, PUT, DELETE, etc.)\n * @param path - API path (will be appended to baseUrl)\n * @param options - Optional request configuration\n * @returns Promise resolving to the parsed JSON response\n */\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const timeout = options.timeout ?? this.defaultTimeout;\n const retries = options.retries ?? this.defaultRetries;\n\n let lastError: RelayTempMailError | Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const response = await this.executeRequest(method, path, options, timeout);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n\n // Check if we should retry\n if (attempt < retries && this.shouldRetry(error)) {\n const delay = 1000 * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n\n // Don't retry, throw the classified error\n if (error instanceof RelayTempMailError) {\n throw error;\n }\n\n // Classify the error if not already classified\n throw this.classifyError(error);\n }\n }\n\n // This should never be reached, but just in case\n throw lastError || new NetworkError('Request failed');\n }\n\n /**\n * Executes the actual HTTP request with timeout support.\n */\n private async executeRequest(\n method: string,\n path: string,\n options: RequestOptions,\n timeout: number\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n signal: controller.signal,\n };\n\n if (options.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Handles the HTTP response, parsing JSON and checking for errors.\n */\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n throw this.classifyError(new Error(`HTTP ${response.status}`), response);\n }\n\n const text = await response.text();\n\n // Handle empty responses\n if (!text) {\n return {} as T;\n }\n\n return JSON.parse(text) as T;\n }\n\n /**\n * Classifies an error based on the error type and HTTP response.\n */\n private classifyError(error: unknown, response?: Response): RelayTempMailError {\n // Network errors (fetch failed)\n if (error instanceof Error && error.name === 'AbortError') {\n return new NetworkError('Request timed out');\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError('Network request failed');\n }\n\n if (error instanceof Error && error.message.includes('Failed to fetch')) {\n return new NetworkError('Network request failed');\n }\n\n // HTTP status-based classification\n if (response) {\n const status = response.status;\n\n if (status === 401 || status === 403) {\n return new AuthError(\n `Authentication failed: ${response.statusText}`,\n status\n );\n }\n\n if (status === 404) {\n return new NotFoundError(`Resource not found: ${response.statusText}`);\n }\n\n if (status === 429) {\n return new RateLimitError(\n `Rate limit exceeded: ${response.statusText}`\n );\n }\n\n if (status >= 500) {\n return new NetworkError(\n `Server error: ${response.statusText}`,\n status\n );\n }\n }\n\n // Default error\n if (error instanceof Error) {\n return new RelayTempMailError(\n error.message,\n 'REQUEST_ERROR',\n response?.status\n );\n }\n\n return new RelayTempMailError('Unknown error occurred', 'UNKNOWN_ERROR');\n }\n\n /**\n * Determines if a request should be retried based on the error.\n */\n private shouldRetry(error: unknown): boolean {\n if (error instanceof NetworkError) {\n return true;\n }\n\n if (error instanceof RelayTempMailError && error.statusCode) {\n return error.statusCode >= 500;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n return true;\n }\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Sleep for a specified duration.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/**\n * MIME email parser for extracting Firefox Relay alias information.\n */\nimport type { ParsedEmail } from './types.js';\n\nconst MOZMAIL_PATTERN = /[a-zA-Z0-9]+@mozmail\\.com/g;\nconst ENCODED_WORD_PATTERN = /=\\?([^?]+)\\?([BbQq])\\?([^?]*)\\?=/g;\n\n/**\n * EmailParser class for parsing MIME email content.\n */\nexport class EmailParser {\n parseEmail(raw: string): ParsedEmail {\n const headers = this.parseHeaders(raw);\n const toHeader = headers.get('to') || '';\n const fromHeader = headers.get('from') || '';\n const messageIdHeader = headers.get('message-id') || '';\n const relayAlias = this.extractRelayAlias(raw);\n \n return {\n id: 0,\n messageId: this.extractMessageId(messageIdHeader),\n source: this.extractEmailAddress(fromHeader),\n address: this.extractEmailAddress(toHeader),\n raw,\n metadata: null,\n createdAt: new Date().toISOString(),\n relayAlias: relayAlias || undefined,\n };\n }\n\n extractRelayAlias(raw: string): string | null {\n try {\n const headers = this.parseHeaders(raw);\n const toHeader = headers.get('to');\n if (!toHeader) return null;\n \n const decodedTo = this.decodeHeader(toHeader);\n const matches = decodedTo.match(MOZMAIL_PATTERN);\n return matches && matches.length > 0 ? matches[0].toLowerCase() : null;\n } catch {\n return null;\n }\n }\n\n private parseHeaders(raw: string): Map<string, string> {\n const headers = new Map<string, string>();\n const headerEnd = raw.indexOf('\\r\\n\\r\\n');\n const headerSection = headerEnd === -1 ? raw : raw.substring(0, headerEnd);\n const lines = headerSection.split(/\\r?\\n/);\n let currentHeader: string | null = null;\n let currentValue = '';\n \n for (const line of lines) {\n if (/^\\s/.test(line)) {\n if (currentHeader) currentValue += ' ' + line.trim();\n } else {\n if (currentHeader) headers.set(currentHeader, currentValue);\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n currentHeader = line.substring(0, colonIndex).toLowerCase().trim();\n currentValue = line.substring(colonIndex + 1).trim();\n } else {\n currentHeader = null;\n currentValue = '';\n }\n }\n }\n if (currentHeader) headers.set(currentHeader, currentValue);\n return headers;\n }\n\n private decodeHeader(value: string): string {\n return value.replace(ENCODED_WORD_PATTERN, (_, charset, encoding, encoded) => {\n try {\n if (encoding.toUpperCase() === 'Q') {\n return this.decodeQuotedPrintable(encoded);\n } else if (encoding.toUpperCase() === 'B') {\n return this.decodeBase64(encoded);\n }\n return encoded;\n } catch {\n return encoded;\n }\n });\n }\n\n private decodeQuotedPrintable(encoded: string): string {\n // RFC 2047: underscores represent spaces in encoded-word\n let decoded = encoded.replace(/_/g, ' ');\n decoded = decoded.replace(/=([0-9A-Fa-f]{2})/g, (_, hex) => \n String.fromCharCode(parseInt(hex, 16))\n );\n return decoded;\n }\n\n private decodeBase64(encoded: string): string {\n return Buffer.from(encoded, 'base64').toString('utf-8');\n }\n\n private extractEmailAddress(headerValue: string): string {\n if (!headerValue) return '';\n const decoded = this.decodeHeader(headerValue);\n const bracketMatch = decoded.match(/<([^>]+)>/);\n if (bracketMatch) return bracketMatch[1].trim().toLowerCase();\n const emailMatch = decoded.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/);\n return emailMatch ? emailMatch[0].toLowerCase() : decoded.trim().toLowerCase();\n }\n\n private extractMessageId(headerValue: string): string {\n if (!headerValue) return `<generated-${Date.now()}@relay-temp-mail>`;\n const cleaned = headerValue.replace(/[<>]/g, '').trim();\n return `<${cleaned}>`;\n }\n}\n","import { HttpClient } from './http';\nimport { RelayAlias } from './types';\n\ninterface RawAliasResponse {\n id: number;\n address: string;\n full_address: string;\n enabled: boolean;\n created_at: string;\n domain: number;\n mask_type: string;\n description?: string;\n num_forwarded?: number;\n num_blocked?: number;\n last_modified_at?: string;\n last_used_at?: string | null;\n num_level_one_trackers_blocked?: number;\n num_replied?: number;\n num_spam?: number;\n block_list_emails?: boolean;\n generated_for?: string;\n used_on?: string | null;\n}\n\nexport class RelayAPIClient {\n private csrfToken: string;\n private sessionId: string;\n private httpClient: HttpClient;\n\n constructor(\n csrfToken: string,\n sessionId: string,\n httpClient?: HttpClient\n ) {\n this.csrfToken = csrfToken;\n this.sessionId = sessionId;\n this.httpClient = httpClient ?? new HttpClient('https://relay.firefox.com');\n }\n\n private getAuthHeaders(): Record<string, string> {\n return {\n 'Origin': 'https://relay.firefox.com',\n 'Referer': 'https://relay.firefox.com/accounts/profile/?',\n 'Accept': 'application/json',\n 'X-CSRFToken': this.csrfToken,\n 'Cookie': `sessionid=${this.sessionId}; csrftoken=${this.csrfToken}`,\n };\n }\n\n async getAliases(): Promise<RelayAlias[]> {\n const response = await this.httpClient.request<RawAliasResponse[]>(\n 'GET',\n '/api/v1/relayaddresses/',\n { headers: this.getAuthHeaders() }\n );\n\n return response.map((item) => this.mapAliasResponse(item));\n }\n\n async createAlias(): Promise<RelayAlias> {\n const response = await this.httpClient.request<RawAliasResponse>(\n 'POST',\n '/api/v1/relayaddresses/',\n {\n headers: this.getAuthHeaders(),\n body: { enabled: true },\n }\n );\n\n return this.mapAliasResponse(response);\n }\n\n async deleteAlias(id: number): Promise<void> {\n await this.httpClient.request<void>(\n 'DELETE',\n `/api/v1/relayaddresses/${id}/`,\n { headers: this.getAuthHeaders() }\n );\n }\n\n private mapAliasResponse(data: RawAliasResponse): RelayAlias {\n return {\n id: data.id,\n address: data.address,\n fullAddress: data.full_address,\n enabled: data.enabled,\n createdAt: data.created_at,\n domain: data.domain,\n maskType: data.mask_type,\n description: data.description,\n numForwarded: data.num_forwarded,\n numBlocked: data.num_blocked,\n lastModifiedAt: data.last_modified_at,\n lastUsedAt: data.last_used_at,\n numLevelOneTrackersBlocked: data.num_level_one_trackers_blocked,\n numReplied: data.num_replied,\n numSpam: data.num_spam,\n blockListEmails: data.block_list_emails,\n generatedFor: data.generated_for,\n usedOn: data.used_on,\n };\n }\n}\n","/**\n * Main client for the relay-temp-mail package.\n *\n * This module provides the RelayClient class which integrates all components\n * (CF API, Relay API, Parser) into a unified interface.\n */\n\nimport { CFEmailClient } from './cf-api.js';\nimport { HttpClient } from './http.js';\nimport { EmailParser } from './parser.js';\nimport { RelayAPIClient } from './relay-api.js';\nimport type {\n RelayConfig,\n RelayAlias,\n ParsedEmail,\n GetEmailsOptions,\n} from './types.js';\n\n/**\n * Main client for interacting with Firefox Relay and CloudFlare temp email services.\n *\n * RelayClient integrates all components to provide a unified interface for:\n * - Managing Firefox Relay email aliases\n * - Retrieving and parsing emails from CloudFlare temp email API\n *\n * @example\n * ```typescript\n * const client = new RelayClient({\n * csrfToken: '...',\n * sessionId: '...',\n * cfApiUrl: 'https://...',\n * cfToken: '...',\n * timeout: 30000\n * });\n *\n * const aliases = await client.listAliases();\n * const emails = await client.getEmails('alias@mozmail.com', { limit: 10 });\n * ```\n */\nexport class RelayClient {\n private readonly relayApi: RelayAPIClient;\n private readonly cfApi: CFEmailClient;\n private readonly parser: EmailParser;\n\n /**\n * Creates a new RelayClient instance.\n *\n * @param config - Configuration object containing authentication tokens and API URLs\n */\n constructor(config: RelayConfig) {\n const timeout = config.timeout ?? 30000;\n\n const relayHttpClient = new HttpClient('https://relay.firefox.com', timeout);\n this.relayApi = new RelayAPIClient(\n config.csrfToken,\n config.sessionId,\n relayHttpClient\n );\n\n this.cfApi = new CFEmailClient(config.cfApiUrl, config.cfToken);\n this.parser = new EmailParser();\n }\n\n /**\n * Lists all Firefox Relay email aliases.\n *\n * @returns Promise resolving to an array of RelayAlias objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async listAliases(): Promise<RelayAlias[]> {\n return this.relayApi.getAliases();\n }\n\n /**\n * Creates a new Firefox Relay email alias.\n *\n * @returns Promise resolving to the newly created RelayAlias\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async createAlias(): Promise<RelayAlias> {\n return this.relayApi.createAlias();\n }\n\n /**\n * Deletes a Firefox Relay email alias.\n *\n * @param id - The ID of the alias to delete\n * @throws AuthError if authentication fails\n * @throws NotFoundError if the alias doesn't exist\n * @throws NetworkError if there's a network problem\n */\n async deleteAlias(id: number): Promise<void> {\n return this.relayApi.deleteAlias(id);\n }\n\n /**\n * Retrieves and parses emails from the CloudFlare temp email API.\n *\n * If aliasAddress is provided, only emails sent to that address are returned.\n *\n * @param aliasAddress - Optional email address to filter by\n * @param options - Query options for pagination\n * @returns Promise resolving to an array of ParsedEmail objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async getEmails(\n aliasAddress?: string,\n options?: GetEmailsOptions\n ): Promise<ParsedEmail[]> {\n const limit = options?.limit ?? 20;\n const offset = options?.offset ?? 0;\n\n const emails = await this.cfApi.getMails(limit, offset);\n\n const parsedEmails: ParsedEmail[] = emails.map((email) => {\n const parsed = this.parser.parseEmail(email.raw);\n return {\n ...parsed,\n id: email.id,\n messageId: email.messageId,\n source: email.source,\n address: email.address,\n createdAt: email.createdAt,\n metadata: email.metadata,\n };\n });\n\n if (aliasAddress) {\n const normalizedAlias = aliasAddress.toLowerCase();\n return parsedEmails.filter(\n (email) => email.relayAlias?.toLowerCase() === normalizedAlias\n );\n }\n\n return parsedEmails;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/cf-api.ts","../src/http.ts","../src/parser.ts","../src/relay-api.ts","../src/client.ts"],"sourcesContent":["/**\n * relay-temp-mail\n * \n * A JavaScript/TypeScript package for managing Firefox Relay email aliases\n * and retrieving temporary emails via the CloudFlare temp email API.\n */\n\n// Re-export types from types.ts\nexport type {\n RelayConfig,\n RelayAlias,\n Email,\n ParsedEmail,\n ListAliasesOptions,\n GetEmailsOptions,\n CFMailsResponse,\n RelayAddressesResponse,\n CreateAliasResponse,\n} from './types.js';\n\n// Re-export error classes from errors.ts\nexport {\n RelayTempMailError,\n NetworkError,\n AuthError,\n NotFoundError,\n ParseError,\n RateLimitError,\n} from './errors.js';\n\n// Re-export main class from client.ts\nexport { RelayClient } from './client.js';\n","/**\n * Custom error classes for the relay-temp-mail package.\n *\n * These errors provide structured error information including error codes,\n * HTTP status codes, and response data for better error handling.\n */\n\n/**\n * Base error class for all relay-temp-mail errors.\n *\n * Extends the built-in Error class with additional context about the error,\n * including an error code for programmatic error handling and optional\n * response data from the API.\n */\nexport class RelayTempMailError extends Error {\n /**\n * Machine-readable error code for programmatic error handling.\n * Examples: 'NETWORK_ERROR', 'AUTH_ERROR', 'NOT_FOUND'\n */\n code: string;\n\n /**\n * HTTP status code associated with this error, if applicable.\n */\n statusCode?: number;\n\n /**\n * Raw response data from the API, if available.\n */\n response?: any;\n\n /**\n * Creates a new RelayTempMailError instance.\n *\n * @param message - Human-readable error message describing the error.\n * @param code - Machine-readable error code (e.g., 'UNKNOWN_ERROR').\n * @param statusCode - Optional HTTP status code associated with the error.\n * @param response - Optional raw response data from the API.\n */\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n response?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.statusCode = statusCode;\n this.response = response;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error for network-related failures.\n *\n * Thrown when there is a problem establishing or maintaining a network\n * connection, such as DNS resolution failures, connection timeouts,\n * or network unreachability.\n */\nexport class NetworkError extends RelayTempMailError {\n code = 'NETWORK_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NETWORK_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for authentication and authorization failures.\n *\n * Thrown when API requests fail due to invalid or missing credentials\n * (401) or when the authenticated user lacks permission for the\n * requested operation (403).\n */\nexport class AuthError extends RelayTempMailError {\n code = 'AUTH_ERROR' as const;\n\n constructor(message: string, statusCode?: number, response?: any) {\n super(message, 'AUTH_ERROR', statusCode, response);\n }\n}\n\n/**\n * Error for resource not found errors.\n *\n * Thrown when the requested resource does not exist (404 response),\n * such as when trying to access a non-existent alias or email.\n */\nexport class NotFoundError extends RelayTempMailError {\n code = 'NOT_FOUND' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NOT_FOUND', 404, response);\n }\n}\n\n/**\n * Error for MIME message parsing failures.\n *\n * Thrown when there is an error parsing email MIME content,\n * such as malformed headers or invalid message structure.\n */\nexport class ParseError extends RelayTempMailError {\n code = 'PARSE_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'PARSE_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for rate limiting responses.\n *\n * Thrown when the API rate limit has been exceeded (429 response).\n * The client should wait and retry the request after the indicated\n * cooldown period.\n */\nexport class RateLimitError extends RelayTempMailError {\n code = 'RATE_LIMIT_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'RATE_LIMIT_ERROR', 429, response);\n }\n}\n","/**\n * CloudFlare temp email API client.\n *\n * This module provides the CFEmailClient class for interacting with the\n * CloudFlare temp email API to retrieve emails.\n */\n\nimport { Email, CFMailsResponse } from './types.js';\nimport { AuthError, NetworkError, NotFoundError, RateLimitError, RelayTempMailError } from './errors.js';\n\n/**\n * HTTP client interface for making requests.\n *\n * This interface allows for dependency injection, making testing easier\n * by allowing mock implementations.\n */\nexport interface HttpClient {\n /**\n * Makes an HTTP GET request.\n *\n * @param url - The URL to request\n * @param options - Request options including headers\n * @returns The response body as unknown\n */\n get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown>;\n}\n\n/**\n * Default HTTP client implementation using fetch.\n */\nclass DefaultHttpClient implements HttpClient {\n async get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown> {\n const response = await fetch(url, {\n method: 'GET',\n headers: options?.headers,\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new RelayTempMailError(\n `HTTP ${response.status}: ${errorBody}`,\n 'HTTP_ERROR',\n response.status,\n errorBody\n );\n }\n\n return response.json();\n }\n}\n\n/**\n * Raw email response from CF API (snake_case properties).\n */\ninterface CFRawEmail {\n id: number;\n message_id: string;\n source: string;\n address: string;\n raw: string;\n metadata: any | null;\n created_at: string;\n}\n\n/**\n * Raw API response structure.\n */\ninterface CFRawResponse {\n results: CFRawEmail[];\n count: number;\n}\n\n/**\n * Client for interacting with the CloudFlare temp email API.\n *\n * This client handles authentication, request formatting, and response\n * mapping from the CF API's snake_case to camelCase.\n */\nexport class CFEmailClient {\n private readonly apiUrl: string;\n private readonly token: string;\n private readonly httpClient: HttpClient;\n\n /**\n * Creates a new CFEmailClient instance.\n *\n * @param apiUrl - Base URL for the CF temp email API\n * @param token - Bearer token for authentication\n * @param httpClient - Optional HTTP client (defaults to fetch-based implementation)\n */\n constructor(apiUrl: string, token: string, httpClient?: HttpClient) {\n this.apiUrl = apiUrl.replace(/\\/+$/, '');\n this.token = token;\n this.httpClient = httpClient ?? new DefaultHttpClient();\n }\n\n /**\n * Retrieves emails from the CF temp email API.\n *\n * @param limit - Maximum number of emails to return (default: 20)\n * @param offset - Pagination offset (default: 0)\n * @returns Promise resolving to an array of Email objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n * @throws NotFoundError if the endpoint doesn't exist\n * @throws RateLimitError if rate limited\n */\n async getMails(limit: number = 20, offset: number = 0): Promise<Email[]> {\n const url = new URL(`${this.apiUrl}/api/mails`);\n url.searchParams.set('limit', String(limit));\n url.searchParams.set('offset', String(offset));\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.token}`,\n };\n\n try {\n const response = await this.httpClient.get(url.toString(), { headers });\n return this.mapCFResponse(response as CFRawResponse);\n } catch (error) {\n throw this.handleError(error);\n }\n }\n\n /**\n * Maps the raw CF API response to the Email interface.\n *\n * Converts snake_case property names to camelCase.\n *\n * @param response - Raw response from CF API\n * @returns Array of Email objects\n */\n private mapCFResponse(response: CFRawResponse): Email[] {\n return response.results.map((item): Email => ({\n id: item.id,\n messageId: item.message_id,\n source: item.source,\n address: item.address,\n raw: item.raw,\n metadata: item.metadata,\n createdAt: item.created_at,\n }));\n }\n\n /**\n * Handles errors from HTTP requests.\n *\n * Maps HTTP errors to appropriate error classes.\n *\n * @param error - The caught error\n * @returns Appropriate RelayTempMailError subclass\n */\n private handleError(error: unknown): RelayTempMailError {\n if (error instanceof RelayTempMailError) {\n const statusCode = error.statusCode;\n\n if (statusCode === 401 || statusCode === 403) {\n return new AuthError(error.message, statusCode, error.response);\n }\n if (statusCode === 404) {\n return new NotFoundError(error.message, error.response);\n }\n if (statusCode === 429) {\n return new RateLimitError(error.message, error.response);\n }\n\n return error;\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError(error.message);\n }\n\n if (error instanceof Error) {\n return new NetworkError(error.message);\n }\n\n return new RelayTempMailError(\n 'Unknown error occurred',\n 'UNKNOWN_ERROR',\n undefined,\n error\n );\n }\n}\n","/**\n * HTTP client utilities for the relay-temp-mail package.\n *\n * This module provides a configurable HTTP client with timeout support,\n * automatic retry logic, and proper error classification for API responses.\n */\n\nimport {\n RelayTempMailError,\n NetworkError,\n AuthError,\n NotFoundError,\n RateLimitError,\n} from './errors';\n\n/**\n * Options for individual HTTP requests.\n */\nexport interface RequestOptions {\n /** Custom headers to include in the request */\n headers?: Record<string, string>;\n\n /** Request body (will be JSON serialized) */\n body?: unknown;\n\n /** Request timeout in milliseconds (overrides client default) */\n timeout?: number;\n\n /** Number of retries on failure (overrides client default) */\n retries?: number;\n}\n\n/**\n * HTTP client for making requests to the relay-temp-mail API.\n *\n * Provides a configurable base URL with timeout, retry, and automatic\n * JSON parsing capabilities.\n */\nexport class HttpClient {\n private baseUrl: string;\n private defaultTimeout: number;\n private defaultRetries: number;\n\n /**\n * Creates a new HttpClient instance.\n *\n * @param baseUrl - Base URL for all requests (e.g., 'https://api.example.com')\n * @param defaultTimeout - Default timeout in milliseconds (default: 30000)\n * @param defaultRetries - Default number of retries on failure (default: 0)\n */\n constructor(\n baseUrl: string,\n defaultTimeout: number = 30000,\n defaultRetries: number = 0\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.defaultTimeout = defaultTimeout;\n this.defaultRetries = defaultRetries;\n }\n\n /**\n * Makes an HTTP request to the specified path.\n *\n * @param method - HTTP method (GET, POST, PUT, DELETE, etc.)\n * @param path - API path (will be appended to baseUrl)\n * @param options - Optional request configuration\n * @returns Promise resolving to the parsed JSON response\n */\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const timeout = options.timeout ?? this.defaultTimeout;\n const retries = options.retries ?? this.defaultRetries;\n\n let lastError: RelayTempMailError | Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const response = await this.executeRequest(method, path, options, timeout);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n\n // Check if we should retry\n if (attempt < retries && this.shouldRetry(error)) {\n const delay = 1000 * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n\n // Don't retry, throw the classified error\n if (error instanceof RelayTempMailError) {\n throw error;\n }\n\n // Classify the error if not already classified\n throw this.classifyError(error);\n }\n }\n\n // This should never be reached, but just in case\n throw lastError || new NetworkError('Request failed');\n }\n\n /**\n * Executes the actual HTTP request with timeout support.\n */\n private async executeRequest(\n method: string,\n path: string,\n options: RequestOptions,\n timeout: number\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n signal: controller.signal,\n };\n\n if (options.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Handles the HTTP response, parsing JSON and checking for errors.\n */\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n throw this.classifyError(new Error(`HTTP ${response.status}`), response);\n }\n\n const text = await response.text();\n\n // Handle empty responses\n if (!text) {\n return {} as T;\n }\n\n return JSON.parse(text) as T;\n }\n\n /**\n * Classifies an error based on the error type and HTTP response.\n */\n private classifyError(error: unknown, response?: Response): RelayTempMailError {\n // Network errors (fetch failed)\n if (error instanceof Error && error.name === 'AbortError') {\n return new NetworkError('Request timed out');\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError('Network request failed');\n }\n\n if (error instanceof Error && error.message.includes('Failed to fetch')) {\n return new NetworkError('Network request failed');\n }\n\n // HTTP status-based classification\n if (response) {\n const status = response.status;\n\n if (status === 401 || status === 403) {\n return new AuthError(\n `Authentication failed: ${response.statusText}`,\n status\n );\n }\n\n if (status === 404) {\n return new NotFoundError(`Resource not found: ${response.statusText}`);\n }\n\n if (status === 429) {\n return new RateLimitError(\n `Rate limit exceeded: ${response.statusText}`\n );\n }\n\n if (status >= 500) {\n return new NetworkError(\n `Server error: ${response.statusText}`,\n status\n );\n }\n }\n\n // Default error\n if (error instanceof Error) {\n return new RelayTempMailError(\n error.message,\n 'REQUEST_ERROR',\n response?.status\n );\n }\n\n return new RelayTempMailError('Unknown error occurred', 'UNKNOWN_ERROR');\n }\n\n /**\n * Determines if a request should be retried based on the error.\n */\n private shouldRetry(error: unknown): boolean {\n if (error instanceof NetworkError) {\n return true;\n }\n\n if (error instanceof RelayTempMailError && error.statusCode) {\n return error.statusCode >= 500;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n return true;\n }\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Sleep for a specified duration.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/**\n * MIME email parser for extracting Firefox Relay alias information.\n */\nimport type { ParsedEmail } from './types.js';\n\nconst EMAIL_PATTERN = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\nconst MOZMAIL_SUFFIX_PATTERN = /@mozmail\\.com$/i;\nconst ENCODED_WORD_PATTERN = /=\\?([^?]+)\\?([BbQq])\\?([^?]*)\\?=/g;\n\n/**\n * EmailParser class for parsing MIME email content.\n */\nexport class EmailParser {\n parseEmail(raw: string): ParsedEmail {\n const headers = this.parseHeaders(raw);\n const toHeader = headers.get('to') || '';\n const fromHeader = headers.get('from') || '';\n const messageIdHeader = headers.get('message-id') || '';\n const relayAlias = this.extractRelayAlias(raw);\n \n return {\n id: 0,\n messageId: this.extractMessageId(messageIdHeader),\n source: this.extractEmailAddress(fromHeader),\n address: this.extractEmailAddress(toHeader),\n raw,\n metadata: null,\n createdAt: new Date().toISOString(),\n relayAlias: relayAlias || undefined,\n };\n }\n\n extractRelayAlias(raw: string): string | null {\n try {\n const headers = this.parseHeaders(raw);\n const fromAddresses = this.extractHeaderEmails(headers.get('from'));\n const toAddresses = this.extractHeaderEmails(headers.get('to'));\n const allAddresses = [...fromAddresses, ...toAddresses];\n\n const mozmailAddress = allAddresses.find((address) =>\n MOZMAIL_SUFFIX_PATTERN.test(address)\n );\n if (mozmailAddress) return mozmailAddress;\n\n return toAddresses[0] ?? null;\n } catch {\n return null;\n }\n }\n\n private parseHeaders(raw: string): Map<string, string> {\n const headers = new Map<string, string>();\n const headerEnd = raw.indexOf('\\r\\n\\r\\n');\n const headerSection = headerEnd === -1 ? raw : raw.substring(0, headerEnd);\n const lines = headerSection.split(/\\r?\\n/);\n let currentHeader: string | null = null;\n let currentValue = '';\n \n for (const line of lines) {\n if (/^\\s/.test(line)) {\n if (currentHeader) currentValue += ' ' + line.trim();\n } else {\n if (currentHeader) headers.set(currentHeader, currentValue);\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n currentHeader = line.substring(0, colonIndex).toLowerCase().trim();\n currentValue = line.substring(colonIndex + 1).trim();\n } else {\n currentHeader = null;\n currentValue = '';\n }\n }\n }\n if (currentHeader) headers.set(currentHeader, currentValue);\n return headers;\n }\n\n private decodeHeader(value: string): string {\n return value.replace(ENCODED_WORD_PATTERN, (_, charset, encoding, encoded) => {\n try {\n if (encoding.toUpperCase() === 'Q') {\n return this.decodeQuotedPrintable(encoded);\n } else if (encoding.toUpperCase() === 'B') {\n return this.decodeBase64(encoded);\n }\n return encoded;\n } catch {\n return encoded;\n }\n });\n }\n\n private decodeQuotedPrintable(encoded: string): string {\n // RFC 2047: underscores represent spaces in encoded-word\n let decoded = encoded.replace(/_/g, ' ');\n decoded = decoded.replace(/=([0-9A-Fa-f]{2})/g, (_, hex) => \n String.fromCharCode(parseInt(hex, 16))\n );\n return decoded;\n }\n\n private decodeBase64(encoded: string): string {\n return Buffer.from(encoded, 'base64').toString('utf-8');\n }\n\n private extractEmailAddress(headerValue: string): string {\n if (!headerValue) return '';\n const decoded = this.decodeHeader(headerValue);\n const bracketMatch = decoded.match(/<([^>]+)>/);\n if (bracketMatch) return bracketMatch[1].trim().toLowerCase();\n const emailMatch = decoded.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/);\n return emailMatch ? emailMatch[0].toLowerCase() : decoded.trim().toLowerCase();\n }\n\n private extractHeaderEmails(headerValue?: string): string[] {\n if (!headerValue) return [];\n const decoded = this.decodeHeader(headerValue);\n const matches = decoded.match(EMAIL_PATTERN);\n return matches ? matches.map((match) => match.toLowerCase()) : [];\n }\n\n private extractMessageId(headerValue: string): string {\n if (!headerValue) return `<generated-${Date.now()}@relay-temp-mail>`;\n const cleaned = headerValue.replace(/[<>]/g, '').trim();\n return `<${cleaned}>`;\n }\n}\n","import { HttpClient } from './http';\nimport { RelayAlias } from './types';\n\ninterface RawAliasResponse {\n id: number;\n address: string;\n full_address: string;\n enabled: boolean;\n created_at: string;\n domain: number;\n mask_type: string;\n description?: string;\n num_forwarded?: number;\n num_blocked?: number;\n last_modified_at?: string;\n last_used_at?: string | null;\n num_level_one_trackers_blocked?: number;\n num_replied?: number;\n num_spam?: number;\n block_list_emails?: boolean;\n generated_for?: string;\n used_on?: string | null;\n}\n\nexport class RelayAPIClient {\n private csrfToken: string;\n private sessionId: string;\n private httpClient: HttpClient;\n\n constructor(\n csrfToken: string,\n sessionId: string,\n httpClient?: HttpClient\n ) {\n this.csrfToken = csrfToken;\n this.sessionId = sessionId;\n this.httpClient = httpClient ?? new HttpClient('https://relay.firefox.com');\n }\n\n private getAuthHeaders(): Record<string, string> {\n return {\n 'Origin': 'https://relay.firefox.com',\n 'Referer': 'https://relay.firefox.com/accounts/profile/?',\n 'Accept': 'application/json',\n 'X-CSRFToken': this.csrfToken,\n 'Cookie': `sessionid=${this.sessionId}; csrftoken=${this.csrfToken}`,\n };\n }\n\n async getAliases(): Promise<RelayAlias[]> {\n const response = await this.httpClient.request<RawAliasResponse[]>(\n 'GET',\n '/api/v1/relayaddresses/',\n { headers: this.getAuthHeaders() }\n );\n\n return response.map((item) => this.mapAliasResponse(item));\n }\n\n async createAlias(): Promise<RelayAlias> {\n const response = await this.httpClient.request<RawAliasResponse>(\n 'POST',\n '/api/v1/relayaddresses/',\n {\n headers: this.getAuthHeaders(),\n body: { enabled: true },\n }\n );\n\n return this.mapAliasResponse(response);\n }\n\n async deleteAlias(id: number): Promise<void> {\n await this.httpClient.request<void>(\n 'DELETE',\n `/api/v1/relayaddresses/${id}/`,\n { headers: this.getAuthHeaders() }\n );\n }\n\n private mapAliasResponse(data: RawAliasResponse): RelayAlias {\n return {\n id: data.id,\n address: data.address,\n fullAddress: data.full_address,\n enabled: data.enabled,\n createdAt: data.created_at,\n domain: data.domain,\n maskType: data.mask_type,\n description: data.description,\n numForwarded: data.num_forwarded,\n numBlocked: data.num_blocked,\n lastModifiedAt: data.last_modified_at,\n lastUsedAt: data.last_used_at,\n numLevelOneTrackersBlocked: data.num_level_one_trackers_blocked,\n numReplied: data.num_replied,\n numSpam: data.num_spam,\n blockListEmails: data.block_list_emails,\n generatedFor: data.generated_for,\n usedOn: data.used_on,\n };\n }\n}\n","/**\n * Main client for the relay-temp-mail package.\n *\n * This module provides the RelayClient class which integrates all components\n * (CF API, Relay API, Parser) into a unified interface.\n */\n\nimport { CFEmailClient } from './cf-api.js';\nimport { HttpClient } from './http.js';\nimport { EmailParser } from './parser.js';\nimport { RelayAPIClient } from './relay-api.js';\nimport type {\n RelayConfig,\n RelayAlias,\n ParsedEmail,\n GetEmailsOptions,\n} from './types.js';\n\n/**\n * Main client for interacting with Firefox Relay and CloudFlare temp email services.\n *\n * RelayClient integrates all components to provide a unified interface for:\n * - Managing Firefox Relay email aliases\n * - Retrieving and parsing emails from CloudFlare temp email API\n *\n * @example\n * ```typescript\n * const client = new RelayClient({\n * csrfToken: '...',\n * sessionId: '...',\n * cfApiUrl: 'https://...',\n * cfToken: '...',\n * timeout: 30000\n * });\n *\n * const aliases = await client.listAliases();\n * const emails = await client.getEmails('alias@mozmail.com', { limit: 10 });\n * ```\n */\nexport class RelayClient {\n private readonly relayApi: RelayAPIClient;\n private readonly cfApi: CFEmailClient;\n private readonly parser: EmailParser;\n\n /**\n * Creates a new RelayClient instance.\n *\n * @param config - Configuration object containing authentication tokens and API URLs\n */\n constructor(config: RelayConfig) {\n const timeout = config.timeout ?? 30000;\n\n const relayHttpClient = new HttpClient('https://relay.firefox.com', timeout);\n this.relayApi = new RelayAPIClient(\n config.csrfToken,\n config.sessionId,\n relayHttpClient\n );\n\n this.cfApi = new CFEmailClient(config.cfApiUrl, config.cfToken);\n this.parser = new EmailParser();\n }\n\n /**\n * Lists all Firefox Relay email aliases.\n *\n * @returns Promise resolving to an array of RelayAlias objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async listAliases(): Promise<RelayAlias[]> {\n return this.relayApi.getAliases();\n }\n\n /**\n * Creates a new Firefox Relay email alias.\n *\n * @returns Promise resolving to the newly created RelayAlias\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async createAlias(): Promise<RelayAlias> {\n return this.relayApi.createAlias();\n }\n\n /**\n * Deletes a Firefox Relay email alias.\n *\n * @param id - The ID of the alias to delete\n * @throws AuthError if authentication fails\n * @throws NotFoundError if the alias doesn't exist\n * @throws NetworkError if there's a network problem\n */\n async deleteAlias(id: number): Promise<void> {\n return this.relayApi.deleteAlias(id);\n }\n\n /**\n * Retrieves and parses emails from the CloudFlare temp email API.\n *\n * If aliasAddress is provided, only emails sent to that address are returned.\n *\n * @param aliasAddress - Optional email address to filter by\n * @param options - Query options for pagination\n * @returns Promise resolving to an array of ParsedEmail objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async getEmails(\n aliasAddress?: string,\n options?: GetEmailsOptions\n ): Promise<ParsedEmail[]> {\n const limit = options?.limit ?? 20;\n const offset = options?.offset ?? 0;\n\n const emails = await this.cfApi.getMails(limit, offset);\n\n const parsedEmails: ParsedEmail[] = emails.map((email) => {\n const parsed = this.parser.parseEmail(email.raw);\n return {\n ...parsed,\n id: email.id,\n messageId: email.messageId,\n source: email.source,\n address: email.address,\n createdAt: email.createdAt,\n metadata: email.metadata,\n };\n });\n\n if (aliasAddress) {\n const normalizedAlias = aliasAddress.toLowerCase();\n return parsedEmails.filter(\n (email) =>\n email.relayAlias?.toLowerCase() === normalizedAlias ||\n email.address.toLowerCase() === normalizedAlias\n );\n }\n\n return parsedEmails;\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -78,7 +78,7 @@ var CFEmailClient = class {
78
78
  * @param httpClient - Optional HTTP client (defaults to fetch-based implementation)
79
79
  */
80
80
  constructor(apiUrl, token, httpClient) {
81
- this.apiUrl = apiUrl;
81
+ this.apiUrl = apiUrl.replace(/\/+$/, "");
82
82
  this.token = token;
83
83
  this.httpClient = httpClient ?? new DefaultHttpClient();
84
84
  }
@@ -320,7 +320,8 @@ var HttpClient = class {
320
320
  };
321
321
 
322
322
  // src/parser.ts
323
- var MOZMAIL_PATTERN = /[a-zA-Z0-9]+@mozmail\.com/g;
323
+ var EMAIL_PATTERN = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
324
+ var MOZMAIL_SUFFIX_PATTERN = /@mozmail\.com$/i;
324
325
  var ENCODED_WORD_PATTERN = /=\?([^?]+)\?([BbQq])\?([^?]*)\?=/g;
325
326
  var EmailParser = class {
326
327
  parseEmail(raw) {
@@ -343,11 +344,14 @@ var EmailParser = class {
343
344
  extractRelayAlias(raw) {
344
345
  try {
345
346
  const headers = this.parseHeaders(raw);
346
- const toHeader = headers.get("to");
347
- if (!toHeader) return null;
348
- const decodedTo = this.decodeHeader(toHeader);
349
- const matches = decodedTo.match(MOZMAIL_PATTERN);
350
- return matches && matches.length > 0 ? matches[0].toLowerCase() : null;
347
+ const fromAddresses = this.extractHeaderEmails(headers.get("from"));
348
+ const toAddresses = this.extractHeaderEmails(headers.get("to"));
349
+ const allAddresses = [...fromAddresses, ...toAddresses];
350
+ const mozmailAddress = allAddresses.find(
351
+ (address) => MOZMAIL_SUFFIX_PATTERN.test(address)
352
+ );
353
+ if (mozmailAddress) return mozmailAddress;
354
+ return toAddresses[0] ?? null;
351
355
  } catch {
352
356
  return null;
353
357
  }
@@ -410,6 +414,12 @@ var EmailParser = class {
410
414
  const emailMatch = decoded.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/);
411
415
  return emailMatch ? emailMatch[0].toLowerCase() : decoded.trim().toLowerCase();
412
416
  }
417
+ extractHeaderEmails(headerValue) {
418
+ if (!headerValue) return [];
419
+ const decoded = this.decodeHeader(headerValue);
420
+ const matches = decoded.match(EMAIL_PATTERN);
421
+ return matches ? matches.map((match) => match.toLowerCase()) : [];
422
+ }
413
423
  extractMessageId(headerValue) {
414
424
  if (!headerValue) return `<generated-${Date.now()}@relay-temp-mail>`;
415
425
  const cleaned = headerValue.replace(/[<>]/g, "").trim();
@@ -562,7 +572,7 @@ var RelayClient = class {
562
572
  if (aliasAddress) {
563
573
  const normalizedAlias = aliasAddress.toLowerCase();
564
574
  return parsedEmails.filter(
565
- (email) => email.relayAlias?.toLowerCase() === normalizedAlias
575
+ (email) => email.relayAlias?.toLowerCase() === normalizedAlias || email.address.toLowerCase() === normalizedAlias
566
576
  );
567
577
  }
568
578
  return parsedEmails;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/cf-api.ts","../src/http.ts","../src/parser.ts","../src/relay-api.ts","../src/client.ts"],"sourcesContent":["/**\n * Custom error classes for the relay-temp-mail package.\n *\n * These errors provide structured error information including error codes,\n * HTTP status codes, and response data for better error handling.\n */\n\n/**\n * Base error class for all relay-temp-mail errors.\n *\n * Extends the built-in Error class with additional context about the error,\n * including an error code for programmatic error handling and optional\n * response data from the API.\n */\nexport class RelayTempMailError extends Error {\n /**\n * Machine-readable error code for programmatic error handling.\n * Examples: 'NETWORK_ERROR', 'AUTH_ERROR', 'NOT_FOUND'\n */\n code: string;\n\n /**\n * HTTP status code associated with this error, if applicable.\n */\n statusCode?: number;\n\n /**\n * Raw response data from the API, if available.\n */\n response?: any;\n\n /**\n * Creates a new RelayTempMailError instance.\n *\n * @param message - Human-readable error message describing the error.\n * @param code - Machine-readable error code (e.g., 'UNKNOWN_ERROR').\n * @param statusCode - Optional HTTP status code associated with the error.\n * @param response - Optional raw response data from the API.\n */\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n response?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.statusCode = statusCode;\n this.response = response;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error for network-related failures.\n *\n * Thrown when there is a problem establishing or maintaining a network\n * connection, such as DNS resolution failures, connection timeouts,\n * or network unreachability.\n */\nexport class NetworkError extends RelayTempMailError {\n code = 'NETWORK_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NETWORK_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for authentication and authorization failures.\n *\n * Thrown when API requests fail due to invalid or missing credentials\n * (401) or when the authenticated user lacks permission for the\n * requested operation (403).\n */\nexport class AuthError extends RelayTempMailError {\n code = 'AUTH_ERROR' as const;\n\n constructor(message: string, statusCode?: number, response?: any) {\n super(message, 'AUTH_ERROR', statusCode, response);\n }\n}\n\n/**\n * Error for resource not found errors.\n *\n * Thrown when the requested resource does not exist (404 response),\n * such as when trying to access a non-existent alias or email.\n */\nexport class NotFoundError extends RelayTempMailError {\n code = 'NOT_FOUND' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NOT_FOUND', 404, response);\n }\n}\n\n/**\n * Error for MIME message parsing failures.\n *\n * Thrown when there is an error parsing email MIME content,\n * such as malformed headers or invalid message structure.\n */\nexport class ParseError extends RelayTempMailError {\n code = 'PARSE_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'PARSE_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for rate limiting responses.\n *\n * Thrown when the API rate limit has been exceeded (429 response).\n * The client should wait and retry the request after the indicated\n * cooldown period.\n */\nexport class RateLimitError extends RelayTempMailError {\n code = 'RATE_LIMIT_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'RATE_LIMIT_ERROR', 429, response);\n }\n}\n","/**\n * CloudFlare temp email API client.\n *\n * This module provides the CFEmailClient class for interacting with the\n * CloudFlare temp email API to retrieve emails.\n */\n\nimport { Email, CFMailsResponse } from './types.js';\nimport { AuthError, NetworkError, NotFoundError, RateLimitError, RelayTempMailError } from './errors.js';\n\n/**\n * HTTP client interface for making requests.\n *\n * This interface allows for dependency injection, making testing easier\n * by allowing mock implementations.\n */\nexport interface HttpClient {\n /**\n * Makes an HTTP GET request.\n *\n * @param url - The URL to request\n * @param options - Request options including headers\n * @returns The response body as unknown\n */\n get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown>;\n}\n\n/**\n * Default HTTP client implementation using fetch.\n */\nclass DefaultHttpClient implements HttpClient {\n async get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown> {\n const response = await fetch(url, {\n method: 'GET',\n headers: options?.headers,\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new RelayTempMailError(\n `HTTP ${response.status}: ${errorBody}`,\n 'HTTP_ERROR',\n response.status,\n errorBody\n );\n }\n\n return response.json();\n }\n}\n\n/**\n * Raw email response from CF API (snake_case properties).\n */\ninterface CFRawEmail {\n id: number;\n message_id: string;\n source: string;\n address: string;\n raw: string;\n metadata: any | null;\n created_at: string;\n}\n\n/**\n * Raw API response structure.\n */\ninterface CFRawResponse {\n results: CFRawEmail[];\n count: number;\n}\n\n/**\n * Client for interacting with the CloudFlare temp email API.\n *\n * This client handles authentication, request formatting, and response\n * mapping from the CF API's snake_case to camelCase.\n */\nexport class CFEmailClient {\n private readonly apiUrl: string;\n private readonly token: string;\n private readonly httpClient: HttpClient;\n\n /**\n * Creates a new CFEmailClient instance.\n *\n * @param apiUrl - Base URL for the CF temp email API\n * @param token - Bearer token for authentication\n * @param httpClient - Optional HTTP client (defaults to fetch-based implementation)\n */\n constructor(apiUrl: string, token: string, httpClient?: HttpClient) {\n this.apiUrl = apiUrl;\n this.token = token;\n this.httpClient = httpClient ?? new DefaultHttpClient();\n }\n\n /**\n * Retrieves emails from the CF temp email API.\n *\n * @param limit - Maximum number of emails to return (default: 20)\n * @param offset - Pagination offset (default: 0)\n * @returns Promise resolving to an array of Email objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n * @throws NotFoundError if the endpoint doesn't exist\n * @throws RateLimitError if rate limited\n */\n async getMails(limit: number = 20, offset: number = 0): Promise<Email[]> {\n const url = new URL(`${this.apiUrl}/api/mails`);\n url.searchParams.set('limit', String(limit));\n url.searchParams.set('offset', String(offset));\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.token}`,\n };\n\n try {\n const response = await this.httpClient.get(url.toString(), { headers });\n return this.mapCFResponse(response as CFRawResponse);\n } catch (error) {\n throw this.handleError(error);\n }\n }\n\n /**\n * Maps the raw CF API response to the Email interface.\n *\n * Converts snake_case property names to camelCase.\n *\n * @param response - Raw response from CF API\n * @returns Array of Email objects\n */\n private mapCFResponse(response: CFRawResponse): Email[] {\n return response.results.map((item): Email => ({\n id: item.id,\n messageId: item.message_id,\n source: item.source,\n address: item.address,\n raw: item.raw,\n metadata: item.metadata,\n createdAt: item.created_at,\n }));\n }\n\n /**\n * Handles errors from HTTP requests.\n *\n * Maps HTTP errors to appropriate error classes.\n *\n * @param error - The caught error\n * @returns Appropriate RelayTempMailError subclass\n */\n private handleError(error: unknown): RelayTempMailError {\n if (error instanceof RelayTempMailError) {\n const statusCode = error.statusCode;\n\n if (statusCode === 401 || statusCode === 403) {\n return new AuthError(error.message, statusCode, error.response);\n }\n if (statusCode === 404) {\n return new NotFoundError(error.message, error.response);\n }\n if (statusCode === 429) {\n return new RateLimitError(error.message, error.response);\n }\n\n return error;\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError(error.message);\n }\n\n if (error instanceof Error) {\n return new NetworkError(error.message);\n }\n\n return new RelayTempMailError(\n 'Unknown error occurred',\n 'UNKNOWN_ERROR',\n undefined,\n error\n );\n }\n}\n","/**\n * HTTP client utilities for the relay-temp-mail package.\n *\n * This module provides a configurable HTTP client with timeout support,\n * automatic retry logic, and proper error classification for API responses.\n */\n\nimport {\n RelayTempMailError,\n NetworkError,\n AuthError,\n NotFoundError,\n RateLimitError,\n} from './errors';\n\n/**\n * Options for individual HTTP requests.\n */\nexport interface RequestOptions {\n /** Custom headers to include in the request */\n headers?: Record<string, string>;\n\n /** Request body (will be JSON serialized) */\n body?: unknown;\n\n /** Request timeout in milliseconds (overrides client default) */\n timeout?: number;\n\n /** Number of retries on failure (overrides client default) */\n retries?: number;\n}\n\n/**\n * HTTP client for making requests to the relay-temp-mail API.\n *\n * Provides a configurable base URL with timeout, retry, and automatic\n * JSON parsing capabilities.\n */\nexport class HttpClient {\n private baseUrl: string;\n private defaultTimeout: number;\n private defaultRetries: number;\n\n /**\n * Creates a new HttpClient instance.\n *\n * @param baseUrl - Base URL for all requests (e.g., 'https://api.example.com')\n * @param defaultTimeout - Default timeout in milliseconds (default: 30000)\n * @param defaultRetries - Default number of retries on failure (default: 0)\n */\n constructor(\n baseUrl: string,\n defaultTimeout: number = 30000,\n defaultRetries: number = 0\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.defaultTimeout = defaultTimeout;\n this.defaultRetries = defaultRetries;\n }\n\n /**\n * Makes an HTTP request to the specified path.\n *\n * @param method - HTTP method (GET, POST, PUT, DELETE, etc.)\n * @param path - API path (will be appended to baseUrl)\n * @param options - Optional request configuration\n * @returns Promise resolving to the parsed JSON response\n */\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const timeout = options.timeout ?? this.defaultTimeout;\n const retries = options.retries ?? this.defaultRetries;\n\n let lastError: RelayTempMailError | Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const response = await this.executeRequest(method, path, options, timeout);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n\n // Check if we should retry\n if (attempt < retries && this.shouldRetry(error)) {\n const delay = 1000 * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n\n // Don't retry, throw the classified error\n if (error instanceof RelayTempMailError) {\n throw error;\n }\n\n // Classify the error if not already classified\n throw this.classifyError(error);\n }\n }\n\n // This should never be reached, but just in case\n throw lastError || new NetworkError('Request failed');\n }\n\n /**\n * Executes the actual HTTP request with timeout support.\n */\n private async executeRequest(\n method: string,\n path: string,\n options: RequestOptions,\n timeout: number\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n signal: controller.signal,\n };\n\n if (options.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Handles the HTTP response, parsing JSON and checking for errors.\n */\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n throw this.classifyError(new Error(`HTTP ${response.status}`), response);\n }\n\n const text = await response.text();\n\n // Handle empty responses\n if (!text) {\n return {} as T;\n }\n\n return JSON.parse(text) as T;\n }\n\n /**\n * Classifies an error based on the error type and HTTP response.\n */\n private classifyError(error: unknown, response?: Response): RelayTempMailError {\n // Network errors (fetch failed)\n if (error instanceof Error && error.name === 'AbortError') {\n return new NetworkError('Request timed out');\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError('Network request failed');\n }\n\n if (error instanceof Error && error.message.includes('Failed to fetch')) {\n return new NetworkError('Network request failed');\n }\n\n // HTTP status-based classification\n if (response) {\n const status = response.status;\n\n if (status === 401 || status === 403) {\n return new AuthError(\n `Authentication failed: ${response.statusText}`,\n status\n );\n }\n\n if (status === 404) {\n return new NotFoundError(`Resource not found: ${response.statusText}`);\n }\n\n if (status === 429) {\n return new RateLimitError(\n `Rate limit exceeded: ${response.statusText}`\n );\n }\n\n if (status >= 500) {\n return new NetworkError(\n `Server error: ${response.statusText}`,\n status\n );\n }\n }\n\n // Default error\n if (error instanceof Error) {\n return new RelayTempMailError(\n error.message,\n 'REQUEST_ERROR',\n response?.status\n );\n }\n\n return new RelayTempMailError('Unknown error occurred', 'UNKNOWN_ERROR');\n }\n\n /**\n * Determines if a request should be retried based on the error.\n */\n private shouldRetry(error: unknown): boolean {\n if (error instanceof NetworkError) {\n return true;\n }\n\n if (error instanceof RelayTempMailError && error.statusCode) {\n return error.statusCode >= 500;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n return true;\n }\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Sleep for a specified duration.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/**\n * MIME email parser for extracting Firefox Relay alias information.\n */\nimport type { ParsedEmail } from './types.js';\n\nconst MOZMAIL_PATTERN = /[a-zA-Z0-9]+@mozmail\\.com/g;\nconst ENCODED_WORD_PATTERN = /=\\?([^?]+)\\?([BbQq])\\?([^?]*)\\?=/g;\n\n/**\n * EmailParser class for parsing MIME email content.\n */\nexport class EmailParser {\n parseEmail(raw: string): ParsedEmail {\n const headers = this.parseHeaders(raw);\n const toHeader = headers.get('to') || '';\n const fromHeader = headers.get('from') || '';\n const messageIdHeader = headers.get('message-id') || '';\n const relayAlias = this.extractRelayAlias(raw);\n \n return {\n id: 0,\n messageId: this.extractMessageId(messageIdHeader),\n source: this.extractEmailAddress(fromHeader),\n address: this.extractEmailAddress(toHeader),\n raw,\n metadata: null,\n createdAt: new Date().toISOString(),\n relayAlias: relayAlias || undefined,\n };\n }\n\n extractRelayAlias(raw: string): string | null {\n try {\n const headers = this.parseHeaders(raw);\n const toHeader = headers.get('to');\n if (!toHeader) return null;\n \n const decodedTo = this.decodeHeader(toHeader);\n const matches = decodedTo.match(MOZMAIL_PATTERN);\n return matches && matches.length > 0 ? matches[0].toLowerCase() : null;\n } catch {\n return null;\n }\n }\n\n private parseHeaders(raw: string): Map<string, string> {\n const headers = new Map<string, string>();\n const headerEnd = raw.indexOf('\\r\\n\\r\\n');\n const headerSection = headerEnd === -1 ? raw : raw.substring(0, headerEnd);\n const lines = headerSection.split(/\\r?\\n/);\n let currentHeader: string | null = null;\n let currentValue = '';\n \n for (const line of lines) {\n if (/^\\s/.test(line)) {\n if (currentHeader) currentValue += ' ' + line.trim();\n } else {\n if (currentHeader) headers.set(currentHeader, currentValue);\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n currentHeader = line.substring(0, colonIndex).toLowerCase().trim();\n currentValue = line.substring(colonIndex + 1).trim();\n } else {\n currentHeader = null;\n currentValue = '';\n }\n }\n }\n if (currentHeader) headers.set(currentHeader, currentValue);\n return headers;\n }\n\n private decodeHeader(value: string): string {\n return value.replace(ENCODED_WORD_PATTERN, (_, charset, encoding, encoded) => {\n try {\n if (encoding.toUpperCase() === 'Q') {\n return this.decodeQuotedPrintable(encoded);\n } else if (encoding.toUpperCase() === 'B') {\n return this.decodeBase64(encoded);\n }\n return encoded;\n } catch {\n return encoded;\n }\n });\n }\n\n private decodeQuotedPrintable(encoded: string): string {\n // RFC 2047: underscores represent spaces in encoded-word\n let decoded = encoded.replace(/_/g, ' ');\n decoded = decoded.replace(/=([0-9A-Fa-f]{2})/g, (_, hex) => \n String.fromCharCode(parseInt(hex, 16))\n );\n return decoded;\n }\n\n private decodeBase64(encoded: string): string {\n return Buffer.from(encoded, 'base64').toString('utf-8');\n }\n\n private extractEmailAddress(headerValue: string): string {\n if (!headerValue) return '';\n const decoded = this.decodeHeader(headerValue);\n const bracketMatch = decoded.match(/<([^>]+)>/);\n if (bracketMatch) return bracketMatch[1].trim().toLowerCase();\n const emailMatch = decoded.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/);\n return emailMatch ? emailMatch[0].toLowerCase() : decoded.trim().toLowerCase();\n }\n\n private extractMessageId(headerValue: string): string {\n if (!headerValue) return `<generated-${Date.now()}@relay-temp-mail>`;\n const cleaned = headerValue.replace(/[<>]/g, '').trim();\n return `<${cleaned}>`;\n }\n}\n","import { HttpClient } from './http';\nimport { RelayAlias } from './types';\n\ninterface RawAliasResponse {\n id: number;\n address: string;\n full_address: string;\n enabled: boolean;\n created_at: string;\n domain: number;\n mask_type: string;\n description?: string;\n num_forwarded?: number;\n num_blocked?: number;\n last_modified_at?: string;\n last_used_at?: string | null;\n num_level_one_trackers_blocked?: number;\n num_replied?: number;\n num_spam?: number;\n block_list_emails?: boolean;\n generated_for?: string;\n used_on?: string | null;\n}\n\nexport class RelayAPIClient {\n private csrfToken: string;\n private sessionId: string;\n private httpClient: HttpClient;\n\n constructor(\n csrfToken: string,\n sessionId: string,\n httpClient?: HttpClient\n ) {\n this.csrfToken = csrfToken;\n this.sessionId = sessionId;\n this.httpClient = httpClient ?? new HttpClient('https://relay.firefox.com');\n }\n\n private getAuthHeaders(): Record<string, string> {\n return {\n 'Origin': 'https://relay.firefox.com',\n 'Referer': 'https://relay.firefox.com/accounts/profile/?',\n 'Accept': 'application/json',\n 'X-CSRFToken': this.csrfToken,\n 'Cookie': `sessionid=${this.sessionId}; csrftoken=${this.csrfToken}`,\n };\n }\n\n async getAliases(): Promise<RelayAlias[]> {\n const response = await this.httpClient.request<RawAliasResponse[]>(\n 'GET',\n '/api/v1/relayaddresses/',\n { headers: this.getAuthHeaders() }\n );\n\n return response.map((item) => this.mapAliasResponse(item));\n }\n\n async createAlias(): Promise<RelayAlias> {\n const response = await this.httpClient.request<RawAliasResponse>(\n 'POST',\n '/api/v1/relayaddresses/',\n {\n headers: this.getAuthHeaders(),\n body: { enabled: true },\n }\n );\n\n return this.mapAliasResponse(response);\n }\n\n async deleteAlias(id: number): Promise<void> {\n await this.httpClient.request<void>(\n 'DELETE',\n `/api/v1/relayaddresses/${id}/`,\n { headers: this.getAuthHeaders() }\n );\n }\n\n private mapAliasResponse(data: RawAliasResponse): RelayAlias {\n return {\n id: data.id,\n address: data.address,\n fullAddress: data.full_address,\n enabled: data.enabled,\n createdAt: data.created_at,\n domain: data.domain,\n maskType: data.mask_type,\n description: data.description,\n numForwarded: data.num_forwarded,\n numBlocked: data.num_blocked,\n lastModifiedAt: data.last_modified_at,\n lastUsedAt: data.last_used_at,\n numLevelOneTrackersBlocked: data.num_level_one_trackers_blocked,\n numReplied: data.num_replied,\n numSpam: data.num_spam,\n blockListEmails: data.block_list_emails,\n generatedFor: data.generated_for,\n usedOn: data.used_on,\n };\n }\n}\n","/**\n * Main client for the relay-temp-mail package.\n *\n * This module provides the RelayClient class which integrates all components\n * (CF API, Relay API, Parser) into a unified interface.\n */\n\nimport { CFEmailClient } from './cf-api.js';\nimport { HttpClient } from './http.js';\nimport { EmailParser } from './parser.js';\nimport { RelayAPIClient } from './relay-api.js';\nimport type {\n RelayConfig,\n RelayAlias,\n ParsedEmail,\n GetEmailsOptions,\n} from './types.js';\n\n/**\n * Main client for interacting with Firefox Relay and CloudFlare temp email services.\n *\n * RelayClient integrates all components to provide a unified interface for:\n * - Managing Firefox Relay email aliases\n * - Retrieving and parsing emails from CloudFlare temp email API\n *\n * @example\n * ```typescript\n * const client = new RelayClient({\n * csrfToken: '...',\n * sessionId: '...',\n * cfApiUrl: 'https://...',\n * cfToken: '...',\n * timeout: 30000\n * });\n *\n * const aliases = await client.listAliases();\n * const emails = await client.getEmails('alias@mozmail.com', { limit: 10 });\n * ```\n */\nexport class RelayClient {\n private readonly relayApi: RelayAPIClient;\n private readonly cfApi: CFEmailClient;\n private readonly parser: EmailParser;\n\n /**\n * Creates a new RelayClient instance.\n *\n * @param config - Configuration object containing authentication tokens and API URLs\n */\n constructor(config: RelayConfig) {\n const timeout = config.timeout ?? 30000;\n\n const relayHttpClient = new HttpClient('https://relay.firefox.com', timeout);\n this.relayApi = new RelayAPIClient(\n config.csrfToken,\n config.sessionId,\n relayHttpClient\n );\n\n this.cfApi = new CFEmailClient(config.cfApiUrl, config.cfToken);\n this.parser = new EmailParser();\n }\n\n /**\n * Lists all Firefox Relay email aliases.\n *\n * @returns Promise resolving to an array of RelayAlias objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async listAliases(): Promise<RelayAlias[]> {\n return this.relayApi.getAliases();\n }\n\n /**\n * Creates a new Firefox Relay email alias.\n *\n * @returns Promise resolving to the newly created RelayAlias\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async createAlias(): Promise<RelayAlias> {\n return this.relayApi.createAlias();\n }\n\n /**\n * Deletes a Firefox Relay email alias.\n *\n * @param id - The ID of the alias to delete\n * @throws AuthError if authentication fails\n * @throws NotFoundError if the alias doesn't exist\n * @throws NetworkError if there's a network problem\n */\n async deleteAlias(id: number): Promise<void> {\n return this.relayApi.deleteAlias(id);\n }\n\n /**\n * Retrieves and parses emails from the CloudFlare temp email API.\n *\n * If aliasAddress is provided, only emails sent to that address are returned.\n *\n * @param aliasAddress - Optional email address to filter by\n * @param options - Query options for pagination\n * @returns Promise resolving to an array of ParsedEmail objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async getEmails(\n aliasAddress?: string,\n options?: GetEmailsOptions\n ): Promise<ParsedEmail[]> {\n const limit = options?.limit ?? 20;\n const offset = options?.offset ?? 0;\n\n const emails = await this.cfApi.getMails(limit, offset);\n\n const parsedEmails: ParsedEmail[] = emails.map((email) => {\n const parsed = this.parser.parseEmail(email.raw);\n return {\n ...parsed,\n id: email.id,\n messageId: email.messageId,\n source: email.source,\n address: email.address,\n createdAt: email.createdAt,\n metadata: email.metadata,\n };\n });\n\n if (aliasAddress) {\n const normalizedAlias = aliasAddress.toLowerCase();\n return parsedEmails.filter(\n (email) => email.relayAlias?.toLowerCase() === normalizedAlias\n );\n }\n\n return parsedEmails;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/cf-api.ts","../src/http.ts","../src/parser.ts","../src/relay-api.ts","../src/client.ts"],"sourcesContent":["/**\n * Custom error classes for the relay-temp-mail package.\n *\n * These errors provide structured error information including error codes,\n * HTTP status codes, and response data for better error handling.\n */\n\n/**\n * Base error class for all relay-temp-mail errors.\n *\n * Extends the built-in Error class with additional context about the error,\n * including an error code for programmatic error handling and optional\n * response data from the API.\n */\nexport class RelayTempMailError extends Error {\n /**\n * Machine-readable error code for programmatic error handling.\n * Examples: 'NETWORK_ERROR', 'AUTH_ERROR', 'NOT_FOUND'\n */\n code: string;\n\n /**\n * HTTP status code associated with this error, if applicable.\n */\n statusCode?: number;\n\n /**\n * Raw response data from the API, if available.\n */\n response?: any;\n\n /**\n * Creates a new RelayTempMailError instance.\n *\n * @param message - Human-readable error message describing the error.\n * @param code - Machine-readable error code (e.g., 'UNKNOWN_ERROR').\n * @param statusCode - Optional HTTP status code associated with the error.\n * @param response - Optional raw response data from the API.\n */\n constructor(\n message: string,\n code: string,\n statusCode?: number,\n response?: any\n ) {\n super(message);\n this.name = this.constructor.name;\n this.code = code;\n this.statusCode = statusCode;\n this.response = response;\n\n // Maintains proper stack trace in V8 environments\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Error for network-related failures.\n *\n * Thrown when there is a problem establishing or maintaining a network\n * connection, such as DNS resolution failures, connection timeouts,\n * or network unreachability.\n */\nexport class NetworkError extends RelayTempMailError {\n code = 'NETWORK_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NETWORK_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for authentication and authorization failures.\n *\n * Thrown when API requests fail due to invalid or missing credentials\n * (401) or when the authenticated user lacks permission for the\n * requested operation (403).\n */\nexport class AuthError extends RelayTempMailError {\n code = 'AUTH_ERROR' as const;\n\n constructor(message: string, statusCode?: number, response?: any) {\n super(message, 'AUTH_ERROR', statusCode, response);\n }\n}\n\n/**\n * Error for resource not found errors.\n *\n * Thrown when the requested resource does not exist (404 response),\n * such as when trying to access a non-existent alias or email.\n */\nexport class NotFoundError extends RelayTempMailError {\n code = 'NOT_FOUND' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'NOT_FOUND', 404, response);\n }\n}\n\n/**\n * Error for MIME message parsing failures.\n *\n * Thrown when there is an error parsing email MIME content,\n * such as malformed headers or invalid message structure.\n */\nexport class ParseError extends RelayTempMailError {\n code = 'PARSE_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'PARSE_ERROR', undefined, response);\n }\n}\n\n/**\n * Error for rate limiting responses.\n *\n * Thrown when the API rate limit has been exceeded (429 response).\n * The client should wait and retry the request after the indicated\n * cooldown period.\n */\nexport class RateLimitError extends RelayTempMailError {\n code = 'RATE_LIMIT_ERROR' as const;\n\n constructor(message: string, response?: any) {\n super(message, 'RATE_LIMIT_ERROR', 429, response);\n }\n}\n","/**\n * CloudFlare temp email API client.\n *\n * This module provides the CFEmailClient class for interacting with the\n * CloudFlare temp email API to retrieve emails.\n */\n\nimport { Email, CFMailsResponse } from './types.js';\nimport { AuthError, NetworkError, NotFoundError, RateLimitError, RelayTempMailError } from './errors.js';\n\n/**\n * HTTP client interface for making requests.\n *\n * This interface allows for dependency injection, making testing easier\n * by allowing mock implementations.\n */\nexport interface HttpClient {\n /**\n * Makes an HTTP GET request.\n *\n * @param url - The URL to request\n * @param options - Request options including headers\n * @returns The response body as unknown\n */\n get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown>;\n}\n\n/**\n * Default HTTP client implementation using fetch.\n */\nclass DefaultHttpClient implements HttpClient {\n async get(url: string, options?: { headers?: Record<string, string> }): Promise<unknown> {\n const response = await fetch(url, {\n method: 'GET',\n headers: options?.headers,\n });\n\n if (!response.ok) {\n const errorBody = await response.text();\n throw new RelayTempMailError(\n `HTTP ${response.status}: ${errorBody}`,\n 'HTTP_ERROR',\n response.status,\n errorBody\n );\n }\n\n return response.json();\n }\n}\n\n/**\n * Raw email response from CF API (snake_case properties).\n */\ninterface CFRawEmail {\n id: number;\n message_id: string;\n source: string;\n address: string;\n raw: string;\n metadata: any | null;\n created_at: string;\n}\n\n/**\n * Raw API response structure.\n */\ninterface CFRawResponse {\n results: CFRawEmail[];\n count: number;\n}\n\n/**\n * Client for interacting with the CloudFlare temp email API.\n *\n * This client handles authentication, request formatting, and response\n * mapping from the CF API's snake_case to camelCase.\n */\nexport class CFEmailClient {\n private readonly apiUrl: string;\n private readonly token: string;\n private readonly httpClient: HttpClient;\n\n /**\n * Creates a new CFEmailClient instance.\n *\n * @param apiUrl - Base URL for the CF temp email API\n * @param token - Bearer token for authentication\n * @param httpClient - Optional HTTP client (defaults to fetch-based implementation)\n */\n constructor(apiUrl: string, token: string, httpClient?: HttpClient) {\n this.apiUrl = apiUrl.replace(/\\/+$/, '');\n this.token = token;\n this.httpClient = httpClient ?? new DefaultHttpClient();\n }\n\n /**\n * Retrieves emails from the CF temp email API.\n *\n * @param limit - Maximum number of emails to return (default: 20)\n * @param offset - Pagination offset (default: 0)\n * @returns Promise resolving to an array of Email objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n * @throws NotFoundError if the endpoint doesn't exist\n * @throws RateLimitError if rate limited\n */\n async getMails(limit: number = 20, offset: number = 0): Promise<Email[]> {\n const url = new URL(`${this.apiUrl}/api/mails`);\n url.searchParams.set('limit', String(limit));\n url.searchParams.set('offset', String(offset));\n\n const headers: Record<string, string> = {\n 'Authorization': `Bearer ${this.token}`,\n };\n\n try {\n const response = await this.httpClient.get(url.toString(), { headers });\n return this.mapCFResponse(response as CFRawResponse);\n } catch (error) {\n throw this.handleError(error);\n }\n }\n\n /**\n * Maps the raw CF API response to the Email interface.\n *\n * Converts snake_case property names to camelCase.\n *\n * @param response - Raw response from CF API\n * @returns Array of Email objects\n */\n private mapCFResponse(response: CFRawResponse): Email[] {\n return response.results.map((item): Email => ({\n id: item.id,\n messageId: item.message_id,\n source: item.source,\n address: item.address,\n raw: item.raw,\n metadata: item.metadata,\n createdAt: item.created_at,\n }));\n }\n\n /**\n * Handles errors from HTTP requests.\n *\n * Maps HTTP errors to appropriate error classes.\n *\n * @param error - The caught error\n * @returns Appropriate RelayTempMailError subclass\n */\n private handleError(error: unknown): RelayTempMailError {\n if (error instanceof RelayTempMailError) {\n const statusCode = error.statusCode;\n\n if (statusCode === 401 || statusCode === 403) {\n return new AuthError(error.message, statusCode, error.response);\n }\n if (statusCode === 404) {\n return new NotFoundError(error.message, error.response);\n }\n if (statusCode === 429) {\n return new RateLimitError(error.message, error.response);\n }\n\n return error;\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError(error.message);\n }\n\n if (error instanceof Error) {\n return new NetworkError(error.message);\n }\n\n return new RelayTempMailError(\n 'Unknown error occurred',\n 'UNKNOWN_ERROR',\n undefined,\n error\n );\n }\n}\n","/**\n * HTTP client utilities for the relay-temp-mail package.\n *\n * This module provides a configurable HTTP client with timeout support,\n * automatic retry logic, and proper error classification for API responses.\n */\n\nimport {\n RelayTempMailError,\n NetworkError,\n AuthError,\n NotFoundError,\n RateLimitError,\n} from './errors';\n\n/**\n * Options for individual HTTP requests.\n */\nexport interface RequestOptions {\n /** Custom headers to include in the request */\n headers?: Record<string, string>;\n\n /** Request body (will be JSON serialized) */\n body?: unknown;\n\n /** Request timeout in milliseconds (overrides client default) */\n timeout?: number;\n\n /** Number of retries on failure (overrides client default) */\n retries?: number;\n}\n\n/**\n * HTTP client for making requests to the relay-temp-mail API.\n *\n * Provides a configurable base URL with timeout, retry, and automatic\n * JSON parsing capabilities.\n */\nexport class HttpClient {\n private baseUrl: string;\n private defaultTimeout: number;\n private defaultRetries: number;\n\n /**\n * Creates a new HttpClient instance.\n *\n * @param baseUrl - Base URL for all requests (e.g., 'https://api.example.com')\n * @param defaultTimeout - Default timeout in milliseconds (default: 30000)\n * @param defaultRetries - Default number of retries on failure (default: 0)\n */\n constructor(\n baseUrl: string,\n defaultTimeout: number = 30000,\n defaultRetries: number = 0\n ) {\n this.baseUrl = baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n this.defaultTimeout = defaultTimeout;\n this.defaultRetries = defaultRetries;\n }\n\n /**\n * Makes an HTTP request to the specified path.\n *\n * @param method - HTTP method (GET, POST, PUT, DELETE, etc.)\n * @param path - API path (will be appended to baseUrl)\n * @param options - Optional request configuration\n * @returns Promise resolving to the parsed JSON response\n */\n async request<T>(\n method: string,\n path: string,\n options: RequestOptions = {}\n ): Promise<T> {\n const timeout = options.timeout ?? this.defaultTimeout;\n const retries = options.retries ?? this.defaultRetries;\n\n let lastError: RelayTempMailError | Error | undefined;\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const response = await this.executeRequest(method, path, options, timeout);\n return await this.handleResponse<T>(response);\n } catch (error) {\n lastError = error as Error;\n\n // Check if we should retry\n if (attempt < retries && this.shouldRetry(error)) {\n const delay = 1000 * Math.pow(2, attempt);\n await this.sleep(delay);\n continue;\n }\n\n // Don't retry, throw the classified error\n if (error instanceof RelayTempMailError) {\n throw error;\n }\n\n // Classify the error if not already classified\n throw this.classifyError(error);\n }\n }\n\n // This should never be reached, but just in case\n throw lastError || new NetworkError('Request failed');\n }\n\n /**\n * Executes the actual HTTP request with timeout support.\n */\n private async executeRequest(\n method: string,\n path: string,\n options: RequestOptions,\n timeout: number\n ): Promise<Response> {\n const url = `${this.baseUrl}${path}`;\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), timeout);\n\n try {\n const fetchOptions: RequestInit = {\n method,\n headers: {\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n signal: controller.signal,\n };\n\n if (options.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n const response = await fetch(url, fetchOptions);\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Handles the HTTP response, parsing JSON and checking for errors.\n */\n private async handleResponse<T>(response: Response): Promise<T> {\n if (!response.ok) {\n throw this.classifyError(new Error(`HTTP ${response.status}`), response);\n }\n\n const text = await response.text();\n\n // Handle empty responses\n if (!text) {\n return {} as T;\n }\n\n return JSON.parse(text) as T;\n }\n\n /**\n * Classifies an error based on the error type and HTTP response.\n */\n private classifyError(error: unknown, response?: Response): RelayTempMailError {\n // Network errors (fetch failed)\n if (error instanceof Error && error.name === 'AbortError') {\n return new NetworkError('Request timed out');\n }\n\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return new NetworkError('Network request failed');\n }\n\n if (error instanceof Error && error.message.includes('Failed to fetch')) {\n return new NetworkError('Network request failed');\n }\n\n // HTTP status-based classification\n if (response) {\n const status = response.status;\n\n if (status === 401 || status === 403) {\n return new AuthError(\n `Authentication failed: ${response.statusText}`,\n status\n );\n }\n\n if (status === 404) {\n return new NotFoundError(`Resource not found: ${response.statusText}`);\n }\n\n if (status === 429) {\n return new RateLimitError(\n `Rate limit exceeded: ${response.statusText}`\n );\n }\n\n if (status >= 500) {\n return new NetworkError(\n `Server error: ${response.statusText}`,\n status\n );\n }\n }\n\n // Default error\n if (error instanceof Error) {\n return new RelayTempMailError(\n error.message,\n 'REQUEST_ERROR',\n response?.status\n );\n }\n\n return new RelayTempMailError('Unknown error occurred', 'UNKNOWN_ERROR');\n }\n\n /**\n * Determines if a request should be retried based on the error.\n */\n private shouldRetry(error: unknown): boolean {\n if (error instanceof NetworkError) {\n return true;\n }\n\n if (error instanceof RelayTempMailError && error.statusCode) {\n return error.statusCode >= 500;\n }\n\n if (error instanceof Error) {\n if (error.name === 'AbortError') {\n return true;\n }\n if (error instanceof TypeError && error.message.includes('fetch')) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Sleep for a specified duration.\n */\n private sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n}\n","/**\n * MIME email parser for extracting Firefox Relay alias information.\n */\nimport type { ParsedEmail } from './types.js';\n\nconst EMAIL_PATTERN = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g;\nconst MOZMAIL_SUFFIX_PATTERN = /@mozmail\\.com$/i;\nconst ENCODED_WORD_PATTERN = /=\\?([^?]+)\\?([BbQq])\\?([^?]*)\\?=/g;\n\n/**\n * EmailParser class for parsing MIME email content.\n */\nexport class EmailParser {\n parseEmail(raw: string): ParsedEmail {\n const headers = this.parseHeaders(raw);\n const toHeader = headers.get('to') || '';\n const fromHeader = headers.get('from') || '';\n const messageIdHeader = headers.get('message-id') || '';\n const relayAlias = this.extractRelayAlias(raw);\n \n return {\n id: 0,\n messageId: this.extractMessageId(messageIdHeader),\n source: this.extractEmailAddress(fromHeader),\n address: this.extractEmailAddress(toHeader),\n raw,\n metadata: null,\n createdAt: new Date().toISOString(),\n relayAlias: relayAlias || undefined,\n };\n }\n\n extractRelayAlias(raw: string): string | null {\n try {\n const headers = this.parseHeaders(raw);\n const fromAddresses = this.extractHeaderEmails(headers.get('from'));\n const toAddresses = this.extractHeaderEmails(headers.get('to'));\n const allAddresses = [...fromAddresses, ...toAddresses];\n\n const mozmailAddress = allAddresses.find((address) =>\n MOZMAIL_SUFFIX_PATTERN.test(address)\n );\n if (mozmailAddress) return mozmailAddress;\n\n return toAddresses[0] ?? null;\n } catch {\n return null;\n }\n }\n\n private parseHeaders(raw: string): Map<string, string> {\n const headers = new Map<string, string>();\n const headerEnd = raw.indexOf('\\r\\n\\r\\n');\n const headerSection = headerEnd === -1 ? raw : raw.substring(0, headerEnd);\n const lines = headerSection.split(/\\r?\\n/);\n let currentHeader: string | null = null;\n let currentValue = '';\n \n for (const line of lines) {\n if (/^\\s/.test(line)) {\n if (currentHeader) currentValue += ' ' + line.trim();\n } else {\n if (currentHeader) headers.set(currentHeader, currentValue);\n const colonIndex = line.indexOf(':');\n if (colonIndex > 0) {\n currentHeader = line.substring(0, colonIndex).toLowerCase().trim();\n currentValue = line.substring(colonIndex + 1).trim();\n } else {\n currentHeader = null;\n currentValue = '';\n }\n }\n }\n if (currentHeader) headers.set(currentHeader, currentValue);\n return headers;\n }\n\n private decodeHeader(value: string): string {\n return value.replace(ENCODED_WORD_PATTERN, (_, charset, encoding, encoded) => {\n try {\n if (encoding.toUpperCase() === 'Q') {\n return this.decodeQuotedPrintable(encoded);\n } else if (encoding.toUpperCase() === 'B') {\n return this.decodeBase64(encoded);\n }\n return encoded;\n } catch {\n return encoded;\n }\n });\n }\n\n private decodeQuotedPrintable(encoded: string): string {\n // RFC 2047: underscores represent spaces in encoded-word\n let decoded = encoded.replace(/_/g, ' ');\n decoded = decoded.replace(/=([0-9A-Fa-f]{2})/g, (_, hex) => \n String.fromCharCode(parseInt(hex, 16))\n );\n return decoded;\n }\n\n private decodeBase64(encoded: string): string {\n return Buffer.from(encoded, 'base64').toString('utf-8');\n }\n\n private extractEmailAddress(headerValue: string): string {\n if (!headerValue) return '';\n const decoded = this.decodeHeader(headerValue);\n const bracketMatch = decoded.match(/<([^>]+)>/);\n if (bracketMatch) return bracketMatch[1].trim().toLowerCase();\n const emailMatch = decoded.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/);\n return emailMatch ? emailMatch[0].toLowerCase() : decoded.trim().toLowerCase();\n }\n\n private extractHeaderEmails(headerValue?: string): string[] {\n if (!headerValue) return [];\n const decoded = this.decodeHeader(headerValue);\n const matches = decoded.match(EMAIL_PATTERN);\n return matches ? matches.map((match) => match.toLowerCase()) : [];\n }\n\n private extractMessageId(headerValue: string): string {\n if (!headerValue) return `<generated-${Date.now()}@relay-temp-mail>`;\n const cleaned = headerValue.replace(/[<>]/g, '').trim();\n return `<${cleaned}>`;\n }\n}\n","import { HttpClient } from './http';\nimport { RelayAlias } from './types';\n\ninterface RawAliasResponse {\n id: number;\n address: string;\n full_address: string;\n enabled: boolean;\n created_at: string;\n domain: number;\n mask_type: string;\n description?: string;\n num_forwarded?: number;\n num_blocked?: number;\n last_modified_at?: string;\n last_used_at?: string | null;\n num_level_one_trackers_blocked?: number;\n num_replied?: number;\n num_spam?: number;\n block_list_emails?: boolean;\n generated_for?: string;\n used_on?: string | null;\n}\n\nexport class RelayAPIClient {\n private csrfToken: string;\n private sessionId: string;\n private httpClient: HttpClient;\n\n constructor(\n csrfToken: string,\n sessionId: string,\n httpClient?: HttpClient\n ) {\n this.csrfToken = csrfToken;\n this.sessionId = sessionId;\n this.httpClient = httpClient ?? new HttpClient('https://relay.firefox.com');\n }\n\n private getAuthHeaders(): Record<string, string> {\n return {\n 'Origin': 'https://relay.firefox.com',\n 'Referer': 'https://relay.firefox.com/accounts/profile/?',\n 'Accept': 'application/json',\n 'X-CSRFToken': this.csrfToken,\n 'Cookie': `sessionid=${this.sessionId}; csrftoken=${this.csrfToken}`,\n };\n }\n\n async getAliases(): Promise<RelayAlias[]> {\n const response = await this.httpClient.request<RawAliasResponse[]>(\n 'GET',\n '/api/v1/relayaddresses/',\n { headers: this.getAuthHeaders() }\n );\n\n return response.map((item) => this.mapAliasResponse(item));\n }\n\n async createAlias(): Promise<RelayAlias> {\n const response = await this.httpClient.request<RawAliasResponse>(\n 'POST',\n '/api/v1/relayaddresses/',\n {\n headers: this.getAuthHeaders(),\n body: { enabled: true },\n }\n );\n\n return this.mapAliasResponse(response);\n }\n\n async deleteAlias(id: number): Promise<void> {\n await this.httpClient.request<void>(\n 'DELETE',\n `/api/v1/relayaddresses/${id}/`,\n { headers: this.getAuthHeaders() }\n );\n }\n\n private mapAliasResponse(data: RawAliasResponse): RelayAlias {\n return {\n id: data.id,\n address: data.address,\n fullAddress: data.full_address,\n enabled: data.enabled,\n createdAt: data.created_at,\n domain: data.domain,\n maskType: data.mask_type,\n description: data.description,\n numForwarded: data.num_forwarded,\n numBlocked: data.num_blocked,\n lastModifiedAt: data.last_modified_at,\n lastUsedAt: data.last_used_at,\n numLevelOneTrackersBlocked: data.num_level_one_trackers_blocked,\n numReplied: data.num_replied,\n numSpam: data.num_spam,\n blockListEmails: data.block_list_emails,\n generatedFor: data.generated_for,\n usedOn: data.used_on,\n };\n }\n}\n","/**\n * Main client for the relay-temp-mail package.\n *\n * This module provides the RelayClient class which integrates all components\n * (CF API, Relay API, Parser) into a unified interface.\n */\n\nimport { CFEmailClient } from './cf-api.js';\nimport { HttpClient } from './http.js';\nimport { EmailParser } from './parser.js';\nimport { RelayAPIClient } from './relay-api.js';\nimport type {\n RelayConfig,\n RelayAlias,\n ParsedEmail,\n GetEmailsOptions,\n} from './types.js';\n\n/**\n * Main client for interacting with Firefox Relay and CloudFlare temp email services.\n *\n * RelayClient integrates all components to provide a unified interface for:\n * - Managing Firefox Relay email aliases\n * - Retrieving and parsing emails from CloudFlare temp email API\n *\n * @example\n * ```typescript\n * const client = new RelayClient({\n * csrfToken: '...',\n * sessionId: '...',\n * cfApiUrl: 'https://...',\n * cfToken: '...',\n * timeout: 30000\n * });\n *\n * const aliases = await client.listAliases();\n * const emails = await client.getEmails('alias@mozmail.com', { limit: 10 });\n * ```\n */\nexport class RelayClient {\n private readonly relayApi: RelayAPIClient;\n private readonly cfApi: CFEmailClient;\n private readonly parser: EmailParser;\n\n /**\n * Creates a new RelayClient instance.\n *\n * @param config - Configuration object containing authentication tokens and API URLs\n */\n constructor(config: RelayConfig) {\n const timeout = config.timeout ?? 30000;\n\n const relayHttpClient = new HttpClient('https://relay.firefox.com', timeout);\n this.relayApi = new RelayAPIClient(\n config.csrfToken,\n config.sessionId,\n relayHttpClient\n );\n\n this.cfApi = new CFEmailClient(config.cfApiUrl, config.cfToken);\n this.parser = new EmailParser();\n }\n\n /**\n * Lists all Firefox Relay email aliases.\n *\n * @returns Promise resolving to an array of RelayAlias objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async listAliases(): Promise<RelayAlias[]> {\n return this.relayApi.getAliases();\n }\n\n /**\n * Creates a new Firefox Relay email alias.\n *\n * @returns Promise resolving to the newly created RelayAlias\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async createAlias(): Promise<RelayAlias> {\n return this.relayApi.createAlias();\n }\n\n /**\n * Deletes a Firefox Relay email alias.\n *\n * @param id - The ID of the alias to delete\n * @throws AuthError if authentication fails\n * @throws NotFoundError if the alias doesn't exist\n * @throws NetworkError if there's a network problem\n */\n async deleteAlias(id: number): Promise<void> {\n return this.relayApi.deleteAlias(id);\n }\n\n /**\n * Retrieves and parses emails from the CloudFlare temp email API.\n *\n * If aliasAddress is provided, only emails sent to that address are returned.\n *\n * @param aliasAddress - Optional email address to filter by\n * @param options - Query options for pagination\n * @returns Promise resolving to an array of ParsedEmail objects\n * @throws AuthError if authentication fails\n * @throws NetworkError if there's a network problem\n */\n async getEmails(\n aliasAddress?: string,\n options?: GetEmailsOptions\n ): Promise<ParsedEmail[]> {\n const limit = options?.limit ?? 20;\n const offset = options?.offset ?? 0;\n\n const emails = await this.cfApi.getMails(limit, offset);\n\n const parsedEmails: ParsedEmail[] = emails.map((email) => {\n const parsed = this.parser.parseEmail(email.raw);\n return {\n ...parsed,\n id: email.id,\n messageId: email.messageId,\n source: email.source,\n address: email.address,\n createdAt: email.createdAt,\n metadata: email.metadata,\n };\n });\n\n if (aliasAddress) {\n const normalizedAlias = aliasAddress.toLowerCase();\n return parsedEmails.filter(\n (email) =>\n email.relayAlias?.toLowerCase() === normalizedAlias ||\n email.address.toLowerCase() === normalizedAlias\n );\n }\n\n return parsedEmails;\n }\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@z_06/relay-temp-mail",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "type": "module",
5
5
  "description": "TypeScript npm package for Firefox Relay + CF temp email API",
6
6
  "main": "./dist/index.cjs",
@@ -18,7 +18,9 @@
18
18
  }
19
19
  }
20
20
  },
21
- "files": ["dist"],
21
+ "files": [
22
+ "dist"
23
+ ],
22
24
  "scripts": {
23
25
  "build": "tsup",
24
26
  "test": "vitest",