logic hook, email body stripped

I noticed that in 7.6.2.2 when I send an email with html tags the email body is stripped.

I use the following function to send emails from logic hooks:

<?php
  //Function to send Email message

  function sendEmail($ToEmailAdd, $FromEmailAdd, $FromEmailName, $EmailSubject, $EmailBody) {
    global $sugar_config;
    $GLOBALS['log']->debug('PREPARE EMAIL to ' . print_r($ToEmailAdd, true));
    require_once ('modules/Emails/Email.php');
    if(is_array($ToEmailAdd)){
      $To = $ToEmailAdd;
    }else{
      $To = explode(';',$ToEmailAdd);
    }
    $now = gmdate("Y-m-d H:i:s");
    foreach ($To as $to_addr){
       $GLOBALS['log']->debug('PREPARE EMAIL TO:' . $to_addr);
       if (filter_var($to_addr, FILTER_VALIDATE_EMAIL)){
                $email = new Email();
                $email->to_addrs_arr = array(array('email' => $to_addr));
                $email->to_addrs = $to_addr;
                $email->from_addr = $FromEmailAdd;
                $email->from_name = $FromEmailName;
                //empty values are necessary to avoid undefined errors in Email.php
                $email->cc_addrs_arr = array();
                $email->bcc_addrs_arr = array();
                $email->saved_attachments = array();
                $email->name = $EmailSubject;
                $email->description_html = $EmailBody;
$GLOBALS['log']->fatal("<br><b>Sending:</b><p>To: " .$to_addr. "<br>From: " . $FromEmailAdd. "<br>From Name: " . $FromEmailName. "<br>Subject: " . $EmailSubject. "<p> " . $EmailBody . "<br>");
                $email->status = 'sent';
                $email->type = 'out';
                $email->date_sent = $now;
                $email->send();
                $email->save();
                $GLOBALS['log']->debug('EMAIL SENT:' . $email->id);
        }
    }
    return;
  }
?>

This is used in several logic hooks for notifications.

For example in Cases when an email is received on a certain department's queue it will notify the people in that department.

This has worked well from 6.x to 7.6.2.1 but after the upgrade to 7.6.2.2 the body of the email gets stripped.

        $EmailBody=<<<BODY
New email received on [CASE:{$c->case_number}] $c->name<br>
Current Case Status: $c->status<br>
Assigned to: $user->user_name<br>
From: {$email->from_addr_name} ( {$email->from_addr} )<br>
To: {$email->to_addrs}<br>
Cc: {$email->cc_addrs}<br>
Subject: $email->name<br>
See: {$sugar_config['site_url']}/#Cases/{$c->id}
<br>
<br>
{$email_text}
BODY;

As of 7.6.2.2

The email record in the database only contains the content of the $email_text in emails_text.description_html
while if I assign the $EmailBody to the $email->description field, it contains the full html tags included.

However, the Log entry from the sendEmail function returns the full body which makes me think that it's the 

$email->send() that somehow strips the first 10 lines. 

Has anyone else experienced this? have you found a solution that works for you?

Support will not look into it because it involves custom code.

Thank you,

