Sending Email from 4th Dimension Version 6.5


ACI - Documentation Français English German ACI Technical Notes ACI Technical Notes, By Subject Back Previous Next

Sending Email from 4th Dimension Version 6.5

By Steve Hussey, CEO, Alto Stratus LLC

Technical Note 99-26

Technical Notes for Technical Notes for 99-06-June 1999

Introduction


With the 'Internet Commands' plug-in (formerly PDM's Internet Toolkit), 4D v6.5 becomes a powerful tool for automating email. 4D v6.5 provides you with the tools to both send (SMTP) and receive email (POP3). This technical note demonstrates how to send email and attachments to a selection of contacts.

While it is easy to send and receive email through standard email clients such as Eudora or Outlook Express, they have limited means for sending email to selections of recipients. Although most email clients offer some support for creating groups of email addresses, they have limited capabilities for managing them. You can easily manage contact records in a database, indexing them by various criteria, to allow for searching and sorting them as required.

A typical example might be an invoicing system. With email functionality you could:

Email an order acknowledgment.

Send confirmation of shipping details with UPS/FedEx tracking numbers.

Announce new products.

Announce updates/upgrades to users of specific product versions.

Send software updates to registered users.

Chase slow payers for payment of invoices past due.

Requirements


4D v6.0.x with PDM's Internet Toolkit or 4D v6.5 with the Internet Commands plug-in installed. The 4D v6.5 installer installs the Internet Commands in the new universal 4DX folder.

An internet connection: the connection can be a dial up connection via modem or a full time connection.

The 4D installer installs the plug-in in the new universal plug-in folder:

On Mac OS this is in the System:Preferences:ACI:Mac4DX folder.

On Windows this is in the C:\Windows\ACI\Win4DX folder.

Plug-ins installed in the new universal folder are automatically accessible to all copies of 4D v6.5/4D Server v6.5 installed on that computer. They do not appear in the 'normal' Mac4DX/Win4DX folders.

Getting Started


When you first launch the Email 4D database, you will be sequentially prompted for two items of data:

Your return email address in the format name@domain.com

Your SMTP server name in the form smtp.domain.com

You need to complete these fields or edit them later, before sending email. Your return email address will be used to complete the 'From:' field in the message. Your SMTP server address is the address of the server that will be used to actually transmit your email.

Contact Data


The enclosed sample database contains only two fields:

Name field

Email address

In this example, the email address is contained in only one field. One problem that may occur with this approach is that 4D uses the '@' character as its search wildcard. Therefore, searching fields with the '@' character embedded, such as email addresses, may cause problems. There are two ways around this problem:

New database property

On the Data Control tab of the Database Properties dialog there is a new option:

Consider @ as a character for Query and Order By

This new option allows you to treat the '@' character as a normal character for queries as long as it is not the first or last character in the string.

Treating the email address as two fields

Another way to deal with this problem is to store the email address in two fields:

Email field

Domain field

The two fields can then be concatenated with an '@' character when required. This has some additional advantages, one of which is that it is easy to query on domains. Some proprietary services, such as America On Line (AOL), have limits on the size of attachments that can be handled. Your code could be modified so that it did not send attachments to email at specific domains.

The sample database has menu items to add and list contacts. There is a valid email address for you to use in the database, and you can add further addresses as required.

Building an Email Message


Choose Send Email from the Select Email menu.

This displays the email dialog where you can compose your message and select an attachment if desired.

Type an appropriate subject.

Enter a message.

 Click the File button to add an attachment. This displays the standard file open document.

Select a file and click OK. The file name will be displayed in the Attachment field.

 Select an appropriate encoding method for the attachment.

 Click Send.

The message will now be sent to all the contacts in this database. A dialog will display the message count as they are sent. If you selected a file attachment it will be sent to all the contacts.

The Code


Called from the Email: Send Email menu item, the EMLR_Send project method is the starting point for the code:

   C_TEXT(strSubject;textBody;textFilePath;textFilePathEncoded)

   strSubject := ""
   textBody := ""
   textFilePath := ""
   textFilePathEncoded := ""
   $Address := ""

The list of desired encoding methods is stored in the list 'Encoding'. Only a few options have been placed in this list -- Internet Commands supports further encoding methods. The list is then copied to the array, which is the drop-down menu on the dialog.

   LIST TO ARRAY("Encoding"; aryEncoding)  ` << List contains the encoding methods available to the user
   The default value (in this case 'None') is then set.
   aryEncoding := 1  ` << Set to default value 'None'

The WND_Cntr method opens a window centered on the current screen – whatever its resolution.

   WND_Cntr (550; 575; 5; "Message"; "WND_CLS")

Now display an appropriate dialog:

   DIALOG ([Contact]; "MSG_Bulk_Mail_DLG")  ` << Display a dialog for email message entry

Close the window after the user clicks OK or Cancel.

   CLOSE WINDOW

If the user clicked OK rather than Cancel

   If (ok = 1)

Here is a cheap and cheerful way to load the preferences record. This record contains your return email address (in the form of name@domain.com) and the address of the SMTP server (in the form smtp.domain.com) that are used to send your email.

      ALL RECORDS ([Preference])  `<< Do something here to load the prefs record

Display a message window for the status message:

      WND_Msg ("Emailing")  ` << Open a status window
      MESSAGE ("Opening TCP Connection")

Execute the EMLR_OpenPPP project method:

      EMLR_OpenPPP   ` << We need to ensure that we have an open TCP connection

This executes the following code:

      $Platform := IT_Platform   ` << What version of Internet Commands are we running, Mac or Win?

The IT_Platform command returns a number that indicates which platform version of the Internet Commands is currently executing.

      If ($Platform < 2)  ` << Mac OS version is executing
      $Err:=IT_MacTCPInit 

On Mac OS you need to ensure that the TCP drivers are loaded. You can do so by using the IT_MacTCPInit function. This function has an unexpected and useful benefit: loading the TCP drivers opens a TCP connection. If a PPP connection was specified in the Mac TCP setup, then the modem will dial up the connection.

      Else 
      ` << Windows - no equivalent
      End if

There is no equivalent for Windows. The Windows TCP connection needs to be open before you start sending email.

Then back to the calling method and erase the message window:


      ERASE WINDOW

Build a selection of contacts to email to:

      ALL RECORDS ([Contact])  ` << Or work on the desired selection of contacts

It is best to encode an attachment before emailing it to recipients. Strictly speaking, you don't need to encode a file before transmission, but you can never be certain about what email client our recipient will be using or what platform they are on. To ensure that the file arrives undamaged, you need to choose an appropriate encoding method. BinHex works well for most email clients and platforms. Its disadvantage is that it increases the file size of the encoded file by about 40 to 50%.


Since you are sending the same file to multiple recipients, it should be encoded before the loop that sends the email. This will save a lot of time, since the file will only be encoded once, not for every contact.


      If (textFilePath # "")  ` << If there is a file attachment decide on encoding method selected
         Case of 
            : (aryEncoding {aryEncoding} = "None")
             $Encode := 0
            : (aryEncoding {aryEncoding} = "Binhex")
             $Encode := 1
            : (aryEncoding {aryEncoding} = "AppleSingle")
             $Encode := 3
            : (aryEncoding {aryEncoding} = "UUEncode")
             $Encode := 7
            : (aryEncoding {aryEncoding} = "MacBinary")
             $Encode := 8
         Else 
             $Encode := 0
         End case 
         $err := IT_Encode (textFilePath; textFilePathEncoded; $Encode)  ` << Encode the file here
         ` << Encode it once only since we are sending the same file each time
      End if

This line of code does the encoding:

      $err := IT_Encode (textFilePath; textFilePathEncoded; $Encode)

textFilePath is the path to the file you have selected as the attachment. textFilePathEncoded is the resulting path of the encoded file. The original file is not changed in any way -- an encoded copy is created in the same folder as the original. Later we will have to dispose of this file. $Encode is the numerical value of the encoding method desired.

You can now loop through the selection of contacts to send the email:

      For ($Contacts; 1; Records in selection([Contact]))
         GOTO XY (0;0)
         MESSAGE (String ($Contacts)+" of "+String (Records in selection ([Contact])))
         If ([Contact]Email_Address # "") ` << Ensure that there is an email address
            EMLR_SndMsg (strSubject; textBody; [Contact]Email_Address; textFilePathEncoded)
         End if 
         NEXT RECORD ([Contact])
      End for

The EMLR_SndMsg project method creates and sends the email.

      ` $1 = Subject
      ` $2 = Body
      ` $3 = address
      ` $4 = Path to Attachment
      $Subject := $1
      $Body := $2
      $Address := $3
      $Attachment := $4

The subject, body, target address and path to the attachment are passed to this method as parameters. Here they are reassigned to local variables for clarity.

First, you need to create a new SMTP email message. The SMTP_New function does this and returns a reference ID that will be used by the rest of the code.

      $err : = SMTP_New ($SMTP_ID)  
         ` << Creates a new SMTP message

Specify the SMTP host through which the email is being transmitted:

      $err := SMTP_Host ($SMTP_ID; [Preference]Mail_Host)  
         ` << Specifies the SMTP mail host to transmit the email

Specify your return email address:

      $err := SMTP_From ($SMTP_ID; [Preference]Return_Email)  
         ` << Senders return email address

You can specify a date and time for transmission using the SMTP_Date command:

         ` << Optionally use SMTP_Date to set date and time
         ` << If no date the SMTP host will set it automatically

If no date and time are specified, the SMTP host will automatically date and time stamp your message as it is transmitted.

Next, the subject is specified:


      $err := SMTP_Subject ($SMTP_ID; $Subject)  
         ` << Email subject

The recipient's email address is provided:

      $err := SMTP_To ($SMTP_ID; $Address)  
         ` << Recipient

The body of the message:

      $err := SMTP_Body ($SMTP_ID; $Body)  
         ` << Body of the message

If there is an attachment, it can now be specified:

   $err := SMTP_Attachment ($SMTP_ID; $Attachment; 0)  
         ` << Already encoded outside of the loop, just attach it

Since it is the same attachment that is being sent each time we have encoded it once, earlier. The attachment that we are specifying here is the encoded copy, not the original.

Now the message can be sent:

      $err := SMTP_Send ($SMTP_ID)  
         ` << Send the message

The final action is to clear the message from memory.

      $err := SMTP_Clear ($SMTP_ID)  
         ` << Clear the sent message from memory: Essential!!

Returning to the calling method, the transmission loop is completed.

         End if 
         NEXT RECORD ([Contact])
      End for 
   End if 

After completing the transmission, there is one final task -- disposing of the encoded file attachment (if there was one).

   If (textFilePathEncoded # "")  ` << Delete the encode file if there was one
      DELETE DOCUMENT (textFilePathEncoded)
   End if 

Potential refinements

Consider storing email addresses in a many table, related to the contacts table. Many people have multiple email addresses, and companies are likely to have multiple addresses too.

Create a template file to store frequently used standard messages.

Allow for personalization of the messages so that each recipient would be addressed appropriately within the body of the message.

Store a copy of the sent message with each contact record, or store a date, time and reference to the message sent.

Create a log of bulk email sent.

Ignore sending attachments greater than a specific size to certain domains. You could create a table of domains with their attachment limits.

Create background processes to send email at off-peak times to avoid overloading the email server.

Summary


The new Internet Commands plug-in is a powerful cross-platform solution for sending and receiving email from within a 4D database. If you do not need to send attachments you can use the quick send command:

   SMTP_QuickSend (hostName; msgFrom; msgTo; subject; message)

The SMTP commands enable you to build email messages based on the content of database records and send these messages with encoded attachments.

Use Your New Powers for Good, Not Evil


Sending unsolicited email is known as spamming. Besides annoying the recipients, this could lead to your email account being closed. Many Internet Service Providers are taking a hard line on spammers. If recipients of your mass mailings complain to your ISP, they might close your account. It is therefore important to ensure that you have the recipients' permission to send them email.


ACI - Documentation Français English German ACI Technical Notes ACI Technical Notes, By Subject Back Previous Next