Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add lsimap troubleshooting tool #330

Merged
merged 1 commit into from
Nov 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
# Ignore binaries at root of repo (often generated here when testing)
/check_imap_mailbox
/list-emails
/lsimap

# Help prevent accidentally including this credentials file in the repo
/accounts.ini
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
SHELL = /bin/bash

# Space-separated list of cmd/BINARY_NAME directories to build
WHAT = check_imap_mailbox list-emails
WHAT = check_imap_mailbox list-emails lsimap

# TODO: This will need to be standardized across all cmd files in order to
# work as intended.
Expand Down
94 changes: 90 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Various tools used to monitor mail services
- [Features](#features)
- [`check_imap_mailbox`](#check_imap_mailbox)
- [`list-emails`](#list-emails)
- [`lsimap`](#lsimap)
- [Requirements](#requirements)
- [Building source code](#building-source-code)
- [Running](#running)
Expand All @@ -32,13 +33,16 @@ Various tools used to monitor mail services
- [Configuration file](#configuration-file)
- [Settings](#settings)
- [Usage](#usage)
- [`lsimap`](#lsimap-1)
- [Command-line arguments](#command-line-arguments-2)
- [Examples](#examples)
- [`check_imap_mailbox`](#check_imap_mailbox-2)
- [As a Nagios plugin](#as-a-nagios-plugin)
- [Login failure](#login-failure)
- [`list-emails`](#list-emails-2)
- [No options](#no-options)
- [Alternate locations for config file, log and report directories](#alternate-locations-for-config-file-log-and-report-directories)
- [`lsimap`](#lsimap-2)
- [License](#license)
- [References](#references)

Expand All @@ -51,10 +55,11 @@ submit improvements for review and potential inclusion into the project.

This repo contains various tools used to monitor mail services.

| Tool Name | Overall Status | Description |
| -------------------- | -------------- | ---------------------------------------------------------- |
| `check_imap_mailbox` | Stable | Nagios plugin used to monitor mailboxes for items |
| `list-emails` | Stable | Small CLI app used to generate listing of mailbox contents |
| Tool Name | Overall Status | Description |
| -------------------- | -------------- | ------------------------------------------------------------------------ |
| `check_imap_mailbox` | Stable | Nagios plugin used to monitor mailboxes for items |
| `list-emails` | Stable | Small CLI app used to generate listing of mailbox contents |
| `lsimap` | Alpha | Small CLI tool to list advertised capabilities for specified IMAP server |

## Features

Expand Down Expand Up @@ -102,6 +107,21 @@ This repo contains various tools used to monitor mail services.
- the intent is to help prevent MySQL errors when posting summary reports
- e.g., `ERROR 1366 (22007): Incorrect string value`

### `lsimap`

- Quick one-off tool to list advertised capabilities for specified IMAP server
- Leveled logging
- `console writer`: human-friendly, colorized output
- choice of `disabled`, `panic`, `fatal`, `error`, `warn`, `info` (the
default), `debug` or `trace`
- enable `debug` level to monitor submitted IMAP commands and received IMAP
server responses
- TLS IMAP4 connectivity
- port defaults to 993/tcp
- network type defaults to either of IPv4 and IPv6, but optionally limited
to IPv4-only or IPv6-only
- user-specified minimum TLS version

## Requirements

The following is a loose guideline. Other combinations of Go and operating
Expand Down Expand Up @@ -288,6 +308,24 @@ You may also place the file wherever you like and refer to it using the
`-config-file` (full-length flag name). See the [Examples](#examples) and
[Command-line arguments](#command-line-arguments) sections for usage details.

### `lsimap`

#### Command-line arguments

- Flags marked as **`required`** must be set via CLI flag.
- Flags *not* marked as required are for settings where a useful default is
already defined.

| Option | Required | Default | Repeat | Possible | Description |
| --------------- | -------- | -------------- | ------ | ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `h`, `help` | No | | No | `-h`, `--help` | Generate listing of all valid command-line options and applicable (short) guidance for using them. |
| `server` | Yes | *empty string* | No | *valid FQDN or IP Address* | The fully-qualified domain name of the remote mail server. |
| `port` | No | `993` | No | *valid IMAP TCP port* | TCP port used to connect to the remote mail server. This is usually the same port used for TLS encrypted IMAP connections. |
| `net-type` | No | `auto` | No | `auto`, `tcp4`, `tcp6` | Limits network connections to remote mail servers to one of the specified types. |
| `min-tls` | No | `tls12` | No | `tls10`, `tls11`, `tls12`, `tls13` | Limits version of TLS used for connections to remote mail servers. |
| `logging-level` | No | `info` | No | `disabled`, `panic`, `fatal`, `error`, `warn`, `info`, `debug`, `trace` | Sets log level. |
| `version` | No | `false` | No | `true`, `false` | Whether to display application version and then immediately exit application |

## Examples

### `check_imap_mailbox`
Expand Down Expand Up @@ -351,6 +389,54 @@ Checking account: email2
OK: Successfully generated reports for accounts: [email protected], [email protected]
```

### `lsimap`

Quick listings for outlook.office365.com and imap.gmail.com.

This tool can be useful for determining at a glance what authentication
mechanisms are supported by an IMAP server.

```console
$ ./lsimap --server outlook.office365.com
6:10AM INF cmd\lsimap\main.go:61 > Connection established to server
6:10AM INF cmd\lsimap\main.go:70 > Gathering pre-login capabilities
6:10AM INF cmd\lsimap\main.go:87 > Capability: AUTH=PLAIN
6:10AM INF cmd\lsimap\main.go:87 > Capability: AUTH=XOAUTH2
6:10AM INF cmd\lsimap\main.go:87 > Capability: CHILDREN
6:10AM INF cmd\lsimap\main.go:87 > Capability: ID
6:10AM INF cmd\lsimap\main.go:87 > Capability: IDLE
6:10AM INF cmd\lsimap\main.go:87 > Capability: IMAP4
6:10AM INF cmd\lsimap\main.go:87 > Capability: IMAP4rev1
6:10AM INF cmd\lsimap\main.go:87 > Capability: LITERAL+
6:10AM INF cmd\lsimap\main.go:87 > Capability: MOVE
6:10AM INF cmd\lsimap\main.go:87 > Capability: NAMESPACE
6:10AM INF cmd\lsimap\main.go:87 > Capability: SASL-IR
6:10AM INF cmd\lsimap\main.go:87 > Capability: UIDPLUS
6:10AM INF cmd\lsimap\main.go:87 > Capability: UNSELECT
6:10AM INF cmd\lsimap\main.go:95 > Connection to server closed

$ ./lsimap --server imap.gmail.com
6:10AM INF cmd\lsimap\main.go:61 > Connection established to server
6:10AM INF cmd\lsimap\main.go:70 > Gathering pre-login capabilities
6:10AM INF cmd\lsimap\main.go:87 > Capability: AUTH=OAUTHBEARER
6:10AM INF cmd\lsimap\main.go:87 > Capability: AUTH=PLAIN
6:10AM INF cmd\lsimap\main.go:87 > Capability: AUTH=PLAIN-CLIENTTOKEN
6:10AM INF cmd\lsimap\main.go:87 > Capability: AUTH=XOAUTH
6:10AM INF cmd\lsimap\main.go:87 > Capability: AUTH=XOAUTH2
6:10AM INF cmd\lsimap\main.go:87 > Capability: CHILDREN
6:10AM INF cmd\lsimap\main.go:87 > Capability: ID
6:10AM INF cmd\lsimap\main.go:87 > Capability: IDLE
6:10AM INF cmd\lsimap\main.go:87 > Capability: IMAP4rev1
6:10AM INF cmd\lsimap\main.go:87 > Capability: NAMESPACE
6:10AM INF cmd\lsimap\main.go:87 > Capability: QUOTA
6:10AM INF cmd\lsimap\main.go:87 > Capability: SASL-IR
6:10AM INF cmd\lsimap\main.go:87 > Capability: UNSELECT
6:10AM INF cmd\lsimap\main.go:87 > Capability: X-GM-EXT-1
6:10AM INF cmd\lsimap\main.go:87 > Capability: XLIST
6:10AM INF cmd\lsimap\main.go:87 > Capability: XYZZY
6:10AM INF cmd\lsimap\main.go:95 > Connection to server closed
```

## License

From the [LICENSE](LICENSE) file:
Expand Down
1 change: 1 addition & 0 deletions cmd/check_imap_mailbox/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func main() {

return
}
logger.Debug().Msg("Connection established to server")

if loginErr := mbxs.Login(c, account.Username, account.Password, logger); loginErr != nil {
logger.Error().Err(loginErr).Msg("Login error occurred")
Expand Down
1 change: 1 addition & 0 deletions cmd/list-emails/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func main() {

return
}
logger.Info().Msg("Connection established to server")

if loginErr := mbxs.Login(c, account.Username, account.Password, logger); loginErr != nil {
logger.Error().Err(loginErr).Msg("failed to login to server")
Expand Down
18 changes: 18 additions & 0 deletions cmd/lsimap/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2022 Adam Chalkley
//
// https://github.com/atc0005/check-mail
//
// Licensed under the MIT License. See LICENSE file in the project root for
// full license information.

// Small CLI tool to list advertised capabilities for specified IMAP server.
//
// See our [GitHub repo]:
//
// - to review documentation (including examples)
// - for the latest code
// - to file an issue or submit improvements for review and potential
// inclusion into the project
//
// [GitHub repo]: https://github.com/atc0005/check-mail
package main
98 changes: 98 additions & 0 deletions cmd/lsimap/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// Copyright 2022 Adam Chalkley
//
// https://github.com/atc0005/check-mail
//
// Licensed under the MIT License. See LICENSE file in the project root for
// full license information.

//go:generate go-winres make --product-version=git-tag --file-version=git-tag

package main

import (
"errors"
"fmt"
"os"
"sort"

"github.com/atc0005/check-mail/internal/config"
"github.com/atc0005/check-mail/internal/mbxs"
"github.com/rs/zerolog"
)

func main() {

// Setup configuration by parsing user-provided flags
cfg, cfgErr := config.New(config.AppType{InspectorIMAPCaps: true})
switch {
case errors.Is(cfgErr, config.ErrVersionRequested):
fmt.Println(config.Version())

return

case cfgErr != nil:

// We make some assumptions when setting up our logger as we do not
// have a working configuration based on sysadmin-specified choices.
consoleWriter := zerolog.ConsoleWriter{Out: os.Stderr}
logger := zerolog.New(consoleWriter).With().Timestamp().Caller().Logger()

logger.Err(cfgErr).Msg("Error initializing application")

return
}

logger := cfg.Log.With().Logger()

// We're reusing the common "Accounts" field (and flags) in order to
// obtain specified server and port values vs adding standalone fields and
// flags; this is effectively a loop of 1 iteration (at least for now). At
// some point we may expand the scope of this tool to handle evaluating
// mail servers for a collection of accounts, so using a workflow intended
// for collections is probably appropriate.
for _, account := range cfg.Accounts {

// Open connection to IMAP server
c, err := mbxs.Connect(account.Server, account.Port, cfg.NetworkType, cfg.MinTLSVersion(), logger)
if err != nil {
logger.Error().Err(err).Msg("error connecting to server")
os.Exit(1)
}
logger.Info().Msg("Connection established to server")

// Enable client network command/response logging if global logging
// level indicates user wishes to see verbose details.
if zerolog.GlobalLevel() == zerolog.DebugLevel ||
zerolog.GlobalLevel() == zerolog.TraceLevel {
c.SetDebug(&logger)
}

logger.Info().Msg("Gathering pre-login capabilities")
capabilities, err := c.Capability()
if err != nil {
logger.Error().Err(err).Msg("Unable to list server capabilities")
os.Exit(1)
}

caps := make([]string, 0, len(capabilities))
for k, v := range capabilities {
if v {
caps = append(caps, k)
}
}

sort.Strings(caps)
// logger.Info().Msgf("Capabilities: %v", caps)
for _, capability := range caps {
logger.Info().Msgf("Capability: %v", capability)
}

logger.Debug().Msg("Closing connection to server")
if err := c.Logout(); err != nil {
logger.Error().Err(err).Msg("failed to close connection to server")
os.Exit(1)
}
logger.Info().Msg("Connection to server closed")

}
}
53 changes: 53 additions & 0 deletions cmd/lsimap/winres/winres.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"RT_MANIFEST": {
"#1": {
"0409": {
"identity": {
"name": "",
"version": ""
},
"description": "Small CLI tool to list advertised capabilities for specified IMAP server",
"minimum-os": "win7",
"execution-level": "as invoker",
"ui-access": false,
"auto-elevate": false,
"dpi-awareness": "system",
"disable-theming": false,
"disable-window-filtering": false,
"high-resolution-scrolling-aware": false,
"ultra-high-resolution-scrolling-aware": false,
"long-path-aware": false,
"printer-driver-isolation": false,
"gdi-scaling": false,
"segment-heap": false,
"use-common-controls-v6": false
}
}
},
"RT_VERSION": {
"#1": {
"0000": {
"fixed": {
"file_version": "0.0.0.0",
"product_version": "0.0.0.0"
},
"info": {
"0409": {
"Comments": "Part of the atc0005/check-mail project",
"CompanyName": "github.com/atc0005",
"FileDescription": "Small CLI tool to list advertised capabilities for specified IMAP server",
"FileVersion": "",
"InternalName": "lsimap",
"LegalCopyright": "© Adam Chalkley. Licensed under MIT.",
"LegalTrademarks": "",
"OriginalFilename": "main.go",
"PrivateBuild": "",
"ProductName": "check-mail",
"ProductVersion": "",
"SpecialBuild": ""
}
}
}
}
}
}
9 changes: 9 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,15 @@ type AppType struct {
//
// Basic Authentication is used to login.
ReporterIMAPMailboxBasicAuth bool

// InspectorIMAPCaps represents an application used for one-off or
// isolated checks of an IMAP server's advertised capabilities.
//
// Unlike a monitoring plugin which is focused on specific attributes
// resulting in a severity-based outcome, an Inspector application is
// intended for examining a small set of targets for
// informational/troubleshooting purposes.
InspectorIMAPCaps bool
}

// MailAccount represents an email account listed within a configuration file.
Expand Down
10 changes: 8 additions & 2 deletions internal/config/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ func (c *Config) handleFlagsConfig(appType AppType) {
flag.StringVar(&c.NetworkType, "net-type", defaultNetworkType, networkTypeFlagHelp)
flag.StringVar(&c.minTLSVersion, "min-tls", defaultMinTLSVersion, minTLSVersionFlagHelp)

// currently only applies to list-emails app, don't expose to Nagios plugin
// Only applies to Reporter app
if appType.ReporterIMAPMailboxBasicAuth {
flag.StringVar(&c.ConfigFile, "config-file", defaultINIConfigFileName, iniConfigFileFlagHelp)
flag.StringVar(&c.ReportFileOutputDir, "report-file-dir", defaultReportFileOutputDir, reportFileOutputDirFlagHelp)
flag.StringVar(&c.LogFileOutputDir, "log-file-dir", defaultLogFileOutputDir, logFileOutputDirFlagHelp)
}

// currently only applies to Nagios plugin
// Inspector app
if appType.InspectorIMAPCaps {
flag.StringVar(&account.Server, "server", defaultServer, serverFlagHelp)
flag.IntVar(&account.Port, "port", defaultPort, portFlagHelp)
}

// Basic Auth Plugin
if appType.PluginIMAPMailboxBasicAuth {
flag.Var(&account.Folders, "folders", foldersFlagHelp)
flag.StringVar(&account.Username, "username", defaultUsername, usernameFlagHelp)
Expand Down
Loading