Skip to main content
Version: 1.0.0

IMAPTransporter

The IMAPTransporter class allows you to retrieve messages from an IMAP email server.

Functions and properties

4D.IMAPTransporter objects provide the following properties and functions:

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

4D.IMAPTransporter.new()

4D.IMAPTransporter.new*( server : object ) : 4D.IMAPTransporter

ParameterTypeDescription
serverobjectMail server information
Result4D.IMAPTransporterIMAP transporter object

Description

The 4D.IMAPTransporter.new() function configures a new IMAP connection according to the server parameter and returns a new transporter object. The returned transporter object will then usually be used to receive emails.

In the server parameter, pass an object containing the following properties:

serverDefault value (if omitted)

False
.accessTokenOAuth2: string
.accessTokenOAuth2: object
string string or token object representing OAuth2 authorization credentials. Used only with OAUTH2 authenticationMode. If accessTokenOAuth2 is used but authenticationMode is omitted, the OAuth 2 protocol is used (if allowed by the server). Not returned in the IMAP transporter object.
none
- the most secure authentication mode supported by the server is used
- 300
- 30
- mandatory
- none
.password : string
User password for authentication on the server. Not returned in the IMAP transporter object.
none
- 993
- none

Warning: Make sure the defined timeout is lower than the server timeout, otherwise the client timeout will be useless.

Result

The function returns an IMAP transporter object. All returned properties are read-only.

The IMAP connection is automatically closed when the transporter object is destroyed.

Example

var server : object
var transporter : 4D.IMAPTransporter
var status : object
var info : string

server = newObject()
server.host = "imap.gmail.com" //Mandatory
server.port = 993
server.user = "qodly@gmail.com"
server.password = "XXXXXXXX"
server.logFile = "LogTest.txt" //log to save in the Logs folder

transporter = 4D.IMAPTransporter.new(server)

status = transporter.checkConnection()
if(not(status.success))
info = "An error occurred: "+status.statusText
end

.addFlags()

.addFlags*( msgIDs : collection , keywords : object ) : object
.addFlags( msgIDs : string , keywords : object ) : object
.addFlags( msgIDs : integer , keywords : object ) : object

ParameterTypeDescription
msgIDscollectionCollection of strings: Message unique IDs (string)
msgIDsstringUnique ID of a message
msgIDsintegerkIMAPAll: All messages in the selected mailbox
keywordsobjectKeyword flags to add
ResultobjectStatus of the addFlags operation

Description

The .addFlags() function adds flags to the msgIDs for the specified keywords.

In the msgIDs parameter, you can pass either:

  • a collection containing the unique IDs of specific messages or
  • the unique ID (string) of a single message or
  • the following constant (integer) for all messages in the selected mailbox:
ConstantValueComment
kIMAPAll1Select all messages in the selected mailbox

The keywords parameter lets you define the flags to add to msgIDs. You can use the following standard flags as well as custom flags (custom flags support depends on the server implementation):

PropertyTypeDescription
$draftbooleantrue to add the "draft" flag to the message
$seenbooleantrue to add the "seen" flag to the message
$flaggedbooleantrue to add the "flagged" flag to the message
$answeredbooleantrue to add the "answered" flag to the message

|$deleted |boolean | true to add the "deleted" flag to the message| |<custom flag> |boolean | true to add the custom flag to the message|

The custom flags names must respect this rule: the keyword must be a case-insensitive string excluding control chars and space and can not include any of these characters: ( ) { ] % * " \

  • For a keyword to be taken into account it has to be true.
  • The interpretation of keyword flags may vary per mail client.

Returned object

The function returns an object describing the IMAP status:

PropertyTypeDescription
successbooleantrue if the operation is successful, False otherwise
statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
errorscollectionQodly error stack (not returned if a IMAP server response is received)
[].errcodeNumberQodly error code
[].messagestringDescription of the Qodly error
[].componentSignaturestringSignature of the internal component which returned the error

Example

var transporter : 4D.IMAPTransporter
var options,boxInfo,status : object

options = newObject()
options.host = "imap.gmail.com"
options.port = 993
options.user = "qodly@gmail.com"
options.password = "xxxxx"

// Create transporter
transporter = 4D.IMAPTransporter.new(options)

// Select mailbox
boxInfo = transporter.selectBox("INBOX")

// Mark all messages from INBOX as read/seen
flags = newObject
flags["$seen"] = true
status = transporter.addFlags(kIMAPAll,flags)

.append()

.append*( mailObj : object , destinationBox : string , options : object ) : object

ParameterTypeDescription
mailObjobjectEmail object
destinationBoxstringMailbox to receive Email object
optionsobjectobject containing charset info
ResultobjectStatus of the append operation

Description

The .append() function appends a mailObj to the destinationBox.

In the mailObj parameter, pass an Email object. For a comprehensive description of mail properties, see Email object. The .append() function supports keyword tags in the Email object's keywords attribute.

The optional destinationBox parameter lets you pass the name of a mailbox where the mailObj will be appended. If omitted, the current mailbox is used.

In the optional options parameter, you can pass an object to define the charset and encoding for specific parts of the email. Available properties:

PropertyTypeDescription
headerCharsetstringCharset and encoding used for the following parts of the email: subject, attachment filenames, and email name attribute(s). Possible values: See possible charsets table below
bodyCharsetstringCharset and encoding used for the html and string body contents of the email. Possible values: See possible charsets table below

Possible charsets:

ConstantValueComment
kMailModeUTF8US-ASCII_UTF8_QPheaderCharset & bodyCharset: US-ASCII if possible, otherwise UTF-8 & Quoted-printable (default value)
kMailModeUTF8InBase64US-ASCII_UTF8_B64headerCharset & bodyCharset: US-ASCII if possible, otherwise UTF-8 & base64

Returned object

The function returns an object describing the IMAP status:

