CapeSoft.Com
Clarion Accessories
NetTalk
Doc Index
Email
CapeSoft Logo

CapeSoft NetTalk
Email

Download Latest Version
Installed Version Latest Version

NetTalk Email

Introduction

Almost all programs can benefit from Sending and/or Receiving emails. NetTalk makes it easy to add simple, or sophisticated, email handling abilities directly into your application.

Emails are sent using the SMTP protocol.

Emails are received using either the POP3 or IMAP protocol.

Upgrading

In NetTalk 10 (specifically 10.22 and later) some of the properties changed from STRING values to STRINGTHEORY objects. Because assigning a value to an object using the = sign causes a GPF, the names of the properties have changed. This means that if you have used the old properties in your embed code then you will get a compile error.

If you get a compile error in your code then you can replace the old property name, and syntax, with the new property name and syntax.

These changes affect Email Sending (SMTP), Email Receiving (POP3 and IMAP) classes.

Old SyntaxNew Syntax
x = email.WholeMessageLenx = email.WholeMessageST.Length()
s = email.WholeMessages = email.WholeMessageST.GetValue()
x = email.MessageTextLenx = email.MessageTextST.Length()
s = email.MessageTexts = email.MessageTextST.GetValue()
email.MessageText = semail.MessageTextST.SetValue(clip(s))
x = email.MessageHTMLLenx = email.MessageHTMLST.Length()
s = email.MessageHTMLs = email.MessageHTMLST.GetValue()
email.MessageHTML = semail.MessageHtmlST.SetValue(clip(s))
if Imap.wholeMessageLenif Imap.wholeMessageST.Length()
x = email.BufferLenx = email.BufferST.Length()
s = email.Buffers = email.BufferST.GetValue()
The prototype for the following methods have changed;


MethodNameChange
EmbedImagesFirst parameter has changed from a *string to a StringTheory object.
The following methods are no longer required, and if you have called them in your embed code then you can just remove the call;
MethodName
SetRequiredMessageSize

JumpStart

Sending Emails

The example in \clarion\examples\NetTalk\Email\Demo\ABC is the best email example. And you can import various dictionary tables and procedures directly from there to speed things along. References to "the example" in the text below are referring to this example. A Legacy version of this example is in  \clarion\examples\NetTalk\Email\Demo\Legacy

In order to be able to send emails from your application there are really only a few basic things to do;
  1. Allow the user to enter server connection settings somewhere so that your program knows which server to send to.
  2. Optionally, create a EmailLog table in your dictionary, and add a browse on this to your app.
  3. Create a SendEmail procedure which you can call from anywhere in your code.
  4. Add a call to SendEmail in all the various places where you wish to send emails.

Server Connection Settings

A number of settings are used when connecting to a server. These settings can vary from one installation to the next so it's important to allow the user to capture these. Once set (on one workstation) the settings are usually valid for all the workstations so (assuming the settings are visible to all machines) no per-workstation setup is required.

