JavaMail mail.smtp.ssl.enable is not working - java

I read on several sites that, when using the JavaMail API, to set the property mail.smtp.ssl.enable to true. I have some code as follows:
props.put("mail.smtp.host", "exchangemail1.example.com");
props.put("mail.from", "myemail#example.com");
props.put("mail.smtp.starttls.enable", "true");
// I tried this by itself and also together with ssl.enable)
props.put("mail.smtp.ssl.enable", "true");
Session session = Session.getInstance(props, null);
MimeMessage msg = new MimeMessage(session);
msg.setFrom();
msg.setRecipients(Message.RecipientType.TO, "me.at#example.com");
// also tried #gmail.com
msg.setSubject("JavaMail ssl test");
msg.setSentDate(new Date());
msg.setText("Hello, world!\n");
props.put("mail.smtp.auth", "false");
Transport trnsport;
trnsport = session.getTransport("smtp");
trnsport.connect();
msg.saveChanges();
trnsport.sendMessage(msg, msg.getAllRecipients());
trnsport.close();
This sends email, but:
when I do traffic capture, I see it is not encrypted
When using debug (props.put("mail.debug", "true")), I see that "isSSL false"
(I also tried above adding in props.put("mail.smtp.auth","true") + user/password....)
Any ideas what I am doing wrong?

To use SSL you should change your protocol from SMTP to SMTPS by changing
trnsport = session.getTransport("smtp");
to
trnsport = session.getTransport("smtps");

Form the Java Doc:
Note that if you're using the "smtps" protocol to access SMTP over SSL, all the properties would be named "mail.smtps.*".

Try
props.put("mail.smtp.auth", "true");
props.setProperty("mail.smtp.**ssl.enable", "true");
props.setProperty("mail.smtp.**ssl.required", "true");

I'd suggest using Apache commons-email. It has setters for the most used properties (including SSL / TLS) and is more friendlier to use and sits ontop of the JavaMail API.
Update: I was looking at commons-email code, and saw these lines:
properties.setProperty("mail.smtp.starttls.enable", this.tls);
properties.setProperty("mail.smtp.auth", "true");
so, give these properties a try as well.

This is from the SSLNOTES document from JavaMail (emphasis added):
First, and perhaps the simplest, is to set a property to enable use
of SSL. For example, to enable use of SSL for SMTP connections, set
the property "mail.smtp.ssl.enable" to "true".
Alternatively, you can configure JavaMail to use one of the SSL-enabled
protocol names. In addition to the non-SSL JavaMail protocols "imap",
"pop3", and "smtp", the protocols "imaps", "pop3s", and "smtps" can
be used to connect to the corresponding services using an SSL
connection.
-- STARTTLS support
The STARTTLS support is available in the standard "imap" and "smtp"
protocols, but must be enabled by setting the appropriate property,
mail.imap.starttls.enable or mail.smtp.starttls.enable, to "true".
When set, if the server supports the STARTTLS command, it will be
used after making the connection and before sending any login
information.
So when using the STARTTLS support it seems that it is not necessary to set the protocol to smtps.

Related

JavaMail with proxy not connecting