PropertyTypeDescription
successbooleantrue if the operation is successful, False otherwise
statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
errorscollectionQodly error stack (not returned if a IMAP server response is received)
[].errcodeNumberQodly error code
[].messagestringDescription of the Qodly error
[].componentSignaturestringSignature of the internal component which returned the error

Example

To save an email in the Drafts mailbox:

var imap : 4D.IMAPTransporter
var settings, status, msg: object

settings = newObject("host", "domain.com", "user", "xxxx", "password", "xxxx", "port", 993)

imap = 4D.IMAPTransporter.new(settings)

msg = newObject()
msg.from = "xxxx@domain.com"
msg.subject = "Lorem Ipsum"
msg.stringBody = "Lorem ipsum dolor sit amet, consectetur adipiscing elit."
msg.keywords = newObject
msg.keywords["$seen"] = true //flag the message as read
msg.keywords["$draft"] = true //flag the message as a draft

status = imap.append(msg, "Drafts")

.checkConnectionDelay

.checkConnectionDelay* : integer

Description

The .checkConnectionDelay property contains the maximum time (in seconds) allowed prior to checking the connection to the server. If this time is exceeded between two method calls, the connection to the server will be checked. By default, if the property has not been set in the server object, the value is 300.

Warning: Make sure the defined timeout is lower than the server timeout, otherwise the client timeout will be useless.

.copy()

.copy*( msgsIDs : collection , destinationBox : string ) : object
.copy( allMsgs : integer , destinationBox : string ) : object

ParameterTypeDescription
msgsIDscollectionCollection of message unique IDs (strings)
allMsgsintegerkIMAPAll: All messages in the selected mailbox
destinationBoxstringMailbox to receive copied messages
ResultobjectStatus of the copy operation

Description

The .copy() function copies the messages defined by msgsIDs or allMsgs to the destinationBox on the IMAP server.

You can pass:

  • in the msgsIDs parameter, a collection containing the unique IDs of the specific messages to copy, or
  • in the allMsgs parameter, the kIMAPAll constant (integer) to copy all messages in the selected mailbox.

The destinationBox parameter allows you to pass a string value with the name of the mailbox where the copies of messages will be placed.

Returned object

The function returns an object describing the IMAP status:

PropertyTypeDescription
successbooleantrue if the operation is successful, False otherwise
statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
errorscollectionQodly error stack (not returned if a IMAP server response is received)
[].errcodeNumberQodly error code
[].messagestringDescription of the Qodly error
[].componentSignaturestringSignature of the internal component which returned the error

Example 1

To copy a selection of messages:

 var server,boxInfo,status : object
var mailIds : collection
var transporter : 4D.IMAPTransporter

server = newObject()
server.host = "imap.gmail.com" //Mandatory
server.port = 993
server.user = "qodly@gmail.com"
server.password = "XXXXXXXX"

transporter = 4D.IMAPTransporter.new(server)

//select mailbox
boxInfo = transporter.selectBox("inbox")

//get collection of message unique IDs
mailIds = transporter.searchMails("subject \"New feature:\"")

// copy found messages to the "documents" mailbox
status = transporter.copy(mailIds,"documents")

Example 2

To copy all messages in the current mailbox:

 var server,boxInfo,status : object
var transporter : 4D.IMAPTransporter

server = newObject()
server.host = "imap.gmail.com" //Mandatory
server.port = 993
server.user = "qodly@gmail.com"
server.password = "XXXXXXXX"

transporter = 4D.IMAPTransporter.new(server)

//select mailbox

boxInfo = transporter.selectBox("inbox")

// copy all messages to the "documents" mailbox
status = transporter.copy(kIMAPAll,"documents")

.createBox()

.createBox*( name : string ) : object

ParameterTypeDescription
namestringName of the new mailbox
ResultobjectStatus of the mailbox creation operation

Description

The .createBox() function creates a mailbox with the given name. If the IMAP server’s hierarchy separator character appears elsewhere in the mailbox name, the IMAP server will create any parent names needed to create the given mailbox.

In other words, an attempt to create "Projects/IMAP/Doc" on a server in which "/" is the hierarchy separator character will create:

  • Only the "Doc" mailbox if "Projects" & "IMAP" already exist.
  • "IMAP" & "Doc" mailboxes if only "Projects" already exists.
  • "Projects" & "IMAP" & "Doc" mailboxes, if they do not already exist.

In the name parameter, pass the name of the new mailbox.

Returned object

The function returns an object describing the IMAP status:

PropertyTypeDescription
successbooleantrue if the operation is successful, False otherwise
statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
errorscollectionQodly error stack (not returned if a IMAP server response is received)
[].errcodeNumberQodly error code
[].messagestringDescription of the Qodly error
[].componentSignaturestringSignature of the internal component which returned the error

Example

To create a new "Invoices" mailbox:

var info : string
var transporter : 4D.IMAPTransporter
var options, status : object

options = newObject()

options.host = "imap.gmail.com"
options.user = "test@gmail.com"
options.password = "XXXX"

transporter = 4D.IMAPTransporter.new(options)

status = transporter.createBox("Invoices")

if(status.success)
info = "Mailbox creation successful!"
else
info = "Error: "+status.statusText
end

.delete()

.delete*( msgsIDs : collection ) : object
.delete( msgsIDs : integer ) : object

ParameterTypeDescription
msgsIDscollectioncollection of message unique IDs (strings)
msgsIDsintegerkIMAPAll: All messages in the selected mailbox
ResultobjectStatus of the delete operation

Description

The .delete() function sets the "deleted" flag for the messages defined in msgsIDs.

In the msgsIDs parameter, you can pass:

  • a collection containing the unique IDs of the specific messages to delete, or
  • the kIMAPAll constant (integer) to delete all messages in the selected mailbox.

