Too much time to send mail with MS exchange SMTP server - java

Hi all and thanks for your help
I use javamail to send mail throhght office365 SMTP server ( smtp.office365.com) , but for some reason it keeps about 60-80 seconds to send mail.
stringaHost = "mail.smtp.host";
stringaUser = "mail.smtp.user";
Security.setProperty("ssl.SocketFactory.provider","com.ibm.jsse2.SSLSocketFactoryImpl");
Security.setProperty("ssl.ServerSocketFactory.provider","com.ibm.jsse2.SSLServerSocketFactoryImpl");
InitialContext initialContext = null;
initialContext = new InitialContext();
session = (Session)initialContext.lookup(nomeJndi);
session.getProperties().put("mail.smtp.auth", "true");
session.getProperties().put("mail.smtp.socketFactory.port", 465);
session.getProperties().put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
MimeMessage MsgEmail = new MimeMessage( session );
com.sun.mail.smtp.SMTPTransport t =(com.sun.mail.smtp.SMTPTransport)session.getTransport("smtp");
t.setStartTLS(true);
t.connect( smtp.office365.com,myUser,myPassword);
t.sendMessage( MsgEmail, MsgEmail.getAllRecipients());
t.close();
java mail spend more than 60 sec to evaluate instruction : t.connect(....) .
Any clue about what can happen and how can this time interval can be reduced ?
P.S. i tried to use t.connect() without parameters, by system technical says that this instruction use SMTP transport protocol from operating system and don't use Office365 server transport protocol
thanks

First, you shouldn't need all those socket factory properties.
If the delay is on the connect call, the possibilities are:
Your name service is slow in looking up the IP address for the server's host name.
The SSL negotiation is slow, perhaps due to certificate management on the client or server.
The server is slow authenticating you.
You can test #1 by seeing how long it takes InetAddress to look up the host name for your server.
You can test #2 by seeing how long it takes SSLSocket to make a connection to the server.
You can test #3 by either watching the JavaMail debug output in real time to see where the delay is, or getting time-stamped log messages from JavaMail.

Related

You must issue STARTTLS command first

