Aurora Corporate documentation

Converting mail messages to PDF using Web API

Aurora Corporate allows for saving mails as PDF files. Assuming this functionality is enabled and properly configured, it is possible to convert mail messages to PDF using Web API as well.

Below we'll go through the complete working sample that lets you download email message from IMAP, convert external images and fetch inline ones to be embedded as base64-encoded data, run conversion to PDF and provide a download link. You can download the sample here.

NB: The purpose of the sample is to demonstrate use of Web API for mail message processing. When used in production, the code should be reviewed with regard to data sanitizing, error handling, obtaining initial parameters and processing the results.

To solve this task, we'll need two helper functions - one will send Web API requests to Aurora Corporate backend, the other one will allow for downloading attachments from the server:

function postdata($sUrl, $aPost, $sToken="") {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $sUrl);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,0);
    curl_setopt($curl, CURLOPT_HEADER,0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $aPost);
    if ($sToken!="") curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$sToken));
    $result = curl_exec($curl);
    curl_close($curl);
    if ($result !== false) {
        $result=json_decode($result,true);
    }
    return $result;
} 
    
function download($sUrl, $sToken="") {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $sUrl);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,0);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,0);
    curl_setopt($curl, CURLOPT_HEADER,0);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER,1);
    curl_setopt($curl, CURLOPT_POST, 1);
    if ($sToken!="") curl_setopt($curl, CURLOPT_HTTPHEADER, array('Authorization: Bearer '.$sToken));
    $result = curl_exec($curl);
    curl_close($curl);
    return $result;
}

Both the functions do their job via cURL. postdata() function is used for Web API calls; Login method of Core module will be used to get authentication token which will subsequently be used in all the requests.

Now we can proceed with the main part of the sample and define the values we'll need to retrieve the message: email address and password of the account, IMAP folder, and message UID.

$sUsername = 'user@domain.com';
$sPassword = 'PassW0rd';
$sFolder = 'INBOX';
$iUID = 12345;
$sUrl = 'http://localhost/webmail/';
$sQuery = $sUrl.'?/Api/';

As mentioned above, the first thing to do is logging into the account and obtaining authentication token:

$aLoginParams = ['Module' => 'Core', 'Method' => 'Login', 'Parameters' => 
    '{"Login": "'.$sUsername.'", "Password": "'.$sPassword.'"}'
];
$aLoginResult = postdata($sQuery, $aLoginParams);
if (isset($aLoginResult["Result"]["AuthToken"])) 
{
    $sToken = $aLoginResult["Result"]["AuthToken"];
    ...
}

We'll also require account ID, GetAuthenticatedAccount method of Core module will do that for us:

$aAccountParams = ['Module' => 'Core', 'Method' => 'GetAuthenticatedAccount', 'Parameters' => '{"AuthToken": "'.$sToken.'"}'];
$aAccountResults = postdata($sQuery, $aAccountParams, $sToken);
if (isset($aAccountResults["Result"]["EntityId"]))
{
    $iAccountID = intval($aAccountResults["Result"]["EntityId"]);
    ...    
}

Now we're ready to retrieve specific message, we already have its UID, folder name and ID of the email account:

$aMsgParams = ['Module' => 'Mail', 'Method' => 'GetMessagesBodies', 'Parameters' => 
    '{"AccountID": '.$iAccountID.', "Folder": "'.$sFolder.'", "Uids": ['.$iUID.']}'
];
$aMsgResults = postdata($sQuery, $aMsgParams, $sToken);

If the message body was correctly downloaded, we can get its HTML body as well as message subject - in Aurora Corporate interface, message subject is used as a filename for a *.PDF file.

if (isset($aMsgResults["Result"][0])) 
{
    $aMsg = $aMsgResults["Result"][0];
    $sSubj = $aMsg["Subject"];
    $sHtml = $aMsg["Html"]; 
    ...
}

For safety reasons, external images are not displayed in email messages by default, and instead of <img src=...> syntax, images are presented as <img data-x-src=...> instead. But in the scenario of converting mail messages to PDF, images aren't displayed for the user and the entire conversion is done on backend, so it's safe to display all the external images, we just need to search and replace HTML accordingly:

$sHtml = str_replace('data-x-src="','src="',$sHtml);

It's much more tricky with the inline images. Each of them needs to be downloaded individually, and supplied in HTML source in base64 encoding. This is where we'll require download() function defined earlier.

if (is_array($aMsg["Attachments"]) && count($aAttachments = $aMsg["Attachments"]["@Collection"])>0) {
    foreach ($aAttachments as $aAttach) {
        if (in_array($aAttach["CID"], $aMsg["FoundedCIDs"])) {
            $sFile = download($sUrl.$aAttach["Actions"]["download"]["url"], $sToken);
            $sMime = $aAttach["MimeType"];
            $sHtml = str_replace('data-x-src-cid="'.$aAttach["CID"].'"','src="data:'.$aAttach["MimeType"].';base64,'.base64_encode($sFile).'"',$sHtml);
        }
    }
}

Now we have the email message presented in HTML, with external and inline images in place, and we can send it into PDF converter to obtain the result.

$sHtml = str_replace(["\r","\n","\t"],"",$sHtml);
$aPdfParams = ['Module' => 'MailSaveMessageAsPdfPlugin', 'Method' => 'GeneratePdfFile', 'Parameters' => 
    '{"Filename": "'.$aMsg["Subject"].'", "Html": "'.str_replace('"','\"',$sHtml).'"}'
];
$aPdfResults = postdata($sQuery, $aPdfParams, $sToken);
$sPDF = $sUrl.$aPdfResults["Result"]["Actions"]["download"]["url"];

Finally, we get a download link for PDF file we have just created. If you need to process the file further, store it on the server filesystem etc., you can use download() function to obtain the file, you'll need to supply token there as well.

You can download the sample here.