Integrations
Rackspace Email Integration
Troubleshooting

Rackspace Email Troubleshooting

This guide covers common issues, error messages, and solutions for the Rackspace Email integration.

Common Issues

Authentication Errors

Invalid API Credentials (401 Unauthorized)

Symptoms:

  • HTTP 401 errors from Rackspace API
  • "Invalid API credentials" error messages
  • All Rackspace API calls failing

Causes:

  • Incorrect API Key or Secret Key
  • Wrong Customer ID
  • Expired or revoked API credentials
  • Extra whitespace in environment variables

Solutions:

  1. Verify Environment Variables

    # Check that variables are set
    echo $RACKSPACE_API_KEY
    echo $RACKSPACE_SECRET_KEY
    echo $RACKSPACE_CUSTOMER_ID
  2. Check for Extra Whitespace

    # Remove any trailing spaces or newlines
    export RACKSPACE_API_KEY="$(echo $RACKSPACE_API_KEY | tr -d '[:space:]')"
    export RACKSPACE_SECRET_KEY="$(echo $RACKSPACE_SECRET_KEY | tr -d '[:space:]')"
  3. Regenerate API Credentials

    • Login to Rackspace Email Admin Panel
    • Navigate to My Account > API Keys
    • Revoke old key and generate new one
    • Update environment variables with new credentials
  4. Test API Connection

    // test-rackspace-auth.js
    const RackspaceClient = require('./sync/rackspace/lib/client');
     
    const client = new RackspaceClient({
      apiKey: process.env.RACKSPACE_API_KEY,
      secretKey: process.env.RACKSPACE_SECRET_KEY,
      customerId: process.env.RACKSPACE_CUSTOMER_ID
    });
     
    client.checkMailboxExists('test@natca.net')
      .then(() => console.log('✅ Authentication successful'))
      .catch(err => console.error('❌ Authentication failed:', err.message));

Signature Verification Failed

Symptoms:

  • "Invalid signature" error from Rackspace API
  • Authentication fails despite correct credentials

Causes:

  • Incorrect timestamp format (must be Unix timestamp in seconds)
  • Wrong User-Agent string
  • Signature calculation error
  • Clock synchronization issues

Solutions:

  1. Verify Timestamp Format

    // Correct: Unix timestamp in seconds
    const timestamp = Math.floor(Date.now() / 1000).toString();
     
    // Incorrect: milliseconds
    const badTimestamp = Date.now().toString(); // Don't use this
  2. Check User-Agent String

    // Must match exactly
    const userAgent = 'MyNATCA Platform'; // Correct
  3. Verify Signature Calculation

    const crypto = require('crypto');
     
    // Correct order: apiKey + userAgent + timestamp + secretKey
    const dataToSign = apiKey + userAgent + timestamp + secretKey;
    const signature = crypto.createHash('sha1').update(dataToSign).digest('hex');
     
    console.log('Data to sign:', dataToSign);
    console.log('Signature:', signature);
    console.log('Header:', `${apiKey}:${timestamp}:${signature}`);
  4. Check Server Time Synchronization

    # Verify server time is accurate
    date
    # If time is wrong, synchronize with NTP
    sudo ntpdate -s time.nist.gov

Email Creation Errors

Email Already Exists

Symptoms:

  • "Email address already exists" error
  • Creation fails even though availability check passed

Causes:

  • Race condition (another request created the email)
  • Email was created outside the platform
  • Cache/timing issue between availability check and creation

Solutions:

  1. Check Email in Rackspace Admin Panel

  2. Try Alternative Email Format

    // If jdoss@natca.net exists, try jason.doss@natca.net
    const formats = [
      `${firstName.charAt(0)}${lastName}@natca.net`,
      `${firstName}.${lastName}@natca.net`,
      `${firstName.charAt(0)}${lastName}2@natca.net` // Add number if needed
    ];
  3. Manual Cleanup If email exists but shouldn't:

    • Delete mailbox in Rackspace Admin Panel
    • Remove from emailinformation table in MySQL
    • Retry creation

Member Already Has NATCA Email

Symptoms:

  • "Member already has a @natca.net email" error
  • User reports they don't have an email but system says they do

Causes:

  • Email exists in database but not in Rackspace
  • Previous email creation failed partially
  • Database record not cleaned up after email deletion

