@ -20,6 +20,7 @@ type emailClient interface {
send ( address , fromName , fromAddr string , email * Email ) error
send ( address , fromName , fromAddr string , email * Email ) error
}
}
// Mailgun client implements emailClient.
type Mailgun struct {
type Mailgun struct {
client * mailgun . MailgunImpl
client * mailgun . MailgunImpl
}
}
@ -38,14 +39,15 @@ func (mg *Mailgun) send(address, fromName, fromAddr string, email *Email) error
return err
return err
}
}
type Smtp struct {
// SMTP supports SSL/TLS and STARTTLS; implements emailClient.
sslTls bool
type SMTP struct {
sslTLS bool
host , server string
host , server string
port int
port int
auth smtp . Auth
auth smtp . Auth
}
}
func ( sm * S mtp ) send ( address , fromName , fromAddr string , email * Email ) error {
func ( sm * S MTP ) send ( address , fromName , fromAddr string , email * Email ) error {
e := jEmail . NewEmail ( )
e := jEmail . NewEmail ( )
e . Subject = email . subject
e . Subject = email . subject
e . From = fmt . Sprintf ( "%s <%s>" , fromName , fromAddr )
e . From = fmt . Sprintf ( "%s <%s>" , fromName , fromAddr )
@ -58,7 +60,7 @@ func (sm *Smtp) send(address, fromName, fromAddr string, email *Email) error {
}
}
server := fmt . Sprintf ( "%s:%d" , sm . server , sm . port )
server := fmt . Sprintf ( "%s:%d" , sm . server , sm . port )
var err error
var err error
if sm . sslT ls {
if sm . sslT LS {
err = e . SendWithTLS ( server , sm . auth , tlsConfig )
err = e . SendWithTLS ( server , sm . auth , tlsConfig )
} else {
} else {
err = e . SendWithStartTLS ( server , sm . auth , tlsConfig )
err = e . SendWithStartTLS ( server , sm . auth , tlsConfig )
@ -78,27 +80,28 @@ type Email struct {
html , text string
html , text string
}
}
func ( email * Emailer ) formatExpiry ( expiry time . Time , tzaware bool , datePattern , timePattern string ) ( d , t , expires _i n string ) {
func ( email er * Emailer ) formatExpiry ( expiry time . Time , tzaware bool , datePattern , timePattern string ) ( d , t , expires I n string ) {
d , _ = strtime . Strftime ( expiry , datePattern )
d , _ = strtime . Strftime ( expiry , datePattern )
t , _ = strtime . Strftime ( expiry , timePattern )
t , _ = strtime . Strftime ( expiry , timePattern )
current _t ime := time . Now ( )
current T ime := time . Now ( )
if tzaware {
if tzaware {
current _time = current_t ime. UTC ( )
current Time = currentT ime. UTC ( )
}
}
_ , _ , days , hours , minutes , _ := timeDiff ( expiry , current _t ime)
_ , _ , days , hours , minutes , _ := timeDiff ( expiry , current T ime)
if days != 0 {
if days != 0 {
expires _i n += fmt . Sprintf ( "%dd " , days )
expires I n += fmt . Sprintf ( "%dd " , days )
}
}
if hours != 0 {
if hours != 0 {
expires _i n += fmt . Sprintf ( "%dh " , hours )
expires I n += fmt . Sprintf ( "%dh " , hours )
}
}
if minutes != 0 {
if minutes != 0 {
expires _i n += fmt . Sprintf ( "%dm " , minutes )
expires I n += fmt . Sprintf ( "%dm " , minutes )
}
}
expires _in = strings . TrimSuffix ( expires_i n, " " )
expires In = strings . TrimSuffix ( expiresI n, " " )
return
return
}
}
// NewEmailer configures and returns a new emailer.
func NewEmailer ( app * appContext ) * Emailer {
func NewEmailer ( app * appContext ) * Emailer {
emailer := & Emailer {
emailer := & Emailer {
fromAddr : app . config . Section ( "email" ) . Key ( "address" ) . String ( ) ,
fromAddr : app . config . Section ( "email" ) . Key ( "address" ) . String ( ) ,
@ -117,6 +120,7 @@ func NewEmailer(app *appContext) *Emailer {
return emailer
return emailer
}
}
// NewMailgun returns a Mailgun emailClient.
func ( emailer * Emailer ) NewMailgun ( url , key string ) {
func ( emailer * Emailer ) NewMailgun ( url , key string ) {
sender := & Mailgun {
sender := & Mailgun {
client : mailgun . NewMailgun ( strings . Split ( emailer . fromAddr , "@" ) [ 1 ] , key ) ,
client : mailgun . NewMailgun ( strings . Split ( emailer . fromAddr , "@" ) [ 1 ] , key ) ,
@ -130,13 +134,14 @@ func (emailer *Emailer) NewMailgun(url, key string) {
emailer . sender = sender
emailer . sender = sender
}
}
func ( emailer * Emailer ) NewSMTP ( server string , port int , password , host string , sslTls bool ) {
// NewSMTP returns an SMTP emailClient.
emailer . sender = & Smtp {
func ( emailer * Emailer ) NewSMTP ( server string , port int , password , host string , sslTLS bool ) {
emailer . sender = & SMTP {
auth : smtp . PlainAuth ( "" , emailer . fromAddr , password , host ) ,
auth : smtp . PlainAuth ( "" , emailer . fromAddr , password , host ) ,
server : server ,
server : server ,
host : host ,
host : host ,
port : port ,
port : port ,
sslT ls: sslTls ,
sslT LS: sslTLS ,
}
}
}
}
@ -145,10 +150,10 @@ func (emailer *Emailer) constructInvite(code string, invite Invite, app *appCont
subject : app . config . Section ( "invite_emails" ) . Key ( "subject" ) . String ( ) ,
subject : app . config . Section ( "invite_emails" ) . Key ( "subject" ) . String ( ) ,
}
}
expiry := invite . ValidTill
expiry := invite . ValidTill
d , t , expires _i n := emailer . formatExpiry ( expiry , false , app . datePattern , app . timePattern )
d , t , expires I n := emailer . formatExpiry ( expiry , false , app . datePattern , app . timePattern )
message := app . config . Section ( "email" ) . Key ( "message" ) . String ( )
message := app . config . Section ( "email" ) . Key ( "message" ) . String ( )
invite _l ink := app . config . Section ( "invite_emails" ) . Key ( "url_base" ) . String ( )
invite L ink := app . config . Section ( "invite_emails" ) . Key ( "url_base" ) . String ( )
invite _l ink = fmt . Sprintf ( "%s/%s" , invite _l ink, code )
invite L ink = fmt . Sprintf ( "%s/%s" , invite L ink, code )
for _ , key := range [ ] string { "html" , "text" } {
for _ , key := range [ ] string { "html" , "text" } {
fpath := app . config . Section ( "invite_emails" ) . Key ( "email_" + key ) . String ( )
fpath := app . config . Section ( "invite_emails" ) . Key ( "email_" + key ) . String ( )
@ -160,8 +165,8 @@ func (emailer *Emailer) constructInvite(code string, invite Invite, app *appCont
err = tpl . Execute ( & tplData , map [ string ] string {
err = tpl . Execute ( & tplData , map [ string ] string {
"expiry_date" : d ,
"expiry_date" : d ,
"expiry_time" : t ,
"expiry_time" : t ,
"expires_in" : expires _i n,
"expires_in" : expires I n,
"invite_link" : invite _l ink,
"invite_link" : invite L ink,
"message" : message ,
"message" : message ,
} )
} )
if err != nil {
if err != nil {
@ -244,7 +249,7 @@ func (emailer *Emailer) constructReset(pwr Pwr, app *appContext) (*Email, error)
email := & Email {
email := & Email {
subject : app . config . Section ( "password_resets" ) . Key ( "subject" ) . MustString ( "Password reset - Jellyfin" ) ,
subject : app . config . Section ( "password_resets" ) . Key ( "subject" ) . MustString ( "Password reset - Jellyfin" ) ,
}
}
d , t , expires _i n := emailer . formatExpiry ( pwr . Expiry , true , app . datePattern , app . timePattern )
d , t , expires I n := emailer . formatExpiry ( pwr . Expiry , true , app . datePattern , app . timePattern )
message := app . config . Section ( "email" ) . Key ( "message" ) . String ( )
message := app . config . Section ( "email" ) . Key ( "message" ) . String ( )
for _ , key := range [ ] string { "html" , "text" } {
for _ , key := range [ ] string { "html" , "text" } {
fpath := app . config . Section ( "password_resets" ) . Key ( "email_" + key ) . String ( )
fpath := app . config . Section ( "password_resets" ) . Key ( "email_" + key ) . String ( )
@ -257,7 +262,7 @@ func (emailer *Emailer) constructReset(pwr Pwr, app *appContext) (*Email, error)
"username" : pwr . Username ,
"username" : pwr . Username ,
"expiry_date" : d ,
"expiry_date" : d ,
"expiry_time" : t ,
"expiry_time" : t ,
"expires_in" : expires _i n,
"expires_in" : expires I n,
"pin" : pwr . Pin ,
"pin" : pwr . Pin ,
"message" : message ,
"message" : message ,
} )
} )
@ -273,6 +278,7 @@ func (emailer *Emailer) constructReset(pwr Pwr, app *appContext) (*Email, error)
return email , nil
return email , nil
}
}
// calls the send method in the underlying emailClient.
func ( emailer * Emailer ) send ( address string , email * Email ) error {
func ( emailer * Emailer ) send ( address string , email * Email ) error {
return emailer . sender . send ( address , emailer . fromName , emailer . fromAddr , email )
return emailer . sender . send ( address , emailer . fromName , emailer . fromAddr , email )
}
}