Executing this function does not actually remove messages. Messages with the "delete" flag can still be found by the .searchMails() function. Flagged messages are deleted from the IMAP server with the .expunge() function or by selecting another mailbox or when the IMAP transporter object (created with 4D.IMAPTransporter.new) is destroyed.

Returned object

The function returns an object describing the IMAP status:

PropertyTypeDescription
successbooleantrue if the operation is successful, False otherwise
statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
errorscollectionQodly error stack (not returned if a IMAP server response is received)
[].errcodeNumberQodly error code
[].messagestringDescription of the Qodly error
[].componentSignaturestringSignature of the internal component which returned the error

Example 1

To delete a selection of messages:

 var server,boxInfo,status : object
var mailIds : collection
var transporter : 4D.IMAPTransporter

server = newObject()
server.host = "imap.gmail.com" //Mandatory
server.port = 993
server.user = "qodly@gmail.com"
server.password = "XXXXXXXX"

transporter = 4D.IMAPTransporter.new(server)

//select mailbox
boxInfo = transporter.selectBox("Inbox")

//get collection of message unique IDs
mailIds = transporter.searchMails("subject \"Reports\"")

// Delete selected messages
status = transporter.delete(mailIds)

Example 2

To delete all messages in the current mailbox:

 var server,boxInfo,status : object
var transporter : 4D.IMAPTransporter

server = newObject()
server.host = "imap.gmail.com" //Mandatory
server.port = 993
server.user = "qodly@gmail.com"
server.password = "XXXXXXXX"

transporter = 4D.IMAPTransporter.new(server)

//select mailbox
boxInfo = transporter.selectBox("Junk Email")

// delete all messages in the current mailbox
status = transporter.delete(kIMAPAll)

.deleteBox()

.deleteBox*( name : string ) : object

ParameterTypeDescription
namestringName of the mailbox to delete
ResultobjectStatus of the mailbox deletion operation

Description

The .deleteBox() function permanently removes the mailbox with the given name from the IMAP server. Attempting to delete an INBOX or a mailbox that does not exist will generate an error.

In the name parameter, pass the name of the mailbox to delete.

  • The function cannot delete a mailbox that has child mailboxes if the parent mailbox has the "\Noselect" attribute.
  • All messages in the deleted mailbox will also be deleted.
  • The ability to delete a mailbox depends on the mail server.

Returned object

The function returns an object describing the IMAP status:

PropertyTypeDescription
successbooleantrue if the operation is successful, False otherwise
statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
errorscollectionQodly error stack (not returned if a IMAP server response is received)
[].errcodeNumberQodly error code
[].messagestringDescription of the Qodly error
[].componentSignaturestringSignature of the internal component which returned the error

Example

To delete the "Nova Orion Industries" child mailbox from the "Bills" mailbox hierarchy:

var pw, name, info : string
var options, status : object
var transporter : 4D.IMAPTransporter

options = newObject()

pw = "XXXXXX" //password

options.host = "imap.gmail.com"
options.user = "test@gmail.com"
options.password = pw

transporter = 4D.IMAPTransporter.new(options)

// delete mailbox
name = "Bills"+transporter.getDelimiter()+"Nova Orion Industries"
status = transporter.deleteBox(name)

if(status.success)
info = "Mailbox deletion successful!"
else
info = "Error: "+status.statusText
end

.expunge()

.expunge*() : object

ParameterTypeDescription
ResultobjectStatus of the expunge operation

Description

The .expunge() function removes all messages with the "deleted" flag from the IMAP mail server. The "deleted" flag can be set with the .delete() or .addFlags() functions.

Returned object

The function returns an object describing the IMAP status:

PropertyTypeDescription
successbooleantrue if the operation is successful, False otherwise
statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
errorscollectionQodly error stack (not returned if a IMAP server response is received)
[].errcodeNumberQodly error code
[].messagestringDescription of the Qodly error
[].componentSignaturestringSignature of the internal component which returned the error

Example

var transporter : 4D.IMAPTransporter
var options,boxInfo,status : object
var ids : collection

options = newObject()
options.host = "imap.gmail.com"
options.port = 993
options.user = "qodly@gmail.com"
options.password = "xxxxx"

// Create transporter
transporter = 4D.IMAPTransporter.new(options)

// Select mailbox
boxInfo = transporter.selectBox("INBOX")

// Find and delete all seen messages in INBOX
ids = transporter.searchMails("SEEN")
status = transporter.delete(ids)

// Purge all messages flagged as deleted
status = transporter.expunge()

.getBoxInfo()

.getBoxInfo*({ name : string }) : object

ParameterTypeDescription
namestringName of the mailbox
ResultobjectboxInfo object

Description

The .getBoxInfo() function returns a boxInfo object corresponding to the current maibox, or the mailbox name. This function returns the same information as .selectBox() without changing the current mailbox.

In the optional name parameter, pass the name of the mailbox to access. The name represents an unambiguous left-to-right hierarchy with levels separated by a specific delimiter character. The delimiter can be found with the .getDelimiter() function.

If the mailbox name is not selectable or does not exist, the function generates an error and returns null.

Returned object

The boxInfo object returned contains the following properties:

PropertyTypeDescription
namestringName of the mailbox
mailCountnumberNumber of messages in the mailbox
mailRecentnumberNumber of messages with the "recent" flag (indicating new messages)
idstringUnique id of the mailbox
mailUnseennumberNumber of messages with the "unseen" flag

Example

 var server : object
var transporter : 4D.IMAPTransporter
var boxInfo : object
var info : string
transporter = 4D.IMAPTransporter.new(server)

boxInfo = transporter.getBoxInfo("INBOX")
info = "INBOX contains "+string(boxInfo.mailRecent)+" recent emails."

.getBoxList()

.getBoxList*( { parameters : object } ) : collection

ParameterTypeDescription
parametersobjectParameter object
ResultcollectionCollection of mailbox objects

Description

The .getBoxList() function returns a collection of mailboxes describing all of the available mailboxes. This function allows you to locally manage the list of messages located on the IMAP mail server.

