mirror of https://github.com/statping/statping
Add smtp and imap service types
parent
4b450537ab
commit
63b3f1cf2a
|
@ -1,4 +1,5 @@
|
||||||
.idea
|
.idea
|
||||||
|
.vscode
|
||||||
snap
|
snap
|
||||||
prime
|
prime
|
||||||
stage
|
stage
|
||||||
|
|
3
Makefile
3
Makefile
|
@ -40,6 +40,9 @@ up:
|
||||||
docker compose -f docker-compose.yml -f dev/docker-compose.full.yml up -d --remove-orphans
|
docker compose -f docker-compose.yml -f dev/docker-compose.full.yml up -d --remove-orphans
|
||||||
make print_details
|
make print_details
|
||||||
|
|
||||||
|
local: clean frontend-build build
|
||||||
|
export STATPING_DIR=./docker/statping/sqlite && ./statping --port 8080
|
||||||
|
|
||||||
down:
|
down:
|
||||||
docker compose -f docker-compose.yml -f dev/docker-compose.full.yml down --volumes --remove-orphans
|
docker compose -f docker-compose.yml -f dev/docker-compose.full.yml down --volumes --remove-orphans
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
<option value="udp">UDP {{ $t('service') }}</option>
|
<option value="udp">UDP {{ $t('service') }}</option>
|
||||||
<option value="icmp">ICMP Ping</option>
|
<option value="icmp">ICMP Ping</option>
|
||||||
<option value="grpc">gRPC {{ $t('service') }}</option>
|
<option value="grpc">gRPC {{ $t('service') }}</option>
|
||||||
|
<option value="smtp">SMTP {{ $t('service') }}</option>
|
||||||
|
<option value="imap">IMAP {{ $t('service') }}</option>
|
||||||
<option value="static">Static {{ $t('service') }}</option>
|
<option value="static">Static {{ $t('service') }}</option>
|
||||||
</select>
|
</select>
|
||||||
<small class="form-text text-muted">Use HTTP if you are checking a website or use TCP if you are checking a server</small>
|
<small class="form-text text-muted">Use HTTP if you are checking a website or use TCP if you are checking a server</small>
|
||||||
|
@ -88,6 +90,12 @@
|
||||||
<input v-model.number="service.port" type="number" name="port" class="form-control" id="service_port" placeholder="8080">
|
<input v-model.number="service.port" type="number" name="port" class="form-control" id="service_port" placeholder="8080">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="service.type.match(/^(smtp|imap)$/)" class="form-group row">
|
||||||
|
<label class="col-sm-4 col-form-label">Port</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input v-model.number="service.port" type="number" name="port" class="form-control" id="service_port" placeholder="587">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div v-if="service.type.match(/^(http)$/)" class="form-group row">
|
<div v-if="service.type.match(/^(http)$/)" class="form-group row">
|
||||||
<label class="col-sm-4 col-form-label">{{ $t('service_check') }}</label>
|
<label class="col-sm-4 col-form-label">{{ $t('service_check') }}</label>
|
||||||
|
@ -132,6 +140,13 @@
|
||||||
<small class="form-text text-muted">Comma delimited list of HTTP Headers (KEY=VALUE,KEY=VALUE)</small>
|
<small class="form-text text-muted">Comma delimited list of HTTP Headers (KEY=VALUE,KEY=VALUE)</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="service.type.match(/^(smtp|imap)$/)" class="form-group row">
|
||||||
|
<label class="col-sm-4 col-form-label">Credentials</label>
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input v-model="service.headers" class="form-control" autocapitalize="none" spellcheck="false" placeholder='Username=user@domain.com,Password=secretpassword'>
|
||||||
|
<small class="form-text text-muted">Comma delimited list of IMAP/SMTP credentials (Username=user@domain.com,Password=secretpassword)</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-if="service.type.match(/^(http)$/)" class="form-group row">
|
<div v-if="service.type.match(/^(http)$/)" class="form-group row">
|
||||||
<label class="col-sm-4 col-form-label">{{ $t('expected_resp') }} (Regex)</label>
|
<label class="col-sm-4 col-form-label">{{ $t('expected_resp') }} (Regex)</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
|
@ -156,7 +171,7 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="service.type.match(/^(http|grpc)$/)" class="form-group row">
|
<div v-if="service.type.match(/^(http|grpc|smtp|imap)$/)" class="form-group row">
|
||||||
<label class="col-12 col-md-4 col-form-label">{{ $t('verify_ssl') }}</label>
|
<label class="col-12 col-md-4 col-form-label">{{ $t('verify_ssl') }}</label>
|
||||||
<div class="col-12 col-md-8 mt-1 mb-2 mb-md-0">
|
<div class="col-12 col-md-8 mt-1 mb-2 mb-md-0">
|
||||||
<span @click="service.verify_ssl = !!service.verify_ssl" class="switch float-left">
|
<span @click="service.verify_ssl = !!service.verify_ssl" class="switch float-left">
|
||||||
|
@ -194,7 +209,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="service.type.match(/^(tcp|http)$/)" class="form-group row">
|
<div v-if="service.type.match(/^(tcp|smtp|imap|http)$/)" class="form-group row">
|
||||||
<label class="col-12 col-md-4 col-form-label">{{ $t('tls_cert') }}</label>
|
<label class="col-12 col-md-4 col-form-label">{{ $t('tls_cert') }}</label>
|
||||||
<div class="col-12 col-md-8 mt-1 mb-2 mb-md-0">
|
<div class="col-12 col-md-8 mt-1 mb-2 mb-md-0">
|
||||||
<span @click="use_tls = !!use_tls" class="switch float-left">
|
<span @click="use_tls = !!use_tls" class="switch float-left">
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -6,6 +6,8 @@ require (
|
||||||
github.com/GeertJohan/go.rice v1.0.3
|
github.com/GeertJohan/go.rice v1.0.3
|
||||||
github.com/aws/aws-sdk-go v1.30.20
|
github.com/aws/aws-sdk-go v1.30.20
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible
|
||||||
|
github.com/emersion/go-imap v1.0.6
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
|
||||||
github.com/fatih/structs v1.1.0
|
github.com/fatih/structs v1.1.0
|
||||||
github.com/foomo/simplecert v1.7.5
|
github.com/foomo/simplecert v1.7.5
|
||||||
github.com/foomo/tlsconfig v0.0.0-20180418120404-b67861b076c9
|
github.com/foomo/tlsconfig v0.0.0-20180418120404-b67861b076c9
|
||||||
|
|
9
go.sum
9
go.sum
|
@ -159,6 +159,14 @@ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m
|
||||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||||
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM=
|
||||||
|
github.com/emersion/go-imap v1.0.6 h1:N9+o5laOGuntStBo+BOgfEB5evPsPD+K5+M0T2dctIc=
|
||||||
|
github.com/emersion/go-imap v1.0.6/go.mod h1:yKASt+C3ZiDAiCSssxg9caIckWF/JG7ZQTO7GAmvicU=
|
||||||
|
github.com/emersion/go-message v0.11.1/go.mod h1:C4jnca5HOTo4bGN9YdqNQM9sITuT3Y0K6bSUw9RklvY=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b h1:uhWtEWBHgop1rqEk2klKaxPAkVDCXexai6hSuRQ7Nvs=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20191210011802-430746ea8b9b/go.mod h1:G/dpzLu16WtQpBfQ/z3LYiYJn3ZhKSGWn83fyoyQe/k=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
|
||||||
|
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
|
||||||
|
github.com/emersion/go-textwrapper v0.0.0-20160606182133-d0e65e56babe/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
|
@ -392,6 +400,7 @@ github.com/liquidweb/liquidweb-go v1.6.1/go.mod h1:UDcVnAMDkZxpw4Y7NOHkqoeiGacVL
|
||||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
github.com/martinlindhe/base36 v1.0.0/go.mod h1:+AtEs8xrBpCeYgSLoY/aJ6Wf37jtBuR0s35750M27+8=
|
||||||
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
|
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
|
|
|
@ -6,27 +6,29 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/statping-ng/statping-ng/types"
|
"github.com/statping-ng/statping-ng/types"
|
||||||
"github.com/statping-ng/statping-ng/types/errors"
|
"github.com/statping-ng/statping-ng/types/errors"
|
||||||
"github.com/statping-ng/statping-ng/types/failures"
|
"github.com/statping-ng/statping-ng/types/failures"
|
||||||
"github.com/statping-ng/statping-ng/types/hits"
|
"github.com/statping-ng/statping-ng/types/hits"
|
||||||
"github.com/statping-ng/statping-ng/utils"
|
"github.com/statping-ng/statping-ng/utils"
|
||||||
"io/ioutil"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const limitedFailures = 25
|
const limitedFailures = 25
|
||||||
|
|
||||||
func (s *Service) LoadTLSCert() (*tls.Config, error) {
|
func (s *Service) LoadTLSCert() (config *tls.Config, err error) {
|
||||||
|
config, err = s.configureTLS()
|
||||||
if s.TLSCert.String == "" || s.TLSCertKey.String == "" {
|
if s.TLSCert.String == "" || s.TLSCertKey.String == "" {
|
||||||
return nil, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// load TLS cert and key from file path or PEM format
|
// load TLS cert and key from file path or PEM format
|
||||||
var cert tls.Certificate
|
var cert tls.Certificate
|
||||||
var err error
|
|
||||||
tlsCertExtension := utils.FileExtension(s.TLSCert.String)
|
tlsCertExtension := utils.FileExtension(s.TLSCert.String)
|
||||||
tlsCertKeyExtension := utils.FileExtension(s.TLSCertKey.String)
|
tlsCertKeyExtension := utils.FileExtension(s.TLSCertKey.String)
|
||||||
if tlsCertExtension == "" && tlsCertKeyExtension == "" {
|
if tlsCertExtension == "" && tlsCertKeyExtension == "" {
|
||||||
|
@ -38,13 +40,14 @@ func (s *Service) LoadTLSCert() (*tls.Config, error) {
|
||||||
return nil, errors.Wrap(err, "issue loading X509KeyPair")
|
return nil, errors.Wrap(err, "issue loading X509KeyPair")
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &tls.Config{
|
if config == nil {
|
||||||
Certificates: []tls.Certificate{cert},
|
config = &tls.Config{}
|
||||||
InsecureSkipVerify: s.TLSCertRoot.String == "",
|
|
||||||
}
|
}
|
||||||
|
config.Certificates = []tls.Certificate{cert}
|
||||||
|
config.InsecureSkipVerify = config.InsecureSkipVerify || s.TLSCertRoot.String == ""
|
||||||
|
|
||||||
if s.TLSCertRoot.String == "" {
|
if s.TLSCertRoot.String == "" {
|
||||||
return config, nil
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// create Root CA pool or use Root CA provided
|
// create Root CA pool or use Root CA provided
|
||||||
|
@ -58,7 +61,23 @@ func (s *Service) LoadTLSCert() (*tls.Config, error) {
|
||||||
|
|
||||||
config.RootCAs = caCertPool
|
config.RootCAs = caCertPool
|
||||||
|
|
||||||
return config, nil
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) configureTLS() (config *tls.Config, err error) {
|
||||||
|
if !s.requiresTLS() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
config = &tls.Config{
|
||||||
|
ServerName: s.Domain,
|
||||||
|
InsecureSkipVerify: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Service) requiresTLS() bool {
|
||||||
|
return s.VerifySSL.Bool || ((s.Type == "smtp" || s.Type == "imap") && (s.Port == 465 || s.Port == 587 || s.Port == 993))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s Service) Duration() time.Duration {
|
func (s Service) Duration() time.Duration {
|
||||||
|
|
|
@ -4,9 +4,11 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/smtp"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -17,6 +19,7 @@ import (
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
|
||||||
|
"github.com/emersion/go-imap/client"
|
||||||
"github.com/statping-ng/statping-ng/types/failures"
|
"github.com/statping-ng/statping-ng/types/failures"
|
||||||
"github.com/statping-ng/statping-ng/types/hits"
|
"github.com/statping-ng/statping-ng/types/hits"
|
||||||
"github.com/statping-ng/statping-ng/utils"
|
"github.com/statping-ng/statping-ng/utils"
|
||||||
|
@ -58,7 +61,7 @@ CheckLoop:
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseHost(s *Service) string {
|
func parseHost(s *Service) string {
|
||||||
if s.Type == "tcp" || s.Type == "udp" || s.Type == "grpc" {
|
if s.Type == "tcp" || s.Type == "udp" || s.Type == "grpc" || s.Type == "smtp" || s.Type == "imap" {
|
||||||
return s.Domain
|
return s.Domain
|
||||||
} else {
|
} else {
|
||||||
u, err := url.Parse(s.Domain)
|
u, err := url.Parse(s.Domain)
|
||||||
|
@ -74,7 +77,7 @@ func dnsCheck(s *Service) (int64, error) {
|
||||||
var err error
|
var err error
|
||||||
t1 := utils.Now()
|
t1 := utils.Now()
|
||||||
host := parseHost(s)
|
host := parseHost(s)
|
||||||
if s.Type == "tcp" || s.Type == "udp" || s.Type == "grpc" {
|
if s.Type == "tcp" || s.Type == "udp" || s.Type == "grpc" || s.Type == "smtp" {
|
||||||
_, err = net.LookupHost(host)
|
_, err = net.LookupHost(host)
|
||||||
} else {
|
} else {
|
||||||
_, err = net.LookupIP(host)
|
_, err = net.LookupIP(host)
|
||||||
|
@ -293,6 +296,222 @@ func CheckTcp(s *Service, record bool) (*Service, error) {
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// checkSmtp will check an SMTP service
|
||||||
|
func CheckSmtp(s *Service, record bool) (*Service, error) {
|
||||||
|
defer s.updateLastCheck()
|
||||||
|
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Name))
|
||||||
|
defer timer.ObserveDuration()
|
||||||
|
|
||||||
|
dnsLookup, err := dnsCheck(s)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("Could not get IP address for %s service %v, %v", strings.ToUpper(s.Type), s.Domain, err), "lookup")
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
s.PingTime = dnsLookup
|
||||||
|
t1 := utils.Now()
|
||||||
|
domain := fmt.Sprintf("%v", s.Domain)
|
||||||
|
if s.Port != 0 {
|
||||||
|
domain = fmt.Sprintf("%v:%v", s.Domain, s.Port)
|
||||||
|
if isIPv6(s.Domain) {
|
||||||
|
domain = fmt.Sprintf("[%v]:%v", s.Domain, s.Port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig, err := s.LoadTLSCert()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var c *smtp.Client
|
||||||
|
var headers []string
|
||||||
|
var username, password string
|
||||||
|
if s.Headers.Valid {
|
||||||
|
headers = strings.Split(s.Headers.String, ",")
|
||||||
|
} else {
|
||||||
|
headers = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if 'Content-Type' header was defined
|
||||||
|
for _, header := range headers {
|
||||||
|
switch strings.ToLower(strings.Split(header, "=")[0]) {
|
||||||
|
case "username":
|
||||||
|
username = strings.Split(header, "=")[1]
|
||||||
|
case "password":
|
||||||
|
password = strings.Split(header, "=")[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.requiresTLS() || s.TLSCert.String != "" {
|
||||||
|
// test TCP connection if TLS Certificate was set
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
KeepAlive: time.Duration(s.Timeout) * time.Second,
|
||||||
|
Timeout: time.Duration(s.Timeout) * time.Second,
|
||||||
|
}
|
||||||
|
conn, err := tls.DialWithDialer(dialer, "tcp", domain, tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("Dial Error: %v", err), "tls")
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
c, err = smtp.NewClient(conn, s.Domain)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("%s Connection Error: %v", strings.ToUpper(s.Type), err), s.Type)
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// test TCP connection if there is no TLS Certificate set
|
||||||
|
conn, err := net.DialTimeout("tcp", domain, time.Duration(s.Timeout)*time.Second)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("Dial Error: %v", err), "tls")
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
c, err = smtp.NewClient(conn, s.Domain)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("%s Connection Error: %v", strings.ToUpper(s.Type), err), s.Type)
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auth
|
||||||
|
if s.Port != 25 {
|
||||||
|
if username == "" || password == "" {
|
||||||
|
err = errors.New("no credentials configured")
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("%s Authentication Error: %v", strings.ToUpper(s.Type), err), s.Type)
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = c.Auth(smtp.PlainAuth("", username, password, s.Domain)); err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("%s Authentication Error: %v", strings.ToUpper(s.Type), err), s.Type)
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||||
|
s.LastResponse = ""
|
||||||
|
s.Online = true
|
||||||
|
if record {
|
||||||
|
RecordSuccess(s)
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckImap(s *Service, record bool) (*Service, error) {
|
||||||
|
defer s.updateLastCheck()
|
||||||
|
timer := prometheus.NewTimer(metrics.ServiceTimer(s.Name))
|
||||||
|
defer timer.ObserveDuration()
|
||||||
|
|
||||||
|
dnsLookup, err := dnsCheck(s)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("Could not get IP address for %s service %v, %v", strings.ToUpper(s.Type), s.Domain, err), "lookup")
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
s.PingTime = dnsLookup
|
||||||
|
t1 := utils.Now()
|
||||||
|
domain := fmt.Sprintf("%v", s.Domain)
|
||||||
|
if s.Port != 0 {
|
||||||
|
domain = fmt.Sprintf("%v:%v", s.Domain, s.Port)
|
||||||
|
if isIPv6(s.Domain) {
|
||||||
|
domain = fmt.Sprintf("[%v]:%v", s.Domain, s.Port)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConfig, err := s.LoadTLSCert()
|
||||||
|
if err != nil {
|
||||||
|
log.Errorln(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var headers []string
|
||||||
|
var username, password string
|
||||||
|
if s.Headers.Valid {
|
||||||
|
headers = strings.Split(s.Headers.String, ",")
|
||||||
|
} else {
|
||||||
|
headers = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if 'Content-Type' header was defined
|
||||||
|
for _, header := range headers {
|
||||||
|
switch strings.ToLower(strings.Split(header, "=")[0]) {
|
||||||
|
case "username":
|
||||||
|
username = strings.Split(header, "=")[1]
|
||||||
|
case "password":
|
||||||
|
password = strings.Split(header, "=")[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var conn *client.Client
|
||||||
|
if s.requiresTLS() || s.TLSCert.String != "" {
|
||||||
|
// test TCP connection if TLS Certificate was set
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
KeepAlive: time.Duration(s.Timeout) * time.Second,
|
||||||
|
Timeout: time.Duration(s.Timeout) * time.Second,
|
||||||
|
}
|
||||||
|
conn, err = client.DialWithDialerTLS(dialer, domain, tlsConfig)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("Dial Error: %v", err), "tls")
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// test TCP connection if there is no TLS Certificate set
|
||||||
|
dialer := &net.Dialer{
|
||||||
|
KeepAlive: time.Duration(s.Timeout) * time.Second,
|
||||||
|
Timeout: time.Duration(s.Timeout) * time.Second,
|
||||||
|
}
|
||||||
|
conn, err = client.DialWithDialer(dialer, domain)
|
||||||
|
if err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("Dial Error: %v", err), "tls")
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer conn.Logout()
|
||||||
|
|
||||||
|
// Auth
|
||||||
|
if s.Port != 143 {
|
||||||
|
if username == "" || password == "" {
|
||||||
|
err = errors.New("no credentials configured")
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("%s Authentication Error: %v", strings.ToUpper(s.Type), err), s.Type)
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = conn.Login(username, password); err != nil {
|
||||||
|
if record {
|
||||||
|
RecordFailure(s, fmt.Sprintf("%s Authentication Error: %v", strings.ToUpper(s.Type), err), s.Type)
|
||||||
|
}
|
||||||
|
return s, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Latency = utils.Now().Sub(t1).Microseconds()
|
||||||
|
s.LastResponse = ""
|
||||||
|
s.Online = true
|
||||||
|
if record {
|
||||||
|
RecordSuccess(s)
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Service) updateLastCheck() {
|
func (s *Service) updateLastCheck() {
|
||||||
s.LastCheck = time.Now()
|
s.LastCheck = time.Now()
|
||||||
}
|
}
|
||||||
|
@ -460,5 +679,9 @@ func (s *Service) CheckService(record bool) {
|
||||||
CheckGrpc(s, record)
|
CheckGrpc(s, record)
|
||||||
case "icmp":
|
case "icmp":
|
||||||
CheckIcmp(s, record)
|
CheckIcmp(s, record)
|
||||||
|
case "smtp":
|
||||||
|
CheckSmtp(s, record)
|
||||||
|
case "imap":
|
||||||
|
CheckImap(s, record)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue