mirror of
https://mau.dev/maunium/synapse.git
synced 2024-12-14 21:53:50 +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 .ratelimiting import RatelimitConfig
|
||||||
from .repository import ContentRepositoryConfig
|
from .repository import ContentRepositoryConfig
|
||||||
from .captcha import CaptchaConfig
|
from .captcha import CaptchaConfig
|
||||||
|
from .email import EmailConfig
|
||||||
|
|
||||||
|
|
||||||
class HomeServerConfig(TlsConfig, ServerConfig, DatabaseConfig, LoggingConfig,
|
class HomeServerConfig(TlsConfig, ServerConfig, DatabaseConfig, LoggingConfig,
|
||||||
RatelimitConfig, ContentRepositoryConfig, CaptchaConfig):
|
RatelimitConfig, ContentRepositoryConfig, CaptchaConfig,
|
||||||
|
EmailConfig):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
import sys
|
import sys
|
||||||
HomeServerConfig.load_config("Generate config", sys.argv[1:], "HomeServer")
|
HomeServerConfig.load_config("Generate config", sys.argv[1:], "HomeServer")
|
||||||
|
|
|
@ -18,6 +18,8 @@ from twisted.internet import defer
|
||||||
from ._base import BaseHandler
|
from ._base import BaseHandler
|
||||||
from synapse.api.errors import LoginError, Codes
|
from synapse.api.errors import LoginError, Codes
|
||||||
from synapse.http.client import PlainHttpClient
|
from synapse.http.client import PlainHttpClient
|
||||||
|
from synapse.util.emailutils import EmailException
|
||||||
|
import synapse.util.emailutils as emailutils
|
||||||
|
|
||||||
import bcrypt
|
import bcrypt
|
||||||
import logging
|
import logging
|
||||||
|
@ -71,6 +73,18 @@ class LoginHandler(BaseHandler):
|
||||||
is_valid = yield self._check_valid_association(user_id, email)
|
is_valid = yield self._check_valid_association(user_id, email)
|
||||||
logger.info("reset_password user=%s email=%s valid=%s", user_id, email,
|
logger.info("reset_password user=%s email=%s valid=%s", user_id, email,
|
||||||
is_valid)
|
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
|
@defer.inlineCallbacks
|
||||||
def _check_valid_association(self, user_id, email):
|
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