diff --git a/src/main/groovy/io/kamax/mxisd/config/invite/medium/EmailInviteConfig.java b/src/main/groovy/io/kamax/mxisd/config/invite/medium/EmailInviteConfig.java
new file mode 100644
index 0000000..76b79c2
--- /dev/null
+++ b/src/main/groovy/io/kamax/mxisd/config/invite/medium/EmailInviteConfig.java
@@ -0,0 +1,101 @@
+/*
+ * mxisd - Matrix Identity Server Daemon
+ * Copyright (C) 2017 Maxime Dor
+ *
+ * https://max.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.mxisd.config.invite.medium;
+
+import io.kamax.mxisd.config.MatrixConfig;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.WordUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import javax.annotation.PostConstruct;
+import java.io.File;
+
+@Configuration
+@ConfigurationProperties("invite.medium.email")
+public class EmailInviteConfig {
+
+ private Logger log = LoggerFactory.getLogger(EmailInviteConfig.class);
+
+ private MatrixConfig mxCfg;
+
+ private String from;
+ private String name;
+ private String template;
+
+ @Autowired
+ public EmailInviteConfig(MatrixConfig mxCfg) {
+ this.mxCfg = mxCfg;
+ }
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTemplate() {
+ return template;
+ }
+
+ public void setTemplate(String template) {
+ this.template = template;
+ }
+
+ @PostConstruct
+ public void build() {
+ log.info("--- E-mail invites config ---");
+ log.info("From: {}", getFrom());
+
+ if (StringUtils.isBlank(getName())) {
+ setName(WordUtils.capitalize(mxCfg.getDomain()) + " Identity Server");
+ }
+ log.info("Name: {}", getName());
+
+ if (!StringUtils.startsWith(getTemplate(), "classpath:")) {
+ if (StringUtils.isBlank(getTemplate())) {
+ log.warn("invite.medium.email is empty! Will not send invites");
+ } else {
+ File cp = new File(getTemplate()).getAbsoluteFile();
+ log.info("Template: {}", cp.getAbsolutePath());
+ if (!cp.exists() || !cp.isFile() || !cp.canRead()) {
+ log.warn(getTemplate() + " does not exist, is not a file or cannot be read");
+ }
+ }
+ } else {
+ log.info("Template: Built-in: {}", getTemplate());
+ }
+ }
+
+}
diff --git a/src/main/groovy/io/kamax/mxisd/config/invite/sender/EmailSenderConfig.java b/src/main/groovy/io/kamax/mxisd/config/threepid/connector/EmailSmtpConfig.java
similarity index 56%
rename from src/main/groovy/io/kamax/mxisd/config/invite/sender/EmailSenderConfig.java
rename to src/main/groovy/io/kamax/mxisd/config/threepid/connector/EmailSmtpConfig.java
index 8a0fa67..24a5e49 100644
--- a/src/main/groovy/io/kamax/mxisd/config/invite/sender/EmailSenderConfig.java
+++ b/src/main/groovy/io/kamax/mxisd/config/threepid/connector/EmailSmtpConfig.java
@@ -18,7 +18,7 @@
* along with this program. If not, see .
*/
-package io.kamax.mxisd.config.invite.sender;
+package io.kamax.mxisd.config.threepid.connector;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
@@ -27,22 +27,18 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
-import java.io.File;
@Configuration
-@ConfigurationProperties(prefix = "invite.sender.email")
-public class EmailSenderConfig {
+@ConfigurationProperties(prefix = "threepid.email.connector.provider.smtp")
+public class EmailSmtpConfig {
- private Logger log = LoggerFactory.getLogger(EmailSenderConfig.class);
+ private Logger log = LoggerFactory.getLogger(EmailSmtpConfig.class);
private String host;
private int port;
private int tls;
private String login;
private String password;
- private String email;
- private String name;
- private String template;
public String getHost() {
return host;
@@ -84,52 +80,14 @@ public class EmailSenderConfig {
this.password = password;
}
- public String getEmail() {
- return email;
- }
-
- public void setEmail(String email) {
- this.email = email;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getTemplate() {
- return template;
- }
-
- public void setTemplate(String template) {
- this.template = template;
- }
-
@PostConstruct
- private void postConstruct() {
- log.info("--- E-mail Invite Sender config ---");
+ public void build() {
+ log.info("--- E-mail SMTP Connector config ---");
log.info("Host: {}", getHost());
log.info("Port: {}", getPort());
log.info("TLS Mode: {}", getTls());
log.info("Login: {}", getLogin());
- log.info("Has password: {}", !StringUtils.isBlank(getPassword()));
- log.info("E-mail: {}", getEmail());
- if (!StringUtils.startsWith(getTemplate(), "classpath:")) {
- if (StringUtils.isBlank(getTemplate())) {
- log.warn("invite.sender.template is empty! Will not send invites");
- } else {
- File cp = new File(getTemplate()).getAbsoluteFile();
- log.info("Template: {}", cp.getAbsolutePath());
- if (!cp.exists() || !cp.isFile() || !cp.canRead()) {
- log.warn(getTemplate() + " does not exist, is not a file or cannot be read");
- }
- }
- } else {
- log.info("Template: Built-in");
- }
+ log.info("Has password: {}", StringUtils.isNotBlank(getPassword()));
}
}
diff --git a/src/main/groovy/io/kamax/mxisd/invitation/InvitationManager.java b/src/main/groovy/io/kamax/mxisd/invitation/InvitationManager.java
index f9bab89..d5502d3 100644
--- a/src/main/groovy/io/kamax/mxisd/invitation/InvitationManager.java
+++ b/src/main/groovy/io/kamax/mxisd/invitation/InvitationManager.java
@@ -26,13 +26,14 @@ import io.kamax.mxisd.config.DnsOverwrite;
import io.kamax.mxisd.config.DnsOverwriteEntry;
import io.kamax.mxisd.exception.BadRequestException;
import io.kamax.mxisd.exception.MappingAlreadyExistsException;
-import io.kamax.mxisd.invitation.sender.IInviteSender;
+import io.kamax.mxisd.invitation.generator.IInviteContentGenerator;
import io.kamax.mxisd.lookup.SingleLookupReply;
import io.kamax.mxisd.lookup.ThreePidMapping;
import io.kamax.mxisd.lookup.strategy.LookupStrategy;
import io.kamax.mxisd.signature.SignatureManager;
import io.kamax.mxisd.storage.IStorage;
import io.kamax.mxisd.storage.ormlite.ThreePidInviteIO;
+import io.kamax.mxisd.threepid.connector.IThreePidConnector;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
@@ -83,14 +84,35 @@ public class InvitationManager {
@Autowired
private DnsOverwrite dns;
- private Map senders;
+ private Map generators;
+ private Map connectors;
private CloseableHttpClient client;
private Gson gson;
private Timer refreshTimer;
- private String getId(IThreePidInvite invite) {
- return invite.getSender().getDomain().toLowerCase() + invite.getMedium().toLowerCase() + invite.getAddress().toLowerCase();
+ @Autowired
+ public InvitationManager(
+ List generatorList,
+ List connectorList
+ ) {
+ generators = new HashMap<>();
+ generatorList.forEach(sender -> { // FIXME to support several possible implementations
+ if (generators.containsKey(sender.getMedium())) {
+ throw new RuntimeException("More than one " + sender.getMedium() + " content generator");
+ }
+
+ generators.put(sender.getMedium(), sender);
+ });
+
+ connectors = new HashMap<>();
+ connectorList.forEach(connector -> { // FIXME to support several possible implementations
+ if (connectors.containsKey(connector.getMedium())) {
+ throw new RuntimeException("More than one " + connector.getMedium() + " connector");
+ }
+
+ connectors.put(connector.getMedium(), connector);
+ });
}
@PostConstruct
@@ -140,9 +162,14 @@ public class InvitationManager {
@PreDestroy
private void preDestroy() {
+ refreshTimer.cancel();
ForkJoinPool.commonPool().awaitQuiescence(1, TimeUnit.MINUTES);
}
+ private String getId(IThreePidInvite invite) {
+ return invite.getSender().getDomain().toLowerCase() + invite.getMedium().toLowerCase() + invite.getAddress().toLowerCase();
+ }
+
private String getIdForLog(IThreePidInviteReply reply) {
return reply.getInvite().getSender().getId() + ":" + reply.getInvite().getRoomId() + ":" + reply.getInvite().getMedium() + ":" + reply.getInvite().getAddress();
}
@@ -193,21 +220,16 @@ public class InvitationManager {
return "https://" + domain + ":8448";
}
- @Autowired
- public InvitationManager(List senderList) {
- senders = new HashMap<>();
- senderList.forEach(sender -> senders.put(sender.getMedium(), sender));
- }
-
public synchronized IThreePidInviteReply storeInvite(IThreePidInvite invitation) { // TODO better sync
- IInviteSender sender = senders.get(invitation.getMedium());
- if (sender == null) {
+ IInviteContentGenerator generator = generators.get(invitation.getMedium());
+ IThreePidConnector connector = connectors.get(invitation.getMedium());
+ if (generator == null || connector == null) {
throw new BadRequestException("Medium type " + invitation.getMedium() + " is not supported");
}
String invId = getId(invitation);
log.info("Handling invite for {}:{} from {} in room {}", invitation.getMedium(), invitation.getAddress(), invitation.getSender(), invitation.getRoomId());
- if (invitations.containsKey(invId)) { // FIXME we need to lookup using the HS domain too!!
+ if (invitations.containsKey(invId)) {
log.info("Invite is already pending for {}:{}, returning data", invitation.getMedium(), invitation.getAddress());
return invitations.get(invId);
}
@@ -224,7 +246,7 @@ public class InvitationManager {
IThreePidInviteReply reply = new ThreePidInviteReply(invId, invitation, token, displayName);
log.info("Performing invite to {}:{}", invitation.getMedium(), invitation.getAddress());
- sender.send(reply);
+ connector.send(reply, generator.generate(reply));
log.info("Storing invite under ID {}", invId);
storage.insertInvite(reply);
diff --git a/src/main/groovy/io/kamax/mxisd/invitation/sender/EmailInviteSender.java b/src/main/groovy/io/kamax/mxisd/invitation/generator/EmailInviteContentGenerator.java
similarity index 58%
rename from src/main/groovy/io/kamax/mxisd/invitation/sender/EmailInviteSender.java
rename to src/main/groovy/io/kamax/mxisd/invitation/generator/EmailInviteContentGenerator.java
index 8a67ac2..bcd1e44 100644
--- a/src/main/groovy/io/kamax/mxisd/invitation/sender/EmailInviteSender.java
+++ b/src/main/groovy/io/kamax/mxisd/invitation/generator/EmailInviteContentGenerator.java
@@ -18,61 +18,35 @@
* along with this program. If not, see .
*/
-package io.kamax.mxisd.invitation.sender;
+package io.kamax.mxisd.invitation.generator;
-import com.sun.mail.smtp.SMTPTransport;
import io.kamax.matrix.ThreePidMedium;
import io.kamax.mxisd.config.MatrixConfig;
-import io.kamax.mxisd.config.invite.sender.EmailSenderConfig;
-import io.kamax.mxisd.exception.ConfigurationException;
+import io.kamax.mxisd.config.invite.medium.EmailInviteConfig;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
-import javax.annotation.PostConstruct;
-import javax.mail.Message;
-import javax.mail.MessagingException;
-import javax.mail.Session;
-import javax.mail.internet.InternetAddress;
-import javax.mail.internet.MimeMessage;
import java.io.FileInputStream;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
-import java.util.Date;
@Component
-public class EmailInviteSender implements IInviteSender {
+public class EmailInviteContentGenerator implements IInviteContentGenerator {
- private Logger log = LoggerFactory.getLogger(EmailInviteSender.class);
-
- @Autowired
- private EmailSenderConfig cfg;
-
- @Autowired
+ private EmailInviteConfig cfg;
private MatrixConfig mxCfg;
-
- @Autowired
private ApplicationContext app;
- private Session session;
- private InternetAddress sender;
-
- @PostConstruct
- private void postConstruct() {
- try {
- session = Session.getInstance(System.getProperties());
- sender = new InternetAddress(cfg.getEmail(), cfg.getName());
- } catch (UnsupportedEncodingException e) {
- // What are we supposed to do with this?!
- throw new ConfigurationException(e);
- }
+ @Autowired
+ public EmailInviteContentGenerator(EmailInviteConfig cfg, MatrixConfig mxCfg, ApplicationContext app) {
+ this.cfg = cfg;
+ this.mxCfg = mxCfg;
+ this.app = app;
}
@Override
@@ -81,7 +55,7 @@ public class EmailInviteSender implements IInviteSender {
}
@Override
- public void send(IThreePidInviteReply invite) {
+ public String generate(IThreePidInviteReply invite) {
if (!ThreePidMedium.Email.is(invite.getInvite().getMedium())) {
throw new IllegalArgumentException(invite.getInvite().getMedium() + " is not a supported 3PID type");
}
@@ -99,7 +73,7 @@ public class EmailInviteSender implements IInviteSender {
StandardCharsets.UTF_8);
templateBody = templateBody.replace("%DOMAIN%", mxCfg.getDomain());
templateBody = templateBody.replace("%DOMAIN_PRETTY%", domainPretty);
- templateBody = templateBody.replace("%FROM_EMAIL%", cfg.getEmail());
+ templateBody = templateBody.replace("%FROM_EMAIL%", cfg.getFrom());
templateBody = templateBody.replace("%FROM_NAME%", cfg.getName());
templateBody = templateBody.replace("%SENDER_ID%", invite.getInvite().getSender().getId());
templateBody = templateBody.replace("%SENDER_NAME%", senderName);
@@ -110,28 +84,9 @@ public class EmailInviteSender implements IInviteSender {
templateBody = templateBody.replace("%ROOM_NAME%", roomName);
templateBody = templateBody.replace("%ROOM_NAME_OR_ID%", roomNameOrId);
- MimeMessage msg = new MimeMessage(session, IOUtils.toInputStream(templateBody, StandardCharsets.UTF_8));
- msg.setHeader("X-Mailer", "mxisd"); // TODO set version
- msg.setSentDate(new Date());
- msg.setFrom(sender);
- msg.setRecipients(Message.RecipientType.TO, invite.getInvite().getAddress());
- msg.saveChanges();
-
- log.info("Sending invite to {} via SMTP using {}:{}", invite.getInvite().getAddress(), cfg.getHost(), cfg.getPort());
- SMTPTransport transport = (SMTPTransport) session.getTransport("smtp");
- transport.setStartTLS(cfg.getTls() > 0);
- transport.setRequireStartTLS(cfg.getTls() > 1);
-
- log.info("Connecting to {}:{}", cfg.getHost(), cfg.getPort());
- transport.connect(cfg.getHost(), cfg.getPort(), cfg.getLogin(), cfg.getPassword());
- try {
- transport.sendMessage(msg, InternetAddress.parse(invite.getInvite().getAddress()));
- log.info("Invite to {} was sent", invite.getInvite().getAddress());
- } finally {
- transport.close();
- }
- } catch (IOException | MessagingException e) {
- throw new RuntimeException("Unable to send e-mail invite to " + invite.getInvite().getAddress(), e);
+ return templateBody;
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to read template file", e);
}
}
diff --git a/src/main/groovy/io/kamax/mxisd/invitation/sender/IInviteSender.java b/src/main/groovy/io/kamax/mxisd/invitation/generator/IInviteContentGenerator.java
similarity index 86%
rename from src/main/groovy/io/kamax/mxisd/invitation/sender/IInviteSender.java
rename to src/main/groovy/io/kamax/mxisd/invitation/generator/IInviteContentGenerator.java
index 14af7fd..a05b381 100644
--- a/src/main/groovy/io/kamax/mxisd/invitation/sender/IInviteSender.java
+++ b/src/main/groovy/io/kamax/mxisd/invitation/generator/IInviteContentGenerator.java
@@ -18,14 +18,14 @@
* along with this program. If not, see .
*/
-package io.kamax.mxisd.invitation.sender;
+package io.kamax.mxisd.invitation.generator;
import io.kamax.mxisd.invitation.IThreePidInviteReply;
-public interface IInviteSender {
+public interface IInviteContentGenerator {
String getMedium();
- void send(IThreePidInviteReply invite);
+ String generate(IThreePidInviteReply invite);
}
diff --git a/src/main/groovy/io/kamax/mxisd/threepid/connector/EmailSmtpConnector.java b/src/main/groovy/io/kamax/mxisd/threepid/connector/EmailSmtpConnector.java
new file mode 100644
index 0000000..b9d68e0
--- /dev/null
+++ b/src/main/groovy/io/kamax/mxisd/threepid/connector/EmailSmtpConnector.java
@@ -0,0 +1,106 @@
+/*
+ * mxisd - Matrix Identity Server Daemon
+ * Copyright (C) 2017 Maxime Dor
+ *
+ * https://max.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.mxisd.threepid.connector;
+
+import com.sun.mail.smtp.SMTPTransport;
+import io.kamax.matrix.ThreePidMedium;
+import io.kamax.mxisd.config.invite.medium.EmailInviteConfig;
+import io.kamax.mxisd.config.threepid.connector.EmailSmtpConfig;
+import io.kamax.mxisd.exception.ConfigurationException;
+import io.kamax.mxisd.invitation.IThreePidInviteReply;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+@Component
+public class EmailSmtpConnector implements IThreePidConnector {
+
+ private Logger log = LoggerFactory.getLogger(EmailSmtpConnector.class);
+
+ private EmailSmtpConfig cfg;
+ private EmailInviteConfig invCfg;
+
+ private Session session;
+ private InternetAddress sender;
+
+ @Autowired
+ public EmailSmtpConnector(EmailSmtpConfig cfg, EmailInviteConfig invCfg) {
+ try {
+ session = Session.getInstance(System.getProperties());
+ sender = new InternetAddress(invCfg.getFrom(), invCfg.getName());
+ } catch (UnsupportedEncodingException e) {
+ // What are we supposed to do with this?!
+ throw new ConfigurationException(e);
+ }
+
+ this.cfg = cfg;
+ this.invCfg = invCfg;
+ }
+
+ @Override
+ public String getMedium() {
+ return ThreePidMedium.Email.getId();
+ }
+
+ @Override
+ public void send(IThreePidInviteReply invite, String content) {
+ if (!ThreePidMedium.Email.is(invite.getInvite().getMedium())) {
+ throw new IllegalArgumentException(invite.getInvite().getMedium() + " is not a supported 3PID type");
+ }
+
+ try {
+ MimeMessage msg = new MimeMessage(session, IOUtils.toInputStream(content, StandardCharsets.UTF_8));
+ msg.setHeader("X-Mailer", "mxisd"); // TODO set version
+ msg.setSentDate(new Date());
+ msg.setFrom(sender);
+ msg.setRecipients(Message.RecipientType.TO, invite.getInvite().getAddress());
+ msg.saveChanges();
+
+ log.info("Sending invite to {} via SMTP using {}:{}", invite.getInvite().getAddress(), cfg.getHost(), cfg.getPort());
+ SMTPTransport transport = (SMTPTransport) session.getTransport("smtp");
+ transport.setStartTLS(cfg.getTls() > 0);
+ transport.setRequireStartTLS(cfg.getTls() > 1);
+
+ log.info("Connecting to {}:{}", cfg.getHost(), cfg.getPort());
+ transport.connect(cfg.getHost(), cfg.getPort(), cfg.getLogin(), cfg.getPassword());
+ try {
+ transport.sendMessage(msg, InternetAddress.parse(invite.getInvite().getAddress()));
+ log.info("Invite to {} was sent", invite.getInvite().getAddress());
+ } finally {
+ transport.close();
+ }
+ } catch (MessagingException e) {
+ throw new RuntimeException("Unable to send e-mail invite to " + invite.getInvite().getAddress(), e);
+ }
+ }
+
+}
diff --git a/src/main/groovy/io/kamax/mxisd/threepid/connector/IThreePidConnector.java b/src/main/groovy/io/kamax/mxisd/threepid/connector/IThreePidConnector.java
new file mode 100644
index 0000000..07bdc1a
--- /dev/null
+++ b/src/main/groovy/io/kamax/mxisd/threepid/connector/IThreePidConnector.java
@@ -0,0 +1,31 @@
+/*
+ * mxisd - Matrix Identity Server Daemon
+ * Copyright (C) 2017 Maxime Dor
+ *
+ * https://max.kamax.io/
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package io.kamax.mxisd.threepid.connector;
+
+import io.kamax.mxisd.invitation.IThreePidInviteReply;
+
+public interface IThreePidConnector {
+
+ String getMedium();
+
+ void send(IThreePidInviteReply invite, String content);
+
+}
diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml
index 87d88f1..8dc80b6 100644
--- a/src/main/resources/application.yaml
+++ b/src/main/resources/application.yaml
@@ -62,12 +62,19 @@ forward:
- "https://matrix.org"
- "https://vector.im"
+threepid:
+ email:
+ connector:
+ active: 'smtp'
+ provider:
+ smtp:
+ port: 587
+ tls: 1
+
invite:
- sender:
+ medium:
email:
- tls: 1
- name: "mxisd Identity Server"
- template: "classpath:email/invite-template.eml"
+ template: 'classpath:email/invite-template.eml'
storage:
backend: 'sqlite'