Reads each PDF that arrives by email and files it into the right Box folder by what it says, or leaves it for you when unsure.
UsesBox
Gmail
OpenAI
File emailed PDFs into the right Box folder
documentSearch to has:attachment filename:pdf newer_than:7d.Set documentSearch to has:attachment filename:pdf newer_than:7d.categoryOneName to blank.Set categoryOneName to blank.categoryOneFolder to blank.Set categoryOneFolder to blank.categoryOneAbout to blank.Set categoryOneAbout to blank.categoryTwoName to blank.Set categoryTwoName to blank.categoryTwoFolder to blank.Set categoryTwoFolder to blank.categoryTwoAbout to blank.Set categoryTwoAbout to blank.categoryThreeName to blank.Set categoryThreeName to blank.categoryThreeFolder to blank.Set categoryThreeFolder to blank.categoryThreeAbout to blank.Set categoryThreeAbout to blank.processedLabel to Document filing.Set processedLabel to Document filing.needsSortingLabel to Needs sorting.Set needsSortingLabel to Needs sorting.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
destinations to an empty list.Set destinations to an empty list.categoryOneName isn't empty and categoryOneFolder isn't emptyIf categoryOneName isn't empty and categoryOneFolder isn't emptyYes
destinations and save it as destinations.Add a record of name, folder, and about to the end of destinations and save it as destinations.No
No steps
categoryTwoName isn't empty and categoryTwoFolder isn't emptyIf categoryTwoName isn't empty and categoryTwoFolder isn't emptyYes
destinations and save it as destinations.Add a record of name, folder, and about to the end of destinations and save it as destinations.No
No steps
categoryThreeName isn't empty and categoryThreeFolder isn't emptyIf categoryThreeName isn't empty and categoryThreeFolder isn't emptyYes
destinations and save it as destinations.Add a record of name, folder, and about to the end of destinations and save it as destinations.No
No steps
filingDestinations to an empty list.Set filingDestinations to an empty list.destination in destinations:For each destination in destinations:destination.folder and save it as folderValue.Trim destination.folder and save it as folderValue.folderValue contains /folder/ (ignoring case)If folderValue contains /folder/ (ignoring case)Yes
folderValue split by /folder/ split by / and save it as folderValue.Trim the first item of the last item of folderValue split by /folder/ split by / and save it as folderValue.No
No steps
folderValue is empty or folderValue multiplied by 1 is not folderValueIf folderValue is empty or folderValue multiplied by 1 is not folderValueYes
No
filingDestinations and save it as filingDestinations.Add a record of name, folder, and about to the end of filingDestinations and save it as filingDestinations.filingDestinations is emptyIf filingDestinations is emptyYes
No
No steps
choicesText to blank.Set choicesText to blank.destination in filingDestinations:For each destination in filingDestinations:choiceLine to - destination.name.Set choiceLine to - destination.name.destination.about and save it as choiceAbout.Trim destination.about and save it as choiceAbout.choiceAbout isn't emptyIf choiceAbout isn't emptyYes
choiceLine to choiceLine: choiceAbout.Change choiceLine to choiceLine: choiceAbout.No
No steps
choicesText to choicesText@choiceLineChange choicesText to choicesText@choiceLine
.@processedLabel -label:@needsSortingLabel'. Save it as found.List emails matching '@documentSearch has:attachment -label:@processedLabel -label:@needsSortingLabel'. Save it as found.handledCount to 0.Set handledCount to 0.filedCount to 0.Set filedCount to 0.messagesLeft to 0.Set messagesLeft to 0.leftForYou to an empty list.Set leftForYou to an empty list.problems to an empty list.Set problems to an empty list.message in found.emails:For each message in found.emails:handledCount is greater than or equal to documentCapIf handledCount 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.senderAddress doesn't contain @ (ignoring case)If senderAddress doesn't contain @ (ignoring case)Yes
processedLabel to email messageId.Add label processedLabel to email messageId.needsSortingLabel to email messageId.Add label needsSortingLabel to email messageId.messageDescription: its sender could not be read to the end of leftForYou and save it as leftForYou.Add messageDescription: its sender could not be read to the end of leftForYou and save it as leftForYou.No
No steps
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
processedLabel to email messageId.Add label processedLabel to email messageId.needsSortingLabel to email messageId.Add label needsSortingLabel to email messageId.messageDescription: only a sender's newest email can be opened, and a newer one from this sender is in the inbox to the end of leftForYou and save it as leftForYou.Add messageDescription: only a sender's newest email can be opened, and a newer one from this sender is in the inbox to the end of leftForYou and save it as leftForYou.No
No steps
senderAddress. Save it as downloaded.Download the attachments on the latest email from senderAddress. Save it as downloaded.processedLabel to email messageId.Add label processedLabel to email messageId.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
documentDetails to an empty list. Set documentDetails to an empty list.failure to blank. Set failure to blank.setAsideReason to blank. Set setAsideReason to blank.readError If a step below fails, save the error as readErrorTry
reading.Run an AI agent: Read the attached document and pull out each of these fields, in this order: - What kind… and save it as reading.answer in reading.output.fields:For each answer in reading.output.fields:answerName to blank. Set answerName to blank.answerNameError If a step below fails, save the error as answerNameErrorTry
answer.name and save it as answerName.Trim answer.name and save it as answerName.On error
No steps
answerValue to blank. Set answerValue to blank.answerValueError If a step below fails, save the error as answerValueErrorTry
answer.value and save it as answerValue.Trim answer.value and save it as answerValue.On error
answerListErrorIf a step below fails, save the error as answerListErrorTry
answer.value with , and save it as answerValue.Join answer.value with , and save it as answerValue.On error
No steps
answerValue isn't empty If answerValue isn't emptyYes
answerName: answerValue truncated to 300 characters using … as the ellipsis to the end of documentDetails and save it as documentDetails.Add answerName: answerValue truncated to 300 characters using … as the ellipsis to the end of documentDetails and save it as documentDetails.No
No steps
On error
it could not be read (@readError.message) and save it as failure.Build the text it could not be read (@readError.message) and save it as failure.chosenName to blank. Set chosenName to blank.chosenFolder to blank. Set chosenFolder to blank.documentDetails isn't empty If documentDetails isn't emptyYes
choiceBrief to:Set choiceBrief to:Decide which folder a document belongs in, using only what the document itself says.
The folders:choiceRules to:Set choiceRules to:Reply with exactly one folder name from the list above and nothing else - no explanation, no punctuation. If the document does not clearly belong in exactly one of them, or you are not sure, reply with the single word UNCLEAR. Do not guess.choicePrompt to choiceBrief@choicesTextSet choicePrompt to choiceBrief@choicesText
What the document says:
documentDetails joined by a new line@choiceRules.verdict to blank.Set verdict to blank.choiceErrorIf a step below fails, save the error as choiceErrorTry
choicePrompt. Save it as chosen.Ask OpenAI: choicePrompt. Save it as chosen.chosen.response_text lowercase and save it as verdict.Make chosen.response_text lowercase and save it as verdict.On error
the folder could not be chosen (@choiceError.message) and save it as failure.Build the text the folder could not be chosen (@choiceError.message) and save it as failure.verdict with replaced by " and save it as verdict.Trim verdict with replaced by " and save it as verdict.verdict ends with . (ignoring case)If verdict ends with . (ignoring case)Yes
verdict truncated to the length of verdict minus 1 characters and save it as verdict.Trim verdict truncated to the length of verdict minus 1 characters and save it as verdict.No
No steps
destination in filingDestinations:For each destination in filingDestinations:destination.name in lowercase is verdict If destination.name in lowercase is verdictYes
chosenName to destination.name.Change chosenName to destination.name.chosenFolder to destination.folder.Change chosenFolder to destination.folder.No
No steps
Else if @failure is empty
setAsideReason to nothing could be read out of it.Change setAsideReason to nothing could be read out of it.Otherwise
No steps
chosenFolder is empty and failure is empty If chosenFolder is empty and failure is emptyYes
setAsideReason is emptyIf setAsideReason is emptyYes
setAsideReason to its contents did not clearly match one of your folders.Change setAsideReason to its contents did not clearly match one of your folders.No
No steps
No
No steps
chosenFolder isn't empty If chosenFolder isn't emptyYes
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 boxNameIf 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.uploadErrorIf a step below fails, save the error as uploadErrorTry
chosenFolder to Box folder documentRef. Save it as stored.Upload chosenFolder 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
chosenFolder. Save it as folderItems.List items in Box folder chosenFolder. 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 isn't emptyIf storedLink isn't emptyYes
filedCount.Add 1 to filedCount.handledCount.Add 1 to handledCount.attachmentLabel under chosenName as boxName.Show in the output: Filed attachmentLabel under chosenName as boxName.No
No steps
it could not be copied into the '@chosenName' folder in Box (@uploadProblem) and save it as failure.Build the text it could not be copied into the '@chosenName' folder in Box (@uploadProblem) and save it as failure.No
No steps
handledCount. Add 1 to handledCount.sortingLabelError If a step below fails, save the error as sortingLabelErrorTry
needsSortingLabel to email messageId.Add label needsSortingLabel to email messageId.On error
attachmentLabel on messageDescription: the '@needsSortingLabel' label could not be added (sortingLabelError.message) to the end of problems and save it as problems.Add attachmentLabel on messageDescription: the '@needsSortingLabel' label could not be added (sortingLabelError.message) to the end of problems and save it as problems.failure isn't empty If failure isn't emptyYes
attachmentLabel on messageDescription: failure to the end of problems and save it as problems.Add attachmentLabel on messageDescription: failure to the end of problems and save it as problems.filedCount is 0If filedCount is 0Yes
attachmentLabel on messageDescription was not filed because failure. It is labelled '@needsSortingLabel' for you. Check the connection or setting this points to; the rest of your mail is left for the next run.Stop and report a problem: Stopped before filing anything: attachmentLabel on messageDescription was not filed because failure. It is labelled '@needsSortingLabel' for you. Check the connection or setting this points to; the rest of your mail is left for the next run.No
No steps
No
attachmentLabel on messageDescription: setAsideReason to the end of leftForYou and save it as leftForYou.Add attachmentLabel on messageDescription: setAsideReason to the end of leftForYou and save it as leftForYou.attachmentLabel. Show in the output: Left for you: attachmentLabel.On error
messageDescription: messageError.message to the end of problems and save it as problems.Add messageDescription: messageError.message to the end of problems and save it as problems.setAsideErrorIf a step below fails, save the error as setAsideErrorTry
processedLabel to email message.Add label processedLabel to email message.needsSortingLabel to email message.Add label needsSortingLabel to email message.On error
No steps
filedCount is 0If filedCount is 0Yes
messageDescription could not be handled (messageError.message). The rest of your mail is left for the next run.Stop and report a problem: Stopped before filing anything: messageDescription could not be handled (messageError.message). The rest of your mail is left for the next run.No
No steps
handledCount is 0 and leftForYou is empty and problems is emptyIf handledCount is 0 and leftForYou is empty and problems is emptyYes
No
No steps
reportLines to an empty list.Set reportLines to an empty list.filedCount document(s) into Box. to the end of reportLines and save it as reportLines.Add Filed filedCount document(s) into Box. to the end of reportLines and save it as reportLines.messagesLeft is greater than 0If messagesLeft is greater than 0Yes
messagesLeft more email(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 email(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
leftForYou isn't emptyIf leftForYou isn't emptyYes
leftForYou with "Join leftForYou with
- and save it as leftForYouList.leftForYouList to the end of reportLines and save it as reportLines.No
No steps
problems isn't emptyIf problems isn't emptyYes
problems with "Join problems with
- and save it as problemList.problemList 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.problems isn't emptyIf problems isn't emptyYes
runReport.Stop and report a problem: runReport.No
No steps
runReport.Finish the run: runReport.