Send an email

To send emails to other SAFE Network users, you need to know their email ID.

First, the app retrieves the encryption key associated with the appendable data that belongs to the recipient. Then, it encrypts the email using that encryption key and saves it as immutable data. Finally, it appends the immutable data that represents the email to the appendable data of the recipient.

Contents

Compose Mail page

The JSON data for the above email would look like this:

{
  "subject": "Test",
  "from": "example",
  "time": "Fri, 16 Sep 2016 10:49:44 GMT",
  "body": "123"
}

Get the appendable data of the recipient

Before fetching the encryption key of the recipient, the app needs to obtain an appendable data handle.

Get a data identifier handle

First, the app fetches a data identifier handle for the appendable data of the recipient.

POST /data-id/appendable-data

data_id_handle_actions.js

export const getAppendableDataIdHandle = (token, name) => ({
  type: ACTION_TYPES.GET_STRUCTURED_DATA_ID_HANDLE,
  payload: {
    request: {
      method: 'post',
      url: '/data-id/appendable-data',
      headers: {
        'Authorization': token
      },
      data: {
        isPrivate: true,
        name
      }
    }
  }
});

The name of the appendable data is obtained by hashing the email ID of the recipient:

app_utils.js

export const hashEmailId = emailId => {
  return crypto.createHash('sha256').update(emailId).digest('base64');
};

Get an appendable data handle

The app fetches an appendable data handle using the data identifier handle previously obtained.

GET /appendable-data/handle/:dataIdHandle

appendable_data_actions.js

export const fetchAppendableDataHandle = (token, dataIdHandle) => { // id => appendable data id
  return {
    type: ACTION_TYPES.FETCH_APPENDABLE_DATA_HANDLER,
    payload: {
      request: {
        url: `/appendable-data/handle/${dataIdHandle}`,
        headers: {
          'Authorization': token,
          'Is-Private': true
        }
      }
    }
  };
};

Drop the data identifier handle

The app drops the data identifier handle for the appendable data of the recipient.

DELETE /data-id/:handleId

data_id_handle_actions.js

export const dropHandler = (token, handleId) => ({
  type: ACTION_TYPES.DROP_HANDLER,
  payload: {
    request: {
      method: 'delete',
      url: `/data-id/${handleId}`,
      headers: {
        'Authorization': token
      }
    }
  }
});

Get the encryption key of the recipient

After the appendable data handle is successfully obtained, the app fetches an handle for the public encryption key of the recipient. By encrypting your email using that encryption key, only the recipient will be able to read it. This is known as asymmetric encryption.

GET /appendable-data/encrypt-key/:handleId

appendable_data_actions.js

export const getEncryptedKey = (token, handleId) => ({
  type: ACTION_TYPES.GET_ENCRYPTED_KEY,
  payload: {
    request: {
      url: `/appendable-data/encrypt-key/${handleId}`,
      headers: {
        'Authorization': token
      }
    }
  }
});

Get a cipher options handle

The app fetches a cipher options handle for asymmetric encryption using the encryption key handle of the recipient.

GET /cipher-opts/:encType/:keyHandle?

cipher-opts_actions.js

export const getCipherOptsHandle = (token, encType, keyHandle='') => ({
  type: ACTION_TYPES.GET_CIPHER_OPTS_HANDLE,
  payload: {
    request: {
      url: `/cipher-opts/${encType}/${keyHandle}`,
      headers: {
        'Authorization': token,
      }
    }
  }
});

Drop the encryption key handle

The app drops the encryption key handle of the recipient.

DELETE /appendable-data/encrypt-key/:handleId

appendable_data_actions.js

export const deleteEncryptedKey = (token, handleId) => ({
  type: ACTION_TYPES.DELETE_ENCRYPTED_KEY,
  payload: {
    request: {
      method: 'delete',
      url: `/appendable-data/encrypt-key/${handleId}`,
      headers: {
        'Authorization': token
      }
    }
  }
});

Create the email

The app creates an email using the cipher handle that contains the encryption key of the recipient.

Get an immutable data writer handle

First, the app fetches an immutable data writer handle.

GET /immutable-data/writer

immutable_data_actions.js

export const createImmutableDataWriterHandle = (token) => ({
  type: ACTION_TYPES.CREATE_IMMUT_WRITER_HANDLE,
  payload: {
    request: {
      url: `/immutable-data/writer`,
      headers: {
        'Authorization': token
      }
    }
  }
});

Write immutable data

The app stores the email as immutable data using the immutable data writer handle.

POST /immutable-data/:handleId

immutable_data_actions.js

export const writeImmutableData = (token, handleId, data) => {
  const dataByteArray = new Uint8Array(new Buffer(JSON.stringify(data)));
  return {
    type: ACTION_TYPES.WRITE_IMMUT_DATA,
    payload: {
      request: {
        method: 'post',
        url: `/immutable-data/${handleId}`,
        headers: {
          'content-type': 'text/plain',
          'Authorization': token
        },
        data: dataByteArray
      }
    }
  };
};

Close the immutable data writer

The app encrypts the data map of the email using the cipher handle that contains the encryption key handle of the recipient. The data map is stored as immutable data on the SAFE Network.

PUT /immutable-data/:handleId/:cipherOptsHandle

immutable_data_actions.js

export const putImmutableData = (token, handleId, cipherOptsHandle) => ({
  type: ACTION_TYPES.PUT_IMMUT_DATA,
  payload: {
    request: {
      method: 'put',
      url: `/immutable-data/${handleId}/${cipherOptsHandle}`,
      headers: {
        'Authorization': token,
      }
    }
  }
});

Once the write operation is successful, the API returns a data identifier handle for the data map of the email.

Drop the immutable data writer handle

The app drops the immutable data writer handle.

DELETE /immutable-data/writer/:handleId

immutable_data_actions.js

export const closeImmutableDataWriter = (token, handleId) => ({
  type: ACTION_TYPES.CLOSE_IMMUT_DATA_WRITER,
  payload: {
    request: {
      method: 'delete',
      url: `/immutable-data/writer/${handleId}`,
      headers: {
        'Authorization': token,
      }
    }
  }
});

Append the email to the appendable data

The app adds the data identifier handle representing your email to the appendable data of the recipient.

PUT /appendable-data/:handleId/:dataIdHandle

appendable_data_actions.js

export const appendAppendableData = (token, handleId, dataIdHandle) => ({
  type: ACTION_TYPES.APPEND_APPENDABLE_DATA,
  payload: {
    request: {
      method: 'put',
      url: `/appendable-data/${handleId}/${dataIdHandle}`,
      headers: {
        'Authorization': token
      }
    }
  }
});

Drop the appendable data handle

After your email is successfully appended to the appendable data of the recipient, the app drops the appendable data handle.

DELETE /appendable-data/handle/:handleId

appendable_data_actions.js

export const dropAppendableDataHandle = (token, handleId) => ({
  type: ACTION_TYPES.DROP_APPENDABLE_DATA_HANDLE,
  payload: {
    request: {
      method: 'delete',
      url: `/appendable-data/handle/${handleId}`,
      headers: {
        'Authorization': token
      }
    }
  }
});

Last updated

Was this helpful?