How to use tsNet to display an e-mail message from an IMAP account
Introduction
tsNet can be used to connect to e-mail servers via the IMAP protocol in order to interact with the messages stored in an e-mail mailbox.
This lesson shows how you can get a list of messages stored in an e-mail inbox via IMAP and then retrieve an e-mail's contents.
Lay out the Stack
To begin with, let's retrieve a list of all the messages currently in the Inbox.
Create a new stack then drag a button and a scrolling list field onto it.
Set the name of this field to "Message List" and change the name of the button to "Get Message List".
Save this stack.
Create the Script
Edit the script of the button that you placed on the stack by right clicking on the button and selecting "edit script".
Add the following code.
on mouseUp
-- This is the IMAP server that you want to connect to, use "imaps://" to specify an SSL connection is to be made
put "imaps://example.com" into tURL
-- Add the IMAP server username and password into the tSettings array to be passed to the tsNet calls
put "username" into tSettings["username"]
put "password" into tSettings["password"]
-- Send a command to the IMAP server to tell it we want to perform operations against the INBOX
put "SELECT INBOX" into tCommand
put tsNetCustomSync(tURL, tCommand, tHeaders, tRecvHeaders, tResult, tBytes, tSettings) into tData
if tResult is 0 then
-- Send a command to the IMAP server to tell it to list all messages that are not deleted
put "SEARCH NOT DELETED" into tCommand
put tsNetCustomSync(tURL, tCommand, tHeaders, tRecvHeaders, tResult, tBytes, tSettings) into tData
if tResult is 0 then
-- The request is successful, so tData will now contain a space separate listed of message UIDs
-- preceded by "* SEARCH"
-- Delete "* SEARCH" from the response
delete word 1 to 2 of tData
-- Convert the space delimited list of message UIDs to a return delimited list
replace space with cr in tData
-- Display the list to the user
put tData into field "Message List"
else
-- Otherwise an error has occurred, advise the user
answer "Error reading message list:" && tResult
end if
else
-- Otherwise an error has occurred, advise the user
answer "Error connecting to server:" && tResult
end if
end mouseUp
What this first script is going to do
You will notice that this script uses the tsNetCustomSync function twice. This tsNet function allows you to send custom messages to a server.
The IMAP protocol has a series of commands that can be sent in order to perform various queries and tasks. In this case, we are performing two tasks:
- "SELECT INBOX" - This tells the IMAP server that the next command being sent is going to be performed on the user's Inbox.
- "SEARCH NOT DELETED" - This command returns a space separated list of message UIDs that are currently in the selected mailbox folder (in this case, the Inbox) that have not been marked for deletion.
Test
Switch to Run mode and click the button.
Now for the next part...
As you can see in the screenshot above, the data returned in the field is a list of message UIDs. These UIDs are used when requesting the contents of a particular message or interacting with it in any other way (marking it as read, deleting it, etc...).
You now have a list of messages which with the use of a scrolling field, your users have now been provided a way to select a message. The next step is to be able to display the contents of a message that has been selected from this list. Follow these instructions in order to achieve this aim.
Drag another button and a field onto the stack that you have already created with the previous steps.
Set the name of this field to "Message Contents" and change the name of the newly added button to "Read Message".
Save this stack.
Create the Script
Edit the script of new button that you placed on the stack by right clicking it and selecting "edit script".
Add the following code.
on mouseUp
-- This is the IMAP server that you want to connect to, use "imaps://" to specify an SSL connection is to be made
put "imaps://example.com" into tURL
-- Add the IMAP server username and password into the tSettings array to be passed to the tsNet calls
put "username" into tSettings["username"]
put "password" into tSettings["password"]
-- Make sure the user has selected a message to view
if the selectedText of field "Message List" is empty then
answer "You must select a message to display"
exit mouseUp
end if
-- Generate a URL which uniquely specifies the selected message (by message UID) in the INBOX of the IMAP server above
put tURL & "/INBOX/;UID=" & the selectedText of field "Message List" into tMessageURL
-- Issue a tsNetGetSync call with the URL created above, this will return the complete e-mail message
-- specified by the URL
put tsNetGetSync(tMessageURL, tHeaders, tRecvHeaders, tResult, tBytes, tSettings) into tData
if tResult is 0 then
-- Display the message to the user
put "Message contents:" & cr & cr & tData into field "Message Contents"
else
-- Otherwise an error has occurred, advise the user
answer tResult
end if
end mouseUp
Test
Switch to Run mode and click the button.
Summary
At this point, you have written all the code to retrieve an e-mail via IMAP.
In the code of the second button, please note that there are no calls to tsNetCustomSync. In a similar manner to interacting with FTP and SFTP servers, you will use the tsNetGet* commands when retrieving a message or folder list.
This example uses the tsNetGetSync command with a specially formatted URL to indicate that we are retrieving a message with UID 212 from the Inbox in order to download the full message source to the LiveCode application.
John
Hi,
I really have no idea what I am doing but I did find a few bugs - or at least 'bugs' that affected my set up. Not sure why, but maybe I can learn something by posting the following.
Both were in the "Read Message" button on this line:
put tURL & "/INBOX/;UID=" & the selectedText of field "Message List" into tMessageURL
I first got an error "tsneter: (3) URL using bad/illegal format or missing URL".
I checked the selectedText of field "Message List" and noted selected text was 1 more char longer than what the number on the line was, ie, 1, returned the number of chars = 2 (I assume a space was included or return char). So I corrected this by adding word 1 of the selectedText of field "Message List"
Then I got this error message:
"tsneter: (78) Remote file not found".
I replaced UID with MAILINDEX (found this after a google search).
Then the script worked as written.
Any thoughts? What can I learn from this?
Panos Merakos
Dear John,
Thank you for the comment.
The tenet library uses the curl library. Looking at curl's docs (https://everything.curl.dev/usingcurl/reademail), it seems both UID and MAILINDEX are valid - but I think for the use-case of this lesson we have to use MAILINDEX. I'll investigate and update the lesson if this is the case.
Thank you for spotting this.
Kind regards,
Panos
--