Questions and discussion about using ProcessMaker: user interface, running cases & functionality
By cosyxu
#794768
Hi Everyone,


Does anybody know how to show or include an upload attachment in an email template ?
1.PNG
1.PNG (12.17 KiB) Viewed 4004 times
My process is: a requester submit a "web-entry"form which includes a upload control, and then manager will receive an email template which includes the upload file for him to download or view.

Any ideas how it works ?

Many thanks.

Yuan
User avatar
By amosbatto
#794789
Yuan, I found a solution, but it involves hacking the PM source code, because the sendMessage() web service doesn't support email attachments.

First, edit the file workflow/engine/methods/services/soap2.php with a plain text editor and change the sendMessage() function definition starting on line 448 to:
Code: Select all
function SendMessage ($params)
{
    $vsResult = isValidSession( $params->sessionId );

    if ($vsResult->status_code !== 0) {
        return $vsResult->getPayloadArray();
    }

    if (ifPermission( $params->sessionId, 'PM_CASES' ) == 0) {
        $result = new wsResponse( 2, G::LoadTranslation('ID_NOT_PRIVILEGES') );

        return $result->getPayloadArray();
    }

    $ws = new wsBase();
    
    //set optional variables:
    $aVariables   = isset($params->variables)   ? json_decode($params->variables, true)   : null;
    $aAttachments = isset($params->attachments) ? json_decode($params->attachments, true) : null;
    $bShowMessage = isset($params->showMessage) ? $params->showMessage                    : true;
    $delIndex     = isset($params->delIndex)    ? $params->delIndex                       : 0;
    $aConfig      = isset($params->config)      ? json_decode($params->config, true)      : array();
    
    $res = $ws->sendMessage( $params->caseId, $params->from, $params->to, $params->cc, $params->bcc, $params->subject, $params->template, 
        $aVariables, $aAttachments, $bShowMessage, $delIndex, $aConfig);
    
    return $res->getPayloadArray();
}
Then, edit the file workflow/engine/methods/services/wsdl2.php and change the definition of sendMessageRequest starting on line 501 to:
Code: Select all
      <xs:element name="sendMessageRequest">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="sessionId" type="xs:string"/>
            <xs:element name="caseId" type="xs:string"/>
            <xs:element name="from" type="xs:string"/>
            <xs:element name="to" type="xs:string"/>
            <xs:element name="cc" type="xs:string"/>
            <xs:element name="bcc" type="xs:string"/>
            <xs:element name="subject" type="xs:string"/>
            <xs:element name="template" type="xs:string"/>
            <xs:element name="variables" minOccurs="0" type="xs:string"/>
            <xs:element name="attachments" minOccurs="0" type="xs:string"/>
            <xs:element name="showMessage" minOccurs="0" type="xs:integer"/>
            <xs:element name="delIndex" minOccurs="0" type="xs:integer"/>
            <xs:element name="config" minOccurs="0" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
Then, add an email template to your process whose filename is "newCase". Here is an example:
emailTemplateEmailFromWebEntry.png
emailTemplateEmailFromWebEntry.png (40.17 KiB) Viewed 3986 times
Then, edit the <STARTING-EVENT-UID>Post.php file which was generated for your web entry.
It is located at this location on your PM server:
<INSTALL-DIRECTORY>/shared/sites/<WORKSPACE>/public/<PROCESS-UID>/<STARTING-EVENT-UID>Post.php
For example on my server:
/opt/pm3.2/shared/sites/workflow/public/739008884599dbeafc7c8b1091050959/852722968599dbedd1e7980062377595Post.php