Solutions:

  1. Check Database Record

    SELECT emailaddress, emailtypeid, isactive, createddate
    FROM emailinformation
    WHERE membernumber = '12345' AND emailaddress LIKE '%@natca.net';
  2. Verify Email in Rackspace

    const exists = await rackspaceClient.checkMailboxExists(email);
    console.log('Email exists in Rackspace:', exists);
  3. Cleanup Orphaned Records

    -- If email doesn't exist in Rackspace, remove database record
    DELETE FROM emailinformation
    WHERE membernumber = '12345'
      AND emailaddress = 'jdoss@natca.net'
      AND emailaddress NOT IN (SELECT email FROM rackspace_verified_emails);
  4. Or Mark as Inactive

    -- Safer option: mark as inactive instead of deleting
    UPDATE emailinformation
    SET isactive = 0
    WHERE membernumber = '12345' AND emailaddress = 'jdoss@natca.net';

Member Not Eligible

Symptoms:

  • "Only NATCA members are eligible" error
  • "Only Active or Retired members can receive @natca.net emails" error

Causes:

  • Member is not membertypeid=6 (NATCA member)
  • Member status is not Active or Retired
  • Member data is outdated

Solutions:

  1. Verify Member Type

    SELECT membernumber, firstname, lastname, membertypeid, status
    FROM members
    WHERE membernumber = '12345';
  2. Check Member Type Mapping

    // membertypeid values:
    // 6 = NATCA member (eligible)
    // Other values = ineligible
     
    if (member.membertypeid !== 6) {
      console.log('Member type:', member.membertypeid, '- Not NATCA');
    }
  3. Verify Member Status

    -- Eligible statuses
    SELECT * FROM members
    WHERE membernumber = '12345'
      AND status IN ('Active', 'Retired');
  4. Update Member Data If member data is outdated:

    • Trigger member sync from source system
    • Verify sync completed successfully
    • Retry email creation

Password Reset Errors

Email Not Found

Symptoms:

  • "Email not found or does not belong to this member" error
  • Password reset fails for valid email

Causes:

  • Email not in emailinformation table
  • Email belongs to different member
  • Typo in email address

Solutions:

  1. Verify Email Ownership

    SELECT membernumber, emailaddress
    FROM emailinformation
    WHERE emailaddress = 'jdoss@natca.net';
  2. Check Rackspace

    const exists = await rackspaceClient.checkMailboxExists('jdoss@natca.net');
    if (!exists) {
      console.log('Email does not exist in Rackspace');
    }
  3. Verify Member Number Match

    // Ensure member owns the email
    const [records] = await pool.query(
      'SELECT * FROM emailinformation WHERE membernumber = ? AND emailaddress = ?',
      [memberNumber, email]
    );
     
    if (records.length === 0) {
      console.log('Email does not belong to member', memberNumber);
    }

Password Doesn't Meet Requirements

Symptoms:

  • "Password does not meet requirements" error from Rackspace
  • Password reset fails despite using generated password

Causes:

  • Password generator bug
  • Rackspace requirements changed
  • Password too short or missing character types

