Email sent but get timeout - spring

I use spring boot 2. I try to send mail. Server is outlook In my build.gradle
compile('org.springframework.boot:spring-boot-starter-mail')
In my facade class
for (FactoryEmailNC factoryEmail : factoryEmails) {
String message = mailContentBuilder.build(factoryEmail);
if (factoryEmail.getEmails() != null && !factoryEmail.getEmails().isEmpty()) {
mailService.sendHtmlMail(factoryEmail.getEmails(), "Not compliant", message);
//query to specify email has been sent.
setSampleEmailSent(factoryEmail);
}
}
private void setSampleEmailSent(FactoryEmailNC factoryEmail) {
....
samplesServices.setEmailsSent(testSampleIdEmailSent);
}
In my SamplesServices class
#Transactional
public void setEmailsSent(Map<String, List<SampleId>> testSampleIdEmailSent){
//call to repository, set flag email sent to true
...
}
public class MailServiceImpl(){
#Autowired
private JavaMailSender javaMailSender;
#Async
public void sendHtmlMail(List<String> to, String subject, String body) throws MessagingException {
MimeMessage mail = javaMailSender.createMimeMessage();
MimeMessageHelper helper = new MimeMessageHelper(mail, true);
...
helper.setTo(to.stream().toArray(String[]::new)); //line 64
javaMailSender.send(mail);
}
}
Actually email is sent, but setSampleEmailSent don't seem to be called because email flag still to false
org.springframework.mail.MailSendException: Failed messages:
javax.mail.MessagingException: Exception reading response; nested
exception is: java.net.SocketTimeoutException: Read timed out at
org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:490)
~[spring-context-support-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] at
org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:360)
~[spring-context-support-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] at
org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:355)
~[spring-context-support-5.1.5.RELEASE.jar!/:5.1.5.RELEASE] at
com.mermacon.service.MailServiceImpl.sendHtmlMail(MailServiceImpl.java:64)
~[classes!/:na]
In my application properties
spring.mail.properties.mail.smtp.connectiontimeout=5000
spring.mail.properties.mail.smtp.timeout=3000
spring.mail.properties.mail.smtp.writetimeout=5000
spring.mail.properties.from=info#meracon.com
spring.mail.host=mail.oldubi.com
spring.mail.port=25
Any idea why email is sent but still get timeout?
Edit 1
I get timeout only if i send more then one email
Log file of sending 1 email
https://pastebin.com/6y6n8MV5
Log file after sending 1 email
https://pastebin.com/j2sT7qHu
Edit 2
I put a thread sleep between every email sent, timeout disapear

Related

Working fine with Spring JMS and getting problem with Apache camel route , IBM MQ Route

I'm Sending request to the Third party IBM MQ with space pattern, like below text (COBOL input file), but i'm getting reponse as a error in Reply queue like below but same input working fine spring jms, i'm facing this problem with apache camel
Sample Input:
GetProducerWithCommissionddRates
C26115
77104 99998
2010-01-01 011
Response:
printing data in controller:: EPPRD02007EAn invalid COBOL Date Format
was provided as input to the Producer Retrieval Service, Get Producer
With Commission Rates Operation: AsOfDate. Source:
(ProducerMediationModule)
ProducerMediationModule
Controller with camel:
#PostMapping("/request-reply")
public String requestReplyMapping(#RequestBody String inputReq) {
Exchange exchangeRequest = ExchangeBuilder.anExchange(camelContext).withBody(inputReq).build();
Exchange exchangeResponse = producer.send("direct:request-reply", exchangeRequest);
return exchangeResponse.getIn().getBody(String.class);
}
Camel Route:
#Component
public class RequestReplyRouter extends RouteBuilder {
#Override
public void configure() throws Exception {
from("direct:request-reply").
to("jms:REQUEST.Q1?ReplyTo=REPLY.Q1&exchangePattern=InOut")
.log("Request-reply Body is ${body} and header info is ${headers} ");
from("jms:REPLY.Q1")
.log("Received Body is ${body} and header info is ${headers} ");
}
}
JMS Controller Code(working) :
#PostMapping(value="request-reply")
public ResponseEntity<String> sendRequestAndReceiveReply (#RequestBody String prd2x4Request) { System.out.println("received prd2x4 request: "+prd2x4Request);
String reply = prd2x4Wrapper.sendReqAndGetMessageId(prd2x4Request);
return new ResponseEntity<String>(reply, HttpStatus.OK);
}
JMS MQ Calling (working) :
private String sendReqAndGetMessage(String prd2x4Request) {
String messageId = "";
MQQueue requestQueue = new MQQueue(RequestQueue);
Session session = jmsTemplate.getConnectionFactory().createConnection().createSession(); MessageProducer mp = session.createProducer(requestQueue);
TextMessage message = session.createTextMessage(prd2x4Request);
message.setStringProperty("JMS_IBM_Character_Set", "IBM037");
mp.send(message);
messageId = message.getJMSMessageID();
mp.close();
session.close();
return messageId;
}

