Using the Document Service to Send Emails from FileMaker
This feature within the Document Service was developed to address a common challenge faced by a client. They needed to send a large number of invoices, more than 500, to their customers regularly. While they had a FileMaker script in place to generate the invoices as PDFs and use the SEND MAIL script step to email them, they encountered an intermittent issue. Occasionally, only the email text was sent, without the attached PDF. Despite various attempts to troubleshoot, the problem persisted. It seemed that the FileMaker send-mail function had some quirks. With no time to wait for a FileMaker solution, we decided to explore an alternative approach to resolve the client's issue.
The solution was to leverage the DocumentService function within the ACF Plugin to send the emails, and it turned out to be a highly effective approach. As the mail sending occurs on the server side, we only had to implement the needed functionality on the SOAP service, and not in the Plugin itself.
Here's how it works:
Preparing the Mail Parameters File
- Create a text file containing mail parameters. This file is saved in the document archive using the
dsPD_SaveDocument
function. The format of this file consists of several parameters separated by double pipe characters (||). The filename should include a serial number, ensuring a unique connection between the attachment and the parameter file.
Example:
logo.gif||fromName||fromemail@doe.com||ToName||toEmail@doe.com||ccemail@doe.com||bccemail@doe.com||MessageSubject||MessageBody
Saving the PDF File
- Next, save the actual PDF file. Append the filename with double pipes, the text "SENDMAIL," and the name of the data file saved in the previous step.
Example:
invoice-10662.pdf||SENDMAIL||data-<serial number>.txt
The SaveDocument
function within the Document Service will open the referenced data file, extract its contents into their respective parameters, and send the email with the attached PDF file.
In the document service index.php file:
public static function SaveDocument($params) {
// some intro handling.
..
..
// Check if we are going to send e-mail:
$re = '/.+?\|\|SENDMAIL\|\|data-.+?.txt/i';
// $str = 'logo.gif||fromName||fromemail@doe.com||ToName||toEmail@doe.com||ccemail@doe.com||bccemail@doe.com||MessageSubject||MessageBody';
$isMailSend = preg_match_all($re, $params->FileName, $matches, PREG_SET_ORDER, 0);
// if true, then it does the mail sending option after saving the document.
..
..
Permanent Feature
We've permanently integrated this feature into the Document Service, making it available for broader use. It's not limited to solving specific issues and can be a valuable tool for various scenarios where emails need to be sent efficiently.
Example Usage:
// Prepare the mail parameter file content
Set Variable [ $FileContent; "logo.gif||fromName||fromemail@doe.com||ToName||toEmail@doe.com||ccemail@doe.com||bccemail@doe.com||Invoice number 10662 from MyCompany.com||
Dear Customer,
Here is the attached invoice for this month's subscription.
Best Regards,
MyCompany.com"]
// Save the parameter file to a temporary location using an ACF Function
Set Variable [$res; ACFU_SaveFile ( "data-00123.txt"; $FileContent)]
// Send the data file to the Document Service
// We use Keyword "UPDATE" to ensure the service does not change the filename. If it happens to be there from before.
Set Variable [$res; dsPD_SaveDocument( "data-00123.txt" ; "data-00123.txt"; "UPDATE" )]
// Send the PDF file, naming it "invoice-10662.pdf"
Set Variable [$res; dsPD_SaveDocument( "invoice-10662.pdf||SENDMAIL||data-00123.txt" ; "invoice-10662.pdf"; "UPDATE" )]
As a result, the recipient at toEmail@doe.com will receive an email with the invoice attached. This function operates swiftly, making it ideal for sending a large number of invoices efficiently.
Let's improve the snippet and add some verification for each function call. We'll also provide error handling messages when the result is not OK. Here's the updated code:
// Prepare the mail parameter file content
Set Variable [ $FileContent; "logo.gif||fromName||fromemail@doe.com||ToName||toEmail@doe.com||ccemail@doe.com||bccemail@doe.com||Invoice number 10662 from MyCompany.com||
Dear Customer,
Here is the attached invoice for this month's subscription.
Best Regards,
MyCompany.com"]
// Save the parameter file to a temporary location using an ACF Function
Set Variable [$paramFile; "data-00123.txt"]
Set Variable [$res; ACFU_SaveFile ( $paramFile; $FileContent)]
// Verify the result of saving the parameter file
If [$res ≠ "1"]
Show Custom Dialog [ "Error"; "Failed to save the parameter file. Error: " & $res ]
Exit Script []
End If
// Send the data file to the Document Service
// We use Keyword "UPDATE" to ensure the service does not change the filename. If it happens to be there from before.
Set Variable [$updateAction; "UPDATE"]
Set Variable [$res; dsPD_SaveDocument( $paramFile ; $paramFile ; $updateAction )]
// Verify the result of sending the data file
If [GetValue($res;1) ≠ "OK"]
Show Custom Dialog [ "Error"; "Failed to send the data file. Error: " & $res ]
Exit Script []
End If
// Send the PDF file, naming it "invoice-10662.pdf"
Set Variable [$pdfFileName; "invoice-10662.pdf"]
Set Variable [$SendMailFunction; "SENDMAIL"]
Set Variable [$res; dsPD_SaveDocument( $pdfFileName & "||" & $SendMailFunction & "||" & $paramFile ; $pdfFileName ; $updateAction )]
// Verify the result of sending the PDF file
If [GetValue($res;1) ≠ "OK"]
Show Custom Dialog [ "Error"; "Failed to send the PDF file. Error: " & $res ]
Exit Script []
End If
With this updated code, we've added verification checks after each function call and display an error message if the result is not "OK." This helps ensure robust error handling while avoiding clutter in the example.
This is also an example on how you can tailor the document service, implementing more functions in it adding properties to the parameters and do other things as well, you could easely do the following:
- Implement a keyword in the "GetDocument" function, to retrieve a file listing of the directory applied in the PATH parameter,
- Implement a keyword in the "GetDocument" function, to delete a file from the archive.
Important Note:
If you intend to utilize the encryption feature within the plugin, please be aware that the files are encrypted before being sent to the service. Consequently, it's essential to decrypt them on the SOAP service before transmission; otherwise, it will not function as intended. Refer to the example provided for the dsPD_GetPHPSampleEncryptDecryptCode
function in the function reference for guidance on implementing decryption using the DocumentEncryptionKey.
Unfortunately, there is no direct way to turn off document encryption when its first enabled. If you need to send unencrypted documents to the service, like here, you can use the dsPD_AuthBase64Encrypted
withhout the document-encryption key tag. See the introduction on how to use this. It is then important to turn the encryption on again when the mail operation is complete.