i have a class that is called "NotifiationService":
#Service("notificacionService")
public class NotificacionServiceImpl implements NotificacionService{
//servicio llama a repositorio
#Autowired
#Qualifier("notificacionService")
private NotificacionService notificacionService;
#Override
public void send(String to, String subject, String text) {
//proxy
Properties p = System.getProperties();
p.setProperty("proxySet","true");
p.setProperty("socksProxyHost","MYPROXY");
p.setProperty("socksProxyPort","MYPORT");
Properties props = new Properties();
// smtp.gmail.com
props.setProperty("mail.smtp.host", "smtp.gmail.com");
// TLS
props.setProperty("mail.smtp.starttls.enable", "false");
// port
props.setProperty("mail.smtp.port","465");
//
props.setProperty("mail.smtp.user", "reciever#gmail.com");
props.setProperty("mail.smtp.auth", "true");
Session session = Session.getDefaultInstance(props);
session.setDebug(true);
MimeMessage message = new MimeMessage(session);
try {
message.setFrom(new InternetAddress("sender#gmail.com"));
message.addRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
message.setText(text);
//
Transport t = session.getTransport("smtp");
t.connect("sender#gmail.com","senderpassword");
t.sendMessage(message,message.getAllRecipients());
t.close();
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
As you can see i have tried to configure a proxy, since the computer is connected to one that redirects the traffic. So even adding all the specifications about the proxy, it keeps giving me an error saying:
com.sun.mail.util.MailConnectException: Couldn't connect to host, port: smtp.gmail.com, 465; timeout -1;
nested exception is:
java.net.SocketException: Permission denied: connect
I have also tried different ports like: 25,485,587 and none of the respond, so i think its a problem with the proxy.
To be able to find the information about the proxy that is implemented i have typed this command in the console:
reg query "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings" | find /i "proxyserver"
and it responds with:
ProxyServer REG_SZ MYPROXY:MYPORT
If i type: "ping google.com" in cmd, it says its inaccessible
Is there a way to be able to connect from java with javamail to gmail and be able to send an email with the current configuration?
Thanks.
If it's not working after setting the SOCKS properties, most likely your proxy server is just a web proxy server and not a SOCKS proxy server. The JavaMail FAQ has pointers to other software that will allow to tunnel connections through a web proxy server.
Since JavaMail 1.6.2, You can set proxy authentication properties for Session object for sending emails.
Refer to the following documentation link.
https://javaee.github.io/javamail/docs/api/
The following properties are introduced newly and works fine with Proxy Authentication (Basic).
mail.smtp.proxy.host
mail.smtp.proxy.port
mail.smtp.proxy.user
mail.smtp.proxy.password
To clarify at least one point concerning the usage of https.proxySet=true and http.proxySet=true.
JDK-4632974 proxySet=false is ignored for HttpURLConnection.getOutputStream
"The use of property http.proxySet was eliminated in favor of simply testing
for the presence of the http.proxyHost property. This property existed up to
JDK1.0.2 but was removed for JDK1.1 in 1996."
In other words, do not use proxySet as it serves no purpose. It is non-existing Java system property nowadays.

does sending email via SMTP with TLS connection encrypt the username and password?

I've written an appilicaiton with Java which sends Email. For sending Email I've used SMTP with TLS.
Recently I've searched about TLS and I found the flowing description about TLS on this website : Transport Layer Security (TLS), a protocol that encrypts and delivers mail securely, helps prevent eavesdropping and spoofing (message forgery) between mail servers.
The above phrase says that TLS guarantees that the mail will be delivered securely, but it does not say any thing about the password...
suppose that I am using following code in my application, so as you can see you need to have hard code for username and password, without any encryption.
final String username = "...#hotmail.com";
final String password = "your Password";
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() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
by using this strategy does TLS encrypt my password while sending from my server to another server or not? should I be worried about it or not?
Password transmission and communication encryption are two separate matters.
TLS is initiated over what is at first an unencrypted channel by issuing the STARTTLS command; if the server supports it, then the exchange is done and after it is done, the channel is encrypted.
And only then the SMTP negotiation starts; and one part of this negociation is authentication if any. And even if you use the plain authentication mechanism (user and password sent over the wire as is), since the channel is encrypted at that time, eavesdroppers won't see it in clear.
Of course, for more security, you may choose to use another authentication mechanism than the plain one (CRAM-MD5 for instance; others exist).
EDIT OK, the answer above is only partially accurate; more details can be found in this excellent answer on ServerFault by #Bruno

Send Java email without authentication (no such provider exception: smtp)

The code I am currently using is as follows:
String to = "....#gmail.com";
String from = ".....#gmail.com";
String host = "127.0.0.1";
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 actual message");
Transport.send(message);
System.out.println("Sent message successfully....");
} catch (MessagingException mex) {
mex.printStackTrace();
}
If I paste the above code in my Java servlet and run it, the following exception gets thrown:
javax.mail.NoSuchProviderException: smtp
I have also tried following the solutions outlined in these resources but to no avail: link1 link2 link3 link4.
It would help if you included the the full stacktrace for the javax.mail.NoSuchProviderException and JavaMail debug output. Because you are running this in a servlet container you could be running into Bug 6668 -skip unusable Store and Transport classes. Change your call to Transport.set to the following:
final ClassLoader ccl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(Session.class.getClassLoader());
try {
Transport.send(message);
} finally {
Thread.currentThread().setContextClassLoader(ccl);
}
That code will isolate which transport class the code is allowed to see. That will rule out that bug in your code.
NoSuchProviderException means something is messed up in your JavaMail API configuration. Where and how have you installed the JavaMail jar file?
Also, in case it's not clear from the other responses, the only way you're going to be able to send mail without authentication is if you're running your own mail server. You can't do it with general purpose online e-mail services (e.g. Gmail).
First of all, if you wanna use gmail to send emails from your program you need to define stmp host as gmail. Your current host "127.0.0.1" is localhost meaning your own computer? Do you have mail server running on your computer?
Here you can see some tutorial how to send an email using gmail: http://www.mkyong.com/java/javamail-api-sending-email-via-gmail-smtp-example/
If you're afraid to pass your normal gmail account details then create some kind of test email like kselvatest or something.
You are missing pretty much those:
final String username = "username#gmail.com";
final String password = "password";
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", "smtp.gmail.com");
props.put("mail.smtp.port", "587");
So basicly all you need to add is:
1.login and password so JavaMail can use some gmail account
2.declare which mail server you wanna use
change String host = "127.0.0.1"; to String host = "smtp.gmail.com";
3.set mail port
For this code you should get javax.mail.MessagingException: Could not connect to SMTP host: 127.0.0.1, port: 25; exception
But I suspect you have a jre issue. May be smtp implementation has a problem. Why don't you download java mail implementation from http://www.oracle.com/technetwork/java/javamail/index-138643.html and add it to your project class path and try?

Return path doesn't get set using mail.smtp.from

I am having problems setting the return path for all yahoo emails I'm sending. Here's what I'm using:
Properties props = new Properties();
props.put("mail.transport.protocol", "smtps");
props.put("mail.smtps.auth", "true");
props.put("mail.host", host);
props.put("mail.port", port);
props.put("mail.user", username);
props.put("mail.password", password);
props.put("mail.smtp.from", bounceAddress);
I'm sending the mimeMessage using transport.sendMessage method. Still, after sending a few, in the Full-header for yahoo mails the return path is the same as the sender email.
Any idea what might be the problem?
Thanks
You're using the "smtps" protocol, but setting the property for the "smtp" protocol. Set "mail.smtps.from" instead.

javamail returning smtp as transport, instead of smtps

I set the mail.transport property to smtps, beside the very basic information for connecting to a smtps server:
Properties p = new Properties();
p.put("mail.transport.protocol", "smtps");
p.put("mail.smtps.host", "smtp.gmail.com");
p.put("mail.smtps.auth", true);
Session s = Session.getDefaultInstance(p,new Authenticator(){/*authenticator impl.*/});
MimeMessage mm = new MimeMessage(s); /*then i set the subject, then the body... */
mm.setRecipients(RecipientType.TO, "myfakeaddress#gmail.com");
And now, i try to send my message. I want to try the static method; using the instance method sendMessage it works fine. Here it is:
Transport.send(mm);
It tries to connect to a smtp server, instead of a smtps server. Stepping inside the implementation of javamail (btw, my version is 1.4.5) i've discovered that the method that fails is:
transport = s.getTransport(addresses[0]);
because it returns an SMTPTransport instead of SMTPSSLTransport; this even if i've set the mail.transport.protocol property to smtps as you can see in the second line of code.
Is my procedure buggy anywhere or it isn't possible to send smtps mails via Transport.send static method?
Transport.send(msg) is looking up the protocol(s) associated with the recipients of your email, for each type of recipient.
All your recipients are InternetAddresses, which have the type rfc822
Here are three ways to set JavaMail to use smtps protocol for rfc822 addresses:
Add the line rfc822=smtps in the property files javamail.address.map or javamail.default.address.map (as described in the Session javadoc)
Call s.setProtocolForAddress("rfc822", "smtps")` on your instantiated session (requires JavaMail 1.4 or later)
Set the property mail.transport.protocol.rfc822 to smtps when instantiating your session (requires JavaMail 1.4.3 or later)
Bill Shannon (current maintainer of Javamail) suggests in this question
Get rid of all the socket factory properties; if you're using a
reasonably recent version of JavaMail you don't need them. See the
JavaMail FAQ for how to configure JavaMail to access Gmail. You'll
also find debugging tips there if it still doesn't work.
Also, change Session.getDefaultInstance to Session.getInstance.
Here is the relevant code from the Javamail FAQ
String host = "smtp.gmail.com";
String username = "user";
String password = "passwd";
Properties props = new Properties();
props.put("mail.smtps.auth", "true");
props.put("mail.debug", "true");
MimeMessage msg = new MimeMessage(session);
// set the message content here
Transport t = session.getTransport("smtps");
try {
t.connect(host, username, password);
t.sendMessage(msg, msg.getAllRecipients());
} finally {
t.close();
}

Categories