Skip to content

Commit ceabd3b

Browse files
committed
feature: Initial Implementation of Email Sending Feature with dummy Data.
1 parent a2bd841 commit ceabd3b

File tree

10 files changed

+98
-8
lines changed

10 files changed

+98
-8
lines changed

server/api-service/lowcoder-domain/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
<groupId>org.lowcoder</groupId>
5151
<artifactId>lowcoder-infra</artifactId>
5252
</dependency>
53+
<dependency>
54+
<groupId>org.springframework.boot</groupId>
55+
<artifactId>spring-boot-starter-mail</artifactId>
56+
</dependency>
5357

5458
<dependency>
5559
<groupId>com.github.cloudyrock.mongock</groupId>

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/user/model/User.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import static com.google.common.base.Suppliers.memoize;
44
import static org.lowcoder.infra.util.AssetUtils.toAssetPath;
55

6+
import java.time.Instant;
67
import java.util.*;
78
import java.util.function.Supplier;
89

@@ -52,6 +53,10 @@ public class User extends HasIdAndAuditing implements BeforeMongodbWrite, AfterM
5253
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
5354
private String password;
5455

56+
private String passwordResetToken;
57+
58+
private Instant passwordResetTokenExpiry;
59+
5560
@Transient
5661
Boolean isAnonymous = false;
5762

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package org.lowcoder.domain.user.service;
2+
3+
import jakarta.mail.internet.MimeMessage;
4+
import lombok.extern.slf4j.Slf4j;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.beans.factory.annotation.Value;
7+
import org.springframework.mail.javamail.JavaMailSender;
8+
import org.springframework.mail.javamail.MimeMessageHelper;
9+
import org.springframework.stereotype.Service;
10+
11+
@Service
12+
@Slf4j(topic = "EmailCommunicationService")
13+
public class EmailCommunicationService {
14+
15+
@Autowired
16+
private JavaMailSender javaMailSender;
17+
18+
@Value("${spring.mail.username}")
19+
private String fromEmail;
20+
21+
public boolean sendMail(String to, String token, String message) {
22+
try {
23+
String subject = "Lost Password Email";
24+
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
25+
26+
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
27+
28+
mimeMessageHelper.setFrom(fromEmail);
29+
mimeMessageHelper.setTo(to);
30+
mimeMessageHelper.setSubject(subject);
31+
32+
// Construct the message with the token link
33+
String resetLink = "http://localhost:8080/lost-password?token=" + token;
34+
String messageWithLink = message + "\n\nReset your password here: " + resetLink;
35+
mimeMessageHelper.setText(messageWithLink, true); // Set HTML to true to allow links
36+
37+
javaMailSender.send(mimeMessage);
38+
39+
return true;
40+
41+
} catch (Exception e) {
42+
log.error("Failed to send mail to: {}, Exception: {}", to, e);
43+
return false;
44+
}
45+
46+
47+
}
48+
49+
}

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/user/service/UserService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public interface UserService {
5050

5151
Mono<String> resetPassword(String userId);
5252

53-
Mono<String> lostPassword(String userEmail);
53+
Mono<Void> lostPassword(String userEmail);
5454

5555
Mono<Boolean> setPassword(String userId, String password);
5656

server/api-service/lowcoder-domain/src/main/java/org/lowcoder/domain/user/service/UserServiceImpl.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.lowcoder.sdk.constants.WorkspaceMode;
3030
import org.lowcoder.sdk.exception.BizError;
3131
import org.lowcoder.sdk.exception.BizException;
32+
import org.lowcoder.sdk.util.HashUtils;
3233
import org.lowcoder.sdk.util.LocaleUtils;
3334
import org.springframework.beans.factory.annotation.Autowired;
3435
import org.springframework.dao.DuplicateKeyException;
@@ -41,7 +42,9 @@
4142
import javax.annotation.Nonnull;
4243
import java.security.SecureRandom;
4344
import java.time.Duration;
45+
import java.time.Instant;
4446
import java.time.LocalDate;
47+
import java.time.temporal.ChronoUnit;
4548
import java.util.*;
4649
import java.util.function.Function;
4750
import java.util.stream.Collectors;
@@ -76,7 +79,8 @@ public class UserServiceImpl implements UserService {
7679
private CommonConfig commonConfig;
7780
@Autowired
7881
private AuthenticationService authenticationService;
79-
82+
@Autowired
83+
private EmailCommunicationService emailCommunicationService;
8084
private Conf<Integer> avatarMaxSizeInKb;
8185

8286
@PostConstruct
@@ -265,10 +269,18 @@ public Mono<String> resetPassword(String userId) {
265269
}
266270

267271
@Override
268-
public Mono<String> lostPassword(String userEmail) {
272+
public Mono<Void> lostPassword(String userEmail) {
269273
return findByName(userEmail)
270274
.flatMap(user -> {
271-
return Mono.justOrEmpty(user.getName());
275+
String token = generateNewRandomPwd();
276+
Instant tokenExpiry = Instant.now().plus(12, ChronoUnit.HOURS);
277+
// TODO - IRFAN this is just a dummy email.
278+
if (!emailCommunicationService.sendMail("notify@lowcoder.org", token, "Click Here")) {
279+
return ofError(BizError.USER_NOT_EXIST, "SENDING_EMAIL_FAILED");
280+
}
281+
user.setPasswordResetToken(HashUtils.hash(token.getBytes()));
282+
user.setPasswordResetTokenExpiry(tokenExpiry);
283+
return Mono.empty();
272284
});
273285
}
274286

server/api-service/lowcoder-sdk/src/main/java/org/lowcoder/sdk/config/CommonConfig.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ public class CommonConfig {
4444
private Cookie cookie = new Cookie();
4545
private JsExecutor jsExecutor = new JsExecutor();
4646
private Set<String> disallowedHosts = new HashSet<>();
47+
private SMTP smtp = new SMTP();
4748

4849
public boolean isSelfHost() {
4950
return !isCloud();
@@ -145,6 +146,13 @@ public static class JsExecutor {
145146
private String host;
146147
}
147148

149+
@Data
150+
public static class SMTP {
151+
private String email;
152+
private String host;
153+
private String port;
154+
}
155+
148156

149157
@Getter
150158
@Setter

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/UserApiService.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public Mono<String> resetPassword(String userId) {
6565
.then(userService.resetPassword(userId));
6666
}
6767

68-
public Mono<String> lostPassword(String userEmail) {
68+
public Mono<Void> lostPassword(String userEmail) {
6969
return userService.lostPassword(userEmail);
7070
}
7171

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/UserController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public Mono<ResponseView<String>> resetPassword(@RequestBody ResetPasswordReques
147147
}
148148

149149
@Override
150-
public Mono<ResponseView<String>> lostPassword(@RequestBody LostPasswordRequest request) {
150+
public Mono<ResponseView<Void>> lostPassword(@RequestBody LostPasswordRequest request) {
151151
if (StringUtils.isBlank(request.userEmail())) {
152152
return ofError(BizError.INVALID_PARAMETER, "INVALID_USER_EMAIL");
153153
}

server/api-service/lowcoder-server/src/main/java/org/lowcoder/api/usermanagement/UserEndpoints.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ public interface UserEndpoints
122122
public Mono<ResponseView<String>> resetPassword(@RequestBody ResetPasswordRequest request);
123123

124124
@PostMapping("/lost-password")
125-
public Mono<ResponseView<String>> lostPassword(@RequestBody LostPasswordRequest userEmail);
125+
public Mono<ResponseView<Void>> lostPassword(@RequestBody LostPasswordRequest userEmail);
126126

127127
@Operation(
128128
tags = TAG_USER_PASSWORD_MANAGEMENT,

server/api-service/lowcoder-server/src/main/resources/application-lowcoder.yml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ spring:
99
main:
1010
allow-bean-definition-overriding: true
1111
allow-circular-references: true
12+
mail:
13+
# TODO - IRFAN this is just a test email to check the email sending.
14+
username: "irfan.ayub@ikhwatech.com"
15+
password: "abcd"
16+
host: "smtp.freesmtpservers.com"
17+
port: 25
18+
# properties:
19+
# mail:
20+
# smtp:
21+
# starttls:
22+
# enable: true
23+
# auth: true
1224

1325
server:
1426
compression:
@@ -62,4 +74,4 @@ auth:
6274
email:
6375
enable: true
6476
enable-register: true
65-
workspace-creation: true
77+
workspace-creation: true

0 commit comments

Comments
 (0)