I am connection to smtp.live.com but when i run program and insert email credentials it asks to use starttls command first what i can do to avoid this exception.
try {
Socket socket1= new Socket("smtp.live.com",587);
again:
while(true) {
Scanner s= new Scanner(System.in);
String from=""; String to=""; String cc=""; String bcc="";
mail[m_count]=new Message();
The problem is here:
Socket socket1 = new Socket("smtp.live.com", 587);
If the port number was 25, that would be fine. The problem is that you are trying to use SSL enabled SMTP, and that requires that you an SSL socket. But that is a bit more complicated ...
However, I think that there is a bigger issue here. The normal way to send / receive emails from Java is to use the javax.mail APIs. But if you are opening a socket (or SSL socket) to the mail server, that implies that you intend to implement the client side of the SMTP specification. Unless you have a really good reason to do that ... it sounds like a waste of effort.
The tutorial link provided by #npinti assumes that you are going to use javax.mail. If you
want to do it the hard way, this tutorial shows you how to use an SSL socket.

Javamail error: SMTPAddressFailedException: 450 too many connections from your IP (rate controlled)

I have a Spring 4.1.1 web application in which the user can set some scheduled tasks. When these tasks complete the administrator will receive an automatic email sent with the SMTP method.
For the email I use the jars: javax.mail-api-1.5.2.jar and mail-1.5.0-b01.jar
The email are sent correctly at first, but when the frequency of the tasks goes up eventually I start to get the following exception and all subsequent emails fails. I can send about 30 emails in a 10 minutes window.
com.sun.mail.smtp.SMTPAddressFailedException: 450 too many connections from your IP (rate controlled)
at com.sun.mail.smtp.SMTPTransport.rcptTo(SMTPTransport.java:1862)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1118)
at com.synaptic.email.MessageMail.sendMessage(MessageMail.java:152)
at com.synaptic.email.EmailManagerImpl.sendGeneralEmail(EmailManagerImpl.java:423)
The code snippet from which I send the emails is:
public void sendMessage(Brand brand, String timeout) throws MessagingException
{
try {
// Prepare message
Properties props = new Properties();
props.put("mail.smtp.host", mailHost);
props.put("mail.smtp.connectiontimeout", timeout);
props.put("mail.smtp.timeout", timeout);
props.put("mail.smtp.writetimeout", timeout);
props.put("mail.smtp.port", Integer.parseInt(brand.getBrandProperties().getEmailPort()));
Session session = Session.getInstance(props);
message = new MimeMessage(session);
createMessage();
if (brand.getBrandProperties().getEmailUsername().isEmpty() && brand.getBrandProperties().getEmailPassword().isEmpty()) {
// Send email message to SMTP server without auth
Transport.send(message);
} else {
// Send message with auth
Transport.send(message,brand.getBrandProperties().getEmailUsername(),brand.getBrandProperties().getEmailPassword());
}
} catch (MessagingException e) {
log.error("Failed to send email message.", e);
throw e;
}
}
From the javamail documentation and source code seems clear that the transport connection are closed on a finally statement, so no connection should be hanging open, but still I hit this exception.
I checked online but I can't find a way to increase this limit.
Am I doing something wrong sending the message? is there a way to monitor the email connections? or is an email server issue?
Your server is telling you that you're making too many connections in too short a time. It's rate-limiting you to prevent you from abusing the server. You may need to pay for a higher quality of service to be allowed to send more messages. Contact your ISP for details.
BTW, you say you're using javax.mail-api-1.5.2.jar and mail-1.5.0-b01.jar. You should not mix and match versions like that. You only need one jar file - the javax.mail-1.5.2.jar file. You can get it on the JavaMail project page.

SMTP/POP3 through proxy System.getProperties() vs new Properties()?

Im trying to get mail from a POP3 server through a proxy. Most "tutorials" suggest doing something like
Properties p = System.getProperties();
p.setProperty("proxySet", "true");//does this line even do anything?
p.setProperty("socksProxyHost", proxyHost);
p.setPorperty("socksProxyPort", proxyPort);
p.setProperty("socksProxyVersion", "5");//or 4 if you want to use 4
p.setProperty("mail.pop3.socketFactory.class", SSL_FACTORY);
p.setProperty("mail.pop3.socketFactory.fallback", "false");//also not sure what it does
p.setProperty("mail.pop3.port", portOnHostYouWantToTalkTo);
p.setProperty("mail.pop3.socketFactory.port", portOnHostYouWantToTalkTo);
Session session = Session.getDefaultInstance(p, null);
//or session = Session.getInstance(p, null);
URLName urlName = new URLName(protocol, hostYouwantToTalkTo, portOnHostYouWantToTalkTo, null, mailbox, mailboxPassword);
Store store = session.getStore(urlName);
Now, if I do something like this I get an exception:
java.net.SocketException: Can't connect to SOCKS proxy:Connection timed out: connect.
My POP3 server does not log any connections, suggesting there is a proxy issue or an error in my code. I am using 73.29.157.190:29099 for now.
2) If, however, I do
Properties p = new Properties();
//all the same logic and stuff
Session = Session.getInstance(p, null);
My POP3 server logs a connection from localhost, and works properly, suggesting that I am NOT using a proxy to connect to it and everything else is fine.
My question is, why do "tutorials" use System.getProperties() and pass it to getInstance()? Every Session instance will keep a reference to System.properties. So, effectively every Session instance will be affected every time you try to create a new one or alter System.getProperties() in any way so you might as well reuse the same one.
Does javamail need something set in System.properties specifically and not the ones passed to Session?
Also, what parameters do you need to set in order to get javamail to use a proxy? What does System.properties have that makes it work unlike my new Properties? A link to a good tutorial or documentation that explains it would be greatly appreciated.
Thanks!
First, get rid of all the socket factory stuff, you don't need it.
Next, make sure you really have a SOCKS proxy and not just a web proxy. If you do, see this JavaMail FAQ entry.
Setting the System properties for a SOCKS proxy will cause all network connections from your program to go through the proxy server, which may not be what you want.

