Files every document that arrives by email into Box and records what it says as a row on your register.
UsesBox
Gmail
Google Sheets
OpenAI
File emailed documents and log what they say
documentSearch to blank.Set documentSearch to blank.boxFolder to blank.Set boxFolder to blank.registerSheetUrl to blank.Set registerSheetUrl to blank.sheetTabName to Documents.Set sheetTabName to Documents.documentFields to Supplier, Document number, Document date, Total amount, Currency.Set documentFields to Supplier, Document number, Document date, Total amount, Currency.processedLabel to Document register.Set processedLabel to Document register.needsFilingLabel to Needs filing.Set needsFilingLabel to Needs filing.maxDocumentsPerRun to 5.Set maxDocumentsPerRun to 5.documentCap to maxDocumentsPerRun multiplied by 1.Set documentCap to maxDocumentsPerRun multiplied by 1.documentCap is greater than 25If documentCap is greater than 25Yes
No
No steps
documentCap is less than 1If documentCap is less than 1Yes
No
No steps
boxFolder and save it as boxFolderId.Trim boxFolder and save it as boxFolderId.boxFolderId contains /folder/ (ignoring case)If boxFolderId contains /folder/ (ignoring case)Yes
boxFolderId split by /folder/ split by / and save it as boxFolderId.Trim the first item of the last item of boxFolderId split by /folder/ split by / and save it as boxFolderId.No
No steps
boxFolderId is empty or boxFolderId multiplied by 1 is not boxFolderIdIf boxFolderId is empty or boxFolderId multiplied by 1 is not boxFolderIdYes
No
No steps
fieldNames to an empty list.Set fieldNames to an empty list.rawFieldName in documentFields split by ,:For each rawFieldName in documentFields split by ,:rawFieldName and save it as fieldName.Trim rawFieldName and save it as fieldName.fieldName isn't emptyIf fieldName isn't emptyYes
fieldName to the end of fieldNames and save it as fieldNames.Add fieldName to the end of fieldNames and save it as fieldNames.No
No steps
fieldNames is emptyIf fieldNames is emptyYes
No
No steps
@processedLabel -label:@needsFilingLabel'. Save it as found.List emails matching '@documentSearch has:attachment -label:@processedLabel -label:@needsFilingLabel'. Save it as found.runStarted.Get the current date and time and save it as runStarted.runStarted readable as “2026-11-02 14:05” and save it as filedAt.Make runStarted readable as “2026-11-02 14:05” and save it as filedAt.filedCount to 0.Set filedCount to 0.messagesLeft to 0.Set messagesLeft to 0.setAside to an empty list.Set setAside to an empty list.unreadDocuments to an empty list.Set unreadDocuments to an empty list.readProblem to blank.Set readProblem to blank.message in found.emails:For each message in found.emails:filedCount is greater than or equal to documentCapIf filedCount is greater than or equal to documentCapYes
messagesLeft.Add 1 to messagesLeft.No
No steps
messageDescription to an email.Set messageDescription to an email.messageErrorIf a step below fails, save the error as messageErrorTry
messageId to blank.Set messageId to blank.idErrorIf a step below fails, save the error as idErrorTry
message.id and save it as messageId.Trim message.id and save it as messageId.On error
No steps
messageId is emptyIf messageId is emptyYes
Skipped a message Gmail returned without an id..Show in the output: Skipped a message Gmail returned without an id..No
No steps
rawFrom to blank.Set rawFrom to blank.fromErrorIf a step below fails, save the error as fromErrorTry
message.from and save it as rawFrom.Trim message.from and save it as rawFrom.On error
No steps
senderAddress to rawFrom.Set senderAddress to rawFrom.rawFrom contains < (ignoring case)If rawFrom contains < (ignoring case)Yes
rawFrom split by < split by > and save it as senderAddress.Trim the first item of the last item of rawFrom split by < split by > and save it as senderAddress.No
No steps
subject to (no subject).Set subject to (no subject).subjectErrorIf a step below fails, save the error as subjectErrorTry
message.subject and save it as subjectText.Trim message.subject and save it as subjectText.subjectText isn't emptyIf subjectText isn't emptyYes
subject to subjectText.Change subject to subjectText.No
No steps
On error
No steps
'@subject' from @senderAddress and save it as messageDescription.Build the text '@subject' from @senderAddress and save it as messageDescription.messageProblems to an empty list.Set messageProblems to an empty list.senderAddress doesn't contain @ (ignoring case)If senderAddress doesn't contain @ (ignoring case)Yes
rawFrom) to the end of messageProblems and save it as messageProblems.Add its sender could not be read (rawFrom) to the end of messageProblems and save it as messageProblems.No
latestId to blank.Set latestId to blank.senderAddress'. Save it as latestFromSender.Find email matching 'from:senderAddress'. Save it as latestFromSender.latestErrorIf a step below fails, save the error as latestErrorTry
latestFromSender.email.id and save it as latestId.Trim latestFromSender.email.id and save it as latestId.On error
No steps
latestId is not messageIdIf latestId is not messageIdYes
only a sender's newest email can be opened, and a newer one from this sender is in the inbox; archive that one first to the end of messageProblems and save it as messageProblems.Add only a sender's newest email can be opened, and a newer one from this sender is in the inbox; archive that one first to the end of messageProblems and save it as messageProblems.No
senderAddress. Save it as downloaded.Download the attachments on the latest email from senderAddress. Save it as downloaded.messageDocuments to 0.Set messageDocuments to 0.attachmentNumber to 0.Set attachmentNumber to 0.namesOnMessage to an empty list.Set namesOnMessage to an empty list.attachment in downloaded.documents:For each attachment in downloaded.documents:fileName to blank. Set fileName to blank.nameError If a step below fails, save the error as nameErrorTry
attachment.filename and save it as fileName.Trim attachment.filename and save it as fileName.On error
No steps
attachmentLabel to (unnamed attachment). Set attachmentLabel to (unnamed attachment).fileName isn't empty If fileName isn't emptyYes
attachmentLabel to fileName.Change attachmentLabel to fileName.No
No steps
fileName in lowercase doesn't end with .pdf (ignoring case) If fileName in lowercase doesn't end with .pdf (ignoring case)Yes
attachmentLabel: only PDF attachments are treated as documents.Show in the output: Skipped attachmentLabel: only PDF attachments are treated as documents.No
No steps
documentRef to blank. Set documentRef to blank.refError If a step below fails, save the error as refErrorTry
attachment.document_ref and save it as documentRef.Trim attachment.document_ref and save it as documentRef.On error
No steps
documentRef is empty If documentRef is emptyYes
attachmentLabel; it was left alone.Show in the output: Could not open attachmentLabel; it was left alone.No
No steps
attachmentNumber. Add 1 to attachmentNumber.\.pdf$ with in attachmentLabel (ignoring case) and save it as fileStem. Replace the pattern \.pdf$ with in attachmentLabel (ignoring case) and save it as fileStem.@fileStem (@messageId).pdf and save it as boxName. Build the text @fileStem (@messageId).pdf and save it as boxName.namesOnMessage contains boxName If namesOnMessage contains boxNameYes
@fileStem (@messageId @attachmentNumber).pdf and save it as boxName.Build the text @fileStem (@messageId @attachmentNumber).pdf and save it as boxName.No
No steps
boxName to the end of namesOnMessage and save it as namesOnMessage. Add boxName to the end of namesOnMessage and save it as namesOnMessage.storedLink to blank. Set storedLink to blank.uploadProblem to blank. Set uploadProblem to blank.uploadError If a step below fails, save the error as uploadErrorTry
boxFolderId to Box folder documentRef. Save it as stored.Upload boxFolderId to Box folder documentRef. Save it as stored.stored.file_link and save it as storedLink.Trim stored.file_link and save it as storedLink.On error
uploadError.message by a new line and save it as uploadErrorLines.Split uploadError.message by a new line and save it as uploadErrorLines.uploadErrorLines and save it as uploadProblem.Get the first item of uploadErrorLines and save it as uploadProblem.lookupErrorIf a step below fails, save the error as lookupErrorTry
boxFolderId. Save it as folderItems.List items in Box folder boxFolderId. Save it as folderItems.folderItems.items where item.name is boxName and save it as sameName.Keep each item in folderItems.items where item.name is boxName and save it as sameName.sameName isn't emptyIf sameName isn't emptyYes
https://app.box.com/file/@sameName[0].id and save it as storedLink.Build the text https://app.box.com/file/@sameName[0].id and save it as storedLink.No
No steps
On error
No steps
storedLink is empty If storedLink is emptyYes
filedCount is 0If filedCount is 0Yes
attachmentLabel on messageDescription could not be copied into Box (uploadProblem). Check that Box is connected and that the 'boxFolder' step names a folder you can add files to. The email is left as it was, so the next run tries it again.Stop and report a problem: Nothing was filed this run: attachmentLabel on messageDescription could not be copied into Box (uploadProblem). Check that Box is connected and that the 'boxFolder' step names a folder you can add files to. The email is left as it was, so the next run tries it again.No
No steps
attachmentLabel could not be copied into Box (uploadProblem) to the end of messageProblems and save it as messageProblems.Add attachmentLabel could not be copied into Box (uploadProblem) to the end of messageProblems and save it as messageProblems.No
No steps
readStatus to Read. Set readStatus to Read.returnedNames to an empty list. Set returnedNames to an empty list.returnedValues to an empty list. Set returnedValues to an empty list.extractError If a step below fails, save the error as extractErrorTry
fieldName… and save it as extraction.Run an AI agent: Read the attached document and pull out each of these fields, in this order: - fieldName… and save it as extraction.returnedField in extraction.output.fields:For each returnedField in extraction.output.fields:returnedName to blank. Set returnedName to blank.fieldNameError If a step below fails, save the error as fieldNameErrorTry
returnedField.name and save it as returnedName.Trim returnedField.name and save it as returnedName.On error
No steps
returnedValue to blank. Set returnedValue to blank.fieldValueError If a step below fails, save the error as fieldValueErrorTry
returnedField.value and save it as returnedValue.Trim returnedField.value and save it as returnedValue.On error
fieldListErrorIf a step below fails, save the error as fieldListErrorTry
returnedField.value with , and save it as returnedValue.Join returnedField.value with , and save it as returnedValue.On error
No steps
returnedName to the end of returnedNames and save it as returnedNames. Add returnedName to the end of returnedNames and save it as returnedNames.returnedValue to the end of returnedValues and save it as returnedValues. Add returnedValue to the end of returnedValues and save it as returnedValues.On error
readStatus to Filed but could not be read.Change readStatus to Filed but could not be read.boxName to the end of unreadDocuments and save it as unreadDocuments.Add boxName to the end of unreadDocuments and save it as unreadDocuments.readProblem to extractError.message.Change readProblem to extractError.message.rowValues to an empty list. Set rowValues to an empty list.filedAt to the end of rowValues and save it as rowValues. Add filedAt to the end of rowValues and save it as rowValues.senderAddress to the end of rowValues and save it as rowValues. Add senderAddress to the end of rowValues and save it as rowValues.subject to the end of rowValues and save it as rowValues. Add subject to the end of rowValues and save it as rowValues.boxName to the end of rowValues and save it as rowValues. Add boxName to the end of rowValues and save it as rowValues.storedLink to the end of rowValues and save it as rowValues. Add storedLink to the end of rowValues and save it as rowValues.readStatus to the end of rowValues and save it as rowValues. Add readStatus to the end of rowValues and save it as rowValues.wantedField in fieldNames: For each wantedField in fieldNames:cellValue to blank. Set cellValue to blank.wantedField in returnedNames and save it as foundAt. Find the position of wantedField in returnedNames and save it as foundAt.foundAt is greater than or equal to 0 If foundAt is greater than or equal to 0Yes
cellValue to returnedValues[@foundAt].Change cellValue to returnedValues[@foundAt].No
No steps
cellValue to the end of rowValues and save it as rowValues. Add cellValue to the end of rowValues and save it as rowValues.registerError If a step below fails, save the error as registerErrorTry
sheetTabName in registerSheetUrl.Add a row to sheetTabName in registerSheetUrl.On error
filedCount is 0If filedCount is 0Yes
boxName could not be written (registerError.message). Check that Google Sheets is connected and that 'registerSheetUrl' and 'sheetTabName' point at your register. The copy is already in Box; the email is left as it was, so the next run tries again and uses that copy.Stop and report a problem: Nothing was added to the register this run: the row for boxName could not be written (registerError.message). Check that Google Sheets is connected and that 'registerSheetUrl' and 'sheetTabName' point at your register. The copy is already in Box; the email is left as it was, so the next run tries again and uses that copy.No
No steps
boxName is in Box but could not be added to the register (registerError.message) to the end of messageProblems and save it as messageProblems.Add boxName is in Box but could not be added to the register (registerError.message) to the end of messageProblems and save it as messageProblems.filedCount. Add 1 to filedCount.messageDocuments. Add 1 to messageDocuments.boxName and added it to the register. Show in the output: Filed boxName and added it to the register.messageProblems is empty and messageDocuments is 0If messageProblems is empty and messageDocuments is 0Yes
messageDescription - it carried no PDF.Show in the output: Nothing to register on messageDescription - it carried no PDF.No
No steps
messageProblems is emptyIf messageProblems is emptyYes
processedLabel to email messageId.Add label processedLabel to email messageId.No
messageProblems with ; and save it as problemText.Join messageProblems with ; and save it as problemText.messageDescription: problemText to the end of setAside and save it as setAside.Add messageDescription: problemText to the end of setAside and save it as setAside.needsFilingLabel to email messageId.Add label needsFilingLabel to email messageId.On error
filedCount is 0If filedCount is 0Yes
messageDescription could not be handled (messageError.message). The email is left as it was, so the next run tries it again.Stop and report a problem: Nothing was filed this run: messageDescription could not be handled (messageError.message). The email is left as it was, so the next run tries it again.No
No steps
messageDescription: messageError.message to the end of setAside and save it as setAside.Add messageDescription: messageError.message to the end of setAside and save it as setAside.setAsideErrorIf a step below fails, save the error as setAsideErrorTry
needsFilingLabel to email message.Add label needsFilingLabel to email message.On error
No steps
filedCount is 0 and setAside is empty and messagesLeft is 0If filedCount is 0 and setAside is empty and messagesLeft is 0Yes
No
No steps
reportLines to an empty list.Set reportLines to an empty list.filedCount document(s) into Box and onto the register. to the end of reportLines and save it as reportLines.Add Filed filedCount document(s) into Box and onto the register. to the end of reportLines and save it as reportLines.messagesLeft is greater than 0If messagesLeft is greater than 0Yes
messagesLeft more message(s) are waiting: this run reached its limit of maxDocumentsPerRun documents, and the next run carries on from there. to the end of reportLines and save it as reportLines.Add messagesLeft more message(s) are waiting: this run reached its limit of maxDocumentsPerRun documents, and the next run carries on from there. to the end of reportLines and save it as reportLines.No
No steps
unreadDocuments isn't emptyIf unreadDocuments isn't emptyYes
unreadDocuments with , and save it as unreadList.Join unreadDocuments with , and save it as unreadList.unreadList. The reader said: readProblem to the end of reportLines and save it as reportLines.Add Filed, but the details could not be read, so their rows are empty for you to fill in: unreadList. The reader said: readProblem to the end of reportLines and save it as reportLines.No
No steps
setAside isn't emptyIf setAside isn't emptyYes
setAside with "Join setAside with
- and save it as setAsideList.setAsideList to the end of reportLines and save it as reportLines.No
No steps
reportLines with a new line and save it as runReport.Join reportLines with a new line and save it as runReport.setAside isn't emptyIf setAside isn't emptyYes
runReport.Stop and report a problem: runReport.No
No steps
unreadDocuments isn't emptyIf unreadDocuments isn't emptyYes
runReport.Stop and report a problem: runReport.No
No steps
runReport.Finish the run: runReport.