Integrations
Rackspace Email Integration
API Workflows

Rackspace Email API Workflows

This guide provides detailed workflows for all Rackspace Email integration operations, including email creation, availability checking, and password management.

Authentication Workflow

All Rackspace API requests require authentication via the X-Api-Signature header.

Signature Generation Process

const crypto = require('crypto');
 
function generateSignature(apiKey, secretKey, userAgent = 'MyNATCA Platform') {
  // 1. Get current Unix timestamp (seconds)
  const timestamp = Math.floor(Date.now() / 1000).toString();
 
  // 2. Concatenate components
  const dataToSign = apiKey + userAgent + timestamp + secretKey;
 
  // 3. Generate SHA1 hash
  const signature = crypto
    .createHash('sha1')
    .update(dataToSign)
    .digest('hex');
 
  // 4. Format header value
  const headerValue = `${apiKey}:${timestamp}:${signature}`;
 
  return {
    timestamp,
    signature,
    headerValue
  };
}
 
// Usage
const auth = generateSignature(
  process.env.RACKSPACE_API_KEY,
  process.env.RACKSPACE_SECRET_KEY
);
 
const headers = {
  'X-Api-Signature': auth.headerValue,
  'User-Agent': 'MyNATCA Platform',
  'Content-Type': 'application/json'
};

Authentication Headers

Every Rackspace API request includes:

X-Api-Signature: apiKey:timestamp:sha1Hash
User-Agent: MyNATCA Platform
Content-Type: application/json

Email Availability Check Workflow

Checks if proposed email formats are available before creation.

Flow Diagram

User Request

Platform API: Validate Session

Platform API: Get Member Info

Platform API: Generate Email Formats

Rackspace API: Check Format 1 (jdoss@natca.net)

Rackspace API: Check Format 2 (jason.doss@natca.net)

Platform API: Return Available Formats

User Response

API Endpoint

POST /api/rackspace/check-availability
Authorization: Session Cookie (Auth0)
Content-Type: application/json

Request

{
  "memberNumber": "12345"
}

Implementation

// 1. Validate Auth0 session
if (!req.session || !req.session.user) {
  return res.status(401).json({ error: 'Authentication required' });
}
 
// 2. Fetch member data from MySQL
const [members] = await pool.query(
  'SELECT membernumber, firstname, lastname, membertypeid, status FROM members WHERE membernumber = ?',
  [memberNumber]
);
 
if (members.length === 0) {
  return res.status(404).json({ error: 'Member not found' });
}
 
const member = members[0];
 
// 3. Validate member eligibility
if (member.membertypeid !== 6) {
  return res.status(400).json({
    error: 'Only NATCA members are eligible for @natca.net emails'
  });
}
 
if (!['Active', 'Retired'].includes(member.status)) {
  return res.status(400).json({
    error: 'Only Active or Retired members can receive @natca.net emails'
  });
}
 
// 4. Check for existing NATCA email
const [existing] = await pool.query(
  "SELECT emailaddress FROM emailinformation WHERE membernumber = ? AND emailaddress LIKE '%@natca.net'",
  [memberNumber]
);
 
if (existing.length > 0) {
  return res.status(400).json({
    error: 'Member already has a @natca.net email',
    existingEmail: existing[0].emailaddress
  });
}
 
// 5. Generate email format options
const formats = [
  `${member.firstname.charAt(0).toLowerCase()}${member.lastname.toLowerCase()}@natca.net`,
  `${member.firstname.toLowerCase()}.${member.lastname.toLowerCase()}@natca.net`
];
 
// 6. Check availability with Rackspace
const availableFormats = [];
for (const format of formats) {
  const exists = await rackspaceClient.checkMailboxExists(format);
  if (!exists) {
    availableFormats.push(format);
  }
}
 
// 7. Return results
res.json({
  memberNumber: member.membernumber,
  firstName: member.firstname,
  lastName: member.lastname,
  availableFormats
});

Response

{
  "memberNumber": "12345",
  "firstName": "Jason",
  "lastName": "Doss",
  "availableFormats": [
    "jdoss@natca.net",
    "jason.doss@natca.net"
  ]
}

Error Responses

Member Not Eligible

{
  "error": "Only NATCA members are eligible for @natca.net emails"
}

Already Has Email

{
  "error": "Member already has a @natca.net email",
  "existingEmail": "jdoss@natca.net"
}

No Formats Available

{
  "memberNumber": "12345",
  "firstName": "Jason",
  "lastName": "Doss",
  "availableFormats": []
}

Email Creation Workflow

Creates a new @natca.net email account for an eligible member.

Flow Diagram

User Request (selects email format)

Platform API: Validate Session

Platform API: Validate Member Eligibility

Platform API: Check No Existing NATCA Email

Platform API: Generate Secure Password

Rackspace API: Create Mailbox

Platform API: Add Email to Member Profile (MySQL)

Platform API: Return Credentials (password shown once)

