Added STARTTLS for SMTP

As many services don't support full encryption, there is now an
encryption option in the [smtp] section, allowing you to choose between
ssl_tls and starttls.
This commit is contained in:
Harvey Tindall 2020-04-26 21:28:55 +01:00
parent 3499843878
commit 16a7ceb8ea
3 changed files with 29 additions and 16 deletions

View File

@ -76,7 +76,7 @@ optional arguments:
#### Emails/Password Resets #### Emails/Password Resets
* When someone initiates forget password on Jellyfin, a file named `passwordreset*.json` is created in its configuration directory. This directory is monitored and when created, the program reads the username, expiry time and PIN, puts it into a template and sends it to whatever address is specified in `emails.json`. * When someone initiates forget password on Jellyfin, a file named `passwordreset*.json` is created in its configuration directory. This directory is monitored and when created, the program reads the username, expiry time and PIN, puts it into a template and sends it to whatever address is specified in `emails.json`.
* **The default forget password popup references the `passwordreset*.json` file created. This is confusing for users, so a quick fix is to edit the `MessageForgotPasswordFileCreated` string in Jellyfin's language folder.** * **The default forget password popup references the `passwordreset*.json` file created. This is confusing for users, so a quick fix is to edit the `MessageForgotPasswordFileCreated` string in Jellyfin's language folder.**
* Currently, jellyfin-accounts supports generic SSL/TLS secured SMTP, and the [mailgun](https://mailgun.com) REST API. * Currently, jellyfin-accounts supports generic SSL/TLS or STARTTLS secured SMTP, and the [mailgun](https://mailgun.com) REST API.
* Email html is created using [mjml](https://mjml.io), and [jinja](https://github.com/pallets/jinja) templating is used. If you wish to create your own, ensure you use the same jinja expressions (`{{ pin }}`, etc.) as used in `data/email.mjml` or `invite-email.mjml`, and also create plain text versions for legacy email clients. * Email html is created using [mjml](https://mjml.io), and [jinja](https://github.com/pallets/jinja) templating is used. If you wish to create your own, ensure you use the same jinja expressions (`{{ pin }}`, etc.) as used in `data/email.mjml` or `invite-email.mjml`, and also create plain text versions for legacy email clients.
#### Configuration #### Configuration
@ -177,11 +177,11 @@ api_url = https://api.mailgun.net...
api_key = your api key api_key = your api key
[smtp] [smtp]
; Insecure SMTP hasn't been implemented, although I doubt many will need it. ; Choose between ssl_tls and starttls. Your provider should tell you which to use, but generally SSL/TLS is 465, STARTTLS 587
ssl = true encryption = starttls
server = smtp.jellyf.in server = smtp.jellyf.in
; Uses SMTP_SSL, so make sure the port is for this, not starttls. ; Uses SMTP_SSL, so make sure the port is for this, not starttls.
port = 465 port = 587
password = smtp password password = smtp password
[files] [files]

View File

@ -88,8 +88,8 @@ api_url = https://api.mailgun.net...
api_key = your api key api_key = your api key
[smtp] [smtp]
; Insecure SMTP hasn't been implemented, although I doubt many will need it. ; Choose between ssl_tls and starttls. Your provider should tell you which to use, but generally SSL/TLS is 465, STARTTLS 587
ssl = true encryption = starttls
server = smtp.jellyf.in server = smtp.jellyf.in
; Uses SMTP_SSL, so make sure the port is for this, not starttls. ; Uses SMTP_SSL, so make sure the port is for this, not starttls.
port = 465 port = 465

View File

@ -139,7 +139,6 @@ class Smtp(Email):
except ValueError: except ValueError:
self.port = 465 self.port = 465
log.debug(f'{self.address}: Defaulting to port {self.port}') log.debug(f'{self.address}: Defaulting to port {self.port}')
self.context = ssl.create_default_context()
def send(self): def send(self):
message = MIMEMultipart("alternative") message = MIMEMultipart("alternative")
@ -151,15 +150,29 @@ class Smtp(Email):
message.attach(text) message.attach(text)
message.attach(html) message.attach(html)
try: try:
with smtplib.SMTP_SSL(self.server, if config['smtp']['encryption'] == 'ssl_tls':
self.port, self.context = ssl.create_default_context()
context=self.context) as server: with smtplib.SMTP_SSL(self.server,
server.login(self.from_address, self.password) self.port,
server.sendmail(self.from_address, context=self.context) as server:
self.address, server.ehlo()
message.as_string()) server.login(self.from_address, self.password)
log.info(f'{self.address}: Sent via smtp') server.sendmail(self.from_address,
return True self.address,
message.as_string())
log.info(f'{self.address}: Sent via smtp (ssl/tls)')
return True
elif config['smtp']['encryption'] == 'starttls':
with smtplib.SMTP(self.server,
self.port) as server:
server.ehlo()
server.starttls()
server.login(self.from_address, self.password)
server.sendmail(self.from_address,
self.address,
message.as_string())
log.info(f'{self.address}: Sent via smtp (starttls)')
return True
except Exception as e: except Exception as e:
err = f'{self.address}: Failed to send via smtp: ' err = f'{self.address}: Failed to send via smtp: '
err += type(e).__name__ err += type(e).__name__