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

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?