User Response (save password)

API Endpoint

POST /api/rackspace/create-email
Authorization: Session Cookie (Auth0)
Content-Type: application/json

Request

{
  "memberNumber": "12345",
  "emailFormat": "jdoss@natca.net"
}

Implementation

// 1. Validate session and member eligibility (same as availability check)
 
// 2. Validate email format
if (!emailFormat.endsWith('@natca.net')) {
  return res.status(400).json({ error: 'Invalid email format' });
}
 
// 3. Verify email doesn't already exist
const exists = await rackspaceClient.checkMailboxExists(emailFormat);
if (exists) {
  return res.status(400).json({
    error: 'Email address already exists',
    email: emailFormat
  });
}
 
// 4. Generate secure password
const password = rackspaceClient.generatePassword();
// Returns: 16-char password with uppercase, lowercase, numbers, special chars
 
// 5. Create mailbox in Rackspace
await rackspaceClient.createMailbox({
  emailAddress: emailFormat,
  password: password,
  displayName: `${member.firstname} ${member.lastname}`,
  firstName: member.firstname,
  lastName: member.lastname
});
 
// 6. Add email to member profile in MySQL
await pool.query(
  'INSERT INTO emailinformation (membernumber, emailaddress, emailtypeid, isactive) VALUES (?, ?, ?, ?)',
  [memberNumber, emailFormat, 3, 1] // emailtypeid=3 for organizational email
);
 
// 7. Log successful creation
logger.info('NATCA email created', {
  memberNumber,
  email: emailFormat,
  service: 'rackspace'
});
 
// 8. Return credentials (password shown once)
res.json({
  success: true,
  email: emailFormat,
  password: password,
  message: 'Email created successfully. Save your password - it will not be shown again.'
});

Response

{
  "success": true,
  "email": "jdoss@natca.net",
  "password": "Xy9#mK2@pL5qR8zA",
  "message": "Email created successfully. Save your password - it will not be shown again."
}

Rackspace API Call

POST https://api.emailsrvr.com/v1/customers/{customerId}/domains/natca.net/rs/mailboxes
X-Api-Signature: apiKey:timestamp:signature
User-Agent: MyNATCA Platform
Content-Type: application/json
 
{
  "name": "jdoss",
  "password": "Xy9#mK2@pL5qR8zA",
  "displayName": "Jason Doss",
  "firstName": "Jason",
  "lastName": "Doss",
  "enabled": true
}

Error Responses

Email Already Exists

{
  "error": "Email address already exists",
  "email": "jdoss@natca.net"
}

Rackspace API Error

{
  "error": "Failed to create email account",
  "message": "Rackspace API error: Mailbox quota exceeded"
}

Database Error

{
  "error": "Failed to update member profile",
  "message": "Unable to save email to database"
}

Password Reset Workflow

Resets the password for an existing @natca.net email account.

Flow Diagram

User Request (existing email)

Platform API: Validate Session

Platform API: Verify Member Owns Email

Platform API: Generate New Secure Password

Rackspace API: Reset Mailbox Password

Platform API: Return New Password (shown once)

User Response (save new password)

API Endpoint

POST /api/rackspace/reset-password
Authorization: Session Cookie (Auth0)
Content-Type: application/json

Request

{
  "memberNumber": "12345",
  "email": "jdoss@natca.net"
}

Implementation

// 1. Validate session
if (!req.session || !req.session.user) {
  return res.status(401).json({ error: 'Authentication required' });
}
 
// 2. Validate email belongs to member
const [emailRecords] = await pool.query(
  'SELECT emailaddress FROM emailinformation WHERE membernumber = ? AND emailaddress = ?',
  [memberNumber, email]
);
 
if (emailRecords.length === 0) {
  return res.status(404).json({
    error: 'Email not found or does not belong to this member'
  });
}
 
// 3. Verify email exists in Rackspace
const exists = await rackspaceClient.checkMailboxExists(email);
if (!exists) {
  return res.status(404).json({
    error: 'Email account not found in Rackspace',
    email
  });
}
 
// 4. Generate new secure password
const newPassword = rackspaceClient.generatePassword();
 
// 5. Reset password in Rackspace
await rackspaceClient.resetPassword(email, newPassword);
 
// 6. Log password reset
logger.info('NATCA email password reset', {
  memberNumber,
  email,
  service: 'rackspace'
});
 
// 7. Return new password (shown once)
res.json({
  success: true,
  email,
  newPassword,
  message: 'Password reset successfully. Save your new password - it will not be shown again.'
});

Response

{
  "success": true,
  "email": "jdoss@natca.net",
  "newPassword": "Bz7!nQ4@wP9xM2yH",
  "message": "Password reset successfully. Save your new password - it will not be shown again."
}

Rackspace API Call

PUT https://api.emailsrvr.com/v1/customers/{customerId}/domains/natca.net/rs/mailboxes/jdoss
X-Api-Signature: apiKey:timestamp:signature
User-Agent: MyNATCA Platform
Content-Type: application/json
 
