mirror of
https://github.com/binwiederhier/ntfy.git
synced 2026-05-15 07:35:49 -06:00
Refine
This commit is contained in:
parent
6aebc5c677
commit
3e634e0a5a
8 changed files with 42 additions and 25 deletions
|
|
@ -56,8 +56,23 @@ func (s *Sender) Close() {
|
|||
close(s.closeChan)
|
||||
}
|
||||
|
||||
// Send sends a plain text email via SMTP
|
||||
func (s *Sender) Send(to, subject, body string) error {
|
||||
// Addr returns the SMTP server address
|
||||
func (s *Sender) Addr() string {
|
||||
return s.config.SMTPAddr
|
||||
}
|
||||
|
||||
// User returns the SMTP username
|
||||
func (s *Sender) User() string {
|
||||
return s.config.SMTPUser
|
||||
}
|
||||
|
||||
// From returns the sender email address
|
||||
func (s *Sender) From() string {
|
||||
return s.config.From
|
||||
}
|
||||
|
||||
// SendRaw sends a raw email message via SMTP
|
||||
func (s *Sender) SendRaw(to string, message []byte) error {
|
||||
host, _, err := net.SplitHostPort(s.config.SMTPAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -66,6 +81,11 @@ func (s *Sender) Send(to, subject, body string) error {
|
|||
if s.config.SMTPUser != "" {
|
||||
auth = smtp.PlainAuth("", s.config.SMTPUser, s.config.SMTPPass, host)
|
||||
}
|
||||
return smtp.SendMail(s.config.SMTPAddr, auth, s.config.From, []string{to}, message)
|
||||
}
|
||||
|
||||
// Send sends a plain text email via SMTP
|
||||
func (s *Sender) Send(to, subject, body string) error {
|
||||
date := time.Now().UTC().Format(time.RFC1123Z)
|
||||
encodedSubject := mime.BEncoding.Encode("utf-8", subject)
|
||||
message := `From: ntfy <{from}>
|
||||
|
|
@ -81,7 +101,7 @@ Content-Type: text/plain; charset="utf-8"
|
|||
message = strings.ReplaceAll(message, "{subject}", encodedSubject)
|
||||
message = strings.ReplaceAll(message, "{body}", body)
|
||||
log.Tag("mail").Field("email_to", to).Debug("Sending email")
|
||||
return smtp.SendMail(s.config.SMTPAddr, auth, s.config.From, []string{to}, []byte(message))
|
||||
return s.SendRaw(to, []byte(message))
|
||||
}
|
||||
|
||||
// SendVerification generates a random code, stores it in-memory, and sends a verification email
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ var (
|
|||
errHTTPBadRequestSequenceIDInvalid = &errHTTP{40049, http.StatusBadRequest, "invalid request: sequence ID invalid", "https://ntfy.sh/docs/publish/#updating-deleting-notifications", nil}
|
||||
errHTTPBadRequestEmailAddressInvalid = &errHTTP{40050, http.StatusBadRequest, "invalid request: invalid e-mail address", "https://ntfy.sh/docs/publish/#e-mail-notifications", nil}
|
||||
errHTTPBadRequestEmailVerificationCodeInvalid = &errHTTP{40051, http.StatusBadRequest, "invalid request: email verification code invalid or expired", "", nil}
|
||||
errHTTPBadRequestEmailAddressNotVerified = &errHTTP{40052, http.StatusBadRequest, "invalid request: email address not verified, or no matching verified email addresses found", "https://ntfy.sh/docs/publish/#e-mail-notifications", nil}
|
||||
errHTTPBadRequestEmailAddressNotVerified = &errHTTP{40052, http.StatusBadRequest, "invalid request: email address not verified", "https://ntfy.sh/docs/publish/#e-mail-notifications", nil}
|
||||
errHTTPBadRequestAnonymousEmailNotAllowed = &errHTTP{40053, http.StatusBadRequest, "invalid request: anonymous email sending is not allowed", "https://ntfy.sh/docs/publish/#e-mail-notifications", nil}
|
||||
errHTTPNotFound = &errHTTP{40401, http.StatusNotFound, "page not found", "", nil}
|
||||
errHTTPUnauthorized = &errHTTP{40101, http.StatusUnauthorized, "unauthorized", "https://ntfy.sh/docs/publish/#authentication", nil}
|
||||
|
|
|
|||
|
|
@ -179,13 +179,13 @@ func New(conf *Config) (*Server, error) {
|
|||
var mailer mailer
|
||||
var mailSender *mail.Sender
|
||||
if conf.SMTPSenderAddr != "" {
|
||||
mailer = &smtpSender{config: conf}
|
||||
mailSender = mail.NewSender(&mail.Config{
|
||||
SMTPAddr: conf.SMTPSenderAddr,
|
||||
SMTPUser: conf.SMTPSenderUser,
|
||||
SMTPPass: conf.SMTPSenderPass,
|
||||
From: conf.SMTPSenderFrom,
|
||||
})
|
||||
mailer = &smtpSender{config: conf, sender: mailSender}
|
||||
}
|
||||
var stripe stripeAPI
|
||||
if payments.Available && conf.StripeSecretKey != "" {
|
||||
|
|
@ -721,6 +721,7 @@ func (s *Server) configResponse() *apiConfigResponse {
|
|||
EnablePayments: s.config.StripeSecretKey != "",
|
||||
EnableCalls: s.config.TwilioAccount != "",
|
||||
EnableEmails: s.config.SMTPSenderFrom != "",
|
||||
EnableEmailVerify: s.config.SMTPSenderVerify,
|
||||
EnableReservations: s.config.EnableReservations,
|
||||
EnableWebPush: s.config.WebPushPublicKey != "",
|
||||
BillingContact: s.config.BillingContact,
|
||||
|
|
@ -1202,7 +1203,7 @@ func (s *Server) parsePublishParams(r *http.Request, m *model.Message) (cache bo
|
|||
m.Icon = icon
|
||||
}
|
||||
email = readParam(r, "x-email", "x-e-mail", "email", "e-mail", "mail", "e")
|
||||
if email != "" && !emailAddressRegex.MatchString(email) {
|
||||
if email != "" && !emailAddressRegex.MatchString(email) && !toBool(email) {
|
||||
return false, false, "", "", "", false, "", errHTTPBadRequestEmailAddressInvalid
|
||||
}
|
||||
if s.smtpSender == nil && email != "" {
|
||||
|
|
|
|||
|
|
@ -689,6 +689,9 @@ func (s *Server) handleAccountEmailDelete(w http.ResponseWriter, r *http.Request
|
|||
// in their verified list. "yes"/"true"/"1" resolves to the first verified email.
|
||||
func (s *Server) convertEmailAddress(u *user.User, email string) (string, *errHTTP) {
|
||||
if !s.config.SMTPSenderVerify {
|
||||
if toBool(email) {
|
||||
return "", errHTTPBadRequestEmailAddressInvalid
|
||||
}
|
||||
return email, nil
|
||||
} else if u == nil {
|
||||
return "", errHTTPBadRequestAnonymousEmailNotAllowed
|
||||
|
|
|
|||
|
|
@ -5,13 +5,12 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"mime"
|
||||
"net"
|
||||
"net/smtp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"heckel.io/ntfy/v2/log"
|
||||
"heckel.io/ntfy/v2/mail"
|
||||
"heckel.io/ntfy/v2/model"
|
||||
"heckel.io/ntfy/v2/util"
|
||||
)
|
||||
|
|
@ -23,6 +22,7 @@ type mailer interface {
|
|||
|
||||
type smtpSender struct {
|
||||
config *Config
|
||||
sender *mail.Sender
|
||||
success int64
|
||||
failure int64
|
||||
mu sync.Mutex
|
||||
|
|
@ -30,31 +30,23 @@ type smtpSender struct {
|
|||
|
||||
func (s *smtpSender) Send(v *visitor, m *model.Message, to string) error {
|
||||
return s.withCount(v, m, func() error {
|
||||
host, _, err := net.SplitHostPort(s.config.SMTPSenderAddr)
|
||||
message, err := formatMail(s.config.BaseURL, v.ip.String(), s.sender.From(), to, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
message, err := formatMail(s.config.BaseURL, v.ip.String(), s.config.SMTPSenderFrom, to, m)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var auth smtp.Auth
|
||||
if s.config.SMTPSenderUser != "" {
|
||||
auth = smtp.PlainAuth("", s.config.SMTPSenderUser, s.config.SMTPSenderPass, host)
|
||||
}
|
||||
ev := logvm(v, m).
|
||||
Tag(tagEmail).
|
||||
Fields(log.Context{
|
||||
"email_via": s.config.SMTPSenderAddr,
|
||||
"email_user": s.config.SMTPSenderUser,
|
||||
"email_via": s.sender.Addr(),
|
||||
"email_user": s.sender.User(),
|
||||
"email_to": to,
|
||||
})
|
||||
if ev.IsTrace() {
|
||||
ev.Field("email_body", message).Trace("Sending email")
|
||||
} else if ev.IsDebug() {
|
||||
ev.Debug("Sending email")
|
||||
ev.Info("Sending email")
|
||||
}
|
||||
return smtp.SendMail(s.config.SMTPSenderAddr, auth, s.config.SMTPSenderFrom, []string{to}, []byte(message))
|
||||
return s.sender.SendRaw(to, []byte(message))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ type apiConfigResponse struct {
|
|||
EnablePayments bool `json:"enable_payments"`
|
||||
EnableCalls bool `json:"enable_calls"`
|
||||
EnableEmails bool `json:"enable_emails"`
|
||||
EnableEmailVerify bool `json:"enable_email_verify"`
|
||||
EnableReservations bool `json:"enable_reservations"`
|
||||
EnableWebPush bool `json:"enable_web_push"`
|
||||
BillingContact string `json:"billing_contact"`
|
||||
|
|
|
|||
|
|
@ -215,7 +215,7 @@
|
|||
"account_basics_phone_numbers_dialog_check_verification_button": "Confirm code",
|
||||
"account_basics_phone_numbers_dialog_channel_sms": "SMS",
|
||||
"account_basics_phone_numbers_dialog_channel_call": "Call",
|
||||
"account_basics_emails_title": "Verified email recipients",
|
||||
"account_basics_emails_title": "Email addresses",
|
||||
"account_basics_emails_description": "For email notifications",
|
||||
"account_basics_emails_no_emails_yet": "No verified emails yet",
|
||||
"account_basics_emails_copied_to_clipboard": "Email address copied to clipboard",
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ const Basics = () => {
|
|||
<PrefGroup>
|
||||
<Username />
|
||||
<ChangePassword />
|
||||
<VerifiedEmails />
|
||||
<Emails />
|
||||
<PhoneNumbers />
|
||||
<AccountType />
|
||||
</PrefGroup>
|
||||
|
|
@ -355,7 +355,7 @@ const AccountType = () => {
|
|||
);
|
||||
};
|
||||
|
||||
const VerifiedEmails = () => {
|
||||
const Emails = () => {
|
||||
const { t } = useTranslation();
|
||||
const { account } = useContext(AccountContext);
|
||||
const [dialogKey, setDialogKey] = useState(0);
|
||||
|
|
@ -388,7 +388,7 @@ const VerifiedEmails = () => {
|
|||
}
|
||||
};
|
||||
|
||||
if (!config.enable_emails) {
|
||||
if (!config.enable_email_verify) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue