pax_global_header00006660000000000000000000000064130371667100014516gustar00rootroot0000000000000052 comment=b0c97f2d264baf9d2441c31aed832bbc12d4a4f4 mailexporter-1.0/000077500000000000000000000000001303716671000140715ustar00rootroot00000000000000mailexporter-1.0/README.md000066400000000000000000000064601303716671000153560ustar00rootroot00000000000000# Mailexporter Metrics Exporter for Mailserver for the [Prometheus](www.prometheus.io)-monitoring-system. This exporter can be used for mailsetups based on Maildir. Other storage formats are currently not supported. It tries to send e-mails in specified time intervals over the specified SMTP-servers and verifies delivery into the specified according maildirs. Success is indicated by a value of `1` of the metric `mail_deliver_success`, failure is indicated by `0`. ## Exported metrics The following metrics are exported, for each metric there is one instance per probe-config, distinguishable by label `configname` (which contains the value of the `Name`-field of the respective configuration section). * `mail_deliver_success`: indicates if last successfully sent mail was delivered in time (`1` if so, `0` if not) * `mail_send_fails`: indicates the number of failed attempts to send a probing mail via the specified SMTP-Server * `mail_last_send_duration_seconds`: duration of last valid mail handover to external SMTP-server in seconds * `mail_send_durations_seconds`: histogram of gauge `mail_last_send_duration_seconds` * `mail_last_deliver_duration_seconds`: time it took for the last received mail to be delivered (doesn't matter if timed out or not) in seconds * `mail_deliver_durations_seconds`: histogram of gauge `last_mail_deliver_duration` * `mail_last_deliver_time`: last time a mail was successfully delivered to the system as a unix timestamp (in seconds) * `mail_late_mails`: number of probing-mails being received after their respective timeout ## Building and running ### manually # actually build and run git clone https://github.com/cherti/mailexporter.git cd mailexporter go get ./... go build mailexporter.go ./mailexporter ### automatically using go-toolchain go get -u "github.com/cherti/mailexporter" ./mailexporter ## Configuration By defaut, mailexporter reads `/etc/mailexporter.conf` as its configfile. This can be changed via the command line flag `-config-file`. The Mailexporter doesn't support TLS and auth natively. This is left to tools intended for that. Nevertheless you are encouraged to use it with TLS and auth, e.g. by binding to `-web.listen-address=127.0.0.1:8083` in combination with an HTTP-reverseproxy capable of doing so (for example nginx, Apache or [AuthGuard](https://github.com/cherti/authguard)). The address mailexporter should listen on is specified by the commandline-flag `-web.listen-address` in the format `
:`. Furthermore you can adjust the HTTP endpoint for metrics by setting the `web.telemetry-path`-flag, which defaults to `/metrics`. Further configuration is done via the configuration file. See `mailexporter.conf` or `man mailexporter.conf` for further info. ### mailexporter.conf The configuration is done in [YAML](www.yaml.org). For detailed info see `mailexporter.conf` as the provided example configuration or `man mailexporter.conf`, if the manpage is installed on your system. By default, mailexporter looks for a configuration file `/etc/mailexporter.conf`. This can be changed via `-config-file=/path/to/file` as cli-flag. ## License This works is released under the [GNU General Public License v3](https://www.gnu.org/licenses/gpl-3.0.txt). You can find a copy of this license at https://www.gnu.org/licenses/gpl-3.0.txt. mailexporter-1.0/mailexporter.conf000066400000000000000000000026461303716671000174630ustar00rootroot00000000000000# This configuration file must be YAML (www.yaml.org) to be properly read by mailexporter # time between two monitoring-attempts monitoringinterval: 10m # Time until mail must have arrived after sending for positive outcome mailchecktimeout: 3m # Disables the mailexporters function to delete probing mails if filesystem access should be restricted # to avoid spamming the log with warnings; defaults to false, can be ommitted if unneeded # disablefiledeletion: false servers: - name: localhost # name for internal prometheus-metric server: localhost # SMTP-server to use port: 587 # port to use on Server for SMTP login: monitoring # login name on server (leave empty together with passphrase to disable authentication) passphrase: 123password # SMTP-login-password (leave empty together with login to disable authentication) from: monitoring@helper1.com # From-Header of monitoring-Mail (e.g. for filtering) to: monitoring@example.com # address to deliver to detectiondir: /home/me/Maildir/new # Maildir in which to look for monitoring-mail - name: helper1 server: mail.helper1.org port: 587 login: monitoring@helper1.org passphrase: password123 from: monitoring@helper1.org to: monitoring@example.com detectiondir: /home/me/Maildir/new mailexporter-1.0/mailexporter.go000066400000000000000000000377441303716671000171520ustar00rootroot00000000000000package main import ( "bytes" "errors" "flag" "io" "io/ioutil" "log" "math/rand" "net/http" "net/mail" "net/smtp" "os" "runtime" "strconv" "strings" "time" "github.com/prometheus/client_golang/prometheus" "gopkg.in/fsnotify.v1" "gopkg.in/yaml.v2" ) var ( logInfo = log.New(os.Stdout, "", 0) logWarn = log.New(os.Stdout, "WARNING: ", 0) logDebug = log.New(os.Stdout, "DEBUG: ", 0) logError = log.New(os.Stdout, "ERROR: ", 0) ) var tokenLength = 40 // length of token for probing-mails const tokenChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" // muxer is used to map probe-tokens to channels where the detection-goroutine should put the found mails. var muxer = make(map[string]chan email) // dispose token is used in probe to announce which tokens are no longer used for waiting for mails var disposeToken = make(chan string) type payload struct { configname string token string timestamp int64 } // newPayload composes a payload to be used in probing mails for identification consisting // of config name, unix time and a unique token for identification and returns it. func newPayload(confname string) payload { //timestamp := strconv.FormatInt(time.Now().UnixNano(), 10) // Now get the token to have a unique token. token := generateToken(tokenLength) //payload = strings.Join([]string{name, token, time.Now().UnixNano()}, "-") p := payload{confname, token, time.Now().UnixNano()} logDebug.Println("composed payload:", p) return p } func (p payload) String() string { return strings.Join([]string{p.configname, p.token, p.timestring()}, "-") } func (p payload) timestring() string { return strconv.FormatInt(p.timestamp, 10) } // decomposePayload returns the config name and unix timestamp as appropriate types // from given payload. func decomposePayload(input []byte) (payload, error) { logDebug.Println("payload to decompose:", input) decomp := strings.Split(string(input), "-") // is it correctly parsable? if len(decomp) != 3 { logDebug.Println("no fitting decomp") return payload{}, errNotOurDept } extractedUnixTime, err := strconv.ParseInt(decomp[2], 10, 64) // is the last one a unix-timestamp? if err != nil { logDebug.Println("unix-timestamp-parse-error") return payload{}, errNotOurDept } return payload{decomp[0], decomp[1], extractedUnixTime}, nil } // holds a configuration of external server to send test mails var globalconf struct { // The time to wait between probe-attempts. MonitoringInterval time.Duration // The time to wait until mail_deliver_success = 0 is reported. MailCheckTimeout time.Duration // Disables deletion of probing-mails found DisableFileDeletion bool // SMTP-Servers used for probing. Servers []smtpServerConfig } type smtpServerConfig struct { // The name the probing attempts via this server are classified with. Name string // The address of the SMTP-server. Server string // The port of the SMTP-server. Port string // The username for the SMTP-server. Login string // The SMTP-user's passphrase. Passphrase string // The sender-address for the probing mails. From string // The destination the probing-mails are sent to. To string // The directory in which mails sent by this server will end up if delivered correctly. Detectiondir string } var ( // cli-flags version = flag.Bool("version", false, "Print version information") confPath = flag.String("config.file", "/etc/mailexporter.conf", "Mailexporter configuration file to use.") logTimestamps = flag.Bool("log.timestamps", false, "Enable timestamps for logging to stdout.") webListenAddress = flag.String("web.listen-address", ":9225", "Colon separated address and port to listen on for the telemetry.") httpEndpoint = flag.String("web.telemetry-path", "/metrics", "Path under which to expose metrics.") verbosity = flag.Int("v", 1, "verbosity; higher means more output") // errors errNotOurDept = errors.New("no mail of ours") // listen-address ) // holds information about probing-email with the corresponding file name type email struct { // filename of the mailfile filename string // name of the configuration the mail originated from configname string // unique token to identify the mail even if timings and name are exactly the same token string // time the mail was sent as unix-timestamp tSent time.Time // time the mail was detected as unix-timestamp tRecv time.Time } // prometheus-instrumentation type durationMetric struct { gauge *prometheus.GaugeVec hist *prometheus.HistogramVec } func (m durationMetric) process(configname string, value float64) { m.gauge.WithLabelValues(configname).Set(value) m.hist.WithLabelValues(configname).Observe(value) } func (m durationMetric) register() { prometheus.MustRegister(m.gauge) prometheus.MustRegister(m.hist) } var deliverOk = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "mail_deliver_success", Help: "indicatior whether last mail was delivered successfully", }, []string{"configname"}, ) var lastMailDeliverTime = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "mail_last_deliver_time", Help: "unix-timestamp of detection of last correctly received mailprobe", }, []string{"configname"}, ) var lateMails = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "mail_late_mails", Help: "number of probing-mails received after their respective timeout", }, []string{"configname"}, ) var mailSendFails = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "mail_send_fails", Help: "number of failed attempts to send a probing mail via specified SMTP-server", }, []string{"configname"}, ) var ( // mail_deliver_durations is linearly bucketed for low roundtrip-times and exponential for higher ones, to // inexpensively catch really all late-comers. Therefore we first build the linear part of the buckets and // afterwards we build larger buckets in an exponential fashion. Both are combined in the declaration of // mailDeliverDurations. delDurHistogramStart float64 = 0.25 delDurLinSpacing float64 = 0.25 delDurLinBucketCount int = 20 delDurLinBuckets []float64 = prometheus.LinearBuckets(delDurHistogramStart, delDurLinSpacing, delDurLinBucketCount) delDurExpFactor float64 = 1.11 delDurExpAreaStart float64 = delDurLinBuckets[delDurLinBucketCount-1] * delDurExpFactor delDurExpBucketCount int = 35 delDurExpBuckets []float64 = prometheus.ExponentialBuckets(delDurExpAreaStart, delDurExpFactor, delDurExpBucketCount) deliverDurationHist = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "mail_deliver_durations_seconds", Help: "durations of mail delivery", Buckets: append(delDurLinBuckets, delDurExpBuckets...), }, []string{"configname"}, ) deliverDurationGauge = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "mail_last_deliver_duration_seconds", Help: "duration of delivery of last correctly received mailprobe", }, []string{"configname"}, ) mailDeliverDuration = durationMetric{deliverDurationGauge, deliverDurationHist} ) var ( // same game for last_send_duration as for last_deliver_duration above sendDurHistogramStart float64 = 0.1 sendDurLinSpacing float64 = 0.1 sendDurLinBucketCount int = 10 sendDurLinBuckets []float64 = prometheus.LinearBuckets(sendDurHistogramStart, sendDurLinSpacing, sendDurLinBucketCount) sendDurExpFactor float64 = 1.3 sendDurExpAreaStart float64 = sendDurLinBuckets[sendDurLinBucketCount-1] * sendDurExpFactor sendDurExpBucketCount int = 25 sendDurExpBuckets []float64 = prometheus.ExponentialBuckets(sendDurExpAreaStart, sendDurExpFactor, sendDurExpBucketCount) sendDurationHist = prometheus.NewHistogramVec( prometheus.HistogramOpts{ Name: "mail_send_durations_seconds", Help: "durations of valid mail handovers to exernal SMTP-servers", Buckets: append(sendDurLinBuckets, sendDurExpBuckets...), }, []string{"configname"}, ) sendDurationGauge = prometheus.NewGaugeVec( prometheus.GaugeOpts{ Name: "mail_last_send_duration_seconds", Help: "duration of last valid mail handover to external SMTP-server", }, []string{"configname"}, ) mailSendDuration = durationMetric{sendDurationGauge, sendDurationHist} ) func init() { prometheus.MustRegister(deliverOk) prometheus.MustRegister(lastMailDeliverTime) prometheus.MustRegister(lateMails) prometheus.MustRegister(mailSendFails) mailDeliverDuration.register() mailSendDuration.register() } // parseConfig parses configuration file and tells us if we are ready to rumble. func parseConfig(r io.Reader) error { content, err := ioutil.ReadAll(r) if err != nil { return err } return yaml.Unmarshal(content, &globalconf) } // send sends a probing-email over SMTP-server specified in config c to be waited for on the receiving side. func send(c smtpServerConfig, msg string) error { logDebug.Println("sending mail") fromheader := "From: " + c.From subjectheader := "Subject: " + "mailexporter-probe" fullmail := fromheader + "\n" + subjectheader + "\n" + msg var a smtp.Auth if c.Login == "" && c.Passphrase == "" { // if login and passphrase are left empty, skip authentication a = nil } else { a = smtp.PlainAuth("", c.Login, c.Passphrase, c.Server) } t1 := time.Now() err := smtp.SendMail(c.Server+":"+c.Port, a, c.From, []string{c.To}, []byte(fullmail)) t2 := time.Now() diff := t2.Sub(t1) sendDuration := float64(diff.Seconds()) mailSendDuration.process(c.Name, sendDuration) return err } // generateToken returns a random string to pad the send mail with for identifying // it later in the maildir (and not mistake another one for it) func generateToken(length int) string { stuff := make([]byte, length) rand.Seed(time.Now().UTC().UnixNano()) for i := 0; i < length; i++ { stuff[i] = tokenChars[rand.Intn(len(tokenChars))] } return string(stuff) } // deleteMail delete the given mail to not leave an untidied maildir. func deleteMailIfEnabled(m email) { if globalconf.DisableFileDeletion { logDebug.Println("file deletion disabled in config, not touching", m.filename) } else { if err := os.Remove(m.filename); err != nil { logWarn.Println("deletion error:", err) } logDebug.Println("rm ", m.filename) } } // handleLateMail handles mails that have been so late that they timed out func handleLateMail(m email) { logDebug.Printf("got late mail via %s; mail took %d\n", m.configname, m.tRecv.Sub(m.tSent)) lateMails.WithLabelValues(m.configname).Inc() deleteMailIfEnabled(m) } // probe probes if mail gets through the entire chain from specified SMTPServer into Maildir. func probe(c smtpServerConfig, p payload) { muxer[p.token] = make(chan email) //send(c, string(p)) err := send(c, p.String()) if err != nil { logWarn.Printf("error sending probe-mail via %s: %s; skipping attempt\n", c.Name, err) mailSendFails.WithLabelValues(c.Name).Inc() disposeToken <- p.token return } timeout := time.After(globalconf.MailCheckTimeout) select { case mail := <-muxer[p.token]: logDebug.Println("checking mail for timeout") deliverOk.WithLabelValues(c.Name).Set(1) deleteMailIfEnabled(mail) case <-timeout: logDebug.Println("Getting mail timed out.") deliverOk.WithLabelValues(c.Name).Set(0) } disposeToken <- p.token } // monitor probes every MonitoringInterval if mail still gets through. func monitor(c smtpServerConfig) { //delay start of monitoring randomly to desync the probing of the monitoring-coroutines time.Sleep(time.Duration(rand.Int()%20000) * time.Millisecond) log.Println("Started monitoring for config", c.Name) for { p := newPayload(c.Name) go probe(c, p) time.Sleep(globalconf.MonitoringInterval) } } // classifyMailMetrics extracts all general mail metrics such as deliver duration etc. // from a mail struct and sets the corresponding metrics func classifyMailMetrics(foundMail email) { // timestamps are in nanoseconds // last_mail_deliver_time shall be standard unix-timestamp // last_mail_deliver_duration shall be seconds (SI-Units) deliverTime := float64(foundMail.tRecv.Unix()) deliverDuration := foundMail.tRecv.Sub(foundMail.tSent).Seconds() lastMailDeliverTime.WithLabelValues(foundMail.configname).Set(deliverTime) mailDeliverDuration.process(foundMail.configname, deliverDuration) } // detectAndMuxMail monitors Detectiondirs, reports mails that come in to the goroutine they belong to // and takes care of removing unneeded report channels func detectAndMuxMail(watcher *fsnotify.Watcher) { log.Println("Started mail-detection.") for { select { case event := <-watcher.Events: if event.Op&fsnotify.Create == fsnotify.Create { if foundMail, err := parseMail(event.Name); err == nil { // first of all: classify the mail classifyMailMetrics(foundMail) // then hand over so the timeout is judged if ch, ok := muxer[foundMail.token]; ok { ch <- foundMail } else { handleLateMail(foundMail) } } } case err := <-watcher.Errors: logWarn.Println("watcher-error:", err) case token := <-disposeToken: // deletion of channels is done here to avoid interference with the report-case of this goroutine close(muxer[token]) delete(muxer, token) } } } func fileClose(f *os.File) { err := f.Close() if err != nil { logWarn.Println("error when closing file:", err) } } // parseMail reads a mailfile's content and parses it into a mail-struct if one of ours. func parseMail(path string) (email, error) { // to date the mails found t := time.Now() // try parsing f, err := os.Open(path) if err != nil { return email{}, err } defer fileClose(f) mail, err := mail.ReadMessage(io.LimitReader(f, 8192)) if err != nil { return email{}, err } payl, err := ioutil.ReadAll(mail.Body) if err != nil { return email{}, err } payloadbytes := bytes.TrimSpace(payl) // mostly for trailing "\n" p, err := decomposePayload(payloadbytes) // return if parsable // (non-parsable mails are not sent by us (or broken) and therefore not needed if err != nil { return email{}, errNotOurDept } return email{path, p.configname, p.token, time.Unix(0, p.timestamp), t}, nil } func watcherClose(w *fsnotify.Watcher) { err := w.Close() if err != nil { logWarn.Println("error when closing watcher:", err) } } func main() { flag.Parse() if *version { logInfo.Println("Prometheus-Mailexporter") logInfo.Printf(" :: version %s", "1.0") logInfo.Printf(" :: Go-version: %s", runtime.Version()) os.Exit(0) } // handle log-verbosity if *verbosity < 1 { // disable everything except error logs logInfo.SetOutput(ioutil.Discard) logWarn.SetOutput(ioutil.Discard) } if *verbosity < 2 { // disable Debug-logs (default) logDebug.SetOutput(ioutil.Discard) } // handle log-timestamping if *logTimestamps { logInfo.SetFlags(3) logWarn.SetFlags(3) logDebug.SetFlags(3) logError.SetFlags(3) } // seed the RNG, otherwise we would have same randomness on every startup // which should not, but might in worst case interfere with leftover-mails // from earlier starts of the binary rand.Seed(time.Now().Unix()) f, err := os.Open(*confPath) if err != nil { logError.Fatal(err) } defer fileClose(f) err = parseConfig(f) if err != nil { logError.Fatal(err) } // initialize Metrics that will be used seldom so that they actually get exported with a metric for _, c := range globalconf.Servers { lateMails.WithLabelValues(c.Name) mailSendFails.WithLabelValues(c.Name) } fswatcher, err := fsnotify.NewWatcher() if err != nil { logError.Fatal(err) } defer watcherClose(fswatcher) for _, c := range globalconf.Servers { logDebug.Println("adding path to watcher:", c.Detectiondir) errAdd := fswatcher.Add(c.Detectiondir) // deduplication is done within fsnotify if errAdd != nil { logWarn.Printf("error adding filesystem-watcher to %s: %s\n", c.Detectiondir, errAdd) } } go detectAndMuxMail(fswatcher) //starts monitoring goroutines for specified SMTP-server for _, c := range globalconf.Servers { go monitor(c) } log.Println("Starting HTTP-endpoint") http.Handle(*httpEndpoint, prometheus.Handler()) logError.Fatal(http.ListenAndServe(*webListenAddress, nil)) } mailexporter-1.0/mailexporter@.service000066400000000000000000000015621303716671000202720ustar00rootroot00000000000000[Unit] Description=Exports prometheus-style metrics about mailserver functionality After=network-online.service Wants=network-online.target [Service] Type=simple ExecStart=/usr/bin/mailexporter -web.listen-address=%i Restart=always # systemd hardening-options # Documentation about these can be found under systemd.exec(5) # The linked websites might be for a newer systemd version than your installed one PrivateDevices=true # https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateDevices= PrivateTmp=true # https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp= ProtectSystem=full # https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ProtectSystem= NoNewPrivileges=true # https://www.freedesktop.org/software/systemd/man/systemd.exec.html#NoNewPrivileges= [Install] WantedBy=multi-user.target mailexporter-1.0/man/000077500000000000000000000000001303716671000146445ustar00rootroot00000000000000mailexporter-1.0/man/mailexporter.1000066400000000000000000000032031303716671000174370ustar00rootroot00000000000000.\" Automatically generated by Pandoc 1.19.1 .\" .TH "mailexporter" "" "" "" "" .hy .SH NAME .PP mailexporter \- export metrics about mail server functionalty .SH SYNOPSIS .PP mailexporter [options] .SH OPTIONS .PP \f[B]\-config.file\f[] config\-file to use (default "/etc/mailexporter.conf") .PP \f[B]\-log.timestamps\f[] Log with timestamps .PP \f[B]\-v=\f[] verbosity; higher means more output (default 1) .PP \f[B]\-web.listen\-address\f[] colon separated address and port mailexporter shall listen on (default ":9225") .PP \f[B]\-web.telemetry\-path\f[] HTTP endpoint for serving metrics (default "/metrics") .SH EXPORTED METRICS .IP \[bu] 2 \f[I]mail_deliver_success\f[] indicates if last successfully sent mail was delivered in time (1 if so, 0 if not) .IP \[bu] 2 \f[I]mail_send_fails\f[] indicates the number of failed attempts to send a probing mail via the specified SMTP\-Server .IP \[bu] 2 \f[I]mail_last_send_duration_seconds\f[] duration of last valid mail handover to external SMTP\-server in seconds .IP \[bu] 2 \f[I]mail_send_durations_seconds\f[] histogram of gauge mail_last_send_duration_seconds .IP \[bu] 2 \f[I]mail_last_deliver_duration_seconds\f[] time it took for the last received mail to be delivered (doesn\[aq]t matter if timed out or not) in seconds .IP \[bu] 2 \f[I]mail_deliver_durations_seconds\f[] histogram of gauge last_mail_deliver_duration .IP \[bu] 2 \f[I]mail_last_deliver_time\f[] last time a mail was successfully delivered to the system as a unix timestamp (in seconds) .IP \[bu] 2 \f[I]mail_late_mails\f[] number of probing\-mails being received after their respective timeout .SH SEE ALSO .PP mailexporter.conf(5) mailexporter-1.0/man/mailexporter.conf.5000066400000000000000000000024231303716671000203720ustar00rootroot00000000000000.\" Automatically generated by Pandoc 1.19.1 .\" .TH "mailexporter" "" "" "" "" .hy .SH NAME .PP mailexporter \- export metrics about mail server functionalty .SH GENERAL OPTIONS .PP \f[B]monitoringinterval\f[] Interval betwteen subsequent probing attempts for one external server .PP \f[B]startupoffset\f[] Delay between starting the monitoring\-subroutines per server .PP \f[B]mailchecktimeout\f[] Timeout until mails are considered "didn\[aq]t make it" .PP \f[B]disablefiledeletion\f[] Disables the mailexporters function to delete probing mails if filesystem access should be restricted to avoid spamming the log with warnings; defaults to false, i.e. detected probing mails are deleted, and can be ommitted if unneeded .SH SERVER\-OPTIONS .PP \f[B]name\f[] name for internal prometheus\-metric \f[B]server\f[] SMTP\-server to use \f[B]port\f[] port to use on Server for SMTP \f[B]login\f[] login name on server (leave empty together with passphrase to disable authentication) \f[B]passphrase\f[] SMTP\-login\-password (leave empty together with login to disable authentication) \f[B]from\f[] From\-Header of monitoring\-Mail (e.g. for filtering) \f[B]to\f[] address to deliver to \f[B]detectiondir\f[] Maildir in which to look for monitoring\-mail .SH SEE ALSO .PP mailexporter(1) mailexporter-1.0/man/mailexporter.conf.rst000066400000000000000000000022561303716671000210420ustar00rootroot00000000000000============== mailexporter ============== NAME ==== mailexporter - export metrics about mail server functionalty GENERAL OPTIONS =============== **monitoringinterval** Interval betwteen subsequent probing attempts for one external server **startupoffset** Delay between starting the monitoring-subroutines per server **mailchecktimeout** Timeout until mails are considered "didn't make it" **disablefiledeletion** Disables the mailexporters function to delete probing mails if filesystem access should be restricted to avoid spamming the log with warnings; defaults to false, i.e. detected probing mails are deleted, and can be ommitted if unneeded SERVER-OPTIONS ============== **name** name for internal prometheus-metric **server** SMTP-server to use **port** port to use on Server for SMTP **login** login name on server (leave empty together with passphrase to disable authentication) **passphrase** SMTP-login-password (leave empty together with login to disable authentication) **from** From-Header of monitoring-Mail (e.g. for filtering) **to** address to deliver to **detectiondir** Maildir in which to look for monitoring-mail SEE ALSO ======== mailexporter(1) mailexporter-1.0/man/mailexporter.rst000066400000000000000000000026741303716671000201220ustar00rootroot00000000000000============== mailexporter ============== NAME ==== mailexporter - export metrics about mail server functionalty SYNOPSIS ======== mailexporter [options] OPTIONS ======= **-config.file** config-file to use (default "/etc/mailexporter.conf") **-log.timestamps** Log with timestamps **-v=** verbosity; higher means more output (default 1) **-web.listen-address** colon separated address and port mailexporter shall listen on (default ":9225") **-web.telemetry-path** HTTP endpoint for serving metrics (default "/metrics") EXPORTED METRICS ================ * *mail_deliver_success* indicates if last successfully sent mail was delivered in time (`1` if so, `0` if not) * *mail_send_fails* indicates the number of failed attempts to send a probing mail via the specified SMTP-Server * *mail_last_send_duration_seconds* duration of last valid mail handover to external SMTP-server in seconds * *mail_send_durations_seconds* histogram of gauge `mail_last_send_duration_seconds` * *mail_last_deliver_duration_seconds* time it took for the last received mail to be delivered (doesn't matter if timed out or not) in seconds * *mail_deliver_durations_seconds* histogram of gauge `last_mail_deliver_duration` * *mail_last_deliver_time* last time a mail was successfully delivered to the system as a unix timestamp (in seconds) * *mail_late_mails* number of probing-mails being received after their respective timeout SEE ALSO ======== mailexporter.conf(5)