Solutions:

  1. Verify Password Requirements

    function validatePassword(password) {
      const hasUppercase = /[A-Z]/.test(password);
      const hasLowercase = /[a-z]/.test(password);
      const hasNumber = /[0-9]/.test(password);
      const hasSpecial = /[!@#$%^&*]/.test(password);
     
      const typesPresent = [hasUppercase, hasLowercase, hasNumber, hasSpecial]
        .filter(Boolean).length;
     
      return password.length >= 8 && typesPresent >= 3;
    }
  2. Test Password Generator

    const password = rackspaceClient.generatePassword();
    console.log('Generated password:', password);
    console.log('Length:', password.length);
    console.log('Valid:', validatePassword(password));
  3. Update Password Generator If requirements changed, update generator in /sync/rackspace/lib/client.js

Database Errors

Failed to Update Member Profile

Symptoms:

  • Email created in Rackspace but not added to database
  • "Failed to update member profile" error

Causes:

  • MySQL connection failure
  • Database permissions issue
  • Duplicate key constraint violation
  • Table doesn't exist

Solutions:

  1. Verify Database Connection

    try {
      const [rows] = await pool.query('SELECT 1');
      console.log('✅ MySQL connection successful');
    } catch (error) {
      console.error('❌ MySQL connection failed:', error.message);
    }
  2. Check Table Exists

    SHOW TABLES LIKE 'emailinformation';
  3. Verify Permissions

    SHOW GRANTS FOR 'your_mysql_user'@'%';
    -- Should include INSERT, UPDATE, SELECT on emailinformation table
  4. Manual Record Creation If automatic insertion fails:

    INSERT INTO emailinformation (membernumber, emailaddress, emailtypeid, isactive)
    VALUES ('12345', 'jdoss@natca.net', 3, 1);
  5. Cleanup on Failure If database insertion fails after Rackspace creation:

    try {
      // Create in Rackspace
      await rackspaceClient.createMailbox(mailboxData);
     
      // Add to database
      await pool.query(insertQuery, values);
     
    } catch (error) {
      // Rollback: delete from Rackspace if database failed
      await rackspaceClient.deleteMailbox(emailAddress);
      throw error;
    }

Rate Limiting

Too Many Requests (429)

Symptoms:

  • HTTP 429 errors from Rackspace API
  • "Rate limit exceeded" messages
  • Intermittent failures during batch operations

Causes:

  • Exceeded Rackspace API rate limits (60 req/min)
  • Multiple concurrent requests
  • Retry loops without delays

Solutions:

  1. Implement Exponential Backoff

    async makeRequestWithRetry(url, options, maxRetries = 3) {
      for (let attempt = 1; attempt <= maxRetries; attempt++) {
        try {
          const response = await fetch(url, options);
     
          if (response.status === 429) {
            const retryAfter = response.headers.get('Retry-After') || 60;
            console.log(`Rate limited, waiting ${retryAfter}s...`);
            await this.sleep(retryAfter * 1000);
            continue;
          }
     
          return response;
     
        } catch (error) {
          if (attempt === maxRetries) throw error;
          await this.sleep(Math.pow(2, attempt) * 1000);
        }
      }
    }
  2. Add Request Queuing

    const queue = [];
    const RATE_LIMIT = 60; // requests per minute
    const INTERVAL = 60000 / RATE_LIMIT; // ms between requests
     
    async function queueRequest(requestFn) {
      queue.push(requestFn);
      if (queue.length === 1) {
        await processQueue();
      }
    }
     
    async function processQueue() {
      while (queue.length > 0) {
        const requestFn = queue.shift();
        await requestFn();
        await sleep(INTERVAL);
      }
    }
  3. Monitor Rate Limits

    logger.info('Rackspace API request', {
      endpoint: url,
      rateLimitRemaining: response.headers.get('X-RateLimit-Remaining'),
      rateLimitReset: response.headers.get('X-RateLimit-Reset')
    });

Debugging Tools

Enable Debug Logging

// In Rackspace client
const DEBUG = process.env.RACKSPACE_DEBUG === 'true';
 
function debugLog(message, data) {
  if (DEBUG) {
    console.log('[Rackspace Debug]', message, JSON.stringify(data, null, 2));
  }
}
 
// Usage
debugLog('Making request', { url, headers: { ...headers, 'X-Api-Signature': '***' } });

Test Individual Methods

// test-rackspace-methods.js
const RackspaceClient = require('./sync/rackspace/lib/client');
 
const client = new RackspaceClient({
  apiKey: process.env.RACKSPACE_API_KEY,
  secretKey: process.env.RACKSPACE_SECRET_KEY,
  customerId: process.env.RACKSPACE_CUSTOMER_ID
});
 
async function testMethods() {
  try {
    // Test 1: Check mailbox exists
    console.log('Test 1: Check mailbox exists');
    const exists = await client.checkMailboxExists('test@natca.net');
    console.log('Result:', exists);
 
    // Test 2: Generate password
    console.log('\nTest 2: Generate password');
    const password = client.generatePassword();
    console.log('Password:', password);
    console.log('Length:', password.length);
 
    // Test 3: Create mailbox (use test account)
    console.log('\nTest 3: Create mailbox');
    const result = await client.createMailbox({
      emailAddress: 'test123@natca.net',
      password: password,
      displayName: 'Test User',
      firstName: 'Test',
      lastName: 'User'
    });
    console.log('Created:', result);
 
    // Test 4: Reset password
    console.log('\nTest 4: Reset password');
    const newPassword = client.generatePassword();
    await client.resetPassword('test123@natca.net', newPassword);
    console.log('Password reset successful');
 
  } catch (error) {
    console.error('Test failed:', error.message);
    console.error('Stack:', error.stack);
  }
}
 
testMethods();

Verify API Signature

// verify-signature.js
const crypto = require('crypto');
 
function verifySignature(apiKey, secretKey, userAgent, timestamp) {
  const dataToSign = apiKey + userAgent + timestamp + secretKey;
  const signature = crypto.createHash('sha1').update(dataToSign).digest('hex');
  const header = `${apiKey}:${timestamp}:${signature}`;
 
  console.log('=== Signature Verification ===');
  console.log('API Key:', apiKey);
  console.log('User Agent:', userAgent);
  console.log('Timestamp:', timestamp);
  console.log('Secret Key:', '***' + secretKey.slice(-4));
  console.log('Data to sign:', dataToSign.replace(secretKey, '***'));
  console.log('SHA1 signature:', signature);
  console.log('X-Api-Signature header:', header);
}
 
// Usage
verifySignature(
  process.env.RACKSPACE_API_KEY,
  process.env.RACKSPACE_SECRET_KEY,
  'MyNATCA Platform',
  Math.floor(Date.now() / 1000).toString()
);

Check Database State

-- View all NATCA emails
SELECT membernumber, emailaddress, emailtypeid, isactive, createddate
FROM emailinformation
WHERE emailaddress LIKE '%@natca.net'
ORDER BY createddate DESC;
 
-- Count NATCA emails by status
SELECT isactive, COUNT(*) as count
FROM emailinformation
WHERE emailaddress LIKE '%@natca.net'
GROUP BY isactive;
 
-- Find members with multiple NATCA emails (should be none)
SELECT membernumber, COUNT(*) as email_count
FROM emailinformation
WHERE emailaddress LIKE '%@natca.net' AND isactive = 1
GROUP BY membernumber
HAVING COUNT(*) > 1;
 
-- Check for orphaned records (email in DB but not in Rackspace)
-- Run this with a script that checks Rackspace API
SELECT emailaddress
FROM emailinformation
WHERE emailaddress LIKE '%@natca.net' AND isactive = 1;

Error Messages Reference

Platform API Errors

Error MessageHTTP CodeCauseSolution
Authentication required401No Auth0 sessionLogin via Auth0
Member not found404Invalid member numberVerify member exists
Only NATCA members are eligible400membertypeid != 6Member must be NATCA
Only Active or Retired members400Invalid statusCheck member status
Member already has email400Existing NATCA emailUse password reset instead
Invalid email format400Email doesn't end with @natca.netUse correct domain
Email address already exists400Mailbox exists in RackspaceTry alternative format
Failed to create email account500Rackspace API errorCheck logs and retry
Failed to update member profile500Database errorCheck MySQL connection

Rackspace API Errors

Error MessageHTTP CodeCauseSolution
Invalid API credentials401Wrong API key/secretVerify credentials
Invalid signature401Signature calculation errorCheck timestamp and hash
Mailbox not found404Email doesn't existVerify email address
Mailbox already exists409Duplicate creationEmail is taken
Password does not meet requirements400Weak passwordUse password generator
Rate limit exceeded429Too many requestsImplement backoff
Mailbox quota exceeded403Account limit reachedContact Rackspace
Domain not found404Wrong customer IDVerify customer ID

Getting Help

Logs to Collect

When reporting issues, include:

  1. Platform Logs

    # View recent Rackspace-related logs
    grep "rackspace" /var/log/platform/platform.log | tail -50
  2. Error Details

    • Full error message
    • HTTP status code
    • Request parameters (redact sensitive data)
    • Timestamp of failure
  3. Environment Information

    • Platform version
    • Node.js version
    • Deployment environment (local/staging/production)
  4. Member Information

    • Member number
    • Member type ID
    • Member status
    • Existing emails in database

Escalation Path

  1. Check This Troubleshooting Guide
  2. Review Platform Logs
  3. Test Individual Components (API, database, Rackspace)
  4. Contact Platform Team with logs and error details
  5. Contact Rackspace Support if API issue confirmed

Related Documentation


This troubleshooting guide helps diagnose and resolve common Rackspace Email integration issues quickly and efficiently.