In the optional parameters parameter, pass an object containing values to filter the returned mailboxes. You can pass:

PropertyTypeDescription
isSubscribedboolean
  • true to return only subscribed mailboxes
  • false to return all available mailboxes
  • namescollectionCollection of objects containing a "name" attribute or collection of texts containing the box names
    withBoxPropertiesbooleanIf true (default): adds the selectable, inferior, and interesting attributes to the result object. If false, these attributes are omitted.
    withBoxInfobooleanDefault value is false. If true, adds the mailCount, mailRecent, and id attributes to the result object.

    Result

    Each object of the returned collection contains the following properties:

    PropertyTypeDescription
    [].namestringName of the mailbox. Returned if withBoxProperties=true or withBoxInfo=true
    [].selectablebooleanIndicates whether or not the access rights allow the mailbox to be selected:
    • true - the mailbox can be selected
    • false - the mailbox can not be selected
    Returned if withBoxProperties=true
    [].inferiorbooleanIndicates whether or not the access rights allow creating a lower hierachy in the mailbox:
    • true - a lower level can be created
    • false - a lower level can not be created
    Returned if withBoxProperties=true
    [].interestingbooleanIndicates if the mailbox has been marked "interesting" by the server:
    • true - The mailbox has been marked "interesting" by the server. For example, it may contain new messages.
    • false - The mailbox has not been marked "interesting" by the server.
    Returned if withBoxProperties=true
    [].mailCountnumberNumber of messages in inbox. Returned if withBoxInfo=true
    [].mailRecentnumberNumber of messages marked "recent" (indicating new messages). Returned if withBoxInfo=true
    [].mailUnseennumberNumber of messages marked "unseen". Returned if withBoxInfo=true
    [].idstringUnique mailbox identifier. Returned if withBoxInfo=true

    If the account does not contain any mailboxes, an empty collection is returned.

    • If there is no open connection, .getBoxList() will open a connection.
    • If the connection has not been used since the designated connection delay (see 4D.IMAPTransporter.new), the .checkConnection( ) function is automatically called.

    Example

     var server : object
    var transporter : 4D.IMAPTransporter
    var boxList : collection
    var info, split : string
    transporter = 4D.IMAPTransporter.new(server)

    boxList = transporter.getBoxList()

    forEach(box,boxList)
    if(box.interesting)
    split = splitString(box.name,transporter.getDelimiter())
    info = "New emails are available in the box: "+split[split.length-1])
    end
    end

    .getDelimiter()

    .getDelimiter*() : string

    ParameterTypeDescription
    ResultstringHierarchy delimiter character

    Description

    The .getDelimiter() function returns the character used to delimit levels of hierarchy in the mailbox name.

    The delimiter is a character which can be used to:

    • create lower level (inferior) mailboxes
    • search higher or lower within the mailbox hierarchy

    Result

    Mailbox name delimiter character.

    Example

    See getBoxList() example.

    .getMail()

    .getMail*( msgNumber: integer { , options : object } ) : object
    .getMail( msgID: string { , options : object } ) : object

    ParameterTypeDescription
    msgNumberintegerSequence number of the message
    msgIDstringUnique ID of the message
    optionsobjectMessage handling instructions
    ResultobjectEmail object

    Description

    The .getMail() function returns the Email object corresponding to the msgNumber or msgID in the mailbox designated by the IMAP transporter object. This function allows you to locally handle the email contents.

    In the first parameter, you can pass either:

    • msgNumber, an integer value indicating the sequence number of the message to retrieve or
    • msgID, a string value indicating the unique ID of the message to retrieve.

    The optional options parameter allows you pass an object defining additional instructions for handling the message. The following properties are available:

    PropertyTypeDescription
    updateSeenbooleanIf true, the message is marked as "seen" in the mailbox. If False, the message is not marked as "seen". Default value: true
    withBodybooleanPass true to return the body of the message. If False, only the message header is returned. Default value: true
    • The function generates an error and returns Null if msgID designates a non-existing message,
    • If no mailbox is selected with the .selectBox() function, an error is generated,
    • If there is no open connection, .getMail() will open a connection the last mailbox specified with .selectBox()`.

    Result

    .getMail() returns an Email object with the following specific IMAP properties: id, receivedAt, and size.

    Example

    You want to get the message with ID = 1:

     var server : object
    var info, mail, boxInfo : variant
    var transporter : 4D.IMAPTransporter

    server = newObject()
    server.host = "imap.gmail.com" //Mandatory
    server.port = 993
    server.user = "qodly@gmail.com"
    server.password = "XXXXXXXX"

    //create transporter
    transporter = 4D.IMAPTransporter.new(server)

    //select mailbox
    boxInfo = transporter.selectBox("Inbox")

    //get Email object with ID 1
    mail = transporter.getMail(1)

    .getMails()

    .getMails*( ids : collection { , options : object } ) : object
    .getMails( startMsg : integer , endMsg : integer { , options : object } ) : object

    ParameterTypeDescription
    idscollectionCollection of message ID
    startMsgintegerSequence number of the first message
    endMsgintegerSequence number of the last message
    optionsobjectMessage handling instructions
    ResultobjectObject containing:
    • a collection of Email objects and
    • a collection of IDs or numbers for missing messages, if any

    Description

    The .getMails() function returns an object containing a collection of Email objects.

    First Syntax:

    .getMails( ids { , options } ) -> result

    The first syntax allows you to retrieve messages based on their IDs.

    In the ids parameter, pass a collection of IDs for the messages to return. You can get the IDs with .getMail().

    The optional options parameter allows you to define the parts of the messages to be returned. See the Options table below for a description of the available properties.

    Second syntax:

    .getMails( startMsg , endMsg { , options } ) -> result

    The second syntax allows you to retrieve messages based on a sequential range. The values passed represent the position of the messages in the mailbox.

    In the startMsg parameter, pass an integer value corresponding to the number of the first message in a sequential range. If you pass a negative number (startMsg <= 0), the first message of the mailbox will be used as the beginning of the sequence.

    In the endMsg parameter, pass an integer value corresponding to the number of the last message to be included in a sequential range. If you pass a negative number (endMsg <= 0), the last message of the mailbox will be used as the end of the sequence.

    The optional options parameter allows you to define the parts of the messages to be returned.

    Options

    PropertyTypeDescription
    updateSeenbooleanIf true, the specified messages are marked as "seen" in the mailbox. If False, the messages are not marked as "seen". Default value: true
    withBodybooleanPass true to return the body of the specified messages. If false, only the message headers are returned. Default value: true
    • If no mailbox is selected with the .selectBox() command, an error is generated.
    • If there is no open connection, .getMails() will open a connection the last mailbox specified with .selectBox().

    Result

    .getMails() returns an object containing the following collections:

    PropertyTypeDescription
    listcollectioncollection of Email objects. If no Email objects are found, an empty collection is returned.
    notFoundcollectioncollection of:
    • first syntax - previously passed message IDs that do not exist
    • second syntax - sequence numbers of messages between startMsg and endMsg that do not exist
    An empty collection is returned if all messages are found.

    Example

    You want to retrieve the 20 most recent emails without changing their "seen" status:

     var server,boxInfo,result : object
    var transporter : 4D.IMAPTransporter

    server = newObject()
    server.host = "imap.gmail.com" //Mandatory
    server.port = 993
    server.user = "qodly@gmail.com"
    server.password = "XXXXXXXX"

    //create transporter
    transporter = 4D.IMAPTransporter.new(server)

    //select mailbox
    boxInfo = transporter.selectBox("INBOX")

    if(boxInfo.mailCount>0)
    // retrieve the headers of the last 20 messages
    // without marking them as read
    result = transporter.getMails(boxInfo.mailCount-20,boxInfo.mailCount,\
    newObject("withBody",false,"updateSeen",false))
    forEach(mail,result.list)
    // ...
    end
    end

    .getMIMEAsblob()

    .getMIMEAsblob*( msgNumber : integer { , updateSeen : boolean } ) : blob
    .getMIMEAsblob( msgID : string { , updateSeen : boolean } ) : blob

    ParameterTypeDescription
    msgNumberintegerSequence number of the message
    msgIDstringUnique ID of the message
    updateSeenbooleanIf true, the message is marked "seen" in the mailbox. If False the message is left untouched.
    ResultBLOBblob of the MIME string returned from the mail server

    Description

    The .getMIMEAsblob() function returns a BLOB containing the MIME contents for the message corresponding to the msgNumber or msgID in the mailbox designated by the IMAP_transporter.

    In the first parameter, you can pass either:

    • msgNumber, an integer value indicating the sequence number of the message to retrieve or
    • msgID, a string value indicating the unique ID of the message to retrieve.

    The optional updateSeen parameter allows you to specify if the message is marked as "seen" in the mailbox. You can pass:

    • true - to mark the message as "seen" (indicating the message has been read)
    • false - to leave the message's "seen" status untouched
    • The function returns an empty blob if msgNumber or msgID* designates a non-existing message,
    • If no mailbox is selected with the .selectBox() command, an error is generated,
    • If there is no open connection, .getMIMEAsblob() will open a connection the last mailbox specified with .selectBox().

    Result

    .getMIMEAsblob() returns a blob which can be archived in a database or converted to an Email object with the mailConvertFromMIME command.

    Example

     var server : object
    var boxInfo : variant
    var blob : blob
    var transporter : 4D.IMAPTransporter

    server = newObject()
    server.host = "imap.gmail.com"
    server.port = 993
    server.user = "qodly@gmail.com"
    server.password = "XXXXXXXX"

    //create transporter
    transporter = 4D.IMAPTransporter.new(server)

    //select mailbox
    boxInfo = transporter.selectBox("Inbox")

    //get BLOB
    blob = transporter.getMIMEAsblob(1)

    .move()

    .move*( msgsIDs : collection , destinationBox : string ) : object
    .move( allMsgs : integer , destinationBox : string ) : object

    ParameterTypeDescription
    msgsIDscollectioncollection of message unique IDs (strings)
    allMsgsintegerkIMAPAll: All messages in the selected mailbox
    destinationBoxstringMailbox to receive moved messages
    ResultobjectStatus of the move operation

    Description

    The .move() function moves the messages defined by msgsIDs or allMsgs to the destinationBox on the IMAP server.

    You can pass:

    • in the msgsIDs parameter, a collection containing the unique IDs of the specific messages to move, or
    • in the allMsgs parameter, the kIMAPAll constant (integer) to move all messages in the selected mailbox.

    The destinationBox parameter allows you to pass a string value with the name of the mailbox where the messages will be moved.

    This function is only supported by IMAP servers compliant with RFC 8474.

    Returned object

    The function returns an object describing the IMAP status:

    PropertyTypeDescription
    successbooleantrue if the operation is successful, False otherwise
    statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
    errorscollection4D error stack (not returned if a IMAP server response is received)
    [].errcodenumberQodly error code
    [].messagestringDescription of the Qodly error
    [].componentSignaturestringSignature of the internal component which returned the error

    Example 1

    To move a selection of messages:

     var server,boxInfo,status : object
    var mailIds : collection
    var transporter : 4D.IMAPTransporter

    server = newObject()
    server.host = "imap.gmail.com" //Mandatory
    server.port = 993
    server.user = "qodly@gmail.com"
    server.password = "XXXXXXXX"

    transporter = 4D.IMAPTransporter.new(server)

    //select mailbox
    boxInfo = transporter.selectBox("inbox")

    //get collection of message unique IDs
    mailIds = transporter.searchMails("subject \"New feature:\"")

    // Move found messages from the current mailbox to the "documents" mailbox
    status = transporter.move(mailIds,"documents")

    Example 2

    To move all messages in the current mailbox:

     var server,boxInfo,status : object
    var transporter : 4D.IMAPTransporter

    server = newObject()
    server.host = "imap.gmail.com" //Mandatory
    server.port = 993
    server.user = "4d@gmail.com"
    server.password = "XXXXXXXX"

    transporter = 4D.IMAPTransporter.new(server)

    //select mailbox
    boxInfo = transporter.selectBox("inbox")

    // move all messages in the current mailbox to the "documents" mailbox
    status = transporter.move(kIMAPAll,"documents")

    .numToID()

    .numToID*( startMsg : integer , endMsg : integer ) : collection

    ParameterTypeDescription
    startMsgintegerSequence number of the first message
    endMsgintegerSequence number of the last message
    Resultcollectioncollection of unique IDs

    Description

    The .numToID() function converts the sequence numbers to IMAP unique IDs for the messages in the sequential range designated by startMsg and endMsg in the currently selected mailbox.

    In the startMsg parameter, pass an integer value corresponding to the number of the first message in a sequential range. If you pass a negative number (startMsg <= 0), the first message of the mailbox will be used as the beginning of the sequence.

    In the endMsg parameter, pass an integer value corresponding to the number of the last message to be included in a sequential range. If you pass a negative number (endMsg <= 0), the last message of the mailbox will be used as the end of the sequence.

    Result

    The function returns a collection of strings (unique IDs).

    Example

     var transporter : 4D.IMAPTransporter
    var server,boxInfo,status : object
    var mailIds : collection

    server = newObject()
    server.host = "imap.gmail.com" //Mandatory
    server.port = 993
    server.user = "qodly@gmail.com"
    server.password = "XXXXXXXX"

    transporter = 4D.IMAPTransporter.new(server)

    //select mailbox
    boxInfo = transporter.selectBox("inbox")

    //get IDs for 5 last messages received
    mailIds = transporter.numToID((boxInfo.mailCount-5),boxInfo.mailCount)

    //delete the messages from the current mailbox
    status = transporter.delete(mailIds)

    .removeFlags()

    .removeFlags*( msgIDs : collection , keywords : object ) : object
    .removeFlags( msgIDs : string , keywords : object ) : object
    .removeFlags( msgIDs : integer , keywords : object ) : object

    ParameterTypeDescription
    msgIDscollectionCollection of strings: Message unique IDs (string)
    msgIDsstringUnique ID of a message
    msgIDsintegerkIMAPAll: All messages in the selected mailbox
    keywordsobjectKeyword flags to remove
    ResultobjectStatus of the removeFlags operation

    Description

    The .removeFlags() function removes flags from the msgIDs for the specified keywords.

    In the msgIDs parameter, you can pass either:

    • a collection containing the unique IDs of specific messages or
    • the unique ID (string) of a single message or
    • the following constant (integer) for all messages in the selected mailbox:
    ConstantValueComment
    kIMAPAll1Select all messages in the selected mailbox

    The keywords parameter lets you define the flags to remove from msgIDs. You can use the following standard flags as well as custom flags:

    ParameterTypeDescription
    $draftbooleantrue to remove the "draft" flag from the message
    $seenbooleantrue to remove the "seen" flag from the message
    $flaggedbooleantrue to remove the "flagged" flag from the message
    $answeredbooleantrue to remove the "answered" flag from the message
    $deletedbooleantrue to remove the "deleted" flag from the message
    <custom flag>booleantrue to remove the custom flag from the message

    Please refer to .addFlags() for more information on custom flags.

    • For a keyword to be taken into account it has to be true.

    Returned object

    The function returns an object describing the IMAP status:

    PropertyTypeDescription
    successbooleantrue if the operation is successful, False otherwise
    statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
    errorscollectionQodly error stack (not returned if a IMAP server response is received)
    [].errcodeNumberQodly error code
    [].messagestringDescription of the Qodly error
    [].componentSignaturestringSignature of the internal component which returned the error

    Example

    var options,boxInfo,status : object
    var transporter : 4D.IMAPTransporter

    options = newObject()
    options.host = "imap.gmail.com"
    options.port = 993
    options.user = "qodly@gmail.com"
    options.password = "xxxxx"

    // Create transporter
    transporter = 4D.IMAPTransporter.new(options)

    // Select mailbox
    boxInfo = transporter.selectBox("INBOX")

    // Mark all messages from INBOX as unseen
    flags = newObject
    flags["$seen"] = true
    status = transporter.removeFlags(kIMAPAll,flags)

    .renameBox()

    .renameBox*( currentName : string , newName : string ) : object

    ParameterTypeDescription
    currentNamestringName of the current mailbox
    newNamestringNew mailbox name
    ResultobjectStatus of the renaming operation

    Description

    The .renameBox() function changes the name of a mailbox on the IMAP server. Attempting to rename a mailbox from a mailbox name that does not exist or to a mailbox name that already exists will generate an error.

    In the currentName parameter, pass the name of the mailbox to be renamed.

    Pass the new name for the mailbox in the newName parameter.

    Returned object

    The function returns an object describing the IMAP status:

    PropertyTypeDescription
    successbooleantrue if the operation is successful, False otherwise
    statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
    errorscollectionQodly error stack (not returned if a IMAP server response is received)
    [].errcodeNumberQodly error code
    [].messagestringDescription of the Qodly error
    [].componentSignaturestringSignature of the internal component which returned the error

    Example

    To to rename your "Invoices mailbox to "Bills":

    var options, status : object
    var transporter : 4D.IMAPTransporter
    var info : string

    options = newObject()

    options.host = "imap.gmail.com"
    options.user = "test@gmail.com"
    options.password = "XXXXX"

    transporter = 4D.IMAPTransporter.new(options)

    // rename mailbox
    status = transporter.renameBox("Invoices", "Bills")

    if(status.success)
    info = "Mailbox renaming successful!"
    else
    info = "Error: "+status.statusText
    end

    .searchMails()

    .searchMails*( searchCriteria : string ) : collection

    ParameterTypeDescription
    searchCriteriastringSearch criteria
    Resultcollectioncollection of message numbers

    Description

    This function is based upon the specification for the IMAP protocol.

    The .searchMails() function searches for messages that match the given searchCriteria in the current mailbox. searchCriteria consists of one or more search keys.

    searchCriteria is a string parameter listing one or more search keys (see Authorized search-keys below) associated or not with values to look for. A search key may be a single or multiple items. For example:

    SearchKey1 = FLAGGED
    SearchKey2 = NOT FLAGGED
    SearchKey3 = FLAGGED DRAFT

    Matching is usually not case-sensitive

    • If the searchCriteria is a null string, the search will be equivalent to a “select all”.
    • If the searchCriteria includes multiple search keys, the result is the intersection (AND function) of all the messages that match those keys.
    searchCriteria = FLAGGED FROM "SMITH"

    ... returns all messages with \Flagged flag set AND sent by Smith.

    • You can use the OR or NOT operators as follows:
    searchCriteria = OR SEEN FLAGGED

    ... returns all messages with \Seen flag set OR \Flagged flag set

    searchCriteria = NOT SEEN

    ... returns all messages with \Seen flag not set.

    searchCriteria = HEADER CONTENT-TYPE "MIXED" NOT HEADER CONTENT-TYPE "TEXT"...

    ... returns message whose content-type header contains “Mixed” and does not contain “string”.

    searchCriteria = HEADER CONTENT-TYPE "E" NOT SUBJECT "o" NOT HEADER CONTENT-TYPE "MIXED"

    ... returns message whose content-type header contains “ e ” and whose Subject header does not contain “ o ” and whose content-type header is not “ Mixed ”.

    As concerns the last two examples, notice that the result of the search is different when you remove the parentheses of the first search key list.

    • The searchCriteria may include the optional [CHARSET] specification. This consists of the "CHARSET" word followed by a registered [CHARSET] (US ASCII, ISO-8859). It indicates the charset of the searchCriteria string. Therefore, you must convert the searchCriteria string into the specified charset if you use the [CHARSET] specification (see the CONVERT FROM TEXT or Convert to string commands). By default, 4D encodes in Quotable Printable the searchCriteria string if it contains extended characters.
    searchCriteria = CHARSET "ISO-8859" BODY "Help"

    ... means the search criteria uses the charset iso-8859 and the server will have to convert the search criteria before searching, if necessary.

    Search value types

    Search-keys may request the value to search for:

    • Search-keys with a date value: the date is a string that must be formatted as follows: date-day+"-"+date-month+"-"+date-year where date-day indicates the number of the day of the month (max. 2 characters), date-month indicates the name of the month (Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Dec) and date-year indicates the year (4 characters). Example: searchCriteria = SENTBEFORE 1-Feb-2020 (a date does not usually need to be quoted since it does not contain any special characters)

    • Search-keys with a string value: the string may contain any character and must be quoted. If the string does not contain any special characters, like the space character for instance, it does not need to be quoted. Quoting such strings will ensure that your string value will be correctly interpreted. Example: searchCriteria = FROM "SMITH" For all search keys that use strings, a message matches the key if the string is a substring of the field. Matching is not case-sensitive.

    • Search-keys with a field-name value: the field-name is the name of a header field. Example: searchCriteria = HEADER CONTENT-TYPE "MIXED"

    • Search-keys with a flag value: the flag may accept one or several keywords (including standard flags), separated by spaces. Example: searchCriteria = KEYWORD \Flagged \Draft

    • Search-keys with a message set value: Identifies a set of messages. For message sequence numbers, these are consecutive numbers from 1 to the total number of messages in the mailbox. A comma delimits individual numbers, a colon delimits between two numbers inclusive. Examples: 2,4:7,9,12:* is 2,4,5,6,7,9,12,13,14,15 for a mailbox with 15 messages. searchCriteria = 1:5 ANSWERED search in message selection from message sequence number 1 to 5 for messages which have the \Answered flag set. searchCriteria = 2,4 ANSWERED search in the message selection (message numbers 2 and 4) for messages which have the \Answered flag set.

    Authorized search-keys

    ALL: All messages in the mailbox.
    ANSWERED: Messages with the \Answered flag set.
    UNANSWERED: Messages that do not have the \Answered flag set.
    DELETED: Messages with the \Deleted flag set.
    UNDELETED: Messages that do not have the \Deleted flag set.
    DRAFT: Messages with the \Draft flag set.
    UNDRAFT: Messages that do not have the \Draft flag set.
    FLAGGED: Messages with the \Flagged flag set.
    UNFLAGGED: Messages that do not have the \Flagged flag set.
    RECENT: Messages that have the \Recent flag set.
    OLD: Messages that do not have the \Recent flag set.
    SEEN: Messages that have the \Seen flag set.
    UNSEEN: Messages that do not have the \Seen flag set.
    NEW: Messages that have the \Recent flag set but not the \Seen flag. This is functionally equivalent to “(RECENT UNSEEN)”.
    KEYWORD flag: Messages with the specified keyword set.
    UNKEYWORD flag: Messages that do not have the specified keyword set.
    BEFORE date: Messages whose internal date is earlier than the specified date.
    ON date: Messages whose internal date is within the specified date.
    SINCE date: Messages whose internal date is within or later than the specified date.
    SENTBEFORE date: Messages whose Date header is earlier than the specified date.
    SENTON date: Messages whose Date header is within the specified date.
    SENTSINCE date: Messages whose Date header is within or later than the specified date.
    TO string: Messages that contain the specified string in the TO header.
    FROM string: Messages that contain the specified string in the FROM header.
    CC string: Messages that contain the specified string in the CC header.
    BCC string: Messages that contain the specified string in the BCC header.
    SUBJECT string: Messages that contain the specified string in the Subject header.
    BODY string: Messages that contain the specified string in the message body.
    TEXT string: Messages that contain the specified string in the header or in the message body.
    HEADER field-name string: Messages that have a header with the specified field-name and that contain the specified string in the field-body.
    UID message-UID: Messages with unique identifiers corresponding to the specified unique identifier set.
    LARGER n: Messages with a size larger than the specified number of bytes.
    SMALLER n: Messages with a size smaller than the specified number of bytes.
    NOT search-key: Messages that do not match the specified search key.
    OR search-key1 search-key2: Messages that match either search key.

    .selectBox()

    .selectBox*( name : string { , state : integer } ) : object

    ParameterTypeDescription
    namestringName of the mailbox
    stateintegerMailbox access status
    ResultobjectboxInfo object

    Description

    The .selectBox() function selects the name mailbox as the current mailbox. This function allows you to retrieve information about the mailbox.

    To get the information from a mailbox without changing the current mailbox, use .getBoxInfo().

    In the name parameter, pass the name of the mailbox to access. The name represents an unambiguous left-to-right hierarchy with levels separated by a specific delimiter character. The delimiter can be found with the .getDelimiter() function.

    The optional state parameter defines the type of access to the mailbox. The possible values are:

    ConstantValueComment
    IMAP read only state1The selected mailbox is accessed with read only privileges. Messages with a "recent" flag (indicating new messages) remain unchanged.
    IMAP read write state0The selected mailbox is accessed with read and write privileges. Messages are considered "seen" and lose the "recent" flag (indicating new messages). (Default value)
    • The function generates an error and returns Null if name designates a non-existing mailbox.
    • If there is no open connection, .selectBox() will open a connection.
    • If the connection has not been used since the designated connection delay (see 4D.IMAPTransporter.new), the .checkConnection() function is automatically called.

    Returned object

    The boxInfo object returned contains the following properties:

    PropertyTypeDescription
    namestringName of the mailbox
    mailCountnumberNumber of messages in the mailbox
    mailRecentnumberNumber of messages with the "recent" flag
    idstringUnique id of the mailbox
    flagsstringList of flags currently used for the mailbox, separated by spaces
    permanentFlagsstringList of flags that the client can change permanently (except for the \Recent flag, which is managed by the IMAP server), separated by spaces
    info

    If permanentFlags string includes the special flag *, it means that the server supports custom flags.

    Example

     var server, boxinfo : object
    var transporter : 4D.IMAPTransporter
    server = newObject()
    server.host = "imap.gmail.com" //Mandatory
    server.user = "4d@gmail.com"
    server.password = "XXXXXXXX"

    transporter = 4D.IMAPTransporter.new(server)
    boxInfo = transporter.selectBox("INBOX")

    .subscribe()

    .subscribe*( name : string ) : object

    ParameterTypeDescription
    namestringName of the mailbox
    ResultobjectStatus of the subscribe operation

    Description

    The .subscribe() function allows adding or removing of the specified mailbox to/from the IMAP server’s set of “subscribed” mailboxes. As such, you can choose to narrow down a large list of available mailboxes by subscribing to those you usually want to see.

    In the name parameter, pass the name of the mailbox to add (subscribe) to your "subscribed" mailboxes.

    Returned object

    The function returns an object describing the IMAP status:

    PropertyTypeDescription
    successbooleantrue if the operation is successful, False otherwise
    statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
    errorscollectionQodly error stack (not returned if a IMAP server response is received)
    [].errcodeNumberQodly error code
    [].messagestringDescription of the Qodly error
    [].componentSignaturestringSignature of the internal component which returned the error

    Example

    To subscribe to the "Atlas Corp" mailbox in the "Bills" hierarchy:

    var name, info : string
    var options, status : object
    var transporter : 4D.IMAPTransporter

    options = newObject()

    options.host = "imap.gmail.com"
    options.user = "test@gmail.com"
    options.password = "XXXXXX"

    transporter = 4D.IMAPTransporter.new(options)

    name = "Bills"+transporter.getDelimiter()+"Atlas Corp"
    status = transporter.subscribe(name)

    if(status.success)
    info = "Mailbox subscription successful!"
    else
    info = "Error: "+status.statusText
    end

    .unsubscribe()

    .unsubscribe*( name : string ) : object

    ParameterTypeDescription
    namestringName of the mailbox
    ResultobjectStatus of the unsubscribe operation

    Description

    The .unsubscribe() function removes a mailbox from a set of subscribed mailboxes. This allows you reduce the number of mailboxes you usually see.

    In the name parameter, pass the name of the mailbox to remove (unsubscribe) from your active mailboxes.

    Returned object

    The function returns an object describing the IMAP status:

    PropertyTypeDescription
    successbooleantrue if the operation is successful, False otherwise
    statusTextstringStatus message returned by the IMAP server, or last error returned in the Qodly error stack
    errorscollectionQodly error stack (not returned if a IMAP server response is received)
    [].errcodeNumberQodly error code
    [].messagestringDescription of the Qodly error
    [].componentSignaturestringSignature of the internal component which returned the error

    Example

    To unsubscribe from the "Atlas Corp” mailbox in the "Bills" hierarchy:

    var info, name : string
    var options, status : object
    var transporter : 4D.IMAPTransporter

    options = newObject()


    options.host = "imap.gmail.com"
    options.user = "test@gmail.com"
    options.password = pw

    transporter = 4D.IMAPTransporter.new(options)

    name = "Bills"+transporter.getDelimiter()+"Atlas Corp"
    status = transporter.unsubscribe(name)

    if(status.success)
    info = "Mailbox unsubscription successful!"
    else
    info = "Error: "+status.statusText
    end