npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pixlcore/xyplug-imap-trigger

v1.0.0

Published

An IMAP email trigger plugin for the xyOps workflow automation system.

Readme

An IMAP trigger plugin for the xyOps Workflow Automation System. It watches an email mailbox on a schedule, launches a job when matching messages are found, and passes the parsed email data plus attachments into the job input.

Use it for inbound order processing, support queues, report ingestion, approval emails, document dropboxes, alert mailboxes, or any workflow where email arrival should start automation.

Features

  • Pure Node.js / npx plugin.
  • Works as a xyOps Trigger Plugin.
  • Polls any IMAP-compatible mailbox on the cadence of a normal xyOps schedule.
  • Defaults to unread messages with UNSEEN style behavior via IMAP search criteria.
  • Processes up to a configurable maximum number of messages per trigger run.
  • Always passes input.data.emails as an array to the launched job.
  • Downloads attachments and passes them to the launched job as normal xyOps input files.
  • Can optionally attach the raw .eml message for archival or forensic workflows.
  • Supports post-processing actions: mark as read, move to folder, delete, or leave unchanged.
  • Uses a xyOps Secret Vault variable for the IMAP password.

Requirements

  • Node.js and npx
  • Network access from the xyOps primary conductor host to your IMAP server

Secrets / Environment Variables

Create a Secret Vault in xyOps and assign this plugin to it. Add:

  • IMAP_PASSWORD

Enter the hostname and username directly in the plugin parameters.

Data Collection

This plugin does not collect, store, or transmit telemetry, analytics, or usage metrics. It only connects to the IMAP server you configure. Your email provider may log IMAP connections and mailbox actions according to its own policies.

How It Works

This is a schedule modifier. Add it alongside a normal xyOps schedule trigger, such as every minute, every five minutes, or hourly. The schedule decides when xyOps asks the plugin for a launch decision. This plugin then checks the configured mailbox and returns yes or no (along with the matched message data).

When matching email is found, the plugin:

  1. Downloads and parses up to Maximum Messages.
  2. Returns launch: true to trigger a job launch.
  3. Passes parsed email records in input.data.emails.
  4. Passes attachments as xyOps input files.
  5. Applies the selected post-processing action.

If no matching email is found, the job is not launched.

Parameters

| Parameter | Required | Description | |-----------|----------|-------------| | IMAP Hostname | Yes | IMAP server hostname. | | Username | Yes | IMAP username. | | Port | No | IMAP TCP port. Defaults to 993. | | Use TLS | No | Use IMAP over TLS. Enabled by default. | | Reject Unauthorized TLS Certs | No | Reject untrusted TLS certificates. Enabled by default. | | Timeout (sec) | No | Connection and socket timeout. Defaults to 30. | | Mailbox | No | Mailbox folder to poll. Defaults to INBOX. | | Search Criteria | No | IMAP search criteria as JSON. Defaults to { "seen": false }. | | Maximum Messages | No | Maximum matching messages to process in one run. Defaults to 1. | | Message Order | No | Process oldest or newest matching UIDs first. Defaults to oldest first. | | Download Attachments | No | Attach email attachments to the launched xyOps job. Enabled by default. | | Attach Raw Email | No | Also attach each raw .eml message. Disabled by default. | | Max Body Characters | No | Maximum characters for text and HTML bodies. Defaults to 250000; 0 means no limit. | | Post-Processing Action | No | Mark as Read, Move to Folder, Delete, or None. Defaults to Mark as Read. | | Move to Folder | Only for move | Destination mailbox for move action. The folder must already exist. |

Search Criteria

The default search criteria is:

{
	"seen": false
}

That means the plugin only processes unread messages. After a successful fetch and staging step, the default post-processing action marks those messages as read so they will not be picked up again.

You can customize the search criteria in the native JSON editor. Examples:

Unread messages from one sender:

{
	"seen": false,
	"from": "[email protected]"
}

Unread messages with a case-insensitive subject match:

{
	"seen": false,
	"subject": "Invoice"
}

Messages received since a date:

{
	"since": "2026-07-01"
}

Unread Gmail messages with a specific label:

{
	"seen": false,
	"labels": {
		"has": [ "Cool" ]
	}
}

For Gmail label searches like this, set Mailbox to [Gmail]/All Mail. Some Gmail labels are not exposed as IMAP folders unless they are enabled for IMAP in Gmail settings.

Post-Processing Choices