You could add these settings to your existing shared settings table or you could create a new table. The settings are as follows:
  • EmailServer (String 255)
    This is the URL of the server. It's sometimes an IP address (eg 192.168.1.1) or a DNS name (eg mail.capesoft.com)
  • EmailPort (Long) (A long.
    The default value should be 25. Values of 587, 990 and 465 are also commonly used.
  • AlwaysSSL (Long).
    A boolean value (0 or 1) this is set to 1 if the connection to the server is always over TLS
  • StartTLS (Long)
    A boolean value (0 or 1) this is set to 1 if the connection starts normally but then a STARTTLS command switches it to TLS.
  • SSLMethod (Long)
    The TLS version to use when connecting to the server. The default is TLS 1.2, 1.1 or 1.0 (in that order).
  • UserName (String 255)
    The user name for the user on the server.
  • Password (String 255)
    The password for this user when connecting to the server
  • FromAddress (String 255)
    The default FROM address of the "person" sending the email. All emails must have a valid FROM address (ie the server must recognize the FROM address) or the chance of the email being successful is very small.

Once you have the fields in your table you should give the user some way to change these settings. They will need to be different with each site you install, so the user will need to have access to them.

Tip: On one of our internet machines we run a mail server. In our shipping programs we default all the above settings to that (internet) mail server. This increases the chances of the email sending "just working" immediately after the program is installed. The customer can change the settings later if they like. Of course if they've blocked the outgoing port in their firewall then they won't be able to send via our server, but then they will have their own internal server they can route the mail through.

EmailLog Table

Keeping a record of outgoing emails is very useful. Exposing this record to the customer adds value to your program and also allows them (or you) to audit what emails were sent, and when.

While you can store any fields you like in this table, the following are recommended;
  • Guid (String 16)
  • User (String 255)
  • Date (Long / Date)
  • Time (Long / Time)
  • SendDate (Long / Date)
  • SendTime (Long / Time)
  • ToEmail (String 255)
  • FromEmail (String 255)
  • Subject (String 255)
  • CC (String 255)
  • BCC (String 255)
  • Attachment (String 1024)
  • EmbedList (String 1024)
  • MessageText (MEMO 64000)
  • MessageHTML (MEMO 64000)
  • Status (Long)

Global Variables

When logging outgoing emails it's useful to know the current user's Name and Email Address. (ie the name and address of the user currently using the program.) There are many systems for managing users, so the easiest way to support this is to add two global variables to your program. These can be set when a user logs in, (you will need to do that in your embed code) and then used in the SendEmail procedure when a mail is sent.

The global variable names are
  • Glo:UserEmail (String 255)
  • Glo:UserName (String 255)
You can change these names if you need to - then just change where they are used in the SendEmail procedure.

UpdateEmailSettings Procedure

The example contains a sample procedure which just edits a single record in a table. Of course you may have added the fields to an existing table, in which case just use your existing form to set the settings.

BrowseEmailLog Procedure

An example of this procedure is in the example. This procedure is optional. It allows users to see what emails have been sent, and if desired, resend an email that did not get through. This procedure is a very standard browse on the table - there are no special NetTalk extensions here. 
The only bit of hand-code in the procedure revolves around the Resend button.

SendEmail Procedure

The SendEmail procedure is a normal procedure in your app tree, so you have a lot of control over what the window looks like, and how it works. If you are logging emails then this is a great procedure to add the logging code to.

The SendEmail procedure has the following prototype;
(EmailParametersGroup pEmail),Long,Proc

The parameters are set to;
(EmailParametersGroup pEmail)

the NetTalk Send Email control template has been added to the window. Note the template settings for this, as this is where you use a combination of the email server settings, and the parameters to construct the email. See the example for some ideas.

The example contains an interface which makes debugging email problems easier. It allows you to see the conversation between the program and the email server as it occurs. The log of the most recent conversation is also written to a text file for you. Plus of course each outgoing email is logged to the EmailLog table.

You can of course edit this procedure to make it work, or look, different so that it better matches your application.

Calling the SendEmail Procedure

The SendEmail procedure can be acalled from any other procedure. It might be a button, or a menu item, or it might happen in source code when some event occurs. To call SendEmail follow these steps:
  1. Create a local variable in the procedure;
    parms group(EmailParametersGroup).
  2. Where you want to send the email, prime the components of the parms parameter
    clear(parms)
    parms.pEmailTo =
    'bruce@capesoft.com'
    parms.pEmailFrom = glo:UserEmail
    parms.pEmailSubject = 'Great Release'
    parms.pEmailCC = ''
    parms.pEmailBCC = ''
    parms.pEmailFileList = ''
    parms.pEmailEmbedList = ''
    parms.pEmailMessageTextST.SetValue('Well done on a great release')
    parms.pEmailMessageHTMLST.SetValue('<html>...</html>')
  3. Call the SendEmail procedure. You can do this on another thread;
    START(SendEmail,25000,parms)
    or on the same thread (in which case you get a returned value;
    result = SendEmail(parms)

Receiving Emails

IMAP

Non-ASCII Characters

For English speaking users, who exclusively use the Roman alphabet from A to Z there is no issue here, and this section in the documentation can be skipped.

For non-English speaking users though, you may need to deal with non-roman characters. You will have some choices in how you do that though, and so those choices need to be communicated to the class so that it knows what you are doing. The default approach though is the one most likely to be used by your program, so it is probable that you will not need to do anything yourself.

A number of the class properties could be subject to these foreign characters. These include any email address list (From, To, CC, BCC), the Subject and of course the MessageText and MessageHTML. It is assumed that whichever approach you take to handling foreign characters, this approach is consistent across all these properties.

The two primary approaches to encoding non-ASCII text are to either use Unicode, or codepages (aka charsets). Since Clarion (up to version 10) cannot display, or get user entry, in Unicode, most programs would use the codepage approach.

Codepages (Charsets)

This is the default approach for non-ASCII characters. The codepage property will default to the setting (system{prop:charset}) used in your program, so it is likely there is nothing you will need to do. If your system charset is set then the class will assume that all outgoing properties are in that charset, and all incoming properties need to be converted to that charset.

You are also able to set the codepage property yourself to any st:CP_ value, as listed in StringTheory.Inc.

The CodePage property will only be used if the encoding property is not set to either st:EncodeUtf8 or st:EncodeUtf16 (see Unicode below).

Unicode

If your email values are already formatted in Unicode then you MUST set the encoding property before calling the SendEmail method. It should be set to either st:EncodeUtf8 or st:EncodeUtf16 (depending on how you have formatted your strings.)

SendEmail Control Template

The SendEmail Control Template lets you easily create your own SendEmail procedure. It places a lot of fields on the window for you, but you can obviously remove the ones you do not want to see. In the Demo example all the fields, except the actual Send button have been removed.

The Control template also acts as the "Glue" between the incoming parameters, the application-wide email settings, and the SendEmail object. The template settings should be filled in carefully.

General Tab

Object Name
Defaults to ThisSendEmail. You can change this if you like.
Base Class
Defaults to NetEmailSend. You can change this to a derived class if you have written one.

Settings Tab

Server
Usually taken from your global setting or settings table.
Port
Usually taken from your global setting or settings table.
User
Usually taken from your global setting or settings table.
Password
Usually taken from your global setting or settings table.
Helo
Usually left blank, then the domain from the FROM address is used.
AlwaysTLS
Usually taken from your global setting or settings table.
StartTLS
Usually taken from your global setting or settings table.
CA Root File
Usually a fixed value, 'caroot.pem'. The caroot.pem file will be copied to the application folder for you and should be distributed with your application.
To
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailTo.
From
Usually set to loc:EmailFrom. This field is calculated in code based on what the user entered, on the parameters, and the global setting.
CC
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailCC.
BCC
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailBCC.
Subject
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailSubject.
Attachments List
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailFileList.
Embeds List
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailEmbedList.
Text
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailMessageText.
HTML
Could be the field on the Window, if the field is there, else set it to pEmail.pEmailMessageHTML.
Show Messages
If this is on the a MESSAGE window is called when the email is sent (or if it fails to send.)
Change Cursor While Sending
If this is on then the cursor will change to a Cursor:Wait while the email is being sent.
Suppress Error Messages
If this option is on then unexpected error messages will not appear in a MESSAGE window.

EmailParametersGroup

A group structure has been defined to easily move multiple fields between procedures. Usually this is used when calling the SendEmail procedure. You don't have to populate all the fields in the group, the ones you don't need can be left blank.
NameTypeDescription
pEmailFromStringThe from address of the person sending the email.
pEmailToStringA semi-colon separated list of email addresses that the email is going To.
pEmailSubjectStringThe subject line of the email.
pEmailCCStringA semi-colon separated list of email addresses who will receive a cc of the mail.
pEmailBccStringA semi-colon separated list of email addresses who will receive a bcc of the mail.
pEmailFileListStringA comma separated list of files to attach to the email.
pEmailEmbedListStringA comma separated list of images that have been embedded in the email. (If left blank this will be constructed by the SendEmail object as long as the images are accessible.)
pEmailMessageTextStringThe "text" contents of the email itself.
pEmailMessageHtmlStringthe "html" contents of the email itself.
pEmailSettingsPathStringnot used
pEmailTestLongnot used
pHeloStringnot used
pSSLLongnot used
pStartTLSLongnot used
pSignLongDigitally signs the email if the necessary certificate is installed.
pHideLongIndicates to the Email Sending window if it should be visible or not.

Constructing HTML Emails

Text Version

Some mail readers, by design or user preference, do not display the HTML part of an email. So even if you populate the MessageHTML property, you should also populate the MessageText property when creating an email. If the client does not display HTML they will display the MessageText part.

HTML Version

Different mail clients use different HTML rendering engines to display emails. Notably Outlook uses the Microsoft Word engine (which is not as advanced as the engine used by IE.) Some clients will remove any links to external CSS, and even CSS collected into a <style> section.

For this reason the HTML used in emails needs to be very simple, and very "old school". If you do send more complex HTML then testing is definitely your friend.

There are numerous posts on the internet regarding best practices in this space - some recommended ones are;

Embedded Images

When constructing the HTML it is often desirable to embed images in it. This is usually done using the HTML <img> tag. For example;

<img src="http://www.capesoft.com/images/logo.png" >

This embeds a link to the image in the HTML. The image itself is not included in the HTML. Rather the image is fetched from the server when the user opens the email [1]. Unfortunately many users have images of this sort turned off in their email client, so the user never fetches, and never sees, the image.

There is a way though to embed the image in the HTML so that it is included in the email itself, and no call to the web server is required. You need to create an <img> tag, setting the source to a local resource. For example;

<img src="c:\images\logo.png" >
or
<img src="logo.png" >

If the HTML is constructed in this way, then you need to make a call to the ProcessHTMLForImages method;

thisEmail.ProcessHTMLForImages(rootfolder)

The Rootfolder parameter allows you to specify a location on the disk. This location will be used by any images which do not have a path set (such as <img src="logo.png" >)

This method should be called after the MessageHTML property has been set, and before the call to Send.

[1] The use of external images in an email message is often used my marketing folks to track when an email was read. This has the side effect of validating email addresses for spammers. For this reason most email clients are set to not load external images by default. Since most users leave the default as is, or even explicitly turn images off, this approach of using external images has largely fallen out of favor.

Digitally Signing Emails

When you send an email to a person, you can digitally sign it. If you do this, and the client email program the receiver is using supports digital signatures, then they will be able to verify that you sent the email, and the content of the email has been unaltered since you sent it.

Note that a Digital Signature is different to the simple Signature option that many email clients provide - the feature that adds simple text to the end of your emails. That is a different thing, and completely unrelated to Digital Signatures.

Digital Signatures require that you acquire and install a special kind of certificate, known as an Email Certificate, on the sending computer. This certificate is specific to the FROM address that you will be using to send your emails from. These certificates are widely available and are usually free. For example Comodo offers a free certificate, but Googling offers many possible choices.

Once you have acquired your certificate it needs to be imported into the Windows Certificate Store on the sending computer. You can run the Certificate Manager by running the CertMgr.Msc program. Go to the Personal / Certificates area, right-click on the Folder and Select All Tasks / Import from the menu. Follow the wizard to import the file. (Note that some web pages for acquiring the certificate install the certificate into the store for you automatically, so this step may not be needed.)

Certificates do expire, typically after 12 months, so you will need to renew them every year.

To digitally sign an email, when sending, set the property OptionsSigned to one of Net:NoSign (the default), Net:Sign or Net:TrySign. If set to Net:Sign, and the certificate does not exist, then the mail will not get sent. If it is set to Net:TrySign, and the certificate does not exist, then the mail will be sent unsigned.  For example;

net.OptionsSigned = Net:Sign

While there are other properties you can set at this point, related to digital signatures, it is unlikely that you will want to change them from their default values. These options, and default values are;

PropertyDefault Value
OptionsSignedProtocolapplication/x-pkcs7-signature
OptionsSignedMicAlgsha256
OptionsSigNamesmime.p7s
In some cases (if the client is unable to process a SHA-256 hash) it may be necessary to change the OptionsSignedMicAlg property to 'sha1'. However this should only be done if problems with old email clients is encountered.

The FROM address for the email is automatically used to identify the certificate to use. If an appropriate certificate is not found, and OptionsSigned is set to Net:Sign, then ErrorTrap will be called and the email will not be sent. If OptionsSigned is set to Net:TrySign then the email will be sent unsigned.

FAQ

  1. Gmail : Enable Less Secure Apps
  2. Secure Email Stopped Working
  3. Someone just tried to sign into your Google Account....
  4. 550 Relaying Prohibited
  5. External Exchange Failure
  6. EML File

Gmail : Enable Less Secure Apps

In order to send emails via the Gmail web service, you need to turn on SMTP and POP3 support for your Gmail account. Since Google is trying to encourage the use of OAuth and their own client software for email they have couched this setting in somewhat disingenuous language. Despite the stern warning it's really just allowing email the way email has always been done.

The solution is to go to your Gmail account and turn on the option Enable Less Secure Apps. Incidentally, despite the warning, the apps themselves are secure as long as you are transporting the email over TLS.

Gmail does allow you to connect over a TLS connection, so this should definitely be turned on as this does indeed make the communication between the client and the server more secure. Of course sending the email via Gmail in the first place means that at the very least Google has access to the contents of the email, so nothing which is particularly confidential should be sent via email anyway.

For some more information on this topic see;
http://security.stackexchange.com/questions/66025/what-are-the-dangers-of-allowing-less-secure-apps-to-access-my-google-account
and
http://forums.mozillazine.org/viewtopic.php?f=39&t=2852231

A good step-by-step guide is here;
http://www.ghacks.net/2014/07/21/gmail-starts-block-less-secure-apps-enable-access/

Secure Email Stopped Working

My email program, which has been working for a long time, using an old build of NetTalk is now getting errors and is unable to send. The error number was -69 which means the SSL Remote Certificate Failed Verification.

If you are connecting to a server via SSL (specifically SSL v3) then you may encounter this problem. SSLv3 was the default level for SSL used for earlier versions of NetTalk. SSL v3 was however broken in October of 2014, and was declared deprecated by the Internet Engineering Task Force (IETF) in RFC 7568 in June of 2015. As a consequence of the attacks in October 2014 many servers immediately moved to stop supporting SSLv3 and this was accelerated by the RFC in June 2015.

The solution is to change the connection your program uses from SSLv3 to TLS. If you are on a recent NetTalk version (NetTalk7 or later) then make sure you are on the latest build and this should be done for you automatically. (The internal default changed from SSLv3 to TLS in build 8.30 and 7.40)

If you are using an older NetTalk, or if you have specifically set the SSLMethod property for a class (so it is not just the default value) then you will need to set the property manually. In your code add;

net.SSLMethod = NET:SSLMethodTLSv1

If you are on NetTalk 8 or later then use the NET:SSLMethodTLS  equate as this covers all TLS versions, and defaults to the highest level of security.

If you are using NetTalk 7 then you can  use NET:SSLMethodTLSv1,  NET:SSLMethodTLSv1_1 or NET:SSLMethodTLSv1_2 equates.

NetTalk 6 and earlier does not support anything other than NET:SSLMethodTLSv1.

Warning: It is probable that at some point servers will turn off support for TLSv1 at which point programs earlier than NT build 7.40 will cease working. An update to NetTalk 8 (or later) is thus recommended to avoid problems when this happens.

550 Relaying Prohibited

"I am getting 550 Relaying Prohibited Errors when trying to send email. What's going on?"

Relaying problems are all to do with your Email Server. Basically it doesn't like who you are sending emails From. There are a couple of things you can do to try and resolve this:
  1. Authenticate with the server using the AuthUser and Password properties
  2. Make sure the FROM address you are sending from is a valid one, one which the server accepts.

External Exchange Failure

"I am using Exchange Server. Internal email sent from NetTalk works fine, but my external emails are never delivered."

Go to Internet mail service properties - routing tab - switch "reroute incoming smtp mail" to on.

EML file

"How do I create an EML file when sending emails"

The WholeMessage property contains the email in EML format. So you can just save this property as a file. This is easy with StringTheory.

For example;

str  StringTheory
  str.SetValue(net.WholeMessage)
  str.SaveFile('something.eml')

Class Reference

NetEmailSend

NetEmailReceive

NetIMAP

[End of this document]
Return to NetTalk Documentation Index