mailbot

3.1.1 • Public • Published

MailBot

This module will help you build an imap bot reacting to incoming emails.

You mainly provide two functions:

  • A trigger which will be called for each received e-mail and should return a promise of a truthy if mail should trigger some job
  • A mailHandler which will be called for each triggered e-mail and will do its job

Warning: Missing tests

There are actually no test because I found a bit too time-consuming to mock an Imap server for testing. They will come later.

Installation

npm install --save mailbot

Usage

const { createBot } = require('mailbot')
 
const bot = createBot(options)
 
bot.start()

API

// Start watching, returns a Promise
bot.start()
 
// Stops watching, returns a Promise
// if argument is true, it will destroy the connection immediately
// you're strongly advised to gracefully disconnect by not setting this parameter
bot.stop(destroy = false)
 
// Restarts
bot.restart(destroy = false)
 
// Update configuration option
// Note: if you update 'imap', 'mailbox', or 'filter', it will restart the bot
// unless said otherwise
bot.configure('imap', connectionInfo, autoRestart = true, destroy = false)

Options

{
 
// IMAP configuration, see module "imap"
imap: {
    user: "user@gmail.com",
    password: "password",
    host: "imap.googlemail.com",
    port: 993,
    keepalive: true,
    tls: true,
    tlsOptions: {
        rejectUnauthorized: false
    },
},
 
// Watched inbox
mailbox: 'INBOX',
 
// Should bot mark fetched emails as read?
// If true, you're sure you will never fetch same mail twice even when restarting
// If false, you'll mess with server emails
markSeen: true,
 
// Search filter to fetch emails
filter: ['UNSEEN'],
 
// Should the trigger be checked when receiving headers, or when body has been parsed?
// If your control depends only on headers (subject, recipient, sender…), you can set it to true
// Warning: in 'headers' phase, headers are not parsed yet and you may need helpers
triggerOnHeaders: false,
 
// The trigger: this function is called for each e-mail
// Input: a mail object (if triggerOnHeaders is true, it will only have 'headers' property)
// Output: a value or a promise of a value
// The mail will be "handled" only if final value is truthy
trigger ({ headers }) {
    // Example: work with e-mails whose subject is 'BOT: <something>'
    const match = headers.subject.match(/BOT: (.*)$/)
    return match && match[1]
},
 
// The mail handler: this is the "job executor"
// Input: a mail object, and the trigger value
mailHandler (mail, trigger) {
    console.log({
        subject: mail.headers.subject,
        trigger
    })
},
 
// The error handler, called for each error occurring during processes
// As there may be error thrown from very different places,
// the function is called with a "context", which can be one of:
// - 'IMAP_ERROR': global error
// - 'SEARCH': failed searching or fetching mails
// - 'TRIGGER': when trying to calculate trigger result (*)
// - 'MAIL': when trying to handle mail (*)
// (*) in those cases the third parameter will be a complete mail object
// allowing you to access sender, subject, etc…
errorHandler (error, context, mail) {
    console.error(context, error)
    if (mail) {
        sendErrorMailTo(mail.from)
    }
},
 
// IMAP client reconnection
autoReconnect: true,
autoReconnectTimeout: 5000,
 
// false: attachments contents will be directly accessible as Buffer in 'content' property
// true: attachments will be streamed via 'stream' property
// Note: you can safely set it to false if you use triggerOnHeaders, otherwise you should work with streams
streamAttachments: true,
 
// If true, mail.text will not contain signature
// Properties 'textSignature' and 'textOriginal' will be added
removeTextSignature: true,
 
// If true, if embedded images are found in signature of mail.html
// they will be dropped from 'attachments' and moved to 'ignoredAttachments'
ignoreAttachmentsInSignature: true,
 
// If true, property 'cleanSubject' will contain the subject without all messy prefixes
cleanSubject: true,
 
// Set to a strictly positive number to define period (milliseconds) between automatic search
// Note that this delay starts AFTER a batch has been handled
// Any falsey value will disable periodic search
searchPeriod: false,
 
}

Mail objects

Mail objects are generated by mailparser (version 0.x, not the buggy 2.0): see full description of parsed mail object.

Following custom properties are added:

  • ignoredAttachments
  • textSignature
  • textOriginal
  • cleanSubject

Helpers

parse addresses in raw headers

Working with triggerOnHeaders: true is interesting for performance purpose, but you get unparsed headers. This function will help you working with to/cc/bcc headers:

{
    triggerOnHeaders: true,
    trigger: ({ headers }) => {
        console.log(headers.to) // "Bob" <bob@a.b>
        parseAddresses(headers)
        console.log(headers.to) // [ { address: 'bob@a.b', raw: '"Bob" <bob@a.b>', phrase: '"Bob"' } ]
    }
}

Extract signature from text body

This function will help you remove signature from e-mail body, using talon:

const { text, signature } = extractSignature(mail.text)

Strip HTML tags

This function will remove any HTML tag from a string, using striptags internally:

const text = stripTags(mail.html)

Debugging

This module uses debug internally, and you can enable internal debug messages adding mailbot to your environment variable DEBUG:

env DEBUG=mailbot node mybot.js

Full sample

See sample.js in repository: it's a mail bot which will react on every mail which subject starts with 'upload to …'. It will fetch all attachments and save it to <upload dir>/<sender address>/<requested path>.

This illustrates how you can easily create that type of bot.

Readme

Keywords

Package Sidebar

Install

npm i mailbot

Weekly Downloads

0

Version

3.1.1

License

MIT

Last publish

Collaborators

  • naholyr