| Action | Behavior | |--------|----------| | Mark as Read | Adds the IMAP Seen flag after messages are staged. This is the safest default. | | Move to Folder | Moves processed messages to another mailbox folder, such as Processed. This is best for audit trails. | | Delete | Deletes processed messages from the mailbox. Use carefully. | | None | Leaves messages unchanged. Useful for testing, but will reprocess the same messages repeatedly. |

Output Summary

When email is found, the launched job receives:

  • input.data.emails: Array of parsed email records.
  • input.data.imap: Summary of the mailbox poll and post-processing action.
  • input.files: Attachment files, and optionally raw .eml files.

Each emails array entry includes common fields such as:

  • uid
  • messageId
  • subject
  • date
  • from
  • to
  • cc
  • replyTo
  • headers
  • text
  • html
  • files

The files array inside each email describes the files attached to the xyOps job. The actual files are passed through xyOps as normal input files for the launched job.

General Notes

  • This plugin does not create jobs by itself. It modifies launches from a normal schedule trigger.
  • Trigger Plugins run on the xyOps primary conductor server, so that server needs network access to your IMAP host.
  • For Gmail, Outlook, Yahoo, and similar providers, you may need an app-specific password or provider-specific IMAP settings.
  • For Gmail labels that are not exposed as IMAP folders, use [Gmail]/All Mail as the mailbox and filter by labels in the search criteria.
  • Move to Folder requires the destination mailbox to already exist.
  • None is useful while testing, but it usually needs strict search criteria to avoid repeated launches.
  • Delete is intentionally opt-in because it removes mail from the source mailbox.
  • The plugin applies the post-processing action after email data and files are staged, but before xyOps launches the downstream job.

Local Testing

When invoked by xyOps, the plugin expects a single JSON document on STDIN using the xyOps Wire Protocol. You can simulate this locally by piping JSON into node index.js.

Example test using an environment variable for the password:

echo '{"xy":1,"type":"trigger","items":[{"timezone":"America/Los_Angeles","now":1783180800,"dargs":{"year":2026,"month":7,"day":4,"weekday":6,"hour":9,"minute":0},"params":{"hostname":"imap.example.com","username":"[email protected]","mailbox":"INBOX","search_criteria":{"seen":false},"max_messages":2,"post_action":"mark_read","download_attachments":true},"job":{"id":"emexample","title":"Process Incoming Email"}}]}' | IMAP_PASSWORD=REPLACE_ME node index.js

Example test using the secrets object, which mirrors what xyOps provides:

{
	"xy": 1,
	"type": "trigger",
	"secrets": {
		"IMAP_PASSWORD": "REPLACE_ME"
	},
	"items": [
		{
			"timezone": "America/Los_Angeles",
			"now": 1783180800,
			"dargs": {
				"year": 2026,
				"month": 7,
				"day": 4,
				"weekday": 6,
				"hour": 9,
				"minute": 0
			},
			"params": {
				"hostname": "imap.example.com",
				"username": "[email protected]",
				"mailbox": "INBOX",
				"search_criteria": {
					"seen": false
				},
				"max_messages": 2,
				"order": "oldest",
				"download_attachments": true,
				"post_action": "mark_read"
			},
			"job": {
				"id": "emexample",
				"title": "Process Incoming Email"
			}
		}
	]
}

Run it like this:

cat sample.json | node index.js

Example response when no matching messages are present:

{
	"xy":1,
	"items": [
		{ "launch":false }
	]
}

Example response shape when a matching message is found:

{
	"xy": 1,
	"items": [
		{
			"launch": true,
			"data": {
				"emails": [
					{
						"mailbox": "INBOX",
						"uid": 101,
						"subject": "Daily Report",
						"from": {
							"name": "Reports",
							"address": "[email protected]"
						},
						"to": [
							{
								"name": "",
								"address": "[email protected]"
							}
						],
						"text": "Report attached.",
						"html": "",
						"files": [
							{
								"type": "attachment",
								"filename": "email-101-attachment-1-report.csv",
								"originalFilename": "report.csv",
								"mimeType": "text/csv",
								"size": 2048
							}
						]
					}
				],
				"imap": {
					"mailbox": "INBOX",
					"count": 1,
					"postAction": "mark_read",
					"moveFolder": ""
				}
			},
			"files": [
				{
					"path": "/tmp/xyplug-imap-example/email-101-attachment-1-report.csv",
					"delete": true
				}
			]
		}
	]
}

The real plugin output is compacted onto one line, as required by the xyOps Wire Protocol.

License

MIT