I found several other questions on SO regarding the JavaMail API and sending mail through an SMTP server, but none of them discussed using TLS security. I'm trying to use JavaMail to send status updates to myself through my work SMTP mail server, but it requires TLS, and I can't find any examples online of how to use JavaMail to access an SMTP server that requires TLS encryption. Can anyone help with this?
We actually have some notification code in our product that uses TLS to send mail if it is available.
You will need to set the Java Mail properties. You only need the TLS one but you might need SSL if your SMTP server uses SSL.
Properties props = new Properties();
props.put("mail.smtp.starttls.enable","true");
props.put("mail.smtp.auth", "true"); // If you need to authenticate
// Use the following if you need SSL
props.put("mail.smtp.socketFactory.port", d_port);
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
You can then either pass this to a JavaMail Session or any other session instantiator like Session.getDefaultInstance(props).
Good post, the line
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
is mandatory if the SMTP server uses SSL Authentication, like the GMail SMTP server does. However if the server uses Plaintext Authentication over TLS, it should not be present, because Java Mail will complain about the initial connection being plaintext.
Also make sure you are using the latest version of Java Mail. Recently I used some old Java Mail jars from a previous project and could not make the code work, because the login process was failing. After I have upgraded to the latest version of Java Mail, the reason of the error became clear: it was a javax.net.ssl.SSLHandshakeException, which was not thrown up in the old version of the lib.
The settings from the example above didn't work for the server I was using (authsmtp.com). I kept on getting this error:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
I removed the mail.smtp.socketFactory settings and everything worked. The final settings were this (SMTP auth was not used and I set the port elsewhere):
java.util.Properties props = new java.util.Properties();
props.put("mail.smtp.starttls.enable", "true");
Just use the following code. It is really useful to send email via Java, and it works:
import java.util.*;
import javax.activation.CommandMap;
import javax.activation.MailcapCommandMap;
import javax.mail.*;
import javax.mail.Provider;
import javax.mail.internet.*;
public class Main {
public static void main(String[] args) {
final String username="your#gmail.com";
final String password="password";
Properties prop=new Properties();
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.host", "smtp.gmail.com");
prop.put("mail.smtp.port", "587");
prop.put("mail.smtp.starttls.enable", "true");
Session session = Session.getDefaultInstance(prop,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
try {
String body="Dear Renish Khunt Welcome";
String htmlBody = "<strong>This is an HTML Message</strong>";
String textBody = "This is a Text Message.";
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("your#gmail.com"));
message.setRecipients(Message.RecipientType.TO,InternetAddress.parse("receiver#gmail.com"));
message.setSubject("Testing Subject");
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap();
mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html");
mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml");
mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain");
mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed");
mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822");
CommandMap.setDefaultCommandMap(mc);
message.setText(htmlBody);
message.setContent(textBody, "text/html");
Transport.send(message);
System.out.println("Done");
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
I just spent quite a bit of time figuring out how to use JavaMail to send emails with gmail or office365. I couldn't find the answer in the faq, but was helped a bit by the javadoc.
If you forget props.put("mail.smtp.starttls.enable","true") you get com.sun.mail.smtp.SMTPSendFailedException: 451 5.7.3 STARTTLS is required to send mail.
If you forget props.put("mail.smtp.ssl.protocols", "TLSv1.2"); you get javax.mail.MessagingException: Could not convert socket to TLS; and No appropriate protocol (protocol is disabled or cipher suites are inappropriate). Apparently this is only necessary for JavaMail versions 1.5.2 and older.
Here is the minimal code I required to get it to work:
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class SendEmail {
public static void main(String[] args) {
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable","true");
// smtp.gmail.com supports TLSv1.2 and TLSv1.3
// smtp.office365.com supports only TLSv1.2
props.put("mail.smtp.ssl.protocols", "TLSv1.2");
props.put("mail.smtp.host", "smtp.office365.com");
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props, new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("test#example.com", "******");
}
});
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("sender#example.com"));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse("recipient#example.com"));
message.setSubject("You got mail");
message.setText("This email was sent with JavaMail.");
Transport.send(message);
System.out.println("Email sent.");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
}
With Simple Java Mail 5.0.0 (simplejavamail.org) it is very straightforward and the library will take care of all the Session properties for you.
Here's an example using Google's SMTP servers:
Email email = EmailBuilder.startingBlank()
.from("lollypop", "lol.pop#somemail.com")
.to("C.Cane", "candycane#candyshop.org")
.withSubject("hey")
.withPlainText("We should meet up!")
.withHTMLText("<b>We should meet up!</b>")
.buildEmail();
MailerBuilder.withSMTPServer("smtp.gmail.com", 25, "user", "pass", SMTP_TLS)
.buildMailer()
.sendMail(email);
MailerBuilder.withSMTPServer("smtp.gmail.com", 587, "user", "pass", SMTP_TLS)
.buildMailer()
.sendMail(email);
MailerBuilder.withSMTPServer("smtp.gmail.com", 465, "user", "pass", SMTP_SSL)
.buildMailer()
.sendMail(email);
If you have two-factor login turned on, you need to generate an application specific password from your Google account.
As a small note, it only started to work for me when I changed smtp to smtps in the examples above per samples from javamail (see smtpsend.java, https://github.com/javaee/javamail/releases/download/JAVAMAIL-1_6_2/javamail-samples.zip, option -S).
My resulting code is as follow:
Properties props=new Properties();
props.put("mail.smtps.starttls.enable","true");
// Use the following if you need SSL
props.put("mail.smtps.socketFactory.port", port);
props.put("mail.smtps.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtps.socketFactory.fallback", "false");
props.put("mail.smtps.host", serverList.get(randNum));
Session session = Session.getDefaultInstance(props);
smtpConnectionPool = new SmtpConnectionPool(
SmtpConnectionFactories.newSmtpFactory(session));
final ClosableSmtpConnection transport = smtpConnectionPool.borrowObject();
...
transport.sendMessage(message, message.getAllRecipients());
Related
My code to send a mail via gmail was working fine 3 months back. But when I checked it again today, it is failing with below error.
My gmail account is not 2 factor authenticated.
Code :
package com.mail;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class Mailer {
public static void sendMail(String messageSubject, String messageString)
{
Properties props = new Properties();
props.put("mail.smtp.host", ConstantsHolder.MAIL_HOST);
props.put("mail.smtp.user", ConstantsHolder.FROM_EMAIL);
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
props.put("mail.smtp.debug", "true");
props.put("mail.smtp.socketFactory.fallback", "false");
//To use TLS
props.put("mail.smtp.starttls.enable", "true");
//get Session
Session session = Session.getDefaultInstance(props,
new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(ConstantsHolder.FROM_EMAIL,ConstantsHolder.FROM_EMAIL_PASSWD);
}
});
//compose message
try {
MimeMessage message = new MimeMessage(session);
message.addRecipient(Message.RecipientType.TO,new InternetAddress(ConstantsHolder.TO_EMAIL));
message.setSubject(messageSubject);
message.setText(messageString);
//send message
Transport.send(message);
System.out.println("message sent successfully");
}
catch (MessagingException e)
{
System.out.println("Failed " + e.getMessage());
throw new RuntimeException(e);
}
}
}
Error is :
Failed failed to connect
Exception in thread "main" java.lang.RuntimeException: javax.mail.AuthenticationFailedException: failed to connect
at com.mail.Mailer.sendMail(Mailer.java:57)
at com.mail.MailMain.main(MailMain.java:7)
Caused by: javax.mail.AuthenticationFailedException: failed to connect
at javax.mail.Service.connect(Service.java:322)
at javax.mail.Service.connect(Service.java:172)
at javax.mail.Service.connect(Service.java:121)
at javax.mail.Transport.send0(Transport.java:190)
at javax.mail.Transport.send(Transport.java:120)
at com.mail.Mailer.sendMail(Mailer.java:51)
... 1 more
Am I doing something wrong here?
I have also checked other question, but its related to "failed to connect : no password provided"
===============================================================
Edit : Solution
After trying debug mode ON as asked by #Nasten1988, I found the root cause of the issue and was able to proceed. Hence marking #Nasten1988 's answer as the right answer.
Read my answer for the actual issue I had.
===============================================================
Failed to connect: maybe you connection is blocked by firewall, is your software up to date? No password provided: check the requirements from Google, they maybe changed them and check how your password is provided for your mail method. Maybe the debugger can help you. That's what I would look for.
So this is what helped me -
I set debug mode to true for the mail session -
session.setDebug(true);
which displayed the actual problem -
Less secure apps were turned off in my gmail account.
Apparently if its not used for some time, its auto turned off.
https://myaccount.google.com/lesssecureapps
You have to turn off 2-Factor authentication before allowing less secure apps.
When I try to send mail in java from my personal email like (sp#gmail.com) it is sent successfully.
But when I am using my company email(sp#example.com) it throws Authentication failed exception. I am using TLS authentication and it is successfully connected to host.
When I am manually login on my email it will always ask for Two Step
verification. Even if I have disabled my two step verification and have also done the change to make it less secure, it still asks for two step verification as it is showing this message after putting my username and password:
2-Step Verification
Based on your organization's policy, you need to turn on 2-step verification. Contact your administrator to learn more.
Enter one of your 8-digit backup codes
In this situation what should I do? As this is my first task in this company, I would be so happy if you could help me. How I can solve this problem?
My code :
String to = "abc#example.com";
String user = "sp#example.com";
String pass = "1234";
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.example.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
Session session = Session.getInstance(props,new javax.mail.Authenticator()
{
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user,pass);
}
});
session.setDebug(true);
try
{
/* Create an instance of MimeMessage,
it accept MIME types and headers
*/
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(user));
message.addRecipient(Message.RecipientType.TO,new InternetAddress(to));
message.setSubject(sub);
message.setText(msg);
/* Transport class is used to deliver the message to the recipients */
Transport.send(message);
}
catch(Exception e)
{
e.printStackTrace();
}
Error message:
535 5.7.3 Authentication unsuccessful javax.mail.AuthenticationFailedException at javax.mail.Service.connect(Service.java:319) at javax.mail.Service.connect(Service.java:169) at javax.mail.Service.connect(Service.java:118) at javax.mail.Transport.send0(Transport.java:188) at javax.mail.Transport.send(Transport.java:118) java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748)
SMTP configuration:
configuration:props.put("mail.smtp.host", "smtp.oceaneering.com"); props.put("mail.smtp.port", "587");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
First is need to turn on 2-Step Verification .(after that google script to give new option for creation app passwords) https://support.google.com/accounts/answer/185839?
Next you must to create the app passwords https://support.google.com/accounts/answer/185833?hl=en
Last step to replace this line in your code
String pass = "1234"; - with app specific password, (it must generate on step 2) Some like String pass = "djd5n7hsd";
And For future reader in may be useful to check network and firewall setting on your system and mail setting your ISP. To check if packet can to reach gmail server.
Try telnet command : telnet smtp.gmail.com 587
I am stuck behind a corporate firewall that won't let me send email via conventional means such as Java Mail API or Apache Commons Email, even to other people inside the organization(which is all I want anyways). But my Outlook 2010 obviously can send these emails. I was wondering if there is a way to automate Outlook 2010 via Java code so that Outlook can send the emails ? I know stuff like "mailto" can be used pop-up the default Outlook send dialog with pre-populated info, but I am looking for a way to have the send operation happen behind the scenes. Thanks for any info.
You can send emails through outlook with javamail use the configurations described on Outlook's official site.
Here is small demo code
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.Properties;
public static void main(String[] args) {
final String username = "your email"; // like yourname#outlook.com
final String password = "*********"; // password here
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp-mail.outlook.com");
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props,
new javax.mail.Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
session.setDebug(true);
try {
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO,
InternetAddress.parse("receiver mail")); // like inzi769#gmail.com
message.setSubject("Test");
message.setText("HI you have done sending mail with outlook");
Transport.send(message);
System.out.println("Done");
} catch (MessagingException e) {
throw new RuntimeException(e);
}
}
.
Note: I tested this with Javamail API 1.5.6
I don't think there's any way to do what you want using Outlook.
Presumably your mail server is also behind the corporate firewall. If you're using Outlook for your client, you're probably using Exchange for your server. Exchange can be configured to support the standard SMTP protocol for sending mail, which would allow use of JavaMail. If you can't configure your Exchange server to support SMTP, you still might be able to use Exchange Web Services. If that doesn't work, you might need to use one of the JavaMail Third Party Products that supports the Microsoft proprietary mail protocol.
Process p = Runtime.getRuntime().exec("cmd /C start outlook ");
I am sending e email using an SMTP error . I am getting Authentication unsuccessful. The username and password are correct. Am I doing something wrong.
The error logs are
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class EmailSender{
public static void main(String args[]) {
String to = "ssss#xxx.om"; // sender email
String from = "dddd#xxx.com"; // receiver email
String host = "dkdkdd.xxx.com"; // mail server host
String login="dkkdkd";
String pass="dkkdkd";
Properties properties = System.getProperties();
properties.setProperty("mail.smtp.host", host);
properties.setProperty("mail.smtp.user", login);
properties.setProperty("mail.smtp.password", pass);
properties.setProperty("mail.smtps.ssl.enable", "true");
// properties.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(properties); // default session
try {
MimeMessage message = new MimeMessage(session); // email message
message.setFrom(new InternetAddress(from)); // setting header fields
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject("Test Mail from Java Program"); // subject line
// actual mail body
message.setText("You can send mail from Java program by using");
// Send message
Transport transport = session.getTransport("smtp");
transport.connect(host, login, pass);
Transport.send(message);
System.out.println("Email Sent successfully....");
} catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
The error is
DEBUG SMTP: AUTH NTLM failed
Exception in thread "main" javax.mail.AuthenticationFailedException: 535 5.7.3 Authentication unsuccessful
at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:826)
at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:761)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:685)
at javax.mail.Service.connect(Service.java:317)
at javax.mail.Service.connect(Service.java:176)
at javax.mail.Service.connect(Service.java:125)
at javax.mail.Transport.send0(Transport.java:194)
at javax.mail.Transport.send(Transport.java:124)
Had the same issue. It's an MS Exchange error that you receive. You are probably not allowed to use your email to send an email via a relay. The administrator of the Exchange server needs to give the rights to do that.
It has nothing to do with a configuration problem on the Java side.
It looks like the problem in how you do the session part...
try doing this:
private Properties emailPorperties;
...
...
emailPorperties = new Properties();
emailPorperties.put("mail.smtp.host", "your host");
emailPorperties.put("mail.smtp.socketFactory.port", "your port");
emailPorperties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
emailPorperties.put("mail.smtp.auth", "true");
emailPorperties.put("mail.smtp.port", "your port");
emailPorperties.put("mail.smtp.ssl.enable", "true");
emailSession = Session.getInstance(emailPorperties, new Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
System.out.println("Authenticating");
return new PasswordAuthentication(USER_NAME, PASSWORD);
}
});
Hello i've got the same issue in the past.
So to solve it i have to connect on the webmail of my outlook or exchage and i noticed that these connexions were stopped by the server so inside i confirm that these transactions was mine.
So u have also to do it usually every 2 month in my case.
The problem is not in the code. The problem occurs because something is wrong with the configuration of the mailboxes I believe.
Same issue resolve by enabling IMAP of the sender email account in Exchange Control Panel (ECP) of outlook mail admin.
Go to your Microsoft admin account and turn off the multi-factor authentication.
By default it is enabled. Once you disable the multi-factor authentication then it works fine for me.
I had a similar issue and in my case, the issue was 'outlook password got expired'.
As I had it logged in default I did not have any issue while logging in to my mail.
I tried logging in to incognito mode and see if my logging asked for an additional layer for logging like multi-factor auth, And when logged in from the incognito tab it asked to change the password with a popup stating 'password got expired'.
I then updated the new password and it started to work fine !!
i am trying to write an application in java that will send emails, i found a tutorial on youtube and tried to follow it. however it does not work for me still, here is the error i get
Exception in thread "main" javax.mail.MessagingException: Could not connect to SMTP host: localhost, port: 25, response: 421
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1949)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654)
at javax.mail.Service.connect(Service.java:295)
at javax.mail.Service.connect(Service.java:176)
at javax.mail.Service.connect(Service.java:125)
at javax.mail.Transport.send0(Transport.java:194)
at javax.mail.Transport.send(Transport.java:124)
at libraryFineList.ParseRecords.main(ParseRecords.java:90)
i have no idea, what's wrong, anything i found on google did not help,
here is the code
public static void main(String[] args) throws IOException, MessagingException {
Properties props = new Properties();
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.socketFactory.port", 465);
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.port", "465");
Session session = Session.getDefaultInstance(props,
new javax.mail.Authenticator(){
protected PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication("user#gmail.com", "pass");
}
}
);
try{
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress("user#gmail.com"));
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("ycharnetskaya#gmail.com", "Mr. User"));
message.setSubject("Your Example.com account has been activated");
message.setText("Worked");
Transport.send(message);
}catch(Exception e){
e.printStackTrace();
}
The tutorial you followed is full of errors. Start by fixing these common mistakes. Then follow these instructions for connecting to Gmail. If you're still having problems, you'll find lots more help in the JavaMail FAQ. There's also many sample programs available.
It's strange that your error message is complaining about a problem connecting to localhost:25 when your properties file is clearly suggesting that you should use smtp.gmail.com.
I don't suppose there's anything dodgy going on with your hosts file that's redirecting smtp.gmail.com back to 127.0.0.1 or something, is there? What happens if you ping smtp.gmail.com from the command line?
Apart from that, I'd suggest checking you're using the latest version of Java Mail.