{"id":19648144,"url":"https://github.com/bestpractical/app-wsgetmail","last_synced_at":"2025-08-15T18:45:03.112Z","repository":{"id":66697540,"uuid":"265543023","full_name":"bestpractical/app-wsgetmail","owner":"bestpractical","description":null,"archived":false,"fork":false,"pushed_at":"2025-04-17T13:10:07.000Z","size":872,"stargazers_count":11,"open_issues_count":0,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-07-01T13:07:11.948Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://metacpan.org/release/app-wsgetmail","language":"Perl","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bestpractical.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-05-20T11:24:25.000Z","updated_at":"2025-04-17T13:09:59.000Z","dependencies_parsed_at":"2023-12-08T00:21:57.260Z","dependency_job_id":"77af4976-193c-478b-afab-1eba84b4fc93","html_url":"https://github.com/bestpractical/app-wsgetmail","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/bestpractical/app-wsgetmail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bestpractical%2Fapp-wsgetmail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bestpractical%2Fapp-wsgetmail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bestpractical%2Fapp-wsgetmail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bestpractical%2Fapp-wsgetmail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bestpractical","download_url":"https://codeload.github.com/bestpractical/app-wsgetmail/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bestpractical%2Fapp-wsgetmail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270616222,"owners_count":24617107,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-15T02:00:12.559Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T14:47:16.207Z","updated_at":"2025-08-15T18:45:03.043Z","avatar_url":"https://github.com/bestpractical.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nApp::wsgetmail - Fetch mail from the cloud using webservices\n\n# SYNOPSIS\n\nRun:\n\n    wsgetmail [options] --config=wsgetmail.json\n\nwhere `wsgetmail.json` looks like:\n\n    {\n    \"client_id\": \"abcd1234-xxxx-xxxx-xxxx-1234abcdef99\",\n    \"tenant_id\": \"abcd1234-xxxx-xxxx-xxxx-123abcde1234\",\n    \"secret\": \"abcde1fghij2klmno3pqrst4uvwxy5~0\",\n    \"global_access\": 1,\n    \"username\": \"rt-comment@example.com\",\n    \"folder\": \"Inbox\",\n    \"stripcr\": 0,\n    \"command\": \"/opt/rt5/bin/rt-mailgate\",\n    \"command_args\": \"--url=http://rt.example.com/ --queue=General --action=comment\",\n    \"command_timeout\": 30,\n    \"action_on_fetched\": \"mark_as_read\"\n    }\n\nUsing App::wsgetmail as a library looks like:\n\n    my $getmail = App::wsgetmail-\u003enew({config =\u003e {\n      # The config hashref takes all the same keys and values as the\n      # command line tool configuration JSON.\n    }});\n    while (my $message = $getmail-\u003eget_next_message()) {\n        $getmail-\u003eprocess_message($message)\n          or warn \"could not process $message-\u003eid\";\n    }\n\n# DESCRIPTION\n\nwsgetmail retrieves mail from a folder available through a web services API\nand delivers it to another system. Currently, it only knows how to retrieve\nmail from the Microsoft Graph API, and deliver it by running another command\non the local system.\n\n# INSTALLATION\n\n    perl Makefile.PL\n    make\n    make test\n    sudo make install\n\n`wsgetmail` will be installed under `/usr/local/bin` if you're using the\nsystem Perl, or in the same directory as `perl` if you built your own.\n\n# ATTRIBUTES\n\n## config\n\nA hash ref that is passed to construct the `mda` and `client` (see below).\n\n## mda\n\nAn instance of [App::wsgetmail::MDA](https://metacpan.org/pod/App%3A%3Awsgetmail%3A%3AMDA) created from our `config` object.\n\n## client\\_class\n\nThe name of the App::wsgetmail package used to construct the\n`client`. Default `MS365`.\n\n## client\n\nAn instance of the `client_class` created from our `config` object.\n\n# METHODS\n\n## process\\_message($message)\n\nGiven a Message object, retrieves the full message content, delivers it\nusing the `mda`, and then executes the configured post-fetch\naction. Returns a boolean indicating success.\n\n## post\\_fetch\\_action($message)\n\nGiven a Message object, executes the configured post-fetch action. Returns a\nboolean indicating success.\n\n# CONFIGURATION\n\n## Configuring Microsoft 365 Client Access\n\nTo use wsgetmail, first you need to set up the app in Microsoft 365.\nTwo authentication methods are supported:\n\n- Client Credentials\n\n    This method uses shared secrets and is preferred by Microsoft.\n    (See [Client credentials](https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#client-credentials))\n\n- Username/password\n\n    This method is more like previous connections via IMAP. It is currently\n    supported by Microsoft, but not recommended. (See [Username/password](https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#usernamepassword))\n\nThis section walks you through each piece of configuration wsgetmail needs,\nand how to obtain it.\n\n- tenant\\_id\n\n    wsgetmail authenticates to an Azure Active Directory (AD) tenant. This\n    tenant is identified by an identifier that looks like a UUID/GUID: it should\n    be mostly alphanumeric, with dividing dashes in the same places as shown in\n    the example configuration above. Microsoft documents how to find your tenant\n    ID, and create a tenant if needed, in the [\"Set up a tenant\"\n    quickstart](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-create-new-tenant). Save\n    this as the `tenant_id` string in your wsgetmail configuration file.\n\n- client\\_id\n\n    You need to register wsgetmail as an application in your Azure Active\n    Directory tenant. Microsoft documents how to do this in the [\"Register an\n    application with the Microsoft identity platform\"\n    quickstart](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#register-an-application),\n    under the section \"Register an application.\" When asked who can use this\n    application, you can leave that at the default \"Accounts in this\n    organizational directory only (Single tenant).\"\n\n    After you successfully register the wsgetmail application, its information\n    page in your Azure account will display an \"Application (client) ID\" in the\n    same UUID/GUID format as your tenant ID. Save this as the `client_id`\n    string in your configuration file.\n\n    After that is done, you need to grant wsgetmail permission to access the\n    Microsoft Graph mail APIs. Microsoft documents how to do this in the\n    [\"Configure a client application to access a web API\"\n    quickstart](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#application-permission-to-microsoft-graph),\n    under the section \"Add permissions to access Microsoft Graph.\" When selecting\n    the type of permissions, select \"Application permissions.\" When prompted to\n    select permissions, select all of the following:\n\n    - Mail.Read\n    - Mail.Read.Shared\n    - Mail.ReadWrite\n    - Mail.ReadWrite.Shared\n    - openid\n    - User.Read\n\n### Configuring client secret authentication\n\nWe recommend you deploy wsgetmail by configuring it with a client\nsecret. Client secrets can be granted limited access to only the mailboxes\nyou choose. You can adjust or revoke wsgetmail's access without interfering\nwith other applications.\n\nMicrosoft documents how to create a client secret in the [\"Register an\napplication with the Microsoft identity platform\"\nquickstart](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app#add-a-client-secret),\nunder the section \"Add a client secret.\" Take care to record the secret\ntoken when it appears; it will never be displayed again. It should look like\na completely random string, not a UUID/GUID.\n\n- global\\_access\n\n    Set this to `1` in your wsgetmail configuration file.\n\n- secret\n\n    Set this to the secret token string you recorded earlier in your wsgetmail\n    configuration file.\n\n- username\n\n    wsgetmail will fetch mail from this user's account. Set this to an email\n    address string in your wsgetmail configuration file.\n\n### Configuring user+password authentication\n\nIf you do not want to use a client secret, you can also configure wsgetmail\nto authenticate with a traditional username+password combination. As noted\nabove, this method is not recommended by Microsoft. It also does not work\nfor systems with federated authentication enabled.\n\n- global\\_access\n\n    Set this to `0` in your wsgetmail configuration file.\n\n- username\n\n    wsgetmail will authenticate as this user. Set this to an email address\n    string in your wsgetmail configuration file.\n\n- user\\_password\n\n    Set this to the password string for `username` in your wsgetmail\n    configuration file.\n\n## Configuring the mail delivery command\n\nNow that you've configured wsgetmail to access a mail account, all that's\nleft is configuring delivery. Set the following in your wsgetmail\nconfiguration file.\n\n- folder\n\n    Set this to the name string of a mail folder to read.\n\n- stripcr\n\n    Set this to 1 to make wsgetmail convert the messages from the CRLF\n    line-ending encoding to the LF line-ending encoding.\n\n    This emulates the fetchmail option of the same name, which enabled\n    the stripcr option if an MDA was declared. The feature is similar,\n    but you need to enable it explicitly in your configuration.\n\n    This option is helpful if you are forwarding email to a Linux\n    utility that doesn't work with CRLF line-endings.\n\n- command\n\n    Set this to an executable command. You can specify an absolute path,\n    or a plain command name which will be found from `$PATH`. For each\n    email wsgetmail retrieves, it will run this command and pass the\n    message data to it via standard input.\n\n- command\\_args\n\n    Set this to a string with additional arguments to pass to `command`.\n    These arguments follow shell quoting rules: you can escape characters\n    with a backslash, and denote a single string argument with single or\n    double quotes.\n\n- command\\_timeout\n\n    Set this to the number of seconds the `command` has to return before\n    timeout is reached.  The default value is 30.  Use \"inf\" for no timeout.\n\n- action\\_on\\_fetched\n\n    Set this to a literal string `\"mark_as_read\"` or `\"delete\"`.\n    For each email wsgetmail retrieves, after the configured delivery\n    command succeeds, it will take this action on the message.\n\n    If you set this to `\"mark_as_read\"`, wsgetmail will only retrieve and\n    deliver messages that are marked unread in the configured folder, so it does\n    not try to deliver the same email multiple times.\n\n- dump\\_messages\n\n    Set this to 1 to preserve the temporary files after processing.\n\n    When `\"debug\"` is also set the filenames will be reported on STDERR.\n\n# TESTING AND DEPLOYMENT\n\nAfter you write your wsgetmail configuration file, you can test it by running:\n\n    wsgetmail --debug --dry-run --config=wsgetmail.json\n\nThis will read and deliver messages, but will not mark them as read or\ndelete them. If there are any problems, those will be reported in the error\noutput. You can update your configuration file and try again until wsgetmail\nruns successfully.\n\nOnce your configuration is stable, you can configure wsgetmail to run\nperiodically through cron or a systemd service on a timer.\n\n# ERRORS AND DIAGNOSTIC MESSAGES\n\nwsgetmail sends warning, error, and debug messages to STDERR, while purely\ninformational messages are sent to STDOUT.  Operators may want to capture both\noutput streams as a merged stream for diagnostic purposes.  For example:\n\n    wsgetmail --debug --dry-run --config=wsgetmail.json \u003e wsgetmail.debug 2\u003e\u00261\n\nWhen the mail processing command exits with an error (non-zero) status the\naction\\_on\\_fetched is not performed on that message so that it will be processed\non the next run.\n\nFull output of the processing command is produced with `--debug`.\n\n# LIMITATIONS\n\n## Fetching from Multiple Folders\n\nwsgetmail can only read from a single folder each time it runs. If you need\nto read multiple folders (possibly spanning different accounts), then you\nneed to run it multiple times with different configuration.\n\nIf you only need to change a couple small configuration settings like the\nfolder name, you can use the `--options` argument to override those from a\nbase configuration file. For example:\n\n    wsgetmail --config=wsgetmail.json --options='{\"folder\": \"Inbox\"}'\n    wsgetmail --config=wsgetmail.json --options='{\"folder\": \"Other Folder\"}'\n\nNOTE: Setting `secret` or `user_password` with `--options` is not secure\nand may expose your credentials to other users on the local system. If you\nneed to set these options, or just change a lot of settings in your\nconfiguration, just run wsgetmail with different configurations:\n\n    wsgetmail --config=account01.json\n    wsgetmail --config=account02.json\n\n## Office 365 API Limits\n\nMicrosoft applies some limits to the amount of API requests allowed as\ndocumented in their [Microsoft Graph throttling guidance](https://docs.microsoft.com/en-us/graph/throttling).\nIf you reach a limit, requests to the API will start failing for a period\nof time.\n\n# SEE ALSO\n\n- [wsgetmail](https://metacpan.org/pod/wsgetmail)\n- [App::wsgetmail::MDA](https://metacpan.org/pod/App%3A%3Awsgetmail%3A%3AMDA)\n- [App::wsgetmail::MS365](https://metacpan.org/pod/App%3A%3Awsgetmail%3A%3AMS365)\n- [App::wsgetmail::MS365::Message](https://metacpan.org/pod/App%3A%3Awsgetmail%3A%3AMS365%3A%3AMessage)\n\n# AUTHOR\n\nBest Practical Solutions, LLC \u003cmodules@bestpractical.com\u003e\n\n# LICENSE AND COPYRIGHT\n\nThis software is Copyright (c) 2015-2022 by Best Practical Solutions, LLC.\n\nThis is free software, licensed under:\n\nThe GNU General Public License, Version 2, June 1991\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbestpractical%2Fapp-wsgetmail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbestpractical%2Fapp-wsgetmail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbestpractical%2Fapp-wsgetmail/lists"}