Added GO-realisation email check service

master
svkalinin 2022-07-06 12:36:21 +03:00
parent 94e1825419
commit 9e23e5a7c9
9 changed files with 2183 additions and 0 deletions

View File

@ -0,0 +1,3 @@
.env
main
email-check

View File

@ -0,0 +1,20 @@
FROM golang:alpine AS build
RUN apk --no-cache add gcc g++ make git
WORKDIR /go/src/app
COPY . .
RUN go get ./...
RUN GOOS=linux go build -ldflags="-s -w" -o ./bin/email-check ./email-check.go
FROM alpine:3.9
RUN apk add tzdata
#RUN apk --no-cache add ca-certificates
WORKDIR /usr/bin
COPY --from=build /go/src/app/bin /go/bin
COPY cronjobs /etc/crontabs/root
# start crond with log level 8 in foreground, output to stderr
CMD ["crond", "-f", "-d", "8"]
#ENTRYPOINT /go/bin/email-check

View File

@ -0,0 +1,131 @@
# Email Monitoring
"Сервис" проверки отправки и получения почты с возможностью мониторинга в Zabbix. Также можно просто отправлять любые сообщения с целью автоматизации чего-нибудь.
Пароли от учетных записей почты сервис может брать из Hashicorp Vault.
Программу можно запускать как в консоли так и в docker-контейнере.
# Режимы работы
# использование
Для работы используются переменные окружения (либо соответствующие им ключи (опции) командной строки), при указании параметров с командной строки , переменные окружения будут проигнорированы:
- IMAP_SERVER=imap.google.com
- IMAP_PORT=143
- IMAP_USER=some@gmail.com
- IMAP_PASSWORD=12345
- MAIL_FROM=some@localmaildomain.ru
- MAIL_MESSAGE="Message body"
- MAIL_SUBJECT="Test email subject"
- MAIL_TO=""some@gmail.com
- SMTP_SERVER=smtp.localmaildomain.ru
- SMTP_PORT=25
- SMTP_USER=some@localmaildomain.ru
- SMTP_PASSWORD=123456
- VAULT_ADDRESS=https://you.vault.address
- VAULT_TOKEN="You vault token"
- ZABBIX_SERVER=https://zabbix2
- ZABBIX_HOST=mail.localmaildomain.ru
- ZABBIX_USERNAME=zabbix_user
- ZABBIX_PASSWORD=somepass
Для отправки сообщения следует указать опцию "-send" и задать все остальные параметры (адреса, пользователей и так далее), для проверки получения сообщения надо указать "-recieve". Если указать обе опции то будет протестирована отправка и получение одного сообщения.
Если Тема (mail-subject) и Сообщение (mail-message) не указаны то будет сгенерирован уникальный код, который будет вставлен в сообщение.
При указании адреса vault и токена с командной строки или через переменные окружения, пароли будут взяты оттуда. В качестве ключа используются значения SMTP_USER (-smtp-user), IMAP_USER (-imap-user), ZABBIX_USER (-zabbix-api-user). Если секреты для почтовых адресов и пароли от заббикса (API) хрянятся в разных разделах, то путь к хранилищу VAULT можно построить указав отдельные пути при помощи опций "-vault-email-secret-path" и "-vault-zabbix-secret-path". Т.е.:
Если указать значения параметров:
```
-vault-address="https://vault:8200/v1/secret/data/"
-vault-email-secret-path="email"
-vault-zabbix-secret-path="zabbix/helpers"
```
или
```
-vault-address="https://vault:8200"
-vault-email-secret-path="/v1/secret/data/email"
-vault-zabbix-secret-path="/v1/secret/data/zabbix/helpers"
```
То, получим полный путь "https://vault:8200/v1/secret/data/email" или https://vault:8200/v1/secret/data/zabbix/helpers".
Для отправки результатов проверки в zabbix можно использовать как Zabbix API (опция "-zabbix-api") так и zabbix-sender (опция "-zabbix-sender"). При указании одного из этих вариантов требуется также указывать параметры работы с заббикс (адрес сервера, узел, пользователя -zabbix-api-user и пароль -zabbix-api-password (в случае АПИ)). Но предварительно следует настроить узел в заббикс и подключить к нему приложенный шаблон (шаблон настроен на использование zabbix-sender).
## Пример команды
Отправка сообщения через локальный SMTP сервер с авторизацией (пароли будут взяты из хрфнилища секретов Vault), и проверка получения этого сообщения в учетной записи gmail по imap:
```
email-check -mail-from "some@localmaildomain.ru" -mail-to "some@gmail.com" \
-smtp-user="some@localmaildomain.ru" -smtp-server="smtp.localmaildomain.ru" -smtp-port="25" \
-imap-port="993" -vault-address="https://vault:8200/v1/secret/data/email" \
-imap-user="some@gmail.com" -imap-server="imap.google.com" -send -recieve -delay 20
```
Опция "-delay" устанавливает задержку между отправкой и получением (чтением) сообщения и по умолчанию равна 10 секунд. Это необходимо для того, чтобы сообщение успело пройти все фильтры и проверки почтовой системы.
# Краткая помощь по программе
Опции командной строки:
```
-delay int
Pause is required between operations (default 10)
-direction string
Direction of email checking. Must be an: 'local', 'incoming', 'outgoing'. (default "local")
-imap-password string
IMAP user password (IMAP_PASSWORD)
-imap-port string
IMAP server port (IMAP_PORT) (default "993")
-imap-server string
IMAP server address (IMAP_SERVER)
-imap-user string
IMAP user (IMAP_USER)
-mail-from string
Mail sender address 'From' (MAIL_FROM)
-mail-message string
Mail message body (MAIL_MESSAGE)
-mail-subject string
Mail message subject (MAIL_SUBJECT)
-mail-to string
Mail receiver address 'From' (MAIL_TO)
-receive
receive message is ON
-send
Sending message is ON
-smtp-password string
SMTP user password (SMTP_PASSWORD)
-smtp-port string
SMTP server port (SMTP_PORT) (default "25")
-smtp-server string
SMTP server address (SMTP_SERVER)
-smtp-user string
SMTP user (SMTP_USER)
-use-zabbix-sender
Send metrics or discovery data into zabbix via zabbix-sender
-vault-address string
Hashicorp (c) vault address (VAULT_ADDRESS)
-vault-email-secret-path string
Path to Vault email secret, where 'full Vault path' = 'vault-address' + 'vault-email-secret-path'
-vault-token string
Vault access token (VAULT_TOKEN)
-vault-zabbix-secret-path string
Path to Vault zabbix secret, where 'full Vault path' = 'vault-address' + 'vault-zabbix-secret-path'
-zabbix-api
Send metrics or discovery data into zabbix via Zabbix API (not implemented yet)
-zabbix-api-password string
Zabbix server API password
-zabbix-api-user string
Zabbix server API user
-zabbix-host string
Zabbix monitoring host name
-zabbix-port int
Zabbix server port (default 10051)
-zabbix-server string
Zabbix server address
```

View File

@ -0,0 +1,5 @@
*/10 * * * * /go/bin/email-check -mail-to "${EXT_RECEIVER_EMAIL}" -mail-from "${SENDER_EMAIL}" -imap-user="${EXT_RECEIVER_EMAIL}" -imap-server="${EXT_IMAP_SERVER}" -smtp-user="${SENDER_EMAIL}" -smtp-server="${MAIL_SERVER}" -send -receive -delay 10 -direction outgoing -use-zabbix-sender -zabbix-host="${MAIL_SERVER}" -vault-email-secret-path="/v1/secret-inf/data/email" >> /var/log/email-check-out.log 2>&1
*/10 * * * * /go/bin/email-check -mail-to "${RECEIVER_EMAIL}" -mail-from "${EXT_SENDER_EMAIL}" -imap-user="${RECEIVER_EMAIL}" -imap-server="${MAIL_SERVER}" -smtp-user="${EXT_SENDER_EMAIL}" -smtp-server="${EXT_SMTP_SERVER}" -send -receive -delay 10 -direction incoming -use-zabbix-sender -zabbix-host="${MAIL_SERVER}" -vault-email-secret-path="/v1/secret-inf/data/email" >> /var/log/email-check-in.log 2>&1
*/10 * * * * /go/bin/email-check -mail-to "${RECEIVER_EMAIL}" -mail-from "${SENDER_EMAIL}" -imap-user="${RECEIVER_EMAIL}" -imap-server="${MAIL_SERVER}" -smtp-user="${SENDER_EMAIL}" -smtp-server="${MAIL_SERVER}" -send -receive -direction local -use-zabbix-sender -zabbix-host="${MAIL_SERVER}" -vault-email-secret-path="/v1/secret-inf/data/email" >> /var/log/email-check-local.log 2>&1

