Can't seem to send email with jhipster application - spring

I'm trying to make a simple form that when submited sends and email to a fixed email.
I'm using spring and i've searched on how to configure the application.yml and i'm using the mailsend method that seems to have been generated with my jhipster application.
I've built my FE service to connect to the back end :
sendForm(): Observable<any>{
return this.http.post(SERVER_API_URL + 'api/sendForm', "");
}
i've built the onsubmit method to make the subscribe to the method above:
onSubmit() {
this.auth.sendForm().subscribe( data => {
console.log(data);
})
}
i've hard coded the mail resource just to mock an email to make sure its working:
#PostMapping("/sendForm")
public void sendForm() {
this.mailService.sendEmail("mymail#gmail.com","Header","texto",false,true);
}
the sendMail method that im sending the information for the mail submition is autogenerated and I believe it should be working
#Async
public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
isMultipart, isHtml, to, subject, content);
// Prepare message using a Spring helper
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, StandardCharsets.UTF_8.name());
message.setTo(to);
message.setFrom(jHipsterProperties.getMail().getFrom());
message.setSubject(subject);
message.setText(content, isHtml);
javaMailSender.send(mimeMessage);
log.debug("Sent email to User '{}'", to);
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.warn("Email could not be sent to user '{}'", to, e);
} else {
log.warn("Email could not be sent to user '{}': {}", to, e.getMessage());
}
}
}
and heres my application-dev.yml (i'm still on dev)
spring:
profiles:
active: dev
mail:
host: smtp.gmail.com
port: 587
username: gmailuserid#gmail.com #Replace this field with your Gmail username.
password: ************ #Replace this field with your Gmail password.
protocol: smtp
tls: true
properties.mail.smtp:
auth: true
starttls.enable: true
ssl.trust: smtp.gmail.com
the errors im getting goes as follows:
org.springframework.mail.MailSendException: Mail server connection failed; nested exception is com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localh
ost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect. Failed messages: com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeo
ut -1;
All I expect is a mail with the mock i've used and I cant seem to be able to put this working.
I hope i've not made the post to long and that everything is well explained.
Thank you in advance for anyone willing to help

Apparently somewhy the properties-prod.yml wasnt being loaded to the server. I had to create a config file with all the configurations for it to work

Related

Setting mail.smtp.connectiontimeout longens requests when working with office 365

We are sending mails in an email service with org.springframework.mail.javamail.JavaMailSender via an office 365 account and SMTP and set the following parameters in application.yml:
spring:
mail:
host: ${EMAIL_HOST:smtp.office365.com}
port: ${EMAIL_PORT:587}
username: ${EMAIL_USERNAME}
password: ${EMAIL_PASSWORD}
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
timeout: 5000
writetimeout: 5000
starttls:
enable: true
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory
The strange thing is: if we set the connectiontimeout to 5s, the service gets a response after 5s. If we set it to 20s, the o365 responds after 20s.
My expectation is that <connectiontimeout> is the maximum amount of time, that the sending may take and not the actual time.
Funny thing is that when setting another provider than office365, connectiontimeout works as expected.
Does anyone have this issue as well and maybe know how to solve that?
Our sender service:
#PostMapping
#ResponseStatus(HttpStatus.ACCEPTED)
public void sendMail(#RequestHeader(name = "X-API-KEY", required = true) String requestApiKey, #Valid #RequestBody EmailSendRequest email, HttpServletResponse response) {
if(!apiKey.equals(requestApiKey)){
LOGGER.error("Unauthorized api key" + requestApiKey);
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED);
}
try {
LOGGER.info("Received request to send mail Subject=[{}] To=[{}] From=[{}]", email.getSubject(), email.getTo(), email.getFrom());
MimeMessage message = mailSender.createMimeMessage();
message.setFrom(new InternetAddress(email.getFrom().getEmail()));
message.addRecipients(Message.RecipientType.TO, toAddressArray(email.getTo()));
message.addRecipients(Message.RecipientType.CC, toAddressArray(email.getCc()));
message.addRecipients(Message.RecipientType.BCC, toAddressArray(email.getBcc()));
message.setSubject(email.getSubject());
message.setSentDate(new Date());
Multipart multipart = new MimeMultipart();
MimeBodyPart messageText = new MimeBodyPart();
messageText.setContent(email.getContent().getValue(),
email.getContent().getType() == null ? DEFAULT_CONTENT_MIMETYPE : email.getContent().getType());
multipart.addBodyPart(messageText);
addAttachments(multipart, email.getAttachments());
message.setContent(multipart);
if(message.getRecipients(Message.RecipientType.TO) != null ||
message.getRecipients(Message.RecipientType.CC) != null ||
message.getRecipients(Message.RecipientType.BCC) != null)
{
mailSender.send(message);
}
else {
LOGGER.warn("Email not send! No recipients or all ignored.");
response.setHeader("X-Ignored","true");
}
LOGGER.info("Mail Subject=[{}] To=[{}}] From=[{}] successfully sent.",email.getSubject(),email.getTo(),email.getFrom());
} catch (MessagingException e) {
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]:", email.getSubject(), email.getTo(), email.getFrom(), e);
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (MailSendException mailSendException) {
Exception[] exceptions = mailSendException.getMessageExceptions();
for (Exception e : exceptions){
if (e instanceof SMTPSendFailedException && (((SMTPSendFailedException)e).getReturnCode() == 554)){
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]: This sender mail address is not allowed.", email.getSubject(), email.getTo(), email.getFrom());
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
}
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]:", email.getSubject(), email.getTo(), email.getFrom(), mailSendException);
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (MailAuthenticationException e) {
LOGGER.error("Error sending mail Subject=[{}] To=[{}] From=[{}]: Wrong SMTP login credentials provided. \nMSG:{}", email.getSubject(), email.getTo(), email.getFrom(),e.getMessage());
throw new ResponseStatusException(HttpStatus.NETWORK_AUTHENTICATION_REQUIRED);
}
}
It seems, that the SocketFactory was responsible for this behaviour. Removing the following lines from application.yml makes the application work as expected:
socketFactory:
port: 465
class: javax.net.ssl.SSLSocketFactory

How to send message to a specific subscription over spring websocket STOMP?

I am using STOMP over websockets with spring boot. Is there a possibility to send a message to a specific subscription? I subscribe to the STOMP endpoints using a STOMP header containing an id field according to the stomp documentation I want this id to be used to determine the clients who should receive a message, but spring seems not to use this id. I can not just use sendToUser because two clients can have the same user id e.g. if a user has two opened browser windows. Only one specific window should receive the message.
In the following example I have two connected clients which are using the same user, but different ids in the STOMP header.
Client1-ID: a32d66bf-03c7-47a4-aea0-e464c0727842
Client2-ID: b3673d33-1bf2-461e-8df3-35b7af07371b
In spring I have executed the following Kotlin code:
val subscriptions = userRegistry.findSubscriptions {
it.destination == "/user/topic/operations/$operationId/runs"
}
subscriptions.forEach{
println("subscription id: ${it.id}");
println("session id: ${it.session.id}");
println("user id ${it.session.user.name}");
}
The output:
subscription id: sub-7
session id: mcjpgn2i
user id 4a27ef88-25eb-4175-a872-f46e7b9d0564
subscription id: sub-7
session id: 0dxuvjgp
user id 4a27ef88-25eb-4175-a872-f46e7b9d0564
There is no sign of the id I have passed to the stomp header.
Is it possible to send a message to one specific subscription determined by the id I have passed with the header?
I got it working.
First of all, there was something wrong with my client setup. I have set the subscription id in the connection header like this:
this.stompClient.webSocketFactory = (): WebSocket => new SockJS("/ws");
this.stompClient.connectHeaders = { id: subscriptionId };
this.stompClient.activate();
But the subscription header has to be set in the subscription header:
this.stompClient.subscribe(this.commonEndpoint,
this.onMessageReceived.bind(this),
{ id: subScriptionId });
If I do this, spring is correctly using this id as the subscription id, instead of using some default like sub-7.
According to that thread I can send messages to specific sessions instead of user.
With the following code I can send a message to a specific subscription:
val subscriptions = userRegistry.findSubscriptions {
it.destination == "/user/topic/operations/$operationId/runs"
}
subscriptions.forEach {
if(it.id === mySubscriptionId){
val headerAccessor =
SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE)
headerAccessor.sessionId = it.session.id
headerAccessor.setLeaveMutable(true)
simpMessagingTemplate.convertAndSendToUser(it.session.id,
"/topic/operations/runs", messageResponseEntity,
headerAccessor.getMessageHeaders())
}
}
I'm able to send message to a specific subscription using SimpMessagingTemplate.
#Autowired
private final SimpMessagingTemplate messagingTemplate;
public void sendMessage(String simpUserId, String destination, String message) {
try {
messagingTemplate.convertAndSendToUser(simpUserId, destination, message);
} catch (Exception ex) {
LOG.error("Exception occurred while sending message [message={}]", ex.getMessage(), ex);
}
}
You may refer SimpMessagingTemplate.convertAndSendToUser

