aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/juick
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/juick')
-rw-r--r--src/main/java/com/juick/server/EmailManager.java84
-rw-r--r--src/main/java/com/juick/server/ServerManager.java14
-rw-r--r--src/main/java/com/juick/server/api/Service.java7
-rw-r--r--src/main/java/com/juick/server/api/Users.java12
-rw-r--r--src/main/java/com/juick/server/configuration/MailConfiguration.java32
-rw-r--r--src/main/java/com/juick/server/www/WebApp.java41
-rw-r--r--src/main/java/com/juick/service/component/AccountVerificationEvent.java44
-rw-r--r--src/main/java/com/juick/service/component/MailVerificationEvent.java44
8 files changed, 207 insertions, 71 deletions
diff --git a/src/main/java/com/juick/server/EmailManager.java b/src/main/java/com/juick/server/EmailManager.java
index d4e521e4..3939d706 100644
--- a/src/main/java/com/juick/server/EmailManager.java
+++ b/src/main/java/com/juick/server/EmailManager.java
@@ -17,20 +17,25 @@
package com.juick.server;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import com.juick.model.Message;
import com.juick.model.User;
import com.juick.server.api.SystemActivity;
+import com.juick.server.util.HttpBadRequestException;
+import com.juick.server.www.WebApp;
import com.juick.service.EmailService;
import com.juick.service.MessagesService;
import com.juick.service.UserService;
import com.juick.service.component.*;
import com.juick.util.MessageUtils;
import com.mitchellbosecke.pebble.PebbleEngine;
-import com.mitchellbosecke.pebble.template.PebbleTemplate;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.event.EventListener;
+import org.springframework.scheduling.annotation.Async;
import javax.annotation.Nonnull;
import javax.inject.Inject;
@@ -42,19 +47,11 @@ import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Properties;
+import java.util.*;
import static com.juick.formatters.PlainTextFormatter.formatPost;
import static com.juick.formatters.PlainTextFormatter.formatUrl;
-@Component
public class EmailManager implements NotificationListener {
public static final String MSGID_PATTERN = "\\.|@|<";
@@ -68,6 +65,12 @@ public class EmailManager implements NotificationListener {
private UserService userService;
@Inject
private PebbleEngine pebbleEngine;
+ @Inject
+ private ObjectMapper jsonMapper;
+ @Inject
+ private WebApp webApp;
+ @Value("${service_email:}")
+ private String serviceEmail;
@Override
public void processSystemEvent(@Nonnull SystemEvent systemEvent) {
@@ -77,6 +80,13 @@ public class EmailManager implements NotificationListener {
if (activity.getType().equals(SystemActivity.ActivityType.message)) {
processMessage(msg, subscribers);
}
+ try {
+ var eventHeader = Collections.singletonMap("X-Event-Version", "1.0");
+ sendEmail("noreply@juick.com", serviceEmail, "New system event",
+ jsonMapper.writeValueAsString(systemEvent.getActivity()), null, eventHeader);
+ } catch (JsonProcessingException e) {
+ logger.warn("JSON exception", e);
+ }
}
private void processMessage(Message msg, List<User> subscribedUsers) {
if (msg.isService()) {
@@ -104,6 +114,24 @@ public class EmailManager implements NotificationListener {
}
+ @Async
+ @EventListener
+ public void processMailVerificationEvent(MailVerificationEvent mailVerificationEvent) {
+ if (!sendEmail("noreply@juick.com", mailVerificationEvent.getEmail(), "Juick authorization link",
+ String.format("Follow link to attach this email to Juick account:\n" +
+ "http://juick.com/settings?page=auth-email&code=%s\n\n" +
+ "If you don't know, what this mean - just ignore this mail.\n", mailVerificationEvent.getCode()),
+ StringUtils.EMPTY, Collections.emptyMap())) {
+ throw new HttpBadRequestException();
+ }
+ }
+ @Async
+ @EventListener
+ public void processAccountVerificationEvent(AccountVerificationEvent accountVerificationEvent) {
+ String signupUrl = String.format("Follow this link to create Juick account: https://juick.com/signup?type=email&hash=%s", accountVerificationEvent.getCode());
+ sendEmail("noreply@juick.com", accountVerificationEvent.getEmail(), "Juick registration", signupUrl, StringUtils.EMPTY, Collections.emptyMap());
+ }
+
private void emailNotify(String email, String subject, Message msg) {
Map<String, String> headers = new HashMap<>();
if (!MessageUtils.isPM(msg)) {
@@ -118,9 +146,9 @@ public class EmailManager implements NotificationListener {
headers.put("In-Reply-To", String.format("<%d.%d@juick.com>", original.getMid(), original.getRid()));
}
}
- String plainText = renderPlaintext(formatPost(msg), formatUrl(msg)).orElseThrow(IllegalStateException::new);
+ String plainText = webApp.renderPlaintext(formatPost(msg), formatUrl(msg)).orElseThrow(IllegalStateException::new);
String hash = userService.getHashByUID(userService.getUserByEmail(email).getUid());
- String htmlText = renderHtml(MessageUtils.formatHtml(msg), formatUrl(msg), msg, hash).orElseThrow(IllegalStateException::new);
+ String htmlText = webApp.renderHtml(MessageUtils.formatHtml(msg), formatUrl(msg), msg, hash).orElseThrow(IllegalStateException::new);
sendEmail(StringUtils.EMPTY, email, subject, plainText, htmlText, headers);
}
public boolean sendEmail(String from, String to, String subject, String textPart, String htmlPart, Map<String, String> messageHeaders) {
@@ -170,34 +198,4 @@ public class EmailManager implements NotificationListener {
return false;
}
}
-
- public Optional<String> renderPlaintext(String body, String messageUrl) {
- PebbleTemplate noteTemplate = pebbleEngine.getTemplate("email/plaintext");
- Map<String, Object> context = new HashMap<>();
- context.put("messageBody", body);
- context.put("messageUrl", messageUrl);
- try {
- Writer writer = new StringWriter();
- noteTemplate.evaluate(writer, context);
- return Optional.of(writer.toString());
- } catch (IOException e) {
- return Optional.empty();
- }
- }
-
- public Optional<String> renderHtml(String body, String messageUrl, Message msg, String hash) {
- PebbleTemplate noteTemplate = pebbleEngine.getTemplate("email/html");
- Map<String, Object> context = new HashMap<>();
- context.put("messageBody", body);
- context.put("messageUrl", messageUrl);
- context.put("msg", msg);
- context.put("hash", hash);
- try {
- Writer writer = new StringWriter();
- noteTemplate.evaluate(writer, context);
- return Optional.of(writer.toString());
- } catch (IOException e) {
- return Optional.empty();
- }
- }
}
diff --git a/src/main/java/com/juick/server/ServerManager.java b/src/main/java/com/juick/server/ServerManager.java
index 8a70251f..d3742503 100644
--- a/src/main/java/com/juick/server/ServerManager.java
+++ b/src/main/java/com/juick/server/ServerManager.java
@@ -62,16 +62,9 @@ public class ServerManager implements NotificationListener {
@Value("${service_user:juick}")
private String serviceUsername;
- @Value("${service_email:root@localhost}")
- private String serviceEmail;
private User serviceUser;
- @Inject
- private EmailManager emailManager;
- @Inject
- private ObjectMapper jsonMapper;
-
@PostConstruct
public void init() {
serviceUser = userService.getUserByName(serviceUsername);
@@ -105,13 +98,6 @@ public class ServerManager implements NotificationListener {
processTop(message);
}
}
- try {
- var eventHeader = Collections.singletonMap("X-Event-Version", "1.0");
- emailManager.sendEmail("noreply@juick.com", serviceEmail, "New system event",
- jsonMapper.writeValueAsString(systemEvent.getActivity()), null, eventHeader);
- } catch (JsonProcessingException e) {
- logger.warn("JSON exception", e);
- }
}
private void processMessage(User from, Message jmsg, List<User> subscribers) {
List<User> subscribedUsers = ListUtils.union(subscribers, Collections.singletonList(jmsg.getUser()));
diff --git a/src/main/java/com/juick/server/api/Service.java b/src/main/java/com/juick/server/api/Service.java
index 2763eab1..4474e4f0 100644
--- a/src/main/java/com/juick/server/api/Service.java
+++ b/src/main/java/com/juick/server/api/Service.java
@@ -27,6 +27,7 @@ import com.juick.server.util.HttpForbiddenException;
import com.juick.service.EmailService;
import com.juick.service.MessagesService;
import com.juick.service.UserService;
+import com.juick.service.component.AccountVerificationEvent;
import com.juick.service.security.annotation.Visitor;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
@@ -36,6 +37,7 @@ import org.apache.commons.mail.util.MimeMessageParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -70,7 +72,7 @@ public class Service {
@Inject
private CommandsManager commandsManager;
@Inject
- private EmailManager emailManager;
+ private ApplicationEventPublisher applicationEventPublisher;
@Value("${api_user:juick}")
private String serviceUser;
@Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}")
@@ -168,8 +170,7 @@ public class Service {
if (!Arrays.asList(ignoredEmails).contains(from)) {
String verificationCode = RandomStringUtils.randomAlphanumeric(8).toUpperCase();
emailService.addVerificationCode(null, from, verificationCode);
- String signupUrl = String.format("Follow this link to create Juick account: https://juick.com/signup?type=email&hash=%s", verificationCode);
- emailManager.sendEmail("noreply@juick.com", from, "Juick registration", signupUrl, StringUtils.EMPTY, Collections.emptyMap());
+ applicationEventPublisher.publishEvent(new AccountVerificationEvent(this, from, verificationCode));
}
}
} else {
diff --git a/src/main/java/com/juick/server/api/Users.java b/src/main/java/com/juick/server/api/Users.java
index e53c5424..531883fc 100644
--- a/src/main/java/com/juick/server/api/Users.java
+++ b/src/main/java/com/juick/server/api/Users.java
@@ -27,11 +27,13 @@ import com.juick.server.util.HttpUtils;
import com.juick.server.util.WebUtils;
import com.juick.server.www.WebApp;
import com.juick.service.*;
+import com.juick.service.component.MailVerificationEvent;
import com.juick.service.security.annotation.Visitor;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@@ -68,7 +70,7 @@ public class Users {
@Value("${upload_tmp_dir:#{systemEnvironment['TEMP'] ?: '/tmp'}}")
private String tmpDir;
@Inject
- private EmailManager emailManager;
+ private ApplicationEventPublisher applicationEventPublisher;
@RequestMapping(value = "/api/auth", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public String getAuthToken(@Visitor User visitor) {
@@ -138,13 +140,7 @@ public class Users {
if (!emailService.verifyAddressByCode(visitor.getUid(), newEmail)) {
String authCode = RandomStringUtils.randomAlphanumeric(8).toUpperCase();
if (emailService.addVerificationCode(visitor.getUid(), newEmail, authCode)) {
- if (!emailManager.sendEmail("noreply@juick.com", newEmail, "Juick authorization link",
- String.format("Follow link to attach this email to Juick account:\n" +
- "http://juick.com/settings?page=auth-email&code=%s\n\n" +
- "If you don't know, what this mean - just ignore this mail.\n", authCode),
- StringUtils.EMPTY, Collections.emptyMap())) {
- throw new HttpBadRequestException();
- }
+ applicationEventPublisher.publishEvent(new MailVerificationEvent(this, newEmail , authCode));
}
}
}
diff --git a/src/main/java/com/juick/server/configuration/MailConfiguration.java b/src/main/java/com/juick/server/configuration/MailConfiguration.java
new file mode 100644
index 00000000..31034339
--- /dev/null
+++ b/src/main/java/com/juick/server/configuration/MailConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2008-2020, Juick
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.server.configuration;
+
+import com.juick.server.EmailManager;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConditionalOnProperty("service_email")
+public class MailConfiguration {
+ @Bean
+ public EmailManager emailManager() {
+ return new EmailManager();
+ }
+}
diff --git a/src/main/java/com/juick/server/www/WebApp.java b/src/main/java/com/juick/server/www/WebApp.java
index 8476224d..bf013c3b 100644
--- a/src/main/java/com/juick/server/www/WebApp.java
+++ b/src/main/java/com/juick/server/www/WebApp.java
@@ -16,9 +16,12 @@
*/
package com.juick.server.www;
+import com.juick.model.Message;
import com.juick.model.Tag;
import com.juick.model.User;
import com.juick.service.TagService;
+import com.mitchellbosecke.pebble.PebbleEngine;
+import com.mitchellbosecke.pebble.template.PebbleTemplate;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@@ -27,9 +30,10 @@ import org.springframework.web.util.UriComponentsBuilder;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.*;
import java.util.stream.Stream;
/**
@@ -42,6 +46,8 @@ public class WebApp {
private TagService tagService;
@Inject
private ResourceUrlProvider resourceUrlProvider;
+ @Inject
+ private PebbleEngine pebbleEngine;
@Value("${img_url:http://localhost:8080/i/}")
private String baseImagesUri;
UriComponentsBuilder avatarBuilder;
@@ -91,4 +97,33 @@ public class WebApp {
avatarBuilder.replacePath(getAvatarWebPath(user));
return avatarBuilder.build().toUriString();
}
+ public Optional<String> renderPlaintext(String body, String messageUrl) {
+ PebbleTemplate noteTemplate = pebbleEngine.getTemplate("email/plaintext");
+ Map<String, Object> context = new HashMap<>();
+ context.put("messageBody", body);
+ context.put("messageUrl", messageUrl);
+ try {
+ Writer writer = new StringWriter();
+ noteTemplate.evaluate(writer, context);
+ return Optional.of(writer.toString());
+ } catch (IOException e) {
+ return Optional.empty();
+ }
+ }
+
+ public Optional<String> renderHtml(String body, String messageUrl, Message msg, String hash) {
+ PebbleTemplate noteTemplate = pebbleEngine.getTemplate("email/html");
+ Map<String, Object> context = new HashMap<>();
+ context.put("messageBody", body);
+ context.put("messageUrl", messageUrl);
+ context.put("msg", msg);
+ context.put("hash", hash);
+ try {
+ Writer writer = new StringWriter();
+ noteTemplate.evaluate(writer, context);
+ return Optional.of(writer.toString());
+ } catch (IOException e) {
+ return Optional.empty();
+ }
+ }
}
diff --git a/src/main/java/com/juick/service/component/AccountVerificationEvent.java b/src/main/java/com/juick/service/component/AccountVerificationEvent.java
new file mode 100644
index 00000000..9ab48015
--- /dev/null
+++ b/src/main/java/com/juick/service/component/AccountVerificationEvent.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008-2020, Juick
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.service.component;
+
+import org.springframework.context.ApplicationEvent;
+
+public class AccountVerificationEvent extends ApplicationEvent {
+ private String email;
+ private String code;
+ /**
+ * Create a new {@code ApplicationEvent}.
+ *
+ * @param source the object on which the event initially occurred or with
+ * which the event is associated (never {@code null})
+ */
+ public AccountVerificationEvent(Object source, String email, String code) {
+ super(source);
+ this.email = email;
+ this.code = code;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getCode() {
+ return code;
+ }
+}
diff --git a/src/main/java/com/juick/service/component/MailVerificationEvent.java b/src/main/java/com/juick/service/component/MailVerificationEvent.java
new file mode 100644
index 00000000..5a6a95a7
--- /dev/null
+++ b/src/main/java/com/juick/service/component/MailVerificationEvent.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008-2020, Juick
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+package com.juick.service.component;
+
+import org.springframework.context.ApplicationEvent;
+
+public class MailVerificationEvent extends ApplicationEvent {
+ private String email;
+ private String code;
+ /**
+ * Create a new {@code ApplicationEvent}.
+ *
+ * @param source the object on which the event initially occurred or with
+ * which the event is associated (never {@code null})
+ */
+ public MailVerificationEvent(Object source, String email, String code) {
+ super(source);
+ this.email = email;
+ this.code = code;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getCode() {
+ return code;
+ }
+}