Limit a #SendToUser broadcast on a specific browser tab

I am using STOMP websocket on Springboot and want to limit a broadcast to a particular page. Here is my process:
User fills up a message to a HTML input.
Browser will send the message through STOMP client.
The server receives the message and validates it. If the message is valid, it will broadcast to all tabs handled by user that User has made a message. If it is invalid, it will send back the error message only to that particular browser tab that sent the message and not with other tabs even if those tabs have the same User logged in.
I already made some parts of it work although I couldn't limit sending the error message to a particular tab, it always broadcast the the error message to all tab sharing the same User. Here is my initial code:
#MessageMapping("/api/secure/message")
#SendToUser("/api/secure/broadcast")
public HttpEntity createMessage(Message message, Authentication authentication) throws Exception {
Set<String> errors = TreeSet<String>();
// Process Message message and add every exceptions encountered to Set errors.
boolean valid = (errors.size() > 0);
if(valid) {
// Broadcast to all.
return new ResponseEntity(message, HttpStatus.OK);
}
else {
// Send the message to that particular tab only.
return new ResponseEntity(errors, HttpStatus.UNPROCESSABLE_ENTITY);
}
}
Is this achievable through websocket? Or should I return back to XHR?
With every tab you would be creating a new websocket session, hence your stomp session-id would be different as well. So we can decide on whether to send to a particular session or all sessions for a particular user.
#Autowired
private SimpMessagingTemplate template;
....
#MessageMapping(...)
public void sendMessage(Message<?> message...) {
.....
StompHeaderAccessor headerAccessor =
StompHeaderAccessor.wrap(message);
String sessionId = headerAccessor.getSessionId();
....
if(valid) {
//Not specifying session Id so sends all users of
<user_name>
template.cnvertAndSendToUser(<user_name>,
<destination>, <payload>)
}
else {
SimpMessageHeaderAccessor headerAccessor =
SimpMessagingHeaderAccessor.create(SimpMessageType.MESSAGE);
headerAccessor.setSessionId(sessionId);
//This will send it to particular session.
template.convertAndSendToUser(<user_name>,
<destination>, <payload>,
headerAccessor.getMessageHeaders());
}
}
Useful References:
Medium post on sending to particular session.
convertAndSendToUser Documentation
User #Srinivas made a good starting reference point. I have modified the code block in my question with my working code:
// inject the [messagingTemplate] bean.
// class org.springframework.messaging.simp.SimpMessagingTemplate
#Autowired
private SimpMessagingTemplate messagingTemplate;
#MessageMapping("/api/secure/message")
// Remove the #SendToUser annotation and change return type to void.
// #SendToUser("/api/secure/broadcast")
// public HttpEntity createMessage(Message messageā€¦
public void createMessage(Message message, Authentication authentication) throws Exception {
Set<String> errors = TreeSet<String>();
// Process Message message and add every exceptions encountered to Set errors.
boolean valid = (errors.size() > 0);
if(valid) {
// Broadcast to all.
// Instead of returning to send the message, use the [messagingTemplate] instead.
// return new ResponseEntity(message, HttpStatus.OK);
messagingTemplate.convertAndSendToUser("/api/secure/broadcast", errors);
}
else {
// Send the message to that particular tab only.
// Each STOMP WebSocket connection has a unique ID that effectively differentiate
// it to the other browser tabs. Retrieve that ID so we can target that specific
// tab to send our error message with.
// class org.springframework.messaging.simp.stomp.StompHeaderAccessor
StompHeaderAccessor stompHeaderAccessor = StompHeaderAccessor.wrap(message);
String sessionId = stompHeaderAccessor.getSessionId();
// class org.springframework.messaging.simp.SimpMessageHeaderAccessor
// class org.springframework.messaging.simp.SimpMessageType
// class org.springframework.util.MimeType
// class java.nio.charset.StandardCharsets
SimpMessageHeaderAccessor simpHeaderAccessor =
SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
simpHeaderAccessor.setSessionId(sessionId);
simpHeaderAccessor.setContentType(new MimeType("application", "json",
StandardCharsets.UTF_8));
simpHeaderAccessor.setLeaveMutable(true);
// Instead of returning to send the message, use the [messagingTemplate] instead.
// It will ensure that it will only broadcast the message to the specific
// STOMP WebSocket sessionId.
// return new ResponseEntity(errors, HttpStatus.UNPROCESSABLE_ENTITY);
messagingTemplate.convertAndSendToUser(sessionId, "/api/secure/broadcast",
errors, simpHeaderAccessor.getMessageHeaders());
}
}
If you are using #ResponseBody #Valid on your controller method parameter, you'll have to move the logic lines to your ControllerAdvice exceptionHandler().