Unable to send SMTP mails using office365 settings

I am using SMTP mail for sending mail using Laravel. Everything working perfect other than office365 mail settings.
Settings I have used is as below:
SMTP HOST = smtp.office365.com
SMTP PORT = 587
SMTP ENCRYPTION = tls
SMTP USER = username(email)
SMTP PASS = password
Error i am getting is:
554 5.2.0
STOREDRV.Submission.Exception:SendAsDeniedException.MapiExceptionSendAsDenied;
Failed to process message due to a permanent exception with message
Cannot submit message
I have already searched google a lot for this error everybody says about clutter like this link
Solution to this error
But I personally don't find any clutter after followed all the steps mentioned.
I cannot log in this email as it's our client email id and I don't have permission to log in.
I also created one outlook email id and test this email setting.
It worked like charm.
I don't know what is wrong with Client email id.
Any suggestions would be great.
Outlook doesn't provide to send using different from address other than your username to log in.
You need both email address same.
You can add one or more sender in your admin panel after that you can send easily from different addresses.
This error means the user whose credentials you specified in the SMTP connection cannot submit messages on behalf of the user specified in the From and/or Sender MIME headers or the FROM SMTP command.
I face the similar issue and i resolved it right now,
you are most likely facing this issue because your "user" email in the auth option and the "from" email at the mail option are different
make the user and from email same and it will work for you
const transporter = nodemailer.createTransport({
service: 'outlook',
port: 587,
auth: {
user: 'abcde#outlook.com',
pass: '******'
},
tls: {
rejectUnauthorized: false
}
});
// setup email data with unicode symbols
let mailOptions = {
from: "abcde#outlook.com", // sender address
to: 'xyz#gmail.com', // list of receivers
subject: 'Node Contact Request', // Subject line
text: 'Hello world?', // plain text body
html: output // html body
};
// send mail with defined transport object
transporter.sendMail(mailOptions, (error, info) => {
console.log(info);
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
});
If your email is not verified you will likely to get more errors
After trying for 4 days, mails started to triggered with port:25, so instead of trying with 587 or 465. Try with other port numbers.
host: "smtp.office***.*",
port:25,
secureConnection: false,
requireTLS: true,
tls: {
ciphers: 'SSLv3'
},
auth: {
user: *,
pass: ***
}
I used Hotmail and had this problem but solved it by editing MAIL_FROM_ADDRESS to be the same as MAIL_USERNAME
Below is my env file set up.
MAIL_MAILER=smtp
MAIL_HOST=smtp-mail.outlook.com
MAIL_PORT=587
MAIL_USERNAME=myemail#hotmail.com (this must be the same as MAIL_FROM_ADDRESS!)
MAIL_PASSWORD=mypassword
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=myemail#hotmail.com (this must be the same as MAIL_USERNAME!)
Everything worked after doing the above.
What works for me is to set DEFAULT_FROM_EMAIL as the EMAIL_HOST_USER.
Working with Office 365 SMTP and Django 3.0.10.
you can also use this Mail-Driver:
https://github.com/motze92/office365-mail
Here you can specify any From-Email Address where your tenant has the permission for. Sent E-Mails will also go into the recipients sent items folder.
for this issue check the jenkins system admin email it is be same as smtp user email
In Spring boot Java you can fix this issue by following code.
application.properties file
spring.mail.properties.mail.smtp.connecttimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000
spring.mail.host=smtp.office365.com
spring.mail.password=password
spring.mail.port=587
spring.mail.username=abc#outlook.com
spring.mail.properties.mail.smtp.starttls.enable=true
security.require-ssl=true
spring.mail.properties.mail.smpt.auth=true
Java class which impliments the mail functionality
#Component
public class MailSenderClass {
#Value("${spring.mail.username}")
private String from;
#Autowired
private JavaMailSender javaMailSender;
public void sendMail(String to, String subject, String body) throws MessagingException {
MimeMessage message = javaMailSender.createMimeMessage();
MimeMessageHelper helper;
helper = new MimeMessageHelper(message, true);//true indicates multipart message
helper.setFrom(from) // <--- THIS IS IMPORTANT
helper.setSubject(subject);
helper.setTo(to);
helper.setText(body, true);//true indicates body is html
javaMailSender.send(message);
}
}
Note: you have to helper.setFrom(from) is important , your issue will be resolved by adding that piece of code.

