I am trying to send email using spring-boot but send it using parallel streams so that it is not synchronized.
Can anyone point me in the right direction with code.
This is what I have so far -
for (String toAddress : emailDto.getToEmailAddresses()) {
message = new SimpleMailMessage();
message.setTo(toAddress);
message.setSubject(emailDto.getSubject());
message.setText(emailDto.getBody());
message.setFrom(fromAddress);
emailSender.send(message);
_logger.info("Send Email successfully to " + toAddress);
}
I am trying to do something along these lines-
toAddresses.parallelStream().forEach(System.out::println);
But use parallel stream to send each email.
SimpleMailMessage.setTo already has the case for multiple addresses so you could simply write
message.setTo(emailDto.getToEmailAddresses().toArray(new String[0]))
I am working with SMTP server and found out an issue.
1) SMTP server is not down: In this case, the SMTP server is busy servicing email requests concurrently and continuously for more than 5 minutes (I'm sending bulk mails). At some point of time during servicing, it is not returning or throwing any exceptions to the Java/JavaMail program. In fact, I've experienced this kind of situation in my real time. In case, if I've not set both mail.smtp.timeout and mail.smtp.connectiontimeout properties within my code, it would never return and goes into infinite state.
If i do set my mail.smtp.connectiontimeout and mail.smtp.timeout, how can I test it?
How can we simulate/reproduce this kind of situation? Any ideas?
2) Also another issue is caused by networking issue where I send the request to SMTP form my java code, and it is queued. I am not sure what happens (I dont have a java loop) but the SMTP sends out multiple emails to the same person. Is it because the SMTP did not send back an response? Should the code not timeout after 3000?
Below is my code
props.put("mail.smtp.timeout", 3000);
props.put("mail.smtp.connectiontimeout", 3000);
SMTPTransport transport = (SMTPTransport)session.getTransport("smtp");
/ do some message setting here /
transport.connect();
int SMTPCodeBeforeSendingMessage = transport.getLastReturnCode();
logger.debug("Connection Code for SMTP connection after connect before sending mesasge" + SMTPCodeBeforeSendingMessage);
transport.sendMessage(msg, msg.getAllRecipients());
String SMTPresponse = transport.getLastServerResponse();
logger.debug("SMTP resposne after sending message" + SMTPresponse);
transport.close();
The application I am working on needs to communicate to an IBM MQ server in a remote location. We currently have a working system using active MQ which uses a broker, and a bridge to connect to this remote IBM MQ server and is working fine.
Due to some new enhancement, we are now trying to achieve the same using IBM client jars instead of Active MQ.
The problem I am facing is that I can connect to the remote server's inboundQ and send messages.But I am always receiving null from the remote servers outbound Queue. But I have no way to check if the messages are received at the remote location. But the same message if sending through the old ActiveMQ system will get a response from remote MQ server.
Old Active MQ internally uses the bridge to connect to remote IBM MQ server which is configured exactly like the new code I am using.
I have tried multiple codes from internet and stack overflow itself and always I am able to connect but not getting any responses.
Also, I get no errors or exceptions while trying to send or receive from remote IBM MQ.
I will paste a sample code which I am trying to get to work. I have changed some configuration values in the code.
My doubts are the following.
All I am doing for this is copying IBM MQ client jars into the application and using the code to send messages to remote MQ. I have not installed any other application. Will such a system work or should there always be some intermediate program like active MQ?
The same code is able to send and receive from an IBM MQ server which I installed in our local network but fails to get a response from the remote server? This leads me to believe if I am missing anything in configuration ? should anything else be configured other than in code?
I see no errors or exceptions. Always message is sent but the response is null. I have not seen the usage of any username-password or public-private key authentication. Is there any authentication used normally to check the source. ?
I am using IBM MQ client 5.3 version which I know is old. But used that since they working active MQ setup uses the same and is working correctly. I have no way of knowing which version on IBM MQ server is present on the remote machine. Is there a problem if we use a different client MQ version than the version of server MQ version. ?
Sample code which works for me in local environment ie is able to send and receive from an IBM MQ server I have installed in another machine in the local network. The same code will fetch null response when I am trying to use it with remote IBM MQ server.
import javax.jms.*;
import javax.jms.JMSException;
import com.ibm.mq.jms.*;
import com.ibm.jms.JMSMessage;
import javax.jms.TextMessage;
public class SendReceive {
private MQQueueConnectionFactory connectionFactory;
private MQQueueConnection connection;
private void runTest() {
try {
connect();
connection.start();
MQQueueSession session = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueue queue = (MQQueue) session.createQueue("INBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueue queue2 = (MQQueue) session.createQueue("OUTBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueueSender sender = (MQQueueSender) session.createSender(queue);
MQQueueReceiver receiver = (MQQueueReceiver) session.createReceiver(queue2);
//TextMessage message = session.createTextMessage("yesyesyes");
String stt = "Test Message"; //
TextMessage message = session.createTextMessage(stt);
message.setJMSReplyTo(queue2);
sender.send(message);
System.out.println("Sent: " + message);
Message msg1 = receiver.receive(5000);
if(msg1!=null){
String responseMsg = ((TextMessage) msg1).getText();
System.out.println("Received: " + responseMsg);
}else{
System.out.println("Message received is null");
}
}catch(Exception e){
System.out.println("Exception caught in program : " + e);
e.printStackTrace();
}
}
public boolean connect() {
boolean connected = false;
try {
/* values below are replaced with correct values in deployment server */
connectionFactory = new MQQueueConnectionFactory();
connectionFactory.setPort(1515);
connectionFactory.setHostName("192.168.1.23"); //
connectionFactory.setQueueManager("QCCMGR");
connectionFactory.setChannel("QCHANNEL");
connectionFactory.setTransportType(JMSC.MQJMS_TP_CLIENT_MQ_TCPIP);
connection = (MQQueueConnection) connectionFactory.createQueueConnection();
connected = true;
} catch (Exception e) {
connected = false;
}
return connected;
}
public static void main(String[] args) {
new SendReceive().runTest();
}
}
MQ v5.3 was released November 29th 2002 and has been out of support since September 28th 2007 (almost 9 years). The version may not have anything to do with your issue but I would strongly suggest that you move to a supported version of the MQ client. Newer MQ client versions can connect to older MQ queue managers. You can download a java only install of MQ 8.0 or MQ 9.0 jar files at the links below:
IBM MQ v8.0 Client
IBM MQ v9.0 Client
I read on some old threads that having the sender and receiver on the same session caused problems when a timeout was specified. Try adding another session for the receiver.
private void runTest() {
try {
connect();
connection.start();
MQQueueSession session = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueueSession session2 = (MQQueueSession) connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
MQQueue queue = (MQQueue) session.createQueue("INBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueue queue2 = (MQQueue) session2.createQueue("OUTBOUND_QUEUE"); /* values replaced with correct values in deployment server */
MQQueueSender sender = (MQQueueSender) session.createSender(queue);
MQQueueReceiver receiver = (MQQueueReceiver) session2.createReceiver(queue2);
//TextMessage message = session.createTextMessage("yesyesyes");
String stt = "Test Message"; //
TextMessage message = session.createTextMessage(stt);
message.setJMSReplyTo(queue2);
sender.send(message);
System.out.println("Sent: " + message);
Message msg1 = receiver.receive(5000);
if(msg1!=null){
String responseMsg = ((TextMessage) msg1).getText();
System.out.println("Received: " + responseMsg);
}else{
System.out.println("Message received is null");
}
}catch(Exception e){
System.out.println("Exception caught in program : " + e);
e.printStackTrace();
}
}
Try taking a JMS trace by adding the following to the execution of the java app:
-DMQJMS_TRACE_LEVEL=base
-DMQJMS_TRACE_DIR=/tracedirectory
ex: java -DMQJMS_TRACE_LEVEL=base -DMQJMS_TRACE_DIR=/tracedirectory JavaApp
This should produce a file that I believe ends in .trc in the directory you specify.
You can review this for errors that might help point you in the right direction.
Suggestions:
Try changing your program to force it to send a blank username:
connection = (MQQueueConnection) connectionFactory.createQueueConnection("", "");
Try closing the sender after sender.send is called
sender.close();
With out further information it is difficult to determine the cause. The more information you can gather the better.
It could be some network related configuration issue or maybe Windows Messaging not configured well. You may consider giving WebSphere MQ - Message Test Utility by IBM to ensure that there are no such system or network configuration issues are present.
I'm a beginner in socket programming. So I can't solve my project's errors, I can't even understand where the problem is!
here is my code:
public static void main(String[] args) {
String to = "parisa.roodheleh#gmail.com";
String from = "parisainfinity#yahoo.com";
String host = "localhost";
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host",host);
Session session = Session.getDefaultInstance(properties);
try{
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject("This is the subject Line!");
message.setText("This is autual message!");
Transport.send(message);
System.out.println("sent message successfully...");
}catch(MessagingException mex){
mex.printStackTrace();
}
}
and here is some errors:
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 25; timeout -1;
nested exception is:
java.net.ConnectException: Connection refused: connect
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:2054)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:697)
any idea?
Seems like you are using an invalid smtp host since you are trying to send an email using a yahoo id. Try using smtp.mail.yahoo.com as the host.
properties.setProperty("mail.smtp.host","smtp.mail.yahoo.com");
Although a bit different question, a similar solution is provided in Sending mail from yahoo id to other email ids using Javamail API.
Also please note that once you set this up, if you keep sending emails continuously, eventually (and quite soon), yahoo (or the smtp host) will terminate/hold the sender's account since you are spamming an account imitating the actions of a potential bot.
check if your port 25 is block or not by :
https://mediatemple.net/community/products/dv/204404564/checking-your-outgoing-mail-server-(is-port-25-blocked)
I'm using javamail to send emails to a list of recipients, but don't want them to be able to see who else received the email. I also don't want to send it using BCC since then the user doesn't even see themselves in the TO list. I thought this code would do it, but it shows all the recipients in the TO list. Other than creating a loop and sending the emails one at a time, is there another way to do this?
(NOTE: recipients[] is a string array containing the email addresses.)
javax.mail.internet.InternetAddress[] addressTo = new javax.mail.internet.InternetAddress[recipients.length];
for (int i = 0; i < recipients.length; i++)
{
addressTo[i] = new javax.mail.internet.InternetAddress(recipients[i]);
}
msg.setRecipients(javax.mail.Message.RecipientType.TO, addressTo);
No, there isn't a way to do this with email.
You have to explicitly build and send an email iterating by each of your recipients, one of them as the sole member of your addressTo array.
The SMTP protocol doesn't care who's listed in the message and the recipients specified on the RCPT TO command are only used to figure out who to transport the message to. There's nothing stopping you from building the RFC822 message with the To header as you've defined above and then writing a custom SMTP client that send your particular message out but with a different set of recipients. And just because you can send the message doesn't mean a spam filter along the way is going to notice the wonky recipient headers and block the message.
In my experience, JavaMail's SMTP client is really good at sending basic messages without any of the mail tricks you often seen used by mailing list providers and spammers. Those companies spend a lot of effort to make sure they can send messages the way they want but they also are in a constant fight to make sure they're messages are treated as legit email.
Short answer: I'd resort to BCC and if this is for marketing purposes, consider using a company that specializes in this kind of thing.
Why are you concerned about the recipient not seeing his own address? He already knows his his own address, so why is it an issue? BCC was designed to handle exactly the problem you describe. It's been around for decades & sounds like a perfect fit.
Actually, we don't have to manually create InternetAddress objects for Multi Recepients.
InternetAddress api provides a parse() method to do this for us.
Sample code for this is as below,
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toAddress));
Here parse method creates multiple InternetAddress objects if toAddress contains multiple email addresses seperated by ,(comma).
Check for below API for more details.
http://docs.oracle.com/javaee/6/api/javax/mail/internet/InternetAddress.html#parse(java.lang.String)
Happy Coding. :)
as Message.RecipientType you should use Message.RecipientType.BCC to not showing the every address to every recipient
Google Keywords: Java Mail BCC
Try this:
Session session = Session.getInstance(properties);
Transport transport = session.getTransport("smtp");
String recipient = "ex1#mail.com,ex2#mail.";
String[] recipients = recipient.split(",");
transport.connect(server, username, password);
for (String to : recipients) {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
InternetAddress[] address = {new InternetAddress(to)};
message.setRecipients(Message.RecipientType.TO, address);
message.setSubject(subject);
message.setText(body);
message.setContent(body, "text/plain");
message.saveChanges();
transport.sendMessage(message, address);
}
transport.close();
According to the documentation for javax.mail.Transport:
public static void send(Message msg,
Address[] addresses)
throws MessagingException
Send the message to the specified addresses, ignoring any recipients specified
in the message itself.
So you should be able to put the actual delivery addresses (RCPT TO addresses) in the array argument to Transport.send, while putting whatever you want the recipients to see in the message headers via Message.setRecipient, MIMEMessage.addHeader, etc.
If you want different sets of users to see different things, you will have to construct and send a separate message for each set.
You can do this by setting the code as below
message.setRecipients(Message.RecipientType.BCC, toAddrs);
instead of
message.setRecipients(Message.RecipientType.TO, toAddrs);
Place your session creation inside the loop. It will create the session for every user but
it's time complex.