How to Send bulk mails using javax.mail API efficiently? & Can we use reuse authenticated sessions to improve speed?

I am able to send a mail using javax.mail API. But the problem here is on an average for each mail it taking around 4.3 seconds to send to destination.
If I am sending a 20 mails sequentially, it takes around 86.599 seconds. For my requirement this approach will not work. I am looking for an approach which can send large number of mails in less time.
When I looked at the debug log, the API is trying to authenticate to SMTP server for each and every message it sending. But I am creating a session only one time and using the same session for all the mails I am sending. Now my question is Isn't it a overhead process every time authenticating itself to the smtp server. Isn't there a better approach ?
Below is the log trace you may find helpful.
250-AUTH LOGIN PLAIN XOAUTH XOAUTH2
250 ENHANCEDSTATUSCODES
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH XOAUTH2"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Attempt to authenticate
DEBUG SMTP: check mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
Please let me know your thoughts on this and any help on this is really appreciated.
-Narendra
How are you sending the messages? The JavaMail FAQ suggests that the static Transport.send method will open a fresh connection for each message, as it is a convenience method that creates a suitable Transport instance, connects it, calls sendMessage and then closes the connection again. If you get your own Transport instance from the Session you can connect once, then call sendMessage repeatedly to send several messages on the one connection, and finally close it. Something along the lines of (untested):
Transport t = session.getTransport();
t.connect();
try {
for(Message m : messages) {
m.saveChanges();
t.sendMessage(m, m.getAllRecipients());
}
} finally {
t.close();
}
Updated to use try with resources block:
try (Transport t = session.getTransport()) {
t.connect();
for(Message m : messages) {
m.saveChanges();
t.sendMessage(m, m.getAllRecipients());
}
}
I got the same requirement at work. I must send bulk emails and standalone email. I do not find simple and satisfactory answer: bulk emails can be sent using a single connection but standalone email cannot until I create an asynchronous buffering to send emails in batch.
Last but not least, using a lot of Transport connection in a short time can lead to a no more socket handles are available because all ports are stuck in the TIME_WAIT state.
I finally conclude the best will be an SMTP connection pool and because no library exists (at least free) I create mine using Apache Common Pool and Java Mail:
//Declare the factory and the connection pool, usually at the application startup
SmtpConnectionPool smtpConnectionPool = new SmtpConnectionPool(SmtpConnectionFactoryBuilder.newSmtpBuilder().build());
//borrow an object in a try-with-resource statement or call `close` by yourself
try (ClosableSmtpConnection transport = smtpConnectionPool.borrowObject()) {
MimeMessage mimeMessage = new MimeMessage(session);
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, false);
mimeMessageHelper.addTo("to#example.com");
mimeMessageHelper.setFrom("from#example.com");
mimeMessageHelper.setSubject("Hi!");
mimeMessageHelper.setText("Hello World!", false);
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
}
//Close the pool, usually when the application shutdown
smtpConnectionPool.close();
The above answers are either not relevant or too complex to implement. So here's I am posting the easiest solution to send bulk emails in Spring Boot
Just use
mimeMessageHelper.setBcc(emailList);
Where,
mimeMessageHelper is MimeMessageHelper, emailList is String[] emailList
NOTE:
Make sure that you are not using
mimeMessageHelper.setTo(emailList)
Otherwise, it will show all receivers' email address in the receiver's received email.
For more reference, This and This can help you to learn how to send emails in Spring Boot
No idea if the standard Java mail API allows what you are trying to accomplish (session reuse), but you may consider using multi-threading:
I would use a ThreadPool and submit mail send jobs to it. Then you do any error handling / resending within the job class code, which is executed by the ThreadPool asynchronously, and your main thread can resume to do other things. Submitting a job will only take milliseconds. It been a while since I implemented something with thread pools in Java, but I remember it was fairly easy and straightforward. If you Google "Java ThreadPool" you find plenty of material.
I developed a way to send 1000 emails in less than 1 min. This email has only text. Heavy HTML takes approx 2 mins.
#Async("bulk-email")
void sendBulkEmail(List<EmailMessage> emailMessages){
// EmailMessage is a custom object with properties like to, cc, subject.
Collection<List<EmailMessage>> partitionedList = Lists.partition(emailMessages,
50); // Google Guava library.
try{
ForkJoinPool customThreadPool = new ForkJoinPool(10);
customThreadPool.submit(()->
partitionedList.parallelStream.forEach(this::sendEmails)).get();
}catch(Exception e){
e.printStackTrace();
}
}
This will create 10 threads with each thread will send 50 emails with one Session and one connection.
private void sendEmails(List<EmailMessage> messages){
Session session = createSession();
try (Transport t = session.getTransport()) {
t.addTransportListener(transportListener);
t.connect();
for(Message m : messages) {
MimeMessage mime = createMimeMessage(session, m);
mime.saveChanges();
t.sendMessage(mime, mime.getAllRecipients());
}
}catch(Exception e){
e.printStackTrace();
}
}
You can use Thread pooling as it gives very good performance.I have implemented and sharing you the below code snippet.
try {
ExecutorService executor = Executors.newFixedThreadPool("no. of threads"); // no. of threads is depend on your cpu/memory usage it's better to test with diff. no. of threads.
Runnable worker = new MyRunnable(message); // message is the javax.mail.Message
executor.execute(worker);
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
}

