mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-11-14 06:10:10 +00:00
Compare commits
No commits in common. "9ae16163bb1b73d7a596ce07b3d4553d5d4502af" and "5ff38392392d9902f34bf119d99129c49e456a9b" have entirely different histories.
9ae16163bb
...
5ff3839239
161
email.go
161
email.go
@ -13,6 +13,7 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
textTemplate "text/template"
|
||||
"time"
|
||||
|
||||
@ -30,6 +31,84 @@ type EmailClient interface {
|
||||
Send(fromName, fromAddr string, message *Message, address ...string) error
|
||||
}
|
||||
|
||||
type DummyClient struct{}
|
||||
|
||||
func (dc *DummyClient) Send(fromName, fromAddr string, email *Message, address ...string) error {
|
||||
fmt.Printf("FROM: %s <%s>\nTO: %s\nTEXT: %s\n", fromName, fromAddr, strings.Join(address, ", "), email.Text)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Mailgun client implements EmailClient.
|
||||
type Mailgun struct {
|
||||
client *mailgun.MailgunImpl
|
||||
}
|
||||
|
||||
func (mg *Mailgun) Send(fromName, fromAddr string, email *Message, address ...string) error {
|
||||
message := mg.client.NewMessage(
|
||||
fmt.Sprintf("%s <%s>", fromName, fromAddr),
|
||||
email.Subject,
|
||||
email.Text,
|
||||
)
|
||||
for _, a := range address {
|
||||
// Adding variable tells mailgun to do a batch send, so users don't see other recipients.
|
||||
message.AddRecipientAndVariables(a, map[string]interface{}{"unique_id": a})
|
||||
}
|
||||
message.SetHtml(email.HTML)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
_, _, err := mg.client.Send(ctx, message)
|
||||
return err
|
||||
}
|
||||
|
||||
// SMTP supports SSL/TLS and STARTTLS; implements EmailClient.
|
||||
type SMTP struct {
|
||||
Client *sMail.SMTPServer
|
||||
}
|
||||
|
||||
func (sm *SMTP) Send(fromName, fromAddr string, email *Message, address ...string) error {
|
||||
from := fmt.Sprintf("%s <%s>", fromName, fromAddr)
|
||||
var cli *sMail.SMTPClient
|
||||
var err error
|
||||
cli, err = sm.Client.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cli.Close()
|
||||
var wg sync.WaitGroup
|
||||
for _, addr := range address {
|
||||
wg.Add(1)
|
||||
go func(addr string) {
|
||||
defer wg.Done()
|
||||
e := sMail.NewMSG()
|
||||
e.SetFrom(from)
|
||||
e.SetSubject(email.Subject)
|
||||
e.AddTo(addr)
|
||||
if email.HTML == "" {
|
||||
e.SetBody(sMail.TextPlain, email.Text)
|
||||
} else {
|
||||
e.SetBody(sMail.TextHTML, email.HTML)
|
||||
e.AddAlternative(sMail.TextPlain, email.Text)
|
||||
}
|
||||
err = e.Send(cli)
|
||||
// e := jEmail.NewEmail()
|
||||
// e.Subject = email.Subject
|
||||
// e.From = from
|
||||
// e.Text = []byte(email.Text)
|
||||
// e.HTML = []byte(email.HTML)
|
||||
// e.To = []string{addr}
|
||||
// err = sm.Pool.Send(e, 15*time.Second)
|
||||
// if sm.sslTLS {
|
||||
// err = sm.Pool.S
|
||||
// err = e.SendWithTLS(server, sm.auth, sm.tlsConfig)
|
||||
// } else {
|
||||
// err = e.SendWithStartTLS(server, sm.auth, sm.tlsConfig)
|
||||
// }
|
||||
}(addr)
|
||||
}
|
||||
wg.Wait()
|
||||
return err
|
||||
}
|
||||
|
||||
// Emailer contains the email sender, translations, and methods to construct messages.
|
||||
type Emailer struct {
|
||||
fromAddr, fromName string
|
||||
@ -96,17 +175,18 @@ func NewEmailer(app *appContext) *Emailer {
|
||||
return emailer
|
||||
}
|
||||
|
||||
// DummyClient just logs the email to the console for debugging purposes. It can be used by settings [email]/method to "dummy".
|
||||
type DummyClient struct{}
|
||||
|
||||
func (dc *DummyClient) Send(fromName, fromAddr string, email *Message, address ...string) error {
|
||||
fmt.Printf("FROM: %s <%s>\nTO: %s\nTEXT: %s\n", fromName, fromAddr, strings.Join(address, ", "), email.Text)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SMTP supports SSL/TLS and STARTTLS; implements EmailClient.
|
||||
type SMTP struct {
|
||||
Client *sMail.SMTPServer
|
||||
// NewMailgun returns a Mailgun emailClient.
|
||||
func (emailer *Emailer) NewMailgun(url, key string) {
|
||||
sender := &Mailgun{
|
||||
client: mailgun.NewMailgun(strings.Split(emailer.fromAddr, "@")[1], key),
|
||||
}
|
||||
// Mailgun client takes the base url, so we need to trim off the end (e.g 'v3/messages')
|
||||
if strings.Contains(url, "messages") {
|
||||
url = url[0:strings.LastIndex(url, "/")]
|
||||
url = url[0:strings.LastIndex(url, "/")]
|
||||
}
|
||||
sender.client.SetAPIBase(url)
|
||||
emailer.sender = sender
|
||||
}
|
||||
|
||||
// NewSMTP returns an SMTP emailClient.
|
||||
@ -157,65 +237,6 @@ func (emailer *Emailer) NewSMTP(server string, port int, username, password stri
|
||||
return
|
||||
}
|
||||
|
||||
func (sm *SMTP) Send(fromName, fromAddr string, email *Message, address ...string) error {
|
||||
from := fmt.Sprintf("%s <%s>", fromName, fromAddr)
|
||||
var cli *sMail.SMTPClient
|
||||
var err error
|
||||
cli, err = sm.Client.Connect()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cli.Close()
|
||||
e := sMail.NewMSG()
|
||||
e.SetFrom(from)
|
||||
e.SetSubject(email.Subject)
|
||||
e.AddTo(address...)
|
||||
if email.HTML == "" {
|
||||
e.SetBody(sMail.TextPlain, email.Text)
|
||||
} else {
|
||||
e.SetBody(sMail.TextHTML, email.HTML)
|
||||
e.AddAlternative(sMail.TextPlain, email.Text)
|
||||
}
|
||||
err = e.Send(cli)
|
||||
return err
|
||||
}
|
||||
|
||||
// Mailgun client implements EmailClient.
|
||||
type Mailgun struct {
|
||||
client *mailgun.MailgunImpl
|
||||
}
|
||||
|
||||
// NewMailgun returns a Mailgun emailClient.
|
||||
func (emailer *Emailer) NewMailgun(url, key string) {
|
||||
sender := &Mailgun{
|
||||
client: mailgun.NewMailgun(strings.Split(emailer.fromAddr, "@")[1], key),
|
||||
}
|
||||
// Mailgun client takes the base url, so we need to trim off the end (e.g 'v3/messages')
|
||||
if strings.Contains(url, "messages") {
|
||||
url = url[0:strings.LastIndex(url, "/")]
|
||||
url = url[0:strings.LastIndex(url, "/")]
|
||||
}
|
||||
sender.client.SetAPIBase(url)
|
||||
emailer.sender = sender
|
||||
}
|
||||
|
||||
func (mg *Mailgun) Send(fromName, fromAddr string, email *Message, address ...string) error {
|
||||
message := mg.client.NewMessage(
|
||||
fmt.Sprintf("%s <%s>", fromName, fromAddr),
|
||||
email.Subject,
|
||||
email.Text,
|
||||
)
|
||||
for _, a := range address {
|
||||
// Adding variable tells mailgun to do a batch send, so users don't see other recipients.
|
||||
message.AddRecipientAndVariables(a, map[string]interface{}{"unique_id": a})
|
||||
}
|
||||
message.SetHtml(email.HTML)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
|
||||
defer cancel()
|
||||
_, _, err := mg.client.Send(ctx, message)
|
||||
return err
|
||||
}
|
||||
|
||||
type templ interface {
|
||||
Execute(wr io.Writer, data interface{}) error
|
||||
}
|
||||
|
@ -100,8 +100,7 @@
|
||||
"searchDiscordUser": "Gib den Discord-Benutzername ein, um den Benutzer zu finden.",
|
||||
"findDiscordUser": "Suche Discord-Benutzer",
|
||||
"linkMatrixDescription": "Gib den Benutzernamen und das Passwort des Benutzers ein, der als Bot verwendet werden soll. Nach dem Absenden wird die App neu gestartet.",
|
||||
"matrixHomeServer": "Adresse des Homeservers",
|
||||
"templates": "Vorlagen"
|
||||
"matrixHomeServer": "Adresse des Homeservers"
|
||||
},
|
||||
"notifications": {
|
||||
"changedEmailAddress": "E-Mail-Adresse von {n} geändert.",
|
||||
@ -141,8 +140,7 @@
|
||||
"noUpdatesAvailable": "Keinen neuen Aktualisierungen verfügbar.",
|
||||
"updateAppliedRefresh": "Update angewendet, bitte aktualisieren.",
|
||||
"telegramVerified": "Telegram-Konto verifiziert.",
|
||||
"accountConnected": "Konto verbunden.",
|
||||
"savedAnnouncement": "Ankündigung gespeichert."
|
||||
"accountConnected": "Konto verbunden."
|
||||
},
|
||||
"quantityStrings": {
|
||||
"modifySettingsFor": {
|
||||
|
@ -101,11 +101,7 @@
|
||||
"findDiscordUser": "Trouver l'utilisateur Discord",
|
||||
"linkMatrixDescription": "Entrez le nom d'utilisateur et le mot de passe de l'utilisateur pour l’utilisateur comme bot. Une fois soumis, l'application va redémarrer.",
|
||||
"searchDiscordUser": "Commencez à taper le nom d'utilisateur Discord pour trouver l'utilisateur.",
|
||||
"matrixHomeServer": "Adresse du serveur domestique",
|
||||
"saveAsTemplate": "Sauvegarder comme modèle",
|
||||
"templateEnterName": "Entrez un nom pour sauvegarder ce modèle.",
|
||||
"deleteTemplate": "Supprimer le modèle",
|
||||
"templates": "Modèles"
|
||||
"matrixHomeServer": "Adresse du serveur"
|
||||
},
|
||||
"notifications": {
|
||||
"changedEmailAddress": "Adresse e-mail modifiée de {n}.",
|
||||
@ -145,8 +141,7 @@
|
||||
"noUpdatesAvailable": "Aucune nouvelle mise à jour disponible.",
|
||||
"telegramVerified": "Compte Telegram vérifié.",
|
||||
"updateAppliedRefresh": "Mise à jour appliquée, veuillez actualiser.",
|
||||
"accountConnected": "Compte connecté.",
|
||||
"savedAnnouncement": "Annonce enregistrée."
|
||||
"accountConnected": "Compte connecté."
|
||||
},
|
||||
"quantityStrings": {
|
||||
"modifySettingsFor": {
|
||||
|
@ -7,7 +7,7 @@
|
||||
"pageTitle": "Créer un compte Jellyfin",
|
||||
"createAccountHeader": "Création du compte",
|
||||
"accountDetails": "Détails",
|
||||
"emailAddress": "E-mail",
|
||||
"emailAddress": "Email",
|
||||
"username": "Nom d'utilisateur",
|
||||
"password": "Mot de passe",
|
||||
"reEnterPassword": "Confirmez mot de passe",
|
||||
|
@ -15,11 +15,7 @@
|
||||
"serverAddress": "Adresse du serveur",
|
||||
"emailSubject": "Objet de l'e-mail",
|
||||
"URL": "URL",
|
||||
"apiKey": "Clé API",
|
||||
"errorUserDisabled": "L'utilisateur est peut-être désactivé.",
|
||||
"error404": "404, vérifiez l'URL interne.",
|
||||
"errorInvalidUserPass": "Nom d'utilisateur/mot de passe invalide.",
|
||||
"errorNotAdmin": "L'utilisateur n'est pas autorisé à gérer le serveur."
|
||||
"apiKey": "Clé API"
|
||||
},
|
||||
"startPage": {
|
||||
"welcome": "Bienvenue !",
|
||||
@ -29,7 +25,7 @@
|
||||
},
|
||||
"endPage": {
|
||||
"finished": "Terminé !",
|
||||
"restartMessage": "Vous pouvez configurer les bots Discord/Telegram/Matrix, personnaliser vos messages et plus encore dans Paramètres. Cliquez ci-dessous pour redémarrer, puis actualisez la page.",
|
||||
"restartMessage": "Il y a d'autres paramètres que vous pouvez configurer sur la page administrateur. Cliquez en dessous pour redémarrer, rafraichissez ensuite la page.",
|
||||
"refreshPage": "Rafraichir"
|
||||
},
|
||||
"language": {
|
||||
@ -90,16 +86,16 @@
|
||||
"mailgunApiURL": "URL de l'API"
|
||||
},
|
||||
"notifications": {
|
||||
"title": "Notifications d'administrateur",
|
||||
"description": "Si activé, vous pouvez choisir (par invitation) de recevoir un message lorsque l'invitation expire, ou lorsque l'utilisateur est créé. Si vous ne choisissez pas la méthode de connexion par Jellyfin, assurez-vous d'avoir fourni votre adresse e-mail ou un autre moyen de contact."
|
||||
"title": "Notifications",
|
||||
"description": "Si activé, vous pouvez choisir (par invitation) de recevoir un e-mail lorsque l'invitation expire, ou lorsque l'utilisateur est créé. Si vous ne choisissez pas la méthode de connexion par Jellyfin, assurez-vous d'avoir fourni votre adresse e-mail."
|
||||
},
|
||||
"welcomeEmails": {
|
||||
"title": "Messages de bienvenue",
|
||||
"description": "Si activé, un message sera envoyé aux nouveaux utilisateurs avec l'URL de Jellyfin/Emby et leur nom d'utilisateur."
|
||||
"title": "E-mails de bienvenue",
|
||||
"description": "Si activé, un e-mail sera envoyé aux nouveaux utilisateurs avec l'URL de Jellyfin/Emby et leur nom d'utilisateur."
|
||||
},
|
||||
"inviteEmails": {
|
||||
"title": "Messages d'invitation",
|
||||
"description": "Si activé, vous pouvez envoyer une invitation directement à l'adresse e-mail, le Discord ou Matrix de l'utilisateur. Parce que vous pourriez utiliser un reverse proxy, vous devez renseigner l'URL d'accès aux invitations. Renseignez votre Base URL et ajoutez '/invite'."
|
||||
"title": "E-mails d'invitation",
|
||||
"description": "Si activé, vous pouvez envoyer une invitation directement à l'adresse e-mail de l'utilisateur. Parce que vous pourriez utiliser un reverse proxy, vous devez renseigner l'URL d'accès aux invitations. Renseignez votre Base URL et ajoutez '/invite'."
|
||||
},
|
||||
"passwordResets": {
|
||||
"title": "Réinitialisation de mot de passe",
|
||||
@ -108,9 +104,7 @@
|
||||
"pathToJellyfinNotice": "Si vous ne savez pas où c'est, essayez de réinitialiser votre mot de passe dans Jellyfin. Une popup avec '<path to jellyfin>/passwordreset-*.json' apparaitra.",
|
||||
"resetLinks": "Envoyer un lien plutôt qu'un PIN",
|
||||
"resetLinksNotice": "Si l'intégration est activée, utilisez ceci pour synchroniser les réinitialisations de mots de passe Jellyfin avec Ombi.",
|
||||
"resetLinksLanguage": "Langue du lien de réinitialisation par défaut",
|
||||
"setPassword": "Définir le mot de passe via le lien",
|
||||
"setPasswordNotice": "L'activation de cette option signifie que l'utilisateur n'a pas à modifier son mot de passe à partir du code PIN après la réinitialisation. La validation du mot de passe sera également appliquée."
|
||||
"resetLinksLanguage": "Langue du lien de réinitialisation par défaut"
|
||||
},
|
||||
"passwordValidation": {
|
||||
"title": "Validation du mot de passe",
|
||||
@ -139,9 +133,5 @@
|
||||
"updateChannel": "Mettre à jour la chaîne",
|
||||
"stable": "Stable",
|
||||
"unstable": "Instable"
|
||||
},
|
||||
"messages": {
|
||||
"title": "Messages",
|
||||
"description": "jfa-go peut envoyer des réinitialisations de mot de passe et divers messages par e-mail, Discord, Telegram et/ou Matrix. Vous pouvez configurer l'e-mail ci-dessous, et les autres peuvent être configurés dans les paramètres plus tard. Les instructions se trouvent sur le {n}. Si vous n'en avez pas besoin, vous pouvez désactiver ces fonctionnalités ici."
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user