diff --git a/api/notification/.air.toml b/api/notification/.air.toml
index 8b52776d..16f8c34b 100644
--- a/api/notification/.air.toml
+++ b/api/notification/.air.toml
@@ -1,57 +1,46 @@
-# Config file for [Air](https://github.com/air-verse/air) in TOML format
-
-# Working directory
-# . or absolute path, please note that the directories following must be under root.
-root = "./.."
+root = "."
+testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
-# Just plain old shell command. You could use `make` as well.
-cmd = "go build -o app -ldflags \"-X 'github.com/tech/sendico/notification/internal/appversion.BuildUser=$(whoami)' -X 'github.com/tech/sendico/notification/internal/appversion.Version=$APP_V' -X 'github.com/tech/sendico/notification/internal/appversion.Branch=$BUILD_BRANCH' -X 'github.com/tech/sendico/notification/internal/appversion.Revision=$GIT_REV' -X 'github.com/tech/sendico/notification/internal/appversion.BuildDate=$(date)' -X 'github.com/tech/sendico/notification/internal/mutil/ampli.Version=$APP_V'\""
-# Binary file yields from `cmd`.
-bin = "./app"
-# Customize binary, can setup environment variables when run your app.
-full_bin = "./app --debug"
-# Watch these filename extensions.
-include_ext = ["go", "tpl", "tmpl", "html"]
-# Ignore these filename extensions or directories.
-exclude_dir = ["notification/.git", "pkg/.git", "notification/tmp", "notification/resources", "notification/env"]
-# Watch these directories if you specified.
-include_dir = []
-# Watch these files.
-include_file = []
-# Exclude files.
-exclude_file = []
-# Exclude specific regular expressions.
-exclude_regex = ["_test\\.go"]
-# Exclude unchanged files.
-exclude_unchanged = true
-# Follow symlink for directories
-follow_symlink = true
-# This log file places in your tmp_dir.
-log = "air.log"
-# It's not necessary to trigger build each time file changes if it's too frequent.
-delay = 0 # ms
-# Stop running old binary when build errors occur.
-stop_on_error = true
-# Send Interrupt signal before killing process (windows does not support this feature)
-send_interrupt = true
-# Delay after sending Interrupt signal
-kill_delay = 500 # ms
-# Add additional arguments when running binary (bin/full_bin). Will run './tmp/main hello world'.
-args_bin = []
-
-[log]
-# Show log time
-time = false
+ args_bin = []
+ entrypoint = "./tmp/main"
+ cmd = "go build -o ./tmp/main ."
+ delay = 1000
+ exclude_dir = ["assets", "tmp", "vendor", "testdata"]
+ exclude_file = []
+ exclude_regex = ["_test.go", "_templ.go"]
+ exclude_unchanged = false
+ follow_symlink = false
+ full_bin = ""
+ include_dir = []
+ include_ext = ["go", "tpl", "tmpl", "html"]
+ include_file = []
+ kill_delay = "0s"
+ log = "build-errors.log"
+ poll = false
+ poll_interval = 0
+ post_cmd = []
+ pre_cmd = []
+ rerun = false
+ rerun_delay = 500
+ send_interrupt = false
+ stop_on_error = false
[color]
-# Customize each part's color. If no color found, use the raw app log.
-main = "magenta"
-watcher = "cyan"
-build = "yellow"
-runner = "green"
+ app = ""
+ build = "yellow"
+ main = "magenta"
+ runner = "green"
+ watcher = "cyan"
+
+[log]
+ main_only = false
+ time = false
[misc]
-# Delete tmp directory on exit
-clean_on_exit = true
\ No newline at end of file
+ clean_on_exit = false
+
+[screen]
+ clear_on_rebuild = false
+ keep_scroll = true
diff --git a/api/notification/.gitignore b/api/notification/.gitignore
index 3bd54220..22180871 100644
--- a/api/notification/.gitignore
+++ b/api/notification/.gitignore
@@ -1,2 +1,4 @@
notification
.gocache
+app
+tmp
diff --git a/api/notification/config.dev.yml b/api/notification/config.dev.yml
new file mode 100755
index 00000000..0630f102
--- /dev/null
+++ b/api/notification/config.dev.yml
@@ -0,0 +1,94 @@
+http_server:
+ listen_address: :8081
+ read_header_timeout: 60
+ shutdown_timeout: 5
+
+api:
+ amplitude:
+ ampli_environment_env: AMPLI_ENVIRONMENT
+ middleware:
+ api_protocol_env: API_PROTOCOL
+ domain_env: SERVICE_HOST
+ api_endpoint_env: API_ENDPOINT
+ signature:
+ secret_key_env: API_ENDPOINT_SECRET
+ algorithm: HS256
+ CORS:
+ max_age: 300
+ allowed_origins:
+ - "http://*"
+ - "https://*"
+ allowed_methods:
+ - "GET"
+ - "POST"
+ - "PATCH"
+ - "DELETE"
+ - "OPTIONS"
+ allowed_headers:
+ - "Accept"
+ - "Authorization"
+ - "Content-Type"
+ exposed_headers:
+ allow_credentials: false
+ websocket:
+ endpoint_env: WS_ENDPOINT
+ timeout: 60
+ message_broker:
+ driver: NATS
+ settings:
+ url_env: NATS_URL
+ host_env: NATS_HOST
+ port_env: NATS_PORT
+ username_env: NATS_USER
+ password_env: NATS_PASSWORD
+ broker_name: Sendico Notification server
+ max_reconnects: 10
+ reconnect_wait: 5
+ buffer_size: 1024
+ # type: in-process
+ # settings:
+ # buffer_size: 10
+ notification:
+ driver: client
+ settings:
+ username_env: MAIL_USER
+ password_env: MAIL_SECRET
+ host: "mail.sendico.io"
+ port: 465
+ from: "Sendico Tech"
+ network_timeout: 10
+ telegram:
+ bot_token_env: TELEGRAM_BOT_TOKEN
+ chat_id_env: TELEGRAM_CHAT_ID
+ thread_id_env: TELEGRAM_THREAD_ID
+ api_url: "https://api.telegram.org"
+ timeout_seconds: 10
+ parse_mode: markdown
+
+localizer:
+ path: "./i18n"
+ languages: ["en", "ru"]
+ service_name: "Sendico"
+ support: "support@sendico.io"
+
+app:
+
+database:
+ driver: mongodb
+ settings:
+ host_env: MONGO_HOST
+ port_env: MONGO_PORT
+ database_env: MONGO_DATABASE
+ user_env: MONGO_USER
+ password_env: MONGO_PASSWORD
+ auth_source_env: MONGO_AUTH_SOURCE
+ replica_set_env: MONGO_REPLICA_SET
+ enforcer:
+ driver: native
+ settings:
+ model_path_env: PERMISSION_MODEL
+ adapter:
+ collection_name_env: PERMISSION_COLLECTION
+ database_name_env: MONGO_DATABASE
+ timeout_seconds_env: PERMISSION_TIMEOUT
+ is_filtered_env: PERMISSION_IS_FILTERED
diff --git a/api/notification/go.mod b/api/notification/go.mod
index cab14e59..c2e9d447 100644
--- a/api/notification/go.mod
+++ b/api/notification/go.mod
@@ -1,6 +1,6 @@
module github.com/tech/sendico/notification
-go 1.25.3
+go 1.25.6
replace github.com/tech/sendico/pkg => ../pkg
@@ -52,7 +52,7 @@ require (
golang.org/x/net v0.49.0 // indirect
golang.org/x/sync v0.19.0 // indirect
golang.org/x/sys v0.40.0 // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 // indirect
google.golang.org/grpc v1.78.0 // indirect
google.golang.org/protobuf v1.36.11 // indirect
)
diff --git a/api/notification/go.sum b/api/notification/go.sum
index 560ac6b4..dfbd8baf 100644
--- a/api/notification/go.sum
+++ b/api/notification/go.sum
@@ -229,8 +229,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d h1:xXzuihhT3gL/ntduUZwHECzAn57E8dA6l8SOtYWdD8Q=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20260122232226-8e98ce8d340d/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409 h1:H86B94AW+VfJWDqFeEbBPhEtHzJwJfTbgE2lZa54ZAQ=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20260128011058-8636f8732409/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
diff --git a/api/notification/i18n/en.json b/api/notification/i18n/en.json
index 41e0bec7..c67bbfa3 100644
--- a/api/notification/i18n/en.json
+++ b/api/notification/i18n/en.json
@@ -25,15 +25,6 @@
"mail.email-changed.subj": "{{.ServiceName}}: your email address has been changed",
"mail.email-changed.greeting": "Hi, {{.Name}}",
"mail.email-changed.body": "You changed your email address to {{.NewEmail}}.
If you have not changed your email address please contact us under {{.SupportMail}}",
- "mail.booking-confirmation.subj": "{{.ServiceName}}: your meeting confirmation",
- "mail.booking-confirmation.greeting": "Hi, {{.Name}}",
- "mail.booking-confirmation.body": "Your meeting time slot is confirmed on {{.Date}} at {{.Time}}.
Should you feel like rescheduling your meeting, follow this link.
If you want to cancel your meeting, click here.",
- "mail.booking-cancellation.subj": "{{.ServiceName}}: your meeting was cancelled",
- "mail.booking-cancellation.greeting": "Hi, {{.Name}}",
- "mail.booking-cancellation.body": "Your meeting on {{.Date}} at {{.Time}} was cancelled.",
- "mail.booking-reschedule.subj": "{{.ServiceName}}: your meeting was rescheduled",
- "mail.booking-reschedule.greeting": "Hi, {{.Name}}",
- "mail.booking-reschedule.body": "Your meeting was rescheduled for a new time on {{.Date}} at {{.Time}}.
Should you feel like rescheduling your meeting again, follow this link.
If you want to cancel your meeting, click here.",
"mail.template.privacy": "Privacy policy",
"mail.template.unsubscribe": "Unsubscribe",
"btn.verify": "Verify",
diff --git a/api/notification/i18n/ru.json b/api/notification/i18n/ru.json
index b1fe7b71..9bddde12 100644
--- a/api/notification/i18n/ru.json
+++ b/api/notification/i18n/ru.json
@@ -25,15 +25,6 @@
"mail.email-changed.subj": "{{.ServiceName}}: ваш адрес изменен",
"mail.email-changed.greeting": "День добрый, {{.Name}}",
"mail.email-changed.body": "Вы изменили свой адрес электронной почты на {{.NewEmail}}.
Если вы не запрашвали и не подтверждали смену электронной почты, свяжитесь с нами по адресу {{.SupportMail}}",
- "mail.booking-confirmation.subj": "{{.ServiceName}}: ваша встреча подтверждена",
- "mail.booking-confirmation.greeting": "День добрый, {{.Name}}",
- "mail.booking-confirmation.body": "Время вашей встречи подтверждено на {{.Date}} в {{.Time}}.
Если вы хотите перенести встречу, перейдите по этой ссылке.
Если вы хотите отменить встречу, нажмите здесь.",
- "mail.booking-cancellation.subj": "{{.ServiceName}}: ваша встреча отменена",
- "mail.booking-cancellation.greeting": "День добрый, {{.Name}}",
- "mail.booking-cancellation.body": "Ваша встреча {{.Date}} в {{.Time}} была отменена.",
- "mail.booking-reschedule.subj": "{{.ServiceName}}: ваша встреча назначена на новое время",
- "mail.booking-reschedule.greeting": "День добрый, {{.Name}}",
- "mail.booking-reschedule.body": "Ваша встреча была перенесена на новое время {{.Date}} в {{.Time}}.
Если вы хотите перенести встречу еще раз, перейдите по этой ссылке.
Если вы хотите отменить встречу, нажмите тут.",
"mail.template.privacy": "Политика конфиденциальности",
"mail.template.unsubscribe": "Отписаться",
"btn.verify": "Подтвердить",
diff --git a/api/notification/internal/server/notificationimp/mail/internal/builder/email.go b/api/notification/internal/server/notificationimp/mail/internal/builder/email.go
index d661d33e..753c6056 100644
--- a/api/notification/internal/server/notificationimp/mail/internal/builder/email.go
+++ b/api/notification/internal/server/notificationimp/mail/internal/builder/email.go
@@ -54,7 +54,7 @@ func (m *EmailNotificationTemplate) prepareUnsubscribe(msg mmail.Message) error
return nil
}
-func (m *EmailNotificationTemplate) prepareButton(msg mmail.Message) error {
+func (m *EmailNotificationTemplate) prepareButton(_ mmail.Message) error {
var block string
if m.hasButton {
var err error