Change lines 156-7 from:
Code: Select all
        $aMessage["MESSAGE"] = "<br />Case created in ProcessMaker<br />Case Number: $caseNr <br />Case Id: $caseId<br />Case derivated to: $assign";
    } else {
To:
Code: Select all
        $aMessage["MESSAGE"] = "<br />Case created in ProcessMaker<br />Case Number: $caseNr <br />Case Id: $caseId<br />Case derivated to: $assign";
        
        if ($result->status_code != 0){
			throw new Exception("Error routing to the first task in the case: ".$result->message);
		}
		
        $nextUserId = $result->routing->userId;
        
        G::LoadClass("pmFunctions");
        
        $aUser = userInfo($nextUserId);
        $emailTo = $aUser['mail'];
        $fullNameTo = $aUser['firstname'].' '.$aUser['lastname'];
        
        //set to same email as used in account at Config -> Email Servers:
        $emailFrom = 'amosbatto@gmail.com'; 
        
        //set to the ID of the Input Document uploaded in the web entry form
        $inpDocId = '243906473599dc51508c834093761947';
        
        //lookup information about the uploaded file in the database:
        $sql = "SELECT * FROM APP_DOCUMENT WHERE APP_UID='$caseId' AND DOC_UID='$inpDocId'";
        $dbResult = executeQuery($sql);
        if (!is_array($dbResult) or count($dbResult) == 0) {
			throw new Exception("Unable to find uploaded file in the database with query:\n$sql");
        }
        
        $fileId   = $dbResult[1]['APP_DOC_UID'];
        $version  = $dbResult[1]['DOC_VERSION'];
        $filename = $dbResult[1]['APP_DOC_FILENAME'];
        $ext = pathinfo($filename, PATHINFO_EXTENSION);
        $path = PATH_DOCUMENT. G::getPathFromUID($caseId) .PATH_SEP. $fileId .'_'. $version .'.'. $ext;
        $aAttachments = array($path);
        
        $fileLink = (G::is_https() ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] .
           ($_SERVER['SERVER_PORT'] == 80 ? '' : ':'.$_SERVER['SERVER_PORT']) . 
           '/sys'.SYS_SYS.'/'.SYS_LANG.'/'.SYS_SKIN.'/cases/cases_ShowDocument?a='. $fileId .'&v='. $version;
        $aVars = array('productLink' => $fileLink);
        
        global $sessionId;
		global $client;
		
        $aParams = array (
           'sessionId'  => $sessionId,
           'caseId'     => $caseId,
           'from'       => $emailFrom,
           'to'         => $emailTo,
           'cc'         => '',
           'bcc'        => '',
           'subject'    => "New case #$caseNr",
           'template'   => 'newCase.html',
           'variables'  => json_encode($aVars),
           'attachments'=> json_encode($aAttachments)
        );
        $msgResult = $client->__SoapCall('sendMessage', array($aParams)); 
        
        if ($msgResult->status_code != 0) {
			throw new Exception("Error sending email: " . $msgResult->message);
		}        
    } else {
You will need to change $emailFrom and $inpDocId to match your system. This example shows how to set the variable "productLink" to display a link to the attached file, plus add it as an attached file to the email.

Note that your web entry form should only use File controls and not Multiple File controls, which currently don't work with web entry.

When the web entry form is submitted, you should receive an email like this:
EmailAttachmentFromWebEntry.png
EmailAttachmentFromWebEntry.png (37.14 KiB) Viewed 3986 times
Here is the sample process that I used to test this in PM 3.2:
(37.98 KiB) Downloaded 322 times
By cosyxu
#794830
Good morning Amosbatto,

Thank you for your detailed solution, it's really helpful.
:D

Yuan
By cosyxu
#812438
amosbatto wrote:Yuan, I found a solution, but it involves hacking the PM source code, because the sendMessage() web service doesn't support email attachments.

First, edit the file workflow/engine/methods/services/soap2.php with a plain text editor and change the sendMessage() function definition starting on line 448 to:
Code: Select all
function SendMessage ($params)
{
    $vsResult = isValidSession( $params->sessionId );

    if ($vsResult->status_code !== 0) {
        return $vsResult->getPayloadArray();
    }

    if (ifPermission( $params->sessionId, 'PM_CASES' ) == 0) {
        $result = new wsResponse( 2, G::LoadTranslation('ID_NOT_PRIVILEGES') );

        return $result->getPayloadArray();
    }

    $ws = new wsBase();
    
    //set optional variables:
    $aVariables   = isset($params->variables)   ? json_decode($params->variables, true)   : null;
    $aAttachments = isset($params->attachments) ? json_decode($params->attachments, true) : null;
    $bShowMessage = isset($params->showMessage) ? $params->showMessage                    : true;
    $delIndex     = isset($params->delIndex)    ? $params->delIndex                       : 0;
    $aConfig      = isset($params->config)      ? json_decode($params->config, true)      : array();
    
    $res = $ws->sendMessage( $params->caseId, $params->from, $params->to, $params->cc, $params->bcc, $params->subject, $params->template, 
        $aVariables, $aAttachments, $bShowMessage, $delIndex, $aConfig);
    
    return $res->getPayloadArray();
}
Then, edit the file workflow/engine/methods/services/wsdl2.php and change the definition of sendMessageRequest starting on line 501 to:
Code: Select all
      <xs:element name="sendMessageRequest">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="sessionId" type="xs:string"/>
            <xs:element name="caseId" type="xs:string"/>
            <xs:element name="from" type="xs:string"/>
            <xs:element name="to" type="xs:string"/>
            <xs:element name="cc" type="xs:string"/>
            <xs:element name="bcc" type="xs:string"/>
            <xs:element name="subject" type="xs:string"/>
            <xs:element name="template" type="xs:string"/>
            <xs:element name="variables" minOccurs="0" type="xs:string"/>
            <xs:element name="attachments" minOccurs="0" type="xs:string"/>
            <xs:element name="showMessage" minOccurs="0" type="xs:integer"/>
            <xs:element name="delIndex" minOccurs="0" type="xs:integer"/>
            <xs:element name="config" minOccurs="0" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
Then, add an email template to your process whose filename is "newCase". Here is an example:
emailTemplateEmailFromWebEntry.png
Then, edit the <STARTING-EVENT-UID>Post.php file which was generated for your web entry.
It is located at this location on your PM server:
<INSTALL-DIRECTORY>/shared/sites/<WORKSPACE>/public/<PROCESS-UID>/<STARTING-EVENT-UID>Post.php
For example on my server:
/opt/pm3.2/shared/sites/workflow/public/739008884599dbeafc7c8b1091050959/852722968599dbedd1e7980062377595Post.php

Change lines 156-7 from:
Code: Select all
        $aMessage["MESSAGE"] = "<br />Case created in ProcessMaker<br />Case Number: $caseNr <br />Case Id: $caseId<br />Case derivated to: $assign";
    } else {
To:
Code: Select all
        $aMessage["MESSAGE"] = "<br />Case created in ProcessMaker<br />Case Number: $caseNr <br />Case Id: $caseId<br />Case derivated to: $assign";
        
        if ($result->status_code != 0){
			throw new Exception("Error routing to the first task in the case: ".$result->message);
		}
		
        $nextUserId = $result->routing->userId;
        
        G::LoadClass("pmFunctions");
        
        $aUser = userInfo($nextUserId);
        $emailTo = $aUser['mail'];
        $fullNameTo = $aUser['firstname'].' '.$aUser['lastname'];
        
        //set to same email as used in account at Config -> Email Servers:
        $emailFrom = 'amosbatto@gmail.com'; 
        
        //set to the ID of the Input Document uploaded in the web entry form
        $inpDocId = '243906473599dc51508c834093761947';
        
        //lookup information about the uploaded file in the database:
        $sql = "SELECT * FROM APP_DOCUMENT WHERE APP_UID='$caseId' AND DOC_UID='$inpDocId'";
        $dbResult = executeQuery($sql);
        if (!is_array($dbResult) or count($dbResult) == 0) {
			throw new Exception("Unable to find uploaded file in the database with query:\n$sql");
        }
        
        $fileId   = $dbResult[1]['APP_DOC_UID'];
        $version  = $dbResult[1]['DOC_VERSION'];
        $filename = $dbResult[1]['APP_DOC_FILENAME'];
        $ext = pathinfo($filename, PATHINFO_EXTENSION);
        $path = PATH_DOCUMENT. G::getPathFromUID($caseId) .PATH_SEP. $fileId .'_'. $version .'.'. $ext;
        $aAttachments = array($path);
        
        $fileLink = (G::is_https() ? 'https://' : 'http://') . $_SERVER['SERVER_NAME'] .
           ($_SERVER['SERVER_PORT'] == 80 ? '' : ':'.$_SERVER['SERVER_PORT']) . 
           '/sys'.SYS_SYS.'/'.SYS_LANG.'/'.SYS_SKIN.'/cases/cases_ShowDocument?a='. $fileId .'&v='. $version;
        $aVars = array('productLink' => $fileLink);
        
        global $sessionId;
		global $client;
		
        $aParams = array (
           'sessionId'  => $sessionId,
           'caseId'     => $caseId,
           'from'       => $emailFrom,
           'to'         => $emailTo,
           'cc'         => '',
           'bcc'        => '',
           'subject'    => "New case #$caseNr",
           'template'   => 'newCase.html',
           'variables'  => json_encode($aVars),
           'attachments'=> json_encode($aAttachments)
        );
        $msgResult = $client->__SoapCall('sendMessage', array($aParams)); 
        
        if ($msgResult->status_code != 0) {
			throw new Exception("Error sending email: " . $msgResult->message);
		}        
    } else {
You will need to change $emailFrom and $inpDocId to match your system. This example shows how to set the variable "productLink" to display a link to the attached file, plus add it as an attached file to the email.

Note that your web entry form should only use File controls and not Multiple File controls, which currently don't work with web entry.

When the web entry form is submitted, you should receive an email like this:
EmailAttachmentFromWebEntry.png
Here is the sample process that I used to test this in PM 3.2:
Email_file_from_web_entry-3.pmx
Hi Amosbatto,

I was wondering whether there is any updated method to achieve this?

If I start by submitting a web-entry Dynaform, it send to the manager an email which contains a link(Link to a form), in this case, could the attachments in the "web-entry Dynaform" display at the "manager Dynaform"?

If it doesn't, could you please advise how can I add links of attachment in the "manager Dynaform" ? (I have to use ABE function)

http://wiki.processmaker.com/3.0/File_c ... _file_info would this possible?

Many thanks,
Yuan

However, it is essential to use it responsibly and[…]

Web3 development encompasses creating decentralize[…]

The Upland Clone Script, offered by Dappsfirm, rep[…]

Dappsfirm offers a bet365 clone script that mirror[…]