# 360Works Email 4.11 User Guide

## Installation

### Requirements

FileMaker version 12 or higher.

When 360Plugins are intialized for the first time, they will automatically download all required support files

### Install Steps for FileMaker Pro

Drag the plugin from the MAC or WIN folder into your FileMaker extensions, and restart FileMaker.

If the plugin does not load correctly, please send an email to support@360works.com

### WebDirect Install (FMS 13+)

Install plug-ins for use with WebDirect by dragging the appropriate plugin to FileMaker Server/Web Publishing/publishing-engine/cwpc/Plugins

### Install steps for Instant Web Publishing

You do not need to do this step unless you plan on using the plugin with Instant Web Publishing with FileMaker Server Advanced. You will need an Enterprise license to use this feature.

For installing into the Web Publishing Engine with FileMaker Server or FileMaker Server Advanced, drag the plugin from the MAC or WIN(.fmx) folder into the FileMaker Server/Web Publishing/publishing-engine/wpc/Plugins folder. If there is no Plugins folder inside the wpc folder, then create it manually. Restart FileMaker Web Publishing, and now the plugins should be ready to go.

The easiest way to test whether the plugin is working is to call the version function of the plugin, and display that on an IWP layout. If it shows "?", then the plugin is not working. If it shows a number, then the plugin has been installed successfully.

### Install steps for Custom Web Publishing

If you are using FileMaker Server 12.0v1, you can follow the same procedure as detailed above for custom web publishing. However, in FileMaker Server 12.0v2 and later, custom web publishing now runs as a 64-bit application and requires the 64-bit version of the plugin You will need an Enterprise license to use this feature.

For Mac, the single plug-in file in the MAC directory contains both 32-bit and 64-bit versions. For Windows, look for the plug-in that has the extension .fmx64 and use it in exclusively in custom web publishing.

To install 64-bit plug-ins, install either the .fmx64 or the .fmplugin to the following directory:

FileMaker Server / Web Publishing / publishing-engine / cwpc / Plugins

If it does not exist, create the Plugin folder manually. Restart FileMaker Web Publishing, and then you can then test a script that contains a plug-in and see if it returns the correct values.

### Install steps for server scheduled scripts

You do not need to do this step unless you plan on using the plugin with scheduled script triggering. You will need an Enterprise license to use this feature.

1. Drag the plugin from the MAC (.fmplugin file) or WIN (.fmx64 file) folder into the FileMaker Server extensions folder. On Mac OS X, this is located at /Library/FileMaker Server/Database Server/Extensions folder. On Windows, this is at C:\Program Files\FileMaker\FileMaker Server\Database Server\Extensions.
2. Restart the FileMaker Script Engine by opening Terminal (Mac) or CMD (Windows) and type the command: fmsadmin restart fmse -y . Note: On Windows you may need to change directories to where the fmsadmin utility is located in order to run this command. By default this is located at "C:\Program Files\FileMaker\FileMaker Server\Database Server" This step is not necessary if using Powershell
3. Go to Configuration -> Database Server->Server Plug-ins and check the box that says 'Enable FileMaker Server to use plug-ins'(if it is not already checked), and then check the 'enabled' box for this plugin. Click the 'save' button and wait a few seconds to make sure that the 'enabled' check box stays checked. If it does not, then there was an error loading the plugin and you should contact us for help troubleshooting. You should now be able to write schedules that trigger scripts which use the plugin.

### Auto Update

360Works has created an AutoUpdate helper database which makes setting up AutoUpdate much easier. This file includes pre-configured plugin files which you can place on your server, and an AutoUpdate script for each of our plugins which you can paste into your own solution.

You can get the AutoUpdate360Works file here Follow the instructions included in the file to either host your own Auto Update server or pull the files from ours.

### Uninstalling the plugin

Uninstall the plugin by quitting FileMaker Pro or stopping FileMaker Server and removing the plugin file from your Extensions directory.

### Demo mode and Registering the plugin

Plugins will run in demo mode until they are registered. While running in Demo mode, the product will run for 2 hours every time you launch FileMaker / FileMaker Server / FileMaker Web Publishing Engine. The 2 hour time limit will reset every time you relaunch FileMaker. There is no expiration date when Demo mode stops working. There are no feature differences between the Demo version and the licensed version.

Once you have purchased the plugin, you can register it with the license key. Once a valid license key is entered, the product will run for as long as FileMaker is running. After FileMaker starts up with the plugin installed, open FileMaker preferences, click on the Plug-ins tab, select the plugin from the list, and click the Configure button. Enter your license key and company name in this dialog. You will only need to do this once on a given machine. Alternately, you can use the registration function to register the plugin during a startup script.

Note: If you are running the plugin with FileMaker Server / FileMaker Web Publishing Engine, you must use the registration function to register the plugin, since there is no preferences dialog on FileMaker Server to enter the license key and company name. You will need to call the register function at the beginning of any script that is going to call plugin functions. This will ensure that you do not get demo mode errors.

### Product Wiki

This is the main documentation for the plugin. However, we also maintain a documentation Wiki that contains additional information for a lot of our products. You can find that page here

## Feedback

We love to hear your suggestions for improving our products! If you are experiencing problems with this plugin, or have a feature request, or are happy with it, we'd appreciate hearing about it. Send us a message on our website, or email us!

## Error Handling/Reporting

When something unexpected happens, a plugin function returns a result of `"ERROR"`. This makes it easy to check for errors. If a plugin function returns "ERROR", call the `EmailSetErrorCapture` function to get a detailed description of what went wrong.

Here is an example of basic error reporting:

    Set Variable [ $result = MyPluginFunction("x" ; "y" ; "z") ]
    If [ $result = "ERROR" ]
        Show Custom Dialog [ "An error occurred: " & EmailSetErrorCapture ]
    End If

### Chaining Multiple Functions Together

Since the string `"ERROR"` evaluates to false when evaluated by FileMaker, and most plugin functions return a `1` when successful, you can chain multiple dependent plugin operations together using the `"and"` operator. However, in this case the result will be a `1` or a `0`, not `"ERROR"`. For example:

    // chain multiple calls together
    // if any of the functions fail, the calculation will
    // short-circuit with a result of false,
    // and none of the subsequent function calls will be evaluated.
    Set Variable [ $success =
        FirstPluginFunction("x") and
        SecondPluginFunction("y") and
        ThirdPluginFunction("z")
    ]
    If [not $success]
        Show Custom Dialog [ "An error occurred: " & EmailSetErrorCapture ]
    End If

Note: the above only works for plugin functions which return `1` on success! Check the documentation for each function used in this manner.

### Additional Error Checking - Plugin not installed

If a plugin is not installed correctly, calls to a plugin function will return "?". As part of your startup script, you should check for this occurrence and display a warning accordingly that the plugin needs to be installed. Note: when treated as a boolean true/false value, FileMaker will treat `?` as `true`.

## Examples

> Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can.
> -Jamie Zawinski's Law of Software Envelopment

The 360Works Email Plugin offers the following advantages over FileMaker's built-in mail functionality:

- Read messages from a mailbox (POP, IMAP)
- Fully functional in Web Direct and server-side scripts
- Send multiple attachments in a single message
- Send formatted (HTML, etc) emails
- Speedy delivery of many messages by re-using a single connection to the server
- Set custom email headers

You must call an EmailConnect[service] function prior to using the other Email Plugin functions as their functionality depends on being run in the context of an e-mail service.

### Example Usages

EmailQuickSend, the easiest way to fire off a single email:

     EmailRegister( "mylicensekey", "My Company" )]
     EmailConnectSMTP( "mail.example.com" )
     EmailQuickSend(
         Email::from ;// required "from" address
         Email::to ; // comma-separated list of addresses
         Email::subject ; // subject of the message
         Email::body ; // message body
         Email::attach)    // path or URL or container to attach
     EmailDisconnect

Sending a plain-text email with one attachment:

     EmailRegister("myLicenseKey"; "My Company")
     EmailConnectSMTP( "mail.example.com" )
     EmailCreate( Email::from ; Email::to ; Email::subject )
     EmailSetBody( Email::body ; "plain" )
     EmailAttachFile( $attachment )
     EmailSend
     EmailDisconnect

