Email read IMAP issue

Hi,

I have set up the ‘Email Read IMAP’ node to read an office 365 folder for incoming emails.

I always try to save attachments even when the email has no attachments, I have the rule in the node that says if it fails continue, but sometimes I get this error:

85|n8n  | TypeError: Cannot read property 'filename' of null
85|n8n  |     at /usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:195:103
85|n8n  |     at runMicrotasks (<anonymous>)
85|n8n  |     at processTicksAndRejections (internal/process/task_queues.js:95:5)
85|n8n  |     at async Promise.all (index 0)
85|n8n  |     at async getNewEmails (/usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:283:39)
85|n8n  |     at async Connection.onmail (/usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:343:44)

To rectify this I then execute workflow manually from gui and the emails are marked as unread and the node triggers correctly.

Could someone please suggest what might be going on please?

Thank you!

Christian

Hey @Christian_Garcia!

Welcome to the community :sparkling_heart:

Do you get this error when there are no attachments? And to make sure that I understood, you get this error when the workflow is triggered, but not when you execute it manually?

Thanks for you fast response.

Sorry for delay I was testing some scenaries, I was test with GUI manually and it give the same error but now there are more details.

It is happend when the mail has attachments.

85|n8n  | (node:13696) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'filename' of null
85|n8n  |     at /usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:195:103
85|n8n  |     at processTicksAndRejections (internal/process/task_queues.js:95:5)
85|n8n  |     at async Promise.all (index 0)
85|n8n  |     at async getNewEmails (/usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:283:39)
85|n8n  |     at async Connection.onmail (/usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:343:44)
85|n8n  | (Use `node --trace-warnings ...` to show where the warning was created)
85|n8n  | (node:13696) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
85|n8n  | (node:13696) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Thanks

Can you share the workflow? Please replace any sensitive data with dummy data. I tested this and it works well for me. I don’t get any errors, for the emails that have attachments and the ones that don’t.

Thanks.