How to copy email in sent folder?

I am using java mail api for sending mail.In that for sending email i configured yahoo smtp port.I am able to send mail from yahoo account but sent mail is not saving in sent item.For incoming service i configured imap yahoo server.
service:
#Component
public class SmtpMailSender {
#Autowired
private JavaMailSender javaMailSender;
private static String folderName = "Sent";
private String host="smtp.mail.yahoo.com";
private String user="abc#yahoo.com";
private String pass="xxxx";
public void send(String to,String subject,String body, String from) throws MessagingException
{
// Java Mail properties
Properties props = System.getProperties();
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", "465");
props.put("mail.smtp.auth", "true");
// Mail session authentified
Session session = Session.getInstance(props);
MimeMessage message=javaMailSender.createMimeMessage();
MimeMessageHelper helper=new MimeMessageHelper(message,true);
helper.setTo(to);
helper.setFrom(from);
helper.setSubject(subject);
helper.setText(body,true);
javaMailSender.send(message);
// Copy message to "Sent Items" folder as read
Store store = session.getStore();
store.connect("imap.mail.yahoo.com", user, pass);
Folder folder = store.getFolder(folderName);
if (!folder.exists()) {
folder.create(Folder.HOLDS_MESSAGES);
}
folder.open(Folder.READ_WRITE);
folder.appendMessages(new Message[] {message});
message.setFlag(FLAGS.Flag.RECENT, true);
System.out.println("Msg send and saved ....");
store.close();
}
}
Controller:
#RestController
public class EmailController {
#Autowired private SmtpMailSender smtpMailSenderObj;
#RequestMapping("/send")
public void sendMail() throws MessagingException {
smtpMailSenderObj
.send
("pqr#gmail.com", "verify sendMail",
"Hii...this is demo for java email send",
"abc#yahoo.com");
}
}
Application.properties:
spring.mail.host=smtp.mail.yahoo.com
spring.mail.username=abc#yahoo.com
spring.mail.password=xxxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.transport.protocol : smtp
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.debug=true
spring.mail.properties.mail.smtp.socketfactory.port=465
spring.mail.properties.mail.imap.ssl.required=true
spring.mail.properties.mail.imap.port=993
You need to explicitly append the message object to the "Sent" Folder.
This is because of imap port connection send mail was not saving in sent items.
Need to add set property in properties file.
props.setProperty("mail.store.protocol", "imaps");
By adding this now i am able to save my sent mail in sent item.