Gmail SMTP Suitable For Production Messaging

I have some automated emailing tasks set up in my application. That is every day I send application specific email to customers to remind them of appointments etc. Is using Gmail's smtp suitable for production tasks beyond just a simple message here any there? Is there any benefit to implementing my own smtp server such as Apache James?
I agree with #Richthofen - Using gmail to send emails in a production environment is a bad (and unethical) idea; Amazon SES or Sendgrid are the best solutions here. If you want to run your own SMTP server then please keep in mind that it will share resources with your application and will probably slow it down.
However I use gmail to test development/testing environments using javamail API. Here's the code:
public class EmailSender{
public void send(){
//javamail code
Session mailSession = createSmtpSession();
//javamail code
}
private Session createSmtpSession() {
final Properties props = new Properties();
props.setProperty ("mail.host", "smtp.gmail.com");
props.setProperty("mail.smtp.auth", "true");
props.setProperty("mail.smtp.port", "" + 587);
props.setProperty("mail.smtp.starttls.enable", "true");
props.setProperty ("mail.transport.protocol", "smtp");
// props.setProperty("mail.debug", "true");
return Session.getDefaultInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"<gmail ID in user#domain format goes here>",
"<password goes here>");
}
});
}
}
Gmail TOS prohibits unsolicited commercial emails. In general I wouldn't deploy any service that relies on Gmail to the public. I think Gmail caps an email recipient list to 100 anyways so it would probably fail if you tried to send the same message to more than 100 people.
Usually you want your own IP for outgoing mail for reputation reasons. For most of my clients when I do freelance work I recommend affordable partner services like http://sendgrid.com/ ... Having your own IP means that you can manage your reputation as a bulk email sender legitimately. And you won't have to worry about Gmail shutting you down for breaking the TOS. Gmail also won't give you metrics about deliverability so you won't have any idea if you're being successful in sending these.
Having worked for a major email marketer, I can tell you that just sending a message to an SMTP server is not enough these days. All major mail service providers do things like require sender identification keys for bulk mail. They also meter messages and flag senders who end up submitting too many messages in a specific amount of time. If you want your mail delivered and not in the SPAM folder you need to do either a lot of work and spin up a dedicated server w/ a dedicated IP, or you should use a vendor who can do some of that work for you.

Categories