mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-14 19:33:52 +01:00
Added support for the HS to send emails. Use it to send password resets. Added email_smtp_server and email_from_address config args. Added emailutils.
This commit is contained in:
parent
5f30a69a9e
commit
cc83b06cd1
4 changed files with 130 additions and 2 deletions
39
synapse/config/email.py
Normal file
39
synapse/config/email.py
Normal file
|
@ -0,0 +1,39 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014 OpenMarket Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from ._base import Config
|
||||
|
||||
|
||||
class EmailConfig(Config):
|
||||
|
||||
def __init__(self, args):
|
||||
super(EmailConfig, self).__init__(args)
|
||||
self.email_from_address = args.email_from_address
|
||||
self.email_smtp_server = args.email_smtp_server
|
||||
|
||||
@classmethod
|
||||
def add_arguments(cls, parser):
|
||||
super(EmailConfig, cls).add_arguments(parser)
|
||||
email_group = parser.add_argument_group("email")
|
||||
email_group.add_argument(
|
||||
"--email-from-address",
|
||||
default="FROM@EXAMPLE.COM",
|
||||
help="The address to send emails from (e.g. for password resets)."
|
||||
)
|
||||
email_group.add_argument(
|
||||
"--email-smtp-server",
|
||||
default="",
|
||||
help="The SMTP server to send emails from (e.g. for password resets)."
|
||||
)
|
|
@ -20,11 +20,15 @@ from .database import DatabaseConfig
|
|||
from .ratelimiting import RatelimitConfig
|
||||
from .repository import ContentRepositoryConfig
|
||||
from .captcha import CaptchaConfig
|
||||
from .email import EmailConfig
|
||||
|
||||
|
||||
class HomeServerConfig(TlsConfig, ServerConfig, DatabaseConfig, LoggingConfig,
|
||||
RatelimitConfig, ContentRepositoryConfig, CaptchaConfig):
|
||||
RatelimitConfig, ContentRepositoryConfig, CaptchaConfig,
|
||||
EmailConfig):
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
HomeServerConfig.load_config("Generate config", sys.argv[1:], "HomeServer")
|
||||
|
|
|
@ -18,6 +18,8 @@ from twisted.internet import defer
|
|||
from ._base import BaseHandler
|
||||
from synapse.api.errors import LoginError, Codes
|
||||
from synapse.http.client import PlainHttpClient
|
||||
from synapse.util.emailutils import EmailException
|
||||
import synapse.util.emailutils as emailutils
|
||||
|
||||
import bcrypt
|
||||
import logging
|
||||
|
@ -71,6 +73,18 @@ class LoginHandler(BaseHandler):
|
|||
is_valid = yield self._check_valid_association(user_id, email)
|
||||
logger.info("reset_password user=%s email=%s valid=%s", user_id, email,
|
||||
is_valid)
|
||||
if is_valid:
|
||||
try:
|
||||
# send an email out
|
||||
emailutils.send_email(
|
||||
smtp_server=self.hs.config.email_smtp_server,
|
||||
from_addr=self.hs.config.email_from_address,
|
||||
to_addr=email,
|
||||
subject="Password Reset",
|
||||
body="TODO."
|
||||
)
|
||||
except EmailException as e:
|
||||
logger.exception(e)
|
||||
|
||||
@defer.inlineCallbacks
|
||||
def _check_valid_association(self, user_id, email):
|
||||
|
|
71
synapse/util/emailutils.py
Normal file
71
synapse/util/emailutils.py
Normal file
|
@ -0,0 +1,71 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014 OpenMarket Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
""" This module allows you to send out emails.
|
||||
"""
|
||||
import email.utils
|
||||
import smtplib
|
||||
import twisted.python.log
|
||||
from email.mime.text import MIMEText
|
||||
from email.mime.multipart import MIMEMultipart
|
||||
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EmailException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def send_email(smtp_server, from_addr, to_addr, subject, body):
|
||||
"""Sends an email.
|
||||
|
||||
Args:
|
||||
smtp_server(str): The SMTP server to use.
|
||||
from_addr(str): The address to send from.
|
||||
to_addr(str): The address to send to.
|
||||
subject(str): The subject of the email.
|
||||
body(str): The plain text body of the email.
|
||||
Raises:
|
||||
EmailException if there was a problem sending the mail.
|
||||
"""
|
||||
if not smtp_server or not from_addr or not to_addr:
|
||||
raise EmailException("Need SMTP server, from and to addresses. Check " +
|
||||
"the config to set these.")
|
||||
|
||||
msg = MIMEMultipart('alternative')
|
||||
msg['Subject'] = subject
|
||||
msg['From'] = from_addr
|
||||
msg['To'] = to_addr
|
||||
plain_part = MIMEText(body)
|
||||
msg.attach(plain_part)
|
||||
|
||||
raw_from = email.utils.parseaddr(from_addr)[1]
|
||||
raw_to = email.utils.parseaddr(to_addr)[1]
|
||||
if not raw_from or not raw_to:
|
||||
raise EmailException("Couldn't parse from/to address.")
|
||||
|
||||
logger.info("Sending email to %s on server %s with subject %s",
|
||||
to_addr, smtp_server, subject)
|
||||
|
||||
try:
|
||||
smtp = smtplib.SMTP(smtp_server)
|
||||
smtp.sendmail(raw_from, raw_to, msg.as_string())
|
||||
smtp.quit()
|
||||
except Exception as origException:
|
||||
twisted.python.log.err()
|
||||
ese = EmailException()
|
||||
ese.cause = origException
|
||||
raise ese
|
Loading…
Reference in a new issue