Request response over HTTP with Spring and activemq

I am building a simple REST api which connects a web server to a back end service, which performs a simple check and sends a response.
So client (over HTTP) -> to Web Server (over ACTIVEMQ/CAMEL)-> to Checking-Service, and back again.
The endpoint for the GET request is "/{id}". I'm trying to make this send a message through queue:ws-out to queue:cs-in and map it all the way back again to the original GET request.
The Checking-Service (cs) code is fine, it simply changes a value in the CheckMessage object to true using jmslistener.
I've searched the web thoroughly for examples, but can't get anything to work. The closest one I found was the following.
This is what I have so far on the Web Server (ws).
RestController
import ...
#RestController
public class RESTController extends Exception{
#Autowired
CamelContext camelContext;
#Autowired
JmsTemplate jmsTemplate;
#GetMapping("/{id}")
public String testCamel(#PathVariable String id) {
//Object used to send out
CheckMessage outMsg = new CheckMessage(id);
//Object used to receive response
CheckMessage inMsg = new CheckMessage(id);
//Sending the message out (working)
jmsTemplate.convertAndSend("ws-out", outMsg);
//Returning the response to the client (need correlation to the out message"
return jmsTemplate.receiveSelectedAndConvert("ws-in", ??);
}
}
Listener on ws
#Service
public class WSListener {
//For receiving the response from Checking-Service
#JmsListener(destination = "ws-in")
public void receiveMessage(CheckMessage response) {
}
}
Thanks!
your receive messages from "ws-in" with 2 consumers jmsTemplate.receiveSelectedAndConvert and WSListener !! message from a queue is consumed by one of the 2.
you send messages to "ws-out" and consume from "ws-in" ?? last queue
is empty and not receive any message, you have to send messages to
it
you need a valid selector to retrieve the message with receiveSelectedAndConvert based on JMSCorrelationID as the example you mntioned or the id received from the rest request but you need to add this id to the message headers like below
this.jmsTemplate.convertAndSend("ws-out", id, new MessageCreator() {
#Override
public Message createMessage(Session session) throws JMSException {
TextMessage tm = session.createTextMessage(new CheckMessage(id));
tm.setJMSCorrelationID(id);
return tm;
}
});
return jmsTemplate.receiveSelectedAndConvert("ws-in", "JMSCorrelationID='" + id+ "'");
forward messages from "ws-out" to "ws-in"
#Service
public class WSListener {
//For receiving the response from Checking-Service
#JmsListener(destination = "ws-out")
public void receiveMessage(CheckMessage response) {
jmsTemplate.convertAndSend("ws-in", response);
}
}

Retrieve JMS Headers right after the message is sent without consuming the message

How can I retrieve JMS Message headers after sending the message but without consuming the message ?
this is my message sending code
jmsTemplate.convertAndSend(que, text, message -> {
LOGGER.info("setting JMS Message header values");
message.setStringProperty(RequestContext.HEADER_ID, id);
// LOGGER.info(message.getJMSMessageId()); -- this gives a null value here
return message;
});
the message headers get generated only after the message is posted to the queue so iis there a simple way to retrieve JMS message headers when using MessagePostProcessor?
I've referred the links - here and here but not much of help :(
You can't get the JmsMessageID header until the message is actually sent; the post processor just allows you to modify the converted message JUST BEFORE it is sent.
However, your second link should work ok, since it saves off a reference to the message which you can access later.
EDIT
Confirmed:
#SpringBootApplication
public class So48001045Application {
public static void main(String[] args) {
SpringApplication.run(So48001045Application.class, args).close();
}
#Bean
public ApplicationRunner runner(JmsTemplate template) {
return args -> {
final AtomicReference<Message> msg = new AtomicReference<>();
template.convertAndSend("foo", "bar", m -> {
msg.set(m);
return m;
});
System.out.println(msg.get().getJMSMessageID());
};
}
}
and
ID:host.local-61612-1514496441253-4:1:1:1:1

Resources