NAME

App::wsgetmail - Fetch mail from the cloud using webservices

SYNOPSIS

Run:

wsgetmail [options] --config=wsgetmail.json

where wsgetmail.json looks like:

{
"client_id": "abcd1234-xxxx-xxxx-xxxx-1234abcdef99",
"tenant_id": "abcd1234-xxxx-xxxx-xxxx-123abcde1234",
"secret": "abcde1fghij2klmno3pqrst4uvwxy5~0",
"global_access": 1,
"username": "rt-comment@example.com",
"folder": "Inbox",
"stripcr": 0,
"size_limit": 10485760,
"body_size_limit": 1048576,
"command": "/opt/rt5/bin/rt-mailgate",
"command_args": "--url=http://rt.example.com/ --queue=General --action=comment",
"command_timeout": 30,
"action_on_fetched": "mark_as_read"
}

Using App::wsgetmail as a library looks like:

my $getmail = App::wsgetmail->new({config => {
  # The config hashref takes all the same keys and values as the
  # command line tool configuration JSON.
}});
while (my $message = $getmail->get_next_message()) {
    $getmail->process_message($message)
      or warn "could not process $message->id";
}

DESCRIPTION

wsgetmail retrieves mail from a folder available through a web services API and delivers it to another system. Currently, it only knows how to retrieve mail from the Microsoft Graph API, and deliver it by running another command on the local system.

INSTALLATION

perl Makefile.PL
make
make test
sudo make install

wsgetmail will be installed under /usr/local/bin if you're using the system Perl, or in the same directory as perl if you built your own.

ATTRIBUTES

config

A hash ref that is passed to construct the mda and client (see below).

mda

An instance of App::wsgetmail::MDA created from our config object.

client_class

The name of the App::wsgetmail package used to construct the client. Default MS365.

client

An instance of the client_class created from our config object.

METHODS

process_message($message)

Given a Message object, retrieves the full message content, delivers it using the mda, and then executes the configured post-fetch action. Returns a boolean indicating success.

post_fetch_action($message)

Given a Message object, executes the configured post-fetch action. Returns a boolean indicating success.

CONFIGURATION

Configuring Microsoft 365 Client Access

To use wsgetmail, first you need to set up the app in Microsoft 365. Two authentication methods are supported:

This section walks you through each piece of configuration wsgetmail needs, and how to obtain it.

Configuring client secret authentication

We recommend you deploy wsgetmail by configuring it with a client secret. Client secrets can be granted limited access to only the mailboxes you choose. You can adjust or revoke wsgetmail's access without interfering with other applications.

Microsoft documents how to create a client secret in the "Register an application with the Microsoft identity platform" quickstart, under the section "Add a client secret." Take care to record the secret token when it appears; it will never be displayed again. It should look like a completely random string, not a UUID/GUID.

Configuring user+password authentication

If you do not want to use a client secret, you can also configure wsgetmail to authenticate with a traditional username+password combination. As noted above, this method is not recommended by Microsoft. It also does not work for systems with federated authentication enabled.

Configuring the mail delivery command

Now that you've configured wsgetmail to access a mail account, all that's left is configuring delivery. Set the following in your wsgetmail configuration file.

TESTING AND DEPLOYMENT

After you write your wsgetmail configuration file, you can test it by running:

wsgetmail --debug --dry-run --config=wsgetmail.json

This will read and deliver messages, but will not mark them as read or delete them. If there are any problems, those will be reported in the error output. You can update your configuration file and try again until wsgetmail runs successfully.

Once your configuration is stable, you can configure wsgetmail to run periodically through cron or a systemd service on a timer.

ERRORS AND DIAGNOSTIC MESSAGES

wsgetmail sends warning, error, and debug messages to STDERR, while purely informational messages are sent to STDOUT. Operators may want to capture both output streams as a merged stream for diagnostic purposes. For example:

wsgetmail --debug --dry-run --config=wsgetmail.json > wsgetmail.debug 2>&1

When the mail processing command exits with an error (non-zero) status the action_on_fetched is not performed on that message so that it will be processed on the next run.

Full output of the processing command is produced with --debug.

LIMITATIONS

Fetching from Multiple Folders

wsgetmail can only read from a single folder each time it runs. If you need to read multiple folders (possibly spanning different accounts), then you need to run it multiple times with different configuration.

If you only need to change a couple small configuration settings like the folder name, you can use the --options argument to override those from a base configuration file. For example:

wsgetmail --config=wsgetmail.json --options='{"folder": "Inbox"}'
wsgetmail --config=wsgetmail.json --options='{"folder": "Other Folder"}'

NOTE: Setting secret or user_password with --options is not secure and may expose your credentials to other users on the local system. If you need to set these options, or just change a lot of settings in your configuration, just run wsgetmail with different configurations:

wsgetmail --config=account01.json
wsgetmail --config=account02.json

Office 365 API Limits

Microsoft applies some limits to the amount of API requests allowed as documented in their Microsoft Graph throttling guidance. If you reach a limit, requests to the API will start failing with HTTP status code 429 for a period of time.

Office 365 API Errors

Best Practical Solutions has observed that very rarely the Microsoft Graph API will return a 5xx error code when attempting to list mail folder details, retrieve the message list, fetch message details, or delete a message. The cause for this is currently unknown, except that it is not related to the API limits mentioned above.

Despite the relative rarity, if you run wsgetmail often enough you can see this multiple times in a typical day.

Therefore, by default wsgetmail now ignores 5xx response codes on all API calls, instead treating them as logically empty success response.

SEE ALSO

AUTHOR

Best Practical Solutions, LLC modules@bestpractical.com

LICENSE AND COPYRIGHT

This software is Copyright (c) 2015-2026 by Best Practical Solutions, LLC.

This is free software, licensed under:

The GNU General Public License, Version 2, June 1991