{
  "name": "email_flow",
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        -860,
        600
      ]
    },
    {
      "parameters": {
        "downloadAttachments": true,
        "options": {}
      },
      "name": "IMAP Email",
      "type": "n8n-nodes-base.emailReadImap",
      "typeVersion": 1,
      "position": [
        -720,
        600
      ],
      "credentials": {
        "imap": "CREDENTIALS"
      }
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://webhook.site/94cf0fe8-09c2-4535-a25f-77576a0695ad",
        "options": {
          "bodyContentType": "form-urlencoded"
        },
        "bodyParametersUi": {
          "parameter": [
            {
              "name": "messageID",
              "value": "={{$json[\"metadata\"][\"message-id\"]}}"
            },
            {
              "name": "reply-id",
              "value": "={{$json[\"metadata\"][\"in-reply-to\"]}}"
            },
            {
              "name": "HTML",
              "value": "={{$json[\"html\"]}}"
            },
            {
              "name": "subject",
              "value": "={{$json[\"subject\"]}}"
            },
            {
              "name": "to",
              "value": "={{$json[\"to\"]}}"
            },
            {
              "name": "from",
              "value": "={{$json[\"from\"]}}"
            },
            {
              "name": "adjunto_1",
              "value": "={{$json[\"url\"]}} {{$json[\"url0\"]}}"
            },
            {
              "name": "adjunto_2",
              "value": "={{$json[\"url1\"]}}"
            },
            {
              "name": "adjunto_3",
              "value": "={{$json[\"url2\"]}}"
            },
            {
              "name": "adjunto_4",
              "value": "={{$json[\"url3\"]}}"
            }
          ]
        }
      },
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        399.8373493975903,
        336.6265060240964
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://url.saveimage.com/saveImageBinaryAPP",
        "jsonParameters": true,
        "options": {
          "bodyContentType": "multipart-form-data"
        },
        "sendBinaryData": true,
        "binaryPropertyName": "attachment_0"
      },
      "name": "adjunto_0",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        -310,
        280
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://url.saveimage.com/saveImageBinaryAPP",
        "jsonParameters": true,
        "options": {
          "bodyContentType": "multipart-form-data"
        },
        "sendBinaryData": true,
        "binaryPropertyName": "attachment_1"
      },
      "name": "adjunto_1",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        -310,
        460
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://url.saveimage.com/saveImageBinaryAPP",
        "jsonParameters": true,
        "options": {
          "bodyContentType": "multipart-form-data"
        },
        "sendBinaryData": true,
        "binaryPropertyName": "attachment_2"
      },
      "name": "adjunto_2",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        -300,
        640
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://url.saveimage.com/saveImageBinaryAPP",
        "jsonParameters": true,
        "options": {
          "bodyContentType": "multipart-form-data"
        },
        "sendBinaryData": true,
        "binaryPropertyName": "attachment_3"
      },
      "name": "adjunto_3",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        -300,
        820
      ],
      "continueOnFail": true
    },
    {
      "parameters": {},
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        -90.16265060240971,
        266.6265060240964
      ]
    },
    {
      "parameters": {},
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        -90.16265060240971,
        476.6265060240964
      ]
    },
    {
      "parameters": {},
      "name": "Merge2",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        119.83734939759029,
        386.6265060240964
      ]
    },
    {
      "parameters": {
        "functionCode": "// Code here will run only once, no matter how many input items there are.\n// More info and help: https://docs.n8n.io/nodes/n8n-nodes-base.function\n//return [{json:{test:\"1\"}}];\n// Loop over inputs and add a new field called 'myNewField' to the JSON of each one\n\nvar result = {};\n\nfor (var i = 0; i < items.length; i++) {\n  result['url'+i] = items[i].json.url;  \n  \n  result.html = items[i].json.textHtml;\n  result.textPlain = items[i].json.textPlain;\n//  console.log(result.html);\n  \n  /*if (items[i].json.textHtml != \"\")\n  {\n    const buff = Buffer.from(items[i].json.textHtml, 'utf-8');\n    result.html = buff.toString('base64');\n  }  */\n  \n//  console.log(result.html)\n  \n//  result.html64 = Buffer.from(result.html).toString('base64')\n  \n  result.metadata= items[i].json.metadata;\n  result.from= items[i].json.from;\n  result.to= items[i].json.to;\n  result.subject= items[i].json.subject;\n  \n  //console.log(items[i]); \n  //result.json = items[i].json;\n}\n\n// You can write logs to the browser console\nconsole.log('Done!');\n\nreturn [{json:result}];\n\n\nreturn items.map(item => {\n  return {\n    json: {\n      dataBase64: Buffer.from(item.json.data).toString('base64'),\n    }\n  }\n});\n"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        500,
        650
      ]
    },
    {
      "parameters": {},
      "name": "Merge3",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        299.8373493975903,
        646.6265060240964
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://other.url/?service=mail_incoming_queue",
        "responseFormat": "string",
        "jsonParameters": true,
        "options": {
          "bodyContentType": "json"
        },
        "bodyParametersJson": "={{$json}}"
      },
      "name": "HTTP queue",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        600,
        340
      ]
    },
    {
      "parameters": {
        "queue": "mail_incoming_queue",
        "options": {
          "arguments": {
            "argument": [
              {
                "key": "x-dead-letter-exchange"
              }
            ]
          },
          "durable": true,
          "headers": {
            "header": [
              {
                "key": "x-delay",
                "value": "7000"
              }
            ]
          }
        }
      },
      "name": "RabbitMQ",
      "type": "n8n-nodes-base.rabbitmq",
      "typeVersion": 1,
      "position": [
        690,
        650
      ],
      "credentials": {
        "rabbitmq": "RabbitMQ"
      }
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json[\"from\"]}}",
              "operation": "notContains",
              "value2": "[email protected]"
            },
            {
              "value1": "={{$json[\"from\"]}}",
              "operation": "notContains",
              "value2": "[email protected]"
            },
            {
              "value1": "={{$json[\"from\"]}}",
              "operation": "notContains",
              "value2": "[email protected]"
            }
          ]
        },
        "combineOperation": "any"
      },
      "name": "IF",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        -560,
        600
      ]
    },
    {
      "parameters": {},
      "name": "NoOp",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        -550,
        820
      ]
    }
  ],
  "connections": {
    "IMAP Email": {
      "main": [
        [
          {
            "node": "IF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "adjunto_0": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "adjunto_1": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "adjunto_2": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "adjunto_3": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge1": {
      "main": [
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge2": {
      "main": [
        [
          {
            "node": "Merge3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "RabbitMQ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge3": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF": {
      "main": [
        [
          {
            "node": "adjunto_0",
            "type": "main",
            "index": 0
          },
          {
            "node": "adjunto_1",
            "type": "main",
            "index": 0
          },
          {
            "node": "adjunto_2",
            "type": "main",
            "index": 0
          },
          {
            "node": "adjunto_3",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge3",
            "type": "main",
            "index": 1
          }
        ],
        [
          {
            "node": "NoOp",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {},
  "id": 5
}

Hey @Christian_Garcia,

Thank you for sharing the workflow. I see that you’ve 4 different HTTP Request nodes that do the same operation. Do you always get 4 files? Also, are you getting this email from a particular email address or with a particular subject? You can setup Custom email rules in the IMAP node to listen for particular emails.

I tested only the IMAP node, and I am not able to replicate your issue still. I am getting the expected result.

Hi, thanks for your help.

I always try to save 4 files because I don’t know if the email has attachments or not, I don’t know if there is another way to check that the email has attachments and then make a iteration “for or each” to save the attachments.

Maybe the error is because it tries to process a third or fourth attachment that does not exist, could you help me with how I can create a “for or each” for the attachments according to the number of attachments

If the emails are from Cortana, or from certain recipients, I will not process them.

Thanks

Hey @Christian_Garcia,

Here’s an example workflow that might help:

{
  "nodes": [
    {
      "parameters": {
        "postProcessAction": "nothing",
        "downloadAttachments": true,
        "options": {
          "customEmailConfig": "[\"UNSEEN\", [\"FROM\",\"[email protected]\"]]"
        }
      },
      "name": "IMAP Email",
      "type": "n8n-nodes-base.emailReadImap",
      "typeVersion": 1,
      "position": [
        880,
        770
      ],
      "credentials": {
        "imap": "Personal IMAP Credentials"
      }
    },
    {
      "parameters": {
        "functionCode": "return Object.keys(items[0].binary).map(key => {\n  return {\n    json: {},\n    binary: {\n      data: items[0].binary[key],\n    }\n  }\n});\n"
      },
      "name": "Split Binary Data",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        1080,
        770
      ]
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://webhook.site/a918be7f-d906-48bd-a2d4-8bd336df584f",
        "jsonParameters": true,
        "options": {
          "bodyContentType": "multipart-form-data"
        },
        "sendBinaryData": true
      },
      "name": "Upload",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        1260,
        770
      ]
    }
  ],
  "connections": {
    "IMAP Email": {
      "main": [
        [
          {
            "node": "Split Binary Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Binary Data": {
      "main": [
        [
          {
            "node": "Upload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

If you see the IMAP Email node, I am using Custom Rules to only trigger the node when I receive an email from a particular email. You can refer to the rules here and set up custom rules.
Next, the Function node, Split Binary Data, splits the incoming binary files into individual items and passes them to the next node.
The HTTP Request node will now use these files and upload them to the specified URL. This solution solves the issue when you receive less or more than 4 files.

I hope this helps :slight_smile:

Thanks, I was testing your code and works, but I have an error “Cannot convert undefined or null to object” when the email has no attachments, can I do something inside function for avoid not executing this node when not has attachments ??

Hey @Christian_Garcia,

You can check if the binary data is present or not and then run the function. The below code should cover your use case

for (let item in items) {
  if(Object.keys(items[item]).includes('binary')){
    return Object.keys(items[item].binary).map(key => {
    return {
      json: {},
      binary: {
        data: items[item].binary[key],
      }
    }
});
  }
}
return items;

Thanks for your help, I replaced workflow with the new and gave the same error:

85|n8n  | TypeError: Cannot read property 'filename' of null
85|n8n  |     at /usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:195:103
85|n8n  |     at runMicrotasks (<anonymous>)
85|n8n  |     at processTicksAndRejections (internal/process/task_queues.js:95:5)
85|n8n  |     at async Promise.all (index 0)
85|n8n  |     at async getNewEmails (/usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:283:39)
85|n8n  |     at async Connection.onmail (/usr/lib/node_modules/n8n/node_modules/n8n-nodes-base/dist/nodes/EmailReadImap.node.js:343:44)

I use pm2 for running n8n in background, I don’t know if this is something related, I did tests by running n8n manually and getting the same error .

:frowning:

Thanks

That is strange. I tested the above code and it worked well for me. Can you share your updated workflow?

Hello,

{
  "name": "email_flow_v2",
  "nodes": [
    {
      "parameters": {},
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        -920,
        600
      ]
    },
    {
      "parameters": {
        "downloadAttachments": true,
        "options": {}
      },
      "name": "IMAP Email",
      "type": "n8n-nodes-base.emailReadImap",
      "typeVersion": 1,
      "position": [
        -750,
        600
      ],
      "credentials": {
        "imap": "credentials"
      }
    },
    {
      "parameters": {
        "functionCode": "for (let item in items) {\n  if(Object.keys(items[item]).includes('binary')){\n    return Object.keys(items[item].binary).map(key => {\n    return {\n      json: {},\n      binary: {\n        data: items[item].binary[key],\n      }\n    }\n});\n  }\n}\nreturn items;\n"
      },
      "name": "Split Binary Data",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        -600,
        490
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "requestMethod": "POST",
        "url": "https://api.tosave.file/com",
        "jsonParameters": true,
        "options": {
          "bodyContentType": "multipart-form-data"
        },
        "sendBinaryData": true
      },
      "name": "adjuntos",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 1,
      "position": [
        -370,
        490
      ],
      "continueOnFail": true
    },
    {
      "parameters": {
        "functionCode": "// Code here will run only once, no matter how many input items there are.\n// More info and help: https://docs.n8n.io/nodes/n8n-nodes-base.function\n//return [{json:{test:\"1\"}}];\n// Loop over inputs and add a new field called 'myNewField' to the JSON of each one\n\nvar result = {};\n\nfor (var i = 0; i < items.length; i++) {\n  result['url'+i] = items[i].json.url;  \n  \n  result.html = items[i].json.textHtml;\n  result.textPlain = items[i].json.textPlain;\n//  console.log(result.html);\n  \n  /*if (items[i].json.textHtml != \"\")\n  {\n    const buff = Buffer.from(items[i].json.textHtml, 'utf-8');\n    result.html = buff.toString('base64');\n  }  */\n  \n//  console.log(result.html)\n  \n//  result.html64 = Buffer.from(result.html).toString('base64')\n  \n  result.metadata= items[i].json.metadata;\n  result.from= items[i].json.from;\n  result.to= items[i].json.to;\n  result.subject= items[i].json.subject;\n  \n  //console.log(items[i]); \n  //result.json = items[i].json;\n}\n\n// You can write logs to the browser console\nconsole.log('Done!');\n\nreturn [{json:result}];\n\n\nreturn items.map(item => {\n  return {\n    json: {\n      dataBase64: Buffer.from(item.json.data).toString('base64'),\n    }\n  }\n});\n"
      },
      "name": "Function",
      "type": "n8n-nodes-base.function",
      "typeVersion": 1,
      "position": [
        110,
        590
      ]
    },
    {
      "parameters": {},
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 1,
      "position": [
        -100,
        690
      ]
    },
    {
      "parameters": {
        "queue": "mail_incoming_queue",
        "options": {
          "arguments": {
            "argument": [
              {
                "key": "x-dead-letter-exchange"
              }
            ]
          },
          "durable": true,
          "headers": {
            "header": [
              {
                "key": "x-delay",
                "value": "7000"
              }
            ]
          }
        }
      },
      "name": "RabbitMQ",
      "type": "n8n-nodes-base.rabbitmq",
      "typeVersion": 1,
      "position": [
        330,
        590
      ],
      "credentials": {
        "rabbitmq": "RabbitMQ"
      }
    }
  ],
  "connections": {
    "IMAP Email": {
      "main": [
        [
          {
            "node": "Split Binary Data",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Split Binary Data": {
      "main": [
        [
          {
            "node": "adjuntos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "adjuntos": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Function": {
      "main": [
        [
          {
            "node": "RabbitMQ",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "Function",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {},
  "id": 7
}

Thanks

Hey @Christian_Garcia,

I tried your workflow and couldn’t replicate the issue. Which version of n8n are you using? If you’re not using the latest version, can you update and try on that?

Hey, thanks for your patience and help.

My version is 0.137.0 :frowning: I think is the last.