Mailbox
objectA logged-in IMAP or POP3 mailbox with one open folder. List, search and poll messages, and save their attachments to the project. The mailbox is read-only: nothing is deleted, moved or marked as read, so the same messages are found again by the next search. Messages are downloaded when you list or search them, so use search criteria and limit on large folders. The connection is re-established automatically if it was dropped, also after close().
- Kind Object
- Library Mail
- Category Messaging & Integrations
- Functions 8
How to get one
local mailbox = Mail.imap(list)Returned by
Functions
-
folderself Opens another folder of the mailbox (for example "Archive" or "INBOX/Invoices"; the separator depends on the server). -
refreshself Closes and reopens the current folder so that messages that arrived since it was opened become visible. -
messagesMailMessage[] Returns every message in the current folder, newest first. -
getMailMessage Returns the message with the given sequence number (the number field of a message, 1 is the oldest). -
searchMailMessage[] Returns the messages of the current folder that match all given criteria, newest first (see MailSearch for the keys). -
pollMailMessage[] Waits for mail: reopens the folder and searches it every interval until at least one message matches, then returns the matches (newest first). -
downloadAttachmentstable Saves all attachments of one message into a directory of the project and returns the saved file paths (relative to the project, as a list). -
closeself Closes the open folder and the connection to the server.
folder()
Section titled “folder()”mailbox.folder(name: string)→self Opens another folder of the mailbox (for example "Archive" or "INBOX/Invoices"; the separator depends on the server). Raises an error when the folder does not exist, or for any folder other than INBOX on POP3. Later calls read from this folder, and message numbers refer to it.
Parameters
-
namestring - Folder name as the server knows it, case-sensitive on most servers
Returns
refresh()
Section titled “refresh()”mailbox.refresh()→self Closes and reopens the current folder so that messages that arrived since it was opened become visible. poll does this by itself on every round; use refresh before messages, search or get when you wait for mail some other way.
Returns
messages()
Section titled “messages()”mailbox.messages()→MailMessage[] Returns every message in the current folder, newest first. All messages are downloaded and parsed, which is slow for a large folder; use search with a limit instead.
Returns
Fields of MailMessage
-
numbernumber - sequence number in the folder (1 is the oldest message); use it with Mailbox.get and Mailbox.downloadAttachments. It can change when messages are added or removed, so do not store it
-
folderstring - name of the folder the message was read from
-
subjectstring - subject line, decoded
-
message_idstring - value of the Message-ID header
-
fromany[] - sender addresses, each as the server gives it: a display name followed by the address in angle brackets, or just the address (alice@example.com)
-
toany[] - recipients in the To header, formatted like from
-
ccany[] - recipients in the Cc header
-
bccany[] - recipients in the Bcc header; normally empty because senders' Bcc headers are not kept
-
reply_toany[] - addresses replies should go to
-
sent_atnumber - Date header as a Unix timestamp in milliseconds, 0 when missing
-
sent_at_isostring - Date header as an ISO 8601 UTC time such as 2025-03-01T08:30:00Z, empty when missing
-
received_atnumber - time the server received the message, in Unix milliseconds, 0 when unknown
-
received_at_isostring - time the server received the message as ISO 8601 UTC, empty when unknown
-
sizenumber - message size in bytes as reported by the server, 0 when unknown
-
content_typestring - MIME type of the whole message, for example multipart/mixed; boundary=...
-
bodystring - the plain text of the message; when it has no plain text part, the HTML source of the HTML part (not converted to text)
-
textstring - all text/plain parts joined, empty when there is none
-
htmlstring - all text/html parts joined, empty when there is none
-
attachmentsMailAttachment[] - metadata of the attachments (use Mailbox.downloadAttachments to save the files)
-
has_attachmentsboolean - true when attachments is not empty
-
seenboolean - the message has been read (always false on POP3, which has no flags)
-
answeredboolean - the message has been answered
-
deletedboolean - the message is marked as deleted
-
draftboolean - the message is a draft
-
flaggedboolean - the message is flagged
-
recentboolean - the message arrived since the last session (IMAP only)
mailbox.get(number: number)→MailMessage Returns the message with the given sequence number (the number field of a message, 1 is the oldest). The number can change when messages are added or removed, so use a number from a recent messages, search or poll result. Raises "No message found with number N" when it is out of range.
Parameters
-
numbernumber - Sequence number from the number field of a message
Returns
Fields of MailMessage
-
numbernumber - sequence number in the folder (1 is the oldest message); use it with Mailbox.get and Mailbox.downloadAttachments. It can change when messages are added or removed, so do not store it
-
folderstring - name of the folder the message was read from
-
subjectstring - subject line, decoded
-
message_idstring - value of the Message-ID header
-
fromany[] - sender addresses, each as the server gives it: a display name followed by the address in angle brackets, or just the address (alice@example.com)
-
toany[] - recipients in the To header, formatted like from
-
ccany[] - recipients in the Cc header
-
bccany[] - recipients in the Bcc header; normally empty because senders' Bcc headers are not kept
-
reply_toany[] - addresses replies should go to
-
sent_atnumber - Date header as a Unix timestamp in milliseconds, 0 when missing
-
sent_at_isostring - Date header as an ISO 8601 UTC time such as 2025-03-01T08:30:00Z, empty when missing
-
received_atnumber - time the server received the message, in Unix milliseconds, 0 when unknown
-
received_at_isostring - time the server received the message as ISO 8601 UTC, empty when unknown
-
sizenumber - message size in bytes as reported by the server, 0 when unknown
-
content_typestring - MIME type of the whole message, for example multipart/mixed; boundary=...
-
bodystring - the plain text of the message; when it has no plain text part, the HTML source of the HTML part (not converted to text)
-
textstring - all text/plain parts joined, empty when there is none
-
htmlstring - all text/html parts joined, empty when there is none
-
attachmentsMailAttachment[] - metadata of the attachments (use Mailbox.downloadAttachments to save the files)
-
has_attachmentsboolean - true when attachments is not empty
-
seenboolean - the message has been read (always false on POP3, which has no flags)
-
answeredboolean - the message has been answered
-
deletedboolean - the message is marked as deleted
-
draftboolean - the message is a draft
-
flaggedboolean - the message is flagged
-
recentboolean - the message arrived since the last session (IMAP only)
search()
Section titled “search()”mailbox.search(criteria: MailSearch)→MailMessage[] Returns the messages of the current folder that match all given criteria, newest first (see MailSearch for the keys). A plain string instead of a table searches the subject, sender, recipients, body and Message-ID for that text. Matching is done in the agent, case-insensitively, on text that contains the search term. Returns an empty list when nothing matches; it does not wait for new mail (use poll for that) and does not see mail that arrived after the folder was opened until you call refresh. Raises an error for a date in since or before that cannot be parsed.
Parameters
-
criteriaMailSearch - Search criteria table, or a string to search in subject, sender, recipients, body and Message-ID
Returns
Fields of MailMessage
-
numbernumber - sequence number in the folder (1 is the oldest message); use it with Mailbox.get and Mailbox.downloadAttachments. It can change when messages are added or removed, so do not store it
-
folderstring - name of the folder the message was read from
-
subjectstring - subject line, decoded
-
message_idstring - value of the Message-ID header
-
fromany[] - sender addresses, each as the server gives it: a display name followed by the address in angle brackets, or just the address (alice@example.com)
-
toany[] - recipients in the To header, formatted like from
-
ccany[] - recipients in the Cc header
-
bccany[] - recipients in the Bcc header; normally empty because senders' Bcc headers are not kept
-
reply_toany[] - addresses replies should go to
-
sent_atnumber - Date header as a Unix timestamp in milliseconds, 0 when missing
-
sent_at_isostring - Date header as an ISO 8601 UTC time such as 2025-03-01T08:30:00Z, empty when missing
-
received_atnumber - time the server received the message, in Unix milliseconds, 0 when unknown
-
received_at_isostring - time the server received the message as ISO 8601 UTC, empty when unknown
-
sizenumber - message size in bytes as reported by the server, 0 when unknown
-
content_typestring - MIME type of the whole message, for example multipart/mixed; boundary=...
-
bodystring - the plain text of the message; when it has no plain text part, the HTML source of the HTML part (not converted to text)
-
textstring - all text/plain parts joined, empty when there is none
-
htmlstring - all text/html parts joined, empty when there is none
-
attachmentsMailAttachment[] - metadata of the attachments (use Mailbox.downloadAttachments to save the files)
-
has_attachmentsboolean - true when attachments is not empty
-
seenboolean - the message has been read (always false on POP3, which has no flags)
-
answeredboolean - the message has been answered
-
deletedboolean - the message is marked as deleted
-
draftboolean - the message is a draft
-
flaggedboolean - the message is flagged
-
recentboolean - the message arrived since the last session (IMAP only)
Example
local invoices = mailbox.search({ subject = "invoice", hasAttachments = true, since = "2025-01-01", limit = 5 })for _, message in ipairs(invoices) do print(message.number, message.subject, message.sent_at_iso)endlocal byText = mailbox.search("password reset")poll()
Section titled “poll()”mailbox.poll()→MailMessage[]mailbox.poll(criteria: MailSearch)→MailMessage[]mailbox.poll(criteria: MailSearch, timeoutSeconds: number)→MailMessage[]mailbox.poll(criteria: MailSearch, timeoutSeconds: number, intervalMs: number)→MailMessage[] Waits for mail: reopens the folder and searches it every interval until at least one message matches, then returns the matches (newest first). When the timeout passes without a match it returns an empty list and does not raise an error, so check the result. A timeout of 0 checks once. Defaults: 30 seconds timeout, 1000 ms interval. Messages that are already in the folder count too, so a poll for a subject that older mail also has returns immediately. Make the criteria specific (a unique subject or code, or since = <time you sent the request>). With a single number as argument, poll(60) waits up to 60 seconds for any message.
Parameters
-
criteriaMailSearch optional - Criteria with the same keys as search (a table or string); a number here is read as the timeout in seconds
-
timeoutSecondsnumber optional - Seconds to keep trying; 0 checks once; default 30
-
intervalMsnumber optional - Milliseconds between checks, at least 1; default 1000
Returns
Fields of MailMessage
-
numbernumber - sequence number in the folder (1 is the oldest message); use it with Mailbox.get and Mailbox.downloadAttachments. It can change when messages are added or removed, so do not store it
-
folderstring - name of the folder the message was read from
-
subjectstring - subject line, decoded
-
message_idstring - value of the Message-ID header
-
fromany[] - sender addresses, each as the server gives it: a display name followed by the address in angle brackets, or just the address (alice@example.com)
-
toany[] - recipients in the To header, formatted like from
-
ccany[] - recipients in the Cc header
-
bccany[] - recipients in the Bcc header; normally empty because senders' Bcc headers are not kept
-
reply_toany[] - addresses replies should go to
-
sent_atnumber - Date header as a Unix timestamp in milliseconds, 0 when missing
-
sent_at_isostring - Date header as an ISO 8601 UTC time such as 2025-03-01T08:30:00Z, empty when missing
-
received_atnumber - time the server received the message, in Unix milliseconds, 0 when unknown
-
received_at_isostring - time the server received the message as ISO 8601 UTC, empty when unknown
-
sizenumber - message size in bytes as reported by the server, 0 when unknown
-
content_typestring - MIME type of the whole message, for example multipart/mixed; boundary=...
-
bodystring - the plain text of the message; when it has no plain text part, the HTML source of the HTML part (not converted to text)
-
textstring - all text/plain parts joined, empty when there is none
-
htmlstring - all text/html parts joined, empty when there is none
-
attachmentsMailAttachment[] - metadata of the attachments (use Mailbox.downloadAttachments to save the files)
-
has_attachmentsboolean - true when attachments is not empty
-
seenboolean - the message has been read (always false on POP3, which has no flags)
-
answeredboolean - the message has been answered
-
deletedboolean - the message is marked as deleted
-
draftboolean - the message is a draft
-
flaggedboolean - the message is flagged
-
recentboolean - the message arrived since the last session (IMAP only)
Example
-- trigger the application to send a mail, then wait up to two minutes for itlocal messages = mailbox.poll({ subject = "Your verification code", to = "test.user@example.com" }, 120, 2000)Assert.equals(1, #messages)local code = messages[1].body:match("(%d%d%d%d%d%d)")downloadAttachments()
Section titled “downloadAttachments()”mailbox.downloadAttachments(messageNumber: number, targetDir: string)→table Saves all attachments of one message into a directory of the project and returns the saved file paths (relative to the project, as a list). The directory is created when needed. File names come from the message with characters that are not allowed in file names (\ / : * ? " < > |) replaced by _; when a file with that name exists, -1, -2, ... is added before the extension, so nothing is overwritten. Inline images of the HTML body are not saved. Returns an empty list when the message has no attachments; raises an error when the number is unknown or writing fails.
Parameters
-
messageNumbernumber - Sequence number from the number field of a message
-
targetDirstring - Directory in the project to save the files in
Returns
Example
local messages = mailbox.search({ subject = "Monthly report", hasAttachments = true, limit = 1 })local files = mailbox.downloadAttachments(messages[1].number, "downloads/mail")for _, path in ipairs(files) do print(path)endclose()
Section titled “close()”mailbox.close()→self Closes the open folder and the connection to the server. Errors while closing are ignored. Calling another function afterwards connects again.
Returns