{ "kind": "open-flow-workflow", "version": 1, "name": "Create Nextcloud Deck Cards from Email", "content": { "modelVersion": 14, "document": { "bindings": {}, "graph": { "nodes": { "n_e96870f205d6b18a": { "name": "Check inbox every minute", "kind": "cron", "cronTimes": [ { "type": "every", "unit": "minute", "value": 1 } ] }, "n_c0545b32b646c364": { "inputs": { "folder": { "kind": "value", "value": "INBOX" }, "unseen": { "kind": "value", "value": true }, "limit": { "kind": "value", "value": 1 } }, "name": "Find an unread email", "kind": "task", "task": { "inputs": [ { "description": "The IMAP folder path returned by list_folders.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The IMAP folder path returned by list_folders.", "default": "INBOX" }, "nullable": true, "handle": "folder", "value": "INBOX" }, { "description": "Whether to return only unread messages.", "jsonSchema": { "type": "boolean", "description": "Whether to return only unread messages." }, "nullable": true, "handle": "unseen", "value": null }, { "description": "A sender search term.", "jsonSchema": { "type": "string", "minLength": 1, "description": "A sender search term." }, "nullable": true, "handle": "from", "value": null }, { "description": "A recipient search term.", "jsonSchema": { "type": "string", "minLength": 1, "description": "A recipient search term." }, "nullable": true, "handle": "to", "value": null }, { "description": "A subject search term.", "jsonSchema": { "type": "string", "minLength": 1, "description": "A subject search term." }, "nullable": true, "handle": "subject", "value": null }, { "description": "A body text search term.", "jsonSchema": { "type": "string", "minLength": 1, "description": "A body text search term." }, "nullable": true, "handle": "text", "value": null }, { "description": "Only include messages on or after this YYYY-MM-DD date.", "jsonSchema": { "type": "string", "format": "date", "description": "Only include messages on or after this YYYY-MM-DD date." }, "nullable": true, "handle": "since", "value": null }, { "description": "Only include messages before this YYYY-MM-DD date.", "jsonSchema": { "type": "string", "format": "date", "description": "Only include messages before this YYYY-MM-DD date." }, "nullable": true, "handle": "before", "value": null }, { "description": "The maximum number of email summaries to return.", "jsonSchema": { "type": "integer", "minimum": 1, "maximum": 100, "description": "The maximum number of email summaries to return.", "default": 20 }, "nullable": true, "handle": "limit", "value": 20 }, { "description": "Only include message UIDs lower than this cursor.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "Only include message UIDs lower than this cursor." }, "nullable": true, "handle": "beforeUid", "value": null } ], "outputs": [ { "description": "The IMAP folder path that was searched.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The IMAP folder path that was searched." }, "nullable": false, "handle": "folder" }, { "description": "The email summaries returned for this page.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "uid": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "messageId": { "type": [ "string", "null" ], "description": "The Message-ID header when available." }, "subject": { "type": [ "string", "null" ], "description": "The email subject when available." }, "from": { "type": [ "object", "null" ], "properties": { "name": { "type": [ "string", "null" ], "description": "The display name when one was provided." }, "email": { "type": [ "string", "null" ], "description": "The email address when one was provided." } }, "required": [ "name", "email" ], "additionalProperties": false, "description": "A normalized email address." }, "to": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": [ "string", "null" ], "description": "The display name when one was provided." }, "email": { "type": [ "string", "null" ], "description": "The email address when one was provided." } }, "required": [ "name", "email" ], "additionalProperties": false, "description": "A normalized email address." }, "description": "The primary recipients parsed from the message envelope." }, "date": { "type": [ "string", "null" ], "format": "date-time", "description": "The message date as an ISO 8601 timestamp." }, "flags": { "type": "array", "items": { "type": "string", "description": "One IMAP flag." }, "description": "The IMAP flags currently set on the message." }, "seen": { "type": "boolean", "description": "Whether the message has the IMAP Seen flag." }, "hasAttachments": { "type": "boolean", "description": "Whether the message has attachment parts." }, "size": { "type": [ "integer", "null" ], "description": "The message size in bytes when available." } }, "required": [ "uid", "messageId", "subject", "from", "to", "date", "flags", "seen", "hasAttachments", "size" ], "additionalProperties": false, "description": "A lightweight IMAP Mailbox message summary." }, "description": "The email summaries returned for this page." }, "nullable": false, "handle": "emails" }, { "description": "The cursor to pass as beforeUid for the next page.", "jsonSchema": { "type": [ "integer", "null" ], "exclusiveMinimum": 0, "description": "The cursor to pass as beforeUid for the next page." }, "nullable": true, "handle": "nextBeforeUid" } ], "name": "Find an unread email", "executor": { "kind": "connector", "action": "generic_imap.search_emails" } } }, "n_4ca74aba668ee12d": { "inputs": { "emails": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_c0545b32b646c364", "output": "emails" } ] } }, "name": "Select the email", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "uid": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "messageId": { "type": [ "string", "null" ], "description": "The Message-ID header when available." }, "subject": { "type": [ "string", "null" ], "description": "The email subject when available." }, "from": { "type": [ "object", "null" ], "properties": { "name": { "type": [ "string", "null" ], "description": "The display name when one was provided." }, "email": { "type": [ "string", "null" ], "description": "The email address when one was provided." } }, "required": [ "name", "email" ], "additionalProperties": false, "description": "A normalized email address." }, "to": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": [ "string", "null" ], "description": "The display name when one was provided." }, "email": { "type": [ "string", "null" ], "description": "The email address when one was provided." } }, "required": [ "name", "email" ], "additionalProperties": false, "description": "A normalized email address." }, "description": "The primary recipients parsed from the message envelope." }, "date": { "type": [ "string", "null" ], "format": "date-time", "description": "The message date as an ISO 8601 timestamp." }, "flags": { "type": "array", "items": { "type": "string", "description": "One IMAP flag." }, "description": "The IMAP flags currently set on the message." }, "seen": { "type": "boolean", "description": "Whether the message has the IMAP Seen flag." }, "hasAttachments": { "type": "boolean", "description": "Whether the message has attachment parts." }, "size": { "type": [ "integer", "null" ], "description": "The message size in bytes when available." } }, "required": [ "uid", "messageId", "subject", "from", "to", "date", "flags", "seen", "hasAttachments", "size" ], "additionalProperties": false, "description": "A lightweight IMAP Mailbox message summary." }, "description": "The email summaries returned for this page." }, "nullable": false, "handle": "emails" } ], "outputs": [ { "jsonSchema": { "type": "boolean" }, "nullable": false, "handle": "more" }, { "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "nullable": false, "handle": "uid" } ], "name": "Select the email", "moduleId": "n_4155a5eb801e7a04", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_fb8e1699ca2b9e5d": { "inputs": {}, "name": "Unread email found?", "kind": "condition", "matchMode": "first", "cases": [ { "output": "yes", "groups": [ { "expressions": [ { "left": { "kind": "source", "source": { "kind": "node", "nodeId": "n_4ca74aba668ee12d", "output": "more" } }, "operator": "isTrue" } ] } ] } ] }, "n_b803272547f316b2": { "inputs": { "folder": { "kind": "value", "value": "INBOX" }, "uid": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_4ca74aba668ee12d", "output": "uid" } ] } }, "name": "Read the email", "kind": "task", "task": { "inputs": [ { "description": "The IMAP folder path returned by list_folders.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The IMAP folder path returned by list_folders.", "default": "INBOX" }, "nullable": true, "handle": "folder", "value": "INBOX" }, { "description": "The IMAP UID of the message.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "nullable": false, "handle": "uid" } ], "outputs": [ { "description": "The IMAP folder path that contained the message.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The IMAP folder path that contained the message." }, "nullable": false, "handle": "folder" }, { "description": "The IMAP UID of the message.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "nullable": false, "handle": "uid" }, { "description": "The Message-ID header when available.", "jsonSchema": { "type": [ "string", "null" ], "description": "The Message-ID header when available." }, "nullable": true, "handle": "messageId" }, { "description": "The email subject when available.", "jsonSchema": { "type": [ "string", "null" ], "description": "The email subject when available." }, "nullable": true, "handle": "subject" }, { "description": "A normalized email address.", "jsonSchema": { "type": [ "object", "null" ], "properties": { "name": { "type": [ "string", "null" ], "description": "The display name when one was provided." }, "email": { "type": [ "string", "null" ], "description": "The email address when one was provided." } }, "required": [ "name", "email" ], "additionalProperties": false, "description": "A normalized email address." }, "nullable": true, "handle": "from" }, { "description": "The primary recipients parsed from the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": [ "string", "null" ], "description": "The display name when one was provided." }, "email": { "type": [ "string", "null" ], "description": "The email address when one was provided." } }, "required": [ "name", "email" ], "additionalProperties": false, "description": "A normalized email address." }, "description": "The primary recipients parsed from the message." }, "nullable": false, "handle": "to" }, { "description": "The carbon-copy recipients parsed from the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": [ "string", "null" ], "description": "The display name when one was provided." }, "email": { "type": [ "string", "null" ], "description": "The email address when one was provided." } }, "required": [ "name", "email" ], "additionalProperties": false, "description": "A normalized email address." }, "description": "The carbon-copy recipients parsed from the message." }, "nullable": false, "handle": "cc" }, { "description": "The message date as an ISO 8601 timestamp.", "jsonSchema": { "type": [ "string", "null" ], "format": "date-time", "description": "The message date as an ISO 8601 timestamp." }, "nullable": true, "handle": "date" }, { "description": "The IMAP flags currently set on the message.", "jsonSchema": { "type": "array", "items": { "type": "string", "description": "One IMAP flag." }, "description": "The IMAP flags currently set on the message." }, "nullable": false, "handle": "flags" }, { "description": "Whether the message has the IMAP Seen flag.", "jsonSchema": { "type": "boolean", "description": "Whether the message has the IMAP Seen flag." }, "nullable": false, "handle": "seen" }, { "description": "The parsed plain text body within the fetch budget.", "jsonSchema": { "type": [ "string", "null" ], "description": "The parsed plain text body within the fetch budget." }, "nullable": true, "handle": "text" }, { "description": "The parsed HTML body within the fetch budget.", "jsonSchema": { "type": [ "string", "null" ], "description": "The parsed HTML body within the fetch budget." }, "nullable": true, "handle": "html" }, { "description": "Whether returned body content was truncated or omitted by budget.", "jsonSchema": { "type": "boolean", "description": "Whether returned body content was truncated or omitted by budget." }, "nullable": false, "handle": "truncated" }, { "description": "Attachment metadata parsed from the message.", "jsonSchema": { "type": "array", "items": { "type": "object", "properties": { "attachmentId": { "type": "string", "minLength": 1, "description": "The IMAP body part identifier returned in an attachment metadata item." }, "filename": { "type": [ "string", "null" ], "description": "The attachment filename when available." }, "contentType": { "type": [ "string", "null" ], "description": "The attachment MIME content type when available." }, "size": { "type": [ "integer", "null" ], "description": "The attachment size in bytes when available." }, "contentId": { "type": [ "string", "null" ], "description": "The attachment Content-ID when available." } }, "required": [ "attachmentId", "filename", "contentType", "size", "contentId" ], "additionalProperties": false, "description": "Attachment metadata without attachment content." }, "description": "Attachment metadata parsed from the message." }, "nullable": false, "handle": "attachments" } ], "name": "Read the email", "executor": { "kind": "connector", "action": "generic_imap.get_email" } } }, "n_9924a88f9aedc77d": { "inputs": { "folder": { "kind": "value", "value": "INBOX" }, "uid": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_4ca74aba668ee12d", "output": "uid" } ] } }, "name": "Mark email read", "kind": "task", "task": { "inputs": [ { "description": "The IMAP folder path returned by list_folders.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The IMAP folder path returned by list_folders.", "default": "INBOX" }, "nullable": true, "handle": "folder", "value": "INBOX" }, { "description": "The IMAP UID of the message.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "nullable": false, "handle": "uid" } ], "outputs": [ { "description": "The IMAP folder path that contained the message.", "jsonSchema": { "type": "string", "minLength": 1, "description": "The IMAP folder path that contained the message." }, "nullable": false, "handle": "folder" }, { "description": "The IMAP UID of the message.", "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "nullable": false, "handle": "uid" }, { "description": "Whether the message is now marked as read.", "jsonSchema": { "const": true, "description": "Whether the message is now marked as read." }, "nullable": false, "handle": "read" } ], "name": "Mark email read", "executor": { "kind": "connector", "action": "generic_imap.mark_email_read" } } }, "n_e82e945409795666": { "inputs": { "uid": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_4ca74aba668ee12d", "output": "uid" } ] }, "actualUid": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b803272547f316b2", "output": "uid" } ] }, "subject": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b803272547f316b2", "output": "subject" } ] }, "text": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b803272547f316b2", "output": "text" } ] }, "html": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b803272547f316b2", "output": "html" } ] }, "truncated": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_b803272547f316b2", "output": "truncated" } ] } }, "name": "Prepare the Deck card", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "nullable": false, "handle": "uid" }, { "jsonSchema": { "type": "integer", "exclusiveMinimum": 0, "description": "The IMAP UID of the message." }, "nullable": false, "handle": "actualUid" }, { "jsonSchema": { "type": [ "string", "null" ], "description": "The email subject when available." }, "nullable": true, "handle": "subject" }, { "jsonSchema": { "type": [ "string", "null" ], "description": "The parsed plain text body within the fetch budget." }, "nullable": true, "handle": "text" }, { "jsonSchema": { "type": [ "string", "null" ], "description": "The parsed HTML body within the fetch budget." }, "nullable": true, "handle": "html" }, { "jsonSchema": { "type": "boolean", "description": "Whether returned body content was truncated or omitted by budget." }, "nullable": false, "handle": "truncated" } ], "outputs": [ { "jsonSchema": { "type": "object", "additionalProperties": true }, "nullable": false, "handle": "card" } ], "name": "Prepare the Deck card", "moduleId": "n_162e520da9781f11", "capabilities": [ { "kind": "connector", "mode": "independent", "actions": [] } ] } }, "n_60afb40df10c484d": { "inputs": { "url": { "kind": "value", "value": "https://YOUR_NEXTCLOUD_HOST/index.php/apps/deck/api/v1.0/boards/YOUR_BOARD_ID/stacks/YOUR_STACK_ID/cards" }, "body": { "kind": "sources", "sources": [ { "kind": "node", "nodeId": "n_e82e945409795666", "output": "card" } ] }, "header.OCS-APIRequest": { "kind": "value", "value": "true" }, "auth.username": { "kind": "unset" }, "auth.password": { "kind": "unset" } }, "name": "Create the Deck card", "kind": "task", "task": { "inputs": [ { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "url" }, { "jsonSchema": { "type": "string" }, "nullable": true, "handle": "header.OCS-APIRequest" }, { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.username" }, { "jsonSchema": { "type": "string" }, "nullable": false, "handle": "auth.password" } ], "outputs": [ { "jsonSchema": {}, "nullable": true, "handle": "body" }, { "jsonSchema": { "type": "integer" }, "nullable": false, "handle": "statusCode" }, { "jsonSchema": { "type": "object", "additionalProperties": { "type": "string" } }, "nullable": false, "handle": "headers" } ], "name": "Create the Deck card", "executor": { "method": "POST", "query": { "mode": "fields", "names": [] }, "headers": { "mode": "fields", "names": [ "OCS-APIRequest" ] }, "bodyFormat": "json", "authentication": { "type": "basic" }, "responseFormat": "json", "statusPolicy": "success", "kind": "http-request" } } } }, "edges": [ { "source": "n_e96870f205d6b18a", "target": "n_c0545b32b646c364" }, { "source": "n_c0545b32b646c364", "target": "n_4ca74aba668ee12d" }, { "source": "n_4ca74aba668ee12d", "target": "n_fb8e1699ca2b9e5d" }, { "source": "n_fb8e1699ca2b9e5d", "target": "n_b803272547f316b2", "sourceHandle": "yes" }, { "source": "n_b803272547f316b2", "target": "n_9924a88f9aedc77d" }, { "source": "n_9924a88f9aedc77d", "target": "n_e82e945409795666" }, { "source": "n_e82e945409795666", "target": "n_60afb40df10c484d" }, { "source": "n_60afb40df10c484d", "target": "n_c0545b32b646c364" } ] } }, "modules": { "n_4155a5eb801e7a04": { "name": "Select the email", "imports": [], "source": "export default function pickDeckMail({emails}) {\n if (!Array.isArray(emails)) throw Error('Invalid IMAP search response');\n if (emails.length === 0) return {more:false,uid:1};\n const uid=emails[0]?.uid;\n if (!Number.isSafeInteger(uid)||uid<1) throw Error('Invalid IMAP UID');\n return {more:true,uid};\n}\n" }, "n_162e520da9781f11": { "name": "Prepare the Deck card", "imports": [], "source": "export default function deckMailCard({uid,actualUid,subject,text,html,truncated}) {\n if(uid!==actualUid||truncated)throw Error('Cannot read the complete email');\n if(typeof subject!=='string'||!subject.trim()||subject.length>255)throw Error('Deck card title must contain 1 to 255 characters');\n const body=typeof html==='string'&&html?html.replace(//g,'\\n').replace(/(<([^>]+)>)/g,''):typeof text==='string'?text:null;\n if(body===null)throw Error('Email body is missing');\n return {card:{title:subject,type:'plain',order:-1,description:body}};\n}\n" } } }, "presentation": { "designer": { "version": 1, "flow": { "direction": "vertical" } } } }