SFTP error : com.jcraft.jsch.JSchException: invalid server's version string

I have the below code to SFTP to a location
public static void putFile(String username, String host, String password, String remotefile, String localfile){
JSch jsch = new JSch();
Session session = null;
try {
session = jsch.getSession(username, host, 22);
session.setConfig("StrictHostKeyChecking", "no");
session.setPassword(password);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelSftp sftpChannel = (ChannelSftp) channel;
sftpChannel.put(localfile, remotefile);
sftpChannel.exit();
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
}
}
I am able to SFTP the document from my local machine using the above code. However when I am trying from a different environment to SFTP to the same location I am getting the follow error.
com.jcraft.jsch.JSchException: invalid server's version string at
com.jcraft.jsch.Session.connect(Session.java:253)
Note : I am using jsch-0.1.31.jar file.
on printing out session.getClientVersion() I am getting "SSH-2.0-JSCH-0.1.31".
I tried to upgrade the jar file to jsch-0.1.51.jar then session.getClientVersion() = "SSH-1.5-JSCH-0.1.51" and I am getting the following error
com.jcraft.jsch.JSchException: Session.connect: java.net.SocketException: Connection reset at com.jcraft.jsch.Session.connect(Session.java:558)
Please can you help me on what parameters should I be looking into and what is causing it to run from my local machine and upload to the same SFTP location and not from other environment?
As noted by #Kenster, the exception is about server's version string, not client's. The "invalid server's version string" exception is thrown by following code in Session.connect:
if(i==buf.buffer.length ||
i<7 || // SSH-1.99 or SSH-2.0
(buf.buffer[4]=='1' && buf.buffer[6]!='9') // SSH-1.5
){
throw new JSchException("invalid server's version string");
}
First, I would try to connect with some client that logs the version string and see yourself. For example with WinSCP, search its log for a pattern like:
. 2014-09-03 17:01:20.596 Server version: SSH-2.0-OpenSSH_5.3
(I'm the author of WinSCP)
Though possibly it's not about version string at all. I would rather believe the error raised by the new version, the Connection reset. The old version may fail to detect that the connection was aborted prematurely and tries to validate some random or incomplete data.
The Connection reset may indicate wide variety of different errors
Server refusing a connection from the other location
Some firewall or proxy not allowing the connection to pass through

h2 mixed mode connection problem

I start h2 database in a servlet context listener:
public void contextInitialized(ServletContextEvent sce) {
org.h2.Driver.load();
String apprealPath = sce.getServletContext().getRealPath("\\");
String h2Url = "jdbc:h2:file:" + apprealPath + "DB\\cdb;AUTO_SERVER=true";
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
StatusPrinter.print(lc);
logger.debug("h2 url : " + h2Url);
try {
conn = DriverManager.getConnection(h2Url, "sa", "sa");
} catch (SQLException e) {
e.printStackTrace();
}
logger.debug("h2 database started in embedded mode");
sce.getServletContext().setAttribute("connection", conn);
}
then I try to use dbvisualizer to connect to h2 using following url :
jdbc:h2:tcp://localhost/~/cdb
but get these error messages:
An error occurred while establishing the connection:
Type: org.h2.jdbc.JdbcSQLException Error Code: 90067 SQL State: 90067
Message:
Connection is broken: "Connection refused: connect" [90067-148]
I tried to replace localhost with "172.17.33.181:58524" (I found it in cdb.lock.db)
reconnect with user "sa" password "sa" ,then server response changed to :
wrong username or password !
In the Automatic Mixed Mode, you don't need to (and you can't) use jdbc:h2:tcp://localhost. Just use the same URL everywhere, that means jdbc:h2:file:...DB\\cdb;AUTO_SERVER=true.
You can use the same database URL independent of whether the database is already open or not. Explicit client/server connections (using jdbc:h2:tcp:// or ssl://) are not supported.

Resources