Francesca

  • Unfortunate that they've changed this, I've relied on it in the past. However, two points that may work:

    So checking the Email class (in modules/Email.php) in the save function there's a line:

    $this->description_html = SugarCleaner::cleanHtml($this->description_html, true);

    You can try and override this class and change that line (not 100% sure it's causing the problem, but it's the most likely culprit, I wouldn't recommend overriding core classes).

    An alternative approach comes to mind:

    There is an Mail restful endpoint that takes html_body as a parameter (you can find the documentation at <yoursugarinstance>/rest/v10/help. There are ways to use rest within the system, but as someone humorously pointed out - it's like leaving through a window and coming back through the door. Additionally, it's asynchronous, which might not work for your system.

    However, if it uses html_body as a parameter, then it obviously can take html as an argument. In 7.7, the API endpoint is in modules/Emails/clients/base/api/MailApi.php. Either you can instantiate the class ($mailAPI = new MailApi();) and then run the function it uses to send mail ($mailAPI->handleMail(null, $args);) - just make sure your arguments are all valid and in the format it expects. Alternatively, reading the function, it uses the MailRecord to actually send the mail, which is in modules/Emails/MailRecord.php - you can just call that class directly. This approach requires rewriting and retesting your mail classes, so a lot more effort, but I suspect the Email object is on the way to being deprecated if it isn't used in version 10 of the API. 

    Let me know how you get along in either approach.

  • It would not be the first time the cleaner is the issue, Defect #72698 SugarCRM, Inc. and Defect #7899 SugarCRM, Inc. have been big problems for us since upgrading to v7 but I dare not go to 7.7.x yet because of all the reported issues with those higher versions.

    I looked at the API code

    modules/Emails/clients/base/api/MailApi.php

    it seems they use html_body and text_body in  

     

    protected function initMailRecord($args)
            $mailRecord->html_body = $args[self::HTML_BODY];
            $mailRecord->text_body = $args[self::TEXT_BODY];

    I updated my scripts to use

    $email->html_body

    instead of 

    $email->description_html

    But that makes no difference.

    I tested via API and it seems to work fine

    $rest = "https://our_sugar_server.com/sugarcrm/rest/v10";
    $user = "theusername"; // userid of the webservice user
    $pass = "thepassword"; // and the password of user “user”


    $html_body =<<<BODY
    New email received on [CASE:1234] Some case name<br>
    Current Case Status: c->status<br>
    Assigned to: user->user_name<br>
    From: email->from_addr_name ( email->from_addr )<br>
    To: email->to_addrs<br>
    Cc: email->cc_addrs<br>
    Subject: email->name<br>
    See: sugar_config['site_url']/#Cases/c->id
    <br>
    <br>
    Some other text
    BODY;

    $api_to_test = '/Mail';

    $test_params = array(
      "email_config"=>'d9fb25dc-b886-4f76-9775-57e94d5129c4',
      "to_addresses"=>array(array('name'=>'Francesca','email'=>'francesca.shiekh@myaddress.com')),
      "subject"=>"test Mail API",
      "html_body"=>$html_body,
      "status"=>"ready",
      "teams"=>array("primary"=>"1")
    );

    $url = $rest . "/oauth2/token"; // login
    $oauth2_token_parameters = array(
      "grant_type" => "password",
      "client_id" => "sugar",
      "client_secret" => "",
      "username" => $user,
      "password" => $pass,
      "platform" => "base"
    );

    $oauth2_token_result = call($url, '', 'POST', $oauth2_token_parameters);
    if (empty($oauth2_token_result->error)){
      //logged in ok
    echo('logged in ok <p>');
      $url = $rest . $api_to_test;
    echo($url.'<p>');
      $post_result = call($url, $oauth2_token_result->access_token, 'create', $test_params);
    echo('<pre>');
    var_dump($post_result);
      $url = $rest . "/oauth2/logout"; // logout
      $oauth2_logout_result = call($url, $oauth2_token_result->access_token, 'POST');
    }else{
      print("<hr>THAT WAS NOT OK<hr>"); // login not successful
    }

    function call($url, $oauthtoken='', $type='GET', $parameters=array())
    {
       $type = strtoupper($type);
       $curl_request = curl_init($url);
       if ($type == 'POST')
       {
          curl_setopt($curl_request, CURLOPT_POST, 1);
       }
       elseif ($type == 'PUT')
       {
          curl_setopt($curl_request, CURLOPT_CUSTOMREQUEST, "PUT");
       }
       elseif ($type == 'DELETE')
       {
          curl_setopt($curl_request, CURLOPT_CUSTOMREQUEST, "DELETE");
       }
       curl_setopt($curl_request, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
       curl_setopt($curl_request, CURLOPT_HEADER, false);
       curl_setopt($curl_request, CURLOPT_SSL_VERIFYPEER, 0);
       curl_setopt($curl_request, CURLOPT_RETURNTRANSFER, 1);
       curl_setopt($curl_request, CURLOPT_FOLLOWLOCATION, 0);
       if (!empty($oauthtoken))
       {
          $token = array("oauth-token: {$oauthtoken}");
          curl_setopt($curl_request, CURLOPT_HTTPHEADER, $token);
       }
       if (!empty($parameters))
       {
          //encode the parameters as JSON
          $jsonEncodedData = json_encode($parameters);
          curl_setopt($curl_request, CURLOPT_POSTFIELDS, $jsonEncodedData);
       }
       $result = curl_exec($curl_request);
       curl_close($curl_request);
       //decode the response from JSON
       $response = json_decode($result);
       return $response;
    }
    ?>

    Next step to figure out the differences between my sendmail and their API

    thanks,

    Francesca

  • The difference is the class you're instantiating. In your version, you've got the following code:

    require_once ('modules/Emails/Email.php');
    //...followed by
    $email = new Email();
    //...followed by
    $email->send();
    $email->save();

    In theirs, they have:

    require_once('modules/Emails/MailRecord.php');
    //..eventually followed by
    $mailRecord = new MailRecord();
    //..eventually followed by
    $mailRecord->send();

    There may be other subtle differences between the two classes but fundamentally they've moved to a completely new class to send emails.

  • With a combination of greps and looking at what they use for workflow notification I have the following which works:

    <?php
      //Function to send Email message
      //one email per recipient

    function sendEmail($ToEmailAdd, $FromEmailAdd, $FromEmailName, $EmailSubject, $EmailBody) {
      global $sugar_config;
      $GLOBALS['log']->debug('PREPARE EMAIL to ' . print_r($ToEmailAdd, true));
      require_once ('modules/Emails/Email.php');
      if(is_array($ToEmailAdd)){
        $To = $ToEmailAdd;
      }else{
        $To = explode(';',$ToEmailAdd);
      }
      foreach ($To as $to_addr){
        $GLOBALS['log']->debug('PREPARE EMAIL TO:' . $to_addr);
        if (filter_var($to_addr, FILTER_VALIDATE_EMAIL)){
          try{
            $phpMailer = MailerFactory::getSystemDefaultMailer();
            $mailTransmissionProtocol = $phpMailer->getMailTransmissionProtocol();
            $FromEmailIdentity = new EmailIdentity($FromEmailAdd, $FromEmailName);
            $header_array = array(
              'From'=>$FromEmailIdentity,
              'ReplyTo'=>'',
              'Sender'=>$FromEmailIdentity, //mandatory
              'Subject'=>$EmailSubject,
            );
            $phpMailer->constructHeaders($header_array);
            $phpMailer->addRecipientsTo(new EmailIdentity($to_addr, $to_addr));
            $phpMailer->setHtmlBody($EmailBody);
            $phpMailer->send();
          }catch(MailerException $me) {
            $message = $me->getMessage();
            $GLOBALS["log"]->warn(
              "SendGroupEmail: error sending e-mail (method: {$mailTransmissionProtocol}), (error: {$message})"
            );
          }
        }
      }
      return;
    }
    ?>

    you can also add Cc recipients and BCc recipients similar to the To.

    To use plain text use $phpMailer->setTextBody($EmailBody)

    Hope this helps someone else.

    FrancescaS