{
  "password": "Bz7!nQ4@wP9xM2yH"
}

Error Responses

Email Not Found

{
  "error": "Email not found or does not belong to this member"
}

Rackspace API Error

{
  "error": "Failed to reset password",
  "message": "Rackspace API error: Mailbox not found"
}

Password Generation

Generates secure passwords meeting Rackspace requirements.

Requirements

  • Minimum length: 8 characters
  • Character types: At least 3 of 4 types:
    • Uppercase letters (A-Z)
    • Lowercase letters (a-z)
    • Numbers (0-9)
    • Special characters (!@#$%^&*)

Implementation

generatePassword(length = 16) {
  const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  const lowercase = 'abcdefghijklmnopqrstuvwxyz';
  const numbers = '0123456789';
  const special = '!@#$%^&*';
 
  // Ensure at least one of each type
  let password = '';
  password += uppercase[Math.floor(Math.random() * uppercase.length)];
  password += lowercase[Math.floor(Math.random() * lowercase.length)];
  password += numbers[Math.floor(Math.random() * numbers.length)];
  password += special[Math.floor(Math.random() * special.length)];
 
  // Fill remaining length with random characters from all sets
  const allChars = uppercase + lowercase + numbers + special;
  for (let i = password.length; i < length; i++) {
    password += allChars[Math.floor(Math.random() * allChars.length)];
  }
 
  // Shuffle password to randomize character positions
  return password.split('').sort(() => Math.random() - 0.5).join('');
}

Example Output

const password = generatePassword();
// Returns: "Xy9#mK2@pL5qR8zA" (16 characters)
 
// Breakdown:
// - 4 uppercase: X, K, R, A
// - 5 lowercase: y, m, p, q, z
// - 4 numbers: 9, 2, 5, 8
// - 3 special: #, @, @

Complete Integration Example

Member Hub Frontend

// Member Hub: Check availability
async function checkEmailAvailability(memberNumber) {
  const response = await fetch('/api/rackspace/check-availability', {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ memberNumber })
  });
 
  const data = await response.json();
 
  if (!response.ok) {
    throw new Error(data.error || 'Failed to check availability');
  }
 
  return data;
}
 
// Member Hub: Create email
async function createEmail(memberNumber, emailFormat) {
  const response = await fetch('/api/rackspace/create-email', {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ memberNumber, emailFormat })
  });
 
  const data = await response.json();
 
  if (!response.ok) {
    throw new Error(data.error || 'Failed to create email');
  }
 
  // Display password to user (one-time display)
  alert(`Your email has been created!\n\nEmail: ${data.email}\nPassword: ${data.password}\n\nSave this password - it will not be shown again!`);
 
  return data;
}
 
// Member Hub: Reset password
async function resetPassword(memberNumber, email) {
  const response = await fetch('/api/rackspace/reset-password', {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ memberNumber, email })
  });
 
  const data = await response.json();
 
  if (!response.ok) {
    throw new Error(data.error || 'Failed to reset password');
  }
 
  // Display new password to user (one-time display)
  alert(`Password reset successful!\n\nEmail: ${data.email}\nNew Password: ${data.newPassword}\n\nSave this password - it will not be shown again!`);
 
  return data;
}

Error Handling

try {
  // Check availability
  const availability = await checkEmailAvailability('12345');
 
  if (availability.availableFormats.length === 0) {
    showError('No email formats available. Please contact support.');
    return;
  }
 
  // User selects format
  const selectedFormat = availability.availableFormats[0];
 
  // Create email
  const result = await createEmail('12345', selectedFormat);
 
  showSuccess(`Email created: ${result.email}`);
 
} catch (error) {
  console.error('Email creation error:', error);
  showError(error.message);
}

Rate Limiting and Retry Logic

Rackspace API Rate Limits

Rackspace Email API typically allows:

  • Rate limit: 60 requests per minute per API key
  • Concurrent requests: Maximum 10 concurrent requests

Retry Implementation

async makeRequest(url, options, retries = 3) {
  for (let attempt = 1; attempt <= retries; attempt++) {
    try {
      const response = await fetch(url, options);
 
      // Success
      if (response.ok) {
        return response;
      }
 
      // Rate limited - wait and retry
      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After') || 60;
        logger.warn('Rate limited, retrying', { attempt, retryAfter });
        await this.sleep(retryAfter * 1000);
        continue;
      }
 
      // Other errors - throw
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
 
    } catch (error) {
      if (attempt === retries) {
        throw error;
      }
 
      // Exponential backoff
      const delay = Math.pow(2, attempt) * 1000;
      logger.warn('Request failed, retrying', { attempt, delay });
      await this.sleep(delay);
    }
  }
}

Related Documentation


These workflows ensure reliable and secure email account management for NATCA members through the Rackspace Email integration.