How to copy email in sent folder? - spring-boot

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.

Related

Not able to call SOAP API in WebServiceGatewaySupport by Spring WebServiceTemplate - Need help to fix this issue

I am trying to call SOAP API in Java Spring Boot using WebServiceGatewaySupport by Spring WebServiceTemplate
Config java class
public WebServiceTemplate createWebServiceTemplate(Jaxb2Marshaller marshaller, ClientInterceptor clientInterceptor) {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
//SOAP URL
webServiceTemplate.setDefaultUri("http://host/Services.asmx");
//Auth ---It seems issue is here only????? need to check
webServiceTemplate.setMessageSender(new Authentication());
webServiceTemplate.setMarshaller(marshaller);
webServiceTemplate.setUnmarshaller(marshaller);
webServiceTemplate.afterPropertiesSet();
webServiceTemplate.setCheckConnectionForFault(true);
webServiceTemplate.setInterceptors((ClientInterceptor[]) Arrays.asList(createLoggingInterceptor()).toArray());
return webServiceTemplate;
}
SOAP Client Call
public class TicketClient extends WebServiceGatewaySupport {
public String getTicket(Ticket req) {
System.out.println("test inside webservice support1");
response = (AcquireTicketResponse) getWebServiceTemplate().marshalSendAndReceive(req);
Authentication Class
public class Authentication extends HttpUrlConnectionMessageSender {
#Override protected void prepareConnection(HttpURLConnection connection) {
String userpassword = username+":"+password+":"+domain;
String encoded =
Base64.getEncoder().withoutPadding().encodeToString(userpassword.getBytes(StandardCharsets.UTF_8));
connection.setRequestProperty("Authorization", "Basic "+encoded); connection.setRequestProperty("Content-Type", "application/xml"); super.prepareConnection(connection);
}
Not using Authetication class and add the above into
ClientInterceptor
public class SoapLoggingInterceptor implements ClientInterceptor {
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
String username="test";
String password="test";
String domain = "#test";
String userpassword = username+":"+password+domain;
String encoded = Base64.getEncoder().withoutPadding().encodeToString(userpassword.getBytes(StandardCharsets.UTF_8));
messageContext.setProperty("Authorization", "Basic "+encoded);
messageContext.setProperty("Content-type", "XML");
Case -1 --->When I passed (user, pwd, domain and content-type) through messagesender, content type is taking but throwed "BAD REQUEST ERROR 400"....When i comment contenttype property, then it throwed "INTERNAL SERVER ERROR 500".
Case-2...when I passed (user, pwd, domain and content-type) through ClientInterceptor , always it throwed "INTERNAL SERVER ERROR 500"......It seems Authentication properties for the service are not going to API call.............................Please suggest some options
Both the cases, Authentication is not passing to service, if i comment,Authentication code (userid/pwd/domain) in both cases also...no efforts in output
After setting the user ID/pwd
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
String username="test";
String password="test";
String domain = "#test";
String userpassword = username+":"+password+domain;
byte[] userpassword = (username+":"+password).getBytes(StandardCharsets.UTF_8);
String encoded = Base64.getEncoder().encodeToString(userpassword);
ByteArrayTransportOutputStream os = new
ByteArrayTransportOutputStream();
try {
TransportContext context = TransportContextHolder.getTransportContext();
WebServiceConnection conn = context.getConnection();
((HeadersAwareSenderWebServiceConnection) conn).addRequestHeader("Authorization", "Basic " + encoded);
} catch (IOException e) {
throw new WebServiceIOException(e.getMessage(), e);
}
First of all don't set the content type Spring WebServices will do that for you, messing around with that will only make things worse.
You should get the WebServiceConnection and cast that to a HeadersAwareSenderWebServiceConnection to add a header.
public class BasicAuthenticationInterceptor implements ClientInterceptor {
#Override
public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException {
String username="test#test";
String password="test";
byte[] userpassword = (username+":"+password).getBytes(UTF_8);
String encoded = Base64.getEncoder().encodeToString(userpassword);
WebServiceConnection conn = TransportContext.getConnection();
((HeadersAwareSenderWebServiceConnection) conn).addHeader("Authorization", "Basic " + encoded);
}
}
You also need to configure it. Assuming it is a bean don't call afterPropertiesSet (and ofcourse you are now using the ClientInterceptor remove the new Authentication() for your customized message sender.
The List<ClientInterceptor> will automatically create a list with all the interceptors so you can easily inject them.
#Bean
public WebServiceTemplate createWebServiceTemplate(Jaxb2Marshaller marshaller, List<ClientInterceptor> clientInterceptors) {
WebServiceTemplate webServiceTemplate = new WebServiceTemplate(marshaller);
//SOAP URL
webServiceTemplate.setDefaultUri("http://host/Services.asmx");
webServiceTemplate.setCheckConnectionForFault(true);
webServiceTemplate.setInterceptors(clientInterceptors);
return webServiceTemplate;
}
If this doesn't work there is something else you are doing wrong and you will need to get in touch with the server developers and get more information on the error.
Update:
Apparently you also need to provide a SOAP Action in your request, which you currently don't. For this you can specify the SoapActionCallback in the marshalSendAndReceive method. Which action to specify you can find in the WSDL you are using.
SoapActionCallback soapAction = new SoapActionCallback("SoapActionToUse");
response = (AcquireTicketResponse) getWebServiceTemplate().marshalSendAndReceive(req, soapAction);

Spring and SimpleMailMessage: change setTo and setFrom

I am building a Spring app that allows the user to send an email to customer support.
I have noticed though that it doesn't matter what I put in the attributes "setTo" and "setFrom" of the SimpleMailMessage, I keep receiving the email from myself to myself.
Here is my code:
Controller Endpoint
#PostMapping("/send-email")
public ResponseEntity<Object> sendEmail(#RequestParam String userEmail) {
log.info("[START] send-email");
notificationService.sendNotification();
return new ResponseEntity<>(HttpStatus.OK);
}
Service
public void sendNotification(String emailUtente) {
SimpleMailMessage messaggio = new SimpleMailMessage();
messaggio.setTo(customerServiceAddress);
messaggio.setFrom(emailUtente);
messaggio.setSubject("Test Spring Email");
messaggio.setText("Tadaaaa! Email da Spring!");
try{
javaMailSender.send(messaggio);
} catch (Exception ex){
log.error("Error! " + ex.getMessage());
}
}
application.properties
spring.mail.host=smtp.gmail.com
spring.mail.port=587
spring.mail.username=theCustomerServiceAddress
spring.mail.password=thePassword
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
Where am I mistaking?
Also, I am not sure what should be put into the property spring.mail.username, I guessed the email address of whom is receiving the email?
Thank you for your experience and time.

My SQSListener returns body as messageID, And How do I get send MessageId with QueueMessagingTemplate Spring Boot?

I have 2 issues regarding Spring AWS-SQS sdk, (Or maybe I am doing it wrong).
First is that I used CLI earlier and I managed to get the message Id of the sent message example:
aws sqs send-message --queue-url https://sqs.us-west-2.amazonaws.com/testqueue --message-body hooray
'{
"MD5OfMessageBody": "d3101ad",
"MessageId": "jdhj-933"
}
Now I tried with spring-cloud-starter-aws-messaging and I setup a Queue Messaging template like this
private final QueueMessagingTemplate queueMessagingTemplate;
public SqsQueueService(#Qualifier("amazonSQSAsync") final AmazonSQSAsync amazonSQS) {
this.queueMessagingTemplate = new QueueMessagingTemplate(amazonSQS);
}
public void sendMessage(String queueName, String queueMessage) {
Map<String, Object> headers = new HashMap<>();
queueMessagingTemplate.convertAndSend(queueName, queueMessage, headers);
}
I can seem to get the message Id of the sent message using queueMessagingTemplate.convertAndSend(queueName, queueMessage, headers);
I need the messageId to fulfil some business logic.
The second issue is my listener can receive messages however the messageID is null as well;
#Async
#SqsListener(value = "${notification.sqs-queue-url}", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
public void listen(Acknowledgment acknowledgment, String message, String messageId) {
//messageId is equal to message here. which is wrong for me
}
The message is always equal to messageId, which is confusing, Any advice on where I maybe going wrong?
I changed the listner method signature to
#Async
#SqsListener(value = "${queue-url}", deletionPolicy = SqsMessageDeletionPolicy.NEVER)
public void listen(Acknowledgment acknowledgment, String message, #Headers MessageHeaders headers) throws ExecutionException, InterruptedException {
String messageId = (String) headers.get("MessageId");
acknowledgment.acknowledge().get();
}
Then extracted the messageId from the headers map

Email sent but get timeout

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

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);
}
}

Resources