up
This commit is contained in:
@@ -110,6 +110,7 @@ const (
|
||||
keyEmailUser = "email.smtp_user"
|
||||
keyEmailPassword = "email.smtp_password"
|
||||
keyEmailFrom = "email.from"
|
||||
keyEmailReplyTo = "email.reply_to" // optional Reply-To: replies go here, not the From sender
|
||||
keyEmailEncryption = "email.encryption" // "ssl" | "starttls" | "none"
|
||||
keyEmailAuth = "email.auth" // "1" → SMTP requires authorization (send user/password)
|
||||
keyEmailAutoSend = "email.auto_send" // "1" → auto-send recording on log when an e-mail is known
|
||||
@@ -3438,13 +3439,19 @@ func (a *App) saveQSORecording(q *qso.QSO) {
|
||||
parts = append(parts, time.Now().UTC().Format("20060102_150405"))
|
||||
name := strings.Join(parts, "_") + "." + ext
|
||||
path := filepath.Join(a.qsoRecDir(), name)
|
||||
if err := a.qsoRec.SaveQSO(path); err != nil {
|
||||
applog.Printf("qso-rec: save failed: %v", err)
|
||||
|
||||
// Snapshot the audio synchronously (fast — frees the recorder for the next
|
||||
// QSO). The slow part is encoding the file (a long MP3), which we defer to a
|
||||
// goroutine so logging stays snappy.
|
||||
pcm, err := a.qsoRec.TakeQSO()
|
||||
if err != nil {
|
||||
applog.Printf("qso-rec: snapshot failed: %v", err)
|
||||
return
|
||||
}
|
||||
applog.Printf("qso-rec: saved %s", path)
|
||||
|
||||
// Remember the recording on the QSO so it can be e-mailed later.
|
||||
// Stamp the recording's path on the QSO now, synchronously, so it's set
|
||||
// before the eQSL auto-send reads the QSO (their full-row Updates would
|
||||
// otherwise race and clobber each other's extras).
|
||||
if q.ID != 0 {
|
||||
if q.Extras == nil {
|
||||
q.Extras = map[string]string{}
|
||||
@@ -3455,11 +3462,18 @@ func (a *App) saveQSORecording(q *qso.QSO) {
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-send to the correspondent when enabled and an e-mail is known.
|
||||
if es, _ := a.GetEmailSettings(); es.Enabled && es.AutoSend && strings.TrimSpace(q.Email) != "" {
|
||||
qc := *q
|
||||
go func() { _ = a.sendRecordingEmail(qc, path) }()
|
||||
}
|
||||
qc := *q
|
||||
go func() {
|
||||
if err := audio.WritePCM(path, pcm); err != nil {
|
||||
applog.Printf("qso-rec: save failed: %v", err)
|
||||
return
|
||||
}
|
||||
applog.Printf("qso-rec: saved %s", path)
|
||||
// Auto-send the recording once the file exists.
|
||||
if es, _ := a.GetEmailSettings(); es.Enabled && es.AutoSend && strings.TrimSpace(qc.Email) != "" {
|
||||
_ = a.sendRecordingEmail(qc, path)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// sanitizeFilename makes a callsign safe for a filename (slashes etc.).
|
||||
@@ -3527,6 +3541,7 @@ type EmailSettings struct {
|
||||
User string `json:"smtp_user"`
|
||||
Password string `json:"smtp_password"`
|
||||
From string `json:"from"`
|
||||
ReplyTo string `json:"reply_to"` // optional — where correspondents' replies go
|
||||
Encryption string `json:"encryption"` // "ssl" | "starttls" | "none"
|
||||
Auth bool `json:"auth"` // SMTP requires authorization
|
||||
AutoSend bool `json:"auto_send"`
|
||||
@@ -3542,7 +3557,7 @@ func (a *App) GetEmailSettings() (EmailSettings, error) {
|
||||
}
|
||||
m, err := a.settings.GetMany(a.ctx,
|
||||
keyEmailEnabled, keyEmailHost, keyEmailPort, keyEmailUser, keyEmailPassword,
|
||||
keyEmailFrom, keyEmailEncryption, keyEmailAuth, keyEmailAutoSend, keyEmailSubject, keyEmailBody)
|
||||
keyEmailFrom, keyEmailReplyTo, keyEmailEncryption, keyEmailAuth, keyEmailAutoSend, keyEmailSubject, keyEmailBody)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
@@ -3554,6 +3569,7 @@ func (a *App) GetEmailSettings() (EmailSettings, error) {
|
||||
out.User = m[keyEmailUser]
|
||||
out.Password = m[keyEmailPassword]
|
||||
out.From = m[keyEmailFrom]
|
||||
out.ReplyTo = m[keyEmailReplyTo]
|
||||
if e := m[keyEmailEncryption]; e == "ssl" || e == "starttls" || e == "none" {
|
||||
out.Encryption = e
|
||||
}
|
||||
@@ -3593,6 +3609,7 @@ func (a *App) SaveEmailSettings(s EmailSettings) error {
|
||||
keyEmailUser: strings.TrimSpace(s.User),
|
||||
keyEmailPassword: s.Password,
|
||||
keyEmailFrom: strings.TrimSpace(s.From),
|
||||
keyEmailReplyTo: strings.TrimSpace(s.ReplyTo),
|
||||
keyEmailEncryption: enc,
|
||||
keyEmailAuth: b2s(s.Auth),
|
||||
keyEmailAutoSend: b2s(s.AutoSend),
|
||||
@@ -3607,7 +3624,7 @@ func (a *App) SaveEmailSettings(s EmailSettings) error {
|
||||
}
|
||||
|
||||
func (a *App) emailConfig(s EmailSettings) email.Config {
|
||||
return email.Config{Host: s.Host, Port: s.Port, User: s.User, Password: s.Password, From: s.From, Encryption: s.Encryption, Auth: s.Auth}
|
||||
return email.Config{Host: s.Host, Port: s.Port, User: s.User, Password: s.Password, From: s.From, ReplyTo: s.ReplyTo, Encryption: s.Encryption, Auth: s.Auth}
|
||||
}
|
||||
|
||||
// TestEmail sends a test message to `to` (defaults to the From address) to
|
||||
|
||||
Reference in New Issue
Block a user