Sending an HTML-formatted email

     EmailRegister("myLicenseKey"; "My Company")
     EmailConnectSMTP( "mail.example.com" )
     EmailCreate( Email::from ; Email::to ; Email::subject )
     EmailSetBody( Email::body ); "html" )
     EmailSend
     EmailDisconnect

###

HTML Generation The Email plugin cannot generate HTML so supplying the HTML for the email body will be up to you. If you already have the HTML, then all you need to do is paste it in a FileMaker field and reference it like the above example or hard code it directly into the function call. If you already have an HTML file, you can open it with a text editor like Sublime Text or NotePad++ and then copy the HTML into a FileMaker field. If the HTML file is hosted, you can use EmailSetBodyFile like so:

         EmailRegister("myLicenseKey"; "My Company")
         EmailConnectSMTP( "mail.example.com" )
         EmailCreate( Email::from ; Email::to ; Email::subject )
         //set the second parameter in EmailSetBodyFile to true to embed resources
         EmailSetBodyFile( "http://SomeURLtoHTML.com/emailbody.html";true )
         EmailSend
         EmailDisconnect

If you do not have HTML yet and do not know how to write it then you could use an HTML generator like the one located here. There are several editors available online and stand alone programs so find one you like. This one is just a simple WYSIWYG editor.

Sending a single message multiple times to different recipients can be done by creating a message using {@link #EmailCreate}, then calling EmailRecipients and EmailSend multiple times. If you are sending large messages with attachments, this avoids the overhead of creating a separate message for each recipient.

You can also send a single message to multiple TO, CC, or BCC recipients by passing a comma-separated list of addresses.

Note: Email is sent from whichever machine the plugin is being used on, be sure to open up port 25 for outgoing SMTP access on those machines.

#### Displaying a name instead of the FROM address

The "from" field can be either an email address "you@yourdomain.com" or a name and email address like "FirstName LastName <you@yourdomain.com>" instead. Most email clients will then display the name in the from field instead of the address. However, if the address is already in address book, most clients are configured to preempt with that associated name instead.

#### Sending Attachments

EmailAttachFile accepts several different types of arguments. You can pass in a container field URL, or a path. A URL can be to a resource on the web, or can be a file url pointing to a local file (e.g. `file:///path/to/attachment.jpg`).

### Bulk Mail

When sending to multiple recipients, instead of creating a new message for each recipient, you can create a single message, connect once to your server, and then send the same message multiple times, switching the subject, recipients, and message body for each recipient.

     //First connect to the SMTP server and create the message.
     EmailConnectSMTP( "mail.example.com" )
     EmailCreate( Email::from ; Email::to ; Email::subject )
     EmailSetBody( GetAsCSS( Email::body ); "html" )
     Go To Record/Request [ First ]
     Loop
         Set Variable [ $setRecipients; Value: EmailRecipients [ Email::to ] ]
         Set Variable [ $msgSend; Value = EmailSend ]
         Go To Record/Request [ Next ; Exit After Last ]
     End Loop
     // We've sent the same message to all recipients. Now disconnect
     Set Variable [ $disconnect; Value: EmailDisconnect ]

### Reading Mail

Version 1.3 of the Email Plugin introduced support for reading messages from a mailbox. The API for reading messages was revised in version 1.6.

- First call EmailConnectPOP or {@link #EmailConnectIMAP} to connect to a server. If you will be reading emails, you must specify a username & password.
- Next, use the EmailListMailboxes function to get a list of mailboxes for the account.
- Then, you can call EmailReadMessages to get a list of messages in a certain mailbox.
- Create records for the email messages. You can either import the messages as XML data or iterate over them using the EmailGetNextMessage and EmailReadMessageValue functions
- Finally, it's a good idea to call EmailDisconnect to close the connection to the server when you no longer need it.

Here is a brief example of how to read the first 25 unread messages from the server:

     Set Variable [$registerResult; Value: EmailRegister ( license ; company )]
     // check for registration success here
     Set Variable [$connectResult; Value: EmailConnectIMAP( server ; username ; password )]
     // check for connection success here
     Set Variable [$$importUrl; Value: EmailReadMessages ("mailbox=INBOX" ;"viewed=false" ;"max=25" ;"attachments=true")]
     // check for import success here
     If [$$importUrl = "ERROR"]
         Show Custom Dialog [EmailLastError]
         Exit Script
     End If
     // Import the email messages from the local XML file
     // which was created by the EmailReadMessages function
     Import records [$$importUrl ; Update Matching]
     // Now disconnect from the IMAP server
     Set Variable [ $disconnect; Value: EmailDisconnect ]
     If [$disconnect = "ERROR"]
         Show Custom Dialog [EmailLastError]
         Exit Script
     End If

Alternatively, you can process the Emails using EmailGetNextMessage. This is a requirement if you're running on FileMaker Server or via Web Direct/IWP/CWP since [Import XML]is not a web-safe script step. The general pattern looks like this:

     Set Variable [$$importUrl; Value= EmailReadMessages ("mailbox=INBOX" ;"viewed=false" ;"max=25" ;"attachments=true")]
     // check for errors here
     Loop
         Exit Loop If [not EmailGetNextMessage]
         New Record/Request
         Set Field[ImportedMessage::date ; EmailReadMessageValue( "dateSent" )]
         Set Field[ImportedMessage::from ; EmailReadMessageValue( "from" )]
         Set Field[ImportedMessage::to ; EmailReadMessageValue( "to" )]
         Set Field[ImportedMessage::subject ; EmailReadMessageValue( "subject" )]
         Set Field[ImportedMessage::body ; EmailReadMessageValue( "body" )]
         Set Field[ImportedMessage::messageId ; EmailReadMessageValue( "messageId" )]
     End Loop

#### Microsoft Exchange Server

To read mail from a Microsoft Exchange Server, you'll need to enable IMAP access on your exchange server. This article covers the steps for doing so. You may need to restart your server for this change to take effect. Once IMAP access is enabled, you can connect normally as described above.

### Modifying Mail Messages

Version 1.6 of the Email Plugin provided the ability to modify messages on a remote mailbox. To do this, you must read the messages using the EmailReadMessages function as described above, being sure to include the flag `readonly=false`.

Note: setting `readonly=false` will cause any fetched messages to be marked as "viewed"! Then iterate to a message using the {@link #EmailGetNextMessage()} function. Finally, use the EmailMessageSetFlag function to apply flags to a message (such as deleted, flagged, viewed, etc).

Here is an example of how to fetch any unread messages from a mailbox, marking them all as `viewed` (by setting `readonly=false`). Additionally, any messages from a certain address are marked as `deleted`:

     Set Variable [ $result = EmailReadMessages( "viewed=false" ; "readonly=false" ) ]
     If [$result = "ERROR"]
         # Handle Error Here...
     End If
     Loop
         Exit Loop If [not EmailGetNextMessage]
         Set Variable[$result ; EmailMessageSetFlag("viewed")
         If [EmailReadMessageValue("from") = "deleteme@example.com"]
             Set Variable[$result ;Value: EmailMessageSetFlag("deleted")
         End If
     End Loop

## Function Detail

### EmailAttachFile ( data )

Attach a file at a URL to an email message, from either a URL, container, or file path. For example:

     EmailAttachFile("http://localhost:8080/SuperContainer/RawData/123");

-or-

     EmailAttachFile("file:///path/to/invoice.pdf");

-or-

     EmailAttachFile("/Macintosh HD/path/to/invoice.pdf");

-or-

     EmailAttachFile(myTable::myContainerField);

You can call this multiple times to attach multiple files to a message.

Note on paths vs urls: This function can also accept a path (/path/to/file) instead of a file URL (file://path/to/file). This is handy for attaching PDFs generated by FileMaker.

If called on a machine running Mac OS X, a file URL is created from a path by prepending the directory `/Volumes` to the supplied path, since FileMaker includes the hard drive name in paths. For example, `/MacintoshHD/Users/John Smith/Documents/` is converted to the file URL `file:///Volumes/MacintoshHD/Users/John Smith/Documents/`.

### Auto-zip of attached directories

If the path points to a directory/folder instead of a file, the email plugin will automatically zip the contents of the folder into a temporary file and send that as the attachment. This allows sending of Mac OS X bundles such as `.pages` files, etc.

Parameters:

  `data` - a container, path to a file, or a URL pointing to a file to attach to the message.

Returns: 1 on success, ERROR on error.

### EmailAttachFileInline ( data ; contentId )

Add an inline attachment to an HTML message. If you are sending HTML email with embedded images or other resources, use this function to embed the resource files in the message.

For example:

     EmailCreate("to@example.com"; "from@example.com"; "My Newsletter")
     EmailSetBody(
         "<html><body><img src=\"cid:headergif123\">" &
         "This is an HTML message with embedded images" &
         "<img src=\"cid:footergif456\">" &
         "</body></html>";
         "html"
     )
     EmailAttachFileInline( Globals::headerContainer ; "headergif123" )
     EmailAttachFileInline( Globals::footerContainer ; "footergif456" )
     EmailSend

### Content IDs

When creating your HTML email message, reference inline containers using `cid:contentid`, where `contentid` is an arbitrary unique string you create for each inline attachment.

Your contentIds should be globally unique for a given image/file resource, as mail clients will use this to cache the contents of the message.

You should only use letters and numbers for your content ids, some mail clients have trouble with other characters.

Parameters:

  `data` - a path to a file, or a URL pointing to a file to attach to the message (see EmailAttachFile for valid arguments).
  `contentId` - contentId of the attachment.

See also: EmailAttachFile
Returns: 1 on success, ERROR on error.

### EmailBCCRecipients ( bcc_addresses { ; append } )

Set the BCC (blank carbon copy) recipients for the current message. This can be called multiple times before sending, to build up a list of recipients (set `append` to true if doing this).

     //Assumes the connection the SMTP server has already been established.
     EmailCreate( "from@example.com", "to@example.com", "A multipart message" )

     EmailBCCRecipients(somebody@360works.com;true)
     EmailBCCRecipients(someOneElse@360works.com;true)//passing in false will overwrite the BCC recipients list
     EmailSetBody( GetAsCSS( Email::body ); "html" )

     EmailSend

Parameters:

  `bcc_addresses` - comma-separated list of addresses
  `append` - whether to append the new addresses to existing ones, or overwrite them.

Returns: 1 on success, ERROR if one or more addresses are invalid.

### EmailBodySubstitute ( searchString ; replaceString )

Perform a substitute operation on the HTML or plain-text portion of the current HTML message. You can call this multiple times on the same message, using the same `searchString` each time. Once a message is sent, the replaced values are reset to their original values.

This is useful if you are using EmailSetBodyFile to load static HTML content as the body part, but want to insert dynamic content in the body. Or, if you are sending many emails and want to merge data into a static body text field.

         Text in the body field: Hello CUSTOMERNAME, your account ending in ACCOUNTLASTFOUR is past due.
         Please pay ACCOUNTBALANCE by DUEDATE or your account will be terminated

         EmailCreate(someOne@360works.com;someOneElse@360works.com;"Example Email")
         EmailSetBody(myTable::bodyField;"html")//also works with plain text
         EmailBodySubstitute("CUSTOMERNAME";Customer::Name)
         EmailBodySubstitute("ACCOUNTLASTFOUR";Customer::AccountLastFour)
         EmailBodySubstitute("ACCOUNTBALANCE";Customer::Balance)
         EmailBodySubstitute("DUEDATE";Customer::Due Date)
         EmailSend

Parameters:

  `searchString` - the text to replace
  `replaceString` - the replacement text

Returns: 1 on success, or "ERROR" on failure.

### EmailCCRecipients ( cc_addresses { ; append } )

Set the CC (carbon copy) recipients for the current message. This can be called multiple times before sending, to build up a list of recipients (set `append` to true if doing this).

         EmailCreate( "from@example.com", "to@example.com", "A multipart message" )
         EmailCCRecipients(someOne@email.com;true) //appends address to CC list
         EmailCCRecipients(someOneElse@email.com, anotherOne@email.com;true) //appends addresses to CC list
         EmailSetBody( GetAsCSS( Email::body ); "html" )
         EmailSend

         EmailCCRecipients(someOne@email.com;false) //overwrites current CC list
         EmailCCRecipients(someOneElse@email.com;false) //overwrites previous call

Parameters:

  `cc_addresses` - comma-separated list of addresses
  `append` - whether to append the new addresses to existing ones, or overwrite them.

Returns: 1 on success, ERROR if one or more addresses are invalid.

### EmailChooseFile ( { initialPath ; fileType ; title } )

Shows a file chooser dialog where a user can browse the local hard drive. When the user selects a file or directory and clicks "OK" on the file chooser, this function returns the path to the selected file or directory. If the user hits the cancel button, nothing is returned.

### File Type

By supplying a `fileType` parameter, you can allow the user to just select files, just select directories, or select both files and directories. The default behavior is to only allow file selection.

Note: specifying a fileType of "directories" or "files + directories" will cause a non-native file dialog to be used on some platforms, as the native dialogs may not support directory selection.

Parameters:

  `initialPath` - optional path to set the initial dialog selection to. If empty, will default to the user's home directory.
  `fileType` - whether to allow `"files"`, `"directories"`, or both `"files + directories"`
  `title` - optional title string to display as the title of the FileChooser dialog

Returns: Path to the selected file, nothing if no file was selected, or "ERROR" if an error occurred.

### EmailConnect ( host_address_deprecated { ; user_deprecated ; password_deprecated } )

This function is deprecated and only included for legacy purposes. Please use EmailConnectSMTP instead. The username and password are optional, and may not be required for sending mail. This establishes a connection to the email server. When you are finished getting/sending email, you should call {@link #EmailDisconnect()} to close the connection.

Parameters:

  `host_address` - the SMTP host address. This parameter may contain a port number using a colon syntax, e.g. `smtp.example.com:2525`
  `user` - The optional SMTP authentication username
  `password` - The optional SMTP authentication password

See also: EmailConnectSMTP, EmailConnectPOP, EmailConnectIMAP

### EmailConnectAmazon ( accessKey ; secretKey { ; region } )

Connect to the Amazon Simple Email Service (SES) servers for sending email. Communication happens via HTTPS protocol instead of SMTP, this can be especially useful when using the plugin in environments that only allow communication over HTTP/HTTPS.

You can sign up for this service at http://aws.amazon.com/ses/. You will need to create an access key/secret key and verify your sending email address with SES before you can send emails using this service. Follow instructions found here to create the required keys. Email address verification is done in the SES section of your AWS account

Example: `EmailConnectAmazon( "nf298nrc23r"; "208chr29-hrc-29hr1983f")`

It's also possible to use Amazon SES via SMTP. In this case you would need to generate SMTP keys and use {@link #EmailConnectSMTP}. Please note that these are different than the access key/secret keys created for this function. See EmailConnectSMTP for a link to instructions on how to generate these keys.

Parameters:

Returns: successValue

### EmailConnectIMAP ( host ; username ; password { ; secureConnection ; tls=true ; ... } )

Connect to an incoming IMAP mail server. This function (or `EmailConnectPOP`) must be called before reading email messages from the server. This establishes a connection to the email server. When you are finished getting/sending email, it is a good idea to call EmailDisconnect to close the connection.

Here is an example of connecting to a regular mail server:

     Set Variable[$result ; Value: EmailConnectIMAP("my_email_host" ;"username" ;"password")]

### SSL Encryption

Use the optional arguments to enable SSL encryption by passing `"ssl=1"`. If you are connecting to GMail, SSL encryption is required. Here is an example of connecting to google mail (gmail) with SSL encryption, and expunge set to true:

     Set Variable[$result ; Value: EmailConnectIMAP("imap.gmail.com" ;"username" ;"password" ;"ssl=1" ;"expunge=true")]

### Optional Flags

The following can be passed as additional parameters to the EmailConnectIMAP function:

ssl
  pass `true` to enable SSL encryption. Some mail services (like Gmail) require this.
expunge
  pass `true` or `false` to determine whether flagging a message for deletion permanently removes the message from your mail server. If unspecified, messages are only removed/expunged if the server does not support deleted flags.

if your IMAP server requires TLS pass in a 1 or true for the secureConnection parameter if calling the function as a script step. If called as a function pass in tls=1. If your IMAP server requires SSL, you will need to call the EmailConnectIMAP function in a calculation and set the parameter to ssl=1 or true

Parameters:

  `host` - the IMAP host address. This parameter may contain a port number using a colon syntax, e.g. `imap.example.com:2525`
  `username` - The authentication username
  `password` - The authentication password
  `args` - Additional optional arguments (ssl, forceTrust, tls).

See also: EmailDisconnect
Returns: 1 on successful connection, or "ERROR" if an error occurred (use EMailLastError in this case)

### EmailConnectPOP ( host ; username ; password { ; secureConnection ; tls=true ; ... } )

Connect to an incoming POP mail server. This function (or `EmailConnectIMAP`) must be called before reading email messages from the server. This establishes a connection to the email server. When you are finished getting/sending email, it is a good idea to call EmailDisconnect to close the connection.

Note: We strongly recommend using IMAP instead of POP with Gmail due to possible confusion over Gmail's labels and tags.

Here is an example of connecting to a regular mail server:

     Set Variable[$result; Value: EmailConnectPOP("my_email_host" ;"username" ;"password")]

### SSL Encryption

Use the optional arguments to enable SSL encryption by passing `"ssl=1"`. If you are connecting to GMail, SSL encryption is required. Here is an example of connecting to google mail (gmail) with SSL encryption:

     Set Variable[$result ; Value: EmailConnectPOP("pop.gmail.com" ;"username" ;"password" ;"ssl=1")]

if your POP server requires TLS pass in a 1 or true for the secureConnection parameter. If your POP server requires SSL, you will need to call the EmailConnectPOP function in a calculation and set the parameter to ssl=1 or true

Parameters:

  `host` - the POP host address. This parameter may contain a port number using a colon syntax, e.g. `pop.example.com:2525`
  `username` - The authentication username
  `password` - The authentication password
  `args` - Additional optional arguments (ssl, forceTrust, tls).

See also: EmailDisconnect
Returns: 1 on successful connection, or "ERROR" if an error occurred (use EMailLastError in this case)

### EmailConnectSMTP ( host { ; username ; password ; secureConnection ; ssl=true ; forceTrust=true ; tls=true ; timeout=10 ; ... } )

Connect to an outgoing SMTP mail server. This function must be called before sending mail. The username and password are optional, and may not be required for sending mail, depending on your SMTP server's setup. Most public mail server's settings can be found by searching for them on the web. If you are not using a service like Gmail, make sure to contact the server administrator for the required credentials needed to connect to the mail server. When you are finished getting/sending email, it is a good idea to call EmailDisconnect to close the connection.

Note for Gmail users: By default, Gmail will set the "from" address to the email address used with EmailConnectSMTP for all outbound messages. If you want to set the "from" address to a different email address, you must add the desired email address manually in Gmail Settings. Gmail also requires that you change the "allow less secure apps" to true in order to connect to it with 3rd party software. This setting can be changed in the Security section in account settings.

Here is an example of connecting to a regular mail server:

     Set Variable[$result ; Value: EmailConnectSMTP("my_email_host" ;"username" ;"password")]

### SSL Encryption

Use the optional arguments to enable SSL encryption by passing `"ssl=1"`. If you are connecting to Gmail, SSL encryption is required. Here is an example of connecting to Gmail with SSL encryption:

     Set Variable[$result; Value: EmailConnectSMTP("smtp.gmail.com:465" ;"username" ;"password" ;"ssl=1")]

if your SMTP server requires TLS pass in a 1 or true for the secureConnection parameter. If your SMTP server requires SSL, you will need to call the EmailConnectSMTP function in a calculation and set the parameter to ssl=1 or true

NOTE: If you are using access and secret keys, you should be using EmailConnectAmazon. If you want to use EmailConnectSMTP, you must use Amazon's SES SMTP interface which requires separate SMTP credentials. Instructions to generate those credentials can be found here. Example connecting to SES SMTP US East Endpoint

         Set Variable[$connect; Value: EmailConnectSMTP("email-smtp.us-east-1.amazonaws.com";"SMTPaccessKey";"SMTPsecretKey";"tls=1")

Parameters:

  `host` - the SMTP host address. This parameter may contain a port number using a colon syntax, e.g. `smtp.example.com:2525`
  `username` - The optional SMTP authentication username
  `password` - The optional SMTP authentication password
  `args` - Additional optional arguments (ssl=true, forceTrust=true, tls=true, timeout=<<seconds>>).

See also: EmailDisconnect
Returns: 1 on successful connection, or "ERROR" if an error occurred (use EmailLastError in this case)

### EmailCreate ( from ; to ; subject { ; content } )

Create a new email message, clearing any previous recipients and attachments. This needs to be called before any other message building functions i.e. EmailSetBody,EmailSetSubject, etc.

Parameters:

  `from` - the FROM address for the new message. Use "Name <you@domain.com>" for displaying the name instead.
  `to` - the TO address for the new message
  `subject` - the SUBJECT of the new message

Returns: 1 on success

### EmailDisconnect

Close any open connections to email servers established via the Email plugin.

See also: EmailConnectSMTP
Returns: 1 on success

### EmailGetMessageCount ( { flag1 ; flag2 ; ... } )

Returns a count of messages in a particular mailbox, INBOX is used if no mailbox is specified.

Parameters:

  `flags` - optional flags which control how messages are counted

Returns: number of messages in the mailbox

### EmailGetNextMessage

Loads a single message which was fetched in a previous call to the `EmailReadMessages` function.

To use this function, first call `EmailReadMessages` with the appropriate parameters.

Next, call `EmailGetNextMessage`, which returns 1 or 0 depending on whether a message was loaded.

Finally, call `EmailReadMessageValue` to get individual properties of the currently loaded message.

See also: EmailReadMessageValue, EmailReadMessages
Returns: 1 if a message is loaded, 0 if there are no more messages, or ERROR if an error occurred.

### EmailGoogleConnect ( username ; tokenStore { ; googleClientId ; googleClientSecret ; state } )

This is a convenience function that will execute both EmailGoogleConnectSMTP and EmailGoogleConnectIMAP

Parameters:

  `username` -
  `tokenStore` -
  `googleClientId` -
  `googleClientSecret` -
  `state` -

Returns:

### EmailGoogleConnectIMAP ( username ; tokenStore { ; googleClientId ; googleClientSecret ; state } )

This function will first get a new token store, then it will log into Google's IMAP Server using the new token store. If login is successful then it will return a new valid token store. When fetching a new token store, we will examine the current token store to determine what action, if any, needs to be taken to return a valid, current token store.

- If the current token store is still valid, then it is used and returned from this function
- If the current token store has an expired access token, but a valid refresh token, then the token is silently refreshed and the new token store is used to login then returned.
- If the current token store is invalid or empty, then a new token store is fetched. (Note, you must call EmailGoogleGetLoginUrl and login to Google first to be able to fetch a token.)

The optional parameter "state", should only be used if this OAuth Workflow is being performed across multiple sessions (i.e. Different PSOS calls for EmailGoogleGetLoginUrl and EmailGoogleConnectIMAP) If that is the case, then you must supply the same state parameter to both functions.

Parameters:

  `username` - - The email address of the Google account that will be connected to
  `tokenStore` - - The OAuth token that will be used to log in to the account. This can be null, or expired, and the function will attempt to fetch, or refresh, the token.
  `googleClientId` - - The client_id from your Google Developer Account. This is optional and only necessary if you can't call EmailGoogleGetLoginUrl first (i.e. multiple sessions/PSOS calls)
  `googleClientSecret` - - The client_secret from your Google Developer Account. This is optional and only necessary if you can't call EmailGoogleGetLoginUrl first (i.e. multiple sessions/PSOS calls)
  `state` - - The UUID that is used to match the login url request and the fetch token request. This is optional, and only required if performing these functions across different sessions. This can be any value, it's recommended to use Get(UUID).

Returns:

### EmailGoogleConnectSMTP ( username ; tokenStore { ; googleClientId ; googleClientSecret ; state } )

This function will first get a new token store, then it will log into Google's SMTP Server using the new token store. If login is successful then it will return a new valid token store. When fetching a new token store, we will examine the current token store to determine what action, if any, needs to be taken to return a valid, current token store.

- If the current token store is still valid, then it is used and returned from this function
- If the current token store has an expired access token, but a valid refresh token, then the token is silently refreshed and the new token store is used to login then returned.
- If the current token store is invalid or empty, then a new token store is fetched. (Note, you must call EmailGoogleGetLoginUrl and login to Google first to be able to fetch a token.)

The optional parameter "state", should only be used if this OAuth Workflow is being performed across multiple sessions (i.e. Different PSOS calls for EmailGoogleGetLoginUrl and EmailGoogleConnectIMAP) If that is the case, then you must supply the same state parameter to both functions.

Parameters:

  `username` - - The email address of the Google account that will be connected to
  `tokenStore` - - The OAuth token that will be used to log in to the account. This can be null, or expired, and the function will attempt to fetch, or refresh, the token.
  `googleClientId` - - The client_id from your Google Developer Account. This is optional and only necessary if you can't call EmailGoogleGetLoginUrl first (i.e. multiple sessions/PSOS calls)
  `googleClientSecret` - - The client_secret from your Google Developer Account. This is optional and only necessary if you can't call EmailGoogleGetLoginUrl first (i.e. multiple sessions/PSOS calls)
  `state` - - The UUID that is used to match the login url request and the fetch token request. This is optional, and only required if performing these functions across different sessions. This can be any value, it's recommended to use Get(UUID).

Returns:

### EmailGoogleGetLoginUrl ( tokenStore ; googleClientId ; googleClientSecret { ; state } )

This function will examine the tokenStore provided and return:

- A login url, if the token is empty, or both tokens are invalid. Users will need to log into the url, then you can call EmailGoogleConnectIMAP or EmailGoogleConnectSMTP to retrieve the tokens generated by the OAuth process.
- Empty, if the token is valid, or it can be silently refreshed. We will need to call EmailGoogleConnectIMAP or EmailGoogleConnectSMTP to refresh the current token store.
- ERROR, if there was an error when creating the login url

The optional parameter "state", should only be used if this OAuth Workflow is being performed across multiple sessions (i.e. Different PSOS calls for EmailGoogleGetLoginUrl and EmailGoogleConnectSMTP) If that is the case, then you must supply the same parameters to all functions.

Parameters:

  `tokenStore` - - The OAuth token that will be used to log in to the account. This can be null, or expired, and the function will attempt to fetch, or refresh, the token.
  `googleClientId` - - The client_id from your Google Developer Account. This is required.
  `googleClientSecret` - - The client_secret from your Google Developer Account. This is required.
  `state` - - The UUID that is used to match the login url request and the fetch token request. This is optional, and only required if performing these functions across different sessions.

Returns: a login url, an empty result, or ERROR.

### EmailInboundIsConnected

### EmailLastError

Returns detailed information about the last error generated by this plugin. If another plugin function returns the text "ERROR", call this function to get a user-presentable description of what went wrong.

Returns: Error text, or `""` if there was no error.

### EmailLicenseInfo

Retrieve information about the Email plugin licensing and version.

Returns: version, type, registeredTo values.

### EmailListMailboxes ( { parent ; recursive } )

Gets a return-separated list of mailboxes in a specific folder on the currently connected inbound mail server. This is useful for when you need to call EmailReadMessages on multiple mailboxes but are unsure of the folder names on the IMAP server Note: this is only works for IMAP mailboxes, as POP does not support a folder system.

         EmailConnectIMAP(....)//connect to IMAP Server
         Set Variable[$mailboxes;Value:EmailListMailboxes("INBOX";true)] //passing in true gets all sub-folders in INBOX

Parameters:

  `parent` - optional mailbox to traverse. If not specified/empty, the root mailbox is used.
  `recursive` - optional parameter for whether to traverse sub-folders recursively. Default is false.

See also: EmailConnectIMAP, EmailConnectPOP
Returns: a return-separated list of mailboxes. If recursion is enabled, nested mailboxes will be separated by a slash (`/`) character.

### EmailMessageSetFlag ( flag { ; value } )

Applies a flag to the current message, as retrieved by the function EmailGetNextMessage. Note: You must call EmailReadMessages with a parameter of `readonly=false` to use this function. The allowed flags are:

- deleted
- replied (IMAP only)
- draft (IMAP only)
- flagged (IMAP only)
- viewed (IMAP only)
- recent (IMAP only)

POP vs IMAP. POP accounts typically do not support persistent flags, so if you flag a message as `deleted` in a POP account, it will be permanently deleted when you disconnect from the server.

Parameters:

  `flag` - one of the named flags to set
  `value` - the optional value to set the flag to. Default is `0` (or `false`).

Returns: 1 on successful delete, or "ERROR" if an error occurred (use EMailLastError in this case)

### EmailMoveCurrentMessage ( folder )

Moves a message on an IMAP mailbox. This operates either on the current message queued for delivery in FileMaker, or on the most recently fetched message from the IMAP server.

### Saving Outgoing Messages

To save a copy of an outgoing message in your "Sent" mailbox, you can do something like the following:

     EmailCreate( "my@mydomain.com" ; "bob@example.com" ; "Moving a test message" )
     EmailSetBody( "Hi Bob!  I'm saving a copy of this in my 'Sent' folder" )
     EmailSend
     EmailMoveCurrentMessage( "Sent" )

The above example assumes that you are already connected both to your IMAP server and your SMTP server.

First we create a message and set the message body. Next, we deliver the message by calling EmailSend. Finally, If the message was delivered successfully, we save it to the "Sent" folder on our IMAP mailbox.

### Moving Existing Messages

To move existing messages on your IMAP mailbox, call `EmailMoveCurrentMessage` after fetching the message with EmailGetNextMessage. This will copy the message to the destination mailbox, creating the mailbox if it doesn't exist. If the original mailbox has `readonly=false` specified, the message is flagged for deletion from the original mailbox. This can be useful for processing all messages in a certain folder, then moving them to a "processed" folder on the mailserver, for example.

     Set Variable [ $result = EmailReadMessages( "readonly=false" ) ]
     If [$result = "ERROR"]
         # Handle Error Here...
     End If
     Loop
         Exit Loop If [not EmailGetNextMessage]
         // PROCESS THE MESSAGE HERE...
         Set Variable [ $moveResult = EmailMoveCurrentMessage ("Processed") ]
     End Loop

The above script fetches all messages in the INBOX, then loops through them, performing some action on each message, then moving the message to the "Processed" mailbox. NOTE: the `readonly=false` is required for the processed messages to be removed from the mailbox. If not specified, the messages will still remain in the original mailbox.

Parameters:

  `folder` - the name of the folder to move the message to

Returns: 1 on success, "ERROR" on error (use EmailLastError to get a detailed error message)

### EmailOffice365Connect ( username ; tokenStore { ; office365ClientId ; office365ClientSecret ; office365TenantId ; state } )

This is a convenience function that will execute both EmailOffice365ConnectSMTP and EmailOffice365ConnectIMAP

Parameters:

  `username` -
  `tokenStore` -
  `office365ClientId` -
  `office365ClientSecret` -
  `state` -

Returns:

### EmailOffice365ConnectIMAP ( username ; tokenStore { ; office365ClientId ; office365ClientSecret ; office365TenantId ; state } )

This function will first get a new token store, then it will log into Office365's IMAP Server using the new token store. If login is successful then it will return a new valid token store. When fetching a new token store, we will examine the current token store to determine what action, if any, needs to be taken to return a valid, current token store.

- If the current token store is still valid, then it is used and returned from this function
- If the current token store has an expired access token, but a valid refresh token, then the token is silently refreshed and the new token store is used to login then returned.
- If the current token store is invalid or empty, then a new token store is fetched. (Note, you must call EmailOffice365GetLoginUrl and login to Office365 first to be able to fetch a token.)

The optional parameters (office365ClientId, office365ClientSecret, and state) should only be used if this OAuth Workflow is being performed across multiple sessions (i.e. Different PSOS calls for EmailOffice365GetLoginUrl and EmailOffice365ConnectIMAP) If that is the case, then you must supply the same state parameter to both functions, and if you are using custom Office365 keys, supply those as well.

Parameters:

  `username` - - The email address of the Office365 account that will be connected to
  `tokenStore` - - The OAuth token that will be used to log in to the account. This can be null, or expired, and the function will attempt to fetch, or refresh, the token.
  `office365ClientId` - - The client_id from your Microsoft Azure Account. This is optional and can be omitted. However, if you supply these parameters to this call, be sure that you have supplied them to EmailOffice365GetLoginUrl as well.
  `office365ClientSecret` - - The client_secret from your Microsoft Azure Account. This is optional and can be omitted.
  `office365TenantId` - - The Tenant ID associated to the application with client_id. This is optional and can be omitted.
  `state` - - The UUID that is used to match the login url request and the fetch token request. This is optional, and only required if performing these functions across different sessions.

Returns:

### EmailOffice365ConnectSMTP ( username ; tokenStore { ; office365ClientId ; office365ClientSecret ; office365TenantId ; state } )

This function will first get a new token store, then it will log into Office365's SMTP Server using the new token store. If login is successful then it will return a new valid token store. When fetching a new token store, we will examine the current token store to determine what action, if any, needs to be taken to return a valid, current token store.

- If the current token store is still valid, then it is used and returned from this function
- If the current token store has an expired access token, but a valid refresh token, then the token is silently refreshed and the new token store is used to login then returned.
- If the current token store is invalid or empty, then a new token store is fetched. (Note, you must call EmailOffice365GetLoginUrl and login to Office365 first to be able to fetch a token.)

The optional parameters (office365ClientId, office365ClientSecret, and state) should only be used if this OAuth Workflow is being performed across multiple sessions (i.e. Different PSOS calls for EmailOffice365GetLoginUrl and EmailOffice365ConnectIMAP) If that is the case, then you must supply the same state parameter to both functions, and if you are using custom Office365 keys, supply those as well.

Parameters:

  `username` - - The email address of the Office365 account that will be connected to
  `tokenStore` - - The OAuth token that will be used to log in to the account. This can be null, or expired, and the function will attempt to fetch, or refresh, the token.
  `office365ClientId` - - The client_id from your Microsoft Azure Account. This is optional and can be omitted. However, if you supply these parameters to this call, be sure that you have supplied them to EmailOffice365GetLoginUrl as well.
  `office365ClientSecret` - - The client_secret from your Microsoft Azure Account. This is optional and can be omitted.
  `office365TenantId` - - The Tenant ID associated to the application with client_id. This is optional and can be omitted.
  `state` - - The UUID that is used to match the login url request and the fetch token request. This is optional, and only required if performing these functions across different sessions.

Returns:

### EmailOffice365GetLoginUrl ( tokenStore { ; office365ClientId ; office365ClientSecret ; office365TenantId ; state } )

This function will examine the tokenStore provided and return:

- A login url, if the token is empty, or both tokens are invalid. Users will need to log into the url, then you can call EmailOffice365ConnectIMAP or EmailOffice365ConnectSMTP to retrieve the tokens generated by the OAuth process.
- Empty, if the token is valid, or it can be silently refreshed. We will need to call EmailOffice365ConnectIMAP or EmailOffice365ConnectSMTP to refresh the current token store.
- ERROR, if there was an error when creating the login url

The optional parameters "state", "office365ClientId", and "office365ClientSecret", should only be used if this OAuth Workflow is being performed across multiple sessions (i.e. Different PSOS calls for EmailOffice365GetLoginUrl and EmailOffice365ConnectSMTP) If that is the case, then you must supply the same parameters to all functions.

Parameters:

  `tokenStore` - - The OAuth token that will be used to log in to the account. This can be null, or expired, and the function will attempt to fetch, or refresh, the token.
  `office365ClientId` - - The client_id from your Microsoft Azure Account. This is optional and can be omitted. However, if you supply these parameters to this call, be sure to supply them to EmailOffice365ConnectIMAP or EmailOffice365ConnectSMTP as well.
  `office365ClientSecret` - - The client_secret from your Microsoft Azure Account. This is optional and can be omitted.
  `office365TenantId` - - The Tenant ID associated to the application with client_id. This is optional and can be omitted.
  `state` - - The UUID that is used to match the login url request and the fetch token request. This is optional, and only required if performing these functions across different sessions.

Returns: a login url, an empty result, or ERROR.

### EmailOutboundIsConnected

### EmailOutgoingMessageId

Returns the Message-ID of the last message sent using the Emailer plugin.

Returns: a Message-ID value, or "" if there was no available message.

### EmailQuickSend ( from ; to ; subject ; body {; attachment } )

Convenient way to send a single simple message to one or more recipients.

Possible URIs for adding an attachment are listed in the EmailAttachFile function.

Parameters:

  `from` - The "from" email address. Use "Name <you@domain.com> for displaying the name instead.
  `to` - A comma-separated list of "to" email addresses
  `subject` - The subject of the message
  `body` - The message body. If the body starts with `<html` it is assumed to be an HTML-formatted message.
  `attachment` - A container holding an attachment to include with the email, or a URL or path to a file to attach.

Returns: 1 on success, or "ERROR" if something went wrong

### EmailReadAttachment ( path { ; savePath } )

Read a downloaded attachment into a FileMaker container field. To download attachments, you must pass `attachments=true` as a parameter to the EmailReadMessages function.

This function will retrieve attachment files only for paths generated by calling EmailReadMessages() with argument "attachments=true". Also, attachments will no longer be retrievable once the connection to the inbound server has been severed(e.g. calling EmailDisconnect).

After importing an email message into FileMaker, pass any attachment paths to this function to get container data for the attachment path. For example, you might pass the following argument:

     EmailReadAttachment(
         "/Macintosh HD/private/tmp/4545776.01203682301836.JavaMail.root@pluto.local/text.html"
     )

The supplied path should not begin with `file:`, `image:`, or any other prefix - just the path.

This can also be a part of your email parsing loop by passing in the return of EmailReadMessageValue("attachmentsAll")

         EmailConnectIMAP(...)//connect to IMAP Server
         EmailReadMessages("attachments=true")//passing in false will still get a list of attachments but only file names no paths
         Set Variable[$count;Value:1] //variable to control exit loop condition
     Loop
         Exit Loop If [not EmailGetNextMessage]
         New Record/Request
         Set Variable[$attachList ; Value: EmailReadMessageValue( "attachmentsAll" )] //can also specify "attachmentsInline" or "attachments"
         Go to Layout["Attachments"; Animation:None]
         Loop
             Exit Loop If[ValueCount($attachments)< $count]
             New Record/Request
             Set Field[Attachments::Data; EmailReadAttachment(GetValue($attachList;$count))
             Set Variable[$count; Value: $count+1]
         End Loop
         //do some more message parsing here
     End Loop

Note: this function will actually work for any file, it doesn't need to be an email attachment.

Parameters:

  `path` - The path as returned in the email import
  `savePath` - An optional path parameter to save the attachment to a local folder instead of a container field

Returns: container data for the file at `path`, or "ERROR" if an error occurred (use EmailLastError in this case)

### EmailReadMessages ( { flag1 ; flag2 ; ... } )

Reads messages from the currently connected inbound mail server. After calling this function, you will typically use the EmailGetNextMessage function to iterate over the messages which were fetched. As an alternate approach, you can perform an XML import of the fetched message data, using the value returned from this function as the XML file path.

If an error occurs, this function will return "ERROR". Use the {@link #EmailLastError()} function to get more information about the error.

### Fetching Unread Messages

The Email plugin supports reading messages from POP and IMAP mailboxes. Typically, you're interested in only fetching new messages from your mailbox. There are several approaches to doing this.

#### Option 1: Search by UID (IMAP or POP3)

Note: POP3 mail servers are not required to support UIDs. Please check with the server administrator about UID support.

IMAP and POP3 mailboxes assign each message a unique UID. When reading messages from an IMAP or POP3 mailbox, you can get the value for this UID with the following function:

     Set Field[ImportedMessage::uid ; EmailReadMessageValue( "uid" ) ]

Once you have the UID of the most recently fetched message, you can pass that in as an argument to subsequent calls to EmailReadMessages, for example:

     Go To Record/Request/Page [Last]
     Set Variable [ $result = EmailReadMessages (
         "uid=" & ImportedMessage::uid
     )
     ]

This fetches only the messages whose UID is greater than the most recently fetched message. This is the preferred way to fetch new messages from a mailbox, as it is very efficient, doesn't modify any messages, and will work even if another email client accesses the mailbox.

#### Option 2: Search for Unread Messages

You can specify a filter option to only search for unread messages:

     Set Variable [ $result = EmailReadMessages ("viewed=false" ;"readonly=false")

After fetching unread messages, you should then set the "viewed" flag to `true` for each message, so subsequent reads will skip these messages. This is outlined in the following section "Reading Individual Messages"

Note: searching for unread messages will not work correctly if other email clients are accessing the same mailbox and marking messages as viewed.

#### Option 3: Skipping messages

This is similar to option 2, except you don't need to modify the messages on the server. Simple count how many messages have been fetched from the mailbox, and pass a `skip` parameter to the `EmailReadMessages` function whose value is this number.

Note: If messages are deleted from the mailbox, local messages should be deleted as well, so the local `count` matches the number of fetched messages on the server.

### Reading Individual Messages

After successfully calling EmailReadMessages, you can iterate over the fetched messages using the EmailGetNextMessage function. This pattern typically looks like this:

     Loop
         Exit Loop If [not EmailGetNextMessage]
         New Record/Request
         Set Field[ImportedMessage::from ; EmailReadMessageValue( "from" )]
         Set Field[ImportedMessage::to ; EmailReadMessageValue( "to" )]
         Set Field[ImportedMessage::subject ; EmailReadMessageValue( "subject" )]
         Set Field[ImportedMessage::body ; EmailReadMessageValue( "body" )]
         Set Field[ImportedMessage::messageId ; EmailReadMessageValue( "messageId" )]
         // OPTIONAL: mark this messages as "viewed"
         // You must pass readonly=false during EmailReadMessages to do this
         Set Variable[$result ; EmailMessageSetFlag("viewed")]
     End Loop

### Importing Messages via XML

To import email data into FileMaker via XML, use the "Import Records" script step, and specify an XML data source, passing the file URL returned from this function.
Use the "messageId" field in the resulting XML as a match field when defining import options. Note: XML import is not a web-safe script. Use the method described in "Reading Individual Messages" if your script is running in IWP or on the server, or if you need to modify individual messages on the server.

### Flags

This function accepts a variety of flags which allow you to fine-tune how the messages are read. Flags should be entered as `key=value` arguments. You can specify any number of flags you wish.

The following is a description of the available flags:

progress
  Whether to show a cancellable progress bar (default is false).
progressLocation
  Location of the progress bar, e.g. "`100,200`". Default is centered on-screen.
mailbox
  The name of the mailbox to read messages from Note: this is only useful for IMAP accounts. The default behavior is to read messages from the `INBOX`.
attachments
  Boolean flag indicating whether to download attachment data. The default value is `true`, which enables attachment downloading. Setting this to `false` will disable downloading attachments, which can be significantly faster. If attachment downloading is disabled, you can still retrieve a list of the attachments in a message using the `EmailReadMessageValue ( "attachments" )` function. You can then re-read the message at a later time to download the attachments.
skip
  Skip this many records before reading results. This is useful for fetching messages in batches, if you know that messages will not be deleted from a mailbox during reading.
max
  Do not return more than this many records in the import
uid
  (Note: not all POP3 mail servers support UIDs) only fetch messages whose `uid` is newer than the one passed in. This is very useful for only fetching new messages from IMAP mailboxes. When looping through new messages, call `EmailReadMessageValue("uid")` on the last message and save this to a field in your database. Then when fetching new messages, pass this `uid` in as a filter argument. Only newer messages will be returned. Note: if you specify this option and the mailbox is an IMAP mailbox, some of the other search filters (skip, to, from, date) will be ignored.
dateFrom
  Filter messages to only return messages sent on or after a certain date (some IMAP mailboxes require an additional flag of "deleted=any" for EmailReadMessages to read emails using this parameter).
dateTo
  Filter messages to only return messages sent on or before a certain date (some IMAP mailboxes require an additional flag of "deleted=any" for EmailReadMessages to read emails using this parameter).
from
  Filter messages by `from` address
to
  Filter messages by `to` address
subject
  Filter messages by `subject`
messageId
  Filter messages by `messageId.` Note: If the message is in a different folder/mailbox other than inbox, you will need to specify the folder/mailbox by using the `mailbox` parameter.
body
  Filter messages by `body`
attachmentsDir
  Specify a directory for attachments to be downloaded into
viewed
  Filter messages by their read/unread status. Pass `true` to return only previously viewed messages, `false` to return only unread messages.
flagged
  Filter messages by their flagged status. Pass `true` to return only flagged messages, `false` to return only non-flagged messages.
deleted
  Filter messages by their deleted status. Pass `true` to return only deleted messages, `false` to return only non-deleted messages The default is `false`, meaning deleted message will be excluded.
alternateDecoding
  Use an alternate method of decoding retrieved emails. Please contact 360Works if you are unsure of when to use this parameter. Pass `1` to enable (e.g., "alternateDecoding=1"). The alternate decoding method is disabled by default
readonly
  Whether to open the mailbox folder as readonly or read-write. The default is `true` (read-only). If you plan on deleting, moving, or flagging any messages, use `false` in this parameter. Note: setting `readonly=false` will cause any fetched messages to be marked as "viewed"!

For example, you might use the following to fetch the first 25 unread messages from your inbox, not downloading attachments:

     EmailReadMessages("mailbox=INBOX" ;"attachments=false" ;"max=25";"viewed=false")

Parameters:

  `flags` - optional flags which control how messages are read.

See also: EmailConnectIMAP, EmailConnectPOP, EmailGetNextMessage, EmailReadMessageValue
Returns: The URL of the local XML file. This URL can be passed to FileMaker as the XML data source location.

### EmailReadMessagesFromFile ( file { ; charset=UTF-8 } )

This reads messages from an non-directory `MBOX` file or raw message content file (`.eml`), and stores the parsed messages in an FMPXML file, suitable for import into FileMaker. In addition, you can use the EmailGetNextMessage function after calling this to loop over the messages and programatically read individual values using the EmailReadMessageValue

### Flags

The following is a description of the available flags:

charset
  Character set of the file. Leave this blank to use the default for your locale.

Note: this will disconnect from your current mail server if there is an active connection.

Parameters:

  `file` - path to an MBOX file

Returns: URL to an FMPXML file containing the parsed messages in the file

### EmailReadMessageValue ( key )

This is included so this function can be called as a script step. Please see below for documentation on this function

Parameters:

  `key` - The key to retrieve

See also: EmailGetNextMessage, EmailReadMessages
Returns: The value for that key in the current message.

### EmailReadMessageValue ( key )

Retrieves information about the last message which was gotten by the `EmailGetNextMessage` function.

If there are multiple values for a key, each value will be on a separate line.

The parameter must be one of the following values (case-insensitive):

- count (The total number of messages fetched from the server)
- from (The FROM address)
- to (The TO addresses, comma-separated)
- cc (The CC addresses, comma-separatapped)
- bcc (The BCC addresses, comma-separated)
- replyTo (The reply-to address)
- subject
- messageNumber (the integer index of the message on the server. 1 is the first message in the mailbox)
- sent (The timestamp the message was sent)
- messageID (The unique message ID for the email message)
- attachments (A return-separated list of attachments for the message. Each line is either the attachment file path, or the name, depending on the value of the `attachments` parameter in `EmailReadMessages`). Note: inlined attachments are excluded from this list. Use `attachmentsAll` to get all attachments including inlined ones, or `attachemntsINLINE` to get only inline attachments..
- text (The plain-text message content, if available)
- html (The HTML body part, if one is available. If attachments are set to download, inline attachment images will be converted to base64 data URLs automatically. If you don't want this behavior, use `htmlRaw` instead, or set `attachments=false` when fetching messages.)
- htmlRaw (The HTML body part unaltered, if one is available.)
- uid (returns the IMAP or POP3 folder uid Note: not all POP3 mail servers support UIDs)
- viewed (1 or empty to indicate whether the message has been read (1) or is unread)
- flagged (1 or empty to indicate whether the message is flagged)
- replied (1 or empty)
- deleted (1 or empty)
- header:HEADER_NAME (any header value, replace HEADER_NAME with the name of the header to retrieve)
- headers (a return-separated list of all message headers)
- raw: (the raw source of the entire message)

### Reading Message Headers

You can retrieve any message header by using this function. For example, to get information about the mail application which sent the message, you can use `EmailReadMessageValue("header:X-Mailer")`. If a header has multiple values, they will be returned as a return-separated list.

Parameters:

  `key` - The key to retrieve, must be one of the above listed keys.

See also: EmailGetNextMessage, EmailReadMessages
Returns: The value for that key in the current message.

### EmailRecipients ( to_addresses { ; append } )

Set the TO recipients for the current message. This can be called multiple times before sending, to build up a list of recipients (set `append` to true if doing this).

         EmailRecipients(someOne@email.com;true)
         EmailRecipients(someOneElse@email.com, anotherOne@email.com;true)//appends address to recipients list

         EmailRecipients(someOne@email.com;false) //overwrites current recipient list
         EmailRecipients(someOneElse@email.com;false) //overwrites previous call

Parameters:

  `to_addresses` - comma-separated list of addresses
  `append` - whether to append the new addresses to existing ones, or overwrite them.

Returns: 1 on success, ERROR if one or more addresses are invalid.

### EmailRegister ( licenseKey ; registeredTo )

Registers the Email Plugin.

Parameters:

  `licenseKey` - a valid license key string.
  `registeredTo` - the company name for the license key used.

Returns: 1 on success, or "ERROR" on failure.

### EmailReportProblem ( emailAddress ; problemDescription )

Send a problem report to 360Works.

Parameters:

  `emailAddress` - The user's email address to allow for support contact
  `problemDescription` - A description of the current issue

Returns: Always returns 1

### EmailSend ( progress ; progressLocation )

Send the current email, as defined in the EmailCreate, EmailSetSubject, EmailSetBody, and other functions.

Parameters:

  `showProgress` - Whether to show a progress bar. Default = `false`
  `progressLocation` - Location of the progress bar, e.g. "`100,200`"

### EmailSend ( { progress=true ; progressLocation=100,200 ; ... } )

Send the current email, as defined in the EmailCreate, EmailSetSubject, EmailSetBody, and other functions.

### Optional Parameters

progress
  Whether to show a progress bar. Default = `false`.
progressLocation
  Location of the progress bar, e.g. "`100,200`". Default is centered on-screen.

Parameters:

  `options` - optional parameters

Returns: 1 on success, ERROR if something went wrong with sending the message

### EmailSetBody ( body { ; contentType ; characterSet } )

Sets a body part of the current message. Common content types are "plain" and "html". You can call this multiple times for a single message to provide an HTML body part with a plaintext alternative part. You can use the EmailBodySubstitute function to perform substitute/replace operations on the body content loaded by this function.

     EmailCreate( "from@example.com", "to@example.com", "A multipart message" )
     EmailSetBody( Email::body ; "plain" ) // this is used for mail clients which don't display HTML
     EmailSetBody( Email::HTMLbody ); "html" ) // HTML version with formatting
     EmailSend

Parameters:

  `body` - text to be displayed in the message
  `contentType` - type of formatting used in the body, e.g. "plain", "html", "rtf".
  `characterSet` - optional character set

Returns: 1 on success

### EmailSetBodyFile ( url ; embedResources )

This is used to load an HTML document as the email body part. You can use the EmailBodySubstitute function to perform substitute/replace operations on the body content loaded by this function.

### Embedding Resources

If you pass `true` as the `embedResources` parameter, any images or stylesheets referenced in the email message will be included as inline attachments in the email message. This means that users will not need to load the resources from the central server, but it can increase the email message size considerably.

If you pass `false` as the `embedResources` parameter, any referenced image URLs will be rewritten as absolute URLs.

### MHTML Files

This function also accepts .mhtml html archive files, which have the advantage of already having all images embedded in the file. The `embedResources` parameter is always effectively `true` for .mhtml files.

Parameters:

  `url` - URL to the HTML document.
  `embedResources` - whether resources should be embedded in the HTML email or rewritten as absolute URLs.

Returns: 1 on success, "ERROR" on failure (use the EmailLastError function to get more information)

### EmailSetErrorCapture ( errorCapture )

Toggles error dialogs on or off. When something unexpected happens, the plug-in will pop up a dialog displaying the error message. This makes it easy to see what went wrong. However, in some cases, you may prefer to show your own message to the user, or possibly not show a message at all. In that case, you can call EmailSetErrorCapture with a parameter of true. That will suppress the error dialog from appearing to the user. This is a boolean value so make sure you do not put the parameter in "". NOTE:This will only suppress error dialogs when plugin functions are called as part of a calculation. If you are calling plugin functions as script steps ( available in FM 16+) then you will need to use the native FileMaker function Set Error Capture On/Off

Parameters:

  `errorCapture` - set to true to suppress the default popups.

### EmailSetHeader ( header ; value )

Set a custom header in the message. This is not needed for the majority of cases. A list of header fields can be found here. These should be modified by advanced users only. For Example (below is a short list of the more commonly used headers):

      EmailSetHeader( "reply-to" ; "reply@example.com" )
      EmailSetHeader( "bcc" ; "blind@example.com" )
      EmailSetHeader( "subject" ; "List of Example Headers" )

Parameters:

  `header` - the header name
  `value` - the header value

Returns: 1 on success, or ERROR on failure

### EmailSetSubject ( subject )

This allows you to customize the subject of the current outgoing email message, as specified in the {@link #EmailCreate} function. This can be useful if you are sending the same message to multiple recipients, with a custom subject for each recipient.

       EmailConnectSMTP(...)//Connect to SMTP server
       EmailCreate( "from@example.com", "to@example.com", "Multiple Subjects" )
       EmailSetBody( Email::body; "html" )//body will be the same for all recipients
       Go to Record/Request/Page [First]
       Loop
           EmailRecipients(Customer::EmailAddress) //not passing in true for append parameter overwrites recipients list
           EmailSetSubject("Alert for:"& Customer::Name)
           EmailSend
       Go to Record/Request/Page[Next;Exit after last: On]
       End Loop

Parameters:

  `subject` - the email message subject

Returns: 1 on success

### EmailSetWindowManagement ( windowManagement )

Parameters:

### EmailSMSSend ( accessKey ; secretKey ; recipient ; body { ; region } )

Sends an SMS message via Amazon AWS / SNS. Separate multiple recipients with a comma or newline.

Parameters:

  `accessKey` - Your AWS access key
  `secretKey` - Your AWS secret key
  `recipient` - Phone numbers to send the message to
  `body` - SMS Body. Some carriers may break long messages into separate, shorter messages.
  `region` - Optional. AWS region from which the SMS message will send. Default is us-east-1

### EmailVersion

Returns the version number of the Email plugin.

Returns: a text version number

### IsValidEmail ( email )

Convenience function for validating an email address. This checks for conformance to RFC 822, but does not actually check that an active email account exists at this address.

Parameters:

  `email` - one or more email addresses to validate (comma-separated).

Returns: 1 if the all emails are valid, 0 if any address is invalid, or "" if `email` is empty.