View File

@ -0,0 +1,9 @@
version: '3'
services:
check_email:
image: check-email-delivery:latest
env_file: .env
restart: always
build:
context: .

View File

@ -0,0 +1,585 @@
// ------------------------------------------------------
// Email sender and receiver for checking mail transport
// Author: Sergey Kalinin, 2022
//-------------------------------------------------------
package main
import (
"crypto/tls"
"encoding/json"
"errors"
"flag"
"fmt"
"log"
"net"
"net/http"
"net/smtp"
"os"
"strconv"
"time"
"github.com/adubkov/go-zabbix"
"github.com/emersion/go-imap"
"github.com/emersion/go-imap/client"
"github.com/google/uuid"
)
type SmtpSession struct {
smtpUser string
smtpPassword string
smtpServer string
smtpPort string
}
type ImapSession struct {
imapPassword string
imapServer string
imapUser string
imapPort string
}
type ZabbixSession struct {
zabbixUser string
zabbixPassword string
zabbixServer string
zabbixPort int
zabbixHost string
}
type MailMessage struct {
mailFrom string
mailTo string
mailSubject string
mailMessage string
messageUUID string
}
type loginAuth struct {
username, password string
}
func LoginAuth(username, password string) smtp.Auth {
return &loginAuth{username, password}
}
func (a *loginAuth) Start(server *smtp.ServerInfo) (string, []byte, error) {
return "LOGIN", []byte(a.username), nil
}
func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if more {
switch string(fromServer) {
case "Username:":
return []byte(a.username), nil
case "Password:":
return []byte(a.password), nil
default:
return nil, errors.New("Unknown from server")
}
}
return nil, nil
}
func sendEmail(smtpSession *SmtpSession, message *MailMessage) bool {
// Receiver email address.
to := []string{
message.mailTo,
}
serverName := smtpSession.smtpServer + ":" + smtpSession.smtpPort
// fmt.Println(serverName, smtpSession.smtpUser, smtpSession.smtpPassword)
conn, err := net.Dial("tcp", serverName)
if err != nil {
log.Println(err)
}
c, err := smtp.NewClient(conn, smtpSession.smtpServer)
if err != nil {
log.Println(err)
}
tlsconfig := &tls.Config{
ServerName: smtpSession.smtpServer,
}
if err = c.StartTLS(tlsconfig); err != nil {
log.Println(err)
}
auth := LoginAuth(smtpSession.smtpUser, smtpSession.smtpPassword)
if err = c.Auth(auth); err != nil {
log.Println(err)
}
msg := []byte("From: " + message.mailFrom + "\r\n" +
"To: " + message.mailTo + "\r\n" +
"Subject: " + message.mailSubject + "\r\n\r\n" +
message.mailMessage + "\r\n")
// Sending email.
err = smtp.SendMail(serverName, auth, message.mailFrom, to, msg)
if err != nil {
fmt.Println(err)
return false
}
// fmt.Println("Email Sent!")
if err != nil {
log.Fatal(err)
return false
} else {
log.Println("Email", message.messageUUID, "from", message.mailFrom, "sent successfully via", smtpSession.smtpServer)
return true
}
}
var httpClient = &http.Client{
Timeout: 10 * time.Second,
}
func genMessageUID() string {
id := uuid.New().String()
return id
}
func getVaultData(vaultAddr string, vaultToken string, vaultSecretName string) string {
customTransport := &(*http.DefaultTransport.(*http.Transport))
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
client := &http.Client{Transport: customTransport}
// client := &http.Client{}
req, _ := http.NewRequest("GET", vaultAddr, nil)
req.Header.Add("Accept", "application/json")
req.Header.Add("X-Vault-Token", vaultToken)
resp, err := client.Do(req)
if err != nil {
log.Println("Errored when sending request to the Vault server")
}
var result map[string]interface{}
json.NewDecoder(resp.Body).Decode(&result)
secret := result["data"].(map[string]interface{})["data"].(map[string]interface{})[vaultSecretName]
return fmt.Sprint(secret)
}
func zabbixSender(zabbixSession *ZabbixSession, zabbixItem string, zabbixItemValue string) bool {
var (
metrics []*zabbix.Metric
err error
)
metrics = append(metrics, zabbix.NewMetric(zabbixSession.zabbixHost, zabbixItem, zabbixItemValue, time.Now().Unix()))
// metrics = append(metrics, zabbix.NewMetric(zabbixSession.zabbixHost, "status", "OK"))
// Create instance of Packet class
packet := zabbix.NewPacket(metrics)
// fmt.Println(zabbix_host, metric_name, metric_value, metrics)
// Send packet to zabbix
z := zabbix.NewSender(zabbixSession.zabbixServer, zabbixSession.zabbixPort)
res, err := z.Send(packet)
log.Println(zabbixSession.zabbixServer, zabbixSession.zabbixPort, zabbixSession.zabbixHost, zabbixItem, zabbixItemValue, metrics, zabbixSession)
log.Println("Result", string(res))
if err != nil {
log.Println("Sending to zabbix should have failed:", err)
}
return true
}
func receiveEmail(imapSession *ImapSession, message *MailMessage) bool {
serverName := imapSession.imapServer + ":" + imapSession.imapPort
log.Println("Connecting to server", serverName, "...")
// Connect to server
c, err := client.DialTLS(serverName, nil)
if err != nil {
log.Fatal(err)
}
log.Println("Connected")
log.Println("Trying to logged in to imap with username", imapSession.imapUser, "...")
// Don't forget to logout
defer c.Logout()
// Login
if err := c.Login(imapSession.imapUser, imapSession.imapPassword); err != nil {
log.Fatal(err)
return false
}
log.Println(imapSession.imapUser, "logged in")
// Select INBOX
_, err = c.Select("INBOX", false)
if err != nil {
log.Fatal(err)
}
log.Println("Select the INBOX:")
// Get the last 4 messages
// from := uint32(1)
// to := mbox.Messages
// if mbox.Messages > 10 {
// // We're using unsigned integers here, only subtract if the result is > 0
// from = mbox.Messages - 10
// }
// seqset := new(imap.SeqSet)
// seqset.AddRange(from, to)
// messages := make(chan *imap.Message, 10)
// done := make(chan error, 1)
// go func() {
// done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope, imap.FetchUid}, messages)
// }()
// // var uid uint32
// log.Println("Search message with subject", message.mailSubject, "in last messages:")
// for msg := range messages {
// log.Println(msg.Uid)
// if msg.Envelope.Subject == message.mailSubject {
// log.Println("Message was found:", msg.Envelope.Subject, msg.Envelope.MessageId, msg.Uid)
// // uid = msg.Uid
// // item := imap.FormatFlagsOp(imap.AddFlags, true)
// // flags := []interface{}{imap.DeletedFlag}
// // if err := c.Store(seqset, item, flags, nil); err != nil {
// // log.Fatal(err)
// // } else {
// // log.Println("Message with UID", mbox.Messages, "was marked for deletion")
// // }
// }
// }
// if err := <-done; err != nil {
// log.Fatal(err)
// return false
// }
// -----------------------
// We will delete the last message
// if mbox.Messages == 0 {
// log.Fatal("No message in mailbox")
// }
// seqset.Clear()
// seqSet := new(imap.SeqSet)
// seqSet.AddNum(uid)
// // First mark the message as deleted
// item := imap.FormatFlagsOp(imap.AddFlags, true)
// flags := []interface{}{imap.DeletedFlag}
// if err := c.Store(seqSet, item, flags, nil); err != nil {
// log.Fatal(err)
// } else {
// log.Println("Last", mbox.Messages, "messages was marked for deletion")
// }
// Then delete it
// if err := c.Expunge(nil); err != nil {
// log.Fatal(err)
// }
// log.Println("Last messages has been deleted")
log.Println("Search message with subject", message.mailSubject, "in last messages...")
criteria := imap.NewSearchCriteria()
criteria.Text = []string{message.mailSubject}
ids, err := c.Search(criteria)
if err != nil {
log.Fatal(err)
}
log.Println("Total messages :", ids)
if len(ids) > 0 {
seqset := new(imap.SeqSet)
seqset.AddNum(ids...)
messages := make(chan *imap.Message, 10)
done := make(chan error, 1)
go func() {
done <- c.Fetch(seqset, []imap.FetchItem{imap.FetchEnvelope}, messages)
}()
// log.Println("Unseen messages:")
for msg := range messages {
log.Println("Message was found:", msg.Envelope.Subject, msg.Envelope.MessageId, msg.Uid)
// log.Println("* " + msg.Envelope.Subject)
}
if err := <-done; err != nil {
log.Fatal(err)
return false
}
item := imap.FormatFlagsOp(imap.AddFlags, true)
flags := []interface{}{imap.DeletedFlag}
if err := c.Store(seqset, item, flags, nil); err != nil {
log.Fatal(err)
return false
} else {
log.Println("The message with subject", message.mailSubject, "was marked for deletion")
}
}
// Then delete it
log.Println("Delete marked messages...")
if err := c.Expunge(nil); err != nil {
log.Fatal(err)
} else {
log.Println("All marked messages was deleted")
}
log.Println("Done!")
return true
}
func main() {
var (
vaultAddress string
vaultToken string
vaultEmailSecretPath string
vaultZabbixSecretPath string
vaultPath string
message MailMessage
smtpSession SmtpSession
imapSession ImapSession
zabbixSession ZabbixSession
sendMessage bool
receiveMessage bool
operationDelay int
useZabbixSender bool
zabbixApi bool
err error
msgSendResult bool
msgReceiveResult bool
direction string
)
// Genarate uniq ID
message.messageUUID = genMessageUID()
// ----------------------------------------------------------
// Read command line options and and settins the variables
flag.StringVar(&message.mailFrom, "mail-from", "", "Mail sender address 'From' (MAIL_FROM)")
flag.StringVar(&message.mailTo, "mail-to", "", "Mail receiver address 'From' (MAIL_TO)")
flag.StringVar(&message.mailSubject, "mail-subject", "", "Mail message subject (MAIL_SUBJECT)")
flag.StringVar(&message.mailMessage, "mail-message", "", "Mail message body (MAIL_MESSAGE)")
flag.StringVar(&smtpSession.smtpServer, "smtp-server", "", "SMTP server address (SMTP_SERVER)")
flag.StringVar(&smtpSession.smtpPort, "smtp-port", "587", "SMTP server port (SMTP_PORT)")
flag.StringVar(&smtpSession.smtpUser, "smtp-user", "", "SMTP user (SMTP_USER)")
flag.StringVar(&smtpSession.smtpPassword, "smtp-password", "", "SMTP user password (SMTP_PASSWORD)")
flag.StringVar(&imapSession.imapServer, "imap-server", "", "IMAP server address (IMAP_SERVER)")
flag.StringVar(&imapSession.imapPort, "imap-port", "993", "IMAP server port (IMAP_PORT)")
flag.StringVar(&imapSession.imapUser, "imap-user", "", "IMAP user (IMAP_USER)")
flag.StringVar(&imapSession.imapPassword, "imap-password", "", "IMAP user password (IMAP_PASSWORD)")
flag.StringVar(&vaultAddress, "vault-address", "", "Hashicorp (c) vault address (VAULT_ADDRESS)")
flag.StringVar(&vaultToken, "vault-token", "", "Vault access token (VAULT_TOKEN)")
flag.StringVar(&vaultEmailSecretPath, "vault-email-secret-path", "", "Path to Vault email secret, where 'full Vault path' = 'vault-address' + 'vault-email-secret-path'")
flag.StringVar(&vaultZabbixSecretPath, "vault-zabbix-secret-path", "", "Path to Vault zabbix secret, where 'full Vault path' = 'vault-address' + 'vault-zabbix-secret-path'")
flag.BoolVar(&sendMessage, "send", false, "Sending message is ON")
flag.BoolVar(&receiveMessage, "receive", false, "receive message is ON")
flag.IntVar(&operationDelay, "delay", 5, "Pause is required between operations")
flag.BoolVar(&useZabbixSender, "use-zabbix-sender", false, "Send metrics or discovery data into zabbix via zabbix-sender")
flag.BoolVar(&zabbixApi, "zabbix-api", false, "Send metrics or discovery data into zabbix via Zabbix API (not implemented yet)")
flag.StringVar(&zabbixSession.zabbixServer, "zabbix-server", "", "Zabbix server address (ZABBIX_SERVER)")
flag.IntVar(&zabbixSession.zabbixPort, "zabbix-port", 10051, "Zabbix server port (ZABBIX_PORT)")
flag.StringVar(&zabbixSession.zabbixUser, "zabbix-api-user", "", "Zabbix server API user (ZABBIX_USER)")
flag.StringVar(&zabbixSession.zabbixPassword, "zabbix-api-password", "", "Zabbix server API password (ZABBIX_PASSWORD)")
flag.StringVar(&zabbixSession.zabbixHost, "zabbix-host", "", "Zabbix monitoring host name")
flag.StringVar(&direction, "direction", "local", "Direction of email checking. Must be an: 'local', 'incoming', 'outgoing'.")
flag.Parse()
if os.Getenv("VAULT_ADDRESS") != "" {
vaultAddress = os.Getenv("VAULT_ADDRESS")
}
if vaultAddress != "" && vaultToken == "" && os.Getenv("VAULT_TOKEN") == "" {
fmt.Println("If You setting VAULT_ADDRES, You must sure environment variables `VAULT_TOKEN`, or used with '-vault-token' argument")
os.Exit(1)
} else if vaultToken == "" && os.Getenv("VAULT_TOKEN") != "" {
vaultToken = os.Getenv("VAULT_TOKEN")
}
if message.mailFrom == "" && os.Getenv("MAIL_FROM") == "" {
fmt.Println("Make sure environment variables `MAIL_FROM`, or used with '-mail-from' argument")
os.Exit(1)
} else if message.mailFrom == "" && os.Getenv("MAIL_FROM") != "" {
message.mailFrom = os.Getenv("MAIL_FROM")
}
if message.mailTo == "" && os.Getenv("MAIL_TO") == "" {
fmt.Println("Make sure environment variables `MAIL_TO`, or used with '-mail-to' argument")
os.Exit(1)
} else if message.mailTo == "" && os.Getenv("MAIL_TO") != "" {
message.mailTo = os.Getenv("MAIL_TO")
}
if message.mailSubject == "" && os.Getenv("MAIL_SUBJECT") == "" {
message.mailSubject = message.messageUUID
// fmt.Println("Make sure environment variables `MAIL_SUBJECT`, or used with '-mail-subject' argument")
// os.Exit(1)
} else if message.mailSubject == "" && os.Getenv("MAIL_SUBJECT") != "" {
message.mailFrom = os.Getenv("MAIL_SUBJECT")
}
if message.mailMessage == "" && os.Getenv("MAIL_MESSAGE") == "" {
message.mailMessage = message.messageUUID
// fmt.Println("Make sure environment variables `MAIL_MESSAGE`, or used with '-mail-message' argument")
// os.Exit(1)
} else if message.mailMessage == "" && os.Getenv("MAIL_MESSAGE") != "" {
message.mailMessage = os.Getenv("MAIL_MESSAGE")
}
if smtpSession.smtpUser == "" && os.Getenv("SMTP_USER") == "" {
fmt.Println("Make sure environment variables `SMTP_USER`, or used with '-smtp-user' argument")
os.Exit(1)
} else if smtpSession.smtpUser == "" && os.Getenv("SMTP_USER") != "" {
smtpSession.smtpServer = os.Getenv("SMTP_USER")
}
if smtpSession.smtpPassword == "" && os.Getenv("SMTP_PASSWORD") == "" && vaultAddress == "" {
fmt.Println("Make sure environment variables `SMTP_PASSWORD`, or used with '-smtp-password' argument")
os.Exit(1)
} else if smtpSession.smtpPassword == "" && os.Getenv("SMTP_PASSWORD") != "" {
smtpSession.smtpPassword = os.Getenv("SMTP_PASSWORD")
} else if vaultAddress != "" && smtpSession.smtpUser != "" && smtpSession.smtpPassword == "" {
vaultPath = vaultAddress + vaultEmailSecretPath
smtpSession.smtpPassword = getVaultData(vaultPath, vaultToken, smtpSession.smtpUser)
// fmt.Println(smtpUser, smtpPassword)
}
if smtpSession.smtpServer == "" && os.Getenv("SMTP_SERVER") == "" {
fmt.Println("Make sure environment variables `SMTP_SERVER`, or used with '-smtp-server' argument")
os.Exit(1)
} else if smtpSession.smtpServer == "" && os.Getenv("SMTP_SERVER") != "" {
smtpSession.smtpServer = os.Getenv("SMTP_SERVER")
}
if imapSession.imapUser == "" && os.Getenv("IMAP_USER") == "" {
fmt.Println("Make sure environment variables `IMAP_USER`, or used with '-imap-user' argument")
os.Exit(1)
} else if imapSession.imapUser == "" && os.Getenv("IMAP_USER") != "" {
imapSession.imapServer = os.Getenv("IMAP_USER")
}
if imapSession.imapPassword == "" && os.Getenv("IMAP_PASSWORD") == "" && vaultAddress == "" {
fmt.Println("Make sure environment variables `IMAP_PASSWORD`, or used with '-imap-password' argument")
os.Exit(1)
} else if imapSession.imapUser == "" && os.Getenv("IMAP_PASSWORD") != "" {
imapSession.imapPassword = os.Getenv("IMAP_PASSWORD")
} else if vaultAddress != "" && imapSession.imapUser != "" && imapSession.imapPassword == "" {
// secret := append("")
vaultPath = vaultAddress + vaultEmailSecretPath
imapSession.imapPassword = getVaultData(vaultPath, vaultToken, imapSession.imapUser)
// fmt.Println(imapUser, imapPassword)
}
if imapSession.imapServer == "" && os.Getenv("IMAP_SERVER") == "" {
fmt.Println("Make sure environment variables `IMAP_SERVER`, or used with '-imap-server' argument")
os.Exit(1)
} else if imapSession.imapServer == "" && os.Getenv("IMAP_SERVER") != "" {
imapSession.imapServer = os.Getenv("IMAP_SERVER")
}
if zabbixApi || useZabbixSender {
if zabbixSession.zabbixServer == "" && os.Getenv("ZABBIX_SERVER") == "" {
fmt.Println("Make sure environment variables `ZABBIX_SERVER`, or used with '-zabbix-server' argument")
os.Exit(1)
} else if zabbixSession.zabbixServer == "" && os.Getenv("ZABBIX_SERVER") != "" {
zabbixSession.zabbixServer = os.Getenv("ZABBIX_SERVER")
}
if os.Getenv("ZABBIX_PORT") != "" {
fmt.Println("Make sure environment variables `ZABBIX_PORT`, or used with '-zabbix-port' argument")
os.Exit(1)
if zabbixSession.zabbixPort, err = strconv.Atoi(os.Getenv("ZABBIX_PORT")); err != nil {
log.Println(zabbixSession.zabbixPort, "Zabbix port value error")
}
}
if zabbixSession.zabbixHost == "" && os.Getenv("ZABBIX_HOST") == "" {
fmt.Println("Make sure environment variables `ZABBIX_HOST`, or used with '-zabbix-host' argument")
os.Exit(1)
} else if zabbixSession.zabbixHost == "" && os.Getenv("ZABBIX_HOST") != "" {
zabbixSession.zabbixHost = os.Getenv("ZABBIX_HOST")
}
}
if zabbixApi {
if zabbixSession.zabbixUser == "" && os.Getenv("ZABBIX_USER") == "" {
fmt.Println("Make sure environment variables `ZABBIX_USER`, or used with '-zabbix-api-user' argument")
os.Exit(1)
} else if zabbixSession.zabbixUser == "" && os.Getenv("ZABBIX_USER") != "" {
zabbixSession.zabbixUser = os.Getenv("ZABBIX_USER")
}
if zabbixSession.zabbixPassword == "" && os.Getenv("ZABBIX_PASSWORD") == "" {
fmt.Println("Make sure environment variables `ZABBIX_PASSWORD`, or used with '-zabbix-api-password' argument")
os.Exit(1)
} else if vaultAddress != "" && zabbixSession.zabbixUser != "" && zabbixSession.zabbixPassword == "" {
// secret := append("")
vaultPath = vaultAddress + vaultZabbixSecretPath
zabbixSession.zabbixPassword = getVaultData(vaultPath, vaultToken, zabbixSession.zabbixUser)
// fmt.Println(imapUser, imapPassword)
} else if zabbixSession.zabbixPassword == "" && os.Getenv("ZABBIX_PASSWORD") != "" {
zabbixSession.zabbixUser = os.Getenv("ZABBIX_USER")
}
}
fmt.Println(useZabbixSender)
// ----------------------------------------------------------
// Run the operations
// Send message
if sendMessage {
log.Println("Send email message with UUID:", message.messageUUID)
msgSendResult = sendEmail(&smtpSession, &message)
// Send result into zabbix
if useZabbixSender {
if msgSendResult {
zabbixSender(&zabbixSession, `email.smtp_send.`+direction+`.status`, "OK")
} else {
zabbixSender(&zabbixSession, `email.smtp_send.`+direction+`.status`, "CRITICAL")
}
}
}
// When using both "send" and "receive",
// a 10-second pause between operations is required
if sendMessage && receiveMessage {
time.Sleep(time.Duration(operationDelay) * time.Second)
}
// Receive message
if receiveMessage {
log.Println("Read email message with UUID:", message.messageUUID, "via", imapSession.imapServer)
msgReceiveResult = receiveEmail(&imapSession, &message)
// Send result into zabbix
if useZabbixSender {
if msgReceiveResult {
zabbixSender(&zabbixSession, `email.imap_receive.`+direction+`.status`, "OK")
} else {
zabbixSender(&zabbixSession, `email.imap_receive.`+direction+`.status`, "CRITICAL")
}
}
}
// Send result into zabbix
if useZabbixSender {
if msgSendResult && msgReceiveResult {
zabbixSender(&zabbixSession, `email.delivery.`+direction+`.status`, "OK")
} else {
zabbixSender(&zabbixSession, `email.delivery.`+direction+`.status`, "CRITICAL")
}
}
}

View File

@ -0,0 +1,9 @@
module email-check.go
go 1.15
require (
github.com/adubkov/go-zabbix v0.0.0-20170118040903-3c6a95ec4fdc // indirect
github.com/emersion/go-imap v1.2.1 // indirect
github.com/google/uuid v1.3.0 // indirect
)

View File

@ -0,0 +1,14 @@
github.com/adubkov/go-zabbix v0.0.0-20170118040903-3c6a95ec4fdc h1:gqqI4ZPa7uwK+gX9Zgk2AweAh+2dX0FpETcXTsA2TrE=
github.com/adubkov/go-zabbix v0.0.0-20170118040903-3c6a95ec4fdc/go.mod h1:ihDXRSVen590YHlXIrv00CcmRrL6pUho/Iwm3ZmM8n8=
github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA=
github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY=
github.com/emersion/go-message v0.15.0/go.mod h1:wQUEfE+38+7EW8p8aZ96ptg6bAb1iwdgej19uXASlE4=
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-20200911093747-65d896831594/go.mod h1:aqO8z8wPrjkscevZJFVE1wXJrLpC5